diff --git a/CMakeLists.txt b/CMakeLists.txt index 49414bf..f188c37 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,85 +1,72 @@ cmake_minimum_required(VERSION 2.8.12) project(PlasmaIntegration) set(PROJECT_VERSION "5.11.90") set(PROJECT_VERSION_MAJOR 5) include(FeatureSummary) find_package(ECM 5.17.0 NO_MODULE) set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake Modules." URL "https://projects.kde.org/projects/kdesupport/extra-cmake-modules") feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND FATAL_ON_MISSING_REQUIRED_PACKAGES) set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) include(GenerateExportHeader) include(ECMPackageConfigHelpers) include(ECMSetupVersion) include(ECMGenerateHeaders) include(KDEInstallDirs) include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE) include(KDECMakeSettings) -set(REQUIRED_QT_VERSION 5.5.0) +set(REQUIRED_QT_VERSION 5.9.0) find_package(Qt5 ${REQUIRED_QT_VERSION} CONFIG REQUIRED Widgets DBus X11Extras QuickControls2) set(KF5_DEP_VERSION "5.33.0") find_package(KF5 ${KF5_DEP_VERSION} REQUIRED COMPONENTS Config ConfigWidgets I18n IconThemes KIO Notifications Wayland WidgetsAddons WindowSystem ) find_package(XCB COMPONENTS XCB) set_package_properties(XCB PROPERTIES DESCRIPTION "X protocol C-language Binding" URL "http://xcb.freedesktop.org" TYPE REQUIRED PURPOSE "Required to pass style properties to native Windows on X11 Platform" ) find_package(Breeze ${PROJECT_VERSION} CONFIG) set_package_properties(Breeze PROPERTIES TYPE REQUIRED PURPOSE "For setting the default QStyle name") # dependencies for QPA plugin -if(Qt5Core_VERSION VERSION_LESS "5.8.0") - find_package(Qt5PlatformSupport REQUIRED) -else() - find_package(Qt5ThemeSupport REQUIRED) -endif() - -if(Qt5Core_VERSION VERSION_LESS "5.8.0") - add_definitions(-DQ_FONTCONFIGDATABASE) - set(QT5PLATFORMSUPPORT_LIBS Qt5PlatformSupport::Qt5PlatformSupport) -else() - set(QT5PLATFORMSUPPORT_LIBS - Qt5ThemeSupport::Qt5ThemeSupport -) -endif() - +find_package(Qt5ThemeSupport REQUIRED) +set(QT5PLATFORMSUPPORT_LIBS Qt5ThemeSupport::Qt5ThemeSupport) add_definitions(-DTRANSLATION_DOMAIN=\"plasmaintegration5\") if (IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/po") ki18n_install(po) endif() add_subdirectory(src) add_subdirectory(autotests) add_subdirectory(tests) find_package(FontNotoSans) set_package_properties(FontNotoSans PROPERTIES PURPOSE "Default sans-serif font -- this is not detected automatically, pass -DCMAKE_DISABLE_FIND_PACKAGE_FontNotoSans=true to mark it ignored." URL "https://www.google.com/get/noto/" TYPE RUNTIME ) find_package(FontHack) set_package_properties(FontHack PROPERTIES PURPOSE "Default monospace font -- this is not detected automatically, pass -DCMAKE_DISABLE_FIND_PACKAGE_FontHack=true to mark it ignored." URL "http://sourcefoundry.org/hack/" TYPE RUNTIME ) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt index 74cc271..f5b5109 100644 --- a/autotests/CMakeLists.txt +++ b/autotests/CMakeLists.txt @@ -1,90 +1,84 @@ include(ECMMarkAsTest) include(ECMMarkNonGuiExecutable) find_package(Qt5Test ${REQUIRED_QT_VERSION} CONFIG QUIET) find_package(Qt5Qml ${REQUIRED_QT_VERSION} CONFIG QUIET) if(NOT Qt5Test_FOUND) message(STATUS "Qt5Test not found, autotests will not be built.") return() endif() if(NOT Qt5Qml_FOUND) message(STATUS "Qt5Qml not found, QML autotests will not be built.") endif() include_directories( ${Qt5Gui_PRIVATE_INCLUDE_DIRS} ${Qt5PlatformSupport_PRIVATE_INCLUDE_DIRS} ${CMAKE_BINARY_DIR}/src/platformtheme ) set(CONFIGFILE "${CMAKE_CURRENT_SOURCE_DIR}/kdeplatformtheme_kdeglobals") set(CHANGED_CONFIGFILE "${CMAKE_CURRENT_SOURCE_DIR}/kdeplatformtheme_changed_kdeglobals") configure_file(kdeplatformtheme_config.h.in ${CMAKE_CURRENT_BINARY_DIR}/kdeplatformtheme_config.h) remove_definitions(-DQT_NO_CAST_FROM_ASCII) # qdbusmenubar uses them remove_definitions(-DQT_NO_SIGNALS_SLOTS_KEYWORDS) macro(FRAMEWORKINTEGRATION_TESTS _testname) add_executable(${_testname} ${_testname}.cpp ${ARGN}) set_target_properties(${_testname} PROPERTIES COMPILE_FLAGS "-DUNIT_TEST") add_test(frameworkintegration-${_testname} ${_testname}) ecm_mark_as_test(${_testname}) ecm_mark_nongui_executable(${_testname}) target_link_libraries(${_testname} Qt5::Test Qt5::DBus Qt5::X11Extras Qt5::QuickControls2 ${QT5PLATFORMSUPPORT_LIBS} KF5::ConfigWidgets KF5::ConfigCore KF5::IconThemes KF5::KIOFileWidgets KF5::I18n KF5::Notifications KF5::WindowSystem KF5::WaylandClient XCB::XCB) endmacro() set(platformThemeSRCS + ../src/platformtheme/qdbusmenubar.cpp # fork of Qt's qdbusmenubar with some added setters for our convenience ../src/platformtheme/kdeplatformtheme.cpp ../src/platformtheme/kfontsettingsdata.cpp ../src/platformtheme/khintssettings.cpp ../src/platformtheme/kdeplatformfiledialoghelper.cpp ../src/platformtheme/kdeplatformfiledialogbase.cpp ../src/platformtheme/kdeplatformsystemtrayicon.cpp ../src/platformtheme/kdirselectdialog.cpp ../src/platformtheme/kfiletreeview.cpp ../src/platformtheme/kwaylandintegration.cpp ../src/platformtheme/x11integration.cpp ) -if(Qt5Core_VERSION VERSION_EQUAL "5.7.0" OR Qt5Core_VERSION VERSION_GREATER "5.7.0") -set(platformThemeSRCS - ../src/platformtheme/qdbusmenubar.cpp # fork of Qt's qdbusmenubar with some added setters for our convenience - ${platformThemeSRCS} -) -endif() - frameworkintegration_tests( kdeplatformtheme_unittest ${platformThemeSRCS} ) frameworkintegration_tests( kfontsettingsdata_unittest ../src/platformtheme/kfontsettingsdata.cpp ) frameworkintegration_tests( kfiledialog_unittest ) frameworkintegration_tests( ksni_unittest ) frameworkintegration_tests( kdirselectdialog_unittest ../src/platformtheme/kdeplatformfiledialogbase.cpp ../src/platformtheme/kdirselectdialog.cpp ../src/platformtheme/kfiletreeview.cpp ) frameworkintegration_tests( khintssettings_unittest ../src/platformtheme/khintssettings.cpp ) if(Qt5Qml_FOUND) add_test(NAME qmltests COMMAND qmltestrunner WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) frameworkintegration_tests(kfiledialogqml_unittest) target_link_libraries(kfiledialogqml_unittest Qt5::Qml) endif() diff --git a/autotests/kfiledialog_unittest.cpp b/autotests/kfiledialog_unittest.cpp index 37e9d9e..fe86bef 100644 --- a/autotests/kfiledialog_unittest.cpp +++ b/autotests/kfiledialog_unittest.cpp @@ -1,403 +1,399 @@ /* This file is part of the KDE libraries * Copyright 2014 Dominik Haumann * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License or ( at * your option ) version 3 or, at the discretion of KDE e.V. ( which shall * act as a proxy as in section 14 of the GPLv3 ), any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include Q_DECLARE_METATYPE(QFileDialog::ViewMode) Q_DECLARE_METATYPE(QFileDialog::FileMode) Q_DECLARE_METATYPE(KFile::FileView) Q_DECLARE_METATYPE(KFile::Modes) class KFileDialog_UnitTest : public QObject { Q_OBJECT private Q_SLOTS: void initTestCase() { qputenv("KDE_FORK_SLAVES", "yes"); } void init() { } void cleanupTestCase() { } void testSetNameFilters() { QFileDialog dialog; QStringList nameFilterList = QStringList() << QStringLiteral("c (*.cpp)") << QStringLiteral("h (*.h)"); dialog.setNameFilters(nameFilterList); QCOMPARE(dialog.nameFilters(), nameFilterList); } void testSelectNameFilter() { QFileDialog dialog; QStringList nameFilterList = QStringList() << QStringLiteral("c (*.cpp)") << QStringLiteral("h (*.h)"); dialog.setNameFilters(nameFilterList); QCOMPARE(dialog.nameFilters(), nameFilterList); QString selectNameFilter(QStringLiteral("h (*.h)")); dialog.selectNameFilter(selectNameFilter); QEXPECT_FAIL("", "Does currently not work. Works, once the dialog gets shown, though.", Continue); QCOMPARE(dialog.selectedNameFilter(), selectNameFilter); dialog.show(); QCOMPARE(dialog.selectedNameFilter(), selectNameFilter); } -#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) void testSelectedMimeTypeFilter_data() { QTest::addColumn("mimeTypeFilters"); QTest::addColumn("targetMimeTypeFilter"); const auto headerMime = QStringLiteral("text/x-chdr"); const auto jsonMime = QStringLiteral("application/json"); const auto zipMime = QStringLiteral("application/zip"); QTest::newRow("single mime filter (C header file)") << QStringList {headerMime} << headerMime; QTest::newRow("single mime filter (JSON file)") << QStringList {jsonMime} << jsonMime; QTest::newRow("multiple mime filters") << QStringList {jsonMime, zipMime} << jsonMime; } void testSelectedMimeTypeFilter() { QFileDialog dialog; QFETCH(QStringList, mimeTypeFilters); dialog.setMimeTypeFilters(mimeTypeFilters); QFETCH(QString, targetMimeTypeFilter); dialog.selectMimeTypeFilter(targetMimeTypeFilter); dialog.show(); QCOMPARE(dialog.selectedMimeTypeFilter(), targetMimeTypeFilter); } void testFallbackOnFirstFilterInSaveMode() { QFileDialog dialog; dialog.setAcceptMode(QFileDialog::AcceptSave); dialog.setMimeTypeFilters({QStringLiteral("application/json"), QStringLiteral("application/zip")}); dialog.show(); QCOMPARE(dialog.selectedMimeTypeFilter(), QStringLiteral("application/json")); } -#endif - - void testSetDirectory() { QFileDialog dialog; dialog.setDirectory(QDir::rootPath()); QCOMPARE(dialog.directory().absolutePath(), QDir::rootPath()); } void testSelectUrl() { QTemporaryFile tempFile(m_tempDir.path()+"/kfiledialogtest_XXXXXX"); tempFile.setAutoRemove(true); tempFile.open(); QString tempName = tempFile.fileName(); QUrl url = QUrl::fromLocalFile(tempName); int idx = tempName.lastIndexOf('/'); QUrl directoryUrl = QUrl::fromLocalFile(tempName.left(idx+1)); QFileDialog dialog; dialog.selectUrl(url); dialog.show(); // check if dialog was set to base directory url of the passed file url QCOMPARE(dialog.directoryUrl(), directoryUrl); } void testGetSaveFileUrl() { QObject lambdaGuard; QTemporaryFile tempFile(m_tempDir.path()+"/kfiledialogtest_XXXXXX"); tempFile.open(); const QString tempName = tempFile.fileName(); const QUrl url = QUrl::fromLocalFile(tempName); // Need to use a lambda and not just QTest::qWaitForWindowExposed(); // because with the static getSaveFileUrl we do not have access // to the QFileDialog object, so instead we hook to a signal KFileWidget::OperationMode saveFileOperationMode = KFileWidget::Other; connect(qApp, &QGuiApplication::focusWindowChanged, &lambdaGuard, [&saveFileOperationMode] { KFileWidget *fileWidget = findFileWidget(); saveFileOperationMode = fileWidget->operationMode(); qApp->activeWindow()->close(); }); QFileDialog::getSaveFileUrl(0, QString(), url); QCOMPARE(saveFileOperationMode, KFileWidget::Saving); } void testViewMode() { // Open a file dialog, and change view mode to tree { QFileDialog dialog; dialog.show(); KFileWidget *fw = findFileWidget(); QVERIFY(fw); fw->setViewMode(KFile::Tree); fw->slotCancel(); // the saving happens there } // Open another one, and check that the view mode is now tree, change it to simple { QFileDialog dialog; dialog.show(); KFileWidget *fw = findFileWidget(); QVERIFY(fw); // real show() is delayed to next event. QVERIFY(QTest::qWaitForWindowExposed(fw->window())); KDirOperator *op = fw->dirOperator(); QCOMPARE(fileViewToString(op->viewMode()), fileViewToString(KFile::Tree)); fw->setViewMode(KFile::Simple); fw->slotCancel(); } // Open another one, and check that the view mode is now simple { QFileDialog dialog; dialog.show(); KFileWidget *fw = findFileWidget(); QVERIFY(fw); KDirOperator *op = fw->dirOperator(); QCOMPARE(fileViewToString(op->viewMode()), fileViewToString(KFile::Simple)); fw->setViewMode(KFile::Detail); fw->slotCancel(); } } void testOpenDialog() { // Open parentless { QFileDialog dialog; dialog.open(); KFileWidget *fw = findFileWidget(); QVERIFY(fw); // real show() is delayed to next event. QVERIFY(QTest::qWaitForWindowExposed(fw->window())); QCOMPARE(fw->isVisible(), true); fw->slotCancel(); } // Open with parent { QWidget w; w.show(); QFileDialog dialog(&w); dialog.open(); KFileWidget *fw = findFileWidget(); QVERIFY(fw); // real show() is delayed to next event. QVERIFY(QTest::qWaitForWindowExposed(fw->window())); QCOMPARE(fw->isVisible(), true); fw->slotCancel(); } } void testShowDialog() { // Show parentless { QFileDialog dialog; dialog.show(); KFileWidget *fw = findFileWidget(); QVERIFY(fw); // real show() is delayed to next event. QVERIFY(QTest::qWaitForWindowExposed(fw->window())); QCOMPARE(fw->isVisible(), true); fw->slotCancel(); } // Show with parent { QWidget w; w.show(); QFileDialog dialog(&w); dialog.show(); KFileWidget *fw = findFileWidget(); QVERIFY(fw); // real show() is delayed to next event. QVERIFY(QTest::qWaitForWindowExposed(fw->window())); QCOMPARE(fw->isVisible(), true); fw->slotCancel(); } } void testSetFileMode_data() { QTest::addColumn("qtFileMode"); QTest::addColumn("kdeFileMode"); QTest::newRow("anyfile") << QFileDialog::AnyFile << KFile::Modes(KFile::File); QTest::newRow("existingfile") << QFileDialog::ExistingFile << KFile::Modes(KFile::File | KFile::ExistingOnly); QTest::newRow("directory") << QFileDialog::Directory << KFile::Modes(KFile::Directory | KFile::ExistingOnly); QTest::newRow("existingfiles") << QFileDialog::ExistingFiles << KFile::Modes(KFile::Files | KFile::ExistingOnly); } void testSetFileMode() { QFETCH(QFileDialog::FileMode, qtFileMode); QFETCH(KFile::Modes, kdeFileMode); QFileDialog dialog; dialog.setFileMode(qtFileMode); dialog.show(); KFileWidget *fw = findFileWidget(); QVERIFY(fw); QCOMPARE(fw->mode(), kdeFileMode); QCOMPARE(dialog.fileMode(), qtFileMode); } void testSaveOverwrite_data() { QTest::addColumn("qtOverwriteOption"); QTest::addColumn("messageBoxExpected"); QTest::newRow("checkoverwrite") << false << true; QTest::newRow("allowoverwrite") << true << false; } void testSaveOverwrite() { QFETCH(bool, qtOverwriteOption); QFETCH(bool, messageBoxExpected); QTemporaryFile tempFile(m_tempDir.path()+"/kfiledialogtest_XXXXXX"); tempFile.setAutoRemove(true); tempFile.open(); QString tempName = tempFile.fileName(); tempFile.close(); int idx = tempName.lastIndexOf('/'); QFileDialog dialog; dialog.setAcceptMode(QFileDialog::AcceptSave); if (qtOverwriteOption) dialog.setOption(QFileDialog::DontConfirmOverwrite); dialog.setDirectory(tempName.left(idx+1)); dialog.selectFile(tempName.mid(idx+1)); dialog.open(); KFileWidget *fw = findFileWidget(); QVERIFY(fw); QVERIFY(QTest::qWaitForWindowExposed(fw->window())); QCOMPARE(fw->isVisible(), true); bool timerRun = false; QTimer::singleShot(3500, this, [&] { timerRun = true; QDialog *msgbox = findMessageBox(); if (msgbox) { QVERIFY(QTest::qWaitForWindowExposed(msgbox)); QCOMPARE(msgbox->isVisible(), true); msgbox->close(); QVERIFY(messageBoxExpected); } else { QVERIFY(!messageBoxExpected); } }); fw->slotOk(); QTRY_VERIFY(timerRun); } private: QTemporaryDir m_tempDir; static QString fileViewToString(KFile::FileView fv) { switch (fv) { case KFile::Detail: return QStringLiteral("Detail"); case KFile::Simple: return QStringLiteral("Simple"); case KFile::Tree: return QStringLiteral("Tree"); case KFile::DetailTree: return QStringLiteral("DetailTree"); default: break; } return QStringLiteral("ERROR"); } static KFileWidget *findFileWidget() { QList widgets; foreach (QWidget *widget, QApplication::topLevelWidgets()) { KFileWidget *fw = widget->findChild(); if (fw) { widgets.append(fw); } } Q_ASSERT(widgets.count() == 1); return (widgets.count() == 1) ? widgets.first() : Q_NULLPTR; } static QDialog *findMessageBox() { QList widgets; foreach (QWidget *widget, QApplication::topLevelWidgets()) { QDialog *dlg = widget->findChild(); if (dlg) { widgets.append(dlg); } } return (widgets.count() == 1) ? widgets.first() : Q_NULLPTR; } }; QTEST_MAIN(KFileDialog_UnitTest) #include "kfiledialog_unittest.moc" diff --git a/src/platformtheme/CMakeLists.txt b/src/platformtheme/CMakeLists.txt index dbb117f..f852383 100644 --- a/src/platformtheme/CMakeLists.txt +++ b/src/platformtheme/CMakeLists.txt @@ -1,73 +1,67 @@ find_package(X11) set_package_properties(X11 PROPERTIES DESCRIPTION "Required for updating the Cursor theme on X11" URL "http://www.x.org" TYPE REQUIRED ) set(HAVE_X11 ${X11_FOUND}) if(HAVE_X11) find_package(Qt5 ${REQUIRED_QT_VERSION} CONFIG REQUIRED X11Extras) find_package(XCB COMPONENTS XCB) set_package_properties(XCB PROPERTIES TYPE REQUIRED) endif() configure_file(config-platformtheme.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-platformtheme.h ) # qdbusmenubar uses them remove_definitions(-DQT_NO_SIGNALS_SLOTS_KEYWORDS) include_directories(${Qt5Core_PRIVATE_INCLUDE_DIRS}) include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS}) set(platformtheme_SRCS + qdbusmenubar.cpp # fork of Qt's qdbusmenubar with some added setters for our convenience kdeplatformtheme.cpp kfontsettingsdata.cpp khintssettings.cpp kdeplatformfiledialoghelper.cpp kdeplatformfiledialogbase.cpp kdeplatformsystemtrayicon.cpp kfiletreeview.cpp kdirselectdialog.cpp kwaylandintegration.cpp x11integration.cpp main.cpp ) -if(Qt5Core_VERSION VERSION_EQUAL "5.7.0" OR Qt5Core_VERSION VERSION_GREATER "5.7.0") -set(platformtheme_SRCS - qdbusmenubar.cpp # fork of Qt's qdbusmenubar with some added setters for our convenience - ${platformtheme_SRCS} -) -endif() - add_library(KDEPlasmaPlatformTheme MODULE ${platformtheme_SRCS}) target_link_libraries(KDEPlasmaPlatformTheme PRIVATE Qt5::DBus Qt5::X11Extras Qt5::QuickControls2 KF5::ConfigWidgets KF5::ConfigCore KF5::IconThemes KF5::KIOFileWidgets # KFileFilterCombo, KDirSortFilterProxyModel, KRecentDirs KF5::KIOWidgets KF5::XmlGui KF5::I18n KF5::Notifications KF5::WindowSystem KF5::WaylandClient XCB::XCB ${QT5PLATFORMSUPPORT_LIBS} ) if(HAVE_X11) target_link_libraries(KDEPlasmaPlatformTheme PRIVATE Qt5::X11Extras ${X11_Xcursor_LIB} ${XCB_XCB_LIBRARY}) endif() install(TARGETS KDEPlasmaPlatformTheme DESTINATION ${KDE_INSTALL_QTPLUGINDIR}/platformthemes) install(FILES fonts_global_toolbar.upd fonts_global.upd fonts_akregator.upd fonts_kate.upd DESTINATION ${KDE_INSTALL_KCONFUPDATEDIR}) install(PROGRAMS fonts_global.pl fonts_akregator.pl fonts_kate.pl DESTINATION ${KDE_INSTALL_KCONFUPDATEDIR}) diff --git a/src/platformtheme/kdeplatformfiledialoghelper.cpp b/src/platformtheme/kdeplatformfiledialoghelper.cpp index e0329e3..738e81d 100644 --- a/src/platformtheme/kdeplatformfiledialoghelper.cpp +++ b/src/platformtheme/kdeplatformfiledialoghelper.cpp @@ -1,444 +1,434 @@ /* This file is part of the KDE libraries * Copyright 2013 Aleix Pol Gonzalez * Copyright 2014 Martin Klapetek * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License or ( at * your option ) version 3 or, at the discretion of KDE e.V. ( which shall * act as a proxy as in section 14 of the GPLv3 ), any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kdeplatformfiledialoghelper.h" #include "kdeplatformfiledialogbase_p.h" #include "kdirselectdialog_p.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace { /* * Map a Qt filter string into a KDE one. */ static QString qt2KdeFilter(const QStringList &f) { QString filter; QTextStream str(&filter, QIODevice::WriteOnly); QStringList list(f); list.replaceInStrings(QStringLiteral("/"), QStringLiteral("\\/")); QStringList::const_iterator it(list.constBegin()), end(list.constEnd()); bool first = true; for (; it != end; ++it) { int ob = it->lastIndexOf(QLatin1Char('(')), cb = it->lastIndexOf(QLatin1Char(')')); if (-1 != cb && ob < cb) { if (first) { first = false; } else { str << '\n'; } str << it->mid(ob + 1, (cb - ob) - 1) << '|' << it->mid(0, ob); } } return filter; } /* * Map a KDE filter string into a Qt one. */ static QString kde2QtFilter(const QStringList &list, const QString &kde) { QStringList::const_iterator it(list.constBegin()), end(list.constEnd()); int pos; for (; it != end; ++it) { if (-1 != (pos = it->indexOf(kde)) && pos > 0 && (QLatin1Char('(') == (*it)[pos - 1] || QLatin1Char(' ') == (*it)[pos - 1]) && it->length() >= kde.length() + pos && (QLatin1Char(')') == (*it)[pos + kde.length()] || QLatin1Char(' ') == (*it)[pos + kde.length()])) { return *it; } } return QString(); } } KDEPlatformFileDialog::KDEPlatformFileDialog() : KDEPlatformFileDialogBase() , m_fileWidget(new KFileWidget(QUrl(), this)) { setLayout(new QVBoxLayout); connect(m_fileWidget, SIGNAL(filterChanged(QString)), SIGNAL(filterSelected(QString))); layout()->addWidget(m_fileWidget); m_buttons = new QDialogButtonBox(this); m_buttons->addButton(m_fileWidget->okButton(), QDialogButtonBox::AcceptRole); m_buttons->addButton(m_fileWidget->cancelButton(), QDialogButtonBox::RejectRole); connect(m_buttons, SIGNAL(rejected()), m_fileWidget, SLOT(slotCancel())); connect(m_fileWidget->okButton(), SIGNAL(clicked(bool)), m_fileWidget, SLOT(slotOk())); connect(m_fileWidget, SIGNAL(accepted()), m_fileWidget, SLOT(accept())); connect(m_fileWidget, SIGNAL(accepted()), SLOT(accept())); connect(m_fileWidget->cancelButton(), SIGNAL(clicked(bool)), SLOT(reject())); layout()->addWidget(m_buttons); } QUrl KDEPlatformFileDialog::directory() { return m_fileWidget->baseUrl(); } QList KDEPlatformFileDialog::selectedFiles() { return m_fileWidget->selectedUrls(); } void KDEPlatformFileDialog::selectFile(const QUrl &filename) { QUrl dirUrl = filename.adjusted(QUrl::RemoveFilename); m_fileWidget->setUrl(dirUrl); m_fileWidget->setSelectedUrl(filename); } void KDEPlatformFileDialog::setViewMode(QFileDialogOptions::ViewMode view) { switch (view) { case QFileDialogOptions::ViewMode::Detail: m_fileWidget->setViewMode(KFile::FileView::Detail); break; case QFileDialogOptions::ViewMode::List: m_fileWidget->setViewMode(KFile::FileView::Simple); break; default: m_fileWidget->setViewMode(KFile::FileView::Default); break; } } void KDEPlatformFileDialog::setFileMode(QFileDialogOptions::FileMode mode) { switch (mode) { case QFileDialogOptions::FileMode::AnyFile: m_fileWidget->setMode(KFile::File); break; case QFileDialogOptions::FileMode::ExistingFile: m_fileWidget->setMode(KFile::Mode::File | KFile::Mode::ExistingOnly); break; case QFileDialogOptions::FileMode::Directory: m_fileWidget->setMode(KFile::Mode::Directory | KFile::Mode::ExistingOnly); break; case QFileDialogOptions::FileMode::ExistingFiles: m_fileWidget->setMode(KFile::Mode::Files | KFile::Mode::ExistingOnly); break; default: m_fileWidget->setMode(KFile::File); break; } } void KDEPlatformFileDialog::setCustomLabel(QFileDialogOptions::DialogLabel label, const QString &text) { if (label == QFileDialogOptions::Accept) { // OK button m_fileWidget->okButton()->setText(text); } else if (label == QFileDialogOptions::Reject) { // Cancel button m_fileWidget->cancelButton()->setText(text); } else if (label == QFileDialogOptions::LookIn) { // Location label m_fileWidget->setLocationLabel(text); } } QString KDEPlatformFileDialog::selectedMimeTypeFilter() { if (m_fileWidget->filterWidget()->isMimeFilter()) { const auto mimeTypeFromFilter = QMimeDatabase().mimeTypeForName(m_fileWidget->filterWidget()->currentFilter()); // If one does not call selectMimeTypeFilter(), KFileFilterCombo::currentFilter() returns invalid mimeTypes, // such as "application/json application/zip". if (mimeTypeFromFilter.isValid()) { return mimeTypeFromFilter.name(); } } if (selectedFiles().isEmpty()) { return QString(); } // Works for both KFile::File and KFile::Files modes. return QMimeDatabase().mimeTypeForUrl(selectedFiles().at(0)).name(); } QString KDEPlatformFileDialog::selectedNameFilter() { return m_fileWidget->filterWidget()->currentFilter(); } void KDEPlatformFileDialog::selectMimeTypeFilter(const QString &filter) { m_fileWidget->filterWidget()->setCurrentFilter(filter); } void KDEPlatformFileDialog::selectNameFilter(const QString &filter) { m_fileWidget->filterWidget()->setCurrentFilter(filter); } void KDEPlatformFileDialog::setDirectory(const QUrl &directory) { if (!directory.isLocalFile()) { // Qt can not determine if the remote URL points to a file or a // directory, that is why options()->initialDirectory() always returns // the full URL. KIO::StatJob *job = KIO::stat(directory); KJobWidgets::setWindow(job, this); if (job->exec()) { KIO::UDSEntry entry = job->statResult(); if (!entry.isDir()) { // this is probably a file remove the file part m_fileWidget->setUrl(directory.adjusted(QUrl::RemoveFilename)); m_fileWidget->setSelectedUrl(directory); } else { m_fileWidget->setUrl(directory); } } } else { m_fileWidget->setUrl(directory); } } bool KDEPlatformFileDialogHelper::isSupportedUrl(const QUrl& url) const { return KProtocolInfo::protocols().contains(url.scheme()); } //////////////////////////////////////////////// KDEPlatformFileDialogHelper::KDEPlatformFileDialogHelper() : QPlatformFileDialogHelper() , m_dialog(new KDEPlatformFileDialog) { connect(m_dialog, SIGNAL(closed()), SLOT(saveSize())); connect(m_dialog, SIGNAL(finished(int)), SLOT(saveSize())); connect(m_dialog, SIGNAL(currentChanged(QUrl)), SIGNAL(currentChanged(QUrl))); connect(m_dialog, SIGNAL(directoryEntered(QUrl)), SIGNAL(directoryEntered(QUrl))); connect(m_dialog, SIGNAL(fileSelected(QUrl)), SIGNAL(fileSelected(QUrl))); connect(m_dialog, SIGNAL(filesSelected(QList)), SIGNAL(filesSelected(QList))); connect(m_dialog, SIGNAL(filterSelected(QString)), SIGNAL(filterSelected(QString))); connect(m_dialog, SIGNAL(accepted()), SIGNAL(accept())); connect(m_dialog, SIGNAL(rejected()), SIGNAL(reject())); } KDEPlatformFileDialogHelper::~KDEPlatformFileDialogHelper() { saveSize(); delete m_dialog; } void KDEPlatformFileDialogHelper::initializeDialog() { if (options()->testOption(QFileDialogOptions::ShowDirsOnly)) { m_dialog->deleteLater(); m_dialog = new KDirSelectDialog(options()->initialDirectory()); connect(m_dialog, SIGNAL(accepted()), SIGNAL(accept())); connect(m_dialog, SIGNAL(rejected()), SIGNAL(reject())); if (!options()->windowTitle().isEmpty()) m_dialog->setWindowTitle(options()->windowTitle()); } else { // needed for accessing m_fileWidget KDEPlatformFileDialog *dialog = qobject_cast(m_dialog); dialog->m_fileWidget->setOperationMode(options()->acceptMode() == QFileDialogOptions::AcceptOpen ? KFileWidget::Opening : KFileWidget::Saving); if (options()->windowTitle().isEmpty()) { dialog->setWindowTitle(options()->acceptMode() == QFileDialogOptions::AcceptOpen ? i18nc("@title:window", "Open File") : i18nc("@title:window", "Save File")); } else { dialog->setWindowTitle(options()->windowTitle()); } setDirectory(options()->initialDirectory()); //dialog->setViewMode(options()->viewMode()); // don't override our options, fixes remembering the chosen view mode and sizes! dialog->setFileMode(options()->fileMode()); // custom labels if (options()->isLabelExplicitlySet(QFileDialogOptions::Accept)) { // OK button dialog->setCustomLabel(QFileDialogOptions::Accept, options()->labelText(QFileDialogOptions::Accept)); } else if (options()->isLabelExplicitlySet(QFileDialogOptions::Reject)) { // Cancel button dialog->setCustomLabel(QFileDialogOptions::Reject, options()->labelText(QFileDialogOptions::Reject)); } else if (options()->isLabelExplicitlySet(QFileDialogOptions::LookIn)) { // Location label dialog->setCustomLabel(QFileDialogOptions::LookIn, options()->labelText(QFileDialogOptions::LookIn)); } const QStringList mimeFilters = options()->mimeTypeFilters(); const QStringList nameFilters = options()->nameFilters(); if (!mimeFilters.isEmpty()) { QString defaultMimeFilter; if (options()->acceptMode() == QFileDialogOptions::AcceptSave) { -#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) defaultMimeFilter = options()->initiallySelectedMimeTypeFilter(); -#endif if (defaultMimeFilter.isEmpty()) { defaultMimeFilter = mimeFilters.at(0); } } dialog->m_fileWidget->setMimeFilter(mimeFilters, defaultMimeFilter); if ( mimeFilters.contains( QStringLiteral("inode/directory") ) ) dialog->m_fileWidget->setMode( dialog->m_fileWidget->mode() | KFile::Directory ); } else if (!nameFilters.isEmpty()) { dialog->m_fileWidget->setFilter(qt2KdeFilter(nameFilters)); } -#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) if (!options()->initiallySelectedMimeTypeFilter().isEmpty()) { selectMimeTypeFilter(options()->initiallySelectedMimeTypeFilter()); } else if (!options()->initiallySelectedNameFilter().isEmpty()) { selectNameFilter(options()->initiallySelectedNameFilter()); } -#else - if (!options()->initiallySelectedNameFilter().isEmpty()) { - selectNameFilter(options()->initiallySelectedNameFilter()); - } -#endif // overwrite option if (options()->testOption(QFileDialogOptions::FileDialogOption::DontConfirmOverwrite)) { dialog->m_fileWidget->setConfirmOverwrite(false); } else if (options()->acceptMode() == QFileDialogOptions::AcceptSave) { dialog->m_fileWidget->setConfirmOverwrite(true); } } } void KDEPlatformFileDialogHelper::exec() { restoreSize(); // KDEPlatformFileDialog::show() will always be called during QFileDialog::exec() // discard the delayed show() it and use exec() and it will call show() for us. // We can't hide and show it here because of https://bugreports.qt.io/browse/QTBUG-48248 m_dialog->discardDelayedShow(); m_dialog->exec(); } void KDEPlatformFileDialogHelper::hide() { m_dialog->discardDelayedShow(); m_dialog->hide(); } void KDEPlatformFileDialogHelper::saveSize() { KSharedConfig::Ptr conf = KSharedConfig::openConfig(); KConfigGroup group = conf->group("FileDialogSize"); KWindowConfig::saveWindowSize(m_dialog->windowHandle(), group); } void KDEPlatformFileDialogHelper::restoreSize() { m_dialog->winId(); // ensure there's a window created KSharedConfig::Ptr conf = KSharedConfig::openConfig(); KWindowConfig::restoreWindowSize(m_dialog->windowHandle(), conf->group("FileDialogSize")); // NOTICE: QWindow::setGeometry() does NOT impact the backing QWidget geometry even if the platform // window was created -> QTBUG-40584. We therefore copy the size here. // TODO: remove once this was resolved in QWidget QPA m_dialog->resize(m_dialog->windowHandle()->size()); } bool KDEPlatformFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) { initializeDialog(); m_dialog->setWindowFlags(windowFlags); m_dialog->setWindowModality(windowModality); restoreSize(); m_dialog->windowHandle()->setTransientParent(parent); // Use a delayed show here to delay show() after the internal Qt invisible QDialog. // The delayed call shouldn't matter, because for other "real" native QPlatformDialog // implementation like Mac and Windows, the native dialog is not necessarily // show up immediately. m_dialog->delayedShow(); return true; } QList KDEPlatformFileDialogHelper::selectedFiles() const { return m_dialog->selectedFiles(); } -#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) QString KDEPlatformFileDialogHelper::selectedMimeTypeFilter() const { return m_dialog->selectedMimeTypeFilter(); } void KDEPlatformFileDialogHelper::selectMimeTypeFilter(const QString &filter) { m_dialog->selectMimeTypeFilter(filter); } -#endif QString KDEPlatformFileDialogHelper::selectedNameFilter() const { return kde2QtFilter(options()->nameFilters(), m_dialog->selectedNameFilter()); } QUrl KDEPlatformFileDialogHelper::directory() const { return m_dialog->directory(); } void KDEPlatformFileDialogHelper::selectFile(const QUrl &filename) { m_dialog->selectFile(filename); // Qt 5 at least <= 5.8.0 does not derive the directory from the passed url // and set the initialDirectory option accordingly, also not for known schemes // like file://, so we have to do it ourselves options()->setInitialDirectory(m_dialog->directory()); } void KDEPlatformFileDialogHelper::setDirectory(const QUrl &directory) { if (!directory.isEmpty()) { m_dialog->setDirectory(directory); } } void KDEPlatformFileDialogHelper::selectNameFilter(const QString &filter) { m_dialog->selectNameFilter(qt2KdeFilter(QStringList(filter))); } void KDEPlatformFileDialogHelper::setFilter() { } bool KDEPlatformFileDialogHelper::defaultNameFilterDisables() const { return false; } diff --git a/src/platformtheme/kdeplatformfiledialoghelper.h b/src/platformtheme/kdeplatformfiledialoghelper.h index 24cf561..b0ea0c2 100644 --- a/src/platformtheme/kdeplatformfiledialoghelper.h +++ b/src/platformtheme/kdeplatformfiledialoghelper.h @@ -1,87 +1,85 @@ /* This file is part of the KDE libraries * Copyright 2013 Aleix Pol Gonzalez * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License or ( at * your option ) version 3 or, at the discretion of KDE e.V. ( which shall * act as a proxy as in section 14 of the GPLv3 ), any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KDEPLATFORMFILEDIALOGHELPER_H #define KDEPLATFORMFILEDIALOGHELPER_H #include #include "kdeplatformfiledialogbase_p.h" class KFileWidget; class QDialogButtonBox; class KDEPlatformFileDialog : public KDEPlatformFileDialogBase { Q_OBJECT public: friend class KDEPlatformFileDialogHelper; explicit KDEPlatformFileDialog(); QUrl directory() override; void selectMimeTypeFilter(const QString &filter) override; void selectNameFilter(const QString &filter) override; void setDirectory(const QUrl &directory) override; void selectFile(const QUrl &filename) override; void setViewMode(QFileDialogOptions::ViewMode view); void setFileMode(QFileDialogOptions::FileMode mode); void setCustomLabel(QFileDialogOptions::DialogLabel label, const QString & text); QString selectedMimeTypeFilter() override; QString selectedNameFilter() override; QList selectedFiles() override; protected: KFileWidget *m_fileWidget; }; class KDEPlatformFileDialogHelper : public QPlatformFileDialogHelper { Q_OBJECT public: KDEPlatformFileDialogHelper(); virtual ~KDEPlatformFileDialogHelper(); void initializeDialog(); bool defaultNameFilterDisables() const override; QUrl directory() const override; QList selectedFiles() const override; -#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) QString selectedMimeTypeFilter() const override; void selectMimeTypeFilter(const QString &filter) override; -#endif QString selectedNameFilter() const override; void selectNameFilter(const QString &filter) override; void selectFile(const QUrl &filename) override; void setFilter() override; void setDirectory(const QUrl &directory) override; bool isSupportedUrl(const QUrl& url) const override; void exec() override; void hide() override; bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) override; private Q_SLOTS: void saveSize(); private: void restoreSize(); KDEPlatformFileDialogBase *m_dialog; }; #endif // KDEPLATFORMFILEDIALOGHELPER_H diff --git a/src/platformtheme/kdeplatformtheme.cpp b/src/platformtheme/kdeplatformtheme.cpp index 451b2c5..64cdbfe 100644 --- a/src/platformtheme/kdeplatformtheme.cpp +++ b/src/platformtheme/kdeplatformtheme.cpp @@ -1,408 +1,397 @@ /* This file is part of the KDE libraries * Copyright 2013 Kevin Ottens * Copyright 2013 Aleix Pol Gonzalez * Copyright 2014 Lukáš Tinkl * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License or ( at * your option ) version 3 or, at the discretion of KDE e.V. ( which shall * act as a proxy as in section 14 of the GPLv3 ), any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include "kdeplatformtheme.h" #include "kfontsettingsdata.h" #include "khintssettings.h" #include "kdeplatformfiledialoghelper.h" #include "kdeplatformsystemtrayicon.h" #include "kwaylandintegration.h" #include "x11integration.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#if QT_VERSION >= QT_VERSION_CHECK(5,7,0) #include "qdbusmenubar_p.h" -#endif static const QByteArray s_x11AppMenuServiceNamePropertyName = QByteArrayLiteral("_KDE_NET_WM_APPMENU_SERVICE_NAME"); static const QByteArray s_x11AppMenuObjectPathPropertyName = QByteArrayLiteral("_KDE_NET_WM_APPMENU_OBJECT_PATH"); static bool checkDBusGlobalMenuAvailable() { if (qEnvironmentVariableIsSet("KDE_NO_GLOBAL_MENU")) { return false; } QDBusConnection connection = QDBusConnection::sessionBus(); QString registrarService = QStringLiteral("com.canonical.AppMenu.Registrar"); return connection.interface()->isServiceRegistered(registrarService); } static bool isDBusGlobalMenuAvailable() { static bool dbusGlobalMenuAvailable = checkDBusGlobalMenuAvailable(); return dbusGlobalMenuAvailable; } KdePlatformTheme::KdePlatformTheme() { loadSettings(); if (KWindowSystem::isPlatformWayland()) { m_kwaylandIntegration.reset(new KWaylandIntegration()); m_kwaylandIntegration->init(); } #if HAVE_X11 if (KWindowSystem::isPlatformX11()) { m_x11Integration.reset(new X11Integration()); m_x11Integration->init(); } #endif QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, false); setQtQuickControlsTheme(); } KdePlatformTheme::~KdePlatformTheme() { delete m_fontsData; delete m_hints; } QVariant KdePlatformTheme::themeHint(QPlatformTheme::ThemeHint hintType) const { QVariant hint = m_hints->hint(hintType); if (hint.isValid()) { return hint; } else { return QPlatformTheme::themeHint(hintType); } } QIcon KdePlatformTheme::fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions iconOptions) const { if (iconOptions.testFlag(DontUseCustomDirectoryIcons) && fileInfo.isDir()) { return QIcon::fromTheme(QLatin1String("inode-directory")); } return QIcon::fromTheme(KIO::iconNameForUrl(QUrl::fromLocalFile(fileInfo.absoluteFilePath()))); } -#if QT_VERSION < QT_VERSION_CHECK(5, 8, 0) -QPixmap KdePlatformTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size, QPlatformTheme::IconOptions iconOptions) const -{ - return fileIcon(fileInfo, iconOptions).pixmap(size.toSize(), QIcon::Normal); -} -#endif - const QPalette *KdePlatformTheme::palette(Palette type) const { QPalette *palette = m_hints->palette(type); if (palette) { return palette; } else { return QPlatformTheme::palette(type); } } const QFont *KdePlatformTheme::font(Font type) const { KFontSettingsData::FontTypes fdtype; switch (type) { case SystemFont: fdtype = KFontSettingsData::GeneralFont; break; case MenuFont: case MenuBarFont: case MenuItemFont: fdtype = KFontSettingsData::MenuFont; break; case MessageBoxFont: case LabelFont: case TipLabelFont: case StatusBarFont: case PushButtonFont: case ItemViewFont: case ListViewFont: case HeaderViewFont: case ListBoxFont: case ComboMenuItemFont: case ComboLineEditFont: fdtype = KFontSettingsData::GeneralFont; break; case TitleBarFont: case MdiSubWindowTitleFont: case DockWidgetTitleFont: fdtype = KFontSettingsData::WindowTitleFont; break; case SmallFont: case MiniFont: fdtype = KFontSettingsData::SmallestReadableFont; break; case FixedFont: fdtype = KFontSettingsData::FixedFont; break; case ToolButtonFont: fdtype = KFontSettingsData::ToolbarFont; break; default: fdtype = KFontSettingsData::GeneralFont; break; } return m_fontsData->font(fdtype); } QIconEngine *KdePlatformTheme::createIconEngine(const QString &iconName) const { return new KIconEngine(iconName, KIconLoader::global()); } void KdePlatformTheme::loadSettings() { m_fontsData = new KFontSettingsData; m_hints = new KHintsSettings; } QList KdePlatformTheme::keyBindings(QKeySequence::StandardKey key) const { switch (key) { case QKeySequence::HelpContents: return KStandardShortcut::shortcut(KStandardShortcut::Help); case QKeySequence::WhatsThis: return KStandardShortcut::shortcut(KStandardShortcut::WhatsThis); case QKeySequence::Open: return KStandardShortcut::shortcut(KStandardShortcut::Open); case QKeySequence::Close: return KStandardShortcut::shortcut(KStandardShortcut::Close); case QKeySequence::Save: return KStandardShortcut::shortcut(KStandardShortcut::Save); case QKeySequence::New: return KStandardShortcut::shortcut(KStandardShortcut::New); case QKeySequence::Cut: return KStandardShortcut::shortcut(KStandardShortcut::Cut); case QKeySequence::Copy: return KStandardShortcut::shortcut(KStandardShortcut::Copy); case QKeySequence::Paste: return KStandardShortcut::shortcut(KStandardShortcut::Paste); case QKeySequence::Undo: return KStandardShortcut::shortcut(KStandardShortcut::Undo); case QKeySequence::Redo: return KStandardShortcut::shortcut(KStandardShortcut::Redo); case QKeySequence::Back: return KStandardShortcut::shortcut(KStandardShortcut::Back); case QKeySequence::Forward: return KStandardShortcut::shortcut(KStandardShortcut::Forward); case QKeySequence::Refresh: return KStandardShortcut::shortcut(KStandardShortcut::Reload); case QKeySequence::ZoomIn: return KStandardShortcut::shortcut(KStandardShortcut::ZoomIn); case QKeySequence::ZoomOut: return KStandardShortcut::shortcut(KStandardShortcut::ZoomOut); case QKeySequence::Print: return KStandardShortcut::shortcut(KStandardShortcut::Print); case QKeySequence::Find: return KStandardShortcut::shortcut(KStandardShortcut::Find); case QKeySequence::FindNext: return KStandardShortcut::shortcut(KStandardShortcut::FindNext); case QKeySequence::FindPrevious: return KStandardShortcut::shortcut(KStandardShortcut::FindPrev); case QKeySequence::Replace: return KStandardShortcut::shortcut(KStandardShortcut::Replace); case QKeySequence::SelectAll: return KStandardShortcut::shortcut(KStandardShortcut::SelectAll); case QKeySequence::MoveToNextWord: return KStandardShortcut::shortcut(KStandardShortcut::ForwardWord); case QKeySequence::MoveToPreviousWord: return KStandardShortcut::shortcut(KStandardShortcut::BackwardWord); case QKeySequence::MoveToNextPage: return KStandardShortcut::shortcut(KStandardShortcut::Next); case QKeySequence::MoveToPreviousPage: return KStandardShortcut::shortcut(KStandardShortcut::Prior); case QKeySequence::MoveToStartOfLine: return KStandardShortcut::shortcut(KStandardShortcut::BeginningOfLine); case QKeySequence::MoveToEndOfLine: return KStandardShortcut::shortcut(KStandardShortcut::EndOfLine); case QKeySequence::MoveToStartOfDocument: return KStandardShortcut::shortcut(KStandardShortcut::Begin); case QKeySequence::MoveToEndOfDocument: return KStandardShortcut::shortcut(KStandardShortcut::End); case QKeySequence::SaveAs: return KStandardShortcut::shortcut(KStandardShortcut::SaveAs); case QKeySequence::Preferences: return KStandardShortcut::shortcut(KStandardShortcut::Preferences); case QKeySequence::Quit: return KStandardShortcut::shortcut(KStandardShortcut::Quit); case QKeySequence::FullScreen: return KStandardShortcut::shortcut(KStandardShortcut::FullScreen); case QKeySequence::Deselect: return KStandardShortcut::shortcut(KStandardShortcut::Deselect); case QKeySequence::DeleteStartOfWord: return KStandardShortcut::shortcut(KStandardShortcut::DeleteWordBack); case QKeySequence::DeleteEndOfWord: return KStandardShortcut::shortcut(KStandardShortcut::DeleteWordForward); case QKeySequence::NextChild: return KStandardShortcut::shortcut(KStandardShortcut::TabNext); case QKeySequence::PreviousChild: return KStandardShortcut::shortcut(KStandardShortcut::TabPrev); default: return QPlatformTheme::keyBindings(key); } } bool KdePlatformTheme::usePlatformNativeDialog(QPlatformTheme::DialogType type) const { return type == QPlatformTheme::FileDialog && qobject_cast(QCoreApplication::instance()); } QString KdePlatformTheme::standardButtonText(int button) const { switch (static_cast(button)) { case QPlatformDialogHelper::NoButton: qWarning() << Q_FUNC_INFO << "Unsupported standard button:" << button; return QString(); case QPlatformDialogHelper::Ok: return KStandardGuiItem::ok().text(); case QPlatformDialogHelper::Save: return KStandardGuiItem::save().text(); case QPlatformDialogHelper::SaveAll: return i18nc("@action:button", "Save All"); case QPlatformDialogHelper::Open: return KStandardGuiItem::open().text(); case QPlatformDialogHelper::Yes: return KStandardGuiItem::yes().text(); case QPlatformDialogHelper::YesToAll: return i18nc("@action:button", "Yes to All"); case QPlatformDialogHelper::No: return KStandardGuiItem::no().text(); case QPlatformDialogHelper::NoToAll: return i18nc("@action:button", "No to All"); case QPlatformDialogHelper::Abort: // FIXME KStandardGuiItem::stop() doesn't seem right here return i18nc("@action:button", "Abort"); case QPlatformDialogHelper::Retry: return i18nc("@action:button", "Retry"); case QPlatformDialogHelper::Ignore: return i18nc("@action:button", "Ignore"); case QPlatformDialogHelper::Close: return KStandardGuiItem::close().text(); case QPlatformDialogHelper::Cancel: return KStandardGuiItem::cancel().text(); case QPlatformDialogHelper::Discard: return KStandardGuiItem::discard().text(); case QPlatformDialogHelper::Help: return KStandardGuiItem::help().text(); case QPlatformDialogHelper::Apply: return KStandardGuiItem::apply().text(); case QPlatformDialogHelper::Reset: return KStandardGuiItem::reset().text(); case QPlatformDialogHelper::RestoreDefaults: return KStandardGuiItem::defaults().text(); default: return QPlatformTheme::defaultStandardButtonText(button); } } QPlatformDialogHelper *KdePlatformTheme::createPlatformDialogHelper(QPlatformTheme::DialogType type) const { switch (type) { case QPlatformTheme::FileDialog: return new KDEPlatformFileDialogHelper; case QPlatformTheme::FontDialog: case QPlatformTheme::ColorDialog: case QPlatformTheme::MessageDialog: default: return 0; } } QPlatformSystemTrayIcon *KdePlatformTheme::createPlatformSystemTrayIcon() const { return new KDEPlatformSystemTrayIcon; } -#if QT_VERSION >= QT_VERSION_CHECK(5,7,0) QPlatformMenuBar *KdePlatformTheme::createPlatformMenuBar() const { if (isDBusGlobalMenuAvailable()) { auto *menu = new QDBusMenuBar(); QObject::connect(menu, &QDBusMenuBar::windowChanged, menu, [this, menu](QWindow *newWindow, QWindow *oldWindow) { const QString &serviceName = QDBusConnection::sessionBus().baseService(); const QString &objectPath = menu->objectPath(); if (m_x11Integration) { if (oldWindow) { m_x11Integration->setWindowProperty(oldWindow, s_x11AppMenuServiceNamePropertyName, {}); m_x11Integration->setWindowProperty(oldWindow, s_x11AppMenuObjectPathPropertyName, {}); } if (newWindow) { m_x11Integration->setWindowProperty(newWindow, s_x11AppMenuServiceNamePropertyName, serviceName.toUtf8()); m_x11Integration->setWindowProperty(newWindow, s_x11AppMenuObjectPathPropertyName, objectPath.toUtf8()); } } if (m_kwaylandIntegration) { if (oldWindow) { m_kwaylandIntegration->setAppMenu(QString(), QString()); } if (newWindow) { m_kwaylandIntegration->setAppMenu(serviceName, objectPath); } } }); return menu; } return nullptr; } -#endif //force QtQuickControls2 to use the desktop theme as default void KdePlatformTheme::setQtQuickControlsTheme() { //if the user is running only a QGuiApplication, explicitely unset the QQC1 desktop style and abort //as this style is all about QWidgets and we know setting this will make it crash if (!qobject_cast(qApp)) { if (qgetenv("QT_QUICK_CONTROLS_1_STYLE").right(7) == "Desktop") { qunsetenv("QT_QUICK_CONTROLS_1_STYLE"); } return; } //if the user has explicitly set something else, don't meddle if (!QQuickStyle::name().isEmpty()) { return; } QQuickStyle::setStyle(QLatin1String("org.kde.desktop")); } #include "kdeplatformtheme.moc" diff --git a/src/platformtheme/kdeplatformtheme.h b/src/platformtheme/kdeplatformtheme.h index 0318a44..ec82991 100644 --- a/src/platformtheme/kdeplatformtheme.h +++ b/src/platformtheme/kdeplatformtheme.h @@ -1,85 +1,76 @@ /* This file is part of the KDE libraries * Copyright 2013 Kevin Ottens * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License or ( at * your option ) version 3 or, at the discretion of KDE e.V. ( which shall * act as a proxy as in section 14 of the GPLv3 ), any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KDEPLATFORMTHEME_H #define KDEPLATFORMTHEME_H #include #include #include #include class KHintsSettings; class KFontSettingsData; class KWaylandIntegration; class X11Integration; class QIconEngine; class QWindow; class AltKeyEventListener; class KdePlatformTheme : public QPlatformTheme { public: KdePlatformTheme(); ~KdePlatformTheme(); QVariant themeHint(ThemeHint hint) const override; -#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0) QIcon fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions iconOptions) const override; -#else - QPixmap fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size, - QPlatformTheme::IconOptions iconOptions) const override; - // this will be the implementation - QIcon fileIcon(const QFileInfo &fileInfo, - QPlatformTheme::IconOptions iconOptions) const; -#endif + const QPalette *palette(Palette type = SystemPalette) const override; const QFont *font(Font type) const override; QIconEngine *createIconEngine(const QString &iconName) const override; QList keyBindings(QKeySequence::StandardKey key) const override; QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const override; bool usePlatformNativeDialog(DialogType type) const override; QString standardButtonText(int button) const override; QPlatformSystemTrayIcon *createPlatformSystemTrayIcon() const override; -#if QT_VERSION >= QT_VERSION_CHECK(5,7,0) QPlatformMenuBar *createPlatformMenuBar() const override; -#endif private: void loadSettings(); void setQtQuickControlsTheme(); static void setWindowProperty(QWindow *window, const QByteArray &name, const QByteArray &value); KHintsSettings *m_hints; KFontSettingsData *m_fontsData; QScopedPointer m_kwaylandIntegration; QScopedPointer m_x11Integration; }; #endif // KDEPLATFORMTHEME_H diff --git a/src/platformtheme/qdbusmenubar_p.h b/src/platformtheme/qdbusmenubar_p.h index 13343d1..6a5a379 100644 --- a/src/platformtheme/qdbusmenubar_p.h +++ b/src/platformtheme/qdbusmenubar_p.h @@ -1,110 +1,101 @@ /**************************************************************************** ** ** Copyright (C) 2016 Dmitry Shachnev ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QDBUSMENUBAR_P_H #define QDBUSMENUBAR_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include #include #include - -#if (QT_VERSION < QT_VERSION_CHECK(5, 8, 0)) -#include -#include -#include -#include -#else #include #include #include #include -#endif - QT_BEGIN_NAMESPACE class QDBusMenuBar : public QPlatformMenuBar { Q_OBJECT public: QDBusMenuBar(); virtual ~QDBusMenuBar(); void insertMenu(QPlatformMenu *menu, QPlatformMenu *before) override; void removeMenu(QPlatformMenu *menu) override; void syncMenu(QPlatformMenu *menu) override; void handleReparent(QWindow *newParentWindow) override; QPlatformMenu *menuForTag(quintptr tag) const override; QPlatformMenu *createMenu() const override; QWindow *window() const { return m_window; } QString objectPath() const { return m_objectPath; } Q_SIGNALS: void windowChanged(QWindow *newWindow, QWindow *oldWindow); private: QDBusPlatformMenu *m_menu; QDBusMenuAdaptor *m_menuAdaptor; QHash m_menuItems; QWindow *m_window = nullptr; QString m_objectPath; QDBusPlatformMenuItem *menuItemForMenu(QPlatformMenu *menu); static void updateMenuItem(QDBusPlatformMenuItem *item, QPlatformMenu *menu); void registerMenuBar(); void unregisterMenuBar(); }; QT_END_NAMESPACE #endif // QDBUSMENUBAR_P_H diff --git a/src/platformtheme/x11integration.cpp b/src/platformtheme/x11integration.cpp index ff79179..ec6d57a 100644 --- a/src/platformtheme/x11integration.cpp +++ b/src/platformtheme/x11integration.cpp @@ -1,150 +1,149 @@ /* This file is part of the KDE libraries * Copyright 2015 Martin Gräßlin * Copyright 2016 Marco Martin * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License or ( at * your option ) version 3 or, at the discretion of KDE e.V. ( which shall * act as a proxy as in section 14 of the GPLv3 ), any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "x11integration.h" #include #include #include #include #include #include #include #include static const char s_schemePropertyName[] = "KDE_COLOR_SCHEME_PATH"; static const QByteArray s_blurBehindPropertyName = QByteArrayLiteral("ENABLE_BLUR_BEHIND_HINT"); X11Integration::X11Integration() : QObject() { } X11Integration::~X11Integration() = default; void X11Integration::init() { QCoreApplication::instance()->installEventFilter(this); } bool X11Integration::eventFilter(QObject *watched, QEvent *event) { //the drag and drop window should NOT be a tooltip //https://bugreports.qt.io/browse/QTBUG-52560 if (event->type() == QEvent::Show && watched->inherits("QShapedPixmapWindow")) { //static cast should be safe there QWindow *w = static_cast(watched); NETWinInfo info(QX11Info::connection(), w->winId(), QX11Info::appRootWindow(), NET::WMWindowType, NET::Properties2()); info.setWindowType(NET::DNDIcon); // TODO: does this flash the xcb connection? } if (event->type() == QEvent::PlatformSurface) { if (QWindow *w = qobject_cast(watched)) { QPlatformSurfaceEvent *pe = static_cast(event); if (pe->surfaceEventType() == QPlatformSurfaceEvent::SurfaceCreated) { if (qApp->property(s_schemePropertyName).isValid()) { installColorScheme(w); } const auto blurBehindProperty = w->property(s_blurBehindPropertyName.constData()); if (blurBehindProperty.isValid()) { KWindowEffects::enableBlurBehind(w->winId(), blurBehindProperty.toBool()); } installDesktopFileName(w); } } } if (event->type() == QEvent::ApplicationPaletteChange) { const auto topLevelWindows = QGuiApplication::topLevelWindows(); for (QWindow *w : topLevelWindows) { installColorScheme(w); } } return false; } void X11Integration::installColorScheme(QWindow *w) { if (!w->isTopLevel()) { return; } static xcb_atom_t atom = XCB_ATOM_NONE; xcb_connection_t *c = QX11Info::connection(); if (atom == XCB_ATOM_NONE) { const QByteArray name = QByteArrayLiteral("_KDE_NET_WM_COLOR_SCHEME"); const xcb_intern_atom_cookie_t cookie = xcb_intern_atom(c, false, name.length(), name.constData()); QScopedPointer reply(xcb_intern_atom_reply(c, cookie, Q_NULLPTR)); if (!reply.isNull()) { atom = reply->atom; } else { // no point in continuing, we don't have the atom return; } } const QString path = qApp->property(s_schemePropertyName).toString(); if (path.isEmpty()) { xcb_delete_property(c, w->winId(), atom); } else { xcb_change_property(c, XCB_PROP_MODE_REPLACE, w->winId(), atom, XCB_ATOM_STRING, 8, path.size(), qPrintable(path)); } } void X11Integration::installDesktopFileName(QWindow *w) { if (!w->isTopLevel()) { return; } -#if (QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)) + if (QGuiApplication::desktopFileName().isEmpty()) { return; } NETWinInfo info(QX11Info::connection(), w->winId(), QX11Info::appRootWindow(), NET::Properties(), NET::Properties2()); info.setDesktopFileName(QGuiApplication::desktopFileName().toUtf8().constData()); -#endif } void X11Integration::setWindowProperty(QWindow *window, const QByteArray &name, const QByteArray &value) { auto *c = QX11Info::connection(); xcb_atom_t atom; auto it = m_atoms.find(name); if (it == m_atoms.end()) { const xcb_intern_atom_cookie_t cookie = xcb_intern_atom(c, false, name.length(), name.constData()); QScopedPointer reply(xcb_intern_atom_reply(c, cookie, Q_NULLPTR)); if (!reply.isNull()) { atom = reply->atom; m_atoms[name] = atom; } else { return; } } else { atom = *it; } if (value.isEmpty()) { xcb_delete_property(c, window->winId(), atom); } else { xcb_change_property(c, XCB_PROP_MODE_REPLACE, window->winId(), atom, XCB_ATOM_STRING, 8, value.length(), value.constData()); } } diff --git a/tests/qfiledialogtest.cpp b/tests/qfiledialogtest.cpp index a1884c5..ac1478d 100644 --- a/tests/qfiledialogtest.cpp +++ b/tests/qfiledialogtest.cpp @@ -1,140 +1,138 @@ /* This file is part of the KDE libraries * Copyright 2013 Aleix Pol Gonzalez * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License or ( at * your option ) version 3 or, at the discretion of KDE e.V. ( which shall * act as a proxy as in section 14 of the GPLv3 ), any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include #include #include #include int main(int argc, char **argv) { QApplication app(argc, argv); app.setApplicationName(QStringLiteral("QFileDialogTest")); QCommandLineParser parser; parser.addHelpOption(); parser.addOption(QCommandLineOption(QStringList(QStringLiteral("staticFunction")), QStringLiteral("Test one of the static convenience function: 'getOpenFileUrl', 'getExistingDirectory'"), QStringLiteral("function name"))); parser.addOption(QCommandLineOption(QStringList(QStringLiteral("acceptMode")), QStringLiteral("File dialog acceptMode: 'open' or 'save'"), QStringLiteral("type"), QStringLiteral("open"))); parser.addOption(QCommandLineOption(QStringList(QStringLiteral("confirmOverwrite")), QStringLiteral("Test overwrite option: 'on' or 'off'"), QStringLiteral("option"), QStringLiteral("on"))); parser.addOption(QCommandLineOption(QStringList(QStringLiteral("nativeDialog")), QStringLiteral("Use the platform native dialog: 'on' or 'off'"), QStringLiteral("option"), QStringLiteral("on"))); parser.addOption(QCommandLineOption(QStringList(QStringLiteral("fileMode")), QStringLiteral("File dialog fileMode: 'AnyFile' or 'ExistingFile' or 'Directory' or 'ExistingFiles'"), QStringLiteral("type"))); parser.addOption(QCommandLineOption(QStringList(QStringLiteral("nameFilter")), QStringLiteral("Dialog nameFilter, e. g. 'cppfiles (*.cpp *.h *.hpp)', can be specified multiple times"), QStringLiteral("nameFilter"), QStringLiteral("Everything (*)"))); parser.addOption(QCommandLineOption(QStringList(QStringLiteral("mimeTypeFilter")), QStringLiteral("Dialog mimeTypeFilter, e. g. 'application/json', can be specified multiple times"), QStringLiteral("mimeTypeFilter"))); parser.addOption(QCommandLineOption(QStringList(QStringLiteral("selectNameFilter")), QStringLiteral("Initially selected nameFilter"), QStringLiteral("selectNameFilter"))); parser.addOption(QCommandLineOption(QStringList(QStringLiteral("selectMimeTypeFilter")), QStringLiteral("Initially selected mimeTypeFilter"), QStringLiteral("selectMimeTypeFilter"))); parser.addOption(QCommandLineOption(QStringList(QStringLiteral("selectFile")), QStringLiteral("Initially selected file"), QStringLiteral("filename"))); parser.addOption(QCommandLineOption(QStringList(QStringLiteral("selectDirectory")), QStringLiteral("Initially selected directory"), QStringLiteral("dirname"))); parser.addOption(QCommandLineOption(QStringList(QStringLiteral("modal")), QStringLiteral("Test modal dialog"), QStringLiteral("modality"), QStringLiteral("on"))); parser.addOption(QCommandLineOption(QStringList(QStringLiteral("options")), QStringLiteral("See QFileDialog::Options"), QStringLiteral("option"))); parser.process(app); const QString staticFunction = parser.value(QStringLiteral("staticFunction")); if (staticFunction == QLatin1String("getExistingDirectory")) { QString dir = QFileDialog::getExistingDirectory(nullptr, QStringLiteral("getExistingDirectory test"), QStringLiteral("/tmp")); qDebug() << dir; return 0; } else if (staticFunction == QLatin1String("getOpenFileUrl")) { qDebug() << QFileDialog::getOpenFileUrl(Q_NULLPTR, QStringLiteral("getOpenFileUrl test"), QUrl::fromLocalFile(QDir::homePath())); return 0; } QFileDialog dialog; dialog.setAcceptMode( parser.value(QStringLiteral("acceptMode")) == QStringLiteral("open") ? QFileDialog::AcceptOpen : QFileDialog::AcceptSave); QString fileModeValue = parser.value(QStringLiteral("fileMode")); if (fileModeValue == QLatin1String("AnyFile")) { dialog.setFileMode(QFileDialog::AnyFile); } else if (fileModeValue == QLatin1String("ExistingFile")) { dialog.setFileMode(QFileDialog::ExistingFile); } else if (fileModeValue == QLatin1String("ExistingFiles")) { dialog.setFileMode(QFileDialog::ExistingFiles); } else if (fileModeValue == QLatin1String("Directory")) { dialog.setFileMode(QFileDialog::Directory); } else if (!fileModeValue.isEmpty()) { qDebug() << "Not implemented or not valid:" << fileModeValue ; exit(0); } QStringList nameFilterList = parser.values(QStringLiteral("nameFilter")); if (nameFilterList.size() == 1) { dialog.setNameFilter(nameFilterList.first()); } else { dialog.setNameFilters(nameFilterList); } if (parser.isSet(QLatin1String("options"))) { auto optStrings = parser.values(QLatin1String("options")); QFileDialog::Options options = 0; const auto mo = QFileDialog::staticMetaObject; const auto enumerator = mo.indexOfEnumerator("Options"); for(const auto &optString: optStrings) { options |= QFileDialog::Option(mo.enumerator(enumerator).keyToValue(optString.toLatin1().constData())); } dialog.setOptions(options); } const auto mimeFilterList = parser.values(QStringLiteral("mimeTypeFilter")); if (!mimeFilterList.isEmpty()) { dialog.setMimeTypeFilters(mimeFilterList); } QString selectNameFilter = parser.value(QStringLiteral("selectNameFilter")); QString selectMimeTypeFilter = parser.value(QStringLiteral("selectMimeTypeFilter")); if (!selectNameFilter.isEmpty()) { dialog.selectNameFilter(selectNameFilter); } else if (!selectMimeTypeFilter.isEmpty()) { dialog.selectMimeTypeFilter(selectMimeTypeFilter); } if (parser.value(QStringLiteral("confirmOverwrite")) == QStringLiteral("off")) { dialog.setOption(QFileDialog::DontConfirmOverwrite, true); } if (parser.value(QStringLiteral("nativeDialog")) == QStringLiteral("off")) { dialog.setOption(QFileDialog::DontUseNativeDialog, true); } dialog.setDirectoryUrl(QUrl::fromUserInput(parser.value(QStringLiteral("selectDirectory")), {}, QUrl::AssumeLocalFile)); dialog.selectFile(parser.value(QStringLiteral("selectFile"))); int ret; if (parser.value(QStringLiteral("modal")) == QStringLiteral("off")) { dialog.show(); ret = app.exec(); } else { ret = dialog.exec(); } if (dialog.result() == QDialog::Accepted) { qDebug() << "selected files" << dialog.selectedFiles(); qDebug() << "selected urls" << dialog.selectedUrls(); -#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) qDebug() << "selected mime type filter" << dialog.selectedMimeTypeFilter(); -#endif } qDebug() << "mime type filter(s):" << dialog.mimeTypeFilters(); return ret; }