From 94c173de057bcf57a5105810d8ee34d2093fe805 Mon Sep 17 00:00:00 2001 From: Pierre Rossi Date: Fri, 20 May 2011 14:16:33 +0200 Subject: Add tilde (both ~ and ~) expansion to QFileDialog on UNIX. Task-number: QTBUG-3265 Change-Id: Id8062afe69e798e1f9cf3f4e967ae0d30c362b72 Reviewed-on: http://codereview.qt.nokia.com/411 Reviewed-by: Pierre Rossi --- src/gui/dialogs/qfiledialog.cpp | 77 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 73 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/gui/dialogs/qfiledialog.cpp b/src/gui/dialogs/qfiledialog.cpp index c22af651cf..2e57a845c2 100644 --- a/src/gui/dialogs/qfiledialog.cpp +++ b/src/gui/dialogs/qfiledialog.cpp @@ -66,6 +66,9 @@ #if defined(Q_OS_WINCE) extern bool qt_priv_ptr_valid; #endif +#if defined(Q_OS_UNIX) +#include +#endif #endif QT_BEGIN_NAMESPACE @@ -858,23 +861,78 @@ void QFileDialog::selectFile(const QString &filename) d->lineEdit()->setText(file); } +#ifdef Q_OS_UNIX +Q_AUTOTEST_EXPORT QString qt_tildeExpansion(const QString &path, bool *expanded = 0) +{ + if (expanded != 0) + *expanded = false; + if (!path.startsWith(QLatin1Char('~'))) + return path; + QString ret = path; + QStringList tokens = ret.split(QDir::separator()); + if (tokens.first() == QLatin1String("~")) { + ret.replace(0, 1, QDir::homeDirPath()); + } else { + QString userName = tokens.first(); + userName.remove(0, 1); +#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) + passwd pw; + passwd *tmpPw; + char buf[200]; + const int bufSize = sizeof(buf); + int err = getpwnam_r(userName.toLocal8Bit().constData(), &pw, buf, bufSize, &tmpPw); + if (err || !tmpPw) + return ret; + const QString homePath = QString::fromLocal8Bit(pw.pw_dir); +#else + passwd *pw = getpwnam(userName.toLocal8Bit().constData()); + if (!pw) + return ret; + const QString homePath = QString::fromLocal8Bit(pw->pw_dir); +#endif + ret.replace(0, tokens.first().length(), homePath); + } + if (expanded != 0) + *expanded = true; + return ret; +} +#endif + /** Returns the text in the line edit which can be one or more file names */ QStringList QFileDialogPrivate::typedFiles() const { + Q_Q(const QFileDialog); QStringList files; QString editText = lineEdit()->text(); - if (!editText.contains(QLatin1Char('"'))) + if (!editText.contains(QLatin1Char('"'))) { +#ifdef Q_OS_UNIX + const QString prefix = q->directory().absolutePath() + QDir::separator(); + if (QFile::exists(prefix + editText)) + files << editText; + else + files << qt_tildeExpansion(editText); +#else files << editText; - else { +#endif + } else { // " is used to separate files like so: "file1" "file2" "file3" ... // ### need escape character for filenames with quotes (") QStringList tokens = editText.split(QLatin1Char('\"')); for (int i=0; idirectory().absolutePath() + QDir::separator(); + if (QFile::exists(prefix + token)) + files << token; + else + files << qt_tildeExpansion(token); +#else files << toInternal(tokens.at(i)); +#endif } } return addDefaultSuffixToFiles(files); @@ -3338,6 +3396,17 @@ QStringList QFSCompleter::splitPath(const QString &path) const pathCopy = pathCopy.mid(2); else doubleSlash.clear(); +#elif defined(Q_OS_UNIX) + bool expanded; + pathCopy = qt_tildeExpansion(pathCopy, &expanded); + if (expanded) { + QFileSystemModel *dirModel; + if (proxyModel) + dirModel = qobject_cast(proxyModel->sourceModel()); + else + dirModel = sourceModel; + dirModel->fetchMore(dirModel->index(pathCopy)); + } #endif QRegExp re(QLatin1Char('[') + QRegExp::escape(sep) + QLatin1Char(']')); @@ -3354,14 +3423,14 @@ QStringList QFSCompleter::splitPath(const QString &path) const parts.append(QString()); #else QStringList parts = pathCopy.split(re); - if (path[0] == sep[0]) // read the "/" at the beginning as the split removed it + if (pathCopy[0] == sep[0]) // read the "/" at the beginning as the split removed it parts[0] = sep[0]; #endif #if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) bool startsFromRoot = !parts.isEmpty() && parts[0].endsWith(QLatin1Char(':')); #else - bool startsFromRoot = path[0] == sep[0]; + bool startsFromRoot = pathCopy[0] == sep[0]; #endif if (parts.count() == 1 || (parts.count() > 1 && !startsFromRoot)) { const QFileSystemModel *dirModel; -- cgit v1.2.3