From 783bb327cad3e8a5b3c395773c1d4dadf37ad685 Mon Sep 17 00:00:00 2001 From: renbin Date: Wed, 5 Jun 2024 16:31:12 +0800 Subject: [PATCH 1/3] chore: [debian/control] adapat to qt6 Adapt debian/control config based on qt6 Log: Adapt to qt6 --- CMakeLists.txt | 34 +++++++++++++++++++------- debian/control | 66 ++++++++++++++++++++++++++++++++------------------ 2 files changed, 68 insertions(+), 32 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e178034d57..8b7282f585 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,22 @@ if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "mips") add_definitions(-D ARCH_MIPSEL) endif() -find_package(Qt5 COMPONENTS Widgets REQUIRED) +#CMake module +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +include(install_plugin_quick_module) + +# Select major version. +find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core) +message("Using Qt version: ${QT_VERSION_MAJOR}") + +if(QT_VERSION_MAJOR EQUAL "6") + set(DFM_BUILD_WITH_QT6 ON) + set(DTK_VERSION_MAJOR 6) +else() + set(DTK_VERSION_MAJOR "") +endif() + +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets REQUIRED) find_package(DtkCMake REQUIRED) #if no debug, can't out in code define key '__FUNCTION__' and so on add_definitions(-DQT_MESSAGELOGCONTEXT) @@ -128,7 +143,8 @@ endif(NOT CMAKE_BUILD_TYPE) message("Build type:"${CMAKE_BUILD_TYPE}) if (${CMAKE_BUILD_TYPE} STREQUAL "Debug") - set(BUILD_TESTING ON) + # FIXME: QML refactor, disable test temporary. + set(BUILD_TESTING OFF) set(BUILD_DOCS Off) else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Ofast") @@ -139,13 +155,13 @@ else() endif() # sub directories -add_subdirectory(src/apps) -add_subdirectory(src/dfm-base) -add_subdirectory(src/dfm-extension) -add_subdirectory(src/dfm-framework) -add_subdirectory(src/plugins) -add_subdirectory(src/external) -add_subdirectory(src/tools) +# add_subdirectory(src/apps) +# add_subdirectory(src/dfm-base) +# add_subdirectory(src/dfm-extension) +# add_subdirectory(src/dfm-framework) +# add_subdirectory(src/plugins) +# add_subdirectory(src/external) +# add_subdirectory(src/tools) # docs if (BUILD_DOCS) diff --git a/debian/control b/debian/control index 713ccd31d3..519fd77a6d 100644 --- a/debian/control +++ b/debian/control @@ -7,39 +7,59 @@ Build-Depends: doxygen, debhelper (>=9), pkg-config, - qtbase5-dev, - qtbase5-private-dev, - qtmultimedia5-dev, +# Default Qt6 support + qt6-base-dev , + qt6-base-private-dev , + qt6-multimedia-dev , + qt6-tools-dev-tools , + qt6-tools-dev , + qt6-svg-dev , + libdtk6core-dev , + libdtk6core-bin , + libdtk6gui-dev , + libdtk6widget-dev , + libdtk6declarative-dev , + libdfm6-io-dev , + libdfm6-mount-dev , + libdfm6-burn-dev , +# disable for early develop +# libpolkit-qt6-1-dev , +# For Qt5 support, e.g.: dpkg-buildpackage -P pkg.dfm.qt5 ... + qtbase5-dev , + qtbase5-private-dev , + qtmultimedia5-dev , + qttools5-dev-tools , + qttools5-dev , + libqt5svg5-dev , + libqt5xdg-dev , + libdtkwidget-dev , + libdtkgui-dev , + libdtkcore-dev , + libdtkcore5-bin , + libdfm-io-dev , + libdfm-mount-dev , + libdfm-burn-dev , + libpolkit-qt5-1-dev , +# deprecated in qt6? + libkf5codecs-dev , + libgsettings-qt-dev , +# Another depends + libgio-qt-dev, + libdmr-dev, + libdframeworkdbus-dev, + libdeepin-pdfium-dev, + dde-dock-dev(>=4.8.4.1), libffmpegthumbnailer-dev, - libqt5svg5-dev, libpolkit-agent-1-dev, - libpolkit-qt5-1-dev, - libdtkwidget-dev, - libdtkgui-dev, - libdtkcore-dev, - libdtkcore5-bin, - qttools5-dev-tools, - qttools5-dev, - dde-dock-dev(>=4.8.4.1), - libdframeworkdbus-dev, libtag1-dev, - libdmr-dev, libicu-dev, - libdeepin-pdfium-dev, - libqt5xdg-dev, - libgio-qt-dev, - libdfm-io-dev, - libdfm-mount-dev, - libdfm-burn-dev, libssl-dev, libgtest-dev, libgmock-dev, - libgsettings-qt-dev, liblucene++-dev, libdocparser-dev, libboost-filesystem-dev, libsecret-1-dev, - libkf5codecs-dev, libpoppler-cpp-dev, libcryptsetup-dev, libpcre3-dev, @@ -67,7 +87,7 @@ Depends: ${misc:Depends}, libdde-file-manager, libgio-qt, - libqt5xdg3, + libqt5xdg3 , socat, cryfs, libblockdev-crypto2, From 11bf2f68bda16ebadc0b51d79aa92acc712acb30 Mon Sep 17 00:00:00 2001 From: liuyangming Date: Tue, 11 Jun 2024 17:12:02 +0800 Subject: [PATCH 2/3] feat: [base] dfm-base adapt to qt6. dfm-base adapt to qt6. Log: dfm-base adapt to qt6. --- CMakeLists.txt | 2 +- .../interfaces/abstractentryfileentity.h | 2 + install_dconfig.cmake | 2 +- src/dfm-base/CMakeLists.txt | 46 +- src/dfm-base/base/device/devicemanager.cpp | 2 +- .../base/device/private/devicewatcher.cpp | 2 +- .../dialogs/basedialog/basedialog.cpp | 1 - .../controls/checkboxwithmessage.cpp | 2 +- .../dialogs/settingsdialog/settingdialog.cpp | 2 +- .../dialogs/taskdialog/taskdialog.cpp | 7 +- .../dialogs/taskdialog/taskwidget.cpp | 12 +- src/dfm-base/dialogs/taskdialog/taskwidget.h | 2 +- src/dfm-base/file/local/localdiriterator.cpp | 2 +- src/dfm-base/file/local/localfilehandler.cpp | 8 +- src/dfm-base/mimedata/dfmmimedata.cpp | 6 +- src/dfm-base/mimedata/private/dfmmimedata_p.h | 2 +- src/dfm-base/mimetype/dmimedatabase.cpp | 6 +- src/dfm-base/mimetype/mimesappsmanager.cpp | 4 +- src/dfm-base/utils/clipboard.cpp | 10 +- src/dfm-base/utils/desktopfile.cpp | 1 + src/dfm-base/utils/filestatisticsjob.cpp | 2 +- src/dfm-base/utils/fileutils.cpp | 547 +++++++++--------- src/dfm-base/utils/fileutils.h | 2 +- src/dfm-base/utils/hidefilehelper.cpp | 7 +- src/dfm-base/utils/private/infocache_p.h | 2 +- src/dfm-base/utils/sysinfoutils.cpp | 2 +- .../utils/thumbnail/thumbnailcreators.cpp | 4 +- .../utils/thumbnail/thumbnailworker.cpp | 2 +- src/dfm-base/utils/universalutils.cpp | 1 - .../dfmkeyvaluelabel/keyvaluelabel.cpp | 2 +- src/dfm-base/widgets/dfmsplitter/splitter.cpp | 2 +- src/dfm-base/widgets/dfmsplitter/splitter.h | 2 +- .../dfmstatusbar/private/basicstatusbar_p.cpp | 2 +- .../dfmwindow/filemanagerwindowsmanager.cpp | 4 +- 34 files changed, 354 insertions(+), 348 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8b7282f585..517be9db0a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -156,7 +156,7 @@ endif() # sub directories # add_subdirectory(src/apps) -# add_subdirectory(src/dfm-base) +add_subdirectory(src/dfm-base) # add_subdirectory(src/dfm-extension) # add_subdirectory(src/dfm-framework) # add_subdirectory(src/plugins) diff --git a/include/dfm-base/interfaces/abstractentryfileentity.h b/include/dfm-base/interfaces/abstractentryfileentity.h index aa05c52d47..4025a0e9fd 100644 --- a/include/dfm-base/interfaces/abstractentryfileentity.h +++ b/include/dfm-base/interfaces/abstractentryfileentity.h @@ -10,6 +10,8 @@ #include #include #include +#include +#include namespace dfmbase { diff --git a/install_dconfig.cmake b/install_dconfig.cmake index 274768450f..4fbc75c9ae 100644 --- a/install_dconfig.cmake +++ b/install_dconfig.cmake @@ -10,7 +10,7 @@ function(INSTALL_DCONFIG CONFIG_NAME) message("---- AppId: ${DFMAppId}") message("---- Base: ${DConfigPath}") message("---- Files: ${DConfigPath}/${ConfigName}") - dconfig_meta_files(APPID ${DFMAppId} + dtk_add_config_meta_files(APPID ${DFMAppId} BASE ${DConfigPath} FILES ${DConfigPath}/${ConfigName}) else() diff --git a/src/dfm-base/CMakeLists.txt b/src/dfm-base/CMakeLists.txt index 0ad0a9c06c..5c9fac7f2a 100644 --- a/src/dfm-base/CMakeLists.txt +++ b/src/dfm-base/CMakeLists.txt @@ -26,7 +26,7 @@ set(QRC_FILES qrc/resources/resources.qrc qrc/chinese2pinyin/chinese2pinyin.qrc ) -qt5_add_resources(QRC_RESOURCES ${QRC_FILES}) +qt_add_resources(QRC_RESOURCES ${QRC_FILES}) # add code file(GLOB_RECURSE INCLUDE_FILES CONFIGURE_DEPENDS "${PROJECT_SOURCE_DIR}/include/${BIN_NAME}/*") @@ -37,30 +37,30 @@ file(GLOB_RECURSE SRCS CONFIGURE_DEPENDS ) # add depends -find_package(Qt5 COMPONENTS Core REQUIRED) -find_package(Qt5 COMPONENTS Widgets REQUIRED) -find_package(Qt5 COMPONENTS Concurrent REQUIRED) -find_package(Qt5 COMPONENTS DBus REQUIRED) -find_package(Qt5 COMPONENTS Sql REQUIRED) -find_package(Qt5 COMPONENTS X11Extras REQUIRED) -find_package(Qt5 COMPONENTS Network REQUIRED) -find_package(Dtk COMPONENTS Widget REQUIRED) +find_package(Qt6 COMPONENTS Core REQUIRED) +find_package(Qt6 COMPONENTS Widgets REQUIRED) +find_package(Qt6 COMPONENTS Concurrent REQUIRED) +find_package(Qt6 COMPONENTS DBus REQUIRED) +find_package(Qt6 COMPONENTS Sql REQUIRED) +find_package(Qt6 COMPONENTS Network REQUIRED) +find_package(Dtk6 COMPONENTS Core Widget REQUIRED) find_package(PkgConfig REQUIRED) -find_package(KF5Codecs REQUIRED) + +message("Current Qt Version ${QT_VERSION}") pkg_search_module(dfm-burn REQUIRED dfm-burn IMPORTED_TARGET) pkg_search_module(dfm-io REQUIRED dfm-io IMPORTED_TARGET) pkg_search_module(dfm-mount REQUIRED dfm-mount IMPORTED_TARGET) pkg_search_module(gsettings REQUIRED gsettings-qt IMPORTED_TARGET) pkg_check_modules(mount REQUIRED mount IMPORTED_TARGET) -pkg_search_module(Dtk REQUIRED dtkcore IMPORTED_TARGET) -pkg_search_module(X11 REQUIRED x11 IMPORTED_TARGET) +pkg_search_module(Dtk6Core REQUIRED dtk6core IMPORTED_TARGET) # generate dbus interface -qt5_add_dbus_interface(SRCS +qt_add_dbus_interface(SRCS ${DFM_DBUS_XML_DIR}/org.deepin.filemanager.server.DeviceManager.xml devicemanager_interface) + # for generating middle source files of SettingsTemplate to translate. set(TRANS_OF_SETTINGS_CPP) set (DTK_SETTINGS_TOOLS_EXECUTABLE ${DTKCORE_TOOL_DIR}/dtk-settings) @@ -98,28 +98,26 @@ add_library(${BIN_NAME} ) target_link_libraries(${BIN_NAME} PUBLIC - Qt5::Core - Qt5::Widgets - Qt5::Concurrent - Qt5::DBus - Qt5::Sql - Qt5::X11Extras - Qt5::Network + Qt6::Core + Qt6::Widgets + Qt6::Concurrent + Qt6::DBus + Qt6::Sql + Qt6::Network PkgConfig::dfm-burn PkgConfig::dfm-mount PkgConfig::dfm-io PkgConfig::gsettings PkgConfig::mount - PkgConfig::X11 poppler-cpp - KF5::Codecs - ${DtkWidget_LIBRARIES} + Dtk6::Core + Dtk6::Widget ) target_include_directories(${BIN_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/.. - ${Qt5Widgets_PRIVATE_INCLUDE_DIRS} + ${Qt6Widgets_PRIVATE_INCLUDE_DIRS} ) set(ShareDir ${CMAKE_INSTALL_PREFIX}/share/dde-file-manager) # also use for install diff --git a/src/dfm-base/base/device/devicemanager.cpp b/src/dfm-base/base/device/devicemanager.cpp index c3d22af8f3..ead6775bc4 100644 --- a/src/dfm-base/base/device/devicemanager.cpp +++ b/src/dfm-base/base/device/devicemanager.cpp @@ -197,7 +197,7 @@ void DeviceManager::mountBlockDevAsync(const QString &id, const QVariantMap &opt delete fw; }); d->isMountingOptical = true; - fw->setFuture(QtConcurrent::run(d->watcher, &DeviceWatcher::queryOpticalDevUsage, id)); + fw->setFuture(QtConcurrent::run(&DeviceWatcher::queryOpticalDevUsage, d->watcher, id)); } else { QString errMsg; if (DeviceHelper::isMountableBlockDev(dev, errMsg)) { diff --git a/src/dfm-base/base/device/private/devicewatcher.cpp b/src/dfm-base/base/device/private/devicewatcher.cpp index 7b88624f03..4090dc3d57 100644 --- a/src/dfm-base/base/device/private/devicewatcher.cpp +++ b/src/dfm-base/base/device/private/devicewatcher.cpp @@ -312,7 +312,7 @@ void DeviceWatcher::onBlkDevMounted(const QString &id, const QString &mpt) { const QVariantMap &info = d->allBlockInfos.value(id); // query info async avoid blocking main thread when disks' IO load is too high. - QtConcurrent::run(d.data(), &DeviceWatcherPrivate::queryUsageOfItem, info, DFMMOUNT::DeviceType::kBlockDevice); + QtConcurrent::run(&DeviceWatcherPrivate::queryUsageOfItem, d.data(), info, DFMMOUNT::DeviceType::kBlockDevice); emit DevMngIns->blockDevMounted(id, mpt); } diff --git a/src/dfm-base/dialogs/basedialog/basedialog.cpp b/src/dfm-base/dialogs/basedialog/basedialog.cpp index 57399323eb..cc0ad22e90 100644 --- a/src/dfm-base/dialogs/basedialog/basedialog.cpp +++ b/src/dfm-base/dialogs/basedialog/basedialog.cpp @@ -9,7 +9,6 @@ #include #include -#include #include #include #include diff --git a/src/dfm-base/dialogs/settingsdialog/controls/checkboxwithmessage.cpp b/src/dfm-base/dialogs/settingsdialog/controls/checkboxwithmessage.cpp index 76a22aeabd..088281446f 100644 --- a/src/dfm-base/dialogs/settingsdialog/controls/checkboxwithmessage.cpp +++ b/src/dfm-base/dialogs/settingsdialog/controls/checkboxwithmessage.cpp @@ -15,7 +15,7 @@ CheckBoxWithMessage::CheckBoxWithMessage(QWidget *parent) auto widget = new QWidget(this); widget->setContentsMargins(0, 0, 0, 0); QVBoxLayout *layout = new QVBoxLayout(widget); - layout->setMargin(0); + layout->setContentsMargins(0, 0, 0, 0); setLayout(layout); checkBox = new QCheckBox(widget); diff --git a/src/dfm-base/dialogs/settingsdialog/settingdialog.cpp b/src/dfm-base/dialogs/settingsdialog/settingdialog.cpp index fd9800ddb0..2c199b9f3d 100644 --- a/src/dfm-base/dialogs/settingsdialog/settingdialog.cpp +++ b/src/dfm-base/dialogs/settingsdialog/settingdialog.cpp @@ -285,7 +285,7 @@ QPair SettingDialog::createPushButton(QObject *opt) auto rightWidget = new QWidget; rightWidget->setContentsMargins(0, 0, 0, 0); QHBoxLayout *layout = new QHBoxLayout(rightWidget); - layout->setMargin(0); + layout->setContentsMargins(0, 0, 0, 0); rightWidget->setLayout(layout); layout->addStretch(0); diff --git a/src/dfm-base/dialogs/taskdialog/taskdialog.cpp b/src/dfm-base/dialogs/taskdialog/taskdialog.cpp index 6f00e34ee4..aec0110a7d 100644 --- a/src/dfm-base/dialogs/taskdialog/taskdialog.cpp +++ b/src/dfm-base/dialogs/taskdialog/taskdialog.cpp @@ -10,7 +10,8 @@ #include #include #include -#include +#include +// #include #include #include @@ -166,7 +167,7 @@ void TaskDialog::adjustSize(int hight) listHeight += h; } - if (listHeight < qApp->desktop()->availableGeometry().height() - 60) { + if (listHeight < qApp->primaryScreen()->availableGeometry().height() - 60) { taskListWidget->setFixedHeight(listHeight); setFixedHeight(listHeight + 60); kMaxHeight = height(); @@ -186,7 +187,7 @@ void TaskDialog::moveYCenter() if (parent()) { cp = static_cast(parent())->geometry().center(); } else { - cp = qApp->desktop()->availableGeometry().center(); + cp = qApp->primaryScreen()->availableGeometry().center(); } qr.moveCenter(cp); move(x(), qr.y()); diff --git a/src/dfm-base/dialogs/taskdialog/taskwidget.cpp b/src/dfm-base/dialogs/taskdialog/taskwidget.cpp index db21dd1263..d28819b4b7 100644 --- a/src/dfm-base/dialogs/taskdialog/taskwidget.cpp +++ b/src/dfm-base/dialogs/taskdialog/taskwidget.cpp @@ -124,7 +124,7 @@ void TaskWidget::onButtonClicked() infoTimer.stop(); if (btnPause) btnPause->setEnabled(true); - isShowError.store(false); + isShowError.storeRelaxed(false); AbstractJobHandler::SupportActions actions = obj->property(kBtnPropertyActionName).value(); showConflictButtons(actions.testFlag(AbstractJobHandler::SupportAction::kPauseAction)); actions = chkboxNotAskAgain && chkboxNotAskAgain->isChecked() ? actions | AbstractJobHandler::SupportAction::kRememberAction : actions; @@ -143,7 +143,7 @@ void TaskWidget::parentClose() */ void TaskWidget::onShowErrors(const JobInfoPointer jobInfo) { - isShowError.store(true); + isShowError.storeRelaxed(true); AbstractJobHandler::JobErrorType errorType = jobInfo->value(AbstractJobHandler::NotifyInfoKey::kErrorTypeKey).value(); QString sourceMsg = jobInfo->value(AbstractJobHandler::NotifyInfoKey::kSourceMsgKey).toString(); @@ -311,7 +311,7 @@ void TaskWidget::onShowTaskProccess(const JobInfoPointer JobInfo) { if (isPauseState) return; - if (isShowError.load()) + if (isShowError.loadRelaxed()) return; int preValue = progress->value(); @@ -361,7 +361,7 @@ void TaskWidget::onShowSpeedUpdatedInfo(const JobInfoPointer JobInfo) { if (isPauseState) return; - if (isShowError.load()) + if (isShowError.loadRelaxed()) return; if (progress->value() >= 100) { @@ -797,7 +797,7 @@ bool TaskWidget::showFileInfo(const FileInfoPointer info, const bool isOrg) return needRetry; } -void TaskWidget::enterEvent(QEvent *event) +void TaskWidget::enterEvent(QEnterEvent *event) { onMouseHover(true); @@ -808,7 +808,7 @@ void TaskWidget::leaveEvent(QEvent *event) { onMouseHover(false); - return QWidget::enterEvent(event); + return QWidget::leaveEvent(event); } void TaskWidget::paintEvent(QPaintEvent *event) diff --git a/src/dfm-base/dialogs/taskdialog/taskwidget.h b/src/dfm-base/dialogs/taskdialog/taskwidget.h index bd70c1226c..411253b856 100644 --- a/src/dfm-base/dialogs/taskdialog/taskwidget.h +++ b/src/dfm-base/dialogs/taskdialog/taskwidget.h @@ -67,7 +67,7 @@ private Q_SLOTS: bool showFileInfo(const FileInfoPointer info, const bool isOrg); protected: - virtual void enterEvent(QEvent *event); + virtual void enterEvent(QEnterEvent *event); virtual void leaveEvent(QEvent *event); virtual void paintEvent(QPaintEvent *event); diff --git a/src/dfm-base/file/local/localdiriterator.cpp b/src/dfm-base/file/local/localdiriterator.cpp index 86794fefa1..5dedc24c2d 100644 --- a/src/dfm-base/file/local/localdiriterator.cpp +++ b/src/dfm-base/file/local/localdiriterator.cpp @@ -156,7 +156,7 @@ QString LocalDirIterator::fileName() const if (path.isEmpty()) return QString(); - path = path.replace(QRegExp("/*/"), "/"); + path = path.replace(QRegularExpression("/*/"), "/"); if (path == "/") return QString(); diff --git a/src/dfm-base/file/local/localfilehandler.cpp b/src/dfm-base/file/local/localfilehandler.cpp index 06ea28ddfa..2b06d011ed 100644 --- a/src/dfm-base/file/local/localfilehandler.cpp +++ b/src/dfm-base/file/local/localfilehandler.cpp @@ -35,7 +35,7 @@ #include #include #include -#include +// #include #include #include @@ -632,7 +632,7 @@ bool LocalFileHandler::deleteFileRecursive(const QUrl &url) bool LocalFileHandler::setFileTime(const QUrl &url, const QDateTime &accessDateTime, const QDateTime &lastModifiedTime) { - utimbuf buf = { accessDateTime.toTime_t(), lastModifiedTime.toTime_t() }; + utimbuf buf = { accessDateTime.toSecsSinceEpoch(), lastModifiedTime.toSecsSinceEpoch() }; if (::utime(url.toLocalFile().toLocal8Bit(), &buf) == 0) { return true; @@ -1090,9 +1090,9 @@ bool LocalFileHandlerPrivate::doOpenFiles(const QList &urls, const QString bool openResult = doOpenFiles(openInfos, openMineTypes); - bool openMount = doOpenFiles(mountOpenInfos, openMineTypes); + bool openMount = doOpenFiles(mountOpenInfos, mountMineTypes); - bool openCmd = doOpenFiles(cmdOpenInfos, cmdOpenInfos); + bool openCmd = doOpenFiles(cmdOpenInfos, cmdMineTypes); if (openResult || openMount || openCmd) return true; diff --git a/src/dfm-base/mimedata/dfmmimedata.cpp b/src/dfm-base/mimedata/dfmmimedata.cpp index 6b04b036de..43ff68538a 100644 --- a/src/dfm-base/mimedata/dfmmimedata.cpp +++ b/src/dfm-base/mimedata/dfmmimedata.cpp @@ -112,12 +112,12 @@ QByteArray DFMMimeData::toByteArray() if (d->urlList.isEmpty()) return {}; - QVariantMap data; + QMultiMap data; data.insert(kVersionKey, d->version); data.insert(kUrlsKey, QUrl::toStringList(d->urlList)); data.unite(d->attributes); - QJsonDocument doc = QJsonDocument::fromVariant(data); + QJsonDocument doc = QJsonDocument::fromVariant(QVariant::fromValue(data)); return doc.toJson(); } @@ -160,7 +160,7 @@ DFMMimeData DFMMimeData::fromByteArray(const QByteArray &data) mimeData.d->version = version; mimeData.d->urlList = QUrl::fromStringList(map.take(kUrlsKey).toStringList()); - mimeData.d->attributes = map; + mimeData.d->attributes = QMultiMap(map); return mimeData; } diff --git a/src/dfm-base/mimedata/private/dfmmimedata_p.h b/src/dfm-base/mimedata/private/dfmmimedata_p.h index 33159f96a6..bac5f78653 100644 --- a/src/dfm-base/mimedata/private/dfmmimedata_p.h +++ b/src/dfm-base/mimedata/private/dfmmimedata_p.h @@ -22,7 +22,7 @@ class DFMMimeDataPrivate : public QSharedData void parseUrls(const QList &urls); public: - QVariantMap attributes; + QMultiMap attributes; QString version; QList urlList; diff --git a/src/dfm-base/mimetype/dmimedatabase.cpp b/src/dfm-base/mimetype/dmimedatabase.cpp index 761c1a59ea..4642bdbfd6 100644 --- a/src/dfm-base/mimetype/dmimedatabase.cpp +++ b/src/dfm-base/mimetype/dmimedatabase.cpp @@ -48,8 +48,7 @@ QMimeType DMimeDatabase::mimeTypeForFile(const FileInfoPointer &fileInfo, QMimeD || fileInfo->nameOf(NameInfoType::kFileName).endsWith(".lock") || fileInfo->nameOf(NameInfoType::kFileName).endsWith("lockfile")) { QRegularExpression regExp("^/run/user/\\d+/gvfs/(?\\w+(-?)\\w+):\\S*", QRegularExpression::DotMatchesEverythingOption - | QRegularExpression::DontCaptureOption - | QRegularExpression::OptimizeOnFirstUsageOption); + | QRegularExpression::DontCaptureOption); const QRegularExpressionMatch &match = regExp.match(path, 0, QRegularExpression::NormalMatch, QRegularExpression::DontCheckSubjectStringMatchOption); @@ -118,8 +117,7 @@ QMimeType DMimeDatabase::mimeTypeForFile(const QFileInfo &fileInfo, QMimeDatabas || fileInfo.fileName().endsWith(".lock") || fileInfo.fileName().endsWith("lockfile")) { QRegularExpression regExp("^/run/user/\\d+/gvfs/(?\\w+(-?)\\w+):\\S*", QRegularExpression::DotMatchesEverythingOption - | QRegularExpression::DontCaptureOption - | QRegularExpression::OptimizeOnFirstUsageOption); + | QRegularExpression::DontCaptureOption); const QRegularExpressionMatch &match = regExp.match(path, 0, QRegularExpression::NormalMatch, QRegularExpression::DontCheckSubjectStringMatchOption); diff --git a/src/dfm-base/mimetype/mimesappsmanager.cpp b/src/dfm-base/mimetype/mimesappsmanager.cpp index cf98c79624..f9acb7d3c1 100644 --- a/src/dfm-base/mimetype/mimesappsmanager.cpp +++ b/src/dfm-base/mimetype/mimesappsmanager.cpp @@ -525,7 +525,7 @@ void MimesAppsManager::initMimeTypeApps() orderApps.append(info.absoluteFilePath()); } } else { - orderApps.append(apps.toList()); + orderApps.append(apps.values()); } MimeApps.insert(key, orderApps); } @@ -652,7 +652,7 @@ void MimesAppsManager::loadDDEMimeTypes() bool MimesAppsManager::lessByDateTime(const QFileInfo &f1, const QFileInfo &f2) { - return f1.created() < f2.created(); + return f1.birthTime() < f2.birthTime(); } bool MimesAppsManager::removeOneDupFromList(QStringList &list, const QString desktopFilePath) diff --git a/src/dfm-base/utils/clipboard.cpp b/src/dfm-base/utils/clipboard.cpp index 6f52760660..67b0287335 100644 --- a/src/dfm-base/utils/clipboard.cpp +++ b/src/dfm-base/utils/clipboard.cpp @@ -62,7 +62,7 @@ void onClipboardDataChanged() return; } QByteArray data = mimeData->data(kGnomeCopyKey); - data = data.replace(QString(kGnomeCopyKey) + "\n", ""); + data = data.replace(QString(kGnomeCopyKey).append("\n").toLatin1(), ""); if (data.startsWith("cut")) { clipboardAction = ClipBoard::kCutAction; @@ -119,7 +119,7 @@ void ClipBoard::setUrlsToClipboard(const QList &list, ClipBoard::Clipboard QString error; for (const QUrl &qurl : list) { ba.append("\n"); - ba.append(qurl.toString()); + ba.append(qurl.toString().toLatin1()); const QString &path = qurl.toLocalFile(); if (!path.isEmpty()) { @@ -170,7 +170,7 @@ void ClipBoard::setUrlsToClipboard(const QList &list, ClipBoard::Clipboard // 如果是剪切操作,则禁止跨用户的粘贴操作 if (ClipBoard::kCutAction == action) { QByteArray userId; - userId.append(QString::number(getuid())); + userId.append(QString::number(getuid()).toLatin1()); mimeData->setData(GlobalData::kUserIdKey, userId); } @@ -374,7 +374,7 @@ QList ClipBoard::getUrlsByX11() continue; QString path = url.path(); - path = path.replace(QRegExp("/*/"), "/"); + path = path.replace(QRegularExpression("/*/"), "/"); if (path.isEmpty() || path == "/") continue; QUrl temp = QUrl::fromLocalFile(path); @@ -413,7 +413,7 @@ QList ClipBoard::getUrlsByX11() continue; QString path = url.path(); - path = path.replace(QRegExp("/*/"), "/"); + path = path.replace(QRegularExpression("/*/"), "/"); if (path.isEmpty() || path == "/") continue; QUrl temp = QUrl::fromLocalFile(path); diff --git a/src/dfm-base/utils/desktopfile.cpp b/src/dfm-base/utils/desktopfile.cpp index 4b49de4cae..e711e5dc2a 100644 --- a/src/dfm-base/utils/desktopfile.cpp +++ b/src/dfm-base/utils/desktopfile.cpp @@ -8,6 +8,7 @@ #include #include #include +#include using namespace dfmbase; diff --git a/src/dfm-base/utils/filestatisticsjob.cpp b/src/dfm-base/utils/filestatisticsjob.cpp index 8e977a6683..8564c6f951 100644 --- a/src/dfm-base/utils/filestatisticsjob.cpp +++ b/src/dfm-base/utils/filestatisticsjob.cpp @@ -303,7 +303,7 @@ FileStatisticsJob::~FileStatisticsJob() FileStatisticsJob::State FileStatisticsJob::state() const { - return static_cast(d->state.load()); + return static_cast(d->state.loadRelaxed()); } FileStatisticsJob::FileHints FileStatisticsJob::fileHints() const diff --git a/src/dfm-base/utils/fileutils.cpp b/src/dfm-base/utils/fileutils.cpp index 1118167c24..7559320534 100644 --- a/src/dfm-base/utils/fileutils.cpp +++ b/src/dfm-base/utils/fileutils.cpp @@ -23,8 +23,8 @@ #include #include -#include -#include +// #include +// #include #include #include @@ -36,7 +36,7 @@ #include #include #include -#include +// #include #include #include #include @@ -65,14 +65,13 @@ namespace dfmbase { static constexpr char kDDETrashId[] { "dde-trash" }; static constexpr char kDDEComputerId[] { "dde-computer" }; static constexpr char kDDEHomeId[] { "dde-home" }; -static constexpr char kSharePixmapPath[] { "/usr/share/pixmaps" }; static constexpr char kFileAllTrash[] { "dfm.trash.allfiletotrash" }; const static int kDefaultMemoryPageSize = 4096; QMutex FileUtils::cacheCopyingMutex; QSet FileUtils::copyingUrl; -static float codecConfidenceForData(const QTextCodec *codec, const QByteArray &data, const QLocale::Country &country); +// static float codecConfidenceForData(const QTextCodec *codec, const QByteArray &data, const QLocale::Country &country); QString sizeString(const QString &str) { @@ -668,8 +667,9 @@ QString FileUtils::cutFileName(const QString &name, int maxLength, bool useCharC tmpName.clear(); int bytes = 0; - auto codec = QTextCodec::codecForLocale(); + auto encoder = QStringEncoder(QStringEncoder::System); + auto decoder = QStringDecoder(QStringEncoder::System); for (int i = 0; i < name.size(); ++i) { const QChar &ch = name.at(i); QByteArray data; @@ -683,15 +683,15 @@ QString FileUtils::cutFileName(const QString &name, int maxLength, bool useCharC if (!ch.isHighSurrogate() || !nextCh.isLowSurrogate()) break; - data = codec->fromUnicode(name.data() + i - 1, 2); + data = encoder.encode(QString(name.data() + i - 1, 2)); fullChar.setUnicode(name.data() + i - 1, 2); } else { - data = codec->fromUnicode(name.data() + i, 1); + data = encoder.encode(QString(name.data() + i, 1)); fullChar.setUnicode(name.data() + i, 1); } - if (codec->toUnicode(data) != fullChar) { - qCWarning(logDFMBase) << "Failed convert" << fullChar << "to" << codec->name() << "coding"; + if (decoder.decode(data) != fullChar) { + qCWarning(logDFMBase) << "Failed convert" << fullChar << "to" << data << "coding"; continue; } @@ -772,180 +772,185 @@ QString FileUtils::toUnicode(const QByteArray &data, const QString &fileName) if (data.isEmpty()) return QString(); - const QByteArray &encoding = detectCharset(data, fileName); +// const QByteArray &encoding = detectCharset(data, fileName); - if (QTextCodec *codec = QTextCodec::codecForName(encoding)) { - return codec->toUnicode(data); - } +// if (QTextCodec *codec = QTextCodec::codecForName(encoding)) { +// return codec->toUnicode(data); +// } + +// // auto decoder = QStringDecoder(QStringEncoder::System); +// // QString decoding = decoder.decode(encoding); +// // if (!decoding.isEmpty()) +// // return decoding; return QString::fromLocal8Bit(data); } -QByteArray FileUtils::detectCharset(const QByteArray &data, const QString &fileName) -{ - // Return local encoding if nothing in file. - if (data.isEmpty()) { - return QTextCodec::codecForLocale()->name(); - } - - if (QTextCodec *c = QTextCodec::codecForUtfText(data, nullptr)) { - return c->name(); - } - - DFMBASE_NAMESPACE::DMimeDatabase mimeDatabase; - const QMimeType &mimeType = fileName.isEmpty() ? mimeDatabase.mimeTypeForData(data) : mimeDatabase.mimeTypeForFileNameAndData(fileName, data); - const QString &mimetypeName = mimeType.name(); - KEncodingProber::ProberType proberType = KEncodingProber::Universal; - - if (mimetypeName == Global::Mime::kTypeAppXml - || mimetypeName == Global::Mime::kTypeTextHtml - || mimetypeName == Global::Mime::kTypeAppXhtmlXml) { - const QString &_data = QString::fromLatin1(data); - QRegularExpression pattern("<\\bmeta.+\\bcharset=(?'charset'\\S+?)\\s*['\"/>]"); - - pattern.setPatternOptions(QRegularExpression::DontCaptureOption | QRegularExpression::CaseInsensitiveOption); - const QString &charset = pattern.match(_data, 0, QRegularExpression::PartialPreferFirstMatch, - QRegularExpression::DontCheckSubjectStringMatchOption) - .captured("charset"); - - if (!charset.isEmpty()) { - return charset.toLatin1(); - } - - pattern.setPattern("<\\bmeta\\s+http-equiv=\"Content-Language\"\\s+content=\"(?'language'[a-zA-Z-]+)\""); - - const QString &language = pattern.match(_data, 0, QRegularExpression::PartialPreferFirstMatch, - QRegularExpression::DontCheckSubjectStringMatchOption) - .captured("language"); - - if (!language.isEmpty()) { - QLocale l(language); - - switch (l.script()) { - case QLocale::ArabicScript: - proberType = KEncodingProber::Arabic; - break; - case QLocale::SimplifiedChineseScript: - proberType = KEncodingProber::ChineseSimplified; - break; - case QLocale::TraditionalChineseScript: - proberType = KEncodingProber::ChineseTraditional; - break; - case QLocale::CyrillicScript: - proberType = KEncodingProber::Cyrillic; - break; - case QLocale::GreekScript: - proberType = KEncodingProber::Greek; - break; - case QLocale::HebrewScript: - proberType = KEncodingProber::Hebrew; - break; - case QLocale::JapaneseScript: - proberType = KEncodingProber::Japanese; - break; - case QLocale::KoreanScript: - proberType = KEncodingProber::Korean; - break; - case QLocale::ThaiScript: - proberType = KEncodingProber::Thai; - break; - default: - break; - } - } - } else if (mimetypeName == Global::Mime::kTypeTextXPython) { - QRegularExpression pattern("^#coding\\s*:\\s*(?'coding'\\S+)$"); - QTextStream stream(data); - - pattern.setPatternOptions(QRegularExpression::DontCaptureOption | QRegularExpression::CaseInsensitiveOption); - stream.setCodec("latin1"); - - while (!stream.atEnd()) { - const QString &_data = stream.readLine(); - const QString &coding = pattern.match(_data, 0).captured("coding"); - - if (!coding.isEmpty()) { - return coding.toLatin1(); - } - } - } - - // for CJK - const QList> fallbackList { - { KEncodingProber::ChineseSimplified, QLocale::China }, - { KEncodingProber::ChineseTraditional, QLocale::China }, - { KEncodingProber::Japanese, QLocale::Japan }, - { KEncodingProber::Korean, QLocale::NorthKorea }, - { KEncodingProber::Cyrillic, QLocale::Russia }, - { KEncodingProber::Greek, QLocale::Greece }, - { proberType, QLocale::system().country() } - }; - - KEncodingProber prober(proberType); - prober.feed(data); - float preConfidence = prober.confidence(); - QByteArray preEncoding = prober.encoding(); - - QTextCodec *defCodec = QTextCodec::codecForLocale(); - QByteArray encoding; - float confidence = 0; - - for (auto i : fallbackList) { - prober.setProberType(i.first); - prober.feed(data); - - float proberConfidence = prober.confidence(); - QByteArray proberEncoding = prober.encoding(); - - if (i.first != proberType && qFuzzyIsNull(proberConfidence)) { - proberConfidence = preConfidence; - proberEncoding = preEncoding; - } - - confidence: - if (QTextCodec *codec = QTextCodec::codecForName(proberEncoding)) { - if (defCodec == codec) - defCodec = nullptr; - - float c = codecConfidenceForData(codec, data, i.second); - - if (proberConfidence > 0.5) { - c = c / 2 + proberConfidence / 2; - } else { - c = c / 3 * 2 + proberConfidence / 3; - } - - if (c > confidence) { - confidence = c; - encoding = proberEncoding; - } - - if (i.first == KEncodingProber::ChineseTraditional && c < 0.5) { - // test Big5 - c = codecConfidenceForData(QTextCodec::codecForName("Big5"), data, i.second); - - if (c > 0.5 && c > confidence) { - confidence = c; - encoding = "Big5"; - } - } - } - - if (i.first != proberType) { - // 使用 proberType 类型探测出的结果再次做编码检查 - i.first = proberType; - proberConfidence = preConfidence; - proberEncoding = preEncoding; - goto confidence; - } - } - - if (defCodec && codecConfidenceForData(defCodec, data, QLocale::system().country()) > confidence) { - return defCodec->name(); - } - - return encoding; -} +// QByteArray FileUtils::detectCharset(const QByteArray &data, const QString &fileName) +// { +// // Return local encoding if nothing in file. +// if (data.isEmpty()) { +// return QTextCodec::codecForLocale()->name(); +// } + +// if (QTextCodec *c = QTextCodec::codecForUtfText(data, nullptr)) { +// return c->name(); +// } + +// DFMBASE_NAMESPACE::DMimeDatabase mimeDatabase; +// const QMimeType &mimeType = fileName.isEmpty() ? mimeDatabase.mimeTypeForData(data) : mimeDatabase.mimeTypeForFileNameAndData(fileName, data); +// const QString &mimetypeName = mimeType.name(); +// KEncodingProber::ProberType proberType = KEncodingProber::Universal; + +// if (mimetypeName == Global::Mime::kTypeAppXml +// || mimetypeName == Global::Mime::kTypeTextHtml +// || mimetypeName == Global::Mime::kTypeAppXhtmlXml) { +// const QString &_data = QString::fromLatin1(data); +// QRegularExpression pattern("<\\bmeta.+\\bcharset=(?'charset'\\S+?)\\s*['\"/>]"); + +// pattern.setPatternOptions(QRegularExpression::DontCaptureOption | QRegularExpression::CaseInsensitiveOption); +// const QString &charset = pattern.match(_data, 0, QRegularExpression::PartialPreferFirstMatch, +// QRegularExpression::DontCheckSubjectStringMatchOption) +// .captured("charset"); + +// if (!charset.isEmpty()) { +// return charset.toLatin1(); +// } + +// pattern.setPattern("<\\bmeta\\s+http-equiv=\"Content-Language\"\\s+content=\"(?'language'[a-zA-Z-]+)\""); + +// const QString &language = pattern.match(_data, 0, QRegularExpression::PartialPreferFirstMatch, +// QRegularExpression::DontCheckSubjectStringMatchOption) +// .captured("language"); + +// if (!language.isEmpty()) { +// QLocale l(language); + +// switch (l.script()) { +// case QLocale::ArabicScript: +// proberType = KEncodingProber::Arabic; +// break; +// case QLocale::SimplifiedChineseScript: +// proberType = KEncodingProber::ChineseSimplified; +// break; +// case QLocale::TraditionalChineseScript: +// proberType = KEncodingProber::ChineseTraditional; +// break; +// case QLocale::CyrillicScript: +// proberType = KEncodingProber::Cyrillic; +// break; +// case QLocale::GreekScript: +// proberType = KEncodingProber::Greek; +// break; +// case QLocale::HebrewScript: +// proberType = KEncodingProber::Hebrew; +// break; +// case QLocale::JapaneseScript: +// proberType = KEncodingProber::Japanese; +// break; +// case QLocale::KoreanScript: +// proberType = KEncodingProber::Korean; +// break; +// case QLocale::ThaiScript: +// proberType = KEncodingProber::Thai; +// break; +// default: +// break; +// } +// } +// } else if (mimetypeName == Global::Mime::kTypeTextXPython) { +// QRegularExpression pattern("^#coding\\s*:\\s*(?'coding'\\S+)$"); +// QTextStream stream(data); + +// pattern.setPatternOptions(QRegularExpression::DontCaptureOption | QRegularExpression::CaseInsensitiveOption); +// stream.setEncoding(QStringConverter::Latin1); + +// while (!stream.atEnd()) { +// const QString &_data = stream.readLine(); +// const QString &coding = pattern.match(_data, 0).captured("coding"); + +// if (!coding.isEmpty()) { +// return coding.toLatin1(); +// } +// } +// } + +// // for CJK +// const QList> fallbackList { +// { KEncodingProber::ChineseSimplified, QLocale::China }, +// { KEncodingProber::ChineseTraditional, QLocale::China }, +// { KEncodingProber::Japanese, QLocale::Japan }, +// { KEncodingProber::Korean, QLocale::NorthKorea }, +// { KEncodingProber::Cyrillic, QLocale::Russia }, +// { KEncodingProber::Greek, QLocale::Greece }, +// { proberType, QLocale::system().country() } +// }; + +// KEncodingProber prober(proberType); +// prober.feed(data); +// float preConfidence = prober.confidence(); +// QByteArray preEncoding = prober.encoding(); + +// QTextCodec *defCodec = QTextCodec::codecForLocale(); +// QByteArray encoding; +// float confidence = 0; + +// for (auto i : fallbackList) { +// prober.setProberType(i.first); +// prober.feed(data); + +// float proberConfidence = prober.confidence(); +// QByteArray proberEncoding = prober.encoding(); + +// if (i.first != proberType && qFuzzyIsNull(proberConfidence)) { +// proberConfidence = preConfidence; +// proberEncoding = preEncoding; +// } + +// confidence: +// if (QTextCodec *codec = QTextCodec::codecForName(proberEncoding)) { +// if (defCodec == codec) +// defCodec = nullptr; + +// float c = codecConfidenceForData(codec, data, i.second); + +// if (proberConfidence > 0.5) { +// c = c / 2 + proberConfidence / 2; +// } else { +// c = c / 3 * 2 + proberConfidence / 3; +// } + +// if (c > confidence) { +// confidence = c; +// encoding = proberEncoding; +// } + +// if (i.first == KEncodingProber::ChineseTraditional && c < 0.5) { +// // test Big5 +// c = codecConfidenceForData(QTextCodec::codecForName("Big5"), data, i.second); + +// if (c > 0.5 && c > confidence) { +// confidence = c; +// encoding = "Big5"; +// } +// } +// } + +// if (i.first != proberType) { +// // 使用 proberType 类型探测出的结果再次做编码检查 +// i.first = proberType; +// proberConfidence = preConfidence; +// proberEncoding = preEncoding; +// goto confidence; +// } +// } + +// if (defCodec && codecConfidenceForData(defCodec, data, QLocale::system().country()) > confidence) { +// return defCodec->name(); +// } + +// return encoding; +// } /*! * \brief FileUtils::getMemoryPageSize 获取当前內存页大小 @@ -1037,12 +1042,14 @@ class DCollator : public QCollator bool FileUtils::isNumOrChar(const QChar ch) { - return (ch >= 48 && ch <= 57) || (ch >= 65 && ch <= 90) || (ch >= 97 && ch <= 122); + auto chValue = ch.unicode(); + return (chValue >= 48 && chValue <= 57) || (chValue >= 65 && chValue <= 90) || (chValue >= 97 && chValue <= 122); } bool FileUtils::isNumber(const QChar ch) { - return (ch >= 48 && ch <= 57); + auto chValue = ch.unicode(); + return (chValue >= 48 && chValue <= 57); } bool FileUtils::isSymbol(const QChar ch) @@ -1353,95 +1360,95 @@ QUrl DesktopAppUrl::homeDesktopFileUrl() ///###: Do not modify it. ///###: it's auxiliary. -float codecConfidenceForData(const QTextCodec *codec, const QByteArray &data, const QLocale::Country &country) -{ - qreal hepCount = 0; - int nonBaseLatinCount = 0; - qreal unidentificationCount = 0; - int replacementCount = 0; - - QTextDecoder decoder(codec); - const QString &unicodeData = decoder.toUnicode(data); - - for (int i = 0; i < unicodeData.size(); ++i) { - const QChar &ch = unicodeData.at(i); - - if (ch.unicode() > 0x7f) - ++nonBaseLatinCount; - - switch (ch.script()) { - case QChar::Script_Hiragana: - case QChar::Script_Katakana: - hepCount += country == QLocale::Japan ? 1.2 : 0.5; - unidentificationCount += country == QLocale::Japan ? 0 : 0.3; - break; - case QChar::Script_Han: - hepCount += country == QLocale::China ? 1.2 : 0.5; - unidentificationCount += country == QLocale::China ? 0 : 0.3; - break; - case QChar::Script_Hangul: - hepCount += (country == QLocale::NorthKorea) || (country == QLocale::SouthKorea) ? 1.2 : 0.5; - unidentificationCount += (country == QLocale::NorthKorea) || (country == QLocale::SouthKorea) ? 0 : 0.3; - break; - case QChar::Script_Cyrillic: - hepCount += (country == QLocale::Russia) ? 1.2 : 0.5; - unidentificationCount += (country == QLocale::Russia) ? 0 : 0.3; - break; - case QChar::Script_Greek: - hepCount += (country == QLocale::Greece) ? 1.2 : 0.5; - unidentificationCount += (country == QLocale::Greece) ? 0 : 0.3; - break; - default: - // full-width character, emoji, 常用标点, 拉丁文补充1,天城文及其补充,CJK符号和标点符号(如:【】) - if ((ch.unicode() >= 0xff00 && ch <= 0xffef) - || (ch.unicode() >= 0x2600 && ch.unicode() <= 0x27ff) - || (ch.unicode() >= 0x2000 && ch.unicode() <= 0x206f) - || (ch.unicode() >= 0x80 && ch.unicode() <= 0xff) - || (ch.unicode() >= 0xa8e0 && ch.unicode() <= 0xa8ff) - || (ch.unicode() >= 0x0900 && ch.unicode() <= 0x097f) - || (ch.unicode() >= 0x3000 && ch.unicode() <= 0x303f)) { - ++hepCount; - } else if (ch.isSurrogate() && ch.isHighSurrogate()) { - ++i; - - if (i < unicodeData.size()) { - const QChar &next_ch = unicodeData.at(i); - - if (!next_ch.isLowSurrogate()) { - --i; - break; - } - - uint unicode = QChar::surrogateToUcs4(ch, next_ch); - - // emoji - if (unicode >= 0x1f000 && unicode <= 0x1f6ff) { - hepCount += 2; - } - } - } else if (ch.unicode() == QChar::ReplacementCharacter) { - ++replacementCount; - } else if (ch.unicode() > 0x7f) { - // 因为UTF-8编码的容错性很低,所以未识别的编码只需要判断是否为 QChar::ReplacementCharacter 就能排除 - if (codec->name() != "UTF-8") - ++unidentificationCount; - } - break; - } - } - - // blumia: not sure why original author assume non_base_latin_count must greater than zero... - if (nonBaseLatinCount == 0) { - return 1.0f; - } - - float c = static_cast(qreal(hepCount) / nonBaseLatinCount / 1.2); - - c -= static_cast(qreal(replacementCount) / nonBaseLatinCount); - c -= static_cast(qreal(unidentificationCount) / nonBaseLatinCount); - - return qMax(0.0f, c); -} +// float codecConfidenceForData(const QTextCodec *codec, const QByteArray &data, const QLocale::Country &country) +// { +// qreal hepCount = 0; +// int nonBaseLatinCount = 0; +// qreal unidentificationCount = 0; +// int replacementCount = 0; + +// QTextDecoder decoder(codec); +// const QString &unicodeData = decoder.toUnicode(data); + +// for (int i = 0; i < unicodeData.size(); ++i) { +// const QChar &ch = unicodeData.at(i); + +// if (ch.unicode() > 0x7f) +// ++nonBaseLatinCount; + +// switch (ch.script()) { +// case QChar::Script_Hiragana: +// case QChar::Script_Katakana: +// hepCount += country == QLocale::Japan ? 1.2 : 0.5; +// unidentificationCount += country == QLocale::Japan ? 0 : 0.3; +// break; +// case QChar::Script_Han: +// hepCount += country == QLocale::China ? 1.2 : 0.5; +// unidentificationCount += country == QLocale::China ? 0 : 0.3; +// break; +// case QChar::Script_Hangul: +// hepCount += (country == QLocale::NorthKorea) || (country == QLocale::SouthKorea) ? 1.2 : 0.5; +// unidentificationCount += (country == QLocale::NorthKorea) || (country == QLocale::SouthKorea) ? 0 : 0.3; +// break; +// case QChar::Script_Cyrillic: +// hepCount += (country == QLocale::Russia) ? 1.2 : 0.5; +// unidentificationCount += (country == QLocale::Russia) ? 0 : 0.3; +// break; +// case QChar::Script_Greek: +// hepCount += (country == QLocale::Greece) ? 1.2 : 0.5; +// unidentificationCount += (country == QLocale::Greece) ? 0 : 0.3; +// break; +// default: +// // full-width character, emoji, 常用标点, 拉丁文补充1,天城文及其补充,CJK符号和标点符号(如:【】) +// if ((ch.unicode() >= 0xff00 && ch.unicode() <= 0xffef) +// || (ch.unicode() >= 0x2600 && ch.unicode() <= 0x27ff) +// || (ch.unicode() >= 0x2000 && ch.unicode() <= 0x206f) +// || (ch.unicode() >= 0x80 && ch.unicode() <= 0xff) +// || (ch.unicode() >= 0xa8e0 && ch.unicode() <= 0xa8ff) +// || (ch.unicode() >= 0x0900 && ch.unicode() <= 0x097f) +// || (ch.unicode() >= 0x3000 && ch.unicode() <= 0x303f)) { +// ++hepCount; +// } else if (ch.isSurrogate() && ch.isHighSurrogate()) { +// ++i; + +// if (i < unicodeData.size()) { +// const QChar &next_ch = unicodeData.at(i); + +// if (!next_ch.isLowSurrogate()) { +// --i; +// break; +// } + +// uint unicode = QChar::surrogateToUcs4(ch, next_ch); + +// // emoji +// if (unicode >= 0x1f000 && unicode <= 0x1f6ff) { +// hepCount += 2; +// } +// } +// } else if (ch.unicode() == QChar::ReplacementCharacter) { +// ++replacementCount; +// } else if (ch.unicode() > 0x7f) { +// // 因为UTF-8编码的容错性很低,所以未识别的编码只需要判断是否为 QChar::ReplacementCharacter 就能排除 +// if (codec->name() != "UTF-8") +// ++unidentificationCount; +// } +// break; +// } +// } + +// // blumia: not sure why original author assume non_base_latin_count must greater than zero... +// if (nonBaseLatinCount == 0) { +// return 1.0f; +// } + +// float c = static_cast(qreal(hepCount) / nonBaseLatinCount / 1.2); + +// c -= static_cast(qreal(replacementCount) / nonBaseLatinCount); +// c -= static_cast(qreal(unidentificationCount) / nonBaseLatinCount); + +// return qMax(0.0f, c); +// } Match::Match(const QString &group) { diff --git a/src/dfm-base/utils/fileutils.h b/src/dfm-base/utils/fileutils.h index 18e87ea8ab..165e52701d 100644 --- a/src/dfm-base/utils/fileutils.h +++ b/src/dfm-base/utils/fileutils.h @@ -61,7 +61,7 @@ class FileUtils static QString cutFileName(const QString &name, int maxLength, bool useCharCount); static QString nonExistSymlinkFileName(const QUrl &fileUrl, const QUrl &parentUrl = QUrl()); static QString toUnicode(const QByteArray &data, const QString &fileName = QString()); - static QByteArray detectCharset(const QByteArray &data, const QString &fileName = QString {}); + // static QByteArray detectCharset(const QByteArray &data, const QString &fileName = QString {}); static quint16 getMemoryPageSize(); static qint32 getCpuProcessCount(); diff --git a/src/dfm-base/utils/hidefilehelper.cpp b/src/dfm-base/utils/hidefilehelper.cpp index cc79c6cbd4..db8815d257 100644 --- a/src/dfm-base/utils/hidefilehelper.cpp +++ b/src/dfm-base/utils/hidefilehelper.cpp @@ -42,7 +42,8 @@ class HideFileHelperPrivate if (dfile->open(DFMIO::DFile::OpenFlag::kReadOnly)) { const QByteArray &data = dfile->readAll(); const QString &dataStr = QString::fromLocal8Bit(data); - hideList = QSet::fromList(dataStr.split('\n', QString::SkipEmptyParts)); + const QStringList &splitList = dataStr.split('\n', Qt::SkipEmptyParts); + hideList = QSet(splitList.begin(), splitList.end()); hideListUpdate = hideList; dfile->close(); } @@ -103,10 +104,10 @@ bool HideFileHelper::save() const if (!d->dfile) return false; - QStringList lines(d->hideList.toList()); + QStringList lines(d->hideList.values()); QString dataStr = lines.join('\n'); QByteArray data; - data.append(dataStr); + data.append(dataStr.toLatin1()); if (d->dfile->open(DFMIO::DFile::OpenFlag::kWriteOnly | DFMIO::DFile::OpenFlag::kTruncate)) { d->dfile->write(data); diff --git a/src/dfm-base/utils/private/infocache_p.h b/src/dfm-base/utils/private/infocache_p.h index 11bd54d138..f76bcc3bd7 100644 --- a/src/dfm-base/utils/private/infocache_p.h +++ b/src/dfm-base/utils/private/infocache_p.h @@ -32,7 +32,7 @@ class InfoCachePrivate // 时间排序url,利用map的有序性,来处理时间到了要移除的url QMap urlTimeSortMap; - QMap timeToUrlMap; + QMultiMap timeToUrlMap; std::atomic_bool cacheWorkerStoped { false }; diff --git a/src/dfm-base/utils/sysinfoutils.cpp b/src/dfm-base/utils/sysinfoutils.cpp index 002267506e..e28d178924 100644 --- a/src/dfm-base/utils/sysinfoutils.cpp +++ b/src/dfm-base/utils/sysinfoutils.cpp @@ -111,7 +111,7 @@ void SysInfoUtils::setMimeDataUserId(QMimeData *data) { QByteArray userId; QString strUserID = QString::number(getUserId()); - userId.append(strUserID); + userId.append(strUserID.toLatin1()); data->setData(DFMGLOBAL_NAMESPACE::Mime::kDataUserIDKey, userId); QString strKey = QString(DFMGLOBAL_NAMESPACE::Mime::kDataUserIDKey) + "_" + strUserID; diff --git a/src/dfm-base/utils/thumbnail/thumbnailcreators.cpp b/src/dfm-base/utils/thumbnail/thumbnailcreators.cpp index 621d138c7a..5fdfa0ba8c 100644 --- a/src/dfm-base/utils/thumbnail/thumbnailcreators.cpp +++ b/src/dfm-base/utils/thumbnail/thumbnailcreators.cpp @@ -78,14 +78,14 @@ QImage ThumbnailCreators::videoThumbnailCreatorFfmpeg(const QString &filePath, T QString outputs(data); if (!img.loadFromData(data)) { // filter the outputs outputed by video tool. - QStringList data = outputs.split(QRegExp("[\n]"), QString::SkipEmptyParts); + QStringList data = outputs.split(QRegularExpression("[\n]"), Qt::SkipEmptyParts); if (data.isEmpty()) return img; outputs = data.last(); } - if (!img.loadFromData(outputs.toLocal8Bit().data(), "png")) + if (!img.loadFromData(outputs.toLocal8Bit(), "png")) qCWarning(logDFMBase) << "thumbnail: cannot load image from ffmpeg outputs." << filePath; return img; } diff --git a/src/dfm-base/utils/thumbnail/thumbnailworker.cpp b/src/dfm-base/utils/thumbnail/thumbnailworker.cpp index e82c56d2d0..57e6bfcc73 100644 --- a/src/dfm-base/utils/thumbnail/thumbnailworker.cpp +++ b/src/dfm-base/utils/thumbnail/thumbnailworker.cpp @@ -77,7 +77,7 @@ bool ThumbnailWorkerPrivate::checkFileStable(const QUrl &url) // 修改时间稳定 qint64 mtime = info->timeOf(TimeInfoType::kMetadataChangeTimeSecond).toLongLong(); - qint64 curTime = QDateTime::currentDateTime().toTime_t(); + qint64 curTime = QDateTime::currentDateTime().toSecsSinceEpoch(); qint64 diffTime = curTime - mtime; if (diffTime < 2 && diffTime >= 0) diff --git a/src/dfm-base/utils/universalutils.cpp b/src/dfm-base/utils/universalutils.cpp index b003879728..1f31d556c9 100644 --- a/src/dfm-base/utils/universalutils.cpp +++ b/src/dfm-base/utils/universalutils.cpp @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/src/dfm-base/widgets/dfmkeyvaluelabel/keyvaluelabel.cpp b/src/dfm-base/widgets/dfmkeyvaluelabel/keyvaluelabel.cpp index 9272175549..c8ec02f169 100644 --- a/src/dfm-base/widgets/dfmkeyvaluelabel/keyvaluelabel.cpp +++ b/src/dfm-base/widgets/dfmkeyvaluelabel/keyvaluelabel.cpp @@ -43,7 +43,7 @@ void KeyValueLabel::initUI() connect(rightValueEdit, &RightValueWidget::clicked, this, &KeyValueLabel::valueAreaClicked); rightValueEdit->setMinimumWidth(130); glayout = new QGridLayout; - glayout->setMargin(0); + glayout->setContentsMargins(0, 0, 0, 0); glayout->addWidget(leftValueLabel, 0, 0); glayout->addWidget(rightValueEdit, 0, 1); glayout->setColumnStretch(0, 1); diff --git a/src/dfm-base/widgets/dfmsplitter/splitter.cpp b/src/dfm-base/widgets/dfmsplitter/splitter.cpp index 811770c1c7..c5c9be58df 100644 --- a/src/dfm-base/widgets/dfmsplitter/splitter.cpp +++ b/src/dfm-base/widgets/dfmsplitter/splitter.cpp @@ -16,7 +16,7 @@ SplitterHandle::SplitterHandle(Qt::Orientation orientation, QSplitter *parent): } -void SplitterHandle::enterEvent(QEvent *) +void SplitterHandle::enterEvent(QEnterEvent *) { QGuiApplication::setOverrideCursor(orientation() == Qt::Horizontal ? Qt::SizeHorCursor : Qt::SizeVerCursor); } diff --git a/src/dfm-base/widgets/dfmsplitter/splitter.h b/src/dfm-base/widgets/dfmsplitter/splitter.h index f7c16a76b3..3ec7359722 100644 --- a/src/dfm-base/widgets/dfmsplitter/splitter.h +++ b/src/dfm-base/widgets/dfmsplitter/splitter.h @@ -18,7 +18,7 @@ class SplitterHandle: public QSplitterHandle explicit SplitterHandle(Qt::Orientation orientation, QSplitter* parent); protected: - void enterEvent(QEvent*) override; + void enterEvent(QEnterEvent *) override; void leaveEvent(QEvent*) override; }; diff --git a/src/dfm-base/widgets/dfmstatusbar/private/basicstatusbar_p.cpp b/src/dfm-base/widgets/dfmstatusbar/private/basicstatusbar_p.cpp index e50c12820d..795b4f125f 100644 --- a/src/dfm-base/widgets/dfmstatusbar/private/basicstatusbar_p.cpp +++ b/src/dfm-base/widgets/dfmstatusbar/private/basicstatusbar_p.cpp @@ -48,7 +48,7 @@ void BasicStatusBarPrivate::initLayout() q->setFixedHeight(30); q->setContentsMargins(0, 0, 0, 0); auto vLayout = new QVBoxLayout(q); - vLayout->setMargin(0); + vLayout->setContentsMargins(0, 0, 0, 0); vLayout->setSpacing(0); auto line = new DTK_WIDGET_NAMESPACE::DHorizontalLine(q); line->setContentsMargins(0, 0, 0, 0); diff --git a/src/dfm-base/widgets/dfmwindow/filemanagerwindowsmanager.cpp b/src/dfm-base/widgets/dfmwindow/filemanagerwindowsmanager.cpp index 559706d480..54843b3e43 100644 --- a/src/dfm-base/widgets/dfmwindow/filemanagerwindowsmanager.cpp +++ b/src/dfm-base/widgets/dfmwindow/filemanagerwindowsmanager.cpp @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -173,7 +172,8 @@ FileManagerWindowsManager::FMWindow *FileManagerWindowsManager::createWindow(con return window; } - QX11Info::setAppTime(QX11Info::appUserTime()); + //TODO: replace follow code. QX11Info removed in Qt6. + // QX11Info::setAppTime(QX11Info::appUserTime()); // you can inherit from FMWindow to implement a custom window (by call `setCustomWindowCreator`) FMWindow *window = d->customCreator ? d->customCreator(showedUrl) From 0b9ff1e332ae0bc0e68c63a71165cd8e5a61885a Mon Sep 17 00:00:00 2001 From: renbin Date: Wed, 5 Jun 2024 13:03:43 +0800 Subject: [PATCH 3/3] feat: [framework] init qt6 quick framework * Adapt framekwork with Qt6 quick; * Add dfm-gui library; * Adapt dfmplugin-core/dfmplugin-sidebar... * Block unused plugins. Log: Init Qt6 quick framework --- CMakeLists.txt | 19 +- assets/dev/dfm-gui/dfm-gui.pc.in | 7 + assets/dev/dfm-gui/dfm-guiConfig.cmake.in | 3 + cmake/install_plugin_quick_module.cmake | 16 + debian/control | 8 +- debian/rules | 6 +- examples/appletwindow/AppletItemEx.qml | 22 + examples/appletwindow/CMakeLists.txt | 22 + examples/appletwindow/Panel.qml | 61 +++ examples/appletwindow/main.cpp | 48 +++ include/dfm-base/base/schemefactory.h | 1 + include/dfm-framework/lifecycle/lifecycle.h | 1 + .../dfm-framework/lifecycle/pluginmanager.h | 1 + .../lifecycle/pluginmetaobject.h | 18 +- .../lifecycle/pluginquickmetadata.h | 71 ++++ include/dfm-gui/applet.h | 76 ++++ include/dfm-gui/appletfactory.h | 35 ++ include/dfm-gui/appletitem.h | 39 ++ include/dfm-gui/appletmanager.h | 54 +++ include/dfm-gui/containment.h | 51 +++ include/dfm-gui/containmentitem.h | 25 ++ include/dfm-gui/dfm_gui_global.h | 20 + include/dfm-gui/panel.h | 34 ++ include/dfm-gui/quickutils.h | 37 ++ include/dfm-gui/sharedqmlengine.h | 50 +++ include/dfm-gui/windowhandle.h | 42 ++ include/dfm-gui/windowmanager.h | 43 ++ src/apps/CMakeLists.txt | 12 +- src/apps/config.h.in | 6 + src/apps/dde-desktop/CMakeLists.txt | 8 +- src/apps/dde-file-manager/CMakeLists.txt | 14 +- src/apps/dde-file-manager/commandparser.cpp | 3 +- src/apps/dde-file-manager/main.cpp | 35 +- src/dfm-base/CMakeLists.txt | 11 +- .../base/configs/gsetting/gsettingmanager.cpp | 34 +- src/dfm-base/utils/loggerrules.cpp | 2 +- src/dfm-declarative/ActionMenu.qml | 8 + src/dfm-declarative/CMakeLists.txt | 53 +++ src/dfm-framework/CMakeLists.txt | 12 +- src/dfm-framework/event/eventdispatcher.cpp | 4 +- src/dfm-framework/lifecycle/lifecycle.cpp | 14 + src/dfm-framework/lifecycle/pluginmanager.cpp | 5 + .../lifecycle/pluginmetaobject.cpp | 25 ++ .../lifecycle/pluginquickmetadata.cpp | 108 +++++ .../lifecycle/private/pluginmanager_p.cpp | 45 ++ .../lifecycle/private/pluginmetaobject_p.h | 14 + .../lifecycle/private/pluginquickmetadata_p.h | 28 ++ src/dfm-gui/CMakeLists.txt | 124 ++++++ src/dfm-gui/applet.cpp | 158 +++++++ src/dfm-gui/applet_p.h | 38 ++ src/dfm-gui/appletfactory.cpp | 69 +++ src/dfm-gui/appletitem.cpp | 94 ++++ src/dfm-gui/appletitem_p.h | 26 ++ src/dfm-gui/appletmanager.cpp | 402 ++++++++++++++++++ src/dfm-gui/appletmanager_p.h | 49 +++ src/dfm-gui/attachedproperty.cpp | 68 +++ src/dfm-gui/attachedproperty_p.h | 41 ++ src/dfm-gui/containment.cpp | 150 +++++++ src/dfm-gui/containment_p.h | 25 ++ src/dfm-gui/containmentitem.cpp | 30 ++ src/dfm-gui/panel.cpp | 36 ++ src/dfm-gui/panel_p.h | 23 + src/dfm-gui/quickutils.cpp | 18 + src/dfm-gui/sharedqmlengine.cpp | 204 +++++++++ src/dfm-gui/sharedqmlengine_p.h | 41 ++ src/dfm-gui/windowhandle.cpp | 64 +++ src/dfm-gui/windowmanager.cpp | 196 +++++++++ src/dfm-gui/windowmanager_p.h | 31 ++ src/plugins/CMakeLists.txt | 10 +- .../dfmplugin-fileoperations/CMakeLists.txt | 1 + src/plugins/filemanager/CMakeLists.txt | 20 +- .../core/dfmplugin-core/CMakeLists.txt | 9 +- .../core/dfmplugin-core/FileWindow.qml | 90 ++++ .../filemanager/core/dfmplugin-core/core.json | 7 + .../core/dfmplugin-core/utils/corehelper.cpp | 16 +- .../core/dfmplugin-detailspace/CMakeLists.txt | 6 +- .../dfmplugin-detailspace/DetailSpace.qml | 30 ++ .../dfmplugin-detailspace/detailspace.json | 7 + .../views/detailspacewidget.cpp | 2 +- .../views/detailview.cpp | 2 +- .../views/filebaseinfoview.cpp | 6 +- .../core/dfmplugin-sidebar/CMakeLists.txt | 5 +- .../core/dfmplugin-sidebar/Sidebar.qml | 47 ++ .../core/dfmplugin-sidebar/sidebar.json | 7 + .../treeviews/sidebarwidget.cpp | 4 +- .../core/dfmplugin-titlebar/CMakeLists.txt | 7 +- .../core/dfmplugin-titlebar/LineSearch.qml | 16 + .../core/dfmplugin-titlebar/Titlebar.qml | 116 +++++ .../dfmplugin_titlebar_global.h | 2 +- .../dialogs/connecttoserverdialog.cpp | 9 + .../dialogs/connecttoserverdialog.h | 5 + .../dialogs/dpcwidget/dpcconfirmwidget.cpp | 10 + .../dialogs/dpcwidget/dpcprogresswidget.cpp | 4 + .../dialogs/dpcwidget/dpcresultwidget.cpp | 4 + .../core/dfmplugin-titlebar/titlebar.json | 7 + .../utils/searchhistroymanager.cpp | 2 +- .../utils/titlebarhelper.cpp | 8 +- .../dfmplugin-titlebar/views/addressbar.cpp | 14 +- .../dfmplugin-titlebar/views/addressbar.h | 2 +- .../dfmplugin-titlebar/views/crumbbar.cpp | 2 +- .../views/optionbuttonbox.cpp | 4 + .../views/private/addressbar_p.h | 5 + .../views/titlebarwidget.cpp | 4 + .../core/dfmplugin-workspace/CMakeLists.txt | 2 +- .../dfmplugin-workspace/utils/selecthelper.h | 2 +- 105 files changed, 3533 insertions(+), 99 deletions(-) create mode 100644 assets/dev/dfm-gui/dfm-gui.pc.in create mode 100644 assets/dev/dfm-gui/dfm-guiConfig.cmake.in create mode 100644 cmake/install_plugin_quick_module.cmake create mode 100644 examples/appletwindow/AppletItemEx.qml create mode 100644 examples/appletwindow/CMakeLists.txt create mode 100644 examples/appletwindow/Panel.qml create mode 100644 examples/appletwindow/main.cpp create mode 100644 include/dfm-framework/lifecycle/pluginquickmetadata.h create mode 100644 include/dfm-gui/applet.h create mode 100644 include/dfm-gui/appletfactory.h create mode 100644 include/dfm-gui/appletitem.h create mode 100644 include/dfm-gui/appletmanager.h create mode 100644 include/dfm-gui/containment.h create mode 100644 include/dfm-gui/containmentitem.h create mode 100644 include/dfm-gui/dfm_gui_global.h create mode 100644 include/dfm-gui/panel.h create mode 100644 include/dfm-gui/quickutils.h create mode 100644 include/dfm-gui/sharedqmlengine.h create mode 100644 include/dfm-gui/windowhandle.h create mode 100644 include/dfm-gui/windowmanager.h create mode 100644 src/dfm-declarative/ActionMenu.qml create mode 100644 src/dfm-declarative/CMakeLists.txt create mode 100644 src/dfm-framework/lifecycle/pluginquickmetadata.cpp create mode 100644 src/dfm-framework/lifecycle/private/pluginquickmetadata_p.h create mode 100644 src/dfm-gui/CMakeLists.txt create mode 100644 src/dfm-gui/applet.cpp create mode 100644 src/dfm-gui/applet_p.h create mode 100644 src/dfm-gui/appletfactory.cpp create mode 100644 src/dfm-gui/appletitem.cpp create mode 100644 src/dfm-gui/appletitem_p.h create mode 100644 src/dfm-gui/appletmanager.cpp create mode 100644 src/dfm-gui/appletmanager_p.h create mode 100644 src/dfm-gui/attachedproperty.cpp create mode 100644 src/dfm-gui/attachedproperty_p.h create mode 100644 src/dfm-gui/containment.cpp create mode 100644 src/dfm-gui/containment_p.h create mode 100644 src/dfm-gui/containmentitem.cpp create mode 100644 src/dfm-gui/panel.cpp create mode 100644 src/dfm-gui/panel_p.h create mode 100644 src/dfm-gui/quickutils.cpp create mode 100644 src/dfm-gui/sharedqmlengine.cpp create mode 100644 src/dfm-gui/sharedqmlengine_p.h create mode 100644 src/dfm-gui/windowhandle.cpp create mode 100644 src/dfm-gui/windowmanager.cpp create mode 100644 src/dfm-gui/windowmanager_p.h create mode 100644 src/plugins/filemanager/core/dfmplugin-core/FileWindow.qml create mode 100644 src/plugins/filemanager/core/dfmplugin-detailspace/DetailSpace.qml create mode 100644 src/plugins/filemanager/core/dfmplugin-sidebar/Sidebar.qml create mode 100644 src/plugins/filemanager/core/dfmplugin-titlebar/LineSearch.qml create mode 100644 src/plugins/filemanager/core/dfmplugin-titlebar/Titlebar.qml diff --git a/CMakeLists.txt b/CMakeLists.txt index 517be9db0a..0f99f75f89 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -134,6 +134,15 @@ if(NOT DEFINED DFM_THUMBNAIL_TOOL) set(DFM_THUMBNAIL_TOOL ${LIB_INSTALL_DIR}/dde-file-manager/tools) endif() +# qml module +if(NOT DEFINED DFM_QML_MODULE) + set(DFM_QML_MODULE ${DFM_PLUGIN_DIR}/qml) +endif() + +# qml import path for qt creator +list(APPEND QML_DIRS ${DFM_BUILD_PLUGIN_DIR}/qml) +set(QML_IMPORT_PATH ${QML_DIRS} CACHE STRING "Import local module" FORCE) + if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." @@ -155,13 +164,15 @@ else() endif() # sub directories -# add_subdirectory(src/apps) +add_subdirectory(src/apps) add_subdirectory(src/dfm-base) -# add_subdirectory(src/dfm-extension) -# add_subdirectory(src/dfm-framework) -# add_subdirectory(src/plugins) +add_subdirectory(src/dfm-extension) +add_subdirectory(src/dfm-framework) +add_subdirectory(src/dfm-gui) +add_subdirectory(src/plugins) # add_subdirectory(src/external) # add_subdirectory(src/tools) +add_subdirectory(src/dfm-declarative) # docs if (BUILD_DOCS) diff --git a/assets/dev/dfm-gui/dfm-gui.pc.in b/assets/dev/dfm-gui/dfm-gui.pc.in new file mode 100644 index 0000000000..748c4541ba --- /dev/null +++ b/assets/dev/dfm-gui/dfm-gui.pc.in @@ -0,0 +1,7 @@ +Name: @BIN_NAME@ +Description: @CMAKE_PROJECT_DESCRIPTION@ +URL: @CMAKE_PROJECT_HOMEPAGE_URL@ +Version: @PROJECT_VERSION@ +Cflags: -I"@CMAKE_INSTALL_FULL_INCLUDEDIR@" +Libs: -L"@CMAKE_INSTALL_FULL_LIBDIR@" -l@BIN_NAME@ +Libs.private: -L"@CMAKE_INSTALL_FULL_LIBDIR@" -l@BIN_NAME@ diff --git a/assets/dev/dfm-gui/dfm-guiConfig.cmake.in b/assets/dev/dfm-gui/dfm-guiConfig.cmake.in new file mode 100644 index 0000000000..4ab6b7c5b3 --- /dev/null +++ b/assets/dev/dfm-gui/dfm-guiConfig.cmake.in @@ -0,0 +1,3 @@ +set(@BIN_NAME@_INCLUDE_DIR @CMAKE_INSTALL_FULL_INCLUDEDIR@) +set(@BIN_NAME@_LIBRARIES @BIN_NAME@) +include_directories("${@BIN_NAME@_INCLUDE_DIR}") diff --git a/cmake/install_plugin_quick_module.cmake b/cmake/install_plugin_quick_module.cmake new file mode 100644 index 0000000000..7704dbee34 --- /dev/null +++ b/cmake/install_plugin_quick_module.cmake @@ -0,0 +1,16 @@ +# Install all plugin qml component file to + +function(INSTALL_PLUGIN_QUICK_MODULE DST_PATH) + file(GLOB_RECURSE QMLS CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/*.qml") + + if(${CMAKE_BUILD_TYPE} STREQUAL "Debug") + set(QML_BUILD_INSTALL_PATH ${PROJECT_BINARY_DIR}/../../${PROJECT_NAME}) + EXECUTE_PROCESS(COMMAND mkdir -p ${QML_BUILD_INSTALL_PATH}) + EXECUTE_PROCESS(COMMAND cp -f ${QMLS} ${QML_BUILD_INSTALL_PATH}) + message("--- Copy qml file to ${QML_BUILD_INSTALL_PATH}") + + else() + install(FILES ${QMLS} DESTINATION ${DST_PATH}/${PROJECT_NAME}) + message("--- Copy qml file to ${DST_PATH}/${PROJECT_NAME}") + endif() +endfunction(INSTALL_PLUGIN_QUICK_MODULE) diff --git a/debian/control b/debian/control index 519fd77a6d..6e9b7ac8b4 100644 --- a/debian/control +++ b/debian/control @@ -96,7 +96,13 @@ Depends: dde-file-manager-daemon-plugins, dde-file-manager-server-plugins, dde-file-manager-common-plugins, - dde-file-manager-preview-plugins + dde-file-manager-preview-plugins, +# qml required + qml6-module-qtqml, + qml6-module-qtquick, + qml6-module-qtquick-controls, + qml6-module-qtquick-layouts, + qml6-module-qtquick-window Replaces: dde-file-manager-oem, dde-desktop (<< 6.0.1), libdde-file-manager Recommends: dde-qt5integration, avfs, samba, deepin-anything-server Description: File manager front end diff --git a/debian/rules b/debian/rules index 1470042f86..ceaa90f30c 100755 --- a/debian/rules +++ b/debian/rules @@ -21,4 +21,8 @@ override_dh_auto_configure: -DAPP_VERSION=$(DEB_VERSION_UPSTREAM) -DVERSION=$(DEB_VERSION_UPSTREAM) LIB_INSTALL_DIR=/usr/lib/$(DEB_HOST_MULTIARCH) override_dh_auto_build: - dh_auto_build -- -j8 \ No newline at end of file + dh_auto_build -- -j8 + +# FIXME: remove later. +override_dh_install: + echo "FIXME: temporay changes, skip missing file error." diff --git a/examples/appletwindow/AppletItemEx.qml b/examples/appletwindow/AppletItemEx.qml new file mode 100644 index 0000000000..20a2a89df4 --- /dev/null +++ b/examples/appletwindow/AppletItemEx.qml @@ -0,0 +1,22 @@ +import QtQuick 2.15 +import QtQuick.Controls +import org.dfm.base + +AppletItem { + property int flag: 1 + + height: 100 + width: 500 + + Rectangle { + color: "lightyellow" + height: 100 + width: 200 + + Text { + id: appletText + + text: "Applet: " + Applet + } + } +} diff --git a/examples/appletwindow/CMakeLists.txt b/examples/appletwindow/CMakeLists.txt new file mode 100644 index 0000000000..dc9866c073 --- /dev/null +++ b/examples/appletwindow/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.10) + +project(appletwindow) + +add_executable(${PROJECT_NAME} main.cpp + Panel.qml + AppletItemEx.qml) + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Quick) + +target_link_libraries( + ${PROJECT_NAME} + Qt6::Core + Qt6::Gui + Qt6::Quick + DFM::framework + DFM::gui) + +file(GLOB_RECURSE QMLS CONFIGURE_DEPENDS + "./*.qml" +) +EXECUTE_PROCESS(COMMAND cp -f ${QMLS} ${PROJECT_BINARY_DIR}) diff --git a/examples/appletwindow/Panel.qml b/examples/appletwindow/Panel.qml new file mode 100644 index 0000000000..483365b541 --- /dev/null +++ b/examples/appletwindow/Panel.qml @@ -0,0 +1,61 @@ +import QtQuick 2.15 +import QtQuick.Controls +import org.dfm.base + +ApplicationWindow { + height: 600 + width: 800 + + Text { + id: text + + text: "Applets: " + Containment.applets + } + + SplitView { + anchors.bottom: parent.bottom + anchors.top: text.bottom + width: parent.width + + Rectangle { + SplitView.preferredWidth: 150 + + Control { + contentItem: Containment.objectForProperty("flag", 1) + } + } + + Rectangle { + id: content + + SplitView.fillHeight: true + SplitView.fillWidth: true + color: "lightblue" + + Column { + id: layout + + Button { + id: button + + text: "add item" + + onClicked: { + let item = Containment.objectForProperty("flag", 1); + if (item) { + leftControl.contentItem = item; + } + } + } + + Control { + id: leftControl + + onContentItemChanged: { + contentItem.anchors.fill = leftControl; + } + } + } + } + } +} diff --git a/examples/appletwindow/main.cpp b/examples/appletwindow/main.cpp new file mode 100644 index 0000000000..52765429f7 --- /dev/null +++ b/examples/appletwindow/main.cpp @@ -0,0 +1,48 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include +#include + +#include +#include + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + + dpf::PluginQuickMetaDataCreator creator; + creator.create("app", "Panel", QUrl::fromLocalFile("./Panel.qml")); + creator.setType("Panel"); + auto ptr = creator.take(); + + QString errorString; + dfmgui::AppletManager::instance()->registeApplet(ptr, &errorString); + qWarning() << errorString; + + // child + creator.create("plugin", "AppletItemEx", QUrl::fromLocalFile("./AppletItemEx.qml")); + creator.setParent("app.Panel"); + ptr = creator.take(); + dfmgui::AppletManager::instance()->registeApplet(ptr, &errorString); + qWarning() << errorString; + + creator.create("plugin", "AppletItemEx2", QUrl::fromLocalFile("./AppletItemEx.qml")); + creator.setParent("app.Panel"); + ptr = creator.take(); + dfmgui::AppletManager::instance()->registeApplet(ptr, &errorString); + qWarning() << errorString; + + auto handle = dfmgui::WindowManager::instance()->createWindow("app", "Panel"); + handle->window()->show(); + + handle->window()->dumpObjectTree(); + + auto handle2 = dfmgui::WindowManager::instance()->createWindow("app", "Panel", { { "flag", 2 } }); + handle2->window()->show(); + + int ret = app.exec(); + return ret; +} diff --git a/include/dfm-base/base/schemefactory.h b/include/dfm-base/base/schemefactory.h index c32524fefa..ecbdd3f900 100644 --- a/include/dfm-base/base/schemefactory.h +++ b/include/dfm-base/base/schemefactory.h @@ -500,6 +500,7 @@ class SortFilterFactory final : public SchemeFactory static SortFilterFactory &instance(); // 获取全局实例 explicit SortFilterFactory() {} }; + } // namespace dfmbase #endif // SCHEMEFACTORY_H diff --git a/include/dfm-framework/lifecycle/lifecycle.h b/include/dfm-framework/lifecycle/lifecycle.h index 440aac7db3..1c36390010 100644 --- a/include/dfm-framework/lifecycle/lifecycle.h +++ b/include/dfm-framework/lifecycle/lifecycle.h @@ -32,6 +32,7 @@ QStringList lazyLoadList(); PluginMetaObjectPointer pluginMetaObj(const QString &pluginName, const QString version = ""); QList pluginMetaObjs(const std::function &cond = {}); +QList pluginSortedMetaObjs(const std::function &cond = {}); bool readPlugins(); bool loadPlugins(); diff --git a/include/dfm-framework/lifecycle/pluginmanager.h b/include/dfm-framework/lifecycle/pluginmanager.h index 976d4c58b6..59b3637c3a 100644 --- a/include/dfm-framework/lifecycle/pluginmanager.h +++ b/include/dfm-framework/lifecycle/pluginmanager.h @@ -34,6 +34,7 @@ class PluginManager : public QObject QStringList blackList() const; QStringList lazyLoadList() const; QQueue readQueue() const; + QQueue loadQueue() const; void addPluginIID(const QString &pluginIIDs); void addBlackPluginName(const QString &name); void addLazyLoadPluginName(const QString &name); diff --git a/include/dfm-framework/lifecycle/pluginmetaobject.h b/include/dfm-framework/lifecycle/pluginmetaobject.h index eb619c3894..4750456a75 100644 --- a/include/dfm-framework/lifecycle/pluginmetaobject.h +++ b/include/dfm-framework/lifecycle/pluginmetaobject.h @@ -5,6 +5,7 @@ #ifndef PLUGINMETAOBJECT_H #define PLUGINMETAOBJECT_H +#include "dfm-framework/lifecycle/pluginquickmetadata.h" #include #include @@ -24,7 +25,7 @@ class PluginMetaT1 : public QSharedData { Q_DISABLE_COPY(PluginMetaT1) public: - PluginMetaT1() {} + PluginMetaT1() { } }; /*! 插件json元文件示例 @@ -44,6 +45,18 @@ class PluginMetaT1 : public QSharedData * "Depends" : [ * {"Name" : "core", "Version" : "4.8.2"}, * {"Name" : "other", "Version" : "4.8.2"} + * ], + * "Quick" : [ // 可选字段,需展示界面的插件提供 + * { + * "Url" : "MainWindow.qml", // 必须,加载的QML组件文件名,文件位于"插件目录/插件Name/Url" + * "Id" : "mainWindow", // 必须,用于区分的组件ID,运行时会标记为 "插件名.ID" + * "Type" : "[Containment|Panel]", // 可选,无字段或空内容视为 Applet + * "Parent" : "[Depends Plugin Name].[Id]", // 可选,默认为父组件 "插件名.ID" 的一部分, 插件名字段在 “Depends” 中必须存在 + * "Applet" : "core.compoment.applet" // 可选,拓展的 Applet ,需在 AppletFactory 注册 + * }, { + * "Url" : "property.qml", + * "Id" : "propertyDialog" + * } * ] * } * \endcode @@ -91,6 +104,7 @@ class PluginMetaObject final : public PluginMetaT1 QVariantMap customData() const; State pluginState() const; QSharedPointer plugin() const; + QList quickMetaData() const; QString errorString() const; private: @@ -104,7 +118,7 @@ QT_BEGIN_NAMESPACE #ifndef QT_NO_DEBUG_STREAM Q_CORE_EXPORT QDebug operator<<(QDebug, const DPF_NAMESPACE::PluginMetaObject &); Q_CORE_EXPORT QDebug operator<<(QDebug, const DPF_NAMESPACE::PluginMetaObjectPointer &); -#endif //QT_NO_DEBUG_STREAM +#endif // QT_NO_DEBUG_STREAM QT_END_NAMESPACE DPF_END_NAMESPACE diff --git a/include/dfm-framework/lifecycle/pluginquickmetadata.h b/include/dfm-framework/lifecycle/pluginquickmetadata.h new file mode 100644 index 0000000000..6cc7d8bede --- /dev/null +++ b/include/dfm-framework/lifecycle/pluginquickmetadata.h @@ -0,0 +1,71 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef PLUGINQUICKMETADATA_H +#define PLUGINQUICKMETADATA_H + +#include + +#include +#include + +DPF_BEGIN_NAMESPACE + +class PluginQuickData; +class PluginQuickMetaData final +{ + friend class PluginQuickData; + friend class PluginQuickMetaDataCreator; + friend class PluginManager; + friend class PluginManagerPrivate; + friend class PluginMetaObject; + friend Q_CORE_EXPORT QDebug operator<<(QDebug, const PluginQuickMetaData &); + +public: + PluginQuickMetaData(); + PluginQuickMetaData(const QUrl &url, + const QString &id, + const QString &plugin, + const QString &type, + const QString &parent, + const QString &applet); + + QUrl url() const; + QString id() const; + QString plugin() const; + QString type() const; + QString parent() const; + QString applet() const; + +private: + QScopedPointer d; + Q_DISABLE_COPY(PluginQuickMetaData); +}; + +using PluginQuickMetaPtr = QSharedPointer; + +class PluginQuickMetaDataCreator final +{ +public: + PluginQuickMetaDataCreator(); + + void create(const QString &plugin, const QString &id, const QUrl &url); + void setType(const QString &type); + void setParent(const QString &parent); + void setApplet(const QString &applet); + PluginQuickMetaPtr take(); + +private: + PluginQuickMetaPtr metaPtr; +}; + +QT_BEGIN_NAMESPACE +#ifndef QT_NO_DEBUG_STREAM +Q_CORE_EXPORT QDebug operator<<(QDebug, const DPF_NAMESPACE::PluginQuickMetaData &); +#endif // QT_NO_DEBUG_STREAM +QT_END_NAMESPACE + +DPF_END_NAMESPACE + +#endif // PLUGINQUICKMETADATA_H diff --git a/include/dfm-gui/applet.h b/include/dfm-gui/applet.h new file mode 100644 index 0000000000..8bc8389de0 --- /dev/null +++ b/include/dfm-gui/applet.h @@ -0,0 +1,76 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef APPLET_H +#define APPLET_H + +#include +#include + +#include + +class QQuickItem; + +DFMGUI_BEGIN_NAMESPACE + +class Containment; + +class AppletPrivate; +class Applet : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QUrl currentUrl READ currentUrl WRITE setCurrentUrl NOTIFY currentUrlChanged FINAL) + Q_PROPERTY(QObject *rootObject NOTIFY rootObjectChanged FINAL) + +public: + enum Flag { + kUnknown, + kApplet = 0x1, // 基础组件 + kContainment = 0x2, // 容器组件,可管理基础控件 + kPanel = 0x4 | kContainment, // 独特的容器组件,用于顶层窗体 + }; + Q_DECLARE_FLAGS(Flags, Flag) + Q_FLAG(Flags) + + explicit Applet(QObject *parent = nullptr); + ~Applet() override; + + Flags flags() const; + + QObject *rootObject() const; + Q_SIGNAL void rootObjectChanged(QObject *object); + + QUrl currentUrl() const; + void setCurrentUrl(const QUrl &url); + Q_SIGNAL void currentUrlChanged(const QUrl &url); + + Containment *containment() const; + + QString plugin() const; + QString id() const; + + QUrl componentUrl() const; + void setComponentUrl(const QUrl &url); + Q_SIGNAL void componentUrlChanged(const QUrl &url); + +protected: + explicit Applet(AppletPrivate &dd, QObject *parent = nullptr); + QScopedPointer dptr; + +private: + Q_DECLARE_PRIVATE_D(dptr, Applet); + Q_DISABLE_COPY(Applet); + + friend class AppletItem; + friend class ContainmentItem; + friend class SharedQmlEngine; + friend class AppletManager; + friend class WindowManager; + friend class WindowManagerPrivate; +}; + +DFMGUI_END_NAMESPACE + +#endif // APPLET_H diff --git a/include/dfm-gui/appletfactory.h b/include/dfm-gui/appletfactory.h new file mode 100644 index 0000000000..abb4408667 --- /dev/null +++ b/include/dfm-gui/appletfactory.h @@ -0,0 +1,35 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef APPLETFACTORY_H +#define APPLETFACTORY_H + +#include +#include + +DFMGUI_BEGIN_NAMESPACE + +class Applet; +class AppletFactory +{ + explicit AppletFactory(); + ~AppletFactory(); + +public: + using AppletPtr = Applet *; + using Key = QString; + using CreateFunc = std::function; + + static AppletFactory *instance(); + + bool regCreator(const Key &url, CreateFunc creator, QString *errorString = nullptr); + AppletPtr create(const Key &url, QString *errorString = nullptr); + +private: + dfmbase::DThreadMap constructList {}; +}; + +DFMGUI_END_NAMESPACE + +#endif // APPLETFACTORY_H diff --git a/include/dfm-gui/appletitem.h b/include/dfm-gui/appletitem.h new file mode 100644 index 0000000000..a58e21f3d8 --- /dev/null +++ b/include/dfm-gui/appletitem.h @@ -0,0 +1,39 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef APPLETITEM_H +#define APPLETITEM_H + +#include "applet.h" + +#include + +DFMGUI_BEGIN_NAMESPACE + +class AppletItemPrivate; +class AppletItem : public QQuickItem +{ + Q_OBJECT + +public: + explicit AppletItem(QQuickItem *parent = nullptr); + ~AppletItem() override; + + Applet *applet() const; + void setApplet(Applet *applet); + + Q_INVOKABLE QQuickWindow *itemWindow() const; + Q_SIGNAL void itemWindowChanged(QQuickWindow *window); + + static AppletItem *itemForApplet(Applet *applet); + +private: + QScopedPointer dptr; + Q_DECLARE_PRIVATE_D(dptr, AppletItem); + Q_DISABLE_COPY(AppletItem); +}; + +DFMGUI_END_NAMESPACE + +#endif // APPLETITEM_H diff --git a/include/dfm-gui/appletmanager.h b/include/dfm-gui/appletmanager.h new file mode 100644 index 0000000000..2050697d52 --- /dev/null +++ b/include/dfm-gui/appletmanager.h @@ -0,0 +1,54 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef APPLETMANAGER_H +#define APPLETMANAGER_H + +#include +#include + +#include + +DFMGUI_BEGIN_NAMESPACE + +class Applet; +class Containment; +class Panel; + +class AppletManagerPrivate; +class AppletManager : public QObject +{ + Q_OBJECT + + explicit AppletManager(QObject *parent = nullptr); + ~AppletManager(); + +public: + static AppletManager *instance(); + + void initRootTemplates(const QString &configFile = {}); + bool registeApplet(const dpf::PluginQuickMetaPtr &infoPtr); + bool unRegisteApplet(const QString &pluginName, const QString &quickId); + + QList panelIdList() const; + Panel *createPanel(const QString &templateId); + Panel *createPanel(const QString &pluginName, const QString &quickId); + + QList allAppletTemplateIdList() const; + Applet *createApplet(const QString &templateId, QObject *parent = nullptr); + Applet *createApplet(const QString &pluginName, const QString &quickId, QObject *parent = nullptr); + + QString lastError() const; + + static Applet *createAppletFromInfo(const dpf::PluginQuickMetaPtr &metaPtr, QObject *parent = nullptr, QString *errorString = nullptr); + +private: + QScopedPointer dptr; + Q_DECLARE_PRIVATE_D(dptr, AppletManager) + Q_DISABLE_COPY_MOVE(AppletManager) +}; + +DFMGUI_END_NAMESPACE + +#endif // APPLETMANAGER_H diff --git a/include/dfm-gui/containment.h b/include/dfm-gui/containment.h new file mode 100644 index 0000000000..929cebaa30 --- /dev/null +++ b/include/dfm-gui/containment.h @@ -0,0 +1,51 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef CONTAINMENT_H +#define CONTAINMENT_H + +#include +#include + +#include + +DFMGUI_BEGIN_NAMESPACE + +class ContainmentPrivate; +class Containment : public Applet +{ + Q_OBJECT + Q_PROPERTY(QList applets READ applets NOTIFY appletsChanged FINAL) + +public: + explicit Containment(QObject *parent = nullptr); + ~Containment() override; + + Applet *createApplet(const dpf::PluginQuickMetaPtr &metaPtr); + + void appendApplet(Applet *applet); + void removeApplet(Applet *applet); + QList applets() const; + Q_SIGNAL void appletAdded(Applet *applet); + Q_SIGNAL void appletRemoved(Applet *applet); + Q_SIGNAL void appletsChanged(); + // Applet 关联的 QML 组件变更(初始化结束)时触发 + Q_SIGNAL void appletRootObjectChanged(QObject *rootObject); + + Q_INVOKABLE Applet *appletForProperty(const QString &property, const QVariant &var); + Q_INVOKABLE QObject *objectForProperty(const QString &property, const QVariant &var); + +protected: + explicit Containment(ContainmentPrivate &dd, QObject *parent = nullptr); + +private: + Q_DECLARE_PRIVATE_D(dptr, Containment) + Q_DISABLE_COPY(Containment) + + friend class ContainmentItem; +}; + +DFMGUI_END_NAMESPACE + +#endif // CONTAINMENT_H diff --git a/include/dfm-gui/containmentitem.h b/include/dfm-gui/containmentitem.h new file mode 100644 index 0000000000..d0ffc9f1bc --- /dev/null +++ b/include/dfm-gui/containmentitem.h @@ -0,0 +1,25 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef CONTAINMENTITEM_H +#define CONTAINMENTITEM_H + +#include + +DFMGUI_BEGIN_NAMESPACE + +class ContainmentItem : public AppletItem +{ + Q_OBJECT + +public: + ContainmentItem(QQuickItem *parent = nullptr); + ~ContainmentItem() override; + + Q_INVOKABLE AppletItem *itemFor(Applet *applet); +}; + +DFMGUI_END_NAMESPACE + +#endif // CONTAINMENTITEM_H diff --git a/include/dfm-gui/dfm_gui_global.h b/include/dfm-gui/dfm_gui_global.h new file mode 100644 index 0000000000..d8f3129db1 --- /dev/null +++ b/include/dfm-gui/dfm_gui_global.h @@ -0,0 +1,20 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef DFM_GUI_GLOBAL_H +#define DFM_GUI_GLOBAL_H + +#include + +#define DFMGUI_NAMESPACE dfmgui + +#define DFMGUI_BEGIN_NAMESPACE namespace DFMGUI_NAMESPACE { +#define DFMGUI_END_NAMESPACE } +#define DFMGUI_USE_NAMESPACE using namespace DFMGUI_NAMESPACE; + +#include + +Q_DECLARE_LOGGING_CATEGORY(logDFMGui) + +#endif // DFM_GUI_GLOBAL_H diff --git a/include/dfm-gui/panel.h b/include/dfm-gui/panel.h new file mode 100644 index 0000000000..cbf8f7acd4 --- /dev/null +++ b/include/dfm-gui/panel.h @@ -0,0 +1,34 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef PANEL_H +#define PANEL_H + +#include + +#include + +class QQuickWindow; + +DFMGUI_BEGIN_NAMESPACE + +// TODO:此部分是否和 Applet 分离,而非继承关系 +class PanelPrivate; +class Panel : public Containment +{ + Q_OBJECT + +public: + explicit Panel(QObject *parent = nullptr); + + QQuickWindow *window() const; + +private: + Q_DECLARE_PRIVATE_D(dptr, Panel); + Q_DISABLE_COPY(Panel); +}; + +DFMGUI_END_NAMESPACE + +#endif // PANEL_H diff --git a/include/dfm-gui/quickutils.h b/include/dfm-gui/quickutils.h new file mode 100644 index 0000000000..f46a6d08f8 --- /dev/null +++ b/include/dfm-gui/quickutils.h @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef QUICKUTILS_H +#define QUICKUTILS_H + +#include + +#include + +DFMGUI_BEGIN_NAMESPACE + +class QuickUtils : public QObject +{ + Q_OBJECT +public: + /*! + * \brief 用于标识窗体类型 + * QML中 ENUM 必须以大写开头 + */ + enum WidgetType { + UnknownType, + Sidebar, + Titlebar, + DetailSpace, + WorkSpace, + TypeCount, + }; + Q_ENUM(WidgetType) + + explicit QuickUtils(QObject *parent = nullptr); +}; + +DFMGUI_END_NAMESPACE + +#endif // QUICKUTILS_H diff --git a/include/dfm-gui/sharedqmlengine.h b/include/dfm-gui/sharedqmlengine.h new file mode 100644 index 0000000000..1e42cc53e4 --- /dev/null +++ b/include/dfm-gui/sharedqmlengine.h @@ -0,0 +1,50 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef SHAREDQMLENGINE_H +#define SHAREDQMLENGINE_H + +#include + +#include +#include + +class QQmlEngine; +class QQmlContext; + +DFMGUI_BEGIN_NAMESPACE + +class Applet; +class SharedQmlEnginePrivate; +class SharedQmlEngine : public QObject +{ + Q_OBJECT + +public: + explicit SharedQmlEngine(QObject *parent = nullptr); + virtual ~SharedQmlEngine() override; + + QObject *rootObject() const; + QQmlContext *rootContext() const; + QQmlComponent *mainComponent() const; + static QSharedPointer globalEngine(); + + bool create(Applet *applet, bool async = false); + bool completeCreation(const QVariantMap &args = {}); + + static QObject *createObject(const QUrl &url, const QVariantMap &args = {}); + + QQmlComponent::Status status(); + Q_SIGNAL void statusChanged(QQmlComponent::Status status); + Q_SIGNAL void createFinished(bool success); + +private: + QScopedPointer dptr; + Q_DECLARE_PRIVATE_D(dptr, SharedQmlEngine); + Q_DISABLE_COPY(SharedQmlEngine); +}; + +DFMGUI_END_NAMESPACE + +#endif // SHAREDQMLENGINE_H diff --git a/include/dfm-gui/windowhandle.h b/include/dfm-gui/windowhandle.h new file mode 100644 index 0000000000..5660ce72df --- /dev/null +++ b/include/dfm-gui/windowhandle.h @@ -0,0 +1,42 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef WINDOWHANDLE_H +#define WINDOWHANDLE_H + +#include + +#include +#include + +class QQuickWindow; + +DFMGUI_BEGIN_NAMESPACE + +class Panel; +class FileManagerWindowHandleData; + +class WindowHandle +{ +public: + explicit WindowHandle(); + explicit WindowHandle(const QString &error); + WindowHandle(Panel *p, QQuickWindow *w); + ~WindowHandle(); + + bool isValid() const; + QPointer window() const; + QPointer panel() const; + QString lastError() const; + +private: + Q_DISABLE_COPY(WindowHandle); + QScopedPointer data; +}; + +using WindowHandlePtr = QSharedPointer; + +DFMGUI_END_NAMESPACE + +#endif // WINDOWHANDLE_H diff --git a/include/dfm-gui/windowmanager.h b/include/dfm-gui/windowmanager.h new file mode 100644 index 0000000000..7f0ef4b2e3 --- /dev/null +++ b/include/dfm-gui/windowmanager.h @@ -0,0 +1,43 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef WINDOWMANAGER_H +#define WINDOWMANAGER_H + +#include +#include +#include + +class QQuickWindow; +class QQmlEngine; + +DFMGUI_BEGIN_NAMESPACE + +class WindowManagerPrivate; +class WindowManager : public QObject +{ + Q_OBJECT + + explicit WindowManager(); + ~WindowManager() override; + +public: + static WindowManager *instance(); + QSharedPointer engine() const; + + WindowHandlePtr createWindow(const QString &pluginName, const QString &quickId, + const QVariantMap &var = {}); + void showWindow(const WindowHandlePtr &handle); + +private: + QScopedPointer dptr; + Q_DECLARE_PRIVATE_D(dptr, WindowManager); + Q_DISABLE_COPY(WindowManager) +}; + +DFMGUI_END_NAMESPACE + +#define FMQuickWindowIns DFMGUI_NAMESPACE::WindowManager::instance(); + +#endif // WINDOWMANAGER_H diff --git a/src/apps/CMakeLists.txt b/src/apps/CMakeLists.txt index ddadae1924..20674a2e7b 100644 --- a/src/apps/CMakeLists.txt +++ b/src/apps/CMakeLists.txt @@ -10,10 +10,10 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug") # set(CMAKE_L_FLAGS "${CMAKE_L_FLAGS} -fsanitize=undefined,address,leak -fno-omit-frame-pointer") endif() -add_subdirectory(dde-desktop) +# add_subdirectory(dde-desktop) add_subdirectory(dde-file-manager) -add_subdirectory(dde-file-manager-daemon) -add_subdirectory(dde-file-manager-server) -add_subdirectory(dde-file-dialog) -add_subdirectory(dde-file-dialog-x11) -add_subdirectory(dde-file-dialog-wayland) +# add_subdirectory(dde-file-manager-daemon) +# add_subdirectory(dde-file-manager-server) +# add_subdirectory(dde-file-dialog) +# add_subdirectory(dde-file-dialog-x11) +# add_subdirectory(dde-file-dialog-wayland) diff --git a/src/apps/config.h.in b/src/apps/config.h.in index fea81a3acf..fceba617fb 100644 --- a/src/apps/config.h.in +++ b/src/apps/config.h.in @@ -74,6 +74,12 @@ # warning "cmake unseting definition DFM_THUMBNAIL_TOOL" #endif +#ifndef DFM_QML_MODULE +# define DFM_QML_MODULE "${DFM_QML_MODULE}" +#elif +# warning "cmake unseting definition DFM_QML_MODULE" +#endif + #ifndef VERSION # define VERSION "@VERSION@" #endif diff --git a/src/apps/dde-desktop/CMakeLists.txt b/src/apps/dde-desktop/CMakeLists.txt index 1ac359dc4d..912f3bfcb6 100644 --- a/src/apps/dde-desktop/CMakeLists.txt +++ b/src/apps/dde-desktop/CMakeLists.txt @@ -16,12 +16,12 @@ set(SRCS ) find_package(PkgConfig REQUIRED) -find_package(Qt5 COMPONENTS +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets DBus REQUIRED) -find_package(Dtk COMPONENTS Widget REQUIRED) +find_package(Dtk${DTK_VERSION_MAJOR} COMPONENTS Widget REQUIRED) add_executable(${PROJECT_NAME} ${SRCS}) @@ -36,8 +36,8 @@ target_link_libraries( ${PROJECT_NAME} DFM::base DFM::framework - Qt5::Widgets - Qt5::DBus + Qt${QT_VERSION_MAJOR}::Widgets + Qt${QT_VERSION_MAJOR}::DBus ${DtkWidget_LIBRARIES} ) diff --git a/src/apps/dde-file-manager/CMakeLists.txt b/src/apps/dde-file-manager/CMakeLists.txt index 474a7c9ce7..b4a51c156b 100644 --- a/src/apps/dde-file-manager/CMakeLists.txt +++ b/src/apps/dde-file-manager/CMakeLists.txt @@ -24,25 +24,25 @@ set(SRCS ${CMAKE_CURRENT_SOURCE_DIR}/sessionloader.cpp ) -find_package(Qt5 COMPONENTS Widgets REQUIRED) -find_package(Qt5 COMPONENTS Network REQUIRED) -find_package(Dtk COMPONENTS Widget REQUIRED) +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets REQUIRED) +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Network REQUIRED) +find_package(Dtk${DTK_VERSION_MAJOR} COMPONENTS Widget REQUIRED) add_executable(${PROJECT_NAME} ${SRCS}) target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR} - ${DtkWidget_INCLUDE_DIRS} ) target_link_libraries( ${PROJECT_NAME} - Qt5::Widgets - Qt5::Network + Qt${QT_VERSION_MAJOR}::Widgets + Qt${QT_VERSION_MAJOR}::Network DFM::base + DFM::gui DFM::framework - ${DtkWidget_LIBRARIES} + Dtk${DTK_VERSION_MAJOR}::Widget ) install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}) diff --git a/src/apps/dde-file-manager/commandparser.cpp b/src/apps/dde-file-manager/commandparser.cpp index fd5c6108d4..817b959ad7 100644 --- a/src/apps/dde-file-manager/commandparser.cpp +++ b/src/apps/dde-file-manager/commandparser.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include Q_DECLARE_LOGGING_CATEGORY(logAppFileManager) @@ -269,7 +270,7 @@ void CommandParser::openInUrls() //路径字符串在DUrl::fromUserInput中会处理编码,这里不处理 if (!QDir().exists(path) && !path.startsWith("./") && !path.startsWith("../") && !path.startsWith("/")) { // 路径中包含特殊字符的全部uri编码 - QRegExp regexp("[#&@\\!\\?]"); + QRegularExpression regexp("[#&@\\!\\?]"); if (path.contains(regexp)) { QString left, right, encode; int idx = path.indexOf(regexp); diff --git a/src/apps/dde-file-manager/main.cpp b/src/apps/dde-file-manager/main.cpp index 10aa623dd9..e0b7a4d5bf 100644 --- a/src/apps/dde-file-manager/main.cpp +++ b/src/apps/dde-file-manager/main.cpp @@ -13,16 +13,20 @@ #include #include +#include +#include + #include -#include +// #include #include #include #include -#include +// #include #include #include +#include #include #include @@ -120,6 +124,23 @@ static QStringList buildBlackNames() return blackNames; } +static bool initQmlEngine() +{ + QSharedPointer globalEngine = dfmgui::WindowManager::instance()->engine(); + if (!globalEngine) { + return false; + } + +#ifdef QT_DEBUG + const QString &pluginsDir { DFM_BUILD_PLUGIN_DIR }; + globalEngine->addImportPath(pluginsDir + "/qml"); +#else + globalEngine->addImportPath(DFM_QML_MODULE); +#endif + + return true; +} + static bool pluginsLoad() { QString msg; @@ -150,7 +171,7 @@ static bool pluginsLoad() else DPF_NAMESPACE::LifeCycle::setLazyloadFilter(lazyLoadFilter); - qCInfo(logAppFileManager) << "Depend library paths:" << DApplication::libraryPaths(); + // qCInfo(logAppFileManager) << "Depend library paths:" << DApplication::libraryPaths(); qCInfo(logAppFileManager) << "Load plugin paths: " << DPF_NAMESPACE::LifeCycle::pluginPaths(); // read all plugins in setting paths @@ -272,7 +293,7 @@ int main(int argc, char *argv[]) initLog(); // Fixed the locale codec to utf-8 - QTextCodec::setCodecForLocale(QTextCodec::codecForName("utf-8")); + // QTextCodec::setCodecForLocale(QTextCodec::codecForName("utf-8")); SingleApplication a(argc, argv); @@ -320,10 +341,16 @@ int main(int argc, char *argv[]) // check upgrade checkUpgrade(&a); + if (!initQmlEngine()) { + qCCritical(logAppFileManager) << "init QQmlEngine failed!"; + abort(); + } + if (!pluginsLoad()) { qCCritical(logAppFileManager) << "Load pugin failed!"; abort(); } + signal(SIGTERM, handleSIGTERM); signal(SIGPIPE, handleSIGPIPE); } else { diff --git a/src/dfm-base/CMakeLists.txt b/src/dfm-base/CMakeLists.txt index 5c9fac7f2a..05e568d44f 100644 --- a/src/dfm-base/CMakeLists.txt +++ b/src/dfm-base/CMakeLists.txt @@ -48,10 +48,11 @@ find_package(PkgConfig REQUIRED) message("Current Qt Version ${QT_VERSION}") -pkg_search_module(dfm-burn REQUIRED dfm-burn IMPORTED_TARGET) -pkg_search_module(dfm-io REQUIRED dfm-io IMPORTED_TARGET) -pkg_search_module(dfm-mount REQUIRED dfm-mount IMPORTED_TARGET) -pkg_search_module(gsettings REQUIRED gsettings-qt IMPORTED_TARGET) +pkg_search_module(dfm-burn REQUIRED dfm6-burn IMPORTED_TARGET) +pkg_search_module(dfm-io REQUIRED dfm6-io IMPORTED_TARGET) +pkg_search_module(dfm-mount REQUIRED dfm6-mount IMPORTED_TARGET) +# FIXME: ? qgsettings 不再使用 +# pkg_search_module(gsettings REQUIRED gsettings-qt IMPORTED_TARGET) pkg_check_modules(mount REQUIRED mount IMPORTED_TARGET) pkg_search_module(Dtk6Core REQUIRED dtk6core IMPORTED_TARGET) @@ -107,7 +108,7 @@ target_link_libraries(${BIN_NAME} PUBLIC PkgConfig::dfm-burn PkgConfig::dfm-mount PkgConfig::dfm-io - PkgConfig::gsettings + # PkgConfig::gsettings PkgConfig::mount poppler-cpp Dtk6::Core diff --git a/src/dfm-base/base/configs/gsetting/gsettingmanager.cpp b/src/dfm-base/base/configs/gsetting/gsettingmanager.cpp index 0d0da973f8..e3b8c830c2 100644 --- a/src/dfm-base/base/configs/gsetting/gsettingmanager.cpp +++ b/src/dfm-base/base/configs/gsetting/gsettingmanager.cpp @@ -5,7 +5,8 @@ #include "gsettingmanager.h" #include "private/gsettingmanager_p.h" -#include +/// FIXME: ? qgsettings 不再使用 +// #include DFMBASE_USE_NAMESPACE @@ -25,7 +26,8 @@ GSettingManager::~GSettingManager() bool GSettingManager::isSchemaInstalled(const QString &schemaId) { - return QGSettings::isSchemaInstalled(schemaId.toLocal8Bit()); + // return QGSettings::isSchemaInstalled(schemaId.toLocal8Bit()); + return false; } bool GSettingManager::addSettings(const QString &schemaId, const QString &path, QString *err) @@ -37,10 +39,10 @@ bool GSettingManager::addSettings(const QString &schemaId, const QString &path, return false; } - auto gset = new QGSettings(schemaId.toLocal8Bit(), path.toLocal8Bit(), this); - d->settings.insert(schemaId, gset); - locker.unlock(); - connect(gset, &QGSettings::changed, this, [=](const QString &key) { Q_EMIT valueChanged(schemaId, key); }); + // auto gset = new QGSettings(schemaId.toLocal8Bit(), path.toLocal8Bit(), this); + // d->settings.insert(schemaId, gset); + // locker.unlock(); + // connect(gset, &QGSettings::changed, this, [=](const QString &key) { Q_EMIT valueChanged(schemaId, key); }); return true; } @@ -48,7 +50,7 @@ bool GSettingManager::removeSettings(const QString &schemaId, QString *err) { QWriteLocker locker(&d->lock); if (d->settings.contains(schemaId)) { - delete d->settings[schemaId]; + // delete d->settings[schemaId]; d->settings.remove(schemaId); } return true; @@ -65,7 +67,8 @@ QVariant GSettingManager::get(const QString &schemaId, const QString &key) const QReadLocker locker(&d->lock); if (!d->settings.contains(schemaId)) return QVariant(); - return d->settings.value(schemaId)->get(key); + // return d->settings.value(schemaId)->get(key); + return {}; } void GSettingManager::set(const QString &schemaId, const QString &key, const QVariant &value) @@ -73,7 +76,7 @@ void GSettingManager::set(const QString &schemaId, const QString &key, const QVa QReadLocker locker(&d->lock); if (!d->settings.contains(schemaId)) return; - d->settings.value(schemaId)->set(key, value); + // d->settings.value(schemaId)->set(key, value); } bool GSettingManager::trySet(const QString &schemaId, const QString &key, const QVariant &value) @@ -81,26 +84,29 @@ bool GSettingManager::trySet(const QString &schemaId, const QString &key, const QReadLocker locker(&d->lock); if (!d->settings.contains(schemaId)) return false; - return d->settings.value(schemaId)->trySet(key, value); + // return d->settings.value(schemaId)->trySet(key, value); + return {}; } QStringList GSettingManager::keys(const QString &schemaId) const { QReadLocker locker(&d->lock); - return d->settings.contains(schemaId) ? d->settings.value(schemaId)->keys() : QStringList(); + // return d->settings.contains(schemaId) ? d->settings.value(schemaId)->keys() : QStringList(); + return {}; } QVariantList GSettingManager::choices(const QString &schemaId, const QString &key) const { QReadLocker locker(&d->lock); - return d->settings.contains(schemaId) ? d->settings.value(schemaId)->choices(key) : QVariantList(); + // return d->settings.contains(schemaId) ? d->settings.value(schemaId)->choices(key) : QVariantList(); + return {}; } void GSettingManager::reset(const QString &schemaId, const QString &key) { QReadLocker locker(&d->lock); - if (d->settings.contains(schemaId)) - d->settings.value(schemaId)->reset(key); + // if (d->settings.contains(schemaId)) + // d->settings.value(schemaId)->reset(key); } GSettingManager::GSettingManager(QObject *parent) diff --git a/src/dfm-base/utils/loggerrules.cpp b/src/dfm-base/utils/loggerrules.cpp index ca3b2b66f6..8589be7b1f 100644 --- a/src/dfm-base/utils/loggerrules.cpp +++ b/src/dfm-base/utils/loggerrules.cpp @@ -20,7 +20,7 @@ void LoggerRules::initLoggerRules() qunsetenv("QT_LOGGING_RULES"); // set env - currentRules = logRules; + currentRules = QString(logRules); qCWarning(logDFMBase) << "Current system env log rules:" << logRules; logRules = DConfigManager::instance()->value(kDefaultCfgPath, "log_rules").toByteArray(); diff --git a/src/dfm-declarative/ActionMenu.qml b/src/dfm-declarative/ActionMenu.qml new file mode 100644 index 0000000000..10047dcbfa --- /dev/null +++ b/src/dfm-declarative/ActionMenu.qml @@ -0,0 +1,8 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +import QtQuick 2.15 + +Item { +} diff --git a/src/dfm-declarative/CMakeLists.txt b/src/dfm-declarative/CMakeLists.txt new file mode 100644 index 0000000000..8b10c04286 --- /dev/null +++ b/src/dfm-declarative/CMakeLists.txt @@ -0,0 +1,53 @@ +cmake_minimum_required(VERSION 3.10) + +# If do't define version number, specify the version number +set(VERSION "1.0.0" CACHE STRING "define project version") + +set(BASE_NAME declarative) +set(BIN_NAME dfm-${BASE_NAME}) + +if(NOT VERSION) + set(VERSION "1.0.0") +endif() + +if(NOT PROJECT_VERSION_MAJOR) + set(PROJECT_VERSION_MAJOR 1) +endif() + +# signals and slots keyword is disable, use Q_SIGNALS and Q_SLOTS instead +add_compile_definitions(QT_NO_SIGNALS_SLOTS_KEYWORDS) + +# add qrc resources +set(QRC_FILES) + +if(DFM_BUILD_WITH_QT6) + qt6_add_resources(QRC_RESOURCES ${QRC_FILES}) +else() + qt5_add_resources(QRC_RESOURCES ${QRC_FILES}) +endif() + +# add depends +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Quick REQUIRED) + +# TODO:放到公共目录? +# 通过 Qt cmake 接口注册组件 +qt_add_qml_module(${BIN_NAME} + URI org.dfm.${BASE_NAME} + VERSION 1.0 + SHARED + RESOURCE_PREFIX / + OUTPUT_DIRECTORY ${DFM_BUILD_PLUGIN_DIR}/qml/org/dfm/${BASE_NAME} + QML_FILES ActionMenu.qml +) + +target_include_directories(${BIN_NAME} PRIVATE ${PROJECT_SOURCE_DIR}) +target_link_libraries(${BIN_NAME} PUBLIC Qt6::Core Qt6::Quick) + +set_target_properties(${BIN_NAME} PROPERTIES + VERSION ${VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} +) + +# install module +install(DIRECTORY ${DFM_BUILD_PLUGIN_DIR}/qml/org/dfm/${BASE_NAME} DESTINATION ${DFM_QML_MODULE}/org/dfm) diff --git a/src/dfm-framework/CMakeLists.txt b/src/dfm-framework/CMakeLists.txt index a826f526a0..dd51e74a4f 100644 --- a/src/dfm-framework/CMakeLists.txt +++ b/src/dfm-framework/CMakeLists.txt @@ -11,9 +11,9 @@ file(GLOB_RECURSE SRCS CONFIGURE_DEPENDS "./*.cpp" ) -find_package(Qt5 COMPONENTS Core REQUIRED) -find_package(Qt5 COMPONENTS Concurrent REQUIRED) -find_package(Dtk COMPONENTS Core REQUIRED) +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Concurrent REQUIRED) +find_package(Dtk${DTK_VERSION_MAJOR} COMPONENTS Core REQUIRED) add_library(${BIN_NAME} SHARED ${INCLUDE_FILES} @@ -22,9 +22,9 @@ add_library(${BIN_NAME} SHARED target_link_libraries( ${BIN_NAME} - Qt5::Core - Qt5::Concurrent - ${DtkCore_LIBRARIES} + Qt${QT_VERSION_MAJOR}::Core + Qt${QT_VERSION_MAJOR}::Concurrent + Dtk${DTK_VERSION_MAJOR}::Core ) target_include_directories(${BIN_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/include) diff --git a/src/dfm-framework/event/eventdispatcher.cpp b/src/dfm-framework/event/eventdispatcher.cpp index c85ada30af..6a9f213eec 100644 --- a/src/dfm-framework/event/eventdispatcher.cpp +++ b/src/dfm-framework/event/eventdispatcher.cpp @@ -63,8 +63,8 @@ bool EventDispatcherManager::globalFiltered(EventType type, const QVariantList & { QReadLocker lk(&rwLock); - int size { globalFilterMap.size() }; - for (int i = 0; i != size; ++i) { + qsizetype size { globalFilterMap.size() }; + for (qsizetype i = 0; i != size; ++i) { auto key { globalFilterMap.keys()[i] }; if (key) { auto func { globalFilterMap.value(key) }; diff --git a/src/dfm-framework/lifecycle/lifecycle.cpp b/src/dfm-framework/lifecycle/lifecycle.cpp index d7c213c2bb..b43576ad4c 100644 --- a/src/dfm-framework/lifecycle/lifecycle.cpp +++ b/src/dfm-framework/lifecycle/lifecycle.cpp @@ -88,6 +88,20 @@ QList pluginMetaObjs(const std::function pluginSortedMetaObjs(const std::function &cond) +{ + const auto &queue { pluginManager->loadQueue() }; + if (!cond) + return queue; + + QList ptrs; + std::copy_if(queue.begin(), queue.end(), std::back_inserter(ptrs), + [cond](const PluginMetaObjectPointer &ptr) { + return cond(ptr); + }); + return ptrs; +} + /*! * \brief LifeCycle::readPlugins read meta data of all plugins * \pre { diff --git a/src/dfm-framework/lifecycle/pluginmanager.cpp b/src/dfm-framework/lifecycle/pluginmanager.cpp index 554da3a78a..74c4954871 100644 --- a/src/dfm-framework/lifecycle/pluginmanager.cpp +++ b/src/dfm-framework/lifecycle/pluginmanager.cpp @@ -132,3 +132,8 @@ QQueue PluginManager::readQueue() const { return d->readQueue; } + +QQueue PluginManager::loadQueue() const +{ + return d->loadQueue; +} diff --git a/src/dfm-framework/lifecycle/pluginmetaobject.cpp b/src/dfm-framework/lifecycle/pluginmetaobject.cpp index 6573052a4e..bc16aff208 100644 --- a/src/dfm-framework/lifecycle/pluginmetaobject.cpp +++ b/src/dfm-framework/lifecycle/pluginmetaobject.cpp @@ -5,6 +5,7 @@ #include "private/pluginmetaobject_p.h" #include +#include #include @@ -95,6 +96,14 @@ QString PluginMetaObject::errorString() const return d->error; } +/*! + * \return 返回 QML Applet 组件元信息列表 + */ +QList PluginMetaObject::quickMetaData() const +{ + return d->quickMetaList; +} + PluginMetaObject::PluginMetaObject() : d(new PluginMetaObjectPrivate(this)) { @@ -211,6 +220,22 @@ Q_CORE_EXPORT QDebug operator<<(QDebug out, const DPF_NAMESPACE::PluginMetaObjec return out; } +/*! + * \brief 重定向全局Debug打印 PluginQuickInfo 对象的函数 + */ +Q_CORE_EXPORT QDebug operator<<(QDebug out, const DPF_NAMESPACE::PluginQuickMetaData &quickMeta) +{ + DPF_USE_NAMESPACE + out << "PluginQuickInfo(" << QString("0x%0").arg(qint64(&quickMeta), 0, 16) << "){"; + out << kQuickUrl << " : " << quickMeta.url() << "; "; + out << kQuickId << " : " << quickMeta.id() << "; "; + out << kQuickType << " : " << quickMeta.type() << "; "; + out << kQuickParent << " : " << quickMeta.parent() << "; "; + out << kQuickApplet << " : " << quickMeta.applet() << "; "; + out << "}"; + return out; +} + /*! * \brief operator << * 重定向全局Debug入口函数 diff --git a/src/dfm-framework/lifecycle/pluginquickmetadata.cpp b/src/dfm-framework/lifecycle/pluginquickmetadata.cpp new file mode 100644 index 0000000000..bd063b609b --- /dev/null +++ b/src/dfm-framework/lifecycle/pluginquickmetadata.cpp @@ -0,0 +1,108 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include "private/pluginquickmetadata_p.h" + +DPF_BEGIN_NAMESPACE + +PluginQuickMetaData::PluginQuickMetaData() + : d(new PluginQuickData) +{ +} + +/*! + * \class PluginQuickMetaData + * \brief 插件 Quick 组件元信息 + * \details 提供 Quikc 组件的基础信息 + * + * \list + * \li url QML 组件文件的路径,通过此信息加载组件 + * \li id 组件ID + * \li plugin 插件ID + * \li type 组件类型,对应 Applet::Flag + * \li parent 当前组件的父组件,用于查找依赖关系,此字段以 [插件ID].[组件ID] 的格式填入 + * \li applet 当前组件拓展 Applet 的工厂构造函数查找标识,用于查找创建插件注册的 Applet + * \endlist + */ +PluginQuickMetaData::PluginQuickMetaData( + const QUrl &url, const QString &id, const QString &plugin, const QString &type, const QString &parent, const QString &applet) + : d(new PluginQuickData) +{ + d->quickUrl = url; + d->quickId = id; + d->plugin = plugin; + d->quickType = type; + d->quickParent = parent; + d->quickApplet = applet; +} + +QUrl PluginQuickMetaData::url() const +{ + return d->quickUrl; +} + +QString PluginQuickMetaData::id() const +{ + return d->quickId; +} + +QString PluginQuickMetaData::plugin() const +{ + return d->plugin; +} + +QString PluginQuickMetaData::type() const +{ + return d->quickType; +} + +QString PluginQuickMetaData::parent() const +{ + return d->quickParent; +} + +QString PluginQuickMetaData::applet() const +{ + return d->quickApplet; +} + +PluginQuickMetaDataCreator::PluginQuickMetaDataCreator() { } + +void PluginQuickMetaDataCreator::create(const QString &plugin, const QString &id, const QUrl &url) +{ + metaPtr = PluginQuickMetaPtr::create(); + metaPtr->d->plugin = plugin; + metaPtr->d->quickId = id; + metaPtr->d->quickUrl = url; +} + +void PluginQuickMetaDataCreator::setType(const QString &type) +{ + if (metaPtr) { + metaPtr->d->quickType = type; + } +} + +void PluginQuickMetaDataCreator::setParent(const QString &parent) +{ + if (metaPtr) { + metaPtr->d->quickParent = parent; + } +} + +void PluginQuickMetaDataCreator::setApplet(const QString &applet) +{ + if (metaPtr) { + metaPtr->d->quickApplet = applet; + } +} + +PluginQuickMetaPtr PluginQuickMetaDataCreator::take() +{ + PluginQuickMetaPtr tempPtr(std::move(metaPtr)); + return tempPtr; +} + +DPF_END_NAMESPACE diff --git a/src/dfm-framework/lifecycle/private/pluginmanager_p.cpp b/src/dfm-framework/lifecycle/private/pluginmanager_p.cpp index 954ef97814..52552aee68 100644 --- a/src/dfm-framework/lifecycle/private/pluginmanager_p.cpp +++ b/src/dfm-framework/lifecycle/private/pluginmanager_p.cpp @@ -4,6 +4,7 @@ #include "pluginmetaobject_p.h" #include "pluginmanager_p.h" +#include "pluginquickmetadata_p.h" #include #include @@ -259,6 +260,50 @@ void PluginManagerPrivate::jsonToMeta(PluginMetaObjectPointer metaObject, const } metaObject->d->state = PluginMetaObject::kReaded; + + // QML 组件信息 + QJsonArray quickArray = metaData.value(kQuick).toArray(); + for (auto quickItr : quickArray) { + QJsonObject quick = quickItr.toObject(); + + QString quickParent = quick.value(kQuickParent).toString(); + // Quick plugin 的 parent 必须在 Depends 字段存在 + if (!quickParent.isEmpty()) { + QString parPlugin = quickParent.split('.').first(); + QList &depends = metaObject->d->depends; + QList::iterator findItr = std::find_if(depends.begin(), depends.end(), [&](const PluginDepend &depend) { + return depend.pluginName == parPlugin; + }); + + if (findItr == metaObject->d->depends.end()) { + qCWarning(logDPF) << QString("Quick plugin %1 not find parent %2 plugin name on Depends field!") + .arg(metaObject->d->name) + .arg(quickParent); + continue; + } + } + + // id url 不为空 + QString url = quick.value(kQuickUrl).toString(); + QString id = quick.value(kQuickId).toString(); + if (url.isEmpty() || id.isEmpty()) { + qCWarning(logDPF) << QString("Quick plugin's id %1 or url %2 is empty").arg(id).arg(url); + continue; + } + + PluginQuickMetaPtr quickMeta = PluginQuickMetaPtr::create(); + // QML Url = [插件绝对路径 plugin.path] / [插件名称 plugin.name] / [url] + QString pluginPath = QFileInfo(metaObject->fileName()).absolutePath(); + QString fullPath = pluginPath + QDir::separator() + metaObject->name() + QDir::separator() + url; + quickMeta->d->quickUrl = QUrl::fromLocalFile(fullPath); + quickMeta->d->quickId = id; + quickMeta->d->plugin = metaObject->name(); + quickMeta->d->quickType = quick.value(kQuickType).toString(); + quickMeta->d->quickApplet = quick.value(kQuickApplet).toString(); + quickMeta->d->quickParent = quickParent; + + metaObject->d->quickMetaList.append(quickMeta); + } } /*! diff --git a/src/dfm-framework/lifecycle/private/pluginmetaobject_p.h b/src/dfm-framework/lifecycle/private/pluginmetaobject_p.h index 3f7ec1a71a..836a1a48f0 100644 --- a/src/dfm-framework/lifecycle/private/pluginmetaobject_p.h +++ b/src/dfm-framework/lifecycle/private/pluginmetaobject_p.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -34,6 +35,18 @@ inline constexpr char kCustomData[] { "Custom" }; inline constexpr char kVirtualPluginMeta[] { "Meta" }; /// \brief kPluginDepends virtual plugin info list inline constexpr char kVirtualPluginList[] { "VirtualPlugins" }; +/// \brief kQuickUrl QML组件信息 +inline constexpr char kQuick[] { "Quick" }; +/// \brief kQuickUrl QML组件文件Url +inline constexpr char kQuickUrl[] { "Url" }; +/// \brief kQuickUrl QML组件文件ID +inline constexpr char kQuickId[] { "Id" }; +/// \brief kQuickUrl QML组件类型,可选 Containment | Window 空内容视为 Applet +inline constexpr char kQuickType[] { "Type" }; +/// \brief kQuickUrl QML组件父组件名称(使用插件Name),必须在 "Depends" 字段中存在 +inline constexpr char kQuickParent[] { "Parent" }; +/// \brief kQuickUrl QML组件拓展Applet 需在 SchemeFactory 注册 +inline constexpr char kQuickApplet[] { "Applet" }; class PluginMetaObject; class PluginMetaObjectPrivate @@ -59,6 +72,7 @@ class PluginMetaObjectPrivate QSharedPointer plugin; QSharedPointer loader; QVariantMap customData; + QList quickMetaList; explicit PluginMetaObjectPrivate(PluginMetaObject *q) : q(q), loader(new QPluginLoader(nullptr)) diff --git a/src/dfm-framework/lifecycle/private/pluginquickmetadata_p.h b/src/dfm-framework/lifecycle/private/pluginquickmetadata_p.h new file mode 100644 index 0000000000..88ffa2769f --- /dev/null +++ b/src/dfm-framework/lifecycle/private/pluginquickmetadata_p.h @@ -0,0 +1,28 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef PLUGINQUICKMETADATA_P_H +#define PLUGINQUICKMETADATA_P_H + +#include + +#include +#include + +DPF_BEGIN_NAMESPACE + +class PluginQuickData +{ +public: + QUrl quickUrl; + QString quickId; + QString plugin; + QString quickType; + QString quickParent; + QString quickApplet; +}; + +DPF_END_NAMESPACE + +#endif // PLUGINQUICKMETADATA_P_H diff --git a/src/dfm-gui/CMakeLists.txt b/src/dfm-gui/CMakeLists.txt new file mode 100644 index 0000000000..4d3c1acd1a --- /dev/null +++ b/src/dfm-gui/CMakeLists.txt @@ -0,0 +1,124 @@ +cmake_minimum_required(VERSION 3.10) + +# If do't define version number, specify the version number +set (VERSION "1.0.0" CACHE STRING "define project version") + +set(BIN_NAME dfm-gui) + +if (NOT VERSION) + set(VERSION "1.0.0") +endif() + +if (NOT PROJECT_VERSION_MAJOR) + set(PROJECT_VERSION_MAJOR 1) +endif() + +# signals and slots keyword is disable, use Q_SIGNALS and Q_SLOTS instead +add_compile_definitions(QT_NO_SIGNALS_SLOTS_KEYWORDS) +add_compile_definitions(THUMBNAIL_TOOL_DIR="${DFM_THUMBNAIL_TOOL}") + +# add qrc resources +set(QRC_FILES) + +if(DFM_BUILD_WITH_QT6) + qt6_add_resources(QRC_RESOURCES ${QRC_FILES}) +else() + qt5_add_resources(QRC_RESOURCES ${QRC_FILES}) +endif() + +# add code +file(GLOB_RECURSE INCLUDE_FILES CONFIGURE_DEPENDS "${PROJECT_SOURCE_DIR}/include/${BIN_NAME}/*") +file(GLOB_RECURSE SRCS CONFIGURE_DEPENDS + "./*.h" + "./*.hpp" + "./*.cpp" +) + +# add depends +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Quick REQUIRED) +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Concurrent REQUIRED) + +# for generating middle source files of SettingsTemplate to translate. +set(TRANS_OF_SETTINGS_CPP) +set (DTK_SETTINGS_TOOLS_EXECUTABLE ${DTKCORE_TOOL_DIR}/dtk-settings) +if (EXISTS ${DTK_SETTINGS_TOOLS_EXECUTABLE}) + FILE (GLOB SETTING_TEMPALTE_FILES + "${CMAKE_CURRENT_SOURCE_DIR}/qrc/configure/*.js") + + foreach(temp ${SETTING_TEMPALTE_FILES}) +# message("---- found template: ${temp}") + string(REPLACE ".js" "-trans.cpp" TARGET_CPP ${temp}) +# message("---- convert to ${TARGET_CPP}") + execute_process(COMMAND ${DTK_SETTINGS_TOOLS_EXECUTABLE} ${temp} -o ${TARGET_CPP}) + + string(REPLACE "/" ";" PATH_FRAGS ${TARGET_CPP}) + list(GET PATH_FRAGS -1 FUNC_NAME) + string(REPLACE ".cpp" "" FUNC_NAME ${FUNC_NAME}) + string(REPLACE "-" "_" FUNC_NAME ${FUNC_NAME}) + execute_process(COMMAND sed -i "5s/GenerateSettingTranslate/${FUNC_NAME}/" ${TARGET_CPP}) + + list(APPEND TRANS_OF_SETTINGS_CPP ${TARGET_CPP}) + endforeach() + +# message(">>>> cpp source files for translating are generated: ${TRANS_OF_SETTINGS_CPP}") + list(APPEND TRANS_OF_SETTINGS_CPP + ${CMAKE_CURRENT_SOURCE_DIR}/qrc/configure/global-setting-template-manully-trans.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/qrc/configure/global-setting-template-dfmio-trans.cpp) +endif() + +# build +add_library(${BIN_NAME} + SHARED + ${QRC_RESOURCES} + ${INCLUDE_FILES} + ${SRCS} +) + +target_link_libraries(${BIN_NAME} PUBLIC + Qt${QT_VERSION_MAJOR}::Core + Qt${QT_VERSION_MAJOR}::Quick + Qt${QT_VERSION_MAJOR}::Concurrent + DFM::base +) + +target_include_directories(${BIN_NAME} PUBLIC + ${PROJECT_SOURCE_DIR}/include + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ) + +set(ShareDir ${CMAKE_INSTALL_PREFIX}/share/dde-file-manager) # also use for install +target_compile_definitions( + ${BIN_NAME} + PRIVATE + APPSHAREDIR="${ShareDir}" +) + +add_library(DFM::gui ALIAS ${BIN_NAME}) + +set_target_properties(${BIN_NAME} PROPERTIES + VERSION ${VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} +) + +# install library file +install(TARGETS ${BIN_NAME} LIBRARY DESTINATION ${LIB_INSTALL_DIR}) +# install header files +install(DIRECTORY + ${PROJECT_SOURCE_DIR}/include/${BIN_NAME} + DESTINATION include + FILES_MATCHING PATTERN "*.h" +) + +# for pc file config +set(PC_LIBS_PRIVATE Qt${QT_VERSION_MAJOR}Core) +set(PC_REQ_PRIVATE) +set(PC_REQ_PUBLIC) + +# config pkgconfig file +configure_file(${PROJECT_SOURCE_DIR}/assets/dev/${BIN_NAME}/${BIN_NAME}.pc.in ${BIN_NAME}.pc @ONLY) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${BIN_NAME}.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) + +# config cmake file +configure_file(${PROJECT_SOURCE_DIR}/assets/dev/${BIN_NAME}/${BIN_NAME}Config.cmake.in ${BIN_NAME}Config.cmake @ONLY) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${BIN_NAME}Config.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${BIN_NAME}) diff --git a/src/dfm-gui/applet.cpp b/src/dfm-gui/applet.cpp new file mode 100644 index 0000000000..c6da4561a9 --- /dev/null +++ b/src/dfm-gui/applet.cpp @@ -0,0 +1,158 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include +#include "applet_p.h" + +#include + +DFMGUI_BEGIN_NAMESPACE + +AppletPrivate::AppletPrivate(Applet *q) + : q_ptr(q) +{ +} + +AppletPrivate::~AppletPrivate() +{ + // 释放关联的 QQuickItem + if (rootObject && QJSEngine::CppOwnership == QJSEngine::objectOwnership(rootObject)) { + rootObject->deleteLater(); + } +} + +/*! + * \brief 设置 Applet 关联的 QML 组件 \a item ,仅可设置一次 + */ +void AppletPrivate::setRootObject(QObject *item) +{ + Q_ASSERT(nullptr == rootObject); + rootObject = item; + + Q_EMIT q_func()->rootObjectChanged(item); +} + +/*! + * \class Applet + * \brief 管理插件 QML 组件的最小单元,包含基础的组件信息. + * \details 使用此类在 C++ 代码中管理小组件,插件可派生 Applet 并注册对应的构造函数(SchemeFactory)。 + * 设计参考自 plasma-framework 和 dde-shell + * + * \sa AppletItem + */ +Applet::Applet(QObject *parent) + : QObject(parent), dptr(new AppletPrivate(this)) +{ +} + +Applet::Applet(AppletPrivate &dd, QObject *parent) + : QObject(parent), dptr(&dd) +{ +} + +Applet::~Applet() { } + +/*! + * \return 当前操作的文件路径 + */ +QUrl Applet::currentUrl() const +{ + return d_func()->currentUrl; +} + +/*! + * \brief 设置当前操作的文件路径 \a url + */ +void Applet::setCurrentUrl(const QUrl &url) +{ + Q_D(Applet); + if (d->currentUrl != url) { + d->currentUrl = url; + Q_EMIT currentUrlChanged(url); + } +} + +/*! + * \return Applet 标识,按派生类型分为 + * Applet 普通组件 + * Containment 容器组件 + * Panel 面板,用于顶层窗体 + */ +Applet::Flags Applet::flags() const +{ + return d_func()->flag; +} + +/*! + * \return Applet 对应的 QML 组件, + */ +QObject *Applet::rootObject() const +{ + return d_func()->rootObject; +} + +/*! + * \brief 返回当前 Applet 的容器 Containment , 若自身是容器则会返回当前对象 + * \return 容器指针 + */ +Containment *Applet::containment() const +{ + Containment *contain = qobject_cast(const_cast(this)); + if (contain) { + return contain; + } + contain = nullptr; + + QObject *parent = this->parent(); + + while (parent) { + Containment *tmp = qobject_cast(parent); + if (tmp) { + contain = tmp; + break; + } + parent = parent->parent(); + } + + return contain; +} + +/*! + * \return 返回 Applet 对应的插件名称,可用于获取信息创建 Applet + */ +QString Applet::plugin() const +{ + return d_func()->metaPtr->plugin(); +} + +/*! + * \return 返回 Applet 对应的组件ID,可用于获取信息创建 Applet + */ +QString Applet::id() const +{ + return d_func()->metaPtr->id(); +} + +/** + * @return 当前 Applet 对应的 QML 组件文件路径 + */ +QUrl Applet::componentUrl() const +{ + return d_func()->componentUrl; +} + +/*! + * \brief 设置当前 Applet 的 QML 组件文件为 \a url + */ +void Applet::setComponentUrl(const QUrl &url) +{ + Q_D(Applet); + if (d->componentUrl != url) { + d->componentUrl = url; + Q_EMIT componentUrlChanged(url); + } +} + +DFMGUI_END_NAMESPACE diff --git a/src/dfm-gui/applet_p.h b/src/dfm-gui/applet_p.h new file mode 100644 index 0000000000..6206aa09ae --- /dev/null +++ b/src/dfm-gui/applet_p.h @@ -0,0 +1,38 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef APPLET_P_H +#define APPLET_P_H + +#include +#include + +#include +#include +#include + +DFMGUI_BEGIN_NAMESPACE + +class AppletPrivate +{ + Q_DECLARE_PUBLIC(Applet) + +public: + explicit AppletPrivate(Applet *q); + virtual ~AppletPrivate(); + + void setRootObject(QObject *item); + + Applet *q_ptr; + QUrl currentUrl; // 当前 Applet 操作的文件 Url + + Applet::Flags flag = Applet::kUnknown; + QUrl componentUrl; // 加载的 QML 组件 Url + QPointer rootObject = nullptr; // Applet 对应的 QML 组件 + dpf::PluginQuickMetaPtr metaPtr; // Applet 对应元信息 +}; + +DFMGUI_END_NAMESPACE + +#endif // APPLET_P_H diff --git a/src/dfm-gui/appletfactory.cpp b/src/dfm-gui/appletfactory.cpp new file mode 100644 index 0000000000..113b08e3d8 --- /dev/null +++ b/src/dfm-gui/appletfactory.cpp @@ -0,0 +1,69 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include +#include + +DFMGUI_BEGIN_NAMESPACE + +/*! + * \class AppletFactory + * \brief 类似 SchemeFactory 提供拓展 Applet 类创建函数的注册管理 + */ + +AppletFactory::AppletFactory() +{ +} + +AppletFactory::~AppletFactory() +{ +} + +AppletFactory *AppletFactory::instance() +{ + static AppletFactory ins; + return &ins; +} + +bool AppletFactory::regCreator(const AppletFactory::Key &url, CreateFunc creator, QString *errorString) +{ + QString error; + dfmbase::FinallyUtil finally([&]() { + if (errorString) + *errorString = error; + }); + + if (constructList.contains(url)) { + error = "The current url has registered " + "the associated construction class"; + return false; + } + + constructList.insert(url, creator); + finally.dismiss(); + return true; +} + +AppletFactory::AppletPtr AppletFactory::create(const AppletFactory::Key &url, QString *errorString) +{ + QString error; + dfmbase::FinallyUtil finally([&]() { + if (errorString) + *errorString = error; + }); + + CreateFunc constantFunc = constructList.value(url); + if (!constantFunc) { + error = "url should be call registered 'regClass()' function " + "before create function"; + return nullptr; + } + finally.dismiss(); + AppletPtr info = constantFunc(url); + + return info; +} + +DFMGUI_END_NAMESPACE diff --git a/src/dfm-gui/appletitem.cpp b/src/dfm-gui/appletitem.cpp new file mode 100644 index 0000000000..21010e9377 --- /dev/null +++ b/src/dfm-gui/appletitem.cpp @@ -0,0 +1,94 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include +#include "applet_p.h" +#include "appletitem_p.h" + +#include + +DFMGUI_BEGIN_NAMESPACE + +AppletItemPrivate::AppletItemPrivate(AppletItem *q) + : q_ptr(q) +{ +} + +/*! + * \class AppletItem + * \brief Applet 对应的 Quick 组件,通过 Applet componentUrl 创建 + */ +AppletItem::AppletItem(QQuickItem *parent) + : QQuickItem(parent), dptr(new AppletItemPrivate(this)) +{ + connect(this, &QQuickItem::windowChanged, this, &AppletItem::itemWindowChanged); +} + +AppletItem::~AppletItem() { } + +Applet *AppletItem::applet() const +{ + return d_func()->applet; +} + +void AppletItem::setApplet(Applet *applet) +{ + d_func()->applet = applet; +} + +/*! + * \return 当前 Item 所在的顶层窗体 + */ +QQuickWindow *AppletItem::itemWindow() const +{ + return window(); +} + +/*! + * \brief 创建 \a applet componentUrl 对应的 AppletItem,若 componentUrl 指向的 + * QML 组件不基于 AppletItem ,则返回 nullptr . 类型为 Panel 的 Applet 同样 + * 不会创建(基于QQuickWindow) + * \return 创建的 AppletItem 指针 + */ +AppletItem *AppletItem::itemForApplet(Applet *applet) +{ + if (!applet) { + return nullptr; + } + + if (!((Applet::kApplet == applet->flags()) || (Applet::kContainment == applet->flags()))) { + return nullptr; + } + + if (applet->rootObject()) { + return qobject_cast(applet); + } + + if (qApp->closingDown()) { + return nullptr; + } + + SharedQmlEngine engine; + if (!engine.create(applet)) { + return nullptr; + } + if (!engine.completeCreation()) { + return nullptr; + } + + QObject *rootObject = engine.rootObject(); + if (rootObject) { + if (auto item = qobject_cast(rootObject)) { + applet->dptr->setRootObject(item); + return item; + } + + rootObject->deleteLater(); + } + + return nullptr; +} + +DFMGUI_END_NAMESPACE diff --git a/src/dfm-gui/appletitem_p.h b/src/dfm-gui/appletitem_p.h new file mode 100644 index 0000000000..aaf2e80441 --- /dev/null +++ b/src/dfm-gui/appletitem_p.h @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef APPLETITEM_P_H +#define APPLETITEM_P_H + +#include "dfm-gui/appletitem.h" + +DFMGUI_BEGIN_NAMESPACE + +class AppletItemPrivate +{ + Q_DECLARE_PUBLIC(AppletItem) + Q_DISABLE_COPY(AppletItemPrivate) + +public: + explicit AppletItemPrivate(AppletItem *q); + + QPointer q_ptr; + Applet *applet = nullptr; +}; + +DFMGUI_END_NAMESPACE + +#endif // APPLETITEM_P_H diff --git a/src/dfm-gui/appletmanager.cpp b/src/dfm-gui/appletmanager.cpp new file mode 100644 index 0000000000..e2884762ac --- /dev/null +++ b/src/dfm-gui/appletmanager.cpp @@ -0,0 +1,402 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include +#include +#include +#include +#include "appletmanager_p.h" +#include "applet_p.h" + +#include +#include + +#include + +#include + +#include + +DFMGUI_BEGIN_NAMESPACE + +// Applet 类型字段 +inline constexpr char kApplet[] { "Applet" }; +// Applet 类型字段 - 容器 Containment +inline constexpr char kContainment[] { "Containment" }; +// Applet 类型字段 - 面板 Panel +inline constexpr char kPanel[] { "Panel" }; + +AppletManagerPrivate::AppletManagerPrivate(AppletManager *q) + : q_ptr(q), root(AppletTemplateNode::Ptr::create()) +{ +} + +/*! + * \brief 解析静态的插件中的 QML 组件依赖关系,这个关系由插件 json 数据决定, + * 静态的组件间包含关系,用于构建默认界面。 + * 注意同运行时依赖关系区分,程序运行时可将其它小组件嵌入到非静态依赖的父组件中, + * 这些依赖关系变更在 rootApplet (顶层节点)层级之下进行,目前未设计动态增加顶层节点。 + * e.g.: 从小组件列表选取一个小组件拖拽到桌面。 + * \sa initRootApplets() + */ +void AppletManagerPrivate::parseDefaultRootTemplates() +{ + Q_Q(AppletManager); + // 借用已调整加载顺序(loadQueue)的插件列表,仅获取 Quick plugin + QList quickPlugins = dpf::LifeCycle::pluginSortedMetaObjs( + [](const dpf::PluginMetaObjectPointer &ptr) -> bool { return !ptr->quickMetaData().isEmpty(); }); + QString errorString; + + for (const dpf::PluginMetaObjectPointer &metaPtr : quickPlugins) { + QList quickInfoList = metaPtr->quickMetaData(); + + for (const dpf::PluginQuickMetaPtr &infoPtr : quickInfoList) { + if (!q->registeApplet(infoPtr)) { + qCWarning(logDFMGui) << errorString; + } + } + } +} + +/*! + * \brief 从模板节点 \a node 创建对应的 Applet ,将按照模板树递归创建子 Applet + * \return 构造的 Applet + */ +Applet *AppletManagerPrivate::createAppletFromNode(const AppletTemplateNode::Ptr &node, QObject *parent) +{ + Q_Q(AppletManager); + if (!node || !node->quickInfoPtr) { + return nullptr; + } + + Applet *applet = q->createAppletFromInfo(node->quickInfoPtr, parent, &errorString); + if (!applet) { + return nullptr; + } + + if (applet->flags().testFlag(Applet::kContainment) && !node->childNode.isEmpty()) { + Containment *cotainment = applet->containment(); + for (auto childNode : std::as_const(node->childNode)) { + Applet *childApplet = createAppletFromNode(childNode, nullptr); + cotainment->appendApplet(childApplet); + } + } + + return applet; +} + +/*! + * \brief 释放顶层模板和缓存 + */ +void AppletManagerPrivate::clear() +{ + cacheIDToNode.clear(); + root->childNode.clear(); +} + +/*! + * \brief 将配置文件的 "type" 字段字符串 \a typeString 转换为 Applet 标识 + * \param typeString "type" 字段字符串 + * \return Applet 标识,标记配置的 Applet 界面控件类型 + */ +Applet::Flags AppletManagerPrivate::flagFromString(const QString &typeString) +{ + if (typeString.isEmpty() || kApplet == typeString) { + return Applet::kApplet; + } else if (kContainment == typeString) { + return Applet::kContainment; + } else if (kPanel == typeString) { + return Applet::kPanel; + } + + return Applet::kUnknown; +} + +/*! + * \class AppletManager + * \brief Applet 管理器 + * \details 用于从已加载的插件信息中提取 QQuick 组件信息,并按照组件依赖树创建信息模板 + * 后续的窗体创建时,根据模板创建对应的界面。 + * 运行时动态注册的 Applet 元信息将在下一次创建顶层 Applet 时体现。 + * + * 此类设计于: + * 1. 通过 DFM 事件系统动态注册通用组件 + * 2. 通过配置信息恢复界面组件配置(用于桌面) + */ + +AppletManager::AppletManager(QObject *parent) + : QObject(parent), dptr(new AppletManagerPrivate(this)) +{ +} + +AppletManager::~AppletManager() +{ + d_func()->clear(); +} + +AppletManager *AppletManager::instance() +{ + static AppletManager manager; + return &manager; +} + +/*! + * \brief 初始化 rootApplet (顶层节点) , \a configFile 为缓存配置文件, + * 设计在需要恢复子组件信息的应用中使用,例如 dde-desktop + */ +void AppletManager::initRootTemplates(const QString &configFile) +{ + // TODO: 用于桌面的配置信息获取 + Q_UNUSED(configFile) + + static std::once_flag flag; + std::call_once(flag, [this]() { d_func()->parseDefaultRootTemplates(); }); +} + +/*! + * \return 返回顶层 Window 节点的模板 ID 列表,用于后续 createWindowContainment() 创建容器 + */ +QList AppletManager::panelIdList() const +{ + Q_D(const AppletManager); + QList templates; + for (const auto &node : std::as_const(d->root->childNode)) { + if (node->flag.testFlag(Applet::kPanel)) { + templates.append(node->cachedId); + } + } + + return templates; +} + +/*! + * \brief 根据模板 ID 创建对应的 Panel + * \return Panel 指针 + */ +Panel *AppletManager::createPanel(const QString &templateId) +{ + Q_D(AppletManager); + if (auto node = d->cacheIDToNode.value(templateId)) { + if (node->flag.testFlag(Applet::kPanel)) { + std::unique_ptr applet(d->createAppletFromNode(node, nullptr)); + if (!applet) { + return nullptr; + } + + if (Panel *panel = qobject_cast(applet.get())) { + applet.release(); + return panel; + } + + d->errorString = QString("%1 is not based on class panel").arg(templateId); + } else { + d->errorString = QString("%1 is not panel").arg(templateId); + } + } else { + d->errorString = QString("Not found %1 in applet template.").arg(templateId); + } + + return nullptr; +} + +/*! + * \brief 根据插件名和组件 ID 查找创建对应的 Panel + * \return Panel 指针 + */ +Panel *AppletManager::createPanel(const QString &pluginName, const QString &quickId) +{ + return createPanel(d_func()->generateId(pluginName, quickId)); +} + +/*! + * \return 返回当前已注册的所有 Applet 的模板 ID 列表 + */ +QList AppletManager::allAppletTemplateIdList() const +{ + return d_func()->cacheIDToNode.keys(); +} + +/*! + * \brief 根据模板 ID 查找创建对应的 Applet + * 会遍历 Applet 的子节点查找创建 + * \return Applet 指针 + */ +Applet *AppletManager::createApplet(const QString &templateId, QObject *parent) +{ + Q_D(AppletManager); + if (auto node = d->cacheIDToNode.value(templateId)) { + return d->createAppletFromNode(node); + } + + return nullptr; +} + +/*! + * \brief 根据插件名和组件 ID 查找创建对应的 Applet + * \return Applet 指针 + */ +Applet *AppletManager::createApplet(const QString &pluginName, const QString &quickId, QObject *parent) +{ + return createApplet(d_func()->generateId(pluginName, quickId), parent); +} + +/*! + * \return 返回最后一次调用的错误信息 + */ +QString AppletManager::lastError() const +{ + return d_func()->errorString; +} + +/*! + * \brief 根据 Quick 组件元信息注册到 Applet 模板树中并返回结果,下一此创建此 Quick 组件的顶层 Panel 时, + * 将包含其对应的 Applet . + * \return 是否注册成功,若注册失败,错误信息会写入 \a errorString + */ +bool AppletManager::registeApplet(const dpf::PluginQuickMetaPtr &infoPtr) +{ + Q_D(AppletManager); + if (!infoPtr || infoPtr->plugin().isEmpty() || infoPtr->id().isEmpty() || infoPtr->url().isEmpty()) { + d->errorString = QStringLiteral("Invalid plugin quick meta info."); + return false; + } + + QString generatedId = d->generateId(infoPtr->plugin(), infoPtr->id()); + Applet::Flags flag = d->flagFromString(infoPtr->type()); + if (Applet::kUnknown == flag) { + d->errorString = QString("Unknown applet type %1.").arg(infoPtr->type()); + return false; + } + + if (infoPtr->parent().isEmpty()) { + if (flag.testFlag(Applet::kContainment)) { + if (!d->cacheIDToNode.contains(generatedId)) { + auto node = AppletTemplateNode::Ptr::create(); + node->flag = flag; + node->cachedId = generatedId; + node->quickInfoPtr = infoPtr; + node->parent = d->root.toWeakRef(); + d->root->childNode.append(node); + d->cacheIDToNode.insert(generatedId, node); + return true; + } + + d->errorString = QString("duplicate id %1").arg(generatedId); + } else { + // 顶层节点必须是容器 + d->errorString = QString("root applet must be containment"); + } + + } else { + if (auto parNode = d->cacheIDToNode.value(infoPtr->parent())) { + if (flag.testFlag(Applet::kPanel)) { + d->errorString = QString("Window must be root containment"); + + } else if (!d->cacheIDToNode.contains(generatedId)) { + auto node = AppletTemplateNode::Ptr::create(); + node->flag = flag; + node->cachedId = generatedId; + node->quickInfoPtr = infoPtr; + node->parent = parNode.toWeakRef(); + parNode->childNode.append(node); + d->cacheIDToNode.insert(generatedId, node); + return true; + + } else { + d->errorString = QString("duplicate id %1").arg(generatedId); + } + + } else { + // 未查找到父组件 + d->errorString = QString("not find parent %1").arg(infoPtr->parent()); + } + } + + return false; +} + +/*! + * \brief 将插件 \a pluginName 中的 \a quickId 组件从模板树中移除 + * \return 返回是否取消注册成功,false表面当前 Applet 模板树中没有找到对应的 Quick 组件元信息 + */ +bool AppletManager::unRegisteApplet(const QString &pluginName, const QString &quickId) +{ + Q_D(AppletManager); + QString generatedId = d->generateId(pluginName, quickId); + + auto findItr = d->cacheIDToNode.find(generatedId); + if (findItr != d->cacheIDToNode.end()) { + auto parNode = findItr.value()->parent.toStrongRef(); + if (parNode) { + parNode->childNode.removeOne(findItr.value()); + } + d->cacheIDToNode.erase(findItr); + return true; + } + + return false; +} + +/*! + * \brief 通过插件元信息 \a metaPtr 创建 Applet ,可用于创建重复的组件嵌入其他容器。 + * \return 创建的 Applet 若插件信息异常,将返回 false + */ +Applet *AppletManager::createAppletFromInfo(const dpf::PluginQuickMetaPtr &metaPtr, QObject *parent, QString *errorString) +{ + QString error; + dfmbase::FinallyUtil finally([&]() { + if (errorString) + *errorString = error; + }); + + if (!metaPtr) { + error = QStringLiteral("Input plugin quick meta info not valid."); + return nullptr; + } + + if (metaPtr->url().isEmpty() || metaPtr->id().isEmpty()) { + error = QString("Unkown applet id %1 or url %2 is empty.").arg(metaPtr->id()).arg(metaPtr->url().toString()); + return nullptr; + } + + Applet::Flags flag = AppletManagerPrivate::flagFromString(metaPtr->type()); + if (Applet::kUnknown == flag) { + error = QString("Unkown applet %1.%2 type %3").arg(metaPtr->plugin()).arg(metaPtr->id()).arg(metaPtr->type()); + return nullptr; + } + + Applet *appletPtr = nullptr; + if (!metaPtr->applet().isEmpty()) { + appletPtr = AppletFactory::instance()->create(metaPtr->applet(), &error); + if (flag.testFlag(Applet::kContainment) && !appletPtr->containment()) { + error = QString("Extendsion applet %1.%2 sets type to containment but not based on containment") + .arg(metaPtr->plugin()) + .arg(metaPtr->id()); + appletPtr->deleteLater(); + return nullptr; + } + } + + if (!appletPtr) { + switch (flag) { + case Applet::kApplet: + appletPtr = new Applet(parent); + break; + case Applet::kContainment: + appletPtr = new Containment(parent); + break; + case Applet::kPanel: + appletPtr = new Panel(parent); + break; + } + } + Q_ASSERT_X(appletPtr, "Applet load", "Create new applet failed!"); + + appletPtr->dptr->metaPtr = metaPtr; + appletPtr->setComponentUrl(metaPtr->url()); + return appletPtr; +} + +DFMGUI_END_NAMESPACE diff --git a/src/dfm-gui/appletmanager_p.h b/src/dfm-gui/appletmanager_p.h new file mode 100644 index 0000000000..8f4a437c73 --- /dev/null +++ b/src/dfm-gui/appletmanager_p.h @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef APPLETMANAGER_P_H +#define APPLETMANAGER_P_H + +#include +#include + +DFMGUI_BEGIN_NAMESPACE + +struct AppletTemplateNode +{ + typedef QSharedPointer Ptr; + + Applet::Flags flag = Applet::kUnknown; // 组件类型 + QString cachedId; // 缓存ID [插件名.组件名] + dpf::PluginQuickMetaPtr quickInfoPtr; // 记录的 Applet 加载信息 + QWeakPointer parent; + QList childNode; +}; + +class AppletManagerPrivate +{ + Q_DECLARE_PUBLIC(AppletManager) + +public: + explicit AppletManagerPrivate(AppletManager *q); + + void parseDefaultRootTemplates(); + Applet *createAppletFromNode(const AppletTemplateNode::Ptr &node, QObject *parent = nullptr); + void clear(); + + static Applet::Flags flagFromString(const QString &typeString); + inline QString generateId(const QString &pluginName, const QString &quickId) + { + return QString("%1.%2").arg(pluginName).arg(quickId); + } + + AppletManager *q_ptr; + AppletTemplateNode::Ptr root; // 顶层模板节点 + QHash cacheIDToNode; // 缓存信息,<缓存ID,元信息节点> + QString errorString; +}; + +DFMGUI_END_NAMESPACE + +#endif // APPLETMANAGER_P_H diff --git a/src/dfm-gui/attachedproperty.cpp b/src/dfm-gui/attachedproperty.cpp new file mode 100644 index 0000000000..9ffd913c9a --- /dev/null +++ b/src/dfm-gui/attachedproperty.cpp @@ -0,0 +1,68 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "attachedproperty_p.h" + +#include + +#include + +DFMGUI_BEGIN_NAMESPACE + +/*! + * \class AppletAttached + * \brief 用于 Quick 组件 AppletItem 在 QML 中访问对应的附加 Applet 属性 + * 使用 qmlRegisterExtendedType(uri, 1, 0, "Applet") 注册 + */ +AppletAttached::AppletAttached(QObject *parent) + : QObject(parent) +{ +} + +AppletAttached::~AppletAttached() { } + +Applet *AppletAttached::qmlAttachedProperties(QObject *object) +{ + AppletItem *item = qobject_cast(object); + if (item) { + return item->applet(); + } + Applet *applet = qobject_cast(object); + if (applet) { + return applet; + } + + QObject *parent = object->parent(); + while (parent) { + if (auto parItem = qobject_cast(parent)) { + return parItem->applet(); + } + + parent = parent->parent(); + } + + if (auto context = qmlContext(object)) { + return context->contextProperty("_dfm_applet").value(); + } + + return nullptr; +} + +/*! + * \class ContainmentAttached + * \brief 用于 Quick 组件 ContainmentItem 在 QML 中访问对应的附加 Containment 属性 + */ +ContainmentAttached::ContainmentAttached(QObject *parent) + : QObject(parent) +{ +} + +ContainmentAttached::~ContainmentAttached() { } + +Containment *ContainmentAttached::qmlAttachedProperties(QObject *object) +{ + return qobject_cast(AppletAttached::qmlAttachedProperties(object)); +} + +DFMGUI_END_NAMESPACE diff --git a/src/dfm-gui/attachedproperty_p.h b/src/dfm-gui/attachedproperty_p.h new file mode 100644 index 0000000000..fe53586be0 --- /dev/null +++ b/src/dfm-gui/attachedproperty_p.h @@ -0,0 +1,41 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef ATTACHEDPROPERTY_P_H +#define ATTACHEDPROPERTY_P_H + +#include +#include + +#include + +DFMGUI_BEGIN_NAMESPACE + +class AppletAttached : public QObject +{ + Q_OBJECT +public: + explicit AppletAttached(QObject *parent = nullptr); + ~AppletAttached() override; + + static Applet *qmlAttachedProperties(QObject *object); +}; + +class ContainmentAttached : public QObject +{ + Q_OBJECT +public: + explicit ContainmentAttached(QObject *parent = nullptr); + ~ContainmentAttached() override; + + static Containment *qmlAttachedProperties(QObject *object); +}; + +DFMGUI_END_NAMESPACE + +// 此宏标记QML附加属性,需要完整命名空间 +QML_DECLARE_TYPEINFO(DFMGUI_NAMESPACE::AppletAttached, QML_HAS_ATTACHED_PROPERTIES) +QML_DECLARE_TYPEINFO(DFMGUI_NAMESPACE::ContainmentAttached, QML_HAS_ATTACHED_PROPERTIES) + +#endif // ATTACHEDPROPERTY_P_H diff --git a/src/dfm-gui/containment.cpp b/src/dfm-gui/containment.cpp new file mode 100644 index 0000000000..5d823e67dc --- /dev/null +++ b/src/dfm-gui/containment.cpp @@ -0,0 +1,150 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include +#include "containment_p.h" + +#include +#include + +DFMGUI_BEGIN_NAMESPACE + +ContainmentPrivate::ContainmentPrivate(Containment *q) + : AppletPrivate(q) +{ + flag = Applet::kContainment; +} + +/*! + * \class Containment + * \brief 容器,管理多个 Applet , + */ +Containment::Containment(QObject *parent) + : Applet(*new ContainmentPrivate(this), parent) +{ +} + +Containment::Containment(ContainmentPrivate &dd, QObject *parent) + : Applet(dd, parent) +{ +} + +Containment::~Containment() { } + +/*! + * \brief 根据 QQuick 组件元信息 \a metaPtr 创建并追加对应的子 Applet + * \return 创建的子 Applet , 若创建失败则返回 nullptr + */ +Applet *Containment::createApplet(const dpf::PluginQuickMetaPtr &metaPtr) +{ + Applet *applet = AppletManager::instance()->createAppletFromInfo(metaPtr); + if (applet) { + appendApplet(applet); + } + + return applet; +} + +/*! + * \brief 在当前容器中添加 \a applet , 不会自动创建对应的 QQUickItem + */ +void Containment::appendApplet(Applet *applet) +{ + Q_D(Containment); + if (applet && !d->applets.contains(applet)) { + if (Containment *oldContain = applet->containment()) { + oldContain->removeApplet(applet); + } + + // TODO: 不是个好方案 + connect(applet, &Applet::rootObjectChanged, this, &Containment::appletRootObjectChanged); + + applet->setParent(this); + d->applets.append(applet); + + Q_EMIT appletAdded(applet); + Q_EMIT appletsChanged(); + } +} + +/*! + * \brief 在当前容器移除 \a applet ,对应的 QQuickItem 父对象被设置为 \a applet , + * 此函数不会销毁 \a applet ,注意生命周期管理 + */ +void Containment::removeApplet(Applet *applet) +{ + Q_D(Containment); + if (d->applets.contains(applet)) { + disconnect(applet, nullptr, this, nullptr); + applet->setParent(nullptr); + + if (applet->rootObject()) { + switch (applet->flags()) { + case Applet::kApplet: + Q_FALLTHROUGH(); + case Applet::kContainment: + if (auto item = qobject_cast(applet->rootObject())) { + item->setVisible(false); + } + break; + case Applet::kPanel: + if (auto window = qobject_cast(applet->rootObject())) { + window->setVisible(false); + } + break; + default: + break; + } + + // 调整父节点为 Applet + applet->rootObject()->setParent(applet); + } + + d->applets.removeOne(applet); + + Q_EMIT appletRemoved(applet); + Q_EMIT appletsChanged(); + } +} + +/*! + * \return 返回子 Applet 列表 + */ +QList Containment::applets() const +{ + return d_func()->applets; +} + +/*! + * \return 返回存在属性 \a property 值为 \a var 的 Applet + */ +Applet *Containment::appletForProperty(const QString &property, const QVariant &var) +{ + for (Applet *child : applets()) { + if (child && child->property(property.toStdString().c_str()) == var) { + return child; + } + } + + return nullptr; +} + +/*! + * \return 返回存在属性 \a property 值为 \a var 的 Applet 对应的 Qml 组件 + */ +QObject *Containment::objectForProperty(const QString &property, const QVariant &var) +{ + for (Applet *child : applets()) { + if (QObject *item = child->rootObject()) { + if (item->property(property.toStdString().c_str()) == var) { + return item; + } + } + } + + return nullptr; +} + +DFMGUI_END_NAMESPACE diff --git a/src/dfm-gui/containment_p.h b/src/dfm-gui/containment_p.h new file mode 100644 index 0000000000..dae25eeb3e --- /dev/null +++ b/src/dfm-gui/containment_p.h @@ -0,0 +1,25 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef CONTAINMENT_P_H +#define CONTAINMENT_P_H + +#include +#include "applet_p.h" + +DFMGUI_BEGIN_NAMESPACE + +class ContainmentPrivate : public AppletPrivate +{ + Q_DECLARE_PUBLIC(Containment) + +public: + explicit ContainmentPrivate(Containment *q); + + QList applets; +}; + +DFMGUI_END_NAMESPACE + +#endif // CONTAINMENT_P_H diff --git a/src/dfm-gui/containmentitem.cpp b/src/dfm-gui/containmentitem.cpp new file mode 100644 index 0000000000..b49d379636 --- /dev/null +++ b/src/dfm-gui/containmentitem.cpp @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include + +DFMGUI_BEGIN_NAMESPACE + +/*! + * \class ContainmentItem + * \brief Containment 对应的 Quick 组件,通过 Applet componentUrl 创建 + */ +ContainmentItem::ContainmentItem(QQuickItem *parent) + : AppletItem(parent) +{ +} + +ContainmentItem::~ContainmentItem() { } + +AppletItem *ContainmentItem::itemFor(Applet *applet) +{ + if (applet && applet->flags().testFlag(Applet::kContainment)) { + return AppletItem::itemForApplet(applet); + } + + return nullptr; +} + +DFMGUI_END_NAMESPACE diff --git a/src/dfm-gui/panel.cpp b/src/dfm-gui/panel.cpp new file mode 100644 index 0000000000..8455dd4ebd --- /dev/null +++ b/src/dfm-gui/panel.cpp @@ -0,0 +1,36 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include "panel_p.h" + +#include + +DFMGUI_BEGIN_NAMESPACE + +PanelPrivate::PanelPrivate(Panel *q) + : ContainmentPrivate(q) +{ + flag = Applet::kPanel; +} + +/*! + * \class Panel + * \brief 面板/窗体,用于弹出式的 QML 窗体 + * \note Panel 的 componentUrl 需要指向基于 QQuickWindow 的 QML 组件 + */ +Panel::Panel(QObject *parent) + : Containment(*new PanelPrivate(this), parent) +{ +} + +/*! + * \return 返回当前 Panel 关联的 QQuickWindow 窗体指针 + */ +QQuickWindow *Panel::window() const +{ + return qobject_cast(d_func()->rootObject); +} + +DFMGUI_END_NAMESPACE diff --git a/src/dfm-gui/panel_p.h b/src/dfm-gui/panel_p.h new file mode 100644 index 0000000000..1f90a2b901 --- /dev/null +++ b/src/dfm-gui/panel_p.h @@ -0,0 +1,23 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef PANEL_P_H +#define PANEL_P_H + +#include +#include "containment_p.h" + +DFMGUI_BEGIN_NAMESPACE + +class PanelPrivate : public ContainmentPrivate +{ + Q_DECLARE_PUBLIC(Panel) + +public: + explicit PanelPrivate(Panel *q); +}; + +DFMGUI_END_NAMESPACE + +#endif // PANEL_P_H diff --git a/src/dfm-gui/quickutils.cpp b/src/dfm-gui/quickutils.cpp new file mode 100644 index 0000000000..0bc35fe1fc --- /dev/null +++ b/src/dfm-gui/quickutils.cpp @@ -0,0 +1,18 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include + +DFMGUI_BEGIN_NAMESPACE + +/*! + * \class QuickUtils + * \brief 用于 QML 的通用工具类 + */ +QuickUtils::QuickUtils(QObject *parent) + : QObject { parent } +{ +} + +DFMGUI_END_NAMESPACE diff --git a/src/dfm-gui/sharedqmlengine.cpp b/src/dfm-gui/sharedqmlengine.cpp new file mode 100644 index 0000000000..4d553fa37b --- /dev/null +++ b/src/dfm-gui/sharedqmlengine.cpp @@ -0,0 +1,204 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include "sharedqmlengine_p.h" + +#include +#include +#include +#include + +Q_LOGGING_CATEGORY(logDFMGui, "org.deepin.dde.filemanager.lib.gui") + +DFMGUI_BEGIN_NAMESPACE + +QWeakPointer SharedQmlEnginePrivate::s_globalEngine; + +SharedQmlEnginePrivate::SharedQmlEnginePrivate(SharedQmlEngine *q) + : q_ptr(q), sharedEngine(engine()) +{ +} + +/*! + * \return QQmlComponent 加载完成后继续创建对应的 QML 组件对象,并向外抛出加载完成信号 + * createFinished() + */ +bool SharedQmlEnginePrivate::continueLoading() +{ + if (!component) { + qCWarning(logDFMGui) << "No QQmlComponent"; + return false; + } + + if (component->isReady()) { + rootObject = component->beginCreate(rootContext); + Q_EMIT q_ptr->createFinished(true); + return true; + } + + qCWarning(logDFMGui) << "Loading url failed:" << component->url() << "Error:" << component->errorString(); + Q_EMIT q_ptr->createFinished(false); + return false; +} + +QSharedPointer SharedQmlEnginePrivate::engine() +{ + if (auto sharedPtr = s_globalEngine.toStrongRef()) { + return sharedPtr; + } + + auto create = QSharedPointer::create(); + s_globalEngine = create.toWeakRef(); + // 初始化设置 + return create; +} + +/*! + * \class SharedQmlEngine + * \brief 共享的 QQmlEngine ,传入 url 或通过 Applet 的 compnentUrl() 创建 QML 组件。 + * \details 默认同步处理,通过 createFinished() 信号报告创建组件指针,通过调用 completeCreation() + * 完成创建。 + */ +SharedQmlEngine::SharedQmlEngine(QObject *parent) + : QObject(parent), dptr(new SharedQmlEnginePrivate(this)) +{ +} + +SharedQmlEngine::~SharedQmlEngine() +{ + delete d_func()->component; +} + +QObject *SharedQmlEngine::rootObject() const +{ + return d_func()->rootObject; +} + +QQmlContext *SharedQmlEngine::rootContext() const +{ + return d_func()->rootContext; +} + +QQmlComponent *SharedQmlEngine::mainComponent() const +{ + return d_func()->component; +} + +/*! + * \return 返回全局使用 QmlEngine + * \note 返回的共享指针不要进行持久化存储,在初始化时使用 WindowManager::engine() 以确定设置一致 + */ +QSharedPointer SharedQmlEngine::globalEngine() +{ + return SharedQmlEnginePrivate::engine(); +} + +/*! + * \brief 创建 \a applet 对应的 QQuickItem , \a async 为 false 时, + * 此函数*默认期望*同步加载URL信息,调用后通过 completeCreation() 初始化数据, + * \a async 为 true 时,请接收 createFinished() 信号,然后调用 completeCreation() + * 完成创建。 + * + * 组件的上下文信息 QQmlContext 创建后不会释放,跟随组件的生命周期, + * QQmlComponent 跟随 SharedQmlEngine 销毁。 + * \return 执行创建操作是否成功,\a applet 没有组件 Url 等异常时返回 false + */ +bool SharedQmlEngine::create(Applet *applet, bool async) +{ + Q_D(SharedQmlEngine); + if (!applet || applet->componentUrl().isEmpty()) { + return false; + } + + delete d->component; + d->component = new QQmlComponent(d->sharedEngine.get(), this); + QObject::connect(d->component, &QQmlComponent::statusChanged, this, &SharedQmlEngine::statusChanged); + d->component->loadUrl(applet->componentUrl(), async ? QQmlComponent::Asynchronous : QQmlComponent::PreferSynchronous); + + // 用于 QML 组件获取附加属性 + d->rootContext = new QQmlContext(d->sharedEngine.get(), applet); + d->rootContext->setContextProperty("_dfm_applet", applet); + d->curApplet = applet; + + if (d->component->isLoading()) { + QObject::connect(d->component, &QQmlComponent::statusChanged, this, [this]() { d_func()->continueLoading(); }); + } else { + d->continueLoading(); + } + + return true; +} + +/*! + * \brief 完成当前创建, \a args 会在创建前写入到 QML 组件中 + * \param args QML 组件参数 + */ +bool SharedQmlEngine::completeCreation(const QVariantMap &args) +{ + Q_D(SharedQmlEngine); + + if (!d->component) { + return false; + } + + if (d->component->status() != QQmlComponent::Ready || d->component->isError()) { + qCWarning(logDFMGui) << "Loading url failed:" << d->component->url() << "Error:" << d->component->errorString(); + return false; + } + + if (!d->rootObject) { + qCWarning(logDFMGui) << "Loading url failed:" << d->component->url() << "Error:" << d->component->errorString(); + return false; + } + + for (auto it = args.constBegin(); it != args.constEnd(); ++it) { + d->rootObject->setProperty(it.key().toUtf8().data(), it.value()); + } + + d->component->completeCreate(); + return true; +} + +/*! + * \brief 从 \a url 文件创建 Quick 对象,同时在完成创建前设置 QML 参数 \a args + * \return 创建的 Quick 对象,不成功返回 nullptr + */ +QObject *SharedQmlEngine::createObject(const QUrl &url, const QVariantMap &args) +{ + QSharedPointer engine = globalEngine(); + std::unique_ptr comp = std::make_unique(engine.get()); + comp->loadUrl(url); + if (comp->isError()) { + qCWarning(logDFMGui) << QString("Load url failed: %1").arg(comp->errorString()); + return nullptr; + } + + std::unique_ptr context = std::make_unique(engine.get(), engine->rootContext()); + std::unique_ptr object { comp->createWithInitialProperties(args, context.get()) }; + comp->completeCreate(); + + if (!comp->isError() && object) { + context.release(); + return object.release(); + } else { + qCWarning(logDFMGui) << QString("Load url failed: %1").arg(comp->errorString()); + return nullptr; + } +} + +/*! + * \return 返回当前URL文件加载状态 + */ +QQmlComponent::Status SharedQmlEngine::status() +{ + Q_D(SharedQmlEngine); + if (!d->component) { + return QQmlComponent::Null; + } + + return d->component->status(); +} + +DFMGUI_END_NAMESPACE diff --git a/src/dfm-gui/sharedqmlengine_p.h b/src/dfm-gui/sharedqmlengine_p.h new file mode 100644 index 0000000000..27a2ab4886 --- /dev/null +++ b/src/dfm-gui/sharedqmlengine_p.h @@ -0,0 +1,41 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef SHAREDQMLENGINE_P_H +#define SHAREDQMLENGINE_P_H + +#include +#include + +#include + +DFMGUI_BEGIN_NAMESPACE + +class SharedQmlEnginePrivate +{ + Q_DECLARE_PUBLIC(SharedQmlEngine) +public: + explicit SharedQmlEnginePrivate(SharedQmlEngine *q); + + bool continueLoading(); + static QSharedPointer engine(); + + SharedQmlEngine *q_ptr; + + bool delay = false; + Applet *curApplet = nullptr; + QObject *rootObject = nullptr; + QQmlContext *rootContext = nullptr; + QQmlComponent *component = nullptr; + + /*! + * \brief 如此设计是为手动控制程序退出时优先释放 QQmlEngine + */ + QSharedPointer sharedEngine; + static QWeakPointer s_globalEngine; +}; + +DFMGUI_END_NAMESPACE + +#endif // SHAREDQMLENGINE_P_H diff --git a/src/dfm-gui/windowhandle.cpp b/src/dfm-gui/windowhandle.cpp new file mode 100644 index 0000000000..a951aa5c68 --- /dev/null +++ b/src/dfm-gui/windowhandle.cpp @@ -0,0 +1,64 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include + +#include + +DFMGUI_BEGIN_NAMESPACE + +class FileManagerWindowHandleData : public QSharedData +{ +public: + QPointer panel; + QPointer window; + QString errorString; +}; + +/*! + * \class WindowHandle + * \brief 提供用于操作的窗口和Applet指针 + */ +WindowHandle::WindowHandle() + : data(new FileManagerWindowHandleData) +{ +} + +WindowHandle::WindowHandle(const QString &error) + : data(new FileManagerWindowHandleData) +{ + data->errorString = error; +} + +WindowHandle::WindowHandle(Panel *p, QQuickWindow *w) + : data(new FileManagerWindowHandleData) +{ + data->panel = p; + data->window = w; +} + +WindowHandle::~WindowHandle() { } + +bool WindowHandle::isValid() const +{ + return data->window && data->panel; +} + +QPointer WindowHandle::window() const +{ + return data->window; +} + +QPointer WindowHandle::panel() const +{ + return data->panel; +} + +QString WindowHandle::lastError() const +{ + return data->errorString; +} + +DFMGUI_END_NAMESPACE diff --git a/src/dfm-gui/windowmanager.cpp b/src/dfm-gui/windowmanager.cpp new file mode 100644 index 0000000000..1161450500 --- /dev/null +++ b/src/dfm-gui/windowmanager.cpp @@ -0,0 +1,196 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include +#include +#include +#include +#include +#include +#include "applet_p.h" +#include "attachedproperty_p.h" +#include "windowmanager_p.h" + +#include +#include +#include +#include +#include + +#include + +DFMGUI_BEGIN_NAMESPACE + +WindowManagerPrivate::WindowManagerPrivate(WindowManager *q) + : q_ptr(q), globalEngine(new SharedQmlEngine) +{ +} + +/*! + * \brief 异步加载 \a applet 对应的 QML 组件 + */ +void WindowManagerPrivate::asyncLoadQuickItem(Applet *applet) +{ + Q_Q(WindowManager); + SharedQmlEngine *tmpEngine = new SharedQmlEngine(q); + QObject::connect(tmpEngine, &SharedQmlEngine::createFinished, [=](bool success) { + if (success) { + tmpEngine->completeCreation(); + QObject *rootObject = tmpEngine->rootObject(); + if (AppletItem *item = qobject_cast(rootObject)) { + applet->dptr->setRootObject(item); + + if (auto containment = applet->containment()) { + rootObject->setParent(containment->rootObject()); + } + } else { + rootObject->deleteLater(); + } + } + + tmpEngine->deleteLater(); + }); + + tmpEngine->create(applet, true); + + if (auto containment = qobject_cast(applet)) { + for (Applet *child : containment->applets()) { + asyncLoadQuickItem(child); + } + } +} + +/*! + * \brief 应用退出时调用,手动释放全局的 QQmlEngine , + */ +void WindowManagerPrivate::aboutToQuit() +{ + // Note: QQmlApplicationEnginePrivate::cleanUp() 实例化的根对象必须在引擎之前销毁 + for (const WindowHandlePtr &handle : std::as_const(windows)) { + handle->window()->disconnect(globalEngine.get()); + + delete handle->window(); + delete handle->panel(); + } + windows.clear(); + + // 手动释放 + globalEngine.reset(); +} + +/*! + * \class WindowManager + * \brief 窗口管理类,创建 QML 窗体 + * \details 通过已加载的组件信息创建对应的窗体 + * + * \code + * QQuickWindow *window = WindowManager::instance()->createWindow("dfm-core", "MainWindow"); + * window->show(); + * \endcode + */ +WindowManager::WindowManager() + : dptr(new WindowManagerPrivate(this)) +{ + // 注册,使用 @uri ... 标记,以在 QtCreator 中方便访问 + // @uri org.dfm.base + const char *uri { "org.dfm.base" }; + qmlRegisterModule(uri, 1, 0); + qmlRegisterUncreatableType(uri, 1, 0, "Applet", "Applet attached"); + qmlRegisterExtendedType(uri, 1, 0, "Applet"); + qmlRegisterUncreatableType(uri, 1, 0, "Containment", "Containment attached"); + qmlRegisterExtendedType(uri, 1, 0, "Containment"); + qmlRegisterType(uri, 1, 0, "AppletItem"); + qmlRegisterType(uri, 1, 0, "ContainmentItem"); + + // 工具类,生命周期由 WindowManager 管理 + QuickUtils *globalUtils = new QuickUtils(this); + qmlRegisterSingletonInstance(uri, 1, 0, "QuickUtils", globalUtils); + + // 退出时清理界面和 QQmlengine + connect(qApp, &QCoreApplication::aboutToQuit, this, [this]() { + Q_D(WindowManager); + d->aboutToQuit(); + }); +} + +WindowManager::~WindowManager() { } + +WindowManager *WindowManager::instance() +{ + static WindowManager manager; + return &manager; +} + +/*! + * \return 返回当前界面使用的全局 QQmlEngine + */ +QSharedPointer WindowManager::engine() const +{ + Q_D(const WindowManager); + if (d->globalEngine) { + return d->globalEngine->globalEngine(); + } + + return {}; +} + +/*! + * \brief 根据传入的插件 \a pluginName 和组件 \a quickId 信息查找并创建对应的主窗体,\a var 为初始化时传递给主窗体组件的参数 + * \return 创建的 QQuickWindow 和 Panel,无法创建返回空的 Handle + */ +WindowHandlePtr WindowManager::createWindow(const QString &pluginName, const QString &quickId, const QVariantMap &var) +{ + Q_D(WindowManager); + // 首次进入初始化 + AppletManager::instance()->initRootTemplates(); + + std::unique_ptr panel { AppletManager::instance()->createPanel(pluginName, quickId) }; + if (!panel) { + return WindowHandlePtr::create("Create panel failed."); + } + + SharedQmlEngine engine; + if (!engine.create(panel.get())) { + return WindowHandlePtr::create("Load url failed."); + } + if (!engine.completeCreation(var)) { + return WindowHandlePtr::create("Complele compoment creation failed."); + } + // rootObject 父对象已设为 panel + QQuickWindow *window = qobject_cast(engine.rootObject()); + if (!window) { + return WindowHandlePtr::create("Window's base component is not QQuickWindow"); + } + panel->dptr->setRootObject(window); + + // 异步创建子节点 + for (auto child : panel->applets()) { + d->asyncLoadQuickItem(child); + } + + connect(window, &QQuickWindow::destroyed, this, [this](QObject *obj) { + Q_D(WindowManager); + if (auto view = qobject_cast(obj)) { + WindowHandlePtr handle = d->windows.take(view); + if (handle->panel()) { + handle->panel()->deleteLater(); + } + } + }); + + WindowHandlePtr handle = WindowHandlePtr::create(panel.release(), window); + d->windows.insert(window, handle); + return handle; +} + +void WindowManager::showWindow(const WindowHandlePtr &handle) +{ + if (handle && handle->isValid()) { + handle->window()->show(); + Q_EMIT handle->panel()->currentUrlChanged(handle->panel()->currentUrl()); + } +} + +DFMGUI_END_NAMESPACE diff --git a/src/dfm-gui/windowmanager_p.h b/src/dfm-gui/windowmanager_p.h new file mode 100644 index 0000000000..71e8186da9 --- /dev/null +++ b/src/dfm-gui/windowmanager_p.h @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef WINDOWMANAGER_P_H +#define WINDOWMANAGER_P_H + +#include +#include +#include + +DFMGUI_BEGIN_NAMESPACE + +class WindowManagerPrivate +{ + Q_DECLARE_PUBLIC(WindowManager) +public: + explicit WindowManagerPrivate(WindowManager *q); + ~WindowManagerPrivate() = default; + + void asyncLoadQuickItem(Applet *applet); + void aboutToQuit(); + + QPointer q_ptr; + QScopedPointer globalEngine; // 用于资源管理的 QmlEngine 对象 + QMap windows; // 当前已创建的 Window 和 Panel +}; + +DFMGUI_END_NAMESPACE + +#endif // WINDOWMANAGER_P_H diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt index 75eb980924..fe895d0554 100644 --- a/src/plugins/CMakeLists.txt +++ b/src/plugins/CMakeLists.txt @@ -3,8 +3,8 @@ cmake_minimum_required(VERSION 3.10) # add sub dir for business plugins add_subdirectory(filemanager) -add_subdirectory(filedialog) -add_subdirectory(desktop) -add_subdirectory(common) -add_subdirectory(daemon) -add_subdirectory(server) +# add_subdirectory(filedialog) +# add_subdirectory(desktop) +# add_subdirectory(common) +# add_subdirectory(daemon) +# add_subdirectory(server) diff --git a/src/plugins/common/core/dfmplugin-fileoperations/CMakeLists.txt b/src/plugins/common/core/dfmplugin-fileoperations/CMakeLists.txt index 423b0de5f4..f087872de8 100644 --- a/src/plugins/common/core/dfmplugin-fileoperations/CMakeLists.txt +++ b/src/plugins/common/core/dfmplugin-fileoperations/CMakeLists.txt @@ -50,3 +50,4 @@ install(TARGETS ${DFM_PLUGIN_COMMON_CORE_DIR} ) INSTALL_DCONFIG("org.deepin.dde.file-manager.operations.json") + diff --git a/src/plugins/filemanager/CMakeLists.txt b/src/plugins/filemanager/CMakeLists.txt index bddc716592..6b44bb55c0 100644 --- a/src/plugins/filemanager/CMakeLists.txt +++ b/src/plugins/filemanager/CMakeLists.txt @@ -3,16 +3,16 @@ cmake_minimum_required(VERSION 3.10) # add sub dir for business plugins add_subdirectory(core/dfmplugin-core) -add_subdirectory(core/dfmplugin-recent) +# add_subdirectory(core/dfmplugin-recent) add_subdirectory(core/dfmplugin-sidebar) add_subdirectory(core/dfmplugin-titlebar) -add_subdirectory(core/dfmplugin-workspace) +# add_subdirectory(core/dfmplugin-workspace) add_subdirectory(core/dfmplugin-detailspace) -add_subdirectory(core/dfmplugin-computer) -add_subdirectory(core/dfmplugin-trash) -add_subdirectory(dfmplugin-search) -add_subdirectory(dfmplugin-optical) -add_subdirectory(dfmplugin-vault) -add_subdirectory(dfmplugin-myshares) -add_subdirectory(dfmplugin-smbbrowser) -add_subdirectory(dfmplugin-avfsbrowser) +# add_subdirectory(core/dfmplugin-computer) +# add_subdirectory(core/dfmplugin-trash) +# add_subdirectory(dfmplugin-search) +# add_subdirectory(dfmplugin-optical) +# add_subdirectory(dfmplugin-vault) +# add_subdirectory(dfmplugin-myshares) +# add_subdirectory(dfmplugin-smbbrowser) +# add_subdirectory(dfmplugin-avfsbrowser) diff --git a/src/plugins/filemanager/core/dfmplugin-core/CMakeLists.txt b/src/plugins/filemanager/core/dfmplugin-core/CMakeLists.txt index abec8efcb4..d53790df3e 100644 --- a/src/plugins/filemanager/core/dfmplugin-core/CMakeLists.txt +++ b/src/plugins/filemanager/core/dfmplugin-core/CMakeLists.txt @@ -15,11 +15,12 @@ FILE(GLOB CORE_FILES ) -find_package(Dtk COMPONENTS Widget REQUIRED) +find_package(Dtk6 COMPONENTS Widget REQUIRED) add_library(${PROJECT_NAME} SHARED ${CORE_FILES} + FileWindow.qml ) set_target_properties(${PROJECT_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../../) @@ -31,8 +32,9 @@ target_include_directories(${PROJECT_NAME} target_link_libraries(${PROJECT_NAME} DFM::base + DFM::gui DFM::framework - ${DtkWidget_LIBRARIES} + Dtk6::Widget ) #install library file @@ -42,3 +44,6 @@ install(TARGETS DESTINATION ${DFM_PLUGIN_FILEMANAGER_CORE_DIR} ) + +#install qml file +INSTALL_PLUGIN_QUICK_MODULE(${DFM_PLUGIN_FILEMANAGER_CORE_DIR}) diff --git a/src/plugins/filemanager/core/dfmplugin-core/FileWindow.qml b/src/plugins/filemanager/core/dfmplugin-core/FileWindow.qml new file mode 100644 index 0000000000..214460424a --- /dev/null +++ b/src/plugins/filemanager/core/dfmplugin-core/FileWindow.qml @@ -0,0 +1,90 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +import QtQuick +import QtQml +import QtQuick.Controls +import QtQuick.Layouts +import org.dfm.base +import org.dfm.declarative +import org.deepin.dtk + +ApplicationWindow { + id: root + + DWindow.enabled: false + flags: Qt.Window | Qt.WindowMinMaxButtonsHint | Qt.WindowCloseButtonHint | Qt.WindowTitleHint + height: 600 + width: 800 + + // TODO: 待评估方案 + Containment.onAppletRootObjectChanged: appletItem => { + if (!appletItem) { + return; + } + if (undefined !== appletItem.widgetType) { + var control; + switch (appletItem.widgetType) { + case QuickUtils.Sidebar: + sidebar.contentItem = appletItem; + break; + case QuickUtils.Titlebar: + titlebar.target = appletItem; + break; + case QuickUtils.WorkSpace: + workspace.target = appletItem; + break; + case QuickUtils.DetailSpace: + detailspace.target = appletItem; + break; + default: + return; + } + console.warn("Append applet item", appletItem, appletItem.widgetType); + } else { + console.warn("Append invalid applet item", appletItem, appletItem.applet); + } + } + + // For local module test + ActionMenu { + } + + SplitView { + anchors.fill: parent + + Control { + id: sidebar + + contentItem: Rectangle { + width: 200 + } + } + + ColumnLayout { + SplitView.fillHeight: true + SplitView.fillWidth: true + + LayoutItemProxy { + id: titlebar + + } + + RowLayout { + Layout.fillHeight: true + Layout.fillWidth: true + + LayoutItemProxy { + id: workspace + + } + + LayoutItemProxy { + id: detailspace + + } + } + } + } +} diff --git a/src/plugins/filemanager/core/dfmplugin-core/core.json b/src/plugins/filemanager/core/dfmplugin-core/core.json index 2931066fca..b1a8b78996 100644 --- a/src/plugins/filemanager/core/dfmplugin-core/core.json +++ b/src/plugins/filemanager/core/dfmplugin-core/core.json @@ -10,5 +10,12 @@ "Description" : "The core plugin for the filemanager.", "UrlLink" : "https://www.uniontech.com", "Depends" : [ + ], + "Quick": [ + { + "Url": "FileWindow.qml", + "Id": "filewindow", + "Type": "Panel" + } ] } diff --git a/src/plugins/filemanager/core/dfmplugin-core/utils/corehelper.cpp b/src/plugins/filemanager/core/dfmplugin-core/utils/corehelper.cpp index 0702fd453d..5b7a7e909f 100644 --- a/src/plugins/filemanager/core/dfmplugin-core/utils/corehelper.cpp +++ b/src/plugins/filemanager/core/dfmplugin-core/utils/corehelper.cpp @@ -6,9 +6,9 @@ #include #include +#include #include - #include #include @@ -71,7 +71,15 @@ void CoreHelper::openWindow(const QUrl &url, const QVariant &opt) return; } - FMWindowsIns.showWindow(window); + // TODO + // FMWindowsIns.showWindow(window); + + auto handlePtr = DFMGUI_NAMESPACE::WindowManager::instance()->createWindow("dfmplugin-core", "filewindow"); + if (!handlePtr || !handlePtr->isValid()) { + fmCritical() << "Create dfmplugin-core filewindow failed"; + return; + } + DFMGUI_NAMESPACE::WindowManager::instance()->showWindow(handlePtr); } void CoreHelper::cacheDefaultWindow() @@ -157,8 +165,8 @@ bool CoreHelper::eventFilter(QObject *watched, QEvent *event) // we need all components to be displayed at the same time // when the window is showed if (type == QEvent::Show) { - int windowCount { FMWindowsIns.windowIdList().size() }; - int lazyCount { DPF_NAMESPACE::LifeCycle::lazyLoadList().size() }; + qsizetype windowCount { FMWindowsIns.windowIdList().size() }; + qsizetype lazyCount { DPF_NAMESPACE::LifeCycle::lazyLoadList().size() }; if (windowCount > 1 || lazyCount == 0) { fmDebug("Show full window, win count %d, lazy count %d", windowCount, lazyCount); window->removeEventFilter(this); diff --git a/src/plugins/filemanager/core/dfmplugin-detailspace/CMakeLists.txt b/src/plugins/filemanager/core/dfmplugin-detailspace/CMakeLists.txt index 8762c94545..17361b8fa2 100644 --- a/src/plugins/filemanager/core/dfmplugin-detailspace/CMakeLists.txt +++ b/src/plugins/filemanager/core/dfmplugin-detailspace/CMakeLists.txt @@ -13,11 +13,12 @@ FILE(GLOB DETAILSPCE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.json" ) -find_package(Dtk COMPONENTS Widget REQUIRED) +find_package(Dtk${DTK_VERSION_MAJOR} COMPONENTS Widget REQUIRED) add_library(${PROJECT_NAME} SHARED ${DETAILSPCE_FILES} + DetailSpace.qml ) set_target_properties(${PROJECT_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../../) @@ -40,3 +41,6 @@ install(TARGETS DESTINATION ${DFM_PLUGIN_FILEMANAGER_CORE_DIR} ) + +#Install qml file +INSTALL_PLUGIN_QUICK_MODULE(${DFM_PLUGIN_FILEMANAGER_CORE_DIR}) diff --git a/src/plugins/filemanager/core/dfmplugin-detailspace/DetailSpace.qml b/src/plugins/filemanager/core/dfmplugin-detailspace/DetailSpace.qml new file mode 100644 index 0000000000..3fe715f9f0 --- /dev/null +++ b/src/plugins/filemanager/core/dfmplugin-detailspace/DetailSpace.qml @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +import QtQuick +import QtQuick.Layouts +import org.dfm.base + +ContainmentItem { + property int widgetType: QuickUtils.DetailSpace + + Layout.fillHeight: true + implicitWidth: 200 + + ColumnLayout { + anchors.fill: parent + + Rectangle { + Layout.fillHeight: true + color: "lightyellow" + width: 200 + } + } + + Text { + color: "lightgray" + font.pointSize: 36 + text: "Detail Space" + } +} diff --git a/src/plugins/filemanager/core/dfmplugin-detailspace/detailspace.json b/src/plugins/filemanager/core/dfmplugin-detailspace/detailspace.json index 7f92cdb2e3..0dfb48681d 100644 --- a/src/plugins/filemanager/core/dfmplugin-detailspace/detailspace.json +++ b/src/plugins/filemanager/core/dfmplugin-detailspace/detailspace.json @@ -11,5 +11,12 @@ "UrlLink" : "https://www.uniontech.com", "Depends" : [ {"Name" : "dfmplugin-core", "Version": "1.0.0"} + ], + "Quick": [ + { + "Url" : "DetailSpace.qml", + "Id" : "detailspace", + "Parent" : "dfmplugin-core.filewindow" + } ] } diff --git a/src/plugins/filemanager/core/dfmplugin-detailspace/views/detailspacewidget.cpp b/src/plugins/filemanager/core/dfmplugin-detailspace/views/detailspacewidget.cpp index f0d41e8868..0511397acb 100644 --- a/src/plugins/filemanager/core/dfmplugin-detailspace/views/detailspacewidget.cpp +++ b/src/plugins/filemanager/core/dfmplugin-detailspace/views/detailspacewidget.cpp @@ -84,7 +84,7 @@ void DetailSpaceWidget::initializeUi() setBackgroundRole(QPalette::ColorRole::Base); QHBoxLayout *rvLayout = new QHBoxLayout(this); - rvLayout->setMargin(0); + rvLayout->setContentsMargins(0, 0, 0, 0); detailView = new DetailView(this); rvLayout->addWidget(detailView); setLayout(rvLayout); diff --git a/src/plugins/filemanager/core/dfmplugin-detailspace/views/detailview.cpp b/src/plugins/filemanager/core/dfmplugin-detailspace/views/detailview.cpp index 8cf9361705..35bfb66747 100644 --- a/src/plugins/filemanager/core/dfmplugin-detailspace/views/detailview.cpp +++ b/src/plugins/filemanager/core/dfmplugin-detailspace/views/detailview.cpp @@ -73,7 +73,7 @@ bool DetailView::insertCustomControl(int index, QWidget *widget) btn->setEnabled(false); btn->setFixedHeight(1); QVBoxLayout *vlayout = new QVBoxLayout(frame); - vlayout->setMargin(0); + vlayout->setContentsMargins(0, 0, 0, 0); vlayout->setSpacing(10); vlayout->addWidget(btn); vlayout->addWidget(widget); diff --git a/src/plugins/filemanager/core/dfmplugin-detailspace/views/filebaseinfoview.cpp b/src/plugins/filemanager/core/dfmplugin-detailspace/views/filebaseinfoview.cpp index d947032a28..6bd17e181b 100644 --- a/src/plugins/filemanager/core/dfmplugin-detailspace/views/filebaseinfoview.cpp +++ b/src/plugins/filemanager/core/dfmplugin-detailspace/views/filebaseinfoview.cpp @@ -109,9 +109,9 @@ void FileBaseInfoView::basicExpand(const QUrl &url) glayout->setSpacing(0); int row = 0; QList fields = fieldMap.keys(); - QSet fieldset = QSet::fromList(fields); - fields = fieldset.toList(); - qSort(fields.begin(), fields.end()); + QSet fieldset {fields.begin(), fields.end()}; + fields = {fieldset.begin(), fieldset.end()}; + std::sort(fields.begin(), fields.end()); for (BasicFieldExpandEnum &key : fields) { QList kvls = fieldMap.values(key); for (int i = kvls.count() - 1; i >= 0; --i) { diff --git a/src/plugins/filemanager/core/dfmplugin-sidebar/CMakeLists.txt b/src/plugins/filemanager/core/dfmplugin-sidebar/CMakeLists.txt index 48dce5a612..680ffb070a 100644 --- a/src/plugins/filemanager/core/dfmplugin-sidebar/CMakeLists.txt +++ b/src/plugins/filemanager/core/dfmplugin-sidebar/CMakeLists.txt @@ -44,11 +44,12 @@ FILE(GLOB SIDEBAR_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.json" ) endif() -find_package(Dtk COMPONENTS Widget REQUIRED) +find_package(Dtk${DTK_VERSION_MAJOR} COMPONENTS Widget REQUIRED) add_library(${PROJECT_NAME} SHARED ${SIDEBAR_FILES} + Sidebar.qml ) set_target_properties(${PROJECT_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../../) @@ -76,3 +77,5 @@ install(TARGETS include(${CMAKE_SOURCE_DIR}/install_dconfig.cmake) INSTALL_DCONFIG("org.deepin.dde.file-manager.sidebar.json") +# install qml file +INSTALL_PLUGIN_QUICK_MODULE(${DFM_PLUGIN_FILEMANAGER_CORE_DIR}) diff --git a/src/plugins/filemanager/core/dfmplugin-sidebar/Sidebar.qml b/src/plugins/filemanager/core/dfmplugin-sidebar/Sidebar.qml new file mode 100644 index 0000000000..93ca62cb7c --- /dev/null +++ b/src/plugins/filemanager/core/dfmplugin-sidebar/Sidebar.qml @@ -0,0 +1,47 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +import QtQuick +import QtQuick.Layouts +import Qt.labs.folderlistmodel 2.6 +import org.dfm.base + +AppletItem { + property int widgetType: QuickUtils.Sidebar + + Layout.fillHeight: true + implicitWidth: 200 + + ListView { + id: example + + anchors.fill: parent + clip: true + delegate: fileDelegate + model: folderModel + + Component { + id: fileDelegate + + Text { + text: fileName + } + } + + FolderListModel { + id: folderModel + + folder: "File:///home/uos" + nameFilters: ["*"] + showDirs: true + showDirsFirst: true + } + } + + Text { + color: "lightgray" + font.pointSize: 36 + text: "sidebar" + } +} diff --git a/src/plugins/filemanager/core/dfmplugin-sidebar/sidebar.json b/src/plugins/filemanager/core/dfmplugin-sidebar/sidebar.json index faae032fb2..fd6793c81f 100644 --- a/src/plugins/filemanager/core/dfmplugin-sidebar/sidebar.json +++ b/src/plugins/filemanager/core/dfmplugin-sidebar/sidebar.json @@ -11,5 +11,12 @@ "UrlLink" : "https://www.uniontech.com", "Depends" : [ {"Name" : "dfmplugin-core", "Version": "1.0.0"} + ], + "Quick" : [ + { + "Url" : "Sidebar.qml", + "Id" : "sidebar", + "Parent" : "dfmplugin-core.filewindow" + } ] } diff --git a/src/plugins/filemanager/core/dfmplugin-sidebar/treeviews/sidebarwidget.cpp b/src/plugins/filemanager/core/dfmplugin-sidebar/treeviews/sidebarwidget.cpp index 229c376d96..cc16f5fdc5 100644 --- a/src/plugins/filemanager/core/dfmplugin-sidebar/treeviews/sidebarwidget.cpp +++ b/src/plugins/filemanager/core/dfmplugin-sidebar/treeviews/sidebarwidget.cpp @@ -328,7 +328,7 @@ void SideBarWidget::initializeUi() setGraphicsEffect(effect); QHBoxLayout *hlayout = new QHBoxLayout(this); - hlayout->setMargin(0); + // hlayout->setMargin(0); hlayout->setSpacing(0); QWidget *leftSpacer = new QWidget(this); leftSpacer->setAutoFillBackground(true); @@ -337,7 +337,7 @@ void SideBarWidget::initializeUi() QVBoxLayout *vlayout = new QVBoxLayout(); vlayout->addWidget(sidebarView); - vlayout->setMargin(0); + // vlayout->setMargin(0); vlayout->setSpacing(0); hlayout->addWidget(leftSpacer); diff --git a/src/plugins/filemanager/core/dfmplugin-titlebar/CMakeLists.txt b/src/plugins/filemanager/core/dfmplugin-titlebar/CMakeLists.txt index 9bb1ee6178..8b0e940162 100644 --- a/src/plugins/filemanager/core/dfmplugin-titlebar/CMakeLists.txt +++ b/src/plugins/filemanager/core/dfmplugin-titlebar/CMakeLists.txt @@ -24,11 +24,13 @@ FILE(GLOB TITLEBAR_FILES "${CMAKE_CURRENT_SOURCE_DIR}/dialogs/dpcwidget/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/*.json" ) -find_package(Dtk COMPONENTS Widget REQUIRED) +find_package(Dtk${DTK_VERSION_MAJOR} COMPONENTS Widget REQUIRED) add_library(${PROJECT_NAME} SHARED ${TITLEBAR_FILES} + Titlebar.qml + LineSearch.qml ) set_target_properties(${PROJECT_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../../) @@ -51,3 +53,6 @@ install(TARGETS DESTINATION ${DFM_PLUGIN_FILEMANAGER_CORE_DIR} ) + +#install qml file +INSTALL_PLUGIN_QUICK_MODULE(${DFM_PLUGIN_FILEMANAGER_CORE_DIR}) diff --git a/src/plugins/filemanager/core/dfmplugin-titlebar/LineSearch.qml b/src/plugins/filemanager/core/dfmplugin-titlebar/LineSearch.qml new file mode 100644 index 0000000000..f99714d9f3 --- /dev/null +++ b/src/plugins/filemanager/core/dfmplugin-titlebar/LineSearch.qml @@ -0,0 +1,16 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +import QtQuick +import QtQuick.Controls + +TextEdit { + width: 200 + + TextField { + anchors.fill: parent + horizontalAlignment: TextInput.AlignCenter + placeholderText: qsTr("Search") + } +} diff --git a/src/plugins/filemanager/core/dfmplugin-titlebar/Titlebar.qml b/src/plugins/filemanager/core/dfmplugin-titlebar/Titlebar.qml new file mode 100644 index 0000000000..231aed454e --- /dev/null +++ b/src/plugins/filemanager/core/dfmplugin-titlebar/Titlebar.qml @@ -0,0 +1,116 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +import QtQuick +import QtQuick.Window +import QtQuick.Controls +import QtQuick.Layouts +import org.dfm.base +import org.deepin.dtk +import org.deepin.dtk.style 1.0 as DS + +AppletItem { + id: titlebar + + property int breadcrumbsHeight: 30 + // 控件类型 + property int widgetType: QuickUtils.Titlebar + + Layout.fillWidth: true + implicitHeight: DS.Style.titleBar.height + breadcrumbsHeight + + ColumnLayout { + anchors.fill: parent + spacing: 0 + + RowLayout { + Layout.fillWidth: true + Layout.preferredHeight: DS.Style.titleBar.height + + RowLayout { + Layout.fillHeight: true + Layout.fillWidth: true + layoutDirection: Qt.LeftToRight + + CheckBox { + id: _internal_check + + } + + IconButton { + icon.name: "arrow_ordinary_left" + } + + IconButton { + icon.name: "arrow_ordinary_right" + } + + TabBar { + Layout.fillWidth: true + + TabButton { + text: qsTr("Home") + width: implicitWidth + } + + TabButton { + text: qsTr("Discover") + width: implicitWidth + } + + TabButton { + text: qsTr("Activity") + width: implicitWidth + } + } + + IconButton { + icon.name: "button_add" + } + } + + Loader { + Layout.preferredWidth: item ? item.implicitWidth : 0 + active: Window.window + height: DS.Style.titleBar.height + + sourceComponent: TitleBar { + // replace Window.window.width + width: parent.width + } + } + } + + RowLayout { + id: breadcrumbsLayout + + Layout.fillWidth: true + implicitHeight: breadcrumbsHeight + spacing: 0 + + Rectangle { + id: breadcrumbs + + Layout.fillHeight: true + Layout.fillWidth: true + color: "blue" + } + + Rectangle { + id: tools + + Layout.fillHeight: true + color: "yellow" + width: 100 + } + + LineSearch { + id: searchbar + + Layout.fillHeight: true + visible: titlebar.width > 500 + } + } + } +} diff --git a/src/plugins/filemanager/core/dfmplugin-titlebar/dfmplugin_titlebar_global.h b/src/plugins/filemanager/core/dfmplugin-titlebar/dfmplugin_titlebar_global.h index 4925cb9c4a..bd71824f95 100644 --- a/src/plugins/filemanager/core/dfmplugin-titlebar/dfmplugin_titlebar_global.h +++ b/src/plugins/filemanager/core/dfmplugin-titlebar/dfmplugin_titlebar_global.h @@ -110,7 +110,7 @@ class IPHistroyData return map; } - inline bool operator==(const IPHistroyData &other) + inline bool operator==(const IPHistroyData &other) const { return (!this->ipData.compare(other.ipData) && !this->accessedType.compare(other.accessedType, Qt::CaseInsensitive)); diff --git a/src/plugins/filemanager/core/dfmplugin-titlebar/dialogs/connecttoserverdialog.cpp b/src/plugins/filemanager/core/dfmplugin-titlebar/dialogs/connecttoserverdialog.cpp index cc42de17c7..0ec89a4c72 100644 --- a/src/plugins/filemanager/core/dfmplugin-titlebar/dialogs/connecttoserverdialog.cpp +++ b/src/plugins/filemanager/core/dfmplugin-titlebar/dialogs/connecttoserverdialog.cpp @@ -73,7 +73,11 @@ ConnectToServerDialog::ConnectToServerDialog(const QUrl &url, QWidget *parent) initConnect(); protocolIPRegExp.setPattern(kprotocolIPRegExp); +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) protocolIPRegExp.setCaseSensitivity(Qt::CaseInsensitive); +#else + protocolIPRegExp.setPatternOptions(protocolIPRegExp.patternOptions() | QRegularExpression::CaseInsensitiveOption); +#endif } void ConnectToServerDialog::collectionOperate() @@ -107,7 +111,12 @@ void ConnectToServerDialog::onButtonClicked(const int &index) // add search history list SearchHistroyManager::instance()->writeIntoSearchHistory(url); + +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) if (protocolIPRegExp.exactMatch(url)) +#else + if (protocolIPRegExp.match(url).hasMatch()) +#endif SearchHistroyManager::instance()->writeIntoIPHistory(url); } close(); diff --git a/src/plugins/filemanager/core/dfmplugin-titlebar/dialogs/connecttoserverdialog.h b/src/plugins/filemanager/core/dfmplugin-titlebar/dialogs/connecttoserverdialog.h index e7d19a574a..0d401aaacc 100644 --- a/src/plugins/filemanager/core/dfmplugin-titlebar/dialogs/connecttoserverdialog.h +++ b/src/plugins/filemanager/core/dfmplugin-titlebar/dialogs/connecttoserverdialog.h @@ -10,6 +10,7 @@ #include #include #include +#include DWIDGET_BEGIN_NAMESPACE class DIconButton; @@ -65,7 +66,11 @@ private slots: kConnectButton }; +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QRegExp protocolIPRegExp; // smb://ip, ftp://ip, sftp://ip +#else + QRegularExpression protocolIPRegExp; +#endif QUrl currentUrl; QStringList supportedSchemes; DTK_WIDGET_NAMESPACE::DComboBox *serverComboBox { nullptr }; diff --git a/src/plugins/filemanager/core/dfmplugin-titlebar/dialogs/dpcwidget/dpcconfirmwidget.cpp b/src/plugins/filemanager/core/dfmplugin-titlebar/dialogs/dpcwidget/dpcconfirmwidget.cpp index ea57989cea..9a5fd1c6c1 100644 --- a/src/plugins/filemanager/core/dfmplugin-titlebar/dialogs/dpcwidget/dpcconfirmwidget.cpp +++ b/src/plugins/filemanager/core/dfmplugin-titlebar/dialogs/dpcwidget/dpcconfirmwidget.cpp @@ -72,9 +72,15 @@ void DPCConfirmWidget::initUI() DFontSizeManager *fontManager = DFontSizeManager::instance(); fontManager->bind(titleLabel, DFontSizeManager::T5, QFont::Medium); +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QRegExp regx("[^\\x4e00-\\x9fa5]+"); // 创建验证器 QValidator *validator = new QRegExpValidator(regx, this); +#else + QRegularExpression regx("[^\\x4e00-\\x9fa5]+"); + // 创建验证器 + QValidator *validator = new QRegularExpressionValidator(regx, this); +#endif oldPwdEdit = new DPasswordEdit(this); oldPwdEdit->lineEdit()->setValidator(validator); // 设置验证器 @@ -113,7 +119,11 @@ void DPCConfirmWidget::initUI() buttonLayout->addWidget(saveBtn); QVBoxLayout *mainLayout = new QVBoxLayout; +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) mainLayout->setMargin(0); +#else + mainLayout->setContentsMargins(0, 0, 0, 0); +#endif mainLayout->addWidget(titleLabel, 0, Qt::AlignHCenter); mainLayout->addSpacing(10); mainLayout->addLayout(contentLayout); diff --git a/src/plugins/filemanager/core/dfmplugin-titlebar/dialogs/dpcwidget/dpcprogresswidget.cpp b/src/plugins/filemanager/core/dfmplugin-titlebar/dialogs/dpcwidget/dpcprogresswidget.cpp index 8f50a0c6c6..8c359cf914 100644 --- a/src/plugins/filemanager/core/dfmplugin-titlebar/dialogs/dpcwidget/dpcprogresswidget.cpp +++ b/src/plugins/filemanager/core/dfmplugin-titlebar/dialogs/dpcwidget/dpcprogresswidget.cpp @@ -40,7 +40,11 @@ DPCProgressWidget::DPCProgressWidget(QWidget *parent) void DPCProgressWidget::initUI() { QVBoxLayout *mainLayout = new QVBoxLayout; +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) mainLayout->setMargin(0); +#else + mainLayout->setContentsMargins(0, 0, 0, 0); +#endif setLayout(mainLayout); progressTimer = new QTimer(this); diff --git a/src/plugins/filemanager/core/dfmplugin-titlebar/dialogs/dpcwidget/dpcresultwidget.cpp b/src/plugins/filemanager/core/dfmplugin-titlebar/dialogs/dpcwidget/dpcresultwidget.cpp index 11322473d6..b6f47eedda 100644 --- a/src/plugins/filemanager/core/dfmplugin-titlebar/dialogs/dpcwidget/dpcresultwidget.cpp +++ b/src/plugins/filemanager/core/dfmplugin-titlebar/dialogs/dpcwidget/dpcresultwidget.cpp @@ -37,7 +37,11 @@ void DPCResultWidget::setResult(bool success, const QString &msg) void DPCResultWidget::initUI() { QVBoxLayout *mainLayout = new QVBoxLayout; +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) mainLayout->setMargin(0); +#else + mainLayout->setContentsMargins(0, 0, 0, 0); +#endif setLayout(mainLayout); titleLabel = new DLabel(this); diff --git a/src/plugins/filemanager/core/dfmplugin-titlebar/titlebar.json b/src/plugins/filemanager/core/dfmplugin-titlebar/titlebar.json index edbe210b18..d6d10b3433 100644 --- a/src/plugins/filemanager/core/dfmplugin-titlebar/titlebar.json +++ b/src/plugins/filemanager/core/dfmplugin-titlebar/titlebar.json @@ -11,5 +11,12 @@ "UrlLink" : "https://www.uniontech.com", "Depends" : [ {"Name" : "dfmplugin-core", "Version": "1.0.0"} + ], + "Quick" : [ + { + "Url" : "Titlebar.qml", + "Id" : "titlebar", + "Parent" : "dfmplugin-core.filewindow" + } ] } diff --git a/src/plugins/filemanager/core/dfmplugin-titlebar/utils/searchhistroymanager.cpp b/src/plugins/filemanager/core/dfmplugin-titlebar/utils/searchhistroymanager.cpp index 2d829b7f6d..259f5f0a00 100644 --- a/src/plugins/filemanager/core/dfmplugin-titlebar/utils/searchhistroymanager.cpp +++ b/src/plugins/filemanager/core/dfmplugin-titlebar/utils/searchhistroymanager.cpp @@ -86,7 +86,7 @@ void SearchHistroyManager::writeIntoIPHistory(const QString &ipAddr) auto history = getIPHistory(); IPHistroyData data(ipAddr, QDateTime::currentDateTime()); if (history.contains(data)) { - int index = history.indexOf(data); + int index = history.indexOf(data); history.replace(index, data); } else { history << data; diff --git a/src/plugins/filemanager/core/dfmplugin-titlebar/utils/titlebarhelper.cpp b/src/plugins/filemanager/core/dfmplugin-titlebar/utils/titlebarhelper.cpp index ea3616f022..62ba8aaf2c 100644 --- a/src/plugins/filemanager/core/dfmplugin-titlebar/utils/titlebarhelper.cpp +++ b/src/plugins/filemanager/core/dfmplugin-titlebar/utils/titlebarhelper.cpp @@ -23,7 +23,7 @@ #include -#include +// #include #include #include @@ -193,8 +193,10 @@ QList TitleBarHelper::tansToCrumbDataList(const QList &m bool TitleBarHelper::displayIcon() { - QGSettings settings("com.deepin.dde.filemanager.general", "/com/deepin/dde/filemanager/general/"); - return settings.get("contextMenuIcons").toBool(); + //! FIXME: ? qgsetting 不再使用 + // QGSettings settings("com.deepin.dde.filemanager.general", "/com/deepin/dde/filemanager/general/"); + // return settings.get("contextMenuIcons").toBool(); + return false; } void TitleBarHelper::handlePressed(QWidget *sender, const QString &text, bool *isSearch) diff --git a/src/plugins/filemanager/core/dfmplugin-titlebar/views/addressbar.cpp b/src/plugins/filemanager/core/dfmplugin-titlebar/views/addressbar.cpp index aee36ee91e..6cc3013fe2 100644 --- a/src/plugins/filemanager/core/dfmplugin-titlebar/views/addressbar.cpp +++ b/src/plugins/filemanager/core/dfmplugin-titlebar/views/addressbar.cpp @@ -142,7 +142,11 @@ void AddressBarPrivate::initData() { ipRegExp.setPattern(R"(((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3})"); protocolIPRegExp.setPattern(R"(((smb)|(ftp)|(sftp))(://)((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3})"); +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) protocolIPRegExp.setCaseSensitivity(Qt::CaseInsensitive); +#else + protocolIPRegExp.setPatternOptions(protocolIPRegExp.patternOptions() | QRegularExpression::CaseInsensitiveOption); +#endif // 设置补全组件 urlCompleter = new QCompleter(this); setCompleter(urlCompleter); @@ -221,7 +225,11 @@ void AddressBarPrivate::clearCompleterModel() void AddressBarPrivate::updateCompletionState(const QString &text) { isClearSearch = false; +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) if (ipRegExp.exactMatch(text)) { +#else + if (ipRegExp.match(text).hasMatch()) { +#endif inputIsIpAddress = true; completeIpAddress(text); } else { @@ -523,7 +531,11 @@ void AddressBarPrivate::onReturnPressed() } SearchHistroyManager::instance()->writeIntoSearchHistory(text); +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) if (protocolIPRegExp.exactMatch(text)) { +#else + if (protocolIPRegExp.match(text).hasMatch()) { +#endif IPHistroyData data(text, QDateTime::currentDateTime()); if (ipHistroyList.contains(data)) { // update @@ -907,7 +919,7 @@ void AddressBar::inputMethodEvent(QInputMethodEvent *e) QLineEdit::inputMethodEvent(e); } -void AddressBar::enterEvent(QEvent *e) +void AddressBar::enterEvent(QEnterEvent *e) { if (d->indicatorType == AddressBar::Search && d->spinner.isPlaying()) { d->spinner.hide(); diff --git a/src/plugins/filemanager/core/dfmplugin-titlebar/views/addressbar.h b/src/plugins/filemanager/core/dfmplugin-titlebar/views/addressbar.h index 5656363031..478f4361d2 100644 --- a/src/plugins/filemanager/core/dfmplugin-titlebar/views/addressbar.h +++ b/src/plugins/filemanager/core/dfmplugin-titlebar/views/addressbar.h @@ -40,7 +40,7 @@ class AddressBar : public QLineEdit void paintEvent(QPaintEvent *e) override; void showEvent(QShowEvent *event) override; void inputMethodEvent(QInputMethodEvent *e) override; - void enterEvent(QEvent *e) override; + void enterEvent(QEnterEvent *e) override; void leaveEvent(QEvent *e) override; Q_SIGNALS: diff --git a/src/plugins/filemanager/core/dfmplugin-titlebar/views/crumbbar.cpp b/src/plugins/filemanager/core/dfmplugin-titlebar/views/crumbbar.cpp index 4b7d028c9e..775b2f8e29 100644 --- a/src/plugins/filemanager/core/dfmplugin-titlebar/views/crumbbar.cpp +++ b/src/plugins/filemanager/core/dfmplugin-titlebar/views/crumbbar.cpp @@ -18,7 +18,7 @@ #include -#include +// #include #include #include #include diff --git a/src/plugins/filemanager/core/dfmplugin-titlebar/views/optionbuttonbox.cpp b/src/plugins/filemanager/core/dfmplugin-titlebar/views/optionbuttonbox.cpp index a807087a2d..061cc759b2 100644 --- a/src/plugins/filemanager/core/dfmplugin-titlebar/views/optionbuttonbox.cpp +++ b/src/plugins/filemanager/core/dfmplugin-titlebar/views/optionbuttonbox.cpp @@ -227,7 +227,11 @@ void OptionButtonBox::initUiForSizeMode() d->hBoxLayout = nullptr; } d->hBoxLayout = new QHBoxLayout; +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) d->hBoxLayout->setMargin(0); +#else + d->hBoxLayout->setContentsMargins(0, 0, 0, 0); +#endif d->hBoxLayout->addWidget(d->iconViewButton); d->hBoxLayout->addWidget(d->listViewButton); if (d->treeViewButton) diff --git a/src/plugins/filemanager/core/dfmplugin-titlebar/views/private/addressbar_p.h b/src/plugins/filemanager/core/dfmplugin-titlebar/views/private/addressbar_p.h index e5fe951628..ca2d767e7b 100644 --- a/src/plugins/filemanager/core/dfmplugin-titlebar/views/private/addressbar_p.h +++ b/src/plugins/filemanager/core/dfmplugin-titlebar/views/private/addressbar_p.h @@ -72,8 +72,13 @@ class AddressBarPrivate : public QObject bool isClearSearch { false }; bool isKeyPressed { false }; bool isHistoryInCompleterModel { false }; +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QRegExp ipRegExp; // 0.0.0.0-255.255.255.255 QRegExp protocolIPRegExp; // smb://ip, ftp://ip, sftp://ip +#else + QRegularExpression ipRegExp; // 0.0.0.0-255.255.255.255 + QRegularExpression protocolIPRegExp; // smb://ip, ftp://ip, sftp://ip +#endif QString completionPrefix; bool inputIsIpAddress { false }; diff --git a/src/plugins/filemanager/core/dfmplugin-titlebar/views/titlebarwidget.cpp b/src/plugins/filemanager/core/dfmplugin-titlebar/views/titlebarwidget.cpp index e7f96b4750..5bfe2eaae0 100644 --- a/src/plugins/filemanager/core/dfmplugin-titlebar/views/titlebarwidget.cpp +++ b/src/plugins/filemanager/core/dfmplugin-titlebar/views/titlebarwidget.cpp @@ -116,7 +116,11 @@ void TitleBarWidget::initializeUi() #endif titleBarLayout = new QHBoxLayout(this); +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) titleBarLayout->setMargin(0); +#else + titleBarLayout->setContentsMargins(0, 0, 0, 0); +#endif titleBarLayout->setSpacing(0); titleBarLayout->addSpacing(10); titleBarLayout->addWidget(curNavWidget, 0, Qt::AlignLeft); diff --git a/src/plugins/filemanager/core/dfmplugin-workspace/CMakeLists.txt b/src/plugins/filemanager/core/dfmplugin-workspace/CMakeLists.txt index 8a3a1afdf7..a773a50eb9 100644 --- a/src/plugins/filemanager/core/dfmplugin-workspace/CMakeLists.txt +++ b/src/plugins/filemanager/core/dfmplugin-workspace/CMakeLists.txt @@ -24,7 +24,7 @@ FILE(GLOB WORKSPACE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/models/private/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/*.json" ) -find_package(Dtk COMPONENTS Widget REQUIRED) +find_package(Dtk${DTK_VERSION_MAJOR} COMPONENTS Widget REQUIRED) add_library(${PROJECT_NAME} SHARED diff --git a/src/plugins/filemanager/core/dfmplugin-workspace/utils/selecthelper.h b/src/plugins/filemanager/core/dfmplugin-workspace/utils/selecthelper.h index a5db57b808..6a014cc1b5 100644 --- a/src/plugins/filemanager/core/dfmplugin-workspace/utils/selecthelper.h +++ b/src/plugins/filemanager/core/dfmplugin-workspace/utils/selecthelper.h @@ -11,7 +11,7 @@ #include #include -QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE class QItemSelection; QT_END_NAMESPACE