diff options
Diffstat (limited to 'src/widgets/dialogs')
21 files changed, 513 insertions, 198 deletions
diff --git a/src/widgets/dialogs/qcolordialog.cpp b/src/widgets/dialogs/qcolordialog.cpp index 1cb6cb8a2d..fc00290536 100644 --- a/src/widgets/dialogs/qcolordialog.cpp +++ b/src/widgets/dialogs/qcolordialog.cpp @@ -57,6 +57,11 @@ #include "qpainter.h" #include "qpixmap.h" #include "qpushbutton.h" +#if QT_CONFIG(regularexpression) +#include <qregularexpression.h> +#else +#include <qregexp.h> +#endif #if QT_CONFIG(settings) #include "qsettings.h" #endif @@ -1616,7 +1621,7 @@ void QColorDialogPrivate::_q_pickScreenColor() q->grabMouse(); #endif -#ifdef Q_OS_WIN32 // excludes WinCE and WinRT +#ifdef Q_OS_WIN32 // excludes WinRT // On Windows mouse tracking doesn't work over other processes's windows updateTimer->start(30); diff --git a/src/widgets/dialogs/qdialog.cpp b/src/widgets/dialogs/qdialog.cpp index caab6c16ba..3cdd9a5f04 100644 --- a/src/widgets/dialogs/qdialog.cpp +++ b/src/widgets/dialogs/qdialog.cpp @@ -270,12 +270,11 @@ void QDialogPrivate::deletePlatformHelper() The most common way to display a modal dialog is to call its exec() function. When the user closes the dialog, exec() will - provide a useful \l{#return}{return value}. Typically, - to get the dialog to close and return the appropriate value, we - connect a default button, e.g. \uicontrol OK, to the accept() slot and a - \uicontrol Cancel button to the reject() slot. - Alternatively you can call the done() slot with \c Accepted or - \c Rejected. + provide a useful \l{#return}{return value}. To close the dialog + and return the appropriate value, you must connect a default button, + e.g. an \uicontrol OK button to the accept() slot and a + \uicontrol Cancel button to the reject() slot. Alternatively, you + can call the done() slot with \c Accepted or \c Rejected. An alternative is to call setModal(true) or setWindowModality(), then show(). Unlike exec(), show() returns control to the caller @@ -283,7 +282,7 @@ void QDialogPrivate::deletePlatformHelper() progress dialogs, where the user must have the ability to interact with the dialog, e.g. to cancel a long running operation. If you use show() and setModal(true) together to perform a long operation, - you must call QApplication::processEvents() periodically during + you must call QCoreApplication::processEvents() periodically during processing to enable the user to interact with the dialog. (See QProgressDialog.) @@ -692,7 +691,7 @@ void QDialog::contextMenuEvent(QContextMenuEvent *e) if (p.data()->exec(e->globalPos()) == wt) { QHelpEvent e(QEvent::WhatsThis, w->rect().center(), w->mapToGlobal(w->rect().center())); - QApplication::sendEvent(w, &e); + QCoreApplication::sendEvent(w, &e); } delete p.data(); } @@ -827,7 +826,7 @@ QT_WARNING_POP #endif if (fw && !fw->hasFocus()) { QFocusEvent e(QEvent::FocusIn, Qt::TabFocusReason); - QApplication::sendEvent(fw, &e); + QCoreApplication::sendEvent(fw, &e); } #ifndef QT_NO_ACCESSIBILITY diff --git a/src/widgets/dialogs/qdialog_p.h b/src/widgets/dialogs/qdialog_p.h index 92634f6793..74f775a0bd 100644 --- a/src/widgets/dialogs/qdialog_p.h +++ b/src/widgets/dialogs/qdialog_p.h @@ -75,15 +75,15 @@ public: QDialogPrivate() : #if QT_CONFIG(pushbutton) - mainDef(0), + mainDef(nullptr), #endif - orientation(Qt::Horizontal),extension(0), doShowExtension(false), + orientation(Qt::Horizontal),extension(nullptr), doShowExtension(false), #if QT_CONFIG(sizegrip) - resizer(0), + resizer(nullptr), sizeGripEnabled(false), #endif - rescode(0), resetModalityTo(-1), wasModalitySet(true), eventLoop(0), - nativeDialogInUse(false), m_platformHelper(0), m_platformHelperCreated(false) + rescode(0), resetModalityTo(-1), wasModalitySet(true), eventLoop(nullptr), + nativeDialogInUse(false), m_platformHelper(nullptr), m_platformHelperCreated(false) {} ~QDialogPrivate(); @@ -140,14 +140,14 @@ class QAutoPointer { struct internal { void func() {} }; typedef void (internal::*RestrictedBool)(); public: - explicit QAutoPointer(T *t) Q_DECL_NOTHROW : o(t) {} + explicit QAutoPointer(T *t) noexcept : o(t) {} ~QAutoPointer() { delete o; } - T *operator->() const Q_DECL_NOTHROW { return get(); } - T *get() const Q_DECL_NOTHROW { return o; } + T *operator->() const noexcept { return get(); } + T *get() const noexcept { return o; } T &operator*() const { return *get(); } - operator RestrictedBool() const Q_DECL_NOTHROW { return o ? &internal::func : nullptr; } - bool operator!() const Q_DECL_NOTHROW { return !o; } + operator RestrictedBool() const noexcept { return o ? &internal::func : nullptr; } + bool operator!() const noexcept { return !o; } private: Q_DISABLE_COPY(QAutoPointer); }; diff --git a/src/widgets/dialogs/qerrormessage.cpp b/src/widgets/dialogs/qerrormessage.cpp index fd68f19680..f0ec2c0102 100644 --- a/src/widgets/dialogs/qerrormessage.cpp +++ b/src/widgets/dialogs/qerrormessage.cpp @@ -295,7 +295,7 @@ QErrorMessage * QErrorMessage::qtHandler() if (!qtMessageHandler) { qtMessageHandler = new QErrorMessage(0); qAddPostRoutine(deleteStaticcQErrorMessage); // clean up - qtMessageHandler->setWindowTitle(QApplication::applicationName()); + qtMessageHandler->setWindowTitle(QCoreApplication::applicationName()); qInstallMessageHandler(jump); } return qtMessageHandler; @@ -322,8 +322,8 @@ bool QErrorMessagePrivate::nextPending() #else errors->setPlainText(message); #endif - currentMessage = qMove(message); - currentType = qMove(type); + currentMessage = std::move(message); + currentType = std::move(type); return true; } } diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index 2c2d209226..a1b9003c1c 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -44,6 +44,7 @@ #include "qfiledialog.h" #include "qfiledialog_p.h" +#include <private/qapplication_p.h> #include <private/qguiapplication_p.h> #include <qfontmetrics.h> #include <qaction.h> @@ -77,6 +78,8 @@ #include <private/qwasmlocalfileaccess_p.h> #endif +#include <algorithm> + QT_BEGIN_NAMESPACE Q_GLOBAL_STATIC(QUrl, lastVisitedDir) @@ -2445,6 +2448,51 @@ void QFileDialog::getOpenFileContent(const QString &nameFilter, const std::funct } /*! + This is a convenience static function that saves \a fileContent to a file, using + a file name and location chosen by the user. \a fileNameHint can be provided to + suggest a file name to the user. + + This function is used to save files to the local file system on Qt for WebAssembly, where + the web sandbox places restrictions on how such access may happen. Its implementation will + make the browser display a native file dialog, where the user makes the file selection. + + It can also be used on other platforms, where it will fall back to using QFileDialog. + + The function is asynchronous and returns immediately. + + \snippet code/src_gui_dialogs_qfiledialog.cpp 16 + \since 5.14 +*/ +void QFileDialog::saveFileContent(const QByteArray &fileContent, const QString &fileNameHint) +{ +#ifdef Q_OS_WASM + QWasmLocalFileAccess::saveFile(fileContent.constData(), fileContent.size(), fileNameHint.toStdString()); +#else + QFileDialog *dialog = new QFileDialog(); + dialog->setAcceptMode(QFileDialog::AcceptSave); + dialog->setFileMode(QFileDialog::AnyFile); + dialog->selectFile(fileNameHint); + + auto fileSelected = [=](const QString &fileName) { + if (!fileName.isNull()) { + QFile selectedFile(fileName); + if (selectedFile.open(QIODevice::WriteOnly)) + selectedFile.write(fileContent); + } + }; + + auto dialogClosed = [=](int code) { + Q_UNUSED(code); + delete dialog; + }; + + connect(dialog, &QFileDialog::fileSelected, fileSelected); + connect(dialog, &QFileDialog::finished, dialogClosed); + dialog->show(); +#endif +} + +/*! This is a convenience static function that will return a file name selected by the user. The file does not have to exist. @@ -3372,6 +3420,18 @@ void QFileDialogPrivate::_q_goHome() q->setDirectory(QDir::homePath()); } + +void QFileDialogPrivate::saveHistorySelection() +{ + if (qFileDialogUi.isNull() || currentHistoryLocation < 0 || currentHistoryLocation >= currentHistory.size()) + return; + auto &item = currentHistory[currentHistoryLocation]; + item.selection.clear(); + const auto selectedIndexes = qFileDialogUi->listView->selectionModel()->selectedRows(); + for (const auto &index : selectedIndexes) + item.selection.append(QPersistentModelIndex(index)); +} + /*! \internal @@ -3385,17 +3445,49 @@ void QFileDialogPrivate::_q_pathChanged(const QString &newPath) qFileDialogUi->sidebar->selectUrl(QUrl::fromLocalFile(newPath)); q->setHistory(qFileDialogUi->lookInCombo->history()); - if (currentHistoryLocation < 0 || currentHistory.value(currentHistoryLocation) != QDir::toNativeSeparators(newPath)) { + const QString newNativePath = QDir::toNativeSeparators(newPath); + + // equal paths indicate this was invoked by _q_navigateBack/Forward() + if (currentHistoryLocation < 0 || currentHistory.value(currentHistoryLocation).path != newNativePath) { + if (currentHistoryLocation >= 0) + saveHistorySelection(); while (currentHistoryLocation >= 0 && currentHistoryLocation + 1 < currentHistory.count()) { currentHistory.removeLast(); } - currentHistory.append(QDir::toNativeSeparators(newPath)); + currentHistory.append({newNativePath, PersistentModelIndexList()}); ++currentHistoryLocation; } qFileDialogUi->forwardButton->setEnabled(currentHistory.size() - currentHistoryLocation > 1); qFileDialogUi->backButton->setEnabled(currentHistoryLocation > 0); } +void QFileDialogPrivate::navigate(HistoryItem &historyItem) +{ + Q_Q(QFileDialog); + q->setDirectory(historyItem.path); + // Restore selection unless something has changed in the file system + if (qFileDialogUi.isNull() || historyItem.selection.isEmpty()) + return; + if (std::any_of(historyItem.selection.cbegin(), historyItem.selection.cend(), + [](const QPersistentModelIndex &i) { return !i.isValid(); })) { + historyItem.selection.clear(); + return; + } + + QAbstractItemView *view = q->viewMode() == QFileDialog::List + ? static_cast<QAbstractItemView *>(qFileDialogUi->listView) + : static_cast<QAbstractItemView *>(qFileDialogUi->treeView); + auto selectionModel = view->selectionModel(); + const QItemSelectionModel::SelectionFlags flags = QItemSelectionModel::Select + | QItemSelectionModel::Rows; + selectionModel->select(historyItem.selection.constFirst(), + flags | QItemSelectionModel::Clear | QItemSelectionModel::Current); + for (int i = 1, size = historyItem.selection.size(); i < size; ++i) + selectionModel->select(historyItem.selection.at(i), flags); + + view->scrollTo(historyItem.selection.constFirst()); +} + /*! \internal @@ -3403,11 +3495,9 @@ void QFileDialogPrivate::_q_pathChanged(const QString &newPath) */ void QFileDialogPrivate::_q_navigateBackward() { - Q_Q(QFileDialog); if (!currentHistory.isEmpty() && currentHistoryLocation > 0) { - --currentHistoryLocation; - QString previousHistory = currentHistory.at(currentHistoryLocation); - q->setDirectory(previousHistory); + saveHistorySelection(); + navigate(currentHistory[--currentHistoryLocation]); } } @@ -3418,11 +3508,9 @@ void QFileDialogPrivate::_q_navigateBackward() */ void QFileDialogPrivate::_q_navigateForward() { - Q_Q(QFileDialog); if (!currentHistory.isEmpty() && currentHistoryLocation < currentHistory.size() - 1) { - ++currentHistoryLocation; - QString nextHistory = currentHistory.at(currentHistoryLocation); - q->setDirectory(nextHistory); + saveHistorySelection(); + navigate(currentHistory[++currentHistoryLocation]); } } @@ -3633,12 +3721,13 @@ void QFileDialogPrivate::_q_autoCompleteFileName(const QString &text) if (oldFiles.removeAll(idx) == 0) newFiles.append(idx); } - for (int i = 0; i < newFiles.count(); ++i) - select(newFiles.at(i)); - if (lineEdit()->hasFocus()) - for (int i = 0; i < oldFiles.count(); ++i) - qFileDialogUi->listView->selectionModel()->select(oldFiles.at(i), - QItemSelectionModel::Toggle | QItemSelectionModel::Rows); + for (const auto &newFile : qAsConst(newFiles)) + select(newFile); + if (lineEdit()->hasFocus()) { + auto *sm = qFileDialogUi->listView->selectionModel(); + for (const auto &oldFile : qAsConst(oldFiles)) + sm->select(oldFile, QItemSelectionModel::Toggle | QItemSelectionModel::Rows); + } } } @@ -3992,7 +4081,7 @@ bool QFileDialogPrivate::itemViewKeyboardEvent(QKeyEvent *event) { return true; case Qt::Key_Back: #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled()) + if (QApplicationPrivate::keypadNavigationEnabled()) return false; #endif case Qt::Key_Left: diff --git a/src/widgets/dialogs/qfiledialog.h b/src/widgets/dialogs/qfiledialog.h index 95e03618ac..790f52f2e7 100644 --- a/src/widgets/dialogs/qfiledialog.h +++ b/src/widgets/dialogs/qfiledialog.h @@ -92,7 +92,9 @@ public: ShowDirsOnly = 0x00000001, DontResolveSymlinks = 0x00000002, DontConfirmOverwrite = 0x00000004, - DontUseSheet = 0x00000008, +#if QT_DEPRECATED_SINCE(5, 14) + DontUseSheet Q_DECL_ENUMERATOR_DEPRECATED = 0x00000008, +#endif DontUseNativeDialog = 0x00000010, ReadOnly = 0x00000020, HideNameFilterDetails = 0x00000040, @@ -282,6 +284,7 @@ public: static void getOpenFileContent(const QString &nameFilter, const std::function<void(const QString &, const QByteArray &)> &fileContentsReady); + static void saveFileContent(const QByteArray &fileContent, const QString &fileNameHint = QString()); protected: QFileDialog(const QFileDialogArgs &args); diff --git a/src/widgets/dialogs/qfiledialog_p.h b/src/widgets/dialogs/qfiledialog_p.h index 463c77aa23..dcf147348f 100644 --- a/src/widgets/dialogs/qfiledialog_p.h +++ b/src/widgets/dialogs/qfiledialog_p.h @@ -98,7 +98,7 @@ class QPlatformDialogHelper; struct QFileDialogArgs { - QFileDialogArgs() : parent(0), mode(QFileDialog::AnyFile) {} + QFileDialogArgs() : parent(nullptr), mode(QFileDialog::AnyFile) {} QWidget *parent; QString caption; @@ -116,6 +116,14 @@ class Q_WIDGETS_EXPORT QFileDialogPrivate : public QDialogPrivate Q_DECLARE_PUBLIC(QFileDialog) public: + using PersistentModelIndexList = QVector<QPersistentModelIndex>; + + struct HistoryItem + { + QString path; + PersistentModelIndexList selection; + }; + QFileDialogPrivate(); QPlatformFileDialogHelper *platformFileDialogHelper() const @@ -193,9 +201,11 @@ public: void retranslateWindowTitle(); void retranslateStrings(); void emitFilesSelected(const QStringList &files); + void saveHistorySelection(); void _q_goHome(); void _q_pathChanged(const QString &); + void navigate(HistoryItem &); void _q_navigateBackward(); void _q_navigateForward(); void _q_navigateToParent(); @@ -237,7 +247,7 @@ public: QString setWindowTitle; - QStringList currentHistory; + QList<HistoryItem> currentHistory; int currentHistoryLocation; QAction *renameAction; @@ -292,7 +302,7 @@ private: class QFileDialogLineEdit : public QLineEdit { public: - QFileDialogLineEdit(QWidget *parent = 0) : QLineEdit(parent), d_ptr(0){} + QFileDialogLineEdit(QWidget *parent = nullptr) : QLineEdit(parent), d_ptr(nullptr){} void setFileDialogPrivate(QFileDialogPrivate *d_pointer) {d_ptr = d_pointer; } void keyPressEvent(QKeyEvent *e) override; bool hideOnEsc; @@ -303,7 +313,7 @@ private: class QFileDialogComboBox : public QComboBox { public: - QFileDialogComboBox(QWidget *parent = 0) : QComboBox(parent), urlModel(0) {} + QFileDialogComboBox(QWidget *parent = nullptr) : QComboBox(parent), urlModel(nullptr) {} void setFileDialogPrivate(QFileDialogPrivate *d_pointer); void showPopup() override; void setHistory(const QStringList &paths); @@ -319,7 +329,7 @@ private: class QFileDialogListView : public QListView { public: - QFileDialogListView(QWidget *parent = 0); + QFileDialogListView(QWidget *parent = nullptr); void setFileDialogPrivate(QFileDialogPrivate *d_pointer); QSize sizeHint() const override; protected: diff --git a/src/widgets/dialogs/qfileinfogatherer.cpp b/src/widgets/dialogs/qfileinfogatherer.cpp index 1e03ad8b06..0beca82f28 100644 --- a/src/widgets/dialogs/qfileinfogatherer.cpp +++ b/src/widgets/dialogs/qfileinfogatherer.cpp @@ -54,12 +54,12 @@ QT_BEGIN_NAMESPACE static QBasicAtomicInt fetchedRoot = Q_BASIC_ATOMIC_INITIALIZER(false); Q_AUTOTEST_EXPORT void qt_test_resetFetchedRoot() { - fetchedRoot.store(false); + fetchedRoot.storeRelaxed(false); } Q_AUTOTEST_EXPORT bool qt_test_isFetchedRoot() { - return fetchedRoot.load(); + return fetchedRoot.loadRelaxed(); } #endif @@ -79,30 +79,9 @@ static QString translateDriveName(const QFileInfo &drive) Creates thread */ QFileInfoGatherer::QFileInfoGatherer(QObject *parent) - : QThread(parent), abort(false), -#if QT_CONFIG(filesystemwatcher) - watcher(0), -#endif -#ifdef Q_OS_WIN - m_resolveSymlinks(true), -#endif - m_iconProvider(&defaultProvider) + : QThread(parent) + , m_iconProvider(&defaultProvider) { -#if QT_CONFIG(filesystemwatcher) - watcher = new QFileSystemWatcher(this); - connect(watcher, SIGNAL(directoryChanged(QString)), this, SLOT(list(QString))); - connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(updateFile(QString))); - -# if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) - const QVariant listener = watcher->property("_q_driveListener"); - if (listener.canConvert<QObject *>()) { - if (QObject *driveListener = listener.value<QObject *>()) { - connect(driveListener, SIGNAL(driveAdded()), this, SLOT(driveAdded())); - connect(driveListener, SIGNAL(driveRemoved()), this, SLOT(driveRemoved())); - } - } -# endif // Q_OS_WIN && !Q_OS_WINRT -#endif start(LowPriority); } @@ -111,7 +90,7 @@ QFileInfoGatherer::QFileInfoGatherer(QObject *parent) */ QFileInfoGatherer::~QFileInfoGatherer() { - abort.store(true); + abort.storeRelaxed(true); QMutexLocker locker(&mutex); condition.wakeAll(); locker.unlock(); @@ -183,8 +162,8 @@ void QFileInfoGatherer::fetchExtendedInformation(const QString &path, const QStr if (files.isEmpty() && !path.isEmpty() && !path.startsWith(QLatin1String("//")) /*don't watch UNC path*/) { - if (!watcher->directories().contains(path)) - watcher->addPath(path); + if (!watchedDirectories().contains(path)) + watchPaths(QStringList(path)); } #endif } @@ -201,6 +180,91 @@ void QFileInfoGatherer::updateFile(const QString &filePath) fetchExtendedInformation(dir, QStringList(fileName)); } +QStringList QFileInfoGatherer::watchedFiles() const +{ +#if QT_CONFIG(filesystemwatcher) + if (m_watcher) + return m_watcher->files(); +#endif + return {}; +} + +QStringList QFileInfoGatherer::watchedDirectories() const +{ +#if QT_CONFIG(filesystemwatcher) + if (m_watcher) + return m_watcher->directories(); +#endif + return {}; +} + +void QFileInfoGatherer::createWatcher() +{ +#if QT_CONFIG(filesystemwatcher) + m_watcher = new QFileSystemWatcher(this); + connect(m_watcher, &QFileSystemWatcher::directoryChanged, this, &QFileInfoGatherer::list); + connect(m_watcher, &QFileSystemWatcher::fileChanged, this, &QFileInfoGatherer::updateFile); +# if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) + const QVariant listener = m_watcher->property("_q_driveListener"); + if (listener.canConvert<QObject *>()) { + if (QObject *driveListener = listener.value<QObject *>()) { + connect(driveListener, SIGNAL(driveAdded()), this, SLOT(driveAdded())); + connect(driveListener, SIGNAL(driveRemoved()), this, SLOT(driveRemoved())); + } + } +# endif // Q_OS_WIN && !Q_OS_WINRT +#endif +} + +void QFileInfoGatherer::watchPaths(const QStringList &paths) +{ +#if QT_CONFIG(filesystemwatcher) + if (m_watching) { + if (m_watcher == nullptr) + createWatcher(); + m_watcher->addPaths(paths); + } +#else + Q_UNUSED(paths); +#endif +} + +void QFileInfoGatherer::unwatchPaths(const QStringList &paths) +{ +#if QT_CONFIG(filesystemwatcher) + if (m_watcher) + m_watcher->removePaths(paths); +#else + Q_UNUSED(paths); +#endif +} + +bool QFileInfoGatherer::isWatching() const +{ + bool result = false; +#if QT_CONFIG(filesystemwatcher) + QMutexLocker locker(&mutex); + result = m_watching; +#endif + return result; +} + +void QFileInfoGatherer::setWatching(bool v) +{ +#if QT_CONFIG(filesystemwatcher) + QMutexLocker locker(&mutex); + if (v != m_watching) { + if (!v) { + delete m_watcher; + m_watcher = nullptr; + } + m_watching = v; + } +#else + Q_UNUSED(v); +#endif +} + /* List all files in \a directoryPath @@ -210,8 +274,8 @@ void QFileInfoGatherer::clear() { #if QT_CONFIG(filesystemwatcher) QMutexLocker locker(&mutex); - watcher->removePaths(watcher->files()); - watcher->removePaths(watcher->directories()); + unwatchPaths(watchedFiles()); + unwatchPaths(watchedDirectories()); #endif } @@ -224,7 +288,7 @@ void QFileInfoGatherer::removePath(const QString &path) { #if QT_CONFIG(filesystemwatcher) QMutexLocker locker(&mutex); - watcher->removePath(path); + unwatchPaths(QStringList(path)); #else Q_UNUSED(path); #endif @@ -247,9 +311,9 @@ void QFileInfoGatherer::run() { forever { QMutexLocker locker(&mutex); - while (!abort.load() && path.isEmpty()) + while (!abort.loadRelaxed() && path.isEmpty()) condition.wait(&mutex); - if (abort.load()) + if (abort.loadRelaxed()) return; const QString thisPath = qAsConst(path).front(); path.pop_front(); @@ -271,12 +335,13 @@ QExtendedInformation QFileInfoGatherer::getInfo(const QFileInfo &fileInfo) const static const bool watchFiles = qEnvironmentVariableIsSet("QT_FILESYSTEMMODEL_WATCH_FILES"); if (watchFiles) { if (!fileInfo.exists() && !fileInfo.isSymLink()) { - watcher->removePath(fileInfo.absoluteFilePath()); + const_cast<QFileInfoGatherer *>(this)-> + unwatchPaths(QStringList(fileInfo.absoluteFilePath())); } else { const QString path = fileInfo.absoluteFilePath(); if (!path.isEmpty() && fileInfo.exists() && fileInfo.isFile() && fileInfo.isReadable() - && !watcher->files().contains(path)) { - watcher->addPath(path); + && !watchedFiles().contains(path)) { + const_cast<QFileInfoGatherer *>(this)->watchPaths(QStringList(path)); } } } @@ -303,7 +368,7 @@ void QFileInfoGatherer::getFileInfos(const QString &path, const QStringList &fil // List drives if (path.isEmpty()) { #ifdef QT_BUILD_INTERNAL - fetchedRoot.store(true); + fetchedRoot.storeRelaxed(true); #endif QFileInfoList infoList; if (files.isEmpty()) { @@ -332,7 +397,7 @@ void QFileInfoGatherer::getFileInfos(const QString &path, const QStringList &fil QStringList allFiles; if (files.isEmpty()) { QDirIterator dirIt(path, QDir::AllEntries | QDir::System | QDir::Hidden); - while (!abort.load() && dirIt.hasNext()) { + while (!abort.loadRelaxed() && dirIt.hasNext()) { dirIt.next(); fileInfo = dirIt.fileInfo(); allFiles.append(fileInfo.fileName()); @@ -343,7 +408,7 @@ void QFileInfoGatherer::getFileInfos(const QString &path, const QStringList &fil emit newListOfFiles(path, allFiles); QStringList::const_iterator filesIt = filesToCheck.constBegin(); - while (!abort.load() && filesIt != filesToCheck.constEnd()) { + while (!abort.loadRelaxed() && filesIt != filesToCheck.constEnd()) { fileInfo.setFile(path + QDir::separator() + *filesIt); ++filesIt; fetch(fileInfo, base, firstTime, updatedFiles, path); diff --git a/src/widgets/dialogs/qfileinfogatherer_p.h b/src/widgets/dialogs/qfileinfogatherer_p.h index 134a14b7ce..3d30a98d04 100644 --- a/src/widgets/dialogs/qfileinfogatherer_p.h +++ b/src/widgets/dialogs/qfileinfogatherer_p.h @@ -166,15 +166,16 @@ Q_SIGNALS: void directoryLoaded(const QString &path); public: - explicit QFileInfoGatherer(QObject *parent = 0); + explicit QFileInfoGatherer(QObject *parent = nullptr); ~QFileInfoGatherer(); -#if QT_CONFIG(filesystemwatcher) && defined(Q_OS_WIN) - QStringList watchedFiles() const { return watcher->files(); } - QStringList watchedDirectories() const { return watcher->directories(); } - void watchPaths(const QStringList &paths) { watcher->addPaths(paths); } - void unwatchPaths(const QStringList &paths) { watcher->removePaths(paths); } -#endif // filesystemwatcher && Q_OS_WIN + QStringList watchedFiles() const; + QStringList watchedDirectories() const; + void watchPaths(const QStringList &paths); + void unwatchPaths(const QStringList &paths); + + bool isWatching() const; + void setWatching(bool v); // only callable from this->thread(): void clear(); @@ -201,6 +202,8 @@ private: void fetch(const QFileInfo &info, QElapsedTimer &base, bool &firstTime, QVector<QPair<QString, QFileInfo> > &updatedFiles, const QString &path); private: + void createWatcher(); + mutable QMutex mutex; // begin protected by mutex QWaitCondition condition; @@ -210,13 +213,16 @@ private: QAtomicInt abort; #if QT_CONFIG(filesystemwatcher) - QFileSystemWatcher *watcher; -#endif -#ifdef Q_OS_WIN - bool m_resolveSymlinks; // not accessed by run() + QFileSystemWatcher *m_watcher = nullptr; #endif QFileIconProvider *m_iconProvider; // not accessed by run() QFileIconProvider defaultProvider; +#ifdef Q_OS_WIN + bool m_resolveSymlinks = true; // not accessed by run() +#endif +#if QT_CONFIG(filesystemwatcher) + bool m_watching = true; +#endif }; QT_END_NAMESPACE diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp index e486037e08..e9e49e0c33 100644 --- a/src/widgets/dialogs/qfilesystemmodel.cpp +++ b/src/widgets/dialogs/qfilesystemmodel.cpp @@ -227,11 +227,9 @@ bool QFileSystemModel::remove(const QModelIndex &aindex) /*! Constructs a file system model with the given \a parent. */ -QFileSystemModel::QFileSystemModel(QObject *parent) - : QAbstractItemModel(*new QFileSystemModelPrivate, parent) +QFileSystemModel::QFileSystemModel(QObject *parent) : + QFileSystemModel(*new QFileSystemModelPrivate, parent) { - Q_D(QFileSystemModel); - d->init(); } /*! @@ -247,9 +245,7 @@ QFileSystemModel::QFileSystemModel(QFileSystemModelPrivate &dd, QObject *parent) /*! Destroys this file system model. */ -QFileSystemModel::~QFileSystemModel() -{ -} +QFileSystemModel::~QFileSystemModel() = default; /*! \reimp @@ -1268,6 +1264,107 @@ Qt::DropActions QFileSystemModel::supportedDropActions() const } /*! + \enum QFileSystemModel::Option + \since 5.14 + + \value DontWatchForChanges Do not add file watchers to the paths. + This reduces overhead when using the model for simple tasks + like line edit completion. + + \value DontResolveSymlinks Don't resolve symlinks in the file + system model. By default, symlinks are resolved. + + \value DontUseCustomDirectoryIcons Always use the default directory icon. + Some platforms allow the user to set a different icon. Custom icon lookup + causes a big performance impact over network or removable drives. + This sets the QFileIconProvider::DontUseCustomDirectoryIcons + option in the icon provider accordingly. + + \sa resolveSymlinks +*/ + +/*! + \since 5.14 + Sets the given \a option to be enabled if \a on is true; otherwise, + clears the given \a option. + + Options should be set before changing properties. + + \sa options, testOption() +*/ +void QFileSystemModel::setOption(Option option, bool on) +{ + QFileSystemModel::Options previousOptions = options(); + setOptions(previousOptions.setFlag(option, on)); +} + +/*! + \since 5.14 + + Returns \c true if the given \a option is enabled; otherwise, returns + false. + + \sa options, setOption() +*/ +bool QFileSystemModel::testOption(Option option) const +{ + return options().testFlag(option); +} + +/*! + \property QFileSystemModel::options + \brief the various options that affect the model + \since 5.14 + + By default, all options are disabled. + + Options should be set before changing properties. + + \sa setOption(), testOption() +*/ +void QFileSystemModel::setOptions(Options options) +{ + const Options changed = (options ^ QFileSystemModel::options()); + + if (changed.testFlag(DontResolveSymlinks)) + setResolveSymlinks(!options.testFlag(DontResolveSymlinks)); + +#if QT_CONFIG(filesystemwatcher) + Q_D(QFileSystemModel); + if (changed.testFlag(DontWatchForChanges)) + d->fileInfoGatherer.setWatching(!options.testFlag(DontWatchForChanges)); +#endif + + if (changed.testFlag(DontUseCustomDirectoryIcons)) { + if (auto provider = iconProvider()) { + QFileIconProvider::Options providerOptions = provider->options(); + providerOptions.setFlag(QFileIconProvider::DontUseCustomDirectoryIcons, + options.testFlag(QFileSystemModel::DontUseCustomDirectoryIcons)); + provider->setOptions(providerOptions); + } else { + qWarning("Setting QFileSystemModel::DontUseCustomDirectoryIcons has no effect when no provider is used"); + } + } +} + +QFileSystemModel::Options QFileSystemModel::options() const +{ + QFileSystemModel::Options result; + result.setFlag(DontResolveSymlinks, !resolveSymlinks()); +#if QT_CONFIG(filesystemwatcher) + Q_D(const QFileSystemModel); + result.setFlag(DontWatchForChanges, !d->fileInfoGatherer.isWatching()); +#else + result.setFlag(DontWatchForChanges); +#endif + if (auto provider = iconProvider()) { + result.setFlag(DontUseCustomDirectoryIcons, + provider->options().testFlag(QFileIconProvider::DontUseCustomDirectoryIcons)); + } + return result; +} + +/*! Returns the path of the item stored in the model under the \a index given. */ @@ -1390,7 +1487,7 @@ QModelIndex QFileSystemModel::setRootPath(const QString &newPath) if (d->rootDir.path() == longNewPath) return d->index(rootPath()); - bool showDrives = (longNewPath.isEmpty() || longNewPath == d->myComputer()); + bool showDrives = (longNewPath.isEmpty() || longNewPath == QFileSystemModelPrivate::myComputer()); if (!showDrives && !newPathDir.exists()) return d->index(rootPath()); @@ -1513,6 +1610,8 @@ QDir::Filters QFileSystemModel::filter() const This is only relevant on Windows. By default, this property is \c true. + + \sa QFileSystemModel::Options */ void QFileSystemModel::setResolveSymlinks(bool enable) { @@ -1847,8 +1946,7 @@ void QFileSystemModelPrivate::_q_fileSystemChanged(const QString &path, const QV std::sort(rowsToUpdate.begin(), rowsToUpdate.end()); QString min; QString max; - for (int i = 0; i < rowsToUpdate.count(); ++i) { - QString value = rowsToUpdate.at(i); + for (const QString &value : qAsConst(rowsToUpdate)) { //##TODO is there a way to bundle signals with QString as the content of the list? /*if (min.isEmpty()) { min = value; @@ -1946,6 +2044,9 @@ QStringList QFileSystemModelPrivate::unwatchPathsAt(const QModelIndex &index) void QFileSystemModelPrivate::init() { Q_Q(QFileSystemModel); + + delayedSortTimer.setSingleShot(true); + qRegisterMetaType<QVector<QPair<QString,QFileInfo> > >(); #if QT_CONFIG(filesystemwatcher) q->connect(&fileInfoGatherer, SIGNAL(newListOfFiles(QString,QStringList)), diff --git a/src/widgets/dialogs/qfilesystemmodel.h b/src/widgets/dialogs/qfilesystemmodel.h index c2c8b8818e..b0f289dfcd 100644 --- a/src/widgets/dialogs/qfilesystemmodel.h +++ b/src/widgets/dialogs/qfilesystemmodel.h @@ -61,6 +61,7 @@ class Q_WIDGETS_EXPORT QFileSystemModel : public QAbstractItemModel Q_PROPERTY(bool resolveSymlinks READ resolveSymlinks WRITE setResolveSymlinks) Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly) Q_PROPERTY(bool nameFilterDisables READ nameFilterDisables WRITE setNameFilterDisables) + Q_PROPERTY(Options options READ options WRITE setOptions) Q_SIGNALS: void rootPathChanged(const QString &newPath); @@ -75,6 +76,15 @@ public: FilePermissions = Qt::UserRole + 3 }; + enum Option + { + DontWatchForChanges = 0x00000001, + DontResolveSymlinks = 0x00000002, + DontUseCustomDirectoryIcons = 0x00000004 + }; + Q_ENUM(Option) + Q_DECLARE_FLAGS(Options, Option) + explicit QFileSystemModel(QObject *parent = nullptr); ~QFileSystemModel(); @@ -129,6 +139,11 @@ public: void setNameFilters(const QStringList &filters); QStringList nameFilters() const; + void setOption(Option option, bool on = true); + bool testOption(Option option) const; + void setOptions(Options options); + Options options() const; + QString filePath(const QModelIndex &index) const; bool isDir(const QModelIndex &index) const; qint64 size(const QModelIndex &index) const; @@ -165,6 +180,8 @@ inline QString QFileSystemModel::fileName(const QModelIndex &aindex) const inline QIcon QFileSystemModel::fileIcon(const QModelIndex &aindex) const { return qvariant_cast<QIcon>(aindex.data(Qt::DecorationRole)); } +Q_DECLARE_OPERATORS_FOR_FLAGS(QFileSystemModel::Options) + QT_END_NAMESPACE #endif // QFILESYSTEMMODEL_H diff --git a/src/widgets/dialogs/qfilesystemmodel_p.h b/src/widgets/dialogs/qfilesystemmodel_p.h index 9c432e1ae6..844e417e2d 100644 --- a/src/widgets/dialogs/qfilesystemmodel_p.h +++ b/src/widgets/dialogs/qfilesystemmodel_p.h @@ -99,13 +99,13 @@ public: class QFileSystemNode { public: - explicit QFileSystemNode(const QString &filename = QString(), QFileSystemNode *p = 0) - : fileName(filename), populatedChildren(false), isVisible(false), dirtyChildrenIndex(-1), parent(p), info(0) {} + Q_DISABLE_COPY_MOVE(QFileSystemNode) + + explicit QFileSystemNode(const QString &filename = QString(), QFileSystemNode *p = nullptr) + : fileName(filename), parent(p) {} ~QFileSystemNode() { qDeleteAll(children); delete info; - info = 0; - parent = 0; } QString fileName; @@ -116,7 +116,7 @@ public: inline qint64 size() const { if (info && !info->isDir()) return info->size(); return 0; } inline QString type() const { if (info) return info->displayType; return QLatin1String(""); } inline QDateTime lastModified() const { if (info) return info->lastModified(); return QDateTime(); } - inline QFile::Permissions permissions() const { if (info) return info->permissions(); return 0; } + inline QFile::Permissions permissions() const { if (info) return info->permissions(); return nullptr; } inline bool isReadable() const { return ((permissions() & QFile::ReadUser) != 0); } inline bool isWritable() const { return ((permissions() & QFile::WriteUser) != 0); } inline bool isExecutable() const { return ((permissions() & QFile::ExeUser) != 0); } @@ -162,7 +162,7 @@ public: return info && (*info == fileInfo); } - inline bool hasInformation() const { return info != 0; } + inline bool hasInformation() const { return info != nullptr; } void populate(const QExtendedInformation &fileInfo) { if (!info) @@ -204,31 +204,16 @@ public: } } - bool populatedChildren; - bool isVisible; QHash<QFileSystemModelNodePathKey, QFileSystemNode *> children; QList<QString> visibleChildren; - int dirtyChildrenIndex; + QExtendedInformation *info = nullptr; QFileSystemNode *parent; - - - QExtendedInformation *info; - + int dirtyChildrenIndex = -1; + bool populatedChildren = false; + bool isVisible = false; }; - QFileSystemModelPrivate() : - forceSort(true), - sortColumn(0), - sortOrder(Qt::AscendingOrder), - readOnly(true), - setRootPath(false), - filters(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs), - nameFilterDisables(true), // false on windows, true on mac and unix - disableRecursiveSort(false) - { - delayedSortTimer.setSingleShot(true); - } - + QFileSystemModelPrivate() = default; void init(); /* \internal @@ -303,18 +288,7 @@ public: QFileInfoGatherer fileInfoGatherer; #endif // filesystemwatcher QTimer delayedSortTimer; - bool forceSort; - int sortColumn; - Qt::SortOrder sortOrder; - bool readOnly; - bool setRootPath; - QDir::Filters filters; QHash<const QFileSystemNode*, bool> bypassFilters; - bool nameFilterDisables; - //This flag is an optimization for the QFileDialog - //It enable a sort which is not recursive, it means - //we sort only what we see. - bool disableRecursiveSort; #if QT_CONFIG(regularexpression) QStringList nameFilters; #endif @@ -322,7 +296,6 @@ public: QFileSystemNode root; - QBasicTimer fetchingTimer; struct Fetching { QString dir; QString file; @@ -330,6 +303,18 @@ public: }; QVector<Fetching> toFetch; + QBasicTimer fetchingTimer; + + QDir::Filters filters = QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs; + int sortColumn = 0; + Qt::SortOrder sortOrder = Qt::AscendingOrder; + bool forceSort = true; + bool readOnly = true; + bool setRootPath = false; + bool nameFilterDisables = true; // false on windows, true on mac and unix + // This flag is an optimization for QFileDialog. It enables a sort which is + // not recursive, meaning we sort only what we see. + bool disableRecursiveSort = false; }; Q_DECLARE_TYPEINFO(QFileSystemModelPrivate::Fetching, Q_MOVABLE_TYPE); diff --git a/src/widgets/dialogs/qfontdialog.cpp b/src/widgets/dialogs/qfontdialog.cpp index d53d57db86..7e3592e034 100644 --- a/src/widgets/dialogs/qfontdialog.cpp +++ b/src/widgets/dialogs/qfontdialog.cpp @@ -432,7 +432,7 @@ bool QFontDialog::eventFilter(QObject *o , QEvent *e) k->key() == Qt::Key_PageDown)) { int ci = d->sizeList->currentItem(); - (void)QApplication::sendEvent(d->sizeList, k); + QCoreApplication::sendEvent(d->sizeList, k); if (ci != d->sizeList->currentItem() && style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, 0, this)) @@ -680,7 +680,7 @@ void QFontDialogPrivate::updateSampleFont(const QFont &newFont) void QFontDialogPrivate::_q_writingSystemHighlighted(int index) { writingSystem = QFontDatabase::WritingSystem(index); - sampleEdit->setText(fdb.writingSystemSample(writingSystem)); + sampleEdit->setText(QFontDatabase::writingSystemSample(writingSystem)); updateFamilies(); } diff --git a/src/widgets/dialogs/qfscompleter_p.h b/src/widgets/dialogs/qfscompleter_p.h index 3b829d4a52..f5110a7622 100644 --- a/src/widgets/dialogs/qfscompleter_p.h +++ b/src/widgets/dialogs/qfscompleter_p.h @@ -64,8 +64,8 @@ QT_BEGIN_NAMESPACE */ class Q_WIDGETS_EXPORT QFSCompleter : public QCompleter { public: - explicit QFSCompleter(QFileSystemModel *model, QObject *parent = 0) - : QCompleter(model, parent), proxyModel(0), sourceModel(model) + explicit QFSCompleter(QFileSystemModel *model, QObject *parent = nullptr) + : QCompleter(model, parent), proxyModel(nullptr), sourceModel(model) { #if defined(Q_OS_WIN) setCaseSensitivity(Qt::CaseInsensitive); diff --git a/src/widgets/dialogs/qmessagebox.cpp b/src/widgets/dialogs/qmessagebox.cpp index f143e3b527..8dad212692 100644 --- a/src/widgets/dialogs/qmessagebox.cpp +++ b/src/widgets/dialogs/qmessagebox.cpp @@ -1508,7 +1508,7 @@ void QMessageBox::keyPressEvent(QKeyEvent *e) if (d->detailsText) textToCopy += d->detailsText->text() + QLatin1Char('\n') + separator; #endif - QApplication::clipboard()->setText(textToCopy); + QGuiApplication::clipboard()->setText(textToCopy); return; } #endif // Q_OS_WIN @@ -2662,14 +2662,9 @@ QPixmap QMessageBoxPrivate::standardIcon(QMessageBox::Icon icon, QMessageBox *mb break; } if (!tmpIcon.isNull()) { - QWindow *window = nullptr; - if (mb) { - window = mb->windowHandle(); - if (!window) { - if (const QWidget *nativeParent = mb->nativeParentWidget()) - window = nativeParent->windowHandle(); - } - } + QWindow *window = mb + ? qt_widget_private(mb)->windowHandle(QWidgetPrivate::WindowHandleMode::Closest) + : nullptr; return tmpIcon.pixmap(window, QSize(iconSize, iconSize)); } return QPixmap(); diff --git a/src/widgets/dialogs/qprogressdialog.cpp b/src/widgets/dialogs/qprogressdialog.cpp index 078dd6463b..e1a6bce5b1 100644 --- a/src/widgets/dialogs/qprogressdialog.cpp +++ b/src/widgets/dialogs/qprogressdialog.cpp @@ -643,7 +643,7 @@ int QProgressDialog::value() const \warning If the progress dialog is modal (see QProgressDialog::QProgressDialog()), - setValue() calls QApplication::processEvents(), so take care that + setValue() calls QCoreApplication::processEvents(), so take care that this does not cause undesirable re-entrancy in your code. For example, don't use a QProgressDialog inside a paintEvent()! @@ -659,7 +659,7 @@ void QProgressDialog::setValue(int progress) if (d->shown_once) { if (isModal()) - QApplication::processEvents(); + QCoreApplication::processEvents(); } else { if ((!d->setValue_called && progress == 0 /* for compat with Qt < 5.4 */) || progress == minimum()) { d->starttime.start(); diff --git a/src/widgets/dialogs/qsidebar_p.h b/src/widgets/dialogs/qsidebar_p.h index 4a82f88878..6056f19452 100644 --- a/src/widgets/dialogs/qsidebar_p.h +++ b/src/widgets/dialogs/qsidebar_p.h @@ -67,7 +67,7 @@ class QFileSystemModel; class QSideBarDelegate : public QStyledItemDelegate { public: - QSideBarDelegate(QWidget *parent = 0) : QStyledItemDelegate(parent) {} + QSideBarDelegate(QWidget *parent = nullptr) : QStyledItemDelegate(parent) {} void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const override; }; @@ -82,7 +82,7 @@ public: EnabledRole = Qt::UserRole + 2 }; - QUrlModel(QObject *parent = 0); + QUrlModel(QObject *parent = nullptr); QStringList mimeTypes() const override; QMimeData *mimeData(const QModelIndexList &indexes) const override; @@ -127,7 +127,7 @@ Q_SIGNALS: void goToUrl(const QUrl &url); public: - QSidebar(QWidget *parent = 0); + QSidebar(QWidget *parent = nullptr); void setModelAndUrls(QFileSystemModel *model, const QList<QUrl> &newUrls); ~QSidebar(); diff --git a/src/widgets/dialogs/qwizard.cpp b/src/widgets/dialogs/qwizard.cpp index f6f540f57c..7558054da5 100644 --- a/src/widgets/dialogs/qwizard.cpp +++ b/src/widgets/dialogs/qwizard.cpp @@ -1336,7 +1336,7 @@ void QWizardPrivate::updateMinMaxSizes(const QWizardLayoutInfo &info) int extraHeight = 0; #if QT_CONFIG(style_windowsvista) if (isVistaThemeEnabled()) - extraHeight = vistaHelper->titleBarSize() + vistaHelper->topOffset(); + extraHeight = vistaHelper->titleBarSize() + vistaHelper->topOffset(q); #endif QSize minimumSize = mainLayout->totalMinimumSize() + QSize(0, extraHeight); QSize maximumSize = mainLayout->totalMaximumSize(); @@ -1595,23 +1595,25 @@ bool QWizardPrivate::handleAeroStyleChange() bool vistaMargins = false; if (isVistaThemeEnabled()) { + const int topOffset = vistaHelper->topOffset(q); + const int topPadding = vistaHelper->topPadding(q); if (isVistaThemeEnabled(QVistaHelper::VistaAero)) { if (isWindow) { vistaHelper->setDWMTitleBar(QVistaHelper::ExtendedTitleBar); q->installEventFilter(vistaHelper); } q->setMouseTracking(true); - antiFlickerWidget->move(0, vistaHelper->titleBarSize() + vistaHelper->topOffset()); + antiFlickerWidget->move(0, vistaHelper->titleBarSize() + topOffset); vistaHelper->backButton()->move( - 0, vistaHelper->topOffset() // ### should ideally work without the '+ 1' - - qMin(vistaHelper->topOffset(), vistaHelper->topPadding() + 1)); + 0, topOffset // ### should ideally work without the '+ 1' + - qMin(topOffset, topPadding + 1)); vistaMargins = true; vistaHelper->backButton()->show(); } else { if (isWindow) vistaHelper->setDWMTitleBar(QVistaHelper::NormalTitleBar); q->setMouseTracking(true); - antiFlickerWidget->move(0, vistaHelper->topOffset()); + antiFlickerWidget->move(0, topOffset); vistaHelper->backButton()->move(0, -1); // ### should ideally work with (0, 0) } if (isWindow) @@ -2575,7 +2577,7 @@ void QWizard::setWizardStyle(WizardStyle style) //Send a resizeevent since the antiflicker widget probably needs a new size //because of the backbutton in the window title QResizeEvent ev(geometry().size(), geometry().size()); - QApplication::sendEvent(this, &ev); + QCoreApplication::sendEvent(this, &ev); } #endif d->updateLayout(); @@ -3212,7 +3214,7 @@ void QWizard::resizeEvent(QResizeEvent *event) int heightOffset = 0; #if QT_CONFIG(style_windowsvista) if (d->isVistaThemeEnabled()) { - heightOffset = d->vistaHelper->topOffset(); + heightOffset = d->vistaHelper->topOffset(this); if (d->isVistaThemeEnabled(QVistaHelper::VistaAero)) heightOffset += d->vistaHelper->titleBarSize(); } @@ -3244,7 +3246,7 @@ void QWizard::paintEvent(QPaintEvent * event) if (d->isVistaThemeEnabled(QVistaHelper::VistaBasic)) { QPainter painter(this); QColor color = d->vistaHelper->basicWindowFrameColor(); - painter.fillRect(0, 0, width(), QVistaHelper::topOffset(), color); + painter.fillRect(0, 0, width(), QVistaHelper::topOffset(this), color); } d->vistaHelper->paintEvent(event); } @@ -3257,7 +3259,11 @@ void QWizard::paintEvent(QPaintEvent * event) /*! \reimp */ +# if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +bool QWizard::nativeEvent(const QByteArray &eventType, void *message, qintptr *result) +# else bool QWizard::nativeEvent(const QByteArray &eventType, void *message, long *result) +# endif { #if QT_CONFIG(style_windowsvista) Q_D(QWizard); diff --git a/src/widgets/dialogs/qwizard.h b/src/widgets/dialogs/qwizard.h index 0dd837b197..ef71efa0cb 100644 --- a/src/widgets/dialogs/qwizard.h +++ b/src/widgets/dialogs/qwizard.h @@ -188,7 +188,11 @@ protected: void resizeEvent(QResizeEvent *event) override; void paintEvent(QPaintEvent *event) override; #if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC) +# if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result) override; +# else bool nativeEvent(const QByteArray &eventType, void *message, long *result) override; +# endif #endif void done(int result) override; virtual void initializePage(int id); diff --git a/src/widgets/dialogs/qwizard_win.cpp b/src/widgets/dialogs/qwizard_win.cpp index aa9ad7f290..47ac41a791 100644 --- a/src/widgets/dialogs/qwizard_win.cpp +++ b/src/widgets/dialogs/qwizard_win.cpp @@ -87,7 +87,7 @@ QVistaBackButton::QVistaBackButton(QWidget *widget) QSize QVistaBackButton::sizeHint() const { ensurePolished(); - int size = int(QStyleHelper::dpiScaled(32)); + int size = int(QStyleHelper::dpiScaled(32, this)); int width = size, height = size; return QSize(width, height); } @@ -156,7 +156,7 @@ QVistaHelper::QVistaHelper(QWizard *wizard) backButton_ = new QVistaBackButton(wizard); backButton_->hide(); - iconSpacing = QStyleHelper::dpiScaled(7); + iconSpacing = QStyleHelper::dpiScaled(7, wizard); } QVistaHelper::~QVistaHelper() @@ -172,7 +172,7 @@ void QVistaHelper::updateCustomMargins(bool vistaMargins) const QMargins customMarginsDp = vistaMargins ? QMargins(0, -titleBarSizeDp(), 0, 0) : QMargins(); - const QVariant customMarginsV = qVariantFromValue(customMarginsDp); + const QVariant customMarginsV = QVariant::fromValue(customMarginsDp); // The dynamic property takes effect when creating the platform window. window->setProperty("_q_windowsCustomMargins", customMarginsV); // If a platform window exists, change via native interface. @@ -229,7 +229,7 @@ bool QVistaHelper::setDWMTitleBar(TitleBarChangeType type) if (type == NormalTitleBar) mar.cyTopHeight = 0; else - mar.cyTopHeight = (titleBarSize() + topOffset()) * QVistaHelper::m_devicePixelRatio; + mar.cyTopHeight = (titleBarSize() + topOffset(wizard)) * QVistaHelper::m_devicePixelRatio; if (const HWND wizardHandle = wizardHWND()) if (SUCCEEDED(DwmExtendFrameIntoClientArea(wizardHandle, &mar))) value = true; @@ -275,7 +275,7 @@ void QVistaHelper::drawTitleBar(QPainter *painter) if (vistaState() == VistaAero && isWindow) drawBlackRect(QRect(0, 0, wizard->width(), - titleBarSize() + topOffset()), hdc); + titleBarSize() + topOffset(wizard)), hdc); // The button is positioned in QWizardPrivate::handleAeroStyleChange(), // all calculation is relative to it. const int btnTop = backButton_->mapToParent(QPoint()).y(); @@ -293,9 +293,9 @@ void QVistaHelper::drawTitleBar(QPainter *painter) int glowOffset = 0; if (vistaState() == VistaAero) { - textHeight += 2 * glowSize(); - textWidth += 2 * glowSize(); - glowOffset = glowSize(); + glowOffset = glowSize(wizard); + textHeight += 2 * glowOffset; + textWidth += 2 * glowOffset; } const int titleLeft = (wizard->layoutDirection() == Qt::LeftToRight @@ -314,10 +314,10 @@ void QVistaHelper::drawTitleBar(QPainter *painter) const QIcon windowIcon = wizard->windowIcon(); if (!windowIcon.isNull()) { - const int size = QVistaHelper::iconSize(); + const int size = QVistaHelper::iconSize(wizard); const int iconLeft = (wizard->layoutDirection() == Qt::LeftToRight - ? leftMargin() - : wizard->width() - leftMargin() - size); + ? leftMargin(wizard) + : wizard->width() - leftMargin(wizard) - size); const QPoint pos(origin.x() + iconLeft, origin.y() + verticalCenter - size / 2); const QPoint posDp = pos * QVistaHelper::m_devicePixelRatio; @@ -339,7 +339,11 @@ void QVistaHelper::setTitleBarIconAndCaptionVisible(bool visible) SetWindowThemeAttribute(handle, WTA_NONCLIENT, &opt, sizeof(WTA_OPTIONS)); } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +bool QVistaHelper::winEvent(MSG* msg, qintptr *result) +#else bool QVistaHelper::winEvent(MSG* msg, long* result) +#endif { switch (msg->message) { case WM_NCHITTEST: { @@ -401,7 +405,11 @@ void QVistaHelper::mouseEvent(QEvent *event) } } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +bool QVistaHelper::handleWinEvent(MSG *message, qintptr *result) +#else bool QVistaHelper::handleWinEvent(MSG *message, long *result) +#endif { if (message->message == WM_THEMECHANGED || message->message == WM_DWMCOMPOSITIONCHANGED) cachedVistaState = Dirty; @@ -419,7 +427,7 @@ void QVistaHelper::resizeEvent(QResizeEvent * event) { Q_UNUSED(event); rtTop = QRect (0, 0, wizard->width(), frameSize()); - int height = captionSize() + topOffset(); + int height = captionSize() + topOffset(wizard); if (vistaState() == VistaBasic) height -= titleBarSize(); rtTitle = QRect (0, frameSize(), wizard->width(), height); @@ -509,7 +517,11 @@ bool QVistaHelper::eventFilter(QObject *obj, QEvent *event) if (event->type() == QEvent::MouseMove) { QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + qintptr result; +#else long result; +#endif MSG msg; msg.message = WM_NCHITTEST; msg.wParam = 0; @@ -523,7 +535,11 @@ bool QVistaHelper::eventFilter(QObject *obj, QEvent *event) QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event); if (mouseEvent->button() == Qt::LeftButton) { +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + qintptr result; +#else long result; +#endif MSG msg; msg.message = WM_NCHITTEST; msg.wParam = 0; @@ -538,7 +554,11 @@ bool QVistaHelper::eventFilter(QObject *obj, QEvent *event) QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event); if (mouseEvent->button() == Qt::LeftButton) { +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + qintptr result; +#else long result; +#endif MSG msg; msg.message = WM_NCHITTEST; msg.wParam = 0; @@ -617,7 +637,7 @@ bool QVistaHelper::drawTitleText(QPainter *painter, const QString &text, const Q RECT rctext ={0,0, rectDp.width(), rectDp.height()}; dto.dwFlags = DTT_COMPOSITED|DTT_GLOWSIZE; - dto.iGlowSize = glowSize(); + dto.iGlowSize = glowSize(wizard); DrawThemeTextEx(hTheme, dcMem, 0, 0, reinterpret_cast<LPCWSTR>(text.utf16()), -1, uFormat, &rctext, &dto ); BitBlt(hdc, rectDp.left(), rectDp.top(), rectDp.width(), rectDp.height(), dcMem, 0, 0, SRCCOPY); @@ -694,27 +714,27 @@ int QVistaHelper::captionSizeDp() int QVistaHelper::titleOffset() { - int iconOffset = wizard ->windowIcon().isNull() ? 0 : iconSize() + iconSpacing; - return leftMargin() + iconOffset; + int iconOffset = wizard ->windowIcon().isNull() ? 0 : iconSize(wizard) + iconSpacing; + return leftMargin(wizard) + iconOffset; } -int QVistaHelper::iconSize() +int QVistaHelper::iconSize(const QPaintDevice *device) { - return QStyleHelper::dpiScaled(16); // Standard Aero + return QStyleHelper::dpiScaled(16, device); // Standard Aero } -int QVistaHelper::glowSize() +int QVistaHelper::glowSize(const QPaintDevice *device) { - return QStyleHelper::dpiScaled(10); + return QStyleHelper::dpiScaled(10, device); } -int QVistaHelper::topOffset() +int QVistaHelper::topOffset(const QPaintDevice *device) { if (vistaState() != VistaAero) return titleBarSize() + 3; static const int aeroOffset = QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8 ? - QStyleHelper::dpiScaled(4) : QStyleHelper::dpiScaled(13); + QStyleHelper::dpiScaled(4, device) : QStyleHelper::dpiScaled(13, device); return aeroOffset + titleBarSize(); } diff --git a/src/widgets/dialogs/qwizard_win_p.h b/src/widgets/dialogs/qwizard_win_p.h index 02c5e52c2c..2469496b61 100644 --- a/src/widgets/dialogs/qwizard_win_p.h +++ b/src/widgets/dialogs/qwizard_win_p.h @@ -93,7 +93,11 @@ public: bool setDWMTitleBar(TitleBarChangeType type); void setTitleBarIconAndCaptionVisible(bool visible); void mouseEvent(QEvent *event); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + bool handleWinEvent(MSG *message, qintptr *result); +#else bool handleWinEvent(MSG *message, long *result); +#endif void resizeEvent(QResizeEvent *event); void paintEvent(QPaintEvent *event); QVistaBackButton *backButton() const { return backButton_; } @@ -104,10 +108,10 @@ public: static VistaState vistaState(); static int titleBarSize() { return QVistaHelper::titleBarSizeDp() / QVistaHelper::m_devicePixelRatio; } static int titleBarSizeDp() { return QVistaHelper::frameSizeDp() + QVistaHelper::captionSizeDp(); } - static int topPadding() { // padding under text - return int(QStyleHelper::dpiScaled(4)); + static int topPadding(const QPaintDevice *device) { // padding under text + return int(QStyleHelper::dpiScaled(4, device)); } - static int topOffset(); + static int topOffset(const QPaintDevice *device); static HDC backingStoreDC(const QWidget *wizard, QPoint *offset); @@ -121,16 +125,22 @@ private: static int captionSize() { return QVistaHelper::captionSizeDp() / QVistaHelper::m_devicePixelRatio; } static int captionSizeDp(); - static int backButtonSize() { return int(QStyleHelper::dpiScaled(30)); } - static int iconSize(); - static int glowSize(); - int leftMargin() { return backButton_->isVisible() ? backButtonSize() + iconSpacing : 0; } + static int backButtonSize(const QPaintDevice *device) + { return int(QStyleHelper::dpiScaled(30, device)); } + static int iconSize(const QPaintDevice *device); + static int glowSize(const QPaintDevice *device); + int leftMargin(const QPaintDevice *device) + { return backButton_->isVisible() ? backButtonSize(device) + iconSpacing : 0; } int titleOffset(); void drawTitleBar(QPainter *painter); void setMouseCursor(QPoint pos); void collapseTopFrameStrut(); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + bool winEvent(MSG *message, qintptr *result); +#else bool winEvent(MSG *message, long *result); +#endif void mouseMoveEvent(QMouseEvent *event); void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); |