Compare commits
24 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
b03849d6de | |
|
|
187be9a947 | |
|
|
16145642e1 | |
|
|
39a50cca37 | |
|
|
2767618f84 | |
|
|
36c06be095 | |
|
|
80db4dd238 | |
|
|
3d0713f7a2 | |
|
|
af1259edbb | |
|
|
3b5ba9bbda | |
|
|
c8f2955bd0 | |
|
|
96d0b45dd0 | |
|
|
00109d07e3 | |
|
|
d2c2efc49a | |
|
|
9842a0644e | |
|
|
9d3d659afe | |
|
|
eaf96e824d | |
|
|
7c05bace4a | |
|
|
a892ddc4e2 | |
|
|
65cf7b4161 | |
|
|
6b7e941839 | |
|
|
dc2eaeb61c | |
|
|
4dd22b538d | |
|
|
2ea4e762fe |
|
|
@ -34,7 +34,7 @@ Copyright: None
|
|||
License: LGPL-3.0-or-later
|
||||
|
||||
# README
|
||||
Files: *README.md *README.zh_CN.md
|
||||
Files: *README.md *README.zh_CN.md CHANGELOG.md
|
||||
Copyright: None
|
||||
License: CC-BY-4.0
|
||||
|
||||
|
|
|
|||
67
CHANGELOG.md
67
CHANGELOG.md
|
|
@ -5,6 +5,73 @@ All notable changes to this project will be documented in this file.
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [5.7.25] - 2025-10-30
|
||||
|
||||
### Changed
|
||||
|
||||
- Improve icon theme generation with scalable support
|
||||
|
||||
## [5.7.24] - 2025-10-16
|
||||
|
||||
### Added
|
||||
|
||||
- Support Qt 6.10
|
||||
|
||||
### Changed
|
||||
|
||||
- Improve icon size detection and duplicate handling
|
||||
|
||||
### Fixed
|
||||
|
||||
- Correct lockfile path construction
|
||||
- Fix Qt6 compilation error with libxdg
|
||||
|
||||
## [5.7.23] - 2025-09-25
|
||||
|
||||
### Fixed
|
||||
|
||||
- 解决控制中心闪烁问题
|
||||
- Fix build for Qt 6.9
|
||||
|
||||
## [5.7.22] - 2025-09-04
|
||||
|
||||
### Added
|
||||
|
||||
- Add T11 font size and adjust T5 default
|
||||
|
||||
### Fixed
|
||||
|
||||
- Improve PID namespace detection in setSingleInstance
|
||||
|
||||
## [5.7.21] - 2025-08-14
|
||||
|
||||
### Added
|
||||
|
||||
- Add flags parameter to DDciIconPlayer play method
|
||||
|
||||
### Fixed
|
||||
|
||||
- Resolve compilation warnings and deprecation issues
|
||||
|
||||
## [5.7.20] - 2025-07-31
|
||||
|
||||
### Added
|
||||
|
||||
- Add pid namespace isolation to setSingleInstance
|
||||
- Add concurrent processing for DCI icon conversion
|
||||
|
||||
### Changed
|
||||
|
||||
- Update REUSE license file for CHANGELOG
|
||||
- Move icon finder functionality to separate tool
|
||||
- Switch to QGuiApplication for SVG rendering
|
||||
|
||||
## [5.7.19] - 2025-07-03
|
||||
|
||||
### Fixed
|
||||
|
||||
- Enhance build security hardening
|
||||
|
||||
## [5.7.18] - 2025-06-27
|
||||
|
||||
### Fixed
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Maintainer: justforlxz <justforlxz@gmail.com>
|
||||
pkgname=dtkgui-git
|
||||
pkgver=5.7.18
|
||||
pkgver=5.7.25
|
||||
pkgrel=1
|
||||
sourcename=dtkgui
|
||||
sourcetars=("$sourcename"_"$pkgver".tar.xz)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,45 @@
|
|||
dtkgui (5.7.25) unstable; urgency=medium
|
||||
|
||||
* Release 5.7.25
|
||||
|
||||
-- yeshanshan <yeshanshan@uniontech.com> Thu, 30 Oct 2025 21:47:33 +0800
|
||||
|
||||
dtkgui (5.7.24) unstable; urgency=medium
|
||||
|
||||
* Release 5.7.24
|
||||
|
||||
-- yeshanshan <yeshanshan@uniontech.com> Thu, 16 Oct 2025 19:45:30 +0800
|
||||
|
||||
dtkgui (5.7.23) unstable; urgency=medium
|
||||
|
||||
* Release 5.7.23
|
||||
|
||||
-- yeshanshan <packages@deepin.org> Thu, 25 Sep 2025 16:49:18 +0800
|
||||
|
||||
dtkgui (5.7.22) unstable; urgency=medium
|
||||
|
||||
* Release 5.7.22
|
||||
|
||||
-- yeshanshan <yeshanshan@uniontech.com> Thu, 04 Sep 2025 19:27:38 +0800
|
||||
|
||||
dtkgui (5.7.21) unstable; urgency=medium
|
||||
|
||||
* Release 5.7.21
|
||||
|
||||
-- yeshanshan <packages@deepin.org> Thu, 14 Aug 2025 19:47:40 +0800
|
||||
|
||||
dtkgui (5.7.20) unstable; urgency=medium
|
||||
|
||||
* Release 5.7.20
|
||||
|
||||
-- yeshanshan <yeshanshan@uniontech.com> Thu, 31 Jul 2025 19:59:35 +0800
|
||||
|
||||
dtkgui (5.7.19) unstable; urgency=medium
|
||||
|
||||
* Release 5.7.19
|
||||
|
||||
-- yeshanshan <yeshanshan@uniontech.com> Thu, 03 Jul 2025 21:12:27 +0800
|
||||
|
||||
dtkgui (5.7.18) unstable; urgency=medium
|
||||
|
||||
* Release 5.7.18
|
||||
|
|
|
|||
|
|
@ -3,6 +3,12 @@ DPKG_EXPORT_BUILDFLAGS = 1
|
|||
include /usr/share/dpkg/default.mk
|
||||
export QT_SELECT = qt5
|
||||
|
||||
# 安全编译参数
|
||||
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||
export DEB_CFLAGS_MAINT_APPEND = -Wall
|
||||
export DEB_CXXFLAGS_MAINT_APPEND = -Wall
|
||||
export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -Wl,-E
|
||||
|
||||
DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
|
||||
|
||||
VERSION = $(DEB_VERSION_UPSTREAM)
|
||||
|
|
|
|||
|
|
@ -171,6 +171,11 @@
|
|||
@details 为指定的图标模式计算要显示的内容,这可能会导致 currentImage 发生变化。这是个一次性行为,不会影响下一次调用 setMode 后的结果。
|
||||
@param[in] mode 指定要播放的图标模式,如果此模式支持动画,会触发此模式自身的动画播放(与 setMode 导致的动画不同的是,此动画不涉及两种模式变化时的过渡规则),否则将修改 currentImage 为此模式对应的静态图片资源。
|
||||
|
||||
@fn Dtk::Gui::DDciIconPlayer::play(DDciIcon::Mode mode, DDciIconImagePlayer::Flags flags)
|
||||
@details 为指定的图标模式和播放参数计算要显示的内容。
|
||||
@param[in] mode 指定要播放的图标模式。
|
||||
@param[in] flags 播放参数
|
||||
|
||||
@fn Dtk::Gui::DDciIconPlayer::stop()
|
||||
@details 如果当前正在播放动画,则停止当前动画的播放,但不会影响队列中下一个动画的播放。可能会导致 DDciIconPlayer::state 发生变化。
|
||||
@sa DDciIconPlayer::abort
|
||||
|
|
|
|||
19
dtkgui.cmake
19
dtkgui.cmake
|
|
@ -18,11 +18,6 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
|||
|
||||
# Set build option
|
||||
option(DTK_DISABLE_LIBXDG "Disable libxdg" OFF)
|
||||
find_package(Qt${QT_VERSION_MAJOR}XdgIconLoader)
|
||||
if (NOT Qt${QT_VERSION_MAJOR}XdgIconLoader_FOUND)
|
||||
message(WARNING " XdgIconLoader Not Found, DISABLE LIBXDG !")
|
||||
set (DTK_DISABLE_LIBXDG ON)
|
||||
endif()
|
||||
option(DTK_DISABLE_LIBRSVG "Disable librsvg" OFF)
|
||||
option(DTK_DISABLE_EX_IMAGE_FORMAT "Disable libraw and freeimage" OFF)
|
||||
|
||||
|
|
@ -43,7 +38,6 @@ set(CONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_VERSION_MAJOR}Gui
|
|||
set(PKGCONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -Wall -Wextra -fopenmp")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--as-needed")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie")
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(BUILD_TESTING ON)
|
||||
|
|
@ -121,6 +115,19 @@ find_package(Dtk${DTK_VERSION_MAJOR} REQUIRED Core)
|
|||
find_package(DtkBuildHelper REQUIRED)
|
||||
pkg_check_modules(librsvg REQUIRED IMPORTED_TARGET librsvg-2.0)
|
||||
|
||||
if(NOT DTK_DISABLE_LIBXDG)
|
||||
# Only use libxdg under Qt5
|
||||
if (${QT_VERSION_MAJOR} STREQUAL "5")
|
||||
find_package(Qt5XdgIconLoader REQUIRED)
|
||||
if (NOT Qt5XdgIconLoader_FOUND)
|
||||
message(WARNING " XdgIconLoader Not Found, DISABLE LIBXDG !")
|
||||
set (DTK_DISABLE_LIBXDG ON)
|
||||
endif()
|
||||
else()
|
||||
set (DTK_DISABLE_LIBXDG ON)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Check optional image handler dependencies.
|
||||
find_package(FreeImage)
|
||||
pkg_check_modules(libraw IMPORTED_TARGET libraw)
|
||||
|
|
|
|||
|
|
@ -77,7 +77,8 @@ public:
|
|||
Light = 0,
|
||||
Dark = 1
|
||||
};
|
||||
D_DECL_DEPRECATED enum IconAttibute {
|
||||
// IconAttibute is deprecated, please use IconAttribute instead.
|
||||
enum IconAttibute {
|
||||
HasPalette = 0x001
|
||||
};
|
||||
using IconAttribute = DDciIcon::IconAttibute;
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ public:
|
|||
|
||||
QImage currentImage() const;
|
||||
void play(DDciIcon::Mode mode);
|
||||
void play(DDciIcon::Mode mode, DDciIconImagePlayer::Flags flags);
|
||||
void stop();
|
||||
void abort();
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ public:
|
|||
T8,
|
||||
T9,
|
||||
T10,
|
||||
T11,
|
||||
NSizeTypes
|
||||
};
|
||||
Q_ENUM(SizeType)
|
||||
|
|
@ -110,6 +111,10 @@ public:
|
|||
{
|
||||
return get(T10);
|
||||
}
|
||||
inline const QFont t11() const
|
||||
{
|
||||
return get(T11);
|
||||
}
|
||||
|
||||
Q_SIGNALS:
|
||||
void fontChanged();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
Name: dtkgui
|
||||
Version: 5.7.18
|
||||
Version: 5.7.25
|
||||
Release: 1%{?dist}
|
||||
Summary: Deepin dtkgui
|
||||
License: LGPLv3+
|
||||
|
|
|
|||
|
|
@ -1,5 +1,10 @@
|
|||
if("${QT_VERSION_MAJOR}" STREQUAL "6")
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Widgets WaylandClient)
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets WaylandClient)
|
||||
|
||||
if (${Qt6Core_VERSION} VERSION_GREATER_EQUAL "6.10.0")
|
||||
set(QT_NO_PRIVATE_MODULE_WARNING ON)
|
||||
find_package(Qt6 REQUIRED COMPONENTS CorePrivate GuiPrivate WaylandClientPrivate)
|
||||
endif()
|
||||
else()
|
||||
find_package(Qt5 REQUIRED COMPONENTS WaylandClient XkbCommonSupport)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@
|
|||
|
||||
#ifdef Q_OS_LINUX
|
||||
#include <pwd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
|
|
@ -321,7 +322,7 @@ DPlatformTheme *DGuiApplicationHelperPrivate::initWindow(QWindow *window) const
|
|||
window->setProperty(WINDOW_THEME_KEY, QVariant::fromValue(theme));
|
||||
theme->setParent(window); // 跟随窗口销毁
|
||||
|
||||
auto onWindowThemeChanged = [window, theme, this] {
|
||||
auto onWindowThemeChanged = [window, this] {
|
||||
// 如果程序自定义了调色板, 则没有必要再关心窗口自身平台主题的变化
|
||||
// 需要注意的是, 这里的信号和事件可能会与 notifyAppThemeChanged 中的重复
|
||||
// 但是不能因此而移除这里的通知, 当窗口自身所对应的平台主题发生变化时, 这里
|
||||
|
|
@ -391,7 +392,12 @@ void DGuiApplicationHelperPrivate::notifyAppThemeChanged()
|
|||
|
||||
void DGuiApplicationHelperPrivate::notifyAppThemeChangedByEvent()
|
||||
{
|
||||
// https://github.com/qt/qtbase/commit/68a9c5fe513e147e4cffd29b50a4714813df411e
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
|
||||
QWindowSystemInterfacePrivate::ThemeChangeEvent event;
|
||||
#else
|
||||
QWindowSystemInterfacePrivate::ThemeChangeEvent event(nullptr);
|
||||
#endif
|
||||
// 此事件会促使QGuiApplication重新从QPlatformTheme中获取系统级别的QPalette.
|
||||
// 而在deepin平台下, 系统级别的QPalette来源自 \a applicationPalette()
|
||||
QGuiApplicationPrivate::processThemeChanged(&event);
|
||||
|
|
@ -455,7 +461,10 @@ void DGuiApplicationHelperPrivate::initPaletteType() const
|
|||
const_cast<DGuiApplicationHelperPrivate *>(this)->setPaletteType(DGuiApplicationHelper::ColorType(ct), emitSignal);
|
||||
};
|
||||
|
||||
applyThemeType(false);
|
||||
// 读取配置文件中的主题类型并立即应用
|
||||
DTK_CORE_NAMESPACE::DConfig dconfig("org.deepin.dtk.preference");
|
||||
int ct = dconfig.value("themeType", DGuiApplicationHelper::UnknownType).toInt();
|
||||
const_cast<DGuiApplicationHelperPrivate *>(this)->setPaletteType(DGuiApplicationHelper::ColorType(ct), false);
|
||||
|
||||
QObject::connect(_d_dconfig.operator ()(), &OrgDeepinDTKPreference::themeTypeChanged, _d_dconfig, [applyThemeType] {
|
||||
applyThemeType(true);
|
||||
|
|
@ -505,13 +514,13 @@ DGuiApplicationHelper::SizeMode DGuiApplicationHelperPrivate::fetchSizeMode(bool
|
|||
/*!
|
||||
\enum DGuiApplicationHelper::ColorType
|
||||
DGuiApplicationHelper::ColorType 定义了主题类型.
|
||||
|
||||
|
||||
\var DGuiApplicationHelper::ColorType DGuiApplicationHelper::UnknownType
|
||||
未知主题(浅色主题或深色主题)
|
||||
|
||||
|
||||
\var DGuiApplicationHelper::ColorType DGuiApplicationHelper::LightType
|
||||
浅色主题
|
||||
|
||||
|
||||
\var DGuiApplicationHelper::ColorType DGuiApplicationHelper::DarkType
|
||||
深色主题
|
||||
*/
|
||||
|
|
@ -519,28 +528,28 @@ DGuiApplicationHelper::SizeMode DGuiApplicationHelperPrivate::fetchSizeMode(bool
|
|||
/*!
|
||||
\enum DGuiApplicationHelper::Attribute
|
||||
DGuiApplicationHelper::Attribute 定义了功能属性
|
||||
|
||||
|
||||
\var DGuiApplicationHelper::Attribute DGuiApplicationHelper::UseInactiveColorGroup
|
||||
如果开启,当窗口处于Inactive状态时就会使用QPalette::Inactive的颜色,否则窗口将没有任何颜色变化。
|
||||
|
||||
|
||||
\var DGuiApplicationHelper::Attribute DGuiApplicationHelper::ColorCompositing
|
||||
是否采用半透明样式的调色板。
|
||||
|
||||
|
||||
\var DGuiApplicationHelper::Attribute DGuiApplicationHelper::ReadOnlyLimit
|
||||
区分只读枚举。
|
||||
|
||||
|
||||
\var DGuiApplicationHelper::Attribute DGuiApplicationHelper::IsDeepinPlatformTheme
|
||||
获取当前是否使用deepin的platformtheme插件,platformtheme插件可以为Qt程序提供特定的控件样式,默认使用chameleon主题。
|
||||
|
||||
|
||||
\var DGuiApplicationHelper::Attribute DGuiApplicationHelper::IsDXcbPlatform
|
||||
获取当前使用的是不是dtk的xcb窗口插件,dxcb插件提供了窗口圆角和阴影功能。
|
||||
|
||||
|
||||
\var DGuiApplicationHelper::Attribute DGuiApplicationHelper::IsXWindowPlatform
|
||||
获取当前是否运行在X11环境中。
|
||||
|
||||
|
||||
\var DGuiApplicationHelper::Attribute DGuiApplicationHelper::IsTableEnvironment
|
||||
获取当前是否运行在deepin平板环境中,检测XDG_CURRENT_DESKTOP环境变量是不是tablet结尾。
|
||||
|
||||
|
||||
\var DGuiApplicationHelper::Attribute DGuiApplicationHelper::IsDeepinEnvironment
|
||||
获取当前是否运行在deepin桌面环境中,检测XDG_CURRENT_DESKTOP环境变量是不是deepin。
|
||||
*/
|
||||
|
|
@ -1334,6 +1343,11 @@ void DGuiApplicationHelper::setApplicationPalette(const DPalette &palette)
|
|||
*/
|
||||
DPalette DGuiApplicationHelper::windowPalette(QWindow *window) const
|
||||
{
|
||||
#if DTK_VERSION >= DTK_VERSION_CHECK(5, 0, 0, 0)
|
||||
Q_UNUSED(window);
|
||||
qCWarning(dgAppHelper) << "DGuiApplicationHelper::windowPalette is deprecated, please use applicationPalette instead.";
|
||||
return applicationPalette();
|
||||
#else
|
||||
D_DC(DGuiApplicationHelper);
|
||||
|
||||
// 如果程序自定义了调色版, 则不再关心窗口对应的平台主题上的设置
|
||||
|
|
@ -1348,6 +1362,7 @@ DPalette DGuiApplicationHelper::windowPalette(QWindow *window) const
|
|||
}
|
||||
|
||||
return fetchPalette(theme);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -1487,11 +1502,37 @@ bool DGuiApplicationHelper::setSingleInstance(const QString &key, DGuiApplicatio
|
|||
}
|
||||
|
||||
socket_key += key;
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
auto info = QFileInfo{"/proc/self/ns/pid"};
|
||||
// maybe kernel doesn't support namespace
|
||||
while (info.exists()) {
|
||||
auto pidns = QFileInfo{info.symLinkTarget()}.fileName();
|
||||
if (pidns.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
// maybe format has been changed
|
||||
auto start = pidns.indexOf('[');
|
||||
auto end = pidns.indexOf(']');
|
||||
if (start == -1 || end == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
auto num = pidns.mid(start + 1, end - start - 1);
|
||||
|
||||
// append pid namespace
|
||||
socket_key += QStringLiteral("_%1").arg(num);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
QString lockfile = socket_key;
|
||||
if (!lockfile.startsWith(QLatin1Char('/'))) {
|
||||
lockfile = QDir::cleanPath(QDir::tempPath());
|
||||
lockfile += QLatin1Char('/') + socket_key;
|
||||
}
|
||||
|
||||
lockfile += QStringLiteral(".lock");
|
||||
static QScopedPointer <QLockFile> lock(new QLockFile(lockfile));
|
||||
// 同一个进程多次调用本接口使用最后一次设置的 key
|
||||
|
|
@ -1688,7 +1729,7 @@ bool DGuiApplicationHelper::loadTranslator(const QString &fileName, const QList<
|
|||
if (locale.language() != QLocale::English) // English does not need translation
|
||||
localeNames << locale.name();
|
||||
}
|
||||
|
||||
|
||||
if (!localeNames.isEmpty()) {
|
||||
qWarning() << fileName << "can not find qm files for locales" << localeNames;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -280,6 +280,7 @@ DPalette DPlatformTheme::fetchPalette(const DPalette &base, bool *ok) const
|
|||
|
||||
void DPlatformTheme::setPalette(const DPalette &palette)
|
||||
{
|
||||
Q_UNUSED(palette);
|
||||
#define SET_PALETTE(Role) \
|
||||
set##Role(palette.color(QPalette::Normal, DPalette::Role))
|
||||
#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0)
|
||||
|
|
|
|||
|
|
@ -28,6 +28,11 @@ if("${QT_VERSION_MAJOR}" STREQUAL "6")
|
|||
qt6_generate_wayland_protocol_client_sources(${PROJECT_NAME} FILES
|
||||
${TREELAND_PROTOCOLS_DATA_DIR}/treeland-personalization-manager-v1.xml
|
||||
)
|
||||
|
||||
if (${Qt6Core_VERSION} VERSION_GREATER_EQUAL "6.10.0")
|
||||
set(QT_NO_PRIVATE_MODULE_WARNING ON)
|
||||
find_package(Qt6 REQUIRED COMPONENTS GuiPrivate CorePrivate WaylandClientPrivate)
|
||||
endif()
|
||||
else()
|
||||
# ECM setup
|
||||
include(FeatureSummary)
|
||||
|
|
|
|||
|
|
@ -95,11 +95,19 @@ bool MoveWindowHelper::windowEvent(QWindow *w, QEvent *event)
|
|||
isTouchDown = false;
|
||||
}
|
||||
if (isTouchDown && event->type() == QEvent::MouseButtonPress) {
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
touchBeginPosition = static_cast<QMouseEvent*>(event)->globalPosition();
|
||||
#else
|
||||
touchBeginPosition = static_cast<QMouseEvent*>(event)->globalPos();
|
||||
#endif
|
||||
}
|
||||
// add some redundancy to distinguish trigger between system menu and system move
|
||||
if (event->type() == QEvent::MouseMove) {
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
QPointF currentPos = static_cast<QMouseEvent*>(event)->globalPosition();
|
||||
#else
|
||||
QPointF currentPos = static_cast<QMouseEvent*>(event)->globalPos();
|
||||
#endif
|
||||
QPointF delta = touchBeginPosition - currentPos;
|
||||
if (delta.manhattanLength() < QGuiApplication::styleHints()->startDragDistance()) {
|
||||
return DVtableHook::callOriginalFun(w, &QWindow::event, event);
|
||||
|
|
@ -123,8 +131,13 @@ bool MoveWindowHelper::windowEvent(QWindow *w, QEvent *event)
|
|||
self->m_windowMoving = false;
|
||||
}
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
if (is_mouse_move && !event->isAccepted()
|
||||
&& w->geometry().contains(static_cast<QMouseEvent*>(event)->globalPosition().toPoint())) {
|
||||
#else
|
||||
if (is_mouse_move && !event->isAccepted()
|
||||
&& w->geometry().contains(static_cast<QMouseEvent*>(event)->globalPos())) {
|
||||
#endif
|
||||
if (!self->m_windowMoving && self->m_enableSystemMove) {
|
||||
self->m_windowMoving = true;
|
||||
|
||||
|
|
|
|||
|
|
@ -250,14 +250,14 @@ QColor DXCBPlatformInterface::darkActiveColor() const
|
|||
return qvariant_cast<QColor>(value);
|
||||
}
|
||||
|
||||
#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0)
|
||||
#define GET_COLOR(Role) qvariant_cast<QColor>(getSetting(QByteArrayLiteral(#Role)))
|
||||
static QColor getSetting(const QByteArray &key)
|
||||
{
|
||||
Q_UNUSED(key);
|
||||
qWarning() << "Not implemented, key:" << key;
|
||||
return {};
|
||||
}
|
||||
|
||||
#define GET_COLOR(Role) qvariant_cast<QColor>(getSetting(QByteArrayLiteral(#Role)))
|
||||
#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0)
|
||||
QColor DXCBPlatformInterface::window() const
|
||||
{
|
||||
return GET_COLOR(window);
|
||||
|
|
@ -541,13 +541,14 @@ void DXCBPlatformInterface::setDarkActiveColor(const QColor &activeColor)
|
|||
d->theme->setSetting("Qt/DarkActiveColor", activeColor);
|
||||
}
|
||||
|
||||
#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0)
|
||||
#define SET_COLOR(Role) setSetting(QByteArrayLiteral(#Role), Role)
|
||||
static void setSetting(const QByteArray &key, const QColor &color)
|
||||
{
|
||||
Q_UNUSED(key);
|
||||
Q_UNUSED(color);
|
||||
qWarning() << "Not implemented, key: " << key << "value: " << color;
|
||||
}
|
||||
|
||||
#define SET_COLOR(Role) setSetting(QByteArrayLiteral(#Role), Role)
|
||||
#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0)
|
||||
void DXCBPlatformInterface::setWindow(const QColor &window)
|
||||
{
|
||||
SET_COLOR(window);
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ DGUI_BEGIN_NAMESPACE
|
|||
#define DXCB_PLUGIN_KEY "dxcb"
|
||||
#define DXCB_PLUGIN_SYMBOLIC_PROPERTY "_d_isDxcb"
|
||||
|
||||
#define DEFINE_CONST_CHAR(Name) const char _##Name[] = "_d_" #Name
|
||||
#define DEFINE_CONST_CHAR(Name) [[maybe_unused]] const char _##Name[] = "_d_" #Name
|
||||
|
||||
DEFINE_CONST_CHAR(useDxcb);
|
||||
DEFINE_CONST_CHAR(redirectContent);
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class DFontManagerPrivate : public DTK_CORE_NAMESPACE::DObjectPrivate
|
|||
public:
|
||||
DFontManagerPrivate(DFontManager *qq);
|
||||
|
||||
int fontPixelSize[DFontManager::NSizeTypes] = {40, 30, 24, 20, 17, 14, 13, 12, 11, 10};
|
||||
int fontPixelSize[DFontManager::NSizeTypes] = {40, 30, 24, 20, 16, 14, 13, 12, 11, 10, 8};
|
||||
int baseFontSizeType = DFontManager::T6;
|
||||
// 字号的差值
|
||||
int fontPixelSizeDiff = 0;
|
||||
|
|
|
|||
|
|
@ -658,7 +658,11 @@ static const DDciIconEntry::ScalableLayer &findScalableLayer(const DDciIconEntry
|
|||
const DDciIconEntry::ScalableLayer *maxLayer = nullptr;
|
||||
const int imagePixelRatio = qCeil(devicePixelRatio);
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
for (const auto &i : std::as_const(entry->scalableLayers)) {
|
||||
#else
|
||||
for (const auto &i : qAsConst(entry->scalableLayers)) {
|
||||
#endif
|
||||
if (!maxLayer || i.imagePixelRatio > maxLayer->imagePixelRatio)
|
||||
maxLayer = &i;
|
||||
if (i.imagePixelRatio > imagePixelRatio)
|
||||
|
|
@ -1137,7 +1141,11 @@ int DDciIconImage::currentImageNumber() const
|
|||
void DDciIconImagePrivate::init()
|
||||
{
|
||||
readers.reserve(layers.size());
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
for (const auto &layer : std::as_const(layers)) {
|
||||
#else
|
||||
for (const auto &layer : qAsConst(layers)) {
|
||||
#endif
|
||||
ReaderData *data = new ReaderData;
|
||||
Q_ASSERT(data);
|
||||
auto buffer = new QBuffer();
|
||||
|
|
|
|||
|
|
@ -207,7 +207,11 @@ bool DDciIconImagePlayer::setPalette(const DDciIconPalette &palette)
|
|||
d->palette = palette;
|
||||
|
||||
bool hasPalette = false;
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
for (const auto &i : std::as_const(d->images))
|
||||
#else
|
||||
for (const auto &i : qAsConst(d->images))
|
||||
#endif
|
||||
if (i.hasPalette())
|
||||
hasPalette = true;
|
||||
|
||||
|
|
@ -649,7 +653,7 @@ void DDciIconPlayerPrivate::initPlayer()
|
|||
// Remove the finished animation
|
||||
animationJobs.removeFirst();
|
||||
|
||||
qCDebug(diPlayer, "Number of animations remaining is %i", animationJobs.size());
|
||||
qCDebug(diPlayer) << "Number of animations remaining is" << animationJobs.size();
|
||||
if (!animationJobs.isEmpty()) {
|
||||
_q_playFromQueue();
|
||||
return;
|
||||
|
|
@ -1075,10 +1079,15 @@ QImage DDciIconPlayer::currentImage() const
|
|||
return d->image;
|
||||
}
|
||||
|
||||
void DDciIconPlayer::play(DDciIcon::Mode mode)
|
||||
void DDciIconPlayer::play(DDciIcon::Mode mode, DDciIconImagePlayer::Flags flags)
|
||||
{
|
||||
D_D(DDciIconPlayer);
|
||||
d->play(mode, DDciIconImagePlayer::IgnoreLastImageLoop);
|
||||
d->play(mode, flags);
|
||||
}
|
||||
|
||||
void DDciIconPlayer::play(DDciIcon::Mode mode)
|
||||
{
|
||||
play(mode, DDciIconImagePlayer::IgnoreLastImageLoop);
|
||||
}
|
||||
|
||||
void DDciIconPlayer::stop()
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ DFontManager::~DFontManager()
|
|||
\value T4
|
||||
系统级别为 T4 的字体大小, 默认是20 px
|
||||
\value T5
|
||||
系统级别为 T5 的字体大小, 默认是17 px
|
||||
系统级别为 T5 的字体大小, 默认是16 px
|
||||
\value T6
|
||||
系统级别为 T6 的字体大小, 默认是14 px
|
||||
\value T7
|
||||
|
|
@ -60,6 +60,8 @@ DFontManager::~DFontManager()
|
|||
系统级别为 T9 的字体大小, 默认是11 px
|
||||
\value T10
|
||||
系统级别为 T10 的字体大小, 默认是10 px
|
||||
\value T11
|
||||
系统级别为 T11 的字体大小, 默认是8 px
|
||||
|
||||
\omitvalue NSizeTypes
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -126,12 +126,12 @@ bool DIconTheme::isBuiltinIcon(const QIcon &icon)
|
|||
|
||||
bool DIconTheme::isXdgIcon(const QIcon &icon)
|
||||
{
|
||||
#ifdef DTK_DISABLE_LIBXDG
|
||||
return false;
|
||||
#else
|
||||
if (icon.isNull())
|
||||
return false;
|
||||
|
||||
#ifdef DTK_DISABLE_LIBXDG
|
||||
return false;
|
||||
#else
|
||||
QIconEngine *engine = const_cast<QIcon &>(icon).data_ptr()->engine;
|
||||
if (auto proxyEngine = dynamic_cast<DIconProxyEngine *>(engine))
|
||||
return !proxyEngine->proxyKey().compare("XdgIconProxyEngine");
|
||||
|
|
|
|||
|
|
@ -304,6 +304,8 @@ QString DBuiltinIconEngine::iconName()
|
|||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
QList<QSize> DBuiltinIconEngine::availableSizes(QIcon::Mode mode, QIcon::State state)
|
||||
{
|
||||
Q_UNUSED(mode);
|
||||
Q_UNUSED(state);
|
||||
ensureLoaded();
|
||||
|
||||
QList<QSize> sizes;
|
||||
|
|
|
|||
|
|
@ -162,9 +162,10 @@ const
|
|||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
QList<QSize> DDciIconEngine::availableSizes(QIcon::Mode mode, QIcon::State state)
|
||||
{
|
||||
Q_UNUSED(state);
|
||||
ensureIconTheme();
|
||||
|
||||
const auto availableSizes = m_dciIcon.availableSizes(dciTheme(), DDciIcon::Normal);
|
||||
const auto availableSizes = m_dciIcon.availableSizes(dciTheme(), dciMode(mode));
|
||||
QList<QSize> sizes;
|
||||
sizes.reserve(availableSizes.size());
|
||||
|
||||
|
|
|
|||
|
|
@ -275,9 +275,8 @@ void DIconProxyEngine::ensureEngine()
|
|||
}
|
||||
#endif
|
||||
if (!m_iconEngine && !nonCache[theme].contains(m_iconName)) {
|
||||
qWarning("create icon [%s] engine failed.[theme:%s] nonCache[theme].size[%d]",
|
||||
m_iconName.toUtf8().data(),
|
||||
theme.toUtf8().data(), nonCache[theme].size());
|
||||
qWarning() << "create icon [" << m_iconName << "] engine failed."
|
||||
<< "theme:" << theme << "and nonCache's size:" << nonCache.size();
|
||||
nonCache[theme].insert(m_iconName);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,13 @@
|
|||
set(BIN_NAME ut-DtkGui)
|
||||
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets Test)
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Gui Widgets DBus Network Test)
|
||||
if ("${QT_VERSION_MAJOR}" STREQUAL "6")
|
||||
if (${Qt6Core_VERSION} VERSION_GREATER_EQUAL "6.10.0")
|
||||
set(QT_NO_PRIVATE_MODULE_WARNING ON)
|
||||
find_package(Qt6 REQUIRED COMPONENTS CorePrivate GuiPrivate WaylandClientPrivate)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_package(GTest REQUIRED)
|
||||
|
||||
file(GLOB test_SRC
|
||||
|
|
@ -44,7 +51,7 @@ target_link_libraries(${BIN_NAME} PRIVATE
|
|||
m
|
||||
)
|
||||
|
||||
if(NOT DTK_DISABLE_EX_IMAGE_FORMAT AND EX_IMAGE_FORMAT_LIBS_FOUND)
|
||||
if(NOT DTK_DISABLE_EX_IMAGE_FORMAT AND EX_IMAGE_FORMAT_LIBS_FOUND)
|
||||
target_link_libraries(${BIN_NAME} PRIVATE
|
||||
PkgConfig::libraw
|
||||
FreeImage::FreeImage
|
||||
|
|
@ -52,7 +59,7 @@ target_link_libraries(${BIN_NAME} PRIVATE
|
|||
endif()
|
||||
|
||||
if(NOT DTK_DISABLE_LIBXDG)
|
||||
target_link_libraries(${BIN_NAME} PRIVATE
|
||||
target_link_libraries(${BIN_NAME} PRIVATE
|
||||
Qt${QT_VERSION_MAJOR}XdgIconLoader
|
||||
)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -127,6 +127,15 @@ void DDynamicMetaObject::init(const QMetaObject *metaObject)
|
|||
|
||||
QMetaPropertyBuilder op;
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
switch (mp.metaType().id()) {
|
||||
case QMetaType::QByteArray:
|
||||
case QMetaType::QString:
|
||||
case QMetaType::QColor:
|
||||
case QMetaType::Int:
|
||||
case QMetaType::Double:
|
||||
case QMetaType::Bool:
|
||||
#else
|
||||
switch (mp.type()) {
|
||||
case QVariant::Type::ByteArray:
|
||||
case QVariant::Type::String:
|
||||
|
|
@ -134,6 +143,7 @@ void DDynamicMetaObject::init(const QMetaObject *metaObject)
|
|||
case QVariant::Type::Int:
|
||||
case QVariant::Type::Double:
|
||||
case QVariant::Type::Bool:
|
||||
#endif
|
||||
op = ob.addProperty(mp);
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
DGUI_BEGIN_NAMESPACE
|
||||
|
||||
class DPlatformSettings;
|
||||
class DDynamicMetaObject : public QAbstractDynamicMetaObject
|
||||
class Q_DECL_HIDDEN DDynamicMetaObject : public QAbstractDynamicMetaObject
|
||||
{
|
||||
public:
|
||||
explicit DDynamicMetaObject(QObject *base, DPlatformSettings *settings, bool global_settings);
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ QT_END_NAMESPACE
|
|||
|
||||
DGUI_BEGIN_NAMESPACE
|
||||
|
||||
class DPlatformSettings
|
||||
class Q_DECL_HIDDEN DPlatformSettings
|
||||
{
|
||||
public:
|
||||
virtual ~DPlatformSettings() {}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#include "dummysettings.h"
|
||||
#include <QDebug>
|
||||
|
||||
class DummySettingsPrivate : public QObject
|
||||
class Q_DECL_HIDDEN DummySettingsPrivate : public QObject
|
||||
{
|
||||
public:
|
||||
DummySettingsPrivate(DummySettings *q, const QString &domain, QObject *parent = nullptr);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
DGUI_USE_NAMESPACE
|
||||
|
||||
class DummySettingsPrivate;
|
||||
class DummySettings : public DPlatformSettings
|
||||
class Q_DECL_HIDDEN DummySettings : public DPlatformSettings
|
||||
{
|
||||
public:
|
||||
explicit DummySettings(const QString &domain = QString());
|
||||
|
|
|
|||
|
|
@ -13,11 +13,18 @@
|
|||
#include <qpa/qplatformwindow.h>
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
#include <private/qgenericunixeventdispatcher_p.h>
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
|
||||
#include <private/qdesktopunixservices_p.h>
|
||||
#else
|
||||
#include <private/qgenericunixservices_p.h>
|
||||
#endif
|
||||
|
||||
MinimalIntegration::MinimalIntegration(const QStringList ¶meters)
|
||||
{
|
||||
Q_UNUSED(parameters);
|
||||
m_primaryScreen = new MinimalScreen();
|
||||
|
||||
m_primaryScreen->mGeometry = QRect(0, 0, 240, 320);
|
||||
|
|
@ -53,7 +60,11 @@ QAbstractEventDispatcher *MinimalIntegration::createEventDispatcher() const
|
|||
QPlatformServices *MinimalIntegration::services() const
|
||||
{
|
||||
if (!m_services)
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
|
||||
m_services.reset(new QDesktopUnixServices);
|
||||
#else
|
||||
m_services.reset(new QGenericUnixServices);
|
||||
#endif
|
||||
return m_services.get();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ DGUI_USE_NAMESPACE
|
|||
#define ICONNAME "icon_Layout"
|
||||
#define ICONSIZE 16
|
||||
|
||||
class ut_DBuiltinIconEngine : public testing::Test
|
||||
class GTEST_API_ ut_DBuiltinIconEngine : public testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override;
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
DGUI_USE_NAMESPACE
|
||||
|
||||
class ut_DDciIconEngine : public testing::Test
|
||||
class GTEST_API_ ut_DDciIconEngine : public testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
DGUI_USE_NAMESPACE
|
||||
|
||||
class ut_DDciIcon : public DTest
|
||||
class GTEST_API_ ut_DDciIcon : public DTest
|
||||
{
|
||||
public:
|
||||
ut_DDciIcon()
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ TEST(ut_DDciIconImage, render)
|
|||
}
|
||||
}
|
||||
|
||||
class ut_DDciIconPlayer : public DTest
|
||||
class GTEST_API_ ut_DDciIconPlayer : public DTest
|
||||
{
|
||||
protected:
|
||||
ut_DDciIconPlayer()
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ TEST(ut_DFontManager, StaticFunction)
|
|||
ASSERT_TRUE(DFontManager::fontPixelSize(tF) > 0);
|
||||
}
|
||||
|
||||
class TDFontManager : public DTestWithParam<int>
|
||||
class GTEST_API_ TDFontManager : public DTestWithParam<int>
|
||||
{
|
||||
protected:
|
||||
void SetUp();
|
||||
|
|
@ -76,4 +76,5 @@ TEST_F(TDFontManager, testFontSize)
|
|||
ASSERT_EQ(manager->t8().pixelSize(), manager->fontPixelSize(DFontManager::T8));
|
||||
ASSERT_EQ(manager->t9().pixelSize(), manager->fontPixelSize(DFontManager::T9));
|
||||
ASSERT_EQ(manager->t10().pixelSize(), manager->fontPixelSize(DFontManager::T10));
|
||||
ASSERT_EQ(manager->t11().pixelSize(), manager->fontPixelSize(DFontManager::T11));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,14 +14,14 @@ DGUI_BEGIN_NAMESPACE
|
|||
#define WmClass "_d_WmClass"
|
||||
#define ProcessId "_d_ProcessId"
|
||||
|
||||
class TDForeignWindow : public DTest
|
||||
class GTEST_API_ TDForeignWindow : public DTest
|
||||
{
|
||||
protected:
|
||||
virtual void SetUp()
|
||||
{
|
||||
const QVector<quint32> ¤tIdList = DWindowManagerHelper::instance()->currentWorkspaceWindowIdList();
|
||||
foreignWindows.clear();
|
||||
for (quint32 currentId : qAsConst(currentIdList)) {
|
||||
for (const auto ¤tId : currentIdList) {
|
||||
foreignWindows.append(DForeignWindow::fromWinId(currentId));
|
||||
}
|
||||
}
|
||||
|
|
@ -36,13 +36,13 @@ protected:
|
|||
|
||||
TEST_F(TDForeignWindow, wmClass)
|
||||
{
|
||||
for (auto foreignWindow : qAsConst(foreignWindows))
|
||||
for (auto foreignWindow : foreignWindows)
|
||||
ASSERT_NE(foreignWindow->wmClass(), QString());
|
||||
}
|
||||
|
||||
TEST_F(TDForeignWindow, pid)
|
||||
{
|
||||
for (auto foreignWindow : qAsConst(foreignWindows))
|
||||
for (auto foreignWindow : foreignWindows)
|
||||
ASSERT_NE(foreignWindow->pid(), 0);
|
||||
}
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ TEST_F(TDForeignWindow, event)
|
|||
QDynamicPropertyChangeEvent wmevent(WmClass);
|
||||
QDynamicPropertyChangeEvent pidevent(ProcessId);
|
||||
|
||||
for (auto foreignWindow : qAsConst(foreignWindows)) {
|
||||
for (auto foreignWindow : foreignWindows) {
|
||||
QSignalSpy wmspy(foreignWindow, SIGNAL(wmClassChanged()));
|
||||
ASSERT_TRUE(foreignWindow->event(&wmevent));
|
||||
ASSERT_EQ(wmspy.count(), 1);
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ private:
|
|||
void virtual_hook(int id, void *data) override;
|
||||
*/
|
||||
|
||||
class ut_DIconProxyEngine : public testing::Test
|
||||
class GTEST_API_ ut_DIconProxyEngine : public testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override;
|
||||
|
|
|
|||
|
|
@ -20,8 +20,9 @@ TEST(ut_DIconTheme, builtinIcon)
|
|||
// icon2 只可能是从外部找到的图标,不会与 icon1 相同
|
||||
ASSERT_TRUE(icon1.cacheKey() != icon2.cacheKey());
|
||||
#ifndef DTK_DISABLE_LIBXDG
|
||||
if (!icon2.isNull())
|
||||
if (!icon2.isNull()) {
|
||||
ASSERT_TRUE(DIconTheme::isXdgIcon(icon2));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -36,8 +37,9 @@ TEST(ut_DIconTheme, cachedTheme)
|
|||
// icon2 只可能是从外部找到的图标,不会与 icon1 相同
|
||||
ASSERT_TRUE(icon1.cacheKey() != icon2.cacheKey());
|
||||
#ifndef DTK_DISABLE_LIBXDG
|
||||
if (!icon2.isNull())
|
||||
if (!icon2.isNull()) {
|
||||
ASSERT_TRUE(DIconTheme::isXdgIcon(icon2));
|
||||
}
|
||||
#endif
|
||||
|
||||
const QIcon icon1_cached1 = DIconTheme::cached()->findQIcon("edit");
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
DGUI_USE_NAMESPACE
|
||||
DCORE_USE_NAMESPACE
|
||||
|
||||
class ut_DNativeSettings : public testing::Test
|
||||
class GTEST_API_ ut_DNativeSettings : public testing::Test
|
||||
{
|
||||
public:
|
||||
static void SetUpTestSuite();
|
||||
|
|
|
|||
|
|
@ -106,13 +106,21 @@ TEST_F(TDPlatformHandle, testFunction)
|
|||
DPlatformHandle::setDisableWindowOverrideCursor(window, true);
|
||||
QVariant windowRadius = window->property(WINDOWRADIUS);
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
if (windowRadius.isValid() && windowRadius.canConvert<int>()) {
|
||||
#else
|
||||
if (windowRadius.isValid() && windowRadius.canConvert(QVariant::Int)) {
|
||||
#endif
|
||||
ASSERT_EQ(pHandle->windowRadius(), windowRadius.toInt());
|
||||
}
|
||||
|
||||
QVariant borderWidth = window->property(BORDERWIDTH);
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
if (borderWidth.isValid() && borderWidth.canConvert<int>()) {
|
||||
#else
|
||||
if (borderWidth.isValid() && borderWidth.canConvert(QVariant::Int)) {
|
||||
#endif
|
||||
ASSERT_EQ(pHandle->borderWidth(), borderWidth.toInt());
|
||||
} else {
|
||||
ASSERT_EQ(pHandle->borderWidth(), 0);
|
||||
|
|
@ -120,7 +128,11 @@ TEST_F(TDPlatformHandle, testFunction)
|
|||
|
||||
QVariant borderColor = window->property(BORDRCOLOR);
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
if (borderColor.isValid() && borderColor.canConvert<QColor>()) {
|
||||
#else
|
||||
if (borderColor.isValid() && borderColor.canConvert(QVariant::Color)) {
|
||||
#endif
|
||||
ASSERT_EQ(pHandle->borderColor(), borderColor.value<QColor>());
|
||||
} else {
|
||||
ASSERT_FALSE(pHandle->borderColor().isValid());
|
||||
|
|
@ -128,7 +140,11 @@ TEST_F(TDPlatformHandle, testFunction)
|
|||
|
||||
QVariant shadowRadius = window->property(SHADOWRADIUS);
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
if (shadowRadius.isValid() && shadowRadius.canConvert<int>()) {
|
||||
#else
|
||||
if (shadowRadius.isValid() && shadowRadius.canConvert(QVariant::Int)) {
|
||||
#endif
|
||||
ASSERT_EQ(pHandle->shadowRadius(), shadowRadius.toInt());
|
||||
} else {
|
||||
ASSERT_FALSE(pHandle->borderColor().isValid());
|
||||
|
|
@ -136,7 +152,11 @@ TEST_F(TDPlatformHandle, testFunction)
|
|||
|
||||
QVariant shadowOffset = window->property(SHADOWOFFSET);
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
if (shadowOffset.isValid() && shadowOffset.canConvert<QPoint>()) {
|
||||
#else
|
||||
if (shadowOffset.isValid() && shadowOffset.canConvert(QVariant::Point)) {
|
||||
#endif
|
||||
ASSERT_EQ(pHandle->shadowOffset(), shadowOffset.value<QPoint>());
|
||||
} else {
|
||||
ASSERT_TRUE(pHandle->shadowOffset().isNull());
|
||||
|
|
@ -144,7 +164,11 @@ TEST_F(TDPlatformHandle, testFunction)
|
|||
|
||||
QVariant shadowColor = window->property(SHADOWCOLOR);
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
if (shadowColor.isValid() && shadowColor.canConvert<QColor>()) {
|
||||
#else
|
||||
if (shadowColor.isValid() && shadowColor.canConvert(QVariant::Color)) {
|
||||
#endif
|
||||
ASSERT_EQ(pHandle->shadowColor(), shadowColor.value<QColor>());
|
||||
} else {
|
||||
ASSERT_FALSE(pHandle->shadowColor().isValid());
|
||||
|
|
@ -160,7 +184,11 @@ TEST_F(TDPlatformHandle, testFunction)
|
|||
|
||||
QVariant frameMask = window->property(FRAMEMASK);
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
if (frameMask.isValid() && frameMask.canConvert<QRegion>()) {
|
||||
#else
|
||||
if (frameMask.isValid() && frameMask.canConvert(QVariant::Region)) {
|
||||
#endif
|
||||
ASSERT_EQ(pHandle->frameMask(), frameMask.value<QRegion>());
|
||||
} else {
|
||||
ASSERT_TRUE(pHandle->frameMask().isEmpty());
|
||||
|
|
@ -175,35 +203,55 @@ TEST_F(TDPlatformHandle, testFunction)
|
|||
}
|
||||
|
||||
QVariant translucentBackground = window->property(TRANSLUCENTBACKGROUND);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
if (translucentBackground.isValid() && translucentBackground.canConvert<bool>()) {
|
||||
#else
|
||||
if (translucentBackground.isValid() && translucentBackground.canConvert(QVariant::Bool)) {
|
||||
#endif
|
||||
ASSERT_EQ(pHandle->translucentBackground(), translucentBackground.toBool());
|
||||
} else {
|
||||
ASSERT_FALSE(pHandle->translucentBackground());
|
||||
}
|
||||
|
||||
QVariant enableSystemResize = window->property(ENABLESYSTEMRESIZE);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
if (enableSystemResize.isValid() && enableSystemResize.canConvert<bool>()) {
|
||||
#else
|
||||
if (enableSystemResize.isValid() && enableSystemResize.canConvert(QVariant::Bool)) {
|
||||
#endif
|
||||
ASSERT_EQ(pHandle->enableSystemResize(), enableSystemResize.toBool());
|
||||
} else {
|
||||
ASSERT_FALSE(pHandle->enableSystemResize());
|
||||
}
|
||||
|
||||
QVariant enableSystemMove = window->property(ENABLESYSTEMMOVE);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
if (enableSystemMove.isValid() && enableSystemMove.canConvert<bool>()) {
|
||||
#else
|
||||
if (enableSystemMove.isValid() && enableSystemMove.canConvert(QVariant::Bool)) {
|
||||
#endif
|
||||
ASSERT_EQ(pHandle->enableSystemMove(), enableSystemMove.toBool());
|
||||
} else {
|
||||
ASSERT_FALSE(pHandle->enableSystemMove());
|
||||
}
|
||||
|
||||
QVariant enableBlurWindow = window->property(ENABLEBLURWINDOW);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
if (enableBlurWindow.isValid() && enableBlurWindow.canConvert<bool>()) {
|
||||
#else
|
||||
if (enableBlurWindow.isValid() && enableBlurWindow.canConvert(QVariant::Bool)) {
|
||||
#endif
|
||||
ASSERT_EQ(pHandle->enableBlurWindow(), enableBlurWindow.toBool());
|
||||
} else {
|
||||
ASSERT_FALSE(pHandle->enableBlurWindow());
|
||||
}
|
||||
|
||||
QVariant autoInputMaskByClipPath = window->property(AUTOINPUTMASKBYCLIPPATH);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
if (autoInputMaskByClipPath.isValid() && autoInputMaskByClipPath.canConvert<bool>()) {
|
||||
#else
|
||||
if (autoInputMaskByClipPath.isValid() && autoInputMaskByClipPath.canConvert(QVariant::Bool)) {
|
||||
#endif
|
||||
ASSERT_EQ(pHandle->autoInputMaskByClipPath(), autoInputMaskByClipPath.toBool());
|
||||
} else {
|
||||
ASSERT_FALSE(pHandle->autoInputMaskByClipPath());
|
||||
|
|
|
|||
|
|
@ -50,12 +50,14 @@ TEST_F(TDWindowMangerHelper, testStaticFunction)
|
|||
|
||||
DWindowManagerHelper::setMotifDecorations(w->windowHandle(), DWindowManagerHelper::MotifDecorations(TestDecorations));
|
||||
DWindowManagerHelper::MotifDecorations mDecos = DWindowManagerHelper::getMotifDecorations(w->windowHandle());
|
||||
if (wm_helper->windowManagerName() == DWindowManagerHelper::KWinWM)
|
||||
if (wm_helper->windowManagerName() == DWindowManagerHelper::KWinWM) {
|
||||
ASSERT_EQ(mDecos, TestDecorations);
|
||||
}
|
||||
|
||||
mDecos = DWindowManagerHelper::setMotifDecorations(w->windowHandle(), DWindowManagerHelper::MotifDecorations(TestAllDecorations), true);
|
||||
if (wm_helper->windowManagerName() == DWindowManagerHelper::KWinWM)
|
||||
if (wm_helper->windowManagerName() == DWindowManagerHelper::KWinWM) {
|
||||
ASSERT_EQ(mDecos, TestAllDecorations);
|
||||
}
|
||||
|
||||
// 没有崩溃则测试成功
|
||||
enum { TestWindowType = DWindowManagerHelper::DesktopType | DWindowManagerHelper::MenuType };
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
DGUI_USE_NAMESPACE
|
||||
|
||||
class ut_XdgIconProxyEngine : public testing::Test
|
||||
class GTEST_API_ ut_XdgIconProxyEngine : public testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override;
|
||||
|
|
|
|||
|
|
@ -3,3 +3,4 @@ add_subdirectory(dci-image-converter)
|
|||
add_subdirectory(dci-icon-theme)
|
||||
add_subdirectory(dde-kwin-debug)
|
||||
add_subdirectory(image-handler)
|
||||
add_subdirectory(dci-iconfinder)
|
||||
|
|
|
|||
|
|
@ -1,12 +1,15 @@
|
|||
set(BIN_NAME dci-icon-theme)
|
||||
set(TARGET_NAME ${BIN_NAME}${DTK_VERSION_MAJOR})
|
||||
|
||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Concurrent REQUIRED)
|
||||
|
||||
add_executable(${TARGET_NAME}
|
||||
main.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(${TARGET_NAME} PRIVATE
|
||||
Qt${QT_VERSION_MAJOR}::Gui
|
||||
Qt${QT_VERSION_MAJOR}::Concurrent
|
||||
${LIB_NAME}
|
||||
)
|
||||
set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME ${BIN_NAME})
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@ For example, the tool is used in the following ways:
|
|||
dci-icon-theme /usr/share/icons/hicolor/256x256/apps -o ~/Desktop/hicolor -O 3=95
|
||||
dci-icon-theme -m *.png /usr/share/icons/hicolor/256x256/apps -o ~/Desktop/hicolor -O 3=95
|
||||
dci-icon-theme --fix-dark-theme <input dci files directory> -o <output directory path>
|
||||
dci-icon-theme --find <icon name>
|
||||
dci-icon-theme --find <icon name> -t bloom
|
||||
dci-icon-theme <input file directory> -o <output directory path> -s <csv file> -O <qualities>
|
||||
|
||||
|
||||
|
|
@ -34,8 +32,6 @@ Options:
|
|||
--fix-dark-theme Create symlinks from light theme for
|
||||
dark theme files.
|
||||
--find Find dci icon file path
|
||||
-t, --theme <theme name> Give a theme name to find dci icon file
|
||||
path
|
||||
-O, --scale-quality <scale quality> Quility of dci scaled icon image
|
||||
The value may like <scale size>=<quality
|
||||
value> e.g. 2=98:3=95
|
||||
|
|
|
|||
|
|
@ -9,16 +9,28 @@
|
|||
#include <QBuffer>
|
||||
#include <QDebug>
|
||||
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
#include <DDciFile>
|
||||
#include <DIconTheme>
|
||||
#include <DGuiApplicationHelper>
|
||||
#include <DPlatformTheme>
|
||||
#include <stdexcept>
|
||||
#include <atomic>
|
||||
|
||||
DCORE_USE_NAMESPACE
|
||||
DGUI_USE_NAMESPACE
|
||||
|
||||
// Custom exception for DCI processing errors
|
||||
class DciProcessingError : public std::runtime_error {
|
||||
public:
|
||||
explicit DciProcessingError(const QString &message, int code = -1)
|
||||
: std::runtime_error(message.toStdString()), errorCode(code) {}
|
||||
|
||||
int getErrorCode() const { return errorCode; }
|
||||
|
||||
private:
|
||||
int errorCode;
|
||||
};
|
||||
|
||||
#define MAX_SCALE 10
|
||||
#define INVALIDE_QUALITY -2
|
||||
#define SCALABLE_SIZE 256
|
||||
static int quality4Scaled[MAX_SCALE] = {};
|
||||
static inline void initQuality() {
|
||||
for (int i = 0; i < MAX_SCALE; ++i)
|
||||
|
|
@ -28,10 +40,45 @@ static inline void initQuality() {
|
|||
static inline void dciChecker(bool result, std::function<const QString()> cb) {
|
||||
if (!result) {
|
||||
qWarning() << "Failed on writing dci file" << cb();
|
||||
exit(-6);
|
||||
throw DciProcessingError("Failed on writing dci file", -6);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO 应该使用xdg图标查找规范解析index.theme来查找尺寸
|
||||
static int foundSize(const QFileInfo &fileInfo) {
|
||||
QDir dir = fileInfo.absoluteDir();
|
||||
|
||||
// 解析尺寸
|
||||
auto parseSize = [](const QString &dirName) -> int {
|
||||
bool ok;
|
||||
if (int size = dirName.toUInt(&ok); ok) {
|
||||
return size;
|
||||
}
|
||||
|
||||
if (dirName.contains('x') && dirName.split('x').size() == 2) {
|
||||
if (int size = dirName.split('x').first().toUInt(&ok); ok) {
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
if (dirName == "scalable") {
|
||||
return SCALABLE_SIZE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
if (int size = parseSize(dir.dirName()); size > 0) {
|
||||
return size;
|
||||
}
|
||||
|
||||
// 尝试找上一级目录
|
||||
if (!dir.cdUp())
|
||||
return 0;
|
||||
|
||||
return parseSize(dir.dirName());
|
||||
}
|
||||
|
||||
static inline QByteArray webpImageData(const QImage &image, int quality) {
|
||||
QByteArray data;
|
||||
QBuffer buffer(&data);
|
||||
|
|
@ -41,28 +88,18 @@ static inline QByteArray webpImageData(const QImage &image, int quality) {
|
|||
return data;
|
||||
}
|
||||
|
||||
static bool writeScaledImage(DDciFile &dci, const QString &imageFile, const QString &targetDir, int scale/* = 2*/)
|
||||
static bool writeScaledImage(DDciFile &dci, const QImage &image, const QString &targetDir, const int baseSize, int scale/* = 2*/)
|
||||
{
|
||||
QString sizeDir = targetDir.mid(1, targetDir.indexOf("/", 1) - 1);
|
||||
bool ok = false;
|
||||
int baseSize = sizeDir.toInt(&ok);
|
||||
if (!ok)
|
||||
baseSize = 256;
|
||||
|
||||
int size = scale * baseSize;
|
||||
QImageReader image(imageFile);
|
||||
if (!image.canRead()) {
|
||||
qWarning() << "Ignore the null image file:" << imageFile;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (image.supportsOption(QImageIOHandler::ScaledSize)) {
|
||||
image.setScaledSize(QSize(size, size));
|
||||
QImage img;
|
||||
if (image.width() == size) {
|
||||
img = image;
|
||||
} else {
|
||||
img = image.scaledToWidth(size, Qt::SmoothTransformation);
|
||||
}
|
||||
|
||||
dciChecker(dci.mkdir(targetDir + QString("/%1").arg(scale)), [&]{return dci.lastErrorString();});
|
||||
const QImage &img = image.read().scaledToWidth(size, Qt::SmoothTransformation);
|
||||
int quality = quality4Scaled[scale - 1];
|
||||
int quality = quality4Scaled[scale - 1];
|
||||
const QByteArray &data = webpImageData(img, quality);
|
||||
dciChecker(dci.writeFile(targetDir + QString("/%1/1.webp").arg(scale), data), [&]{return dci.lastErrorString();});
|
||||
|
||||
|
|
@ -71,13 +108,28 @@ static bool writeScaledImage(DDciFile &dci, const QString &imageFile, const QStr
|
|||
|
||||
static bool writeImage(DDciFile &dci, const QString &imageFile, const QString &targetDir)
|
||||
{
|
||||
QString sizeDir = targetDir.mid(1, targetDir.indexOf("/", 1) - 1);
|
||||
bool ok = false;
|
||||
int baseSize = sizeDir.toInt(&ok);
|
||||
if (!ok)
|
||||
baseSize = 256;
|
||||
|
||||
QImageReader reader(imageFile);
|
||||
if (!reader.canRead()) {
|
||||
qWarning() << "Ignore the null image file:" << imageFile;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_SCALE; ++i) {
|
||||
if (quality4Scaled[i] == INVALIDE_QUALITY)
|
||||
continue;
|
||||
int scale = i + 1;
|
||||
|
||||
if (!writeScaledImage(dci, imageFile, targetDir, i + 1))
|
||||
reader.setScaledSize(QSize(baseSize * scale, baseSize * scale));
|
||||
auto image = reader.read();
|
||||
if (!writeScaledImage(dci, image, targetDir, baseSize, scale))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -131,7 +183,7 @@ QMultiHash<QString, QString> parseIconFileSymlinkMap(const QString &csvFile) {
|
|||
QFile file(csvFile);
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
qWarning() << "Failed on open symlink map file:" << csvFile;
|
||||
exit(-7);
|
||||
throw DciProcessingError("Failed on open symlink map file", -7);
|
||||
}
|
||||
|
||||
QMultiHash<QString, QString> map;
|
||||
|
|
@ -219,8 +271,6 @@ int main(int argc, char *argv[])
|
|||
,
|
||||
"csv file");
|
||||
QCommandLineOption fixDarkTheme("fix-dark-theme", "Create symlinks from light theme for dark theme files.");
|
||||
QCommandLineOption iconFinder("find", "Find dci icon file path");
|
||||
QCommandLineOption themeOpt({"t","theme"}, "Give a theme name to find dci icon file path", "theme name");
|
||||
QCommandLineOption scaleQuality({"O","scale-quality"}, "Quility of dci scaled icon image\n"
|
||||
"The value may like <scale size>=<quality value> e.g. 2=98:3=95\n"
|
||||
"The quality factor must be in the range 0 to 100 or -1.\n"
|
||||
|
|
@ -229,8 +279,12 @@ int main(int argc, char *argv[])
|
|||
"The higher the quality, the larger the dci icon file size", "scale quality");
|
||||
|
||||
QGuiApplication a(argc, argv);
|
||||
|
||||
a.setApplicationName("dci-icon-theme");
|
||||
a.setApplicationVersion("0.0.6");
|
||||
a.setApplicationVersion(QString("%1.%2.%3")
|
||||
.arg(DTK_VERSION_MAJOR)
|
||||
.arg(DTK_VERSION_MINOR)
|
||||
.arg(DTK_VERSION_PATCH));
|
||||
|
||||
QCommandLineParser cp;
|
||||
cp.setApplicationDescription("dci-icon-theme tool is a command tool that generate dci icons from common icons.\n"
|
||||
|
|
@ -238,12 +292,10 @@ int main(int argc, char *argv[])
|
|||
"\t dci-icon-theme /usr/share/icons/hicolor/256x256/apps -o ~/Desktop/hicolor -O 3=95\n"
|
||||
"\t dci-icon-theme -m *.png /usr/share/icons/hicolor/256x256/apps -o ~/Desktop/hicolor -O 3=95\n"
|
||||
"\t dci-icon-theme --fix-dark-theme <input dci files directory> -o <output directory path> \n"
|
||||
"\t dci-icon-theme --find <icon name>\n"
|
||||
"\t dci-icon-theme --find <icon name> -t bloom\n"
|
||||
"\t dci-icon-theme <input file directory> -o <output directory path> -s <csv file> -O <qualities>\n"""
|
||||
);
|
||||
|
||||
cp.addOptions({fileFilter, outputDirectory, symlinkMap, fixDarkTheme, iconFinder, themeOpt, scaleQuality});
|
||||
cp.addOptions({fileFilter, outputDirectory, symlinkMap, fixDarkTheme, scaleQuality});
|
||||
cp.addPositionalArgument("source", "Search the given directory and it's subdirectories, "
|
||||
"get the files conform to rules of --match.",
|
||||
"~/dci-png-icons");
|
||||
|
|
@ -254,27 +306,11 @@ int main(int argc, char *argv[])
|
|||
if (a.arguments().size() == 1)
|
||||
cp.showHelp(-1);
|
||||
|
||||
bool isIconFinder = cp.isSet(iconFinder);
|
||||
if (cp.positionalArguments().isEmpty()) {
|
||||
qWarning() << "Not give a" << (isIconFinder ? "icon name." : "source directory.");
|
||||
qWarning() << "Not give a source directory.";
|
||||
cp.showHelp(-2);
|
||||
}
|
||||
|
||||
QString iconThemeName;
|
||||
if (cp.isSet(themeOpt)) {
|
||||
iconThemeName = cp.value(themeOpt);
|
||||
} else {
|
||||
iconThemeName = DGuiApplicationHelper::instance()->applicationTheme()->iconThemeName();
|
||||
}
|
||||
|
||||
if (isIconFinder) {
|
||||
QString iconName = cp.positionalArguments().value(0);
|
||||
|
||||
QString iconPath = DIconTheme::findDciIconFile(iconName, iconThemeName);
|
||||
qInfo() << iconName << "[" << iconThemeName << "]:" << iconPath;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!cp.isSet(outputDirectory)) {
|
||||
qWarning() << "Not give -o argument";
|
||||
cp.showHelp(-4);
|
||||
|
|
@ -295,10 +331,6 @@ int main(int argc, char *argv[])
|
|||
#endif
|
||||
QStringList qualityList = cp.value(scaleQuality).split(":", behavior);
|
||||
|
||||
#ifdef QT_DEBUG
|
||||
surfix = cp.value(scaleQuality).prepend("-");
|
||||
#endif
|
||||
|
||||
for (const QString &kv : qualityList) {
|
||||
auto sq = kv.split("=");
|
||||
if (sq.size() != 2) {
|
||||
|
|
@ -331,12 +363,17 @@ int main(int argc, char *argv[])
|
|||
|
||||
QMultiHash<QString, QString> symlinksMap;
|
||||
if (cp.isSet(symlinkMap)) {
|
||||
symlinksMap = parseIconFileSymlinkMap(cp.value(symlinkMap));
|
||||
try {
|
||||
symlinksMap = parseIconFileSymlinkMap(cp.value(symlinkMap));
|
||||
} catch (const DciProcessingError &e) {
|
||||
qWarning() << "Error parsing symlink map:" << e.what();
|
||||
return e.getErrorCode();
|
||||
}
|
||||
}
|
||||
|
||||
const QStringList nameFilter = cp.isSet(fileFilter) ? cp.values(fileFilter) : QStringList();
|
||||
const auto sourceDirectory = cp.positionalArguments();
|
||||
for (const auto &sd : qAsConst(sourceDirectory)) {
|
||||
for (const auto &sd : sourceDirectory) {
|
||||
QDir sourceDir(sd);
|
||||
if (!sourceDir.exists()) {
|
||||
qWarning() << "Ignore the non-exists directory:" << sourceDir;
|
||||
|
|
@ -369,6 +406,8 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
|
||||
// Collect all files first, grouped by icon name to avoid concurrent access to same DCI file
|
||||
QMap<QString, QList<QFileInfo>> iconGroups;
|
||||
QDirIterator di(sourceDir.absolutePath(), nameFilter,
|
||||
QDir::NoDotAndDotDot | QDir::Files,
|
||||
QDirIterator::Subdirectories);
|
||||
|
|
@ -380,7 +419,12 @@ int main(int argc, char *argv[])
|
|||
continue;
|
||||
|
||||
if (cp.isSet(fixDarkTheme)) {
|
||||
doFixDarkTheme(file, outputDir, symlinksMap);
|
||||
try {
|
||||
doFixDarkTheme(file, outputDir, symlinksMap);
|
||||
} catch (const DciProcessingError &e) {
|
||||
qWarning() << "Error fixing dark theme for file" << file.absoluteFilePath() << ":" << e.what();
|
||||
return e.getErrorCode();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -389,46 +433,86 @@ int main(int argc, char *argv[])
|
|||
continue;
|
||||
}
|
||||
|
||||
QString dirName = file.absoluteDir().dirName();
|
||||
bool isNum = false;
|
||||
dirName.toInt(&isNum);
|
||||
dirName.prepend("/");
|
||||
iconGroups[file.completeBaseName()].append(file);
|
||||
}
|
||||
|
||||
// Process with proper exception handling
|
||||
std::atomic<bool> hasError{false};
|
||||
int errorCode = 0;
|
||||
|
||||
// Process icon groups concurrently (each group shares same DCI file)
|
||||
QList<QString> iconNames = iconGroups.keys();
|
||||
QtConcurrent::blockingMap(iconNames, [&](const QString &iconName) {
|
||||
if (hasError.load()) return; // Skip if already has error
|
||||
|
||||
try {
|
||||
const QList<QFileInfo> &files = iconGroups[iconName];
|
||||
const QString dciFilePath(outputDir.absoluteFilePath(iconName) + surfix + ".dci");
|
||||
QScopedPointer<DDciFile> dciFile;
|
||||
|
||||
for (const QFileInfo &file : files) {
|
||||
QString dirName = file.absoluteDir().dirName();
|
||||
uint iconSize = foundSize(file);
|
||||
dirName = iconSize > 0 ? QString("/%1").arg(iconSize) : dirName.prepend("/");
|
||||
|
||||
QScopedPointer<DDciFile> dciFile;
|
||||
const QString dciFilePath(outputDir.absoluteFilePath(file.completeBaseName()) + surfix + ".dci");
|
||||
if (QFileInfo::exists(dciFilePath)) {
|
||||
dciFile.reset(new DDciFile(dciFilePath));
|
||||
if (dciFile->isValid() && dciFile->exists(dirName)) {
|
||||
qWarning() << "Skip exists dci file:" << dciFilePath << dirName << dciFile->list(dirName);
|
||||
continue;
|
||||
// Initialize DCI file once per icon group
|
||||
if (dciFile.isNull()) {
|
||||
if (QFileInfo::exists(dciFilePath)) {
|
||||
dciFile.reset(new DDciFile(dciFilePath));
|
||||
}
|
||||
if (dciFile.isNull() || !dciFile->isValid()) {
|
||||
dciFile.reset(new DDciFile);
|
||||
}
|
||||
}
|
||||
if (dciFile->exists(dirName)) {
|
||||
qWarning() << "Skip exists dci file:" << dciFilePath << dirName << dciFile->list(dirName);
|
||||
continue;
|
||||
}
|
||||
|
||||
qInfo() << "Writing to dci file:" << file.absoluteFilePath() << "==>" << dciFilePath;
|
||||
|
||||
QString sizeDir = iconSize > 0 ? dirName : "/256"; // "/256" as default
|
||||
QString normalLight = sizeDir + "/normal.light"; // "/256/normal.light"
|
||||
QString normalDark = sizeDir + "/normal.dark"; // "/256/normal.dark"
|
||||
|
||||
if (dciFile->exists(sizeDir)) {
|
||||
qWarning() << "Skip exists dci file:" << dciFilePath << sizeDir << dciFile->list(sizeDir);
|
||||
continue;
|
||||
}
|
||||
|
||||
dciChecker(dciFile->mkdir(sizeDir), [&]{return dciFile->lastErrorString();});
|
||||
dciChecker(dciFile->mkdir(normalLight), [&]{return dciFile->lastErrorString();});
|
||||
if (!writeImage(*dciFile, file.filePath(), normalLight))
|
||||
continue;
|
||||
|
||||
dciChecker(dciFile->mkdir(normalDark), [&]{return dciFile->lastErrorString();});
|
||||
QFileInfo darkIcon(file.dir().absoluteFilePath("dark/" + file.fileName()));
|
||||
if (darkIcon.exists()) {
|
||||
writeImage(*dciFile, darkIcon.filePath(), normalDark);
|
||||
} else {
|
||||
dciChecker(recursionLink(*dciFile, normalLight, normalDark), [&]{return dciFile->lastErrorString();});
|
||||
}
|
||||
}
|
||||
|
||||
// Write DCI file once per icon group
|
||||
if (!dciFile.isNull()) {
|
||||
dciChecker(dciFile->writeToFile(dciFilePath), [&]{return dciFile->lastErrorString();});
|
||||
|
||||
// Create symlinks for all files in this group
|
||||
for (const QFileInfo &file : files) {
|
||||
makeLink(file, outputDir, dciFilePath, symlinksMap);
|
||||
}
|
||||
}
|
||||
} catch (const DciProcessingError &e) {
|
||||
qWarning() << "Error processing icon group" << iconName << ":" << e.what();
|
||||
hasError.store(true);
|
||||
errorCode = e.getErrorCode();
|
||||
}
|
||||
});
|
||||
|
||||
qInfo() << "Writing to dci file:" << file.absoluteFilePath() << "==>" << dciFilePath;
|
||||
|
||||
if (dciFile.isNull() || !dciFile->isValid())
|
||||
dciFile.reset(new DDciFile);
|
||||
|
||||
QString sizeDir = isNum ? dirName : "/256"; // "/256"
|
||||
QString normalLight = sizeDir + "/normal.light"; // "/256/normal.light"
|
||||
QString normalDark = sizeDir + "/normal.dark"; // "/256/normal.dark"
|
||||
|
||||
dciChecker(dciFile->mkdir(sizeDir), [&]{return dciFile->lastErrorString();});
|
||||
dciChecker(dciFile->mkdir(normalLight), [&]{return dciFile->lastErrorString();});
|
||||
if (!writeImage(*dciFile, file.filePath(), normalLight))
|
||||
continue;
|
||||
|
||||
dciChecker(dciFile->mkdir(normalDark), [&]{return dciFile->lastErrorString();});
|
||||
QFileInfo darkIcon(file.dir().absoluteFilePath("dark/" + file.fileName()));
|
||||
if (darkIcon.exists()) {
|
||||
writeImage(*dciFile, darkIcon.filePath(), normalDark);
|
||||
} else {
|
||||
dciChecker(recursionLink(*dciFile, normalLight, normalDark), [&]{return dciFile->lastErrorString();});
|
||||
}
|
||||
|
||||
dciChecker(dciFile->writeToFile(dciFilePath), [&]{return dciFile->lastErrorString();});
|
||||
|
||||
makeLink(file, outputDir, dciFilePath, symlinksMap);
|
||||
if (hasError.load()) {
|
||||
qWarning() << "Encountered errors during DCI file writing" << errorCode;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
set(BIN_NAME dci-iconfinder)
|
||||
set(TARGET_NAME ${BIN_NAME}${DTK_VERSION_MAJOR})
|
||||
|
||||
add_executable(${TARGET_NAME}
|
||||
main.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(${TARGET_NAME} PRIVATE
|
||||
Qt${QT_VERSION_MAJOR}::Gui
|
||||
${LIB_NAME}
|
||||
)
|
||||
set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME ${BIN_NAME})
|
||||
|
||||
install(TARGETS ${TARGET_NAME} DESTINATION "${TOOL_INSTALL_DIR}")
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
// SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QCommandLineParser>
|
||||
#include <QDebug>
|
||||
|
||||
#include <DIconTheme>
|
||||
|
||||
DGUI_USE_NAMESPACE
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QGuiApplication a(argc, argv);
|
||||
|
||||
a.setApplicationName("dci-iconfinder");
|
||||
a.setApplicationVersion(QString("%1.%2.%3")
|
||||
.arg(DTK_VERSION_MAJOR)
|
||||
.arg(DTK_VERSION_MINOR)
|
||||
.arg(DTK_VERSION_PATCH));
|
||||
|
||||
QCommandLineParser cp;
|
||||
cp.setApplicationDescription(
|
||||
"dci-iconfinder tool is a command tool that find dci icons in the icon "
|
||||
"theme.\n"
|
||||
"For example, the tool is used in the following ways: \n"
|
||||
"\t dci-iconfinder <icon name>\n"
|
||||
"\t dci-iconfinder <icon name> -t bloom\n");
|
||||
|
||||
QCommandLineOption themeOpt({"t", "theme"},
|
||||
"Give a theme name to find dci icon file path",
|
||||
"theme name");
|
||||
cp.addOptions({themeOpt});
|
||||
cp.addPositionalArgument("iconnames", "The icon names to search for",
|
||||
"iconnames");
|
||||
cp.addHelpOption();
|
||||
cp.addVersionOption();
|
||||
cp.process(a);
|
||||
|
||||
if (cp.positionalArguments().isEmpty()) {
|
||||
qWarning() << "Not give icon name.";
|
||||
cp.showHelp(-1);
|
||||
}
|
||||
|
||||
QString iconThemeName;
|
||||
if (cp.isSet(themeOpt)) {
|
||||
iconThemeName = cp.value(themeOpt);
|
||||
} else {
|
||||
iconThemeName = QIcon::themeName();
|
||||
}
|
||||
|
||||
const auto icons = cp.positionalArguments();
|
||||
for (const QString &iconName : icons) {
|
||||
QString iconPath = DIconTheme::findDciIconFile(iconName, iconThemeName);
|
||||
if (!iconPath.isEmpty())
|
||||
qInfo().noquote() << iconName << "[" << iconThemeName << "]:" << iconPath;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in New Issue