Compare commits

..

1 Commits

60 changed files with 1073 additions and 2144 deletions

19
.github/stale.yml vendored
View File

@ -1,19 +0,0 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 60
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- pinned
- security
- feature request
- enhancement
# Label to use when marking an issue as stale
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.17.0 FATAL_ERROR)
cmake_minimum_required(VERSION 3.3.0 FATAL_ERROR)
# meta data
set(META_PROJECT_NAME qtutilities)
@ -9,7 +9,7 @@ set(META_APP_URL "https://github.com/${META_APP_AUTHOR}/${META_PROJECT_NAME}")
set(META_APP_DESCRIPTION
"Common Qt related C++ classes and routines used by my applications such as dialogs, widgets and models")
set(META_VERSION_MAJOR 6)
set(META_VERSION_MINOR 14)
set(META_VERSION_MINOR 5)
set(META_VERSION_PATCH 1)
set(META_APP_VERSION ${META_VERSION_MAJOR}.${META_VERSION_MINOR}.${META_VERSION_PATCH})
@ -90,8 +90,7 @@ if (ANDROID)
list(APPEND CMAKE_TEMPLATE_FILES cmake/templates/android-deployment.json.in)
endif ()
set(TS_FILES translations/${META_PROJECT_NAME}_zh_CN.ts translations/${META_PROJECT_NAME}_de_DE.ts
translations/${META_PROJECT_NAME}_en_US.ts)
set(TS_FILES translations/${META_PROJECT_NAME}_de_DE.ts translations/${META_PROJECT_NAME}_en_US.ts)
set(DOC_FILES README.md)
@ -116,35 +115,28 @@ set(SCRIPT_FILES scripts/required_icons.sh)
# required to include CMake modules from own project directory
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules" "${CMAKE_MODULE_PATH}")
# find c++utilities
set(CONFIGURATION_PACKAGE_SUFFIX
""
CACHE STRING "sets the suffix for find_package() calls to packages configured via c++utilities")
set(PACKAGE_NAMESPACE
""
CACHE STRING "sets the namespace (prefix) for find_package() calls to packages configured via c++utilities")
if (PACKAGE_NAMESPACE)
set(PACKAGE_NAMESPACE_PREFIX "${PACKAGE_NAMESPACE}-")
endif ()
find_package(${PACKAGE_NAMESPACE_PREFIX}c++utilities${CONFIGURATION_PACKAGE_SUFFIX} 5.5.0 REQUIRED)
use_cpp_utilities()
# configure platform specific capslock detection for enterpassworddialog.cpp
if (WIN32)
set(HAVE_PLATFORM_SPECIFIC_CAPSLOCK_DETECTION ON)
if (WIN32
OR (UNIX
AND NOT APPLE
AND NOT ANDROID))
set(ENABLE_CAPSLOCK_DETECTION_BY_DEFAULT ON)
else ()
include(3rdParty)
use_package(TARGET_NAME X11::X11 PACKAGE_NAME X11 OPTIONAL)
if (TARGET X11::X11)
set_property(
SOURCE enterpassworddialog/enterpassworddialog.cpp
APPEND
PROPERTY COMPILE_DEFINITIONS X_AVAILABLE)
set(HAVE_PLATFORM_SPECIFIC_CAPSLOCK_DETECTION ON)
endif ()
set(ENABLE_CAPSLOCK_DETECTION_BY_DEFAULT OFF)
endif ()
option(CAPSLOCK_DETECTION "enables capslock detection" ${HAVE_PLATFORM_SPECIFIC_CAPSLOCK_DETECTION})
option(CAPSLOCK_DETECTION "enables capslock detection" ${ENABLE_CAPSLOCK_DETECTION_BY_DEFAULT})
if (CAPSLOCK_DETECTION)
if (WIN32)
# WinAPI provides functions to provide capslock detection
set(HAVE_PLATFORM_SPECIFIC_CAPSLOCK_DETECTION ON)
else ()
# X11 can provide functions for capslock detection under non-Windows environments
find_package(X11)
if (X11_FOUND)
list(APPEND LIBRARIES ${X11_LIBRARIES})
set(HAVE_PLATFORM_SPECIFIC_CAPSLOCK_DETECTION ON)
endif ()
endif ()
if (NOT HAVE_PLATFORM_SPECIFIC_CAPSLOCK_DETECTION)
message(FATAL_ERROR "No backend for capslock detection found (WinAPI or X11 must be provided)")
endif ()
@ -176,6 +168,13 @@ else ()
message(STATUS "D-Bus notifications disabled")
endif ()
# find c++utilities
set(CONFIGURATION_PACKAGE_SUFFIX
""
CACHE STRING "sets the suffix for find_package() calls to packages configured via c++utilities")
find_package(c++utilities${CONFIGURATION_PACKAGE_SUFFIX} 5.5.0 REQUIRED)
use_cpp_utilities()
# include modules to apply configuration
include(BasicConfig)
include(QtGuiConfig)
@ -192,7 +191,7 @@ include(ConfigHeader)
# configure test target
include(TestUtilities)
list(APPEND QT_TEST_LIBRARIES ${CPP_UTILITIES_LIB} ${META_TARGET_NAME})
set(QT_TEST_LIBRARIES ${CPP_UTILITIES_LIB} ${META_TARGET_NAME})
use_qt_module(LIBRARIES_VARIABLE "QT_TEST_LIBRARIES" PREFIX "${QT_PACKAGE_PREFIX}" MODULE "Test")
foreach (TEST ${QT_TESTS})
configure_test_target(TEST_NAME "${TEST}_tests" SRC_FILES "tests/${TEST}.cpp" LIBRARIES "${QT_TEST_LIBRARIES}")

View File

@ -6,12 +6,5 @@ Qt utilities depends on c++utilities and is built in the same way. So checkout t
instructions. The documentation for various CMake variables influencing the build is also provided in the
c++utilities repository.
The library also depends on the following Qt modules (only the latest Qt 5 and Qt 6 version tested):
core, gui, widgets
The library also depends on the following Qt modules (version 5.6 or higher): core, gui, widgets
Some header files also require further Qt modules.
## Copyright notice and license
Copyright © 2015-2024 Marius Kittler
All code is licensed under [GPL-2-or-later](LICENSE).

View File

@ -44,7 +44,7 @@ AboutDialog::AboutDialog(QWidget *parent, const QString &applicationName, const
{
m_ui->setupUi(this);
makeHeading(m_ui->productNameLabel);
setStyleSheet(dialogStyleForPalette(palette()));
setStyleSheet(dialogStyle());
setWindowFlags((windowFlags()) & ~(Qt::WindowMinMaxButtonsHint | Qt::WindowContextHelpButtonHint | Qt::WindowFullscreenButtonHint));
if (!applicationName.isEmpty()) {
m_ui->productNameLabel->setText(applicationName);
@ -58,11 +58,7 @@ AboutDialog::AboutDialog(QWidget *parent, const QString &applicationName, const
m_ui->creatorLabel->setText(creator);
} else {
// add "developed by " before creator name
auto setCreator = [this, creator = std::move(creator)] {
m_ui->creatorLabel->setText(tr("developed by %1").arg(creator.isEmpty() ? QApplication::organizationName() : creator));
};
setCreator();
connect(this, &AboutDialog::retranslationRequired, this, std::move(setCreator));
m_ui->creatorLabel->setText(tr("developed by %1").arg(creator.isEmpty() ? QApplication::organizationName() : creator));
}
m_ui->versionLabel->setText(version.isEmpty() ? QApplication::applicationVersion() : version);
const auto &deps(dependencyVersions.size() ? dependencyVersions : CppUtilities::applicationInfo.dependencyVersions);
@ -76,14 +72,10 @@ AboutDialog::AboutDialog(QWidget *parent, const QString &applicationName, const
% linkedAgainst.join(QStringLiteral("</li><li>")) % QStringLiteral("</li></ul>"));
}
if (!website.isEmpty() || CppUtilities::applicationInfo.url) {
auto setWebsite = [this, website = std::move(website)] {
m_ui->websiteLabel->setText(tr("For updates and bug reports visit the <a href=\"%1\" "
"style=\"text-decoration: underline; color: palette(link);\">project "
"website</a>.")
.arg(!website.isEmpty() ? website : QString::fromUtf8(CppUtilities::applicationInfo.url)));
};
setWebsite();
connect(this, &AboutDialog::retranslationRequired, this, std::move(setWebsite));
m_ui->websiteLabel->setText(tr("For updates and bug reports visit the <a href=\"%1\" "
"style=\"text-decoration: underline; color: palette(link);\">project "
"website</a>.")
.arg(!website.isEmpty() ? website : QString::fromUtf8(CppUtilities::applicationInfo.url)));
} else {
m_ui->websiteLabel->hide();
}
@ -96,9 +88,7 @@ AboutDialog::AboutDialog(QWidget *parent, const QString &applicationName, const
: new QGraphicsPixmapItem(QPixmap::fromImage(image));
m_iconScene->addItem(item);
m_ui->graphicsView->setScene(m_iconScene);
auto setQtVersion = [this] { m_ui->qtVersionLabel->setText(tr("Using <a href=\"qtversion\">Qt %1</a>").arg(QString::fromUtf8(qVersion()))); };
setQtVersion();
connect(this, &AboutDialog::retranslationRequired, this, std::move(setQtVersion));
m_ui->qtVersionLabel->setText(tr("Using <a href=\"qtversion\">Qt %1</a>").arg(QString::fromUtf8(qVersion())));
connect(m_ui->qtVersionLabel, &QLabel::linkActivated, this, &AboutDialog::linkActivated);
centerWidget(this, parentWidget());
}
@ -128,22 +118,6 @@ AboutDialog::~AboutDialog()
{
}
bool AboutDialog::event(QEvent *event)
{
const auto res = QDialog::event(event);
switch (event->type()) {
case QEvent::PaletteChange:
setStyleSheet(dialogStyleForPalette(palette()));
break;
case QEvent::LanguageChange:
setWindowTitle(QCoreApplication::translate("QtUtilities::AboutDialog", "About", nullptr));
emit retranslationRequired();
break;
default:;
}
return res;
}
void AboutDialog::linkActivated(const QString &link)
{
if (link == QLatin1String("qtversion")) {

View File

@ -27,12 +27,6 @@ public:
explicit AboutDialog(QWidget *parent, const QString &website = QString(), const QString &description = QString(), const QImage &image = QImage());
~AboutDialog() override;
Q_SIGNALS:
void retranslationRequired();
protected:
bool event(QEvent *event) override;
private Q_SLOTS:
void linkActivated(const QString &link);

View File

@ -1,7 +1,4 @@
cmake_minimum_required(VERSION 3.17.0 FATAL_ERROR)
message(DEPRECATION "Do not use the AndroidApk module anymore. It broke after some minor Qt 5 version. As of Qt 6 the "
"CMake functions that come with Qt itself are sufficient.")
cmake_minimum_required(VERSION 3.3.0 FATAL_ERROR)
# adds a target to create an Android APK with the help of androiddeployqt if target platform is Android

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.17.0 FATAL_ERROR)
cmake_minimum_required(VERSION 3.3.0 FATAL_ERROR)
# applies Qt specific configuration notes: For GUI applications, QtGuiConfig must be included before. This module must always
# be included before AppTarget/LibraryTarget.
@ -66,6 +66,10 @@ if (IMPORTED_KF_MODULES)
endif ()
# find and use the required Qt/KF modules
set(QT_PACKAGE_PREFIX
"Qt5"
CACHE STRING "specifies the prefix for Qt packages")
string(TOLOWER "${QT_PACKAGE_PREFIX}" QT_PACKAGE_PREFIX_LOWER)
set(QT_LINGUIST_TOOLS_PACKAGE "${QT_PACKAGE_PREFIX}LinguistTools")
set(QT_QMAKE_TARGET "${QT_PACKAGE_PREFIX}::qmake")
foreach (MODULE ${QT_MODULES})
@ -75,6 +79,9 @@ foreach (MODULE ${QT_MODULES})
endif ()
use_qt_module(PREFIX "${QT_PACKAGE_PREFIX}" MODULE "${MODULE}" ${MODULE_OPTIONS})
endforeach ()
set(KF_PACKAGE_PREFIX
"KF5"
CACHE STRING "specifies the prefix for KDE Frameworks packages")
foreach (MODULE ${KF_MODULES})
unset(MODULE_OPTIONS)
if ("${MODULE}" IN_LIST META_PUBLIC_KF_MODULES)
@ -103,43 +110,15 @@ foreach (MODULE ${IMPORTED_KF_MODULES})
endif ()
endforeach ()
# enable TLS support by default when using Qt Network (relevant for linking against static plugin)
if (NOT DEFINED TLS_SUPPORT)
if (Network IN_LIST QT_MODULES OR Network IN_LIST IMPORTED_QT_MODULES)
set(TLS_SUPPORT ON)
else ()
set(TLS_SUPPORT OFF)
endif ()
endif ()
# allow configuring certain features when linking against static Qt
option(OPENGL_SUPPORT "whether to enable native Wayland support (when linking against static Qt)" ON)
option(NATIVE_WAYLAND_SUPPORT "whether to enable native Wayland support (when linking against static Qt)" ON)
option(NATIVE_WAYLAND_EGL_SUPPORT "specifies whether to enable native Wayland-EGL support (when linking against static Qt)"
OFF)
# built-in platform, imageformat and iconengine plugins when linking statically against Qt
if (TARGET "${QT_PACKAGE_PREFIX}::Core")
get_target_property(QT_TARGET_TYPE "${QT_PACKAGE_PREFIX}::Core" TYPE)
endif ()
if (STATIC_LINKAGE OR QT_TARGET_TYPE STREQUAL STATIC_LIBRARY)
if (META_PROJECT_IS_APPLICATION)
set(QT_PLUGINS_LIBRARIES_VARIABLE PRIVATE_LIBRARIES)
else ()
set(QT_PLUGINS_LIBRARIES_VARIABLE QT_TEST_LIBRARIES)
endif ()
message(
STATUS
"Linking ${META_PROJECT_NAME} (${QT_PLUGINS_LIBRARIES_VARIABLE}) against Qt plugins because static linkage is enabled or a static Qt build is used."
)
if (STATIC_LINKAGE AND META_PROJECT_IS_APPLICATION)
message(STATUS "Linking application ${META_PROJECT_NAME} against Qt plugins because static linkage is enabled.")
if (Gui IN_LIST QT_MODULES
OR Widgets IN_LIST QT_MODULES
OR Quick IN_LIST QT_MODULES)
if (WIN32 AND TARGET "${QT_PACKAGE_PREFIX}::QWindowsIntegrationPlugin")
if (WIN32)
use_qt_module(
LIBRARIES_VARIABLE
"${QT_PLUGINS_LIBRARIES_VARIABLE}"
PREFIX
"${QT_PACKAGE_PREFIX}"
MODULE
@ -147,10 +126,8 @@ if (STATIC_LINKAGE OR QT_TARGET_TYPE STREQUAL STATIC_LIBRARY)
PLUGINS
WindowsIntegration
ONLY_PLUGINS)
elseif (APPLE AND TARGET "${QT_PACKAGE_PREFIX}::QCocoaIntegrationPlugin")
elseif (APPLE)
use_qt_module(
LIBRARIES_VARIABLE
"${QT_PLUGINS_LIBRARIES_VARIABLE}"
PREFIX
"${QT_PACKAGE_PREFIX}"
MODULE
@ -158,23 +135,8 @@ if (STATIC_LINKAGE OR QT_TARGET_TYPE STREQUAL STATIC_LIBRARY)
PLUGINS
CocoaIntegration
ONLY_PLUGINS)
endif ()
if (UNIX AND TARGET "${QT_PACKAGE_PREFIX}::QOffscreenIntegrationPlugin")
elseif (TARGET "${QT_PACKAGE_PREFIX}::QXcbIntegrationPlugin")
use_qt_module(
LIBRARIES_VARIABLE
"${QT_PLUGINS_LIBRARIES_VARIABLE}"
PREFIX
"${QT_PACKAGE_PREFIX}"
MODULE
Gui
PLUGINS
OffscreenIntegration
ONLY_PLUGINS)
endif ()
if (TARGET "${QT_PACKAGE_PREFIX}::QXcbIntegrationPlugin")
use_qt_module(
LIBRARIES_VARIABLE
"${QT_PLUGINS_LIBRARIES_VARIABLE}"
PREFIX
"${QT_PACKAGE_PREFIX}"
MODULE
@ -182,146 +144,19 @@ if (STATIC_LINKAGE OR QT_TARGET_TYPE STREQUAL STATIC_LIBRARY)
PLUGINS
XcbIntegration
ONLY_PLUGINS)
endif ()
if (OPENGL_SUPPORT AND TARGET "${QT_PACKAGE_PREFIX}::QXcbEglIntegrationPlugin")
use_qt_module(
LIBRARIES_VARIABLE
"${QT_PLUGINS_LIBRARIES_VARIABLE}"
PREFIX
"${QT_PACKAGE_PREFIX}"
MODULE
Gui
PLUGINS
XcbEglIntegration
ONLY_PLUGINS)
endif ()
if (OPENGL_SUPPORT AND TARGET "${QT_PACKAGE_PREFIX}::QXcbGlxIntegrationPlugin")
use_qt_module(
LIBRARIES_VARIABLE
"${QT_PLUGINS_LIBRARIES_VARIABLE}"
PREFIX
"${QT_PACKAGE_PREFIX}"
MODULE
Gui
PLUGINS
XcbGlxIntegration
ONLY_PLUGINS)
endif ()
set(QT_CONFIG_USE_WAYLAND_INTEGRATION NO)
set(QT_CONFIG_WAYLAND_CLIENT_PLUGINS WaylandXdgShellIntegration WaylandWlShellIntegration WaylandIviShellIntegration
WaylandQtShellIntegration)
if (NATIVE_WAYLAND_SUPPORT AND TARGET "${QT_PACKAGE_PREFIX}::QWaylandIntegrationPlugin")
use_qt_module(
LIBRARIES_VARIABLE
"${QT_PLUGINS_LIBRARIES_VARIABLE}"
PREFIX
"${QT_PACKAGE_PREFIX}"
MODULE
Gui
PLUGINS
WaylandIntegration
ONLY_PLUGINS)
set(QT_CONFIG_USE_WAYLAND_INTEGRATION YES)
endif ()
if (NATIVE_WAYLAND_EGL_SUPPORT AND TARGET "${QT_PACKAGE_PREFIX}::QWaylandEglPlatformIntegrationPlugin")
use_qt_module(
LIBRARIES_VARIABLE
"${QT_PLUGINS_LIBRARIES_VARIABLE}"
PREFIX
"${QT_PACKAGE_PREFIX}"
MODULE
Gui
PLUGINS
WaylandEglPlatformIntegration
ONLY_PLUGINS)
set(QT_CONFIG_USE_WAYLAND_INTEGRATION YES)
list(APPEND QT_CONFIG_WAYLAND_CLIENT_PLUGINS WaylandEglClientBuffer)
endif ()
if (QT_CONFIG_USE_WAYLAND_INTEGRATION)
use_qt_module(
LIBRARIES_VARIABLE
"${QT_PLUGINS_LIBRARIES_VARIABLE}"
PREFIX
"${QT_PACKAGE_PREFIX}"
MODULE
WaylandClient
PLUGINS
${QT_CONFIG_WAYLAND_CLIENT_PLUGINS}
ONLY_PLUGINS
PLUGINS_OPTIONAL)
else ()
message(WARNING "The required platform plugin for your platform is unknown an can not be linked in statically.")
endif ()
endif ()
# ensure a TLS plugin is built-in when available and when creating an app using Qt Network - required since Qt 6.2.0
# which "pluginized" TLS support
if (TLS_SUPPORT)
set(KNOWN_TLS_PLUGINS ${META_TLS_PLUGINS} SchannelBackend TlsBackendOpenSSL)
set(USED_TLS_PLUGINS)
foreach (TLS_PLUGIN ${KNOWN_TLS_PLUGINS})
if (TARGET "${QT_PACKAGE_PREFIX}::Q${TLS_PLUGIN}Plugin")
use_qt_module(
LIBRARIES_VARIABLE
"${QT_PLUGINS_LIBRARIES_VARIABLE}"
PREFIX
"${QT_PACKAGE_PREFIX}"
MODULE
Network
PLUGINS
${TLS_PLUGIN}
ONLY_PLUGINS)
list(APPEND USED_TLS_PLUGINS "${TLS_PLUGIN}")
break() # one plugin is sufficient
endif ()
endforeach ()
# allow importing TLS plugins via qtconfig.h
if (USED_TLS_PLUGINS)
list_to_string(" " "\\\n Q_IMPORT_PLUGIN(Q" ")" "${USED_TLS_PLUGINS}" USED_TLS_PLUGINS_ARRAY)
endif ()
endif ()
# enable network information support for projects setting NETWORK_INFORMATION_SUPPORT explicitly
if (NETWORK_INFORMATION_SUPPORT)
set(KNOWN_NETWORK_INFORMATION_PLUGINS
${META_NETWORK_INFORMATION_PLUGINS} NetworkManagerNetworkInformation GlibNetworkInformation NLMNI
AndroidNetworkInformation SCNetworkReachabilityNetworkInformation)
set(USED_NETWORK_INFORMATION_PLUGINS)
foreach (PLUGIN ${KNOWN_NETWORK_INFORMATION_PLUGINS})
if (TARGET "${QT_PACKAGE_PREFIX}::Q${PLUGIN}Plugin")
use_qt_module(
LIBRARIES_VARIABLE
"${QT_PLUGINS_LIBRARIES_VARIABLE}"
PREFIX
"${QT_PACKAGE_PREFIX}"
MODULE
Network
PLUGINS
${PLUGIN}
ONLY_PLUGINS)
if (PLUGIN STREQUAL NLMNI)
set(PLUGIN NetworkListManagerNetworkInformation)
endif ()
list(APPEND USED_NETWORK_INFORMATION_PLUGINS "${PLUGIN}")
endif ()
endforeach ()
# allow importing network information plugins via qtconfig.h
if (USED_NETWORK_INFORMATION_PLUGINS)
list_to_string(" " "\\\n Q_IMPORT_PLUGIN(Q" "BackendFactory)" "${USED_NETWORK_INFORMATION_PLUGINS}"
USED_NETWORK_INFORMATION_PLUGINS_ARRAY)
endif ()
endif ()
# ensure all available widget style plugins are built-in when creating a Qt Widgets application - required since Qt 5.10
# because the styles have been "pluginized" (see commit 4f3249f)
set(KNOWN_WIDGET_STYLE_PLUGINS ModernWindowsStyle WindowsVistaStyle MacStyle AndroidStyle)
# ensure all available widget style plugins are built-in when creating a Qt Widgets application note: required since Qt
# 5.10 because the styles have been "pluginized" (see commit 4f3249f)
set(KNOWN_WIDGET_STYLE_PLUGINS WindowsVistaStyle MacStyle AndroidStyle)
set(USED_WIDGET_STYLE_PLUGINS)
if (Widgets IN_LIST QT_MODULES)
foreach (WIDGET_STYLE_PLUGIN ${KNOWN_WIDGET_STYLE_PLUGINS})
if (TARGET "${QT_PACKAGE_PREFIX}::Q${WIDGET_STYLE_PLUGIN}Plugin")
use_qt_module(
LIBRARIES_VARIABLE
"${QT_PLUGINS_LIBRARIES_VARIABLE}"
PREFIX
"${QT_PACKAGE_PREFIX}"
MODULE
@ -333,7 +168,7 @@ if (STATIC_LINKAGE OR QT_TARGET_TYPE STREQUAL STATIC_LIBRARY)
endif ()
endforeach ()
# allow importing widget style plugins via qtconfig.h
# allow importing image format plugins via qtconfig.h
if (USED_WIDGET_STYLE_PLUGINS)
list_to_string(" " "\\\n Q_IMPORT_PLUGIN(Q" "Plugin)" "${USED_WIDGET_STYLE_PLUGINS}"
WIDGET_STYLE_PLUGINS_ARRAY)
@ -349,8 +184,6 @@ if (STATIC_LINKAGE OR QT_TARGET_TYPE STREQUAL STATIC_LIBRARY)
list(REMOVE_ITEM IMAGE_FORMAT_SUPPORT Svg)
else ()
use_qt_module(
LIBRARIES_VARIABLE
"${QT_PLUGINS_LIBRARIES_VARIABLE}"
PREFIX
"${QT_PACKAGE_PREFIX}"
MODULE
@ -367,12 +200,10 @@ if (STATIC_LINKAGE OR QT_TARGET_TYPE STREQUAL STATIC_LIBRARY)
# ensure SVG plugins are built-in if configured
if ((SVG_SUPPORT OR SVG_ICON_SUPPORT) AND NOT Svg IN_LIST QT_MODULES)
use_qt_module(LIBRARIES_VARIABLE "${QT_PLUGINS_LIBRARIES_VARIABLE}" PREFIX "${QT_PACKAGE_PREFIX}" MODULE Svg)
use_qt_module(PREFIX "${QT_PACKAGE_PREFIX}" MODULE Svg)
endif ()
if (SVG_SUPPORT)
use_qt_module(
LIBRARIES_VARIABLE
"${QT_PLUGINS_LIBRARIES_VARIABLE}"
PREFIX
"${QT_PACKAGE_PREFIX}"
MODULE
@ -383,8 +214,6 @@ if (STATIC_LINKAGE OR QT_TARGET_TYPE STREQUAL STATIC_LIBRARY)
endif ()
if (SVG_ICON_SUPPORT)
use_qt_module(
LIBRARIES_VARIABLE
"${QT_PLUGINS_LIBRARIES_VARIABLE}"
PREFIX
"${QT_PACKAGE_PREFIX}"
MODULE
@ -401,7 +230,6 @@ option(BUILTIN_TRANSLATIONS_OF_QT "enables/disables built-in translations of Qt
"${BUILTIN_TRANSLATIONS}")
# determine relevant Qt translation files
string(TOLOWER "${QT_PACKAGE_PREFIX}" QT_PACKAGE_PREFIX_LOWER)
set(QT_TRANSLATION_FILES)
set(QT_TRANSLATION_SEARCH_PATHS)
query_qmake_variable_path(QT_INSTALL_TRANSLATIONS)
@ -452,7 +280,7 @@ if (NOT QT_TRANSLATIONS_FOUND)
endif ()
# emit warning if no Qt translations found but built-in translations are enabled
if (BUILTIN_TRANSLATIONS_OF_QT AND NOT QT_TRANSLATION_FILES)
if (BUILTIN_TRANSLATIONS AND NOT QT_TRANSLATION_FILES)
message(
WARNING
"Unable to find translations of Qt itself so Qt's translation files will not be built-in. Be sure Qt translations (https://code.qt.io/cgit/qt/qttranslations.git) are installed. Was looking under: ${QT_TRANSLATION_SEARCH_PATHS}"
@ -575,151 +403,117 @@ if (REQUIRED_ICONS)
set(BUILTIN_ICON_THEMES
""
CACHE STRING "specifies icon themes to be built-in")
set(BUILTIN_ICON_THEMES_SEARCH_PATH
""
CACHE PATH "specifies the search path for icon themes to be built-in")
option(BUILTIN_ICON_THEMES_IN_LIBRARIES "specifies whether icon themes should also be built-in when building libraries"
OFF)
if (BUILTIN_ICON_THEMES AND (BUILTIN_ICON_THEMES_IN_LIBRARIES OR (NOT "${META_PROJECT_TYPE}" STREQUAL "library")))
set(BUILTIN_ICON_THEMES_QRC_FILE "${CMAKE_CURRENT_BINARY_DIR}/icons/${META_PROJECT_NAME}_builtinicons.qrc")
list(APPEND RES_FILES "${BUILTIN_ICON_THEMES_QRC_FILE}")
if (EXISTS "${BUILTIN_ICON_THEMES_QRC_FILE}")
message(
STATUS "Using existing \"${BUILTIN_ICON_THEMES_QRC_FILE}\" to bundle icon themes for ${META_PROJECT_NAME}. "
"Remove this file to force re-generation of the resource file.")
else ()
set(ICON_THEME_FILES)
set(ICON_SEARCH_PATHS ${BUILTIN_ICON_THEMES_SEARCH_PATH})
if (CMAKE_FIND_ROOT_PATH)
foreach (ROOT_PATH ${CMAKE_FIND_ROOT_PATH})
list(APPEND ICON_SEARCH_PATHS "${ROOT_PATH}/${CMAKE_INSTALL_DATAROOTDIR}/icons")
endforeach ()
set(ICON_THEME_FILES)
set(ICON_SEARCH_PATHS)
if (CMAKE_FIND_ROOT_PATH)
foreach (ROOT_PATH ${CMAKE_FIND_ROOT_PATH})
list(APPEND ICON_SEARCH_PATHS "${ROOT_PATH}/${CMAKE_INSTALL_DATAROOTDIR}/icons")
endforeach ()
endif ()
list(APPEND ICON_SEARCH_PATHS "${CMAKE_INSTALL_FULL_DATAROOTDIR}/icons")
list(APPEND ICON_SEARCH_PATHS "/usr/${CMAKE_INSTALL_DATAROOTDIR}/icons") # find icons from regular prefix when cross-
# compiling
list(REMOVE_DUPLICATES ICON_SEARCH_PATHS)
set(BUILTIN_ICONS_DIR "${CMAKE_CURRENT_BINARY_DIR}/icons")
set(DEFAULT_THEME_INDEX_FILE "${BUILTIN_ICONS_DIR}/default/index.theme")
file(REMOVE_RECURSE "${BUILTIN_ICONS_DIR}")
file(MAKE_DIRECTORY "${BUILTIN_ICONS_DIR}")
foreach (ICON_THEME ${BUILTIN_ICON_THEMES})
string(REGEX MATCHALL "([^:]+|[^:]+$)" ICON_THEME_PARTS "${ICON_THEME}")
list(LENGTH ICON_THEME_PARTS ICON_THEME_PARTS_LENGTH)
if ("${ICON_THEME_PARTS_LENGTH}" STREQUAL 2)
list(GET ICON_THEME_PARTS 0 ICON_THEME)
list(GET ICON_THEME_PARTS 1 NEW_ICON_THEME_NAME)
else ()
set(NEW_ICON_THEME_NAME "${ICON_THEME}")
endif ()
list(APPEND ICON_SEARCH_PATHS "${CMAKE_INSTALL_FULL_DATAROOTDIR}/icons")
list(APPEND ICON_SEARCH_PATHS "/usr/${CMAKE_INSTALL_DATAROOTDIR}/icons") # find icons from regular prefix when
# cross- compiling
list(APPEND ICON_SEARCH_PATHS "/usr/share/icons") # the project might change CMAKE__DATAROOTDIR to something
# custom so let's add one hardcoded fallback
list(REMOVE_DUPLICATES ICON_SEARCH_PATHS)
set(BUILTIN_ICONS_DIR "${CMAKE_CURRENT_BINARY_DIR}/icons")
set(DEFAULT_THEME_INDEX_FILE "${BUILTIN_ICONS_DIR}/default/index.theme")
set(DEFAULT_DARK_THEME_INDEX_FILE "${BUILTIN_ICONS_DIR}/default-dark/index.theme")
file(REMOVE_RECURSE "${BUILTIN_ICONS_DIR}")
file(MAKE_DIRECTORY "${BUILTIN_ICONS_DIR}")
foreach (ICON_THEME ${BUILTIN_ICON_THEMES})
string(REGEX MATCHALL "([^:]+|[^:]+$)" ICON_THEME_PARTS "${ICON_THEME}")
list(LENGTH ICON_THEME_PARTS ICON_THEME_PARTS_LENGTH)
if ("${ICON_THEME_PARTS_LENGTH}" STREQUAL 2)
list(GET ICON_THEME_PARTS 0 ICON_THEME)
list(GET ICON_THEME_PARTS 1 NEW_ICON_THEME_NAME)
else ()
set(NEW_ICON_THEME_NAME "${ICON_THEME}")
endif ()
foreach (ICON_SEARCH_PATH ${ICON_SEARCH_PATHS})
set(ICON_THEME_PATH "${ICON_SEARCH_PATH}/${ICON_THEME}")
set(NEW_ICON_THEME_PATH "${ICON_SEARCH_PATH}/${ICON_THEME}")
if (IS_DIRECTORY "${ICON_THEME_PATH}")
foreach (ICON_SEARCH_PATH ${ICON_SEARCH_PATHS})
set(ICON_THEME_PATH "${ICON_SEARCH_PATH}/${ICON_THEME}")
set(NEW_ICON_THEME_PATH "${ICON_SEARCH_PATH}/${ICON_THEME}")
if (IS_DIRECTORY "${ICON_THEME_PATH}")
message(
STATUS
"The specified icon theme \"${ICON_THEME}\" has been located under \"${ICON_THEME_PATH}\" and will be built-in."
)
# find index files
if (NOT ICON_THEME STREQUAL FALLBACK_ICON_THEME)
file(
GLOB GLOBBED_ICON_THEME_INDEX_FILES
LIST_DIRECTORIES false
"${ICON_THEME_PATH}/index.theme" "${ICON_THEME_PATH}/icon-theme.cache")
else ()
# only index.theme required when icons are provided as fallback anyways
file(
GLOB GLOBBED_ICON_THEME_INDEX_FILES
LIST_DIRECTORIES false
"${ICON_THEME_PATH}/index.theme")
endif ()
# make the first specified built-in the default theme
if (NOT EXISTS "${DEFAULT_THEME_INDEX_FILE}")
file(MAKE_DIRECTORY "${BUILTIN_ICONS_DIR}/default")
file(WRITE "${DEFAULT_THEME_INDEX_FILE}" "[Icon Theme]\nInherits=${NEW_ICON_THEME_NAME}")
list(APPEND ICON_THEME_FILES "<file>default/index.theme</file>")
endif ()
# find required icons, except the icon theme is provided as fallback anyways
if (NOT ICON_THEME STREQUAL FALLBACK_ICON_THEME)
set(GLOB_PATTERNS)
foreach (REQUIRED_ICON ${REQUIRED_ICONS})
list(APPEND GLOB_PATTERNS "${ICON_THEME_PATH}/${REQUIRED_ICON}"
"${ICON_THEME_PATH}/${REQUIRED_ICON}.*" "${ICON_THEME_PATH}/*/${REQUIRED_ICON}"
"${ICON_THEME_PATH}/*/${REQUIRED_ICON}.*")
endforeach ()
file(
GLOB_RECURSE GLOBBED_ICON_THEME_FILES
LIST_DIRECTORIES false
${GLOB_PATTERNS})
else ()
message(
STATUS
"The specified icon theme \"${ICON_THEME}\" has been located under \"${ICON_THEME_PATH}\" and will be built-in."
"Icon files for specified theme \"${ICON_THEME}\" are skipped because these are provided as fallback anyways."
)
# find index files
if (NOT ICON_THEME STREQUAL FALLBACK_ICON_THEME)
file(
GLOB GLOBBED_ICON_THEME_INDEX_FILES
LIST_DIRECTORIES false
"${ICON_THEME_PATH}/index.theme" "${ICON_THEME_PATH}/icon-theme.cache")
else ()
# only index.theme required when icons are provided as fallback anyways
file(
GLOB GLOBBED_ICON_THEME_INDEX_FILES
LIST_DIRECTORIES false
"${ICON_THEME_PATH}/index.theme")
endif ()
# make the first non-dark specified built-in theme the "default" theme make the first dark specified
# built-in theme the "default-dark" theme
if (NEW_ICON_THEME_NAME MATCHES ".*-dark" AND NOT EXISTS "${DEFAULT_DARK_THEME_INDEX_FILE}")
file(MAKE_DIRECTORY "${BUILTIN_ICONS_DIR}/default-dark")
file(WRITE "${DEFAULT_DARK_THEME_INDEX_FILE}" "[Icon Theme]\nInherits=${NEW_ICON_THEME_NAME}")
list(APPEND ICON_THEME_FILES "<file>default-dark/index.theme</file>")
elseif (NOT EXISTS "${DEFAULT_THEME_INDEX_FILE}")
file(MAKE_DIRECTORY "${BUILTIN_ICONS_DIR}/default")
file(WRITE "${DEFAULT_THEME_INDEX_FILE}" "[Icon Theme]\nInherits=${NEW_ICON_THEME_NAME}")
list(APPEND ICON_THEME_FILES "<file>default/index.theme</file>")
endif ()
# find required icons, except the icon theme is provided as fallback anyways
if (NOT ICON_THEME STREQUAL FALLBACK_ICON_THEME)
set(GLOB_PATTERNS)
foreach (REQUIRED_ICON ${REQUIRED_ICONS})
list(APPEND GLOB_PATTERNS "${ICON_THEME_PATH}/${REQUIRED_ICON}"
"${ICON_THEME_PATH}/${REQUIRED_ICON}.*" "${ICON_THEME_PATH}/*/${REQUIRED_ICON}"
"${ICON_THEME_PATH}/*/${REQUIRED_ICON}.*")
endforeach ()
file(
GLOB_RECURSE GLOBBED_ICON_THEME_FILES
LIST_DIRECTORIES false
${GLOB_PATTERNS})
else ()
message(
STATUS
"Icon files for specified theme \"${ICON_THEME}\" are skipped because these are provided as fallback anyways."
)
set(GLOBBED_ICON_THEME_FILES)
endif ()
# make temporary copy of required icons and create resource list for Qt
foreach (ICON_THEME_FILE ${GLOBBED_ICON_THEME_INDEX_FILES} ${GLOBBED_ICON_THEME_FILES})
# resolve symlinks
if (IS_SYMLINK "${ICON_THEME_FILE}")
string(REGEX REPLACE "^${ICON_SEARCH_PATH}/" "" ICON_THEME_FILE_RELATIVE_PATH
"${ICON_THEME_FILE}")
string(REGEX REPLACE "(^[^/\\]+)" "${NEW_ICON_THEME_NAME}" NEW_ICON_THEME_FILE_RELATIVE_PATH
"${ICON_THEME_FILE_RELATIVE_PATH}")
set(ICON_THEME_FILE_ALIAS " alias=\"${NEW_ICON_THEME_FILE_RELATIVE_PATH}\"")
if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
if (CMAKE_VERSION VERSION_LESS "3.14")
message(FATAL_ERROR "Need at least CMake 3.14 on Windows to read symlinks of"
"icon theme to be bundled.")
endif ()
while (IS_SYMLINK "${ICON_THEME_FILE}")
get_filename_component(ICON_THEME_FILE_DIR "${ICON_THEME_FILE}" DIRECTORY)
file(READ_SYMLINK "${ICON_THEME_FILE}" ICON_THEME_FILE)
if (NOT IS_ABSOLUTE "${ICON_THEME_FILE}")
set(ICON_THEME_FILE "${ICON_THEME_FILE_DIR}/${ICON_THEME_FILE}")
endif ()
endwhile ()
endif ()
get_filename_component(ICON_THEME_FILE "${ICON_THEME_FILE}" REALPATH)
else ()
unset(ICON_THEME_FILE_ALIAS)
endif ()
set(GLOBBED_ICON_THEME_FILES)
endif ()
# make temporary copy of required icons and create resource list for Qt
foreach (ICON_THEME_FILE ${GLOBBED_ICON_THEME_INDEX_FILES} ${GLOBBED_ICON_THEME_FILES})
# resolve symlinks
if (IS_SYMLINK "${ICON_THEME_FILE}")
string(REGEX REPLACE "^${ICON_SEARCH_PATH}/" "" ICON_THEME_FILE_RELATIVE_PATH
"${ICON_THEME_FILE}")
string(REGEX REPLACE "(^[^/\\]+)" "${NEW_ICON_THEME_NAME}" NEW_ICON_THEME_FILE_RELATIVE_PATH
"${ICON_THEME_FILE_RELATIVE_PATH}")
get_filename_component(ICON_THEME_FILE_DIR "${ICON_THEME_FILE_RELATIVE_PATH}" DIRECTORY)
string(REGEX REPLACE "(^[^/\\]+)" "${NEW_ICON_THEME_NAME}" NEW_ICON_THEME_FILE_DIR
"${ICON_THEME_FILE_DIR}")
file(MAKE_DIRECTORY "${BUILTIN_ICONS_DIR}/${NEW_ICON_THEME_FILE_DIR}")
file(COPY "${ICON_THEME_FILE}" DESTINATION "${BUILTIN_ICONS_DIR}/${NEW_ICON_THEME_FILE_DIR}")
list(APPEND ICON_THEME_FILES
"<file${ICON_THEME_FILE_ALIAS}>${NEW_ICON_THEME_FILE_RELATIVE_PATH}</file>")
endforeach ()
break()
endif ()
unset(ICON_THEME_PATH)
endforeach ()
if (NOT ICON_THEME_PATH)
message(FATAL_ERROR "The specified icon theme \"${ICON_THEME}\" could not be found.")
set(ICON_THEME_FILE_ALIAS " alias=\"${NEW_ICON_THEME_FILE_RELATIVE_PATH}\"")
get_filename_component(ICON_THEME_FILE "${ICON_THEME_FILE}" REALPATH)
else ()
unset(ICON_THEME_FILE_ALIAS)
endif ()
string(REGEX REPLACE "^${ICON_SEARCH_PATH}/" "" ICON_THEME_FILE_RELATIVE_PATH "${ICON_THEME_FILE}")
string(REGEX REPLACE "(^[^/\\]+)" "${NEW_ICON_THEME_NAME}" NEW_ICON_THEME_FILE_RELATIVE_PATH
"${ICON_THEME_FILE_RELATIVE_PATH}")
get_filename_component(ICON_THEME_FILE_DIR "${ICON_THEME_FILE_RELATIVE_PATH}" DIRECTORY)
string(REGEX REPLACE "(^[^/\\]+)" "${NEW_ICON_THEME_NAME}" NEW_ICON_THEME_FILE_DIR
"${ICON_THEME_FILE_DIR}")
file(MAKE_DIRECTORY "${BUILTIN_ICONS_DIR}/${NEW_ICON_THEME_FILE_DIR}")
file(COPY "${ICON_THEME_FILE}" DESTINATION "${BUILTIN_ICONS_DIR}/${NEW_ICON_THEME_FILE_DIR}")
list(APPEND ICON_THEME_FILES
"<file${ICON_THEME_FILE_ALIAS}>${NEW_ICON_THEME_FILE_RELATIVE_PATH}</file>")
endforeach ()
break()
endif ()
unset(ICON_THEME_PATH)
endforeach ()
list(REMOVE_DUPLICATES ICON_THEME_FILES)
string(CONCAT BUILTIN_ICON_THEMES_QRC_FILE_CONTENT "<RCC><qresource prefix=\"/icons\">" ${ICON_THEME_FILES}
"</qresource></RCC>")
file(WRITE "${BUILTIN_ICON_THEMES_QRC_FILE}" "${BUILTIN_ICON_THEMES_QRC_FILE_CONTENT}")
endif ()
if (NOT ICON_THEME_PATH)
message(FATAL_ERROR "The specified icon theme \"${ICON_THEME}\" could not be found.")
endif ()
endforeach ()
set(BUILTIN_ICON_THEMES_QRC_FILE "${CMAKE_CURRENT_BINARY_DIR}/icons/${META_PROJECT_NAME}_builtinicons.qrc")
list(REMOVE_DUPLICATES ICON_THEME_FILES)
string(CONCAT BUILTIN_ICON_THEMES_QRC_FILE_CONTENT "<RCC><qresource prefix=\"/icons\">" ${ICON_THEME_FILES}
"</qresource></RCC>")
file(WRITE "${BUILTIN_ICON_THEMES_QRC_FILE}" "${BUILTIN_ICON_THEMES_QRC_FILE_CONTENT}")
list(APPEND RES_FILES "${BUILTIN_ICON_THEMES_QRC_FILE}")
endif ()
endif ()

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.17.0 FATAL_ERROR)
cmake_minimum_required(VERSION 3.3.0 FATAL_ERROR)
if (NOT BASIC_PROJECT_CONFIG_DONE)
message(FATAL_ERROR "Before including the QtGuiConfig module, the BasicConfig module must be included.")
@ -64,8 +64,6 @@ endif ()
if (WIN32)
# set "GUI-type" to WIN32 to hide console under Windows
set(GUI_TYPE WIN32)
# add option for building CLI-wrapper
option(BUILD_CLI_WRAPPER "whether to build a CLI wrapper" ON)
elseif (APPLE)
# make the GUI application a "bundle" under MacOSX
set(GUI_TYPE MACOSX_BUNDLE)

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.17.0 FATAL_ERROR)
cmake_minimum_required(VERSION 3.3.0 FATAL_ERROR)
# determines the JavaScript provider (either Qt Script or Qt Declarative)

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.17.0 FATAL_ERROR)
cmake_minimum_required(VERSION 3.3.0 FATAL_ERROR)
# defines helper to link against Qt dynamically or statically
@ -11,14 +11,6 @@ set(QT_LINKAGE_DETERMINED ON)
# include validate_visibility from c++utilities' 3rdParty module
include(3rdParty)
# allow switching the Qt and KDE Frameworks version
set(QT_PACKAGE_PREFIX
"Qt5"
CACHE STRING "specifies the prefix for Qt packages")
set(KF_PACKAGE_PREFIX
"KF5"
CACHE STRING "specifies the prefix for KDE Frameworks packages")
# determine the minimum Qt version
if (NOT META_QT_VERSION)
if (META_QT5_VERSION)
@ -39,7 +31,7 @@ endif ()
# define function for using Qt and KDE Frameworks modules and static plugins
macro (use_qt_module)
# parse arguments
set(OPTIONAL_ARGS ONLY_PLUGINS PLUGINS_OPTIONAL)
set(OPTIONAL_ARGS ONLY_PLUGINS)
set(ONE_VALUE_ARGS PREFIX MODULE VISIBILITY LIBRARIES_VARIABLE)
set(MULTI_VALUE_ARGS TARGETS PLUGINS)
cmake_parse_arguments(ARGS "${OPTIONAL_ARGS}" "${ONE_VALUE_ARGS}" "${MULTI_VALUE_ARGS}" ${ARGN})
@ -75,7 +67,7 @@ macro (use_qt_module)
find_package("${ARGS_PREFIX}${ARGS_MODULE}" "${META_QT_VERSION}" REQUIRED)
foreach (TARGET ${ARGS_TARGETS})
if (NOT TARGET "${TARGET}")
message(FATAL_ERROR "The CMake module ${ARGS_PREFIX}${ARGS_MODULE} does not provide the target ${TARGET}.")
message(FATAL_ERROR "The ${ARGS_PREFIX}${ARGS_MODULE} does not provide the target ${TARGET}.")
endif ()
if ("${TARGET}" IN_LIST "${ARGS_LIBRARIES_VARIABLE}")
continue()
@ -111,9 +103,6 @@ macro (use_qt_module)
endif ()
endif ()
if (NOT TARGET "${PLUGIN_TARGET}")
if (NOT PLUGINS_OPTIONAL)
continue()
endif ()
message(
FATAL_ERROR
"The ${ARGS_PREFIX}${ARGS_MODULE} package does not provide the target ${ARGS_PREFIX}::Q${PLUGIN}Plugin.")
@ -203,7 +192,7 @@ function (query_qmake_variable_path QMAKE_VARIABLE)
return() # skip if CMake version too old like on Leap 15.1
endif ()
foreach (ROOT_PATH ${CMAKE_FIND_ROOT_PATH} "")
foreach (PREFIX_PATH ${CMAKE_INSTALL_PREFIX} ${CMAKE_PREFIX_PATH} "")
foreach (PREFIX_PATH ${CMAKE_PREFIX_PATH} "")
string(JOIN "/" FULL_PATH ${ROOT_PATH} ${PREFIX_PATH} ${VARIABLE_VALUE})
if (EXISTS "${FULL_PATH}")
set("${QMAKE_VARIABLE}"

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.17.0 FATAL_ERROR)
cmake_minimum_required(VERSION 3.3.0 FATAL_ERROR)
# determines the web view provider (either Qt WebKit or Qt WebEngine)
@ -6,19 +6,9 @@ if (TARGET_CONFIG_DONE)
message(FATAL_ERROR "Can not include QtWebViewProviderConfig module when targets are already configured.")
endif ()
# include required modules
include(QtLinkage)
# check whether Qt WebEngine is present
find_package("${QT_PACKAGE_PREFIX}WebEngineWidgets" "${META_QT_VERSION}")
set(WEBVIEW_PROVIDER_DEFAULT "none")
if ("${${QT_PACKAGE_PREFIX}WebEngineWidgets_FOUND}")
set(WEBVIEW_PROVIDER_DEFAULT "webengine")
endif ()
# configure the specified web view provider
set(WEBVIEW_PROVIDER
"${WEBVIEW_PROVIDER_DEFAULT}"
"webengine"
CACHE STRING "specifies the web view provider: webengine (default), webkit or none")
if (WEBVIEW_PROVIDER STREQUAL "webkit")
set(WEBVIEW_PROVIDER WebKitWidgets)

View File

@ -12,7 +12,5 @@
#cmakedefine IMAGE_FORMAT_SUPPORT
#define IMPORT_IMAGE_FORMAT_PLUGINS @IMAGE_FORMAT_SUPPORT_ARRAY@
#define IMPORT_WIDGET_STYLE_PLUGINS @WIDGET_STYLE_PLUGINS_ARRAY@
#define IMPORT_TLS_PLUGINS @USED_TLS_PLUGINS_ARRAY@
#define IMPORT_NETWORK_INFORMATION_PLUGINS @USED_NETWORK_INFORMATION_PLUGINS_ARRAY@
@META_CUSTOM_QT_CONFIG@
#endif // @META_PROJECT_VARNAME_UPPER@_QT_CONFIG

View File

@ -12,7 +12,8 @@
#include <QMessageBox>
#include <QStyle>
#if defined(QT_UTILITIES_PLATFORM_SPECIFIC_CAPSLOCK_DETECTION) && defined(Q_OS_WIN32)
#ifdef QT_UTILITIES_PLATFORM_SPECIFIC_CAPSLOCK_DETECTION
#if defined(Q_OS_WIN32)
#include <windows.h>
#elif defined(X_AVAILABLE)
#include <X11/XKBlib.h>
@ -21,6 +22,7 @@
#undef FocusIn
#undef FocusOut
#endif
#endif
namespace QtUtilities {
@ -41,7 +43,7 @@ EnterPasswordDialog::EnterPasswordDialog(QWidget *parent)
// setup ui
m_ui->setupUi(this);
makeHeading(m_ui->instructionLabel);
setStyleSheet(dialogStyleForPalette(palette()));
setStyleSheet(dialogStyle());
setDescription();
setPromptForUserName(false);
setVerificationRequired(false);
@ -50,7 +52,12 @@ EnterPasswordDialog::EnterPasswordDialog(QWidget *parent)
m_ui->userNameLineEdit->installEventFilter(this);
m_ui->password1LineEdit->installEventFilter(this);
m_ui->password2LineEdit->installEventFilter(this);
// capslock key detection
#ifdef QT_UTILITIES_PLATFORM_SPECIFIC_CAPSLOCK_DETECTION
m_capslockPressed = isCapslockPressed();
#else
m_capslockPressed = false;
#endif
m_ui->capslockWarningWidget->setVisible(m_capslockPressed);
// draw icon to capslock warning graphics view
QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning, nullptr, this);
@ -205,9 +212,6 @@ void EnterPasswordDialog::setInstruction(const QString &value)
bool EnterPasswordDialog::event(QEvent *event)
{
switch (event->type()) {
case QEvent::PaletteChange:
setStyleSheet(dialogStyleForPalette(palette()));
break;
case QEvent::KeyPress: {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if (keyEvent->key() == Qt::Key_CapsLock) {
@ -216,9 +220,6 @@ bool EnterPasswordDialog::event(QEvent *event)
m_ui->capslockWarningWidget->setVisible(m_capslockPressed);
break;
}
case QEvent::LanguageChange:
m_ui->retranslateUi(this);
break;
default:;
}
return QDialog::event(event);
@ -323,17 +324,22 @@ void EnterPasswordDialog::confirm()
*/
bool EnterPasswordDialog::isCapslockPressed()
{
#if defined(QT_UTILITIES_PLATFORM_SPECIFIC_CAPSLOCK_DETECTION) && defined(Q_OS_WIN32)
#ifdef QT_UTILITIES_PLATFORM_SPECIFIC_CAPSLOCK_DETECTION
// platform dependent method of determining if CAPS LOCK is pressed
#if defined(Q_OS_WIN32)
return GetKeyState(VK_CAPITAL) == 1;
#elif defined(X_AVAILABLE)
auto *const d = XOpenDisplay(nullptr);
auto capsState = false;
Display *d = XOpenDisplay((char *)0);
bool caps_state = false;
if (d) {
unsigned n;
XkbGetIndicatorState(d, XkbUseCoreKbd, &n);
capsState = (n & 0x01) == 1;
caps_state = (n & 0x01) == 1;
}
return capsState;
return caps_state;
#else
return false;
#endif
#else
return false;
#endif

View File

@ -258,9 +258,6 @@
<normaloff/>
</iconset>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
</layout>

View File

@ -4,7 +4,6 @@
#ifndef QT_UTILITIES_GLOBAL
#define QT_UTILITIES_GLOBAL
#include "qtutilities-definitions.h"
#include <c++utilities/application/global.h>
#ifdef QT_UTILITIES_STATIC

View File

@ -3,8 +3,6 @@
#include "../global.h"
#include <c++utilities/misc/traits.h>
#include <QtGlobal>
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
@ -52,10 +50,7 @@ inline StringView makeStringView(const QString &str)
/*!
* \brief Makes either a QStringView or a QStringRef depending on the Qt version, applying "mid()" parameters.
*/
template <typename PosType1, typename PosType2 = PosType1,
CppUtilities::Traits::EnableIf<std::is_integral<PosType1>, std::is_signed<PosType1>, std::is_integral<PosType2>, std::is_signed<PosType2>>
* = nullptr>
inline StringView midRef(const QString &str, PosType1 pos, PosType2 n = -1)
inline StringView midRef(const QString &str, int pos, int n = -1)
{
#ifdef QT_UTILITIES_USE_Q_STRING_VIEW
return QStringView(str).mid(pos, n);
@ -80,17 +75,4 @@ template <class... SplitArgs> inline auto splitRef(const QString &str, SplitArgs
} // namespace QtUtilities
#if (QT_VERSION < QT_VERSION_CHECK(5, 10, 0))
QT_BEGIN_NAMESPACE
/*!
* \brief Provides a fallback for qEnvironmentVariable() when using old Qt versions.
*/
inline QString qEnvironmentVariable(const char *varName, const QString &defaultValue)
{
const auto val = qgetenv(varName);
return !val.isEmpty() ? QString::fromLocal8Bit(val) : defaultValue;
}
QT_END_NAMESPACE
#endif
#endif // QT_UTILITIES_COMPAT_H

View File

@ -12,7 +12,7 @@ namespace QtUtilities {
inline QByteArray toNativeFileName(const QString &fileName)
{
#if !defined(PLATFORM_WINDOWS) || !defined(CPP_UTILITIES_USE_NATIVE_FILE_BUFFER)
#if !defined(PLATFORM_MINGW) || !defined(CPP_UTILITIES_USE_NATIVE_FILE_BUFFER)
return fileName.toLocal8Bit();
#else
return fileName.toUtf8();
@ -21,7 +21,7 @@ inline QByteArray toNativeFileName(const QString &fileName)
inline QString fromNativeFileName(const char *nativeFileName, int size = -1)
{
#if !defined(PLATFORM_WINDOWS) || !defined(CPP_UTILITIES_USE_NATIVE_FILE_BUFFER)
#if !defined(PLATFORM_MINGW) || !defined(CPP_UTILITIES_USE_NATIVE_FILE_BUFFER)
return QString::fromLocal8Bit(nativeFileName, size);
#else
return QString::fromUtf8(nativeFileName, size);
@ -30,7 +30,7 @@ inline QString fromNativeFileName(const char *nativeFileName, int size = -1)
inline QString fromNativeFileName(const std::string &nativeFileName)
{
#if !defined(PLATFORM_WINDOWS) || !defined(CPP_UTILITIES_USE_NATIVE_FILE_BUFFER)
#if !defined(PLATFORM_MINGW) || !defined(CPP_UTILITIES_USE_NATIVE_FILE_BUFFER)
return QString::fromLocal8Bit(nativeFileName.data(), static_cast<int>(nativeFileName.size()));
#else
return QString::fromUtf8(nativeFileName.data(), static_cast<int>(nativeFileName.size()));

View File

@ -113,7 +113,7 @@ inline NotificationImage::NotificationImage(SwappedImage image)
inline NotificationImage::NotificationImage(const QImage &image)
: width(image.width())
, height(image.height())
, rowstride(static_cast<qint32>(image.bytesPerLine()))
, rowstride(image.bytesPerLine())
, hasAlpha(image.hasAlphaChannel())
, channels(image.isGrayscale() ? 1
: hasAlpha ? 4
@ -369,7 +369,7 @@ bool DBusNotification::queryCapabilities(const std::function<void(Capabilities &
if (returnValue.isError()) {
callback(Capabilities());
} else {
callback(Capabilities(std::move(returnValue.value())));
callback(Capabilities(move(returnValue.value())));
}
});
return true;

View File

@ -2,10 +2,6 @@
#include <QDesktopServices>
#include <QUrl>
#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0))
#include <QGuiApplication>
#include <QStyleHints>
#endif
#ifdef Q_OS_WIN32
#include <QFileInfo>
#endif
@ -42,54 +38,4 @@ bool openLocalFileOrDir(const QString &path)
#endif
return QDesktopServices::openUrl(url);
}
/*!
* \brief Returns whether \a palette is dark.
*/
bool isPaletteDark(const QPalette &palette)
{
return palette.color(QPalette::WindowText).lightness() > palette.color(QPalette::Window).lightness();
}
/*!
* \brief Returns whether dark mode is enabled.
* \remarks Whether dark mode is enabled can only be determined on Qt 6.5 or newer and only on certain
* platforms. If it cannot be determined, std::nullopt is returned.
*/
std::optional<bool> isDarkModeEnabled()
{
#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0))
if (const auto *const styleHints = QGuiApplication::styleHints()) {
const auto colorScheme = styleHints->colorScheme();
if (colorScheme != Qt::ColorScheme::Unknown) {
return colorScheme == Qt::ColorScheme::Dark;
}
}
#endif
return std::nullopt;
}
/*!
* \brief Invokes the specified callback when the color scheme changed.
*
* The first argument of the callback will be whether the color scheme is dark now (Qt::ColorScheme::Dark).
* The callback is invoked immediately by this function unless \a invokeImmediately is set to false.
*
* \remarks Whether dark mode is enabled can only be determined on Qt 6.5 or newer and only on certain
* platforms. If it cannot be determined the \a darkModeChangedCallback is never invoked.
*/
QMetaObject::Connection onDarkModeChanged(std::function<void(bool)> &&darkModeChangedCallback, QObject *context, bool invokeImmediately)
{
#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0))
if (const auto *const styleHints = QGuiApplication::styleHints()) {
if (invokeImmediately) {
darkModeChangedCallback(styleHints->colorScheme() == Qt::ColorScheme::Dark);
}
return QObject::connect(styleHints, &QStyleHints::colorSchemeChanged, context,
[handler = std::move(darkModeChangedCallback)](Qt::ColorScheme colorScheme) { return handler(colorScheme == Qt::ColorScheme::Dark); });
}
#endif
return QMetaObject::Connection();
}
} // namespace QtUtilities

View File

@ -3,23 +3,13 @@
#include "../global.h"
#include <QMetaObject>
#include <QPalette>
#include <QtGlobal>
#include <functional>
#include <optional>
QT_FORWARD_DECLARE_CLASS(QObject)
QT_FORWARD_DECLARE_CLASS(QString)
namespace QtUtilities {
QT_UTILITIES_EXPORT bool openLocalFileOrDir(const QString &path);
QT_UTILITIES_EXPORT bool isPaletteDark(const QPalette &palette = QPalette());
QT_UTILITIES_EXPORT std::optional<bool> isDarkModeEnabled();
QT_UTILITIES_EXPORT QMetaObject::Connection onDarkModeChanged(
std::function<void(bool)> &&darkModeChangedCallback, QObject *context = nullptr, bool invokeImmediately = true);
} // namespace QtUtilities
}
#endif // DESKTOP_UTILS_DESKTOPSERVICES_H

View File

@ -1,7 +1,5 @@
#include "./dialogutils.h"
#include "../misc/desktoputils.h"
#include <QCoreApplication>
#include <QDir>
#include <QFileInfo>
@ -58,28 +56,13 @@ QString generateWindowTitle(DocumentStatus documentStatus, const QString &docume
#if defined(QT_UTILITIES_GUI_QTWIDGETS) || defined(QT_UTILITIES_GUI_QTQUICK)
#ifdef Q_OS_WIN32
/*!
* \brief Returns the color used to draw frames.
*/
QColor windowFrameColorForPalette(const QPalette &palette)
{
return palette.window().color().darker(108);
}
/*!
* \brief Returns the color used to draw frames.
*/
QColor windowFrameColor()
{
return windowFrameColorForPalette(QGuiApplication::palette());
}
/*!
* \brief Returns the color used to draw instructions.
*/
QColor instructionTextColorForPalette(const QPalette &palette)
{
return isPaletteDark(palette) ? palette.text().color() : QColor(0x00, 0x33, 0x99);
return QGuiApplication::palette().window().color().darker(108);
}
/*!
@ -87,32 +70,11 @@ QColor instructionTextColorForPalette(const QPalette &palette)
*/
QColor instructionTextColor()
{
return instructionTextColorForPalette(QGuiApplication::palette());
const auto baseColor = QGuiApplication::palette().base().color();
return (baseColor.value() > 204 && baseColor.saturation() < 63) ? QColor(0x00, 0x33, 0x99) : QGuiApplication::palette().text().color();
}
#endif
/*!
* \brief Returns the stylesheet for dialogs and other windows used in my
* applications.
*/
QString dialogStyleForPalette(const QPalette &palette)
{
#ifdef Q_OS_WINDOWS
return QStringLiteral("#mainWidget { color: palette(text); background-color: "
"palette(base); border: none; }"
"#bottomWidget { background-color: palette(window); "
"color: palette(window-text); border-top: 1px solid %1; }"
"QMessageBox QLabel, QInputDialog QLabel, "
"*[classNames~=\"heading\"] { font-size: 12pt; color: %2; "
"}"
"*[classNames~=\"input-invalid\"] { color: red; }")
.arg(windowFrameColorForPalette(palette).name(), instructionTextColorForPalette(palette).name());
#else
Q_UNUSED(palette)
return QStringLiteral("*[classNames~=\"heading\"] { font-weight: bold; }"
"*[classNames~=\"input-invalid\"] { color: red; }");
#endif
}
/*!
* \brief Returns the stylesheet for dialogs and other windows used in my
@ -120,7 +82,20 @@ QString dialogStyleForPalette(const QPalette &palette)
*/
const QString &dialogStyle()
{
static const auto style = dialogStyleForPalette(QGuiApplication::palette());
#ifdef Q_OS_WIN32
static const auto style = QStringLiteral("#mainWidget { color: palette(text); background-color: "
"palette(base); border: none; }"
"#bottomWidget { background-color: palette(window); "
"color: palette(window-text); border-top: 1px solid %1; }"
"QMessageBox QLabel, QInputDialog QLabel, "
"*[classNames~=\"heading\"] { font-size: 12pt; color: %2; "
"}"
"*[classNames~=\"input-invalid\"] { color: red; }")
.arg(windowFrameColor().name(), instructionTextColor().name());
#else
static const auto style = QStringLiteral("*[classNames~=\"heading\"] { font-weight: bold; }"
"*[classNames~=\"input-invalid\"] { color: red; }");
#endif
return style;
}

View File

@ -8,7 +8,6 @@
QT_FORWARD_DECLARE_CLASS(QString)
QT_FORWARD_DECLARE_CLASS(QWidget)
QT_FORWARD_DECLARE_CLASS(QColor)
QT_FORWARD_DECLARE_CLASS(QPalette)
QT_FORWARD_DECLARE_CLASS(QPoint)
QT_FORWARD_DECLARE_CLASS(QRect)
@ -30,14 +29,11 @@ enum class DocumentStatus {
QT_UTILITIES_EXPORT QString generateWindowTitle(DocumentStatus documentStatus, const QString &documentPath);
#if defined(QT_UTILITIES_GUI_QTWIDGETS) || defined(QT_UTILITIES_GUI_QTQUICK)
#ifdef Q_OS_WINDOWS
[[deprecated]] QT_UTILITIES_EXPORT QColor windowFrameColor();
QT_UTILITIES_EXPORT QColor windowFrameColorForPalette(const QPalette &palette);
[[deprecated]] QT_UTILITIES_EXPORT QColor instructionTextColor();
QT_UTILITIES_EXPORT QColor instructionTextColorForPalette(const QPalette &palette);
#ifdef Q_OS_WIN32
QT_UTILITIES_EXPORT QColor windowFrameColor();
QT_UTILITIES_EXPORT QColor instructionTextColor();
#endif
[[deprecated]] QT_UTILITIES_EXPORT const QString &dialogStyle();
QT_UTILITIES_EXPORT QString dialogStyleForPalette(const QPalette &palette);
QT_UTILITIES_EXPORT const QString &dialogStyle();
#ifdef QT_UTILITIES_GUI_QTWIDGETS
QT_UTILITIES_EXPORT QRect availableScreenGeometryAtPoint(const QPoint &point);
QT_UTILITIES_EXPORT void centerWidget(QWidget *widget, const QWidget *parent = nullptr, const QPoint *position = nullptr);

View File

@ -94,7 +94,7 @@ void RecentMenuManager::addEntry(const QString &path)
}
if (!entry) {
// remove old entries to have never more than 10 entries
for (auto i = existingEntries.size() - 1; i > 8; --i) {
for (int i = existingEntries.size() - 1; i > 8; --i) {
delete existingEntries[i];
}
existingEntries = m_menu->actions();

View File

@ -32,7 +32,7 @@ ChecklistModel::ChecklistModel(QObject *parent)
int ChecklistModel::rowCount(const QModelIndex &parent) const
{
if (!parent.isValid()) {
return static_cast<int>(m_items.size());
return m_items.size();
}
return 0;
}
@ -261,7 +261,7 @@ void ChecklistModel::restore(QSettings &settings, const QString &name)
*/
void ChecklistModel::save(QSettings &settings, const QString &name) const
{
settings.beginWriteArray(name, static_cast<int>(m_items.size()));
settings.beginWriteArray(name, m_items.size());
int index = 0;
for (const ChecklistItem &item : m_items) {
settings.setArrayIndex(index);
@ -295,7 +295,7 @@ void ChecklistModel::applyVariantList(const QVariantList &checkedIds)
for (auto &item : m_items) {
item.m_checkState = checkedIds.contains(item.id()) ? Qt::Checked : Qt::Unchecked;
}
emit dataChanged(index(0), index(static_cast<int>(m_items.size())), { Qt::CheckStateRole });
emit dataChanged(index(0), index(m_items.size()), { Qt::CheckStateRole });
}
} // namespace QtUtilities

View File

@ -14,7 +14,6 @@ namespace QtUtilities {
*/
class QT_UTILITIES_EXPORT ColorButton : public QToolButton {
Q_OBJECT
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
Q_PROPERTY(bool backgroundCheckered READ isBackgroundCheckered WRITE setBackgroundCheckered)
public:
ColorButton(QWidget *parent = nullptr);

View File

@ -14,8 +14,6 @@
#include <QStyle>
#include <QToolButton>
#include <type_traits>
namespace QtUtilities {
enum { BrushRole = 33 };
@ -31,6 +29,7 @@ PaletteEditor::PaletteEditor(QWidget *parent)
{
m_ui->setupUi(this);
m_ui->paletteView->setModel(m_paletteModel);
updatePreviewPalette();
updateStyledButton();
m_ui->paletteView->setModel(m_paletteModel);
auto *const delegate = new ColorDelegate(this);
@ -73,9 +72,8 @@ void PaletteEditor::setPalette(const QPalette &palette)
resolve()
#endif
;
using MaskType = std::remove_cv_t<decltype(mask)>;
for (int i = 0; i < static_cast<int>(QPalette::NColorRoles); ++i) {
if (mask & (static_cast<MaskType>(1) << static_cast<MaskType>(i))) {
if (mask & (1 << i)) {
continue;
}
m_editPalette.setBrush(
@ -93,6 +91,7 @@ void PaletteEditor::setPalette(const QPalette &palette)
resolve(mask)
#endif
;
updatePreviewPalette();
updateStyledButton();
m_paletteUpdated = true;
if (!m_modelUpdated) {
@ -107,17 +106,6 @@ void PaletteEditor::setPalette(const QPalette &palette, const QPalette &parentPa
setPalette(palette);
}
bool PaletteEditor::event(QEvent *event)
{
switch (event->type()) {
case QEvent::LanguageChange:
m_ui->retranslateUi(this);
break;
default:;
}
return QDialog::event(event);
}
void PaletteEditor::handleComputeRadioClicked()
{
if (m_compute) {
@ -194,8 +182,6 @@ void PaletteEditor::load()
auto errorMessage = QString();
if (loadPalette(dialog.selectedFiles().constFirst(), &pal, &errorMessage)) {
setPalette(pal);
// apply again as otherwise highlight and possibly other roles are not shown until the next restart
setPalette(pal, pal);
} else {
QMessageBox::warning(this, tr("Error reading palette"), errorMessage);
}
@ -231,6 +217,21 @@ void PaletteEditor::buildPalette()
setPalette(temp);
}
void PaletteEditor::updatePreviewPalette()
{
const QPalette::ColorGroup g = currentColorGroup();
// build the preview palette
const QPalette currentPalette = palette();
QPalette previewPalette;
for (int i = QPalette::WindowText; i < QPalette::NColorRoles; ++i) {
const QPalette::ColorRole r = static_cast<QPalette::ColorRole>(i);
const QBrush br = currentPalette.brush(g, r);
previewPalette.setBrush(QPalette::Active, r, br);
previewPalette.setBrush(QPalette::Inactive, r, br);
previewPalette.setBrush(QPalette::Disabled, r, br);
}
}
void PaletteEditor::updateStyledButton()
{
m_ui->buildButton->setColor(palette().color(QPalette::Active, QPalette::Button));
@ -247,9 +248,8 @@ QPalette PaletteEditor::getPalette(QWidget *parent, const QPalette &init, const
resolve()
#endif
;
using MaskType = std::remove_cv_t<decltype(mask)>;
for (int i = 0; i < static_cast<int>(QPalette::NColorRoles); ++i) {
if (mask & (static_cast<MaskType>(1) << static_cast<MaskType>(i))) {
if (mask & (1 << i)) {
continue;
}
parentPalette.setBrush(
@ -282,7 +282,7 @@ PaletteModel::PaletteModel(QObject *parent)
int PaletteModel::rowCount(const QModelIndex &) const
{
return static_cast<int>(m_roleNames.count());
return m_roleNames.count();
}
int PaletteModel::columnCount(const QModelIndex &) const
@ -308,8 +308,9 @@ QVariant PaletteModel::data(const QModelIndex &index, int role) const
resolve()
#endif
;
using MaskType = std::remove_cv_t<decltype(mask)>;
return mask & (static_cast<MaskType>(1) << static_cast<MaskType>(index.row()));
if (mask & (1 << index.row()))
return true;
return false;
}
return QVariant();
}
@ -347,7 +348,7 @@ bool PaletteModel::setData(const QModelIndex &index, const QVariant &value, int
m_palette.setBrush(QPalette::Disabled, QPalette::Text, br);
m_palette.setBrush(QPalette::Disabled, QPalette::ButtonText, br);
idxBegin = PaletteModel::index(0, 0);
idxEnd = PaletteModel::index(static_cast<int>(m_roleNames.count()) - 1, 3);
idxEnd = PaletteModel::index(m_roleNames.count() - 1, 3);
break;
case QPalette::Window:
m_palette.setBrush(QPalette::Disabled, QPalette::Base, br);
@ -376,7 +377,7 @@ bool PaletteModel::setData(const QModelIndex &index, const QVariant &value, int
const bool isMask = qvariant_cast<bool>(value);
const int r = index.row();
if (isMask) {
mask |= (static_cast<decltype(mask)>(1) << static_cast<decltype(mask)>(r));
mask |= (1 << r);
} else {
m_palette.setBrush(
QPalette::Active, static_cast<QPalette::ColorRole>(r), m_parentPalette.brush(QPalette::Active, static_cast<QPalette::ColorRole>(r)));
@ -384,7 +385,7 @@ bool PaletteModel::setData(const QModelIndex &index, const QVariant &value, int
m_parentPalette.brush(QPalette::Inactive, static_cast<QPalette::ColorRole>(r)));
m_palette.setBrush(QPalette::Disabled, static_cast<QPalette::ColorRole>(r),
m_parentPalette.brush(QPalette::Disabled, static_cast<QPalette::ColorRole>(r)));
mask &= ~static_cast<decltype(mask)>((static_cast<decltype(mask)>(1) << static_cast<decltype(mask)>(index.row())));
mask &= ~static_cast<decltype(mask)>(1 << index.row());
}
m_palette.
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
@ -434,7 +435,7 @@ void PaletteModel::setPalette(const QPalette &palette, const QPalette &parentPal
m_parentPalette = parentPalette;
m_palette = palette;
const QModelIndex idxBegin = index(0, 0);
const QModelIndex idxEnd = index(static_cast<int>(m_roleNames.count()) - 1, 3);
const QModelIndex idxEnd = index(m_roleNames.count() - 1, 3);
emit dataChanged(idxBegin, idxEnd);
}

View File

@ -28,7 +28,6 @@ class PaletteEditor;
*/
class QT_UTILITIES_EXPORT PaletteEditor : public QDialog {
Q_OBJECT
Q_PROPERTY(QPalette palette READ palette WRITE setPalette)
public:
PaletteEditor(QWidget *parent);
~PaletteEditor() override;
@ -39,9 +38,6 @@ public:
void setPalette(const QPalette &palette);
void setPalette(const QPalette &palette, const QPalette &parentPalette);
protected:
bool event(QEvent *event) override;
private Q_SLOTS:
void buildPalette();
void paletteChanged(const QPalette &palette);
@ -51,6 +47,7 @@ private Q_SLOTS:
void save();
private:
void updatePreviewPalette();
void updateStyledButton();
QPalette::ColorGroup currentColorGroup() const

Binary file not shown.

After

Width:  |  Height:  |  Size: 728 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1,146 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="120.94489"
height="120.94489"
viewBox="0 0 32 32"
version="1.1"
id="svg8"
sodipodi:docname="edit-clear.svg"
inkscape:version="0.92.1 r"
inkscape:export-filename="../../48x48/actions/edit-clear.png"
inkscape:export-xdpi="38.099995"
inkscape:export-ydpi="38.099995">
<defs
id="defs2">
<linearGradient
id="circle-filling"
inkscape:collect="always">
<stop
style="stop-color:#464646;stop-opacity:0.41960785"
offset="0"
id="stop6209" />
<stop
id="stop6215"
offset="0.84381574"
style="stop-color:#464646;stop-opacity:0.54509807" />
<stop
style="stop-color:#1e1e1e;stop-opacity:0.74117649"
offset="0.9891246"
id="stop6217" />
<stop
style="stop-color:#1e1e1e;stop-opacity:0.74117649"
offset="1"
id="stop6211" />
</linearGradient>
<linearGradient
id="linearGradient6124"
osb:paint="solid">
<stop
style="stop-color:#656565;stop-opacity:1;"
offset="0"
id="stop6122" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#circle-filling"
id="radialGradient6207"
cx="16"
cy="281"
fx="16"
fy="281"
r="14.037946"
gradientTransform="matrix(1.0685091,-0.0070508,0.00712143,1.0792137,-3.0972671,-22.146217)"
gradientUnits="userSpaceOnUse" />
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Drop Shadow"
id="filter4754">
<feFlood
flood-opacity="0.588235"
flood-color="rgb(0,0,0)"
result="flood"
id="feFlood4744" />
<feComposite
in="flood"
in2="SourceGraphic"
operator="in"
result="composite1"
id="feComposite4746" />
<feGaussianBlur
in="composite1"
stdDeviation="1"
result="blur"
id="feGaussianBlur4748" />
<feOffset
dx="0"
dy="0"
result="offset"
id="feOffset4750" />
<feComposite
in="SourceGraphic"
in2="offset"
operator="over"
result="composite2"
id="feComposite4752" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.6568542"
inkscape:cx="72.66116"
inkscape:cy="44.340881"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1030"
inkscape:window-x="0"
inkscape:window-y="30"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-265)">
<circle
style="opacity:0.8;fill:url(#radialGradient6207);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.20103037;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:1.25;stroke-dasharray:none;stroke-dashoffset:1.99954295;stroke-opacity:0.85034012;paint-order:normal"
id="circle"
cx="16"
cy="281"
r="15" />
<path
style="fill:#ffffff;fill-opacity:0.94557822;fill-rule:evenodd;stroke:none;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;filter:url(#filter4754)"
d="m 12.259207,273.77243 -3.2511908,3.14457 3.7343458,3.64477 -3.6618579,3.58141 3.2511909,3.14457 3.712508,-3.60185 3.675756,3.59174 3.251191,-3.14456 -3.696885,-3.57131 3.769373,-3.63466 -3.251191,-3.14456 -3.748244,3.65508 z"
id="x"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@ -0,0 +1,217 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="120.94489"
height="120.94489"
viewBox="0 0 32 32"
version="1.1"
id="svg8"
sodipodi:docname="edit-error.svg"
inkscape:version="0.92.1 r"
inkscape:export-filename="../../48x48/actions/edit-error.png"
inkscape:export-xdpi="38.099995"
inkscape:export-ydpi="38.099995">
<defs
id="defs2">
<linearGradient
id="circle-filling"
inkscape:collect="always">
<stop
style="stop-color:#8c2a2a;stop-opacity:0.63529414"
offset="0"
id="stop6209" />
<stop
id="stop6215"
offset="0.84381574"
style="stop-color:#8c2a2a;stop-opacity:0.63529414" />
<stop
style="stop-color:#8c2a2a;stop-opacity:0.80612242"
offset="0.9891246"
id="stop6217" />
<stop
style="stop-color:#8c2a2a;stop-opacity:0.63529414"
offset="1"
id="stop6211" />
</linearGradient>
<linearGradient
id="linearGradient6124"
osb:paint="solid">
<stop
style="stop-color:#656565;stop-opacity:1;"
offset="0"
id="stop6122" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#circle-filling"
id="radialGradient6207"
cx="16"
cy="281"
fx="16"
fy="281"
r="14.037946"
gradientTransform="matrix(1.0685091,-0.0070508,0.00712143,1.0792137,-3.0972671,-22.146217)"
gradientUnits="userSpaceOnUse" />
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Drop Shadow"
id="filter4754">
<feFlood
flood-opacity="0.588235"
flood-color="rgb(0,0,0)"
result="flood"
id="feFlood4744" />
<feComposite
in="flood"
in2="SourceGraphic"
operator="in"
result="composite1"
id="feComposite4746" />
<feGaussianBlur
in="composite1"
stdDeviation="1"
result="blur"
id="feGaussianBlur4748" />
<feOffset
dx="0"
dy="0"
result="offset"
id="feOffset4750" />
<feComposite
in="SourceGraphic"
in2="offset"
operator="over"
result="composite2"
id="feComposite4752" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Drop Shadow"
id="filter4716">
<feFlood
flood-opacity="0.580392"
flood-color="rgb(0,0,0)"
result="flood"
id="feFlood4706" />
<feComposite
in="flood"
in2="SourceGraphic"
operator="in"
result="composite1"
id="feComposite4708" />
<feGaussianBlur
in="composite1"
stdDeviation="1"
result="blur"
id="feGaussianBlur4710" />
<feOffset
dx="0"
dy="0"
result="offset"
id="feOffset4712" />
<feComposite
in="SourceGraphic"
in2="offset"
operator="over"
result="composite2"
id="feComposite4714" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Drop Shadow"
id="filter4843">
<feFlood
flood-opacity="0.588235"
flood-color="rgb(0,0,0)"
result="flood"
id="feFlood4833" />
<feComposite
in="flood"
in2="SourceGraphic"
operator="in"
result="composite1"
id="feComposite4835" />
<feGaussianBlur
in="composite1"
stdDeviation="1"
result="blur"
id="feGaussianBlur4837" />
<feOffset
dx="0"
dy="0"
result="offset"
id="feOffset4839" />
<feComposite
in="SourceGraphic"
in2="offset"
operator="over"
result="composite2"
id="feComposite4841" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2"
inkscape:cx="-10.86025"
inkscape:cy="45.456815"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1030"
inkscape:window-x="0"
inkscape:window-y="30"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-265)">
<circle
style="opacity:0.8;fill:url(#radialGradient6207);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.20103037;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:1.25;stroke-dasharray:none;stroke-dashoffset:1.99954295;stroke-opacity:0.85034012;paint-order:normal"
id="circle"
cx="16"
cy="281"
r="15" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:10.58333302px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:0.82745098;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter4843)"
x="3.192997"
y="289.63605"
id="exclamation"
transform="matrix(1.6364428,0,0,1.0537851,-10.572145,-14.295562)"><tspan
sodipodi:role="line"
id="tspan4504"
x="3.192997"
y="289.63605"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:25.39999962px;font-family:'nota sans';-inkscape-font-specification:'nota sans';fill:#ffffff;fill-opacity:0.82745098;stroke-width:0.26458332px"> ! </tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@ -0,0 +1,184 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="120.94489"
height="120.94489"
viewBox="0 0 32 32"
version="1.1"
id="svg8"
sodipodi:docname="edit-menu.svg"
inkscape:version="0.92.1 r"
inkscape:export-filename="../../48x48/actions/edit-menu.png"
inkscape:export-xdpi="38.099995"
inkscape:export-ydpi="38.099995">
<defs
id="defs2">
<linearGradient
id="circle-filling"
inkscape:collect="always">
<stop
style="stop-color:#464646;stop-opacity:0.41960785"
offset="0"
id="stop6209" />
<stop
id="stop6215"
offset="0.84381574"
style="stop-color:#464646;stop-opacity:0.54509807" />
<stop
style="stop-color:#1e1e1e;stop-opacity:0.74117649"
offset="0.9891246"
id="stop6217" />
<stop
style="stop-color:#1e1e1e;stop-opacity:0.74117649"
offset="1"
id="stop6211" />
</linearGradient>
<linearGradient
id="linearGradient6124"
osb:paint="solid">
<stop
style="stop-color:#656565;stop-opacity:1;"
offset="0"
id="stop6122" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#circle-filling"
id="radialGradient6207"
cx="16"
cy="281"
fx="16"
fy="281"
r="14.037946"
gradientTransform="matrix(1.0685091,-0.0070508,0.00712143,1.0792137,-3.0972671,-22.146217)"
gradientUnits="userSpaceOnUse" />
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Drop Shadow"
id="filter4754">
<feFlood
flood-opacity="0.588235"
flood-color="rgb(0,0,0)"
result="flood"
id="feFlood4744" />
<feComposite
in="flood"
in2="SourceGraphic"
operator="in"
result="composite1"
id="feComposite4746" />
<feGaussianBlur
in="composite1"
stdDeviation="1"
result="blur"
id="feGaussianBlur4748" />
<feOffset
dx="0"
dy="0"
result="offset"
id="feOffset4750" />
<feComposite
in="SourceGraphic"
in2="offset"
operator="over"
result="composite2"
id="feComposite4752" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Drop Shadow"
id="filter4716">
<feFlood
flood-opacity="0.580392"
flood-color="rgb(0,0,0)"
result="flood"
id="feFlood4706" />
<feComposite
in="flood"
in2="SourceGraphic"
operator="in"
result="composite1"
id="feComposite4708" />
<feGaussianBlur
in="composite1"
stdDeviation="1"
result="blur"
id="feGaussianBlur4710" />
<feOffset
dx="0"
dy="0"
result="offset"
id="feOffset4712" />
<feComposite
in="SourceGraphic"
in2="offset"
operator="over"
result="composite2"
id="feComposite4714" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.8284271"
inkscape:cx="-64.901506"
inkscape:cy="39.858925"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1030"
inkscape:window-x="0"
inkscape:window-y="30"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-265)">
<circle
style="opacity:0.8;fill:url(#radialGradient6207);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.20103037;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:1.25;stroke-dasharray:none;stroke-dashoffset:1.99954295;stroke-opacity:0.85034012;paint-order:normal"
id="circle"
cx="16"
cy="281"
r="15"
inkscape:export-filename="../../48x48/actions/circle.png"
inkscape:export-xdpi="38"
inkscape:export-ydpi="38" />
<ellipse
style="opacity:1;fill:#ffffff;fill-opacity:0.82653061;fill-rule:nonzero;stroke:none;stroke-width:0.44207191;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.99954295;stroke-opacity:1;paint-order:normal;filter:url(#filter4716)"
id="inner-circle"
cx="-43.410675"
cy="278.35611"
rx="6.4542603"
ry="6.487721"
transform="matrix(0.85951266,-0.17525769,0.18535814,0.85739117,1.8691763,34.503158)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@ -23,8 +23,6 @@ IMPORT_IMAGE_FORMAT_PLUGINS
#endif
IMPORT_WIDGET_STYLE_PLUGINS
#endif // defined(QT_UTILITIES_GUI_QTWIDGETS) || defined(QT_UTILITIES_GUI_QTQUICK)
IMPORT_TLS_PLUGINS
IMPORT_NETWORK_INFORMATION_PLUGINS
#endif // QT_STATIC
#endif // MISC_UTILS_IMPORT_PLUGIN_H

View File

@ -1,7 +1,5 @@
#include "./qtconfigarguments.h"
#include "../misc/compat.h"
#include <c++utilities/conversion/stringconversion.h>
#include <c++utilities/io/ansiescapecodes.h>
@ -17,12 +15,6 @@
#include <QGuiApplication>
#endif
#if defined(Q_OS_WINDOWS) && (QT_VERSION >= QT_VERSION_CHECK(6, 3, 0))
#define QT_UTILITIES_CHECK_WINDOWS_VERSION
#include <QMessageBox>
#include <QOperatingSystemVersion>
#endif
#include <initializer_list>
#include <iostream>
@ -135,14 +127,14 @@ void QtConfigArguments::applySettings(bool preventApplyingDefaultFont) const
}
#endif
if (m_iconThemeArg.isPresent()) {
// set first value of m_iconThemeArg as icon theme and add further values as search paths
if (auto i = m_iconThemeArg.values().cbegin(), end = m_iconThemeArg.values().cend(); i != end) {
QIcon::setThemeName(QString::fromUtf8(*i));
auto i = m_iconThemeArg.values().cbegin(), end = m_iconThemeArg.values().end();
if (i != end) {
QIcon::setThemeName(QString::fromLocal8Bit(*i));
if (++i != end) {
auto searchPaths = QStringList();
searchPaths.reserve(static_cast<QStringList::size_type>(m_iconThemeArg.values().size()));
QStringList searchPaths;
searchPaths.reserve(static_cast<QStringList::size_type>(m_iconThemeArg.values().size() - 1));
for (; i != end; ++i) {
searchPaths << QString::fromUtf8(*i);
searchPaths << QString::fromLocal8Bit(*i);
}
searchPaths << QStringLiteral(":/icons");
QIcon::setThemeSearchPaths(searchPaths);
@ -150,14 +142,24 @@ void QtConfigArguments::applySettings(bool preventApplyingDefaultFont) const
}
} else {
if (qEnvironmentVariableIsSet("ICON_THEME_SEARCH_PATH")) {
QIcon::setThemeSearchPaths(QStringList({ qEnvironmentVariable("ICON_THEME_SEARCH_PATH"), QStringLiteral(":/icons") }));
QString path;
path.append(qgetenv("ICON_THEME_SEARCH_PATH"));
QIcon::setThemeSearchPaths(QStringList({ path, QStringLiteral(":/icons") }));
} else {
QIcon::setThemeSearchPaths(QIcon::themeSearchPaths() << QStringLiteral("../share/icons") << QStringLiteral(":/icons"));
}
if (qEnvironmentVariableIsSet("ICON_THEME")) {
QIcon::setThemeName(qEnvironmentVariable("ICON_THEME"));
QString themeName;
themeName.append(qgetenv("ICON_THEME"));
QIcon::setThemeName(themeName);
}
}
#ifdef Q_OS_WIN32
// default configuration under Windows
if (QIcon::themeName().isEmpty()) {
QIcon::setThemeName(QStringLiteral("default"));
}
#endif
if (m_fontArg.isPresent()) {
QFont font;
font.setFamily(QString::fromLocal8Bit(m_fontArg.values().front()));
@ -186,14 +188,5 @@ void QtConfigArguments::applySettings(bool preventApplyingDefaultFont) const
if (m_sceneGraphRenderLoopArg.isPresent()) {
qputenv(m_sceneGraphRenderLoopArg.environmentVariable(), QByteArray(m_sceneGraphRenderLoopArg.firstValue()));
}
#ifdef QT_UTILITIES_CHECK_WINDOWS_VERSION
if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows10_1809) {
QMessageBox::warning(nullptr, QCoreApplication::applicationName(),
QCoreApplication::translate("QtConfigArguments",
"This application requires Windows 10, version 1809 or newer. The current Windows version is older so the application might not work "
"correctly."));
}
#endif
}
} // namespace CppUtilities

View File

@ -9,13 +9,6 @@
#include <QQuickStyle>
#include <QString>
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
#if defined(PLATFORM_ANDROID)
#define QT_UTILITIES_DEFAULT_QQC2_STYLE "Material"
#elif defined(PLATFORM_WINDOWS)
#define QT_UTILITIES_DEFAULT_QQC2_STYLE "Universal"
#endif
#else
#if defined(PLATFORM_ANDROID)
#define QT_UTILITIES_DEFAULT_QQC2_STYLE "material"
#elif defined(PLATFORM_WINDOWS)
@ -23,8 +16,6 @@
#endif
#endif
#endif
namespace CppUtilities {
class QT_UTILITIES_EXPORT QtConfigArguments {

View File

@ -68,11 +68,6 @@ void cleanup()
*/
namespace TranslationFiles {
/*!
* \brief The translators installed via the load-functions in this namespace.
*/
static QList<QTranslator *> translators;
/*!
* \brief Allows to set an additional search path for translation files.
* \remarks This path is considered *before* the default directories.
@ -137,7 +132,6 @@ void loadQtTranslationFile(initializer_list<QString> repositoryNames, const QStr
|| qtTranslator->load(fileName, path = QStringLiteral("../share/qt/translations"))
|| qtTranslator->load(fileName, path = QStringLiteral(":/translations"))) {
QCoreApplication::installTranslator(qtTranslator);
translators.append(qtTranslator);
if (debugTranslations) {
cerr << "Loading translation file for Qt repository \"" << repoName.toLocal8Bit().data() << "\" and the locale \""
<< localeName.toLocal8Bit().data() << "\" from \"" << path.toLocal8Bit().data() << "\"." << endl;
@ -229,13 +223,13 @@ void loadApplicationTranslationFile(const QString &configName, const QString &ap
QString path;
if ((!additionalTranslationFilePath().isEmpty() && appTranslator->load(fileName, path = additionalTranslationFilePath()))
|| appTranslator->load(fileName, path = QStringLiteral(".")) || appTranslator->load(fileName, path = QStringLiteral("../") % directoryName)
|| appTranslator->load(fileName, path = QStringLiteral("../") % directoryName)
|| appTranslator->load(fileName, path = QStringLiteral("../../") % directoryName)
|| appTranslator->load(fileName, path = QStringLiteral("./translations"))
|| appTranslator->load(fileName, path = QStringLiteral("../share/") % directoryName % QStringLiteral("/translations"))
|| appTranslator->load(fileName, path = QStringLiteral(APP_INSTALL_PREFIX "/share/") % directoryName % QStringLiteral("/translations"))
|| appTranslator->load(fileName, path = QStringLiteral(":/translations"))) {
QCoreApplication::installTranslator(appTranslator);
translators.append(appTranslator);
if (qEnvironmentVariableIsSet("QT_DEBUG_TRANSLATIONS")) {
logTranslationEvent("Loading", configName, applicationName, localeName, path);
}
@ -273,18 +267,6 @@ void loadApplicationTranslationFile(const QString &configName, const std::initia
loadApplicationTranslationFile(configName, applicationName, localeName);
}
}
/*!
* \brief Clears all translation files previously loaded via the load-functions in this namespace.
*/
void clearTranslationFiles()
{
for (auto *const translator : translators) {
QCoreApplication::removeTranslator(translator);
}
translators.clear();
}
} // namespace TranslationFiles
/*!
@ -331,86 +313,12 @@ bool hasCoreApp()
*/
void setupCommonQtApplicationAttributes()
{
// enable dark window frame on Windows if the configured color palette is dark
// - supported as of Qt 6.4; no longer required as of Qt 6.5
// - see https://bugreports.qt.io/browse/QTBUG-72028?focusedCommentId=677819#comment-677819
// and https://www.qt.io/blog/dark-mode-on-windows-11-with-qt-6.5
#if defined(Q_OS_WINDOWS) && (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) && (QT_VERSION < QT_VERSION_CHECK(6, 5, 0))
if (const auto qtVersion = QLibraryInfo::version();
qtVersion >= QVersionNumber(6, 4, 0) && qtVersion < QVersionNumber(6, 5, 0) && !qEnvironmentVariableIsSet("QT_QPA_PLATFORM")) {
qputenv("QT_QPA_PLATFORM", "windows:darkmode=1");
}
#endif
// ensure FONTCONFIG_PATH is set (mainly required for static GNU/Linux builds)
#ifdef QT_FEATURE_fontdialog
if (!qEnvironmentVariableIsSet("FONTCONFIG_PATH") && QDir(QStringLiteral("/etc/fonts")).exists()) {
qputenv("FONTCONFIG_PATH", "/etc/fonts");
}
#endif
// enable settings for High-DPI scaling
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
if (!QCoreApplication::instance()) {
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true);
}
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true);
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true);
#endif
}
/*!
* \brief Returns the settings object for the specified \a organization and \a application.
* \remarks
* - This function always uses INI as that's what I'd like to use in all of my applications consistently, regardless of the platform.
* - The parameter \a application might be empty. In fact, most of my applications use just `getSettings(QStringLiteral(PROJECT_NAME))`.
* - This function first checks whether a file called `$organization/$application.ini` exists in the current working directory (or just
* `$organization.ini` if \a application is empty) and uses that if it exists. That allows having a portable installation.
* - Some of my apps where using values from QCoreApplication for \a organization and \a application in the beginning. This function
* moves those old config files to their new location if needed. This extra handling will likely removed at some point. Note that
* I moved away from using values from QCoreApplication to avoid having spaces and additional config suffixes in the file name.
*/
std::unique_ptr<QSettings> getSettings(const QString &organization, const QString &application)
{
auto settings = std::unique_ptr<QSettings>();
if (const auto portableFile
= QFile(application.isEmpty() ? organization + QStringLiteral(".ini") : organization % QChar('/') % application % QStringLiteral(".ini"));
portableFile.exists()) {
settings = std::make_unique<QSettings>(portableFile.fileName(), QSettings::IniFormat);
} else {
settings = std::make_unique<QSettings>(QSettings::IniFormat, QSettings::UserScope, organization, application);
// move config created by older versions to new location
if (organization != QCoreApplication::organizationName() || application != QCoreApplication::applicationName()) {
const auto oldConfig
= QSettings(QSettings::IniFormat, QSettings::UserScope, QCoreApplication::organizationName(), QCoreApplication::applicationName())
.fileName();
QFile::rename(oldConfig, settings->fileName()) || QFile::remove(oldConfig);
}
}
settings->sync();
return settings;
}
/*!
* \brief Returns an error message for the specified \a settings or an empty string if there's no error.
*/
QString errorMessageForSettings(const QSettings &settings)
{
auto errorMessage = QString();
switch (settings.status()) {
case QSettings::NoError:
return QString();
case QSettings::AccessError:
errorMessage = QCoreApplication::translate("QtUtilities", "unable to access file");
break;
case QSettings::FormatError:
errorMessage = QCoreApplication::translate("QtUtilities", "file has invalid format");
break;
default:
errorMessage = QCoreApplication::translate("QtUtilities", "unknown error");
}
return QCoreApplication::translate("QtUtilities", "Unable to sync settings from \"%1\": %2").arg(settings.fileName(), errorMessage);
}
// namespace ApplicationInstances
} // namespace QtUtilities

View File

@ -3,12 +3,10 @@
#include "../global.h"
#include <QString>
#include <QtContainerFwd>
#include <QtGlobal>
#include <initializer_list>
#include <memory>
QT_FORWARD_DECLARE_CLASS(QString)
QT_FORWARD_DECLARE_CLASS(QSettings)
@ -16,18 +14,6 @@ QT_FORWARD_DECLARE_CLASS(QSettings)
QT_FORWARD_DECLARE_CLASS(QStringList)
#endif
/*!
* \brief Sets the base name of the desktop entry for this application from buildsystem-provided meta-data.
* \remarks
* - This is done as part of SET_QT_APPLICATION_INFO and thus normally doesn't need to be invoked individually.
* - This macro is still experimental.
*/
#define SET_QT_DESKTOP_FILE_NAME
#if defined(Q_OS_LINUX) && defined(qGuiApp) && defined(APP_ID)
#undef SET_QT_DESKTOP_FILE_NAME
#define SET_QT_DESKTOP_FILE_NAME QGuiApplication::setDesktopFileName(QStringLiteral(APP_ID));
#endif
/*!
* \brief Sets the application meta data in the QCoreApplication singleton and attributes commonly used
* within my applications.
@ -38,7 +24,6 @@ QT_FORWARD_DECLARE_CLASS(QStringList)
QCoreApplication::setOrganizationDomain(QStringLiteral(APP_DOMAIN)); \
QCoreApplication::setApplicationName(QStringLiteral(APP_NAME)); \
QCoreApplication::setApplicationVersion(QStringLiteral(APP_VERSION)); \
SET_QT_DESKTOP_FILE_NAME \
::QtUtilities::setupCommonQtApplicationAttributes()
/*!
@ -66,7 +51,6 @@ QT_UTILITIES_EXPORT void loadApplicationTranslationFile(const QString &configNam
QT_UTILITIES_EXPORT void loadApplicationTranslationFile(const QString &configName, const std::initializer_list<QString> &applicationNames);
QT_UTILITIES_EXPORT void loadApplicationTranslationFile(
const QString &configName, const std::initializer_list<QString> &applicationNames, const QString &localeName);
QT_UTILITIES_EXPORT void clearTranslationFiles();
} // namespace TranslationFiles
namespace ApplicationInstances {
@ -81,8 +65,6 @@ QT_UTILITIES_EXPORT bool hasCoreApp();
} // namespace ApplicationInstances
QT_UTILITIES_EXPORT void setupCommonQtApplicationAttributes();
QT_UTILITIES_EXPORT std::unique_ptr<QSettings> getSettings(const QString &organization, const QString &application = QString());
QT_UTILITIES_EXPORT QString errorMessageForSettings(const QSettings &settings);
} // namespace QtUtilities

View File

@ -1,9 +1,6 @@
#include "./optioncategory.h"
#include "./optionpage.h"
#include <QCoreApplication>
#include <QEvent>
namespace QtUtilities {
/*!
@ -62,20 +59,6 @@ void OptionCategory::resetAllPages()
}
}
/*!
* \brief Triggers retranslation of all pages.
* \remarks Has no effect if the pages don't react to the LanguageChange event.
*/
void OptionCategory::retranslateAllPages()
{
auto event = QEvent(QEvent::LanguageChange);
for (auto *const page : m_pages) {
if (page->hasBeenShown()) {
QCoreApplication::sendEvent(page->widget(), &event);
}
}
}
/*!
* \brief Returns whether the option category matches the specified \a
* searchKeyWord.

View File

@ -31,9 +31,9 @@ public:
void setIcon(const QIcon &icon);
const QList<OptionPage *> &pages() const;
void assignPages(const QList<OptionPage *> &pages);
template<typename PageType> PageType *page();
bool applyAllPages();
void resetAllPages();
void retranslateAllPages();
bool matches(const QString &searchKeyWord) const;
int currentIndex() const;
void setCurrentIndex(int currentIndex);
@ -41,7 +41,7 @@ public:
Q_SIGNALS:
void displayNameChanged(const QString &displayName);
void iconChanged(const QIcon &icon);
void pagesChanged(const QList<QtUtilities::OptionPage *> &pages);
void pagesChanged(const QList<OptionPage *> &pages);
private:
QString m_displayName;
@ -90,6 +90,19 @@ inline const QList<OptionPage *> &OptionCategory::pages() const
return m_pages;
}
/*!
* \brief Returns the first page with the specified \tp PageType or nullptr if there is no such page.
*/
template<typename PageType> PageType *OptionCategory::page()
{
for (auto *const genericPage : m_pages) {
if (const auto *const page = qobject_cast<PageType *>(genericPage)) {
return page;
}
}
return nullptr;
}
/*!
* \brief Returns the index of the currently shown page.
* \remarks The returned index might be invalid/out of range.

View File

@ -6,8 +6,6 @@
#include <QStyle>
#endif
#include <utility>
namespace QtUtilities {
/*!
@ -32,7 +30,7 @@ OptionCategoryModel::OptionCategoryModel(const QList<OptionCategory *> &categori
: QAbstractListModel(parent)
, m_categories(categories)
{
for (OptionCategory *category : std::as_const(m_categories)) {
for (OptionCategory *category : m_categories) {
category->setParent(this);
}
}
@ -54,7 +52,7 @@ void OptionCategoryModel::setCategories(const QList<OptionCategory *> &categorie
beginResetModel();
qDeleteAll(m_categories);
m_categories = categories;
for (OptionCategory *const category : std::as_const(m_categories)) {
for (OptionCategory *const category : m_categories) {
category->setParent(this);
connect(category, &OptionCategory::displayNameChanged, this, &OptionCategoryModel::categoryChangedName);
connect(category, &OptionCategory::iconChanged, this, &OptionCategoryModel::categoryChangedIcon);
@ -64,7 +62,7 @@ void OptionCategoryModel::setCategories(const QList<OptionCategory *> &categorie
int OptionCategoryModel::rowCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : static_cast<int>(m_categories.size());
return parent.isValid() ? 0 : m_categories.size();
}
QVariant OptionCategoryModel::data(const QModelIndex &index, int role) const
@ -100,7 +98,7 @@ void OptionCategoryModel::categoryChangedName()
if (!senderCategory) {
return;
}
for (int i = 0, end = static_cast<int>(m_categories.size()); i < end; ++i) {
for (int i = 0, end = m_categories.size(); i < end; ++i) {
if (senderCategory == m_categories.at(i)) {
QModelIndex index = this->index(i);
emit dataChanged(index, index, QVector<int>({ Qt::DisplayRole }));
@ -117,7 +115,7 @@ void OptionCategoryModel::categoryChangedIcon()
if (!senderCategory) {
return;
}
for (int i = 0, end = static_cast<int>(m_categories.size()); i < end; ++i) {
for (int i = 0, end = m_categories.size(); i < end; ++i) {
if (senderCategory == m_categories.at(i)) {
QModelIndex index = this->index(i);
emit dataChanged(index, index, QVector<int>({ Qt::DecorationRole }));

View File

@ -1,14 +1,11 @@
#include "./optionpage.h"
#include <QCheckBox>
#include <QEvent>
#include <QGroupBox>
#include <QLabel>
#include <QPushButton>
#include <QRadioButton>
#include <utility>
namespace QtUtilities {
/*!
@ -84,29 +81,12 @@ bool OptionPage::matches(const QString &searchKeyWord)
m_keywords << groupBox->title();
m_keywordsInitialized = true;
}
for (const QString &keyword : std::as_const(m_keywords))
for (const QString &keyword : m_keywords)
if (keyword.contains(searchKeyWord, Qt::CaseInsensitive))
return true;
return false;
}
/*!
* \brief Emits the paletteChanged() signal.
*/
bool OptionPageWidget::event(QEvent *event)
{
switch (event->type()) {
case QEvent::PaletteChange:
emit paletteChanged();
break;
case QEvent::LanguageChange:
emit retranslationRequired();
break;
default:;
}
return QWidget::event(event);
}
/*!
* \fn OptionPage::apply()
* \brief Applies altered settings.

View File

@ -12,25 +12,6 @@ namespace QtUtilities {
class SettingsDialog;
class QT_UTILITIES_EXPORT OptionPageWidget : public QWidget {
Q_OBJECT
public:
explicit OptionPageWidget(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
Q_SIGNALS:
void paletteChanged();
void retranslationRequired();
protected:
bool event(QEvent *) override;
};
inline OptionPageWidget::OptionPageWidget(QWidget *parent, Qt::WindowFlags f)
: QWidget(parent, f)
{
}
class QT_UTILITIES_EXPORT OptionPage {
friend class SettingsDialog;
@ -144,12 +125,11 @@ template <class UiClass> UiFileBasedOptionPage<UiClass>::~UiFileBasedOptionPage(
*/
template <class UiClass> QWidget *UiFileBasedOptionPage<UiClass>::setupWidget()
{
auto *const widget = new OptionPageWidget();
QWidget *widget = new QWidget();
if (!m_ui) {
m_ui.reset(new UiClass);
}
m_ui->setupUi(widget);
QObject::connect(widget, &OptionPageWidget::retranslationRequired, [this, widget] { m_ui->retranslateUi(widget); });
return widget;
}

View File

@ -10,83 +10,54 @@
#include "../resources/resources.h"
#include "../misc/desktoputils.h"
#include "resources/config.h"
#include "ui_qtappearanceoptionpage.h"
#include "ui_qtenvoptionpage.h"
#include "ui_qtlanguageoptionpage.h"
#include <c++utilities/application/commandlineutils.h>
#include <QDir>
#include <QFileDialog>
#include <QFontDialog>
#include <QIcon>
#include <QOperatingSystemVersion>
#include <QSettings>
#include <QStringBuilder>
#include <QStyleFactory>
#include <QVersionNumber>
#if defined(Q_OS_WINDOWS) && (QT_VERSION >= QT_VERSION_CHECK(6, 3, 0)) && (QT_VERSION < QT_VERSION_CHECK(6, 7, 0))
#include <QOperatingSystemVersion>
#define QT_UTILITIES_USE_FUSION_ON_WINDOWS_11
#endif
#include <iostream>
#include <memory>
#include <optional>
using namespace std;
namespace QtUtilities {
#if defined(Q_OS_WINDOWS) || defined(Q_OS_DARWIN)
#define QT_UTILITIES_CAN_ENFORCE_FREETYPE 1
#endif
#if defined(Q_OS_WINDOWS)
#define QT_UTILITIES_CAN_ENABLE_DARKMODE 1
#endif
struct QtSettingsData {
QtSettingsData();
QtSettingsData() = default;
QFont font;
std::optional<QFont> initialFont;
QPalette palette; // the currently applied palette (only in use if customPalette is true, though)
QPalette selectedPalette; // the intermediately selected palette (chosen in palette editor but not yet applied)
QPalette palette;
QString widgetStyle;
QString initialWidgetStyle;
QString styleSheetPath;
QString iconTheme;
QString initialIconTheme;
QString iconTheme = QIcon::themeName();
QLocale defaultLocale;
QLocale previousLocale;
QString localeName;
QString previousPluginDirectory;
QString localeName = defaultLocale.name();
QString additionalPluginDirectory;
QString previousIconThemeSearchPath;
QString additionalIconThemeSearchPath;
bool customFont;
bool customPalette;
bool customWidgetStyle;
bool customStyleSheet;
bool customIconTheme;
bool customLocale;
bool isPaletteDark;
bool showNotices;
bool retranslatable;
QString fontEngine;
bool customFont = false;
bool customPalette = false;
bool customWidgetStyle = false;
bool customStyleSheet = false;
bool customIconTheme = false;
bool customLocale = false;
bool enableDarkmode = false;
};
inline QtSettingsData::QtSettingsData()
: iconTheme(QIcon::themeName())
, initialIconTheme(iconTheme)
, localeName(defaultLocale.name())
, customFont(false)
, customPalette(false)
, customWidgetStyle(false)
, customStyleSheet(false)
, customIconTheme(false)
, customLocale(false)
, isPaletteDark(false)
, showNotices(true)
, retranslatable(false)
{
}
/*!
* \brief Creates a new settings object.
* \remarks Settings are not restored automatically. Instead, some values (font,
@ -95,7 +66,7 @@ inline QtSettingsData::QtSettingsData()
* system-default.
*/
QtSettings::QtSettings()
: m_d(std::make_unique<QtSettingsData>())
: m_d(make_unique<QtSettingsData>())
{
}
@ -108,35 +79,6 @@ QtSettings::~QtSettings()
{
}
/*!
* \brief Disables notices on option pages that settings take only effect after restarting.
* \remarks
* - This function must be called before obtaining the option pages via category().
* - Only call this function if the application actually re-applies these settings when the
* settings dialog is applied and when it is generally able to handle widget style and
* palette changes well.
* - The localization option page's notice is handled via setRetranslatable() and the notice
* for the environment page is still always shown (as those settings can never be applied
* at runtime). So this affects only the appearance page at this point.
*/
void QtSettings::disableNotices()
{
m_d->showNotices = false;
}
/*!
* \brief Sets whether the application supports changing the locale settings at runtime.
* \remarks
* Set this to true if the application will retranslate its UI after the locale has changed.
* This requires the application to re-install translators and to re-invoke all ts() and
* translate() function calls. If set to true, the notice that the locale setting takes only
* effect after restarting is not shown anymore.
*/
void QtSettings::setRetranslatable(bool retranslatable)
{
m_d->retranslatable = retranslatable;
}
/*!
* \brief Returns whether a custom font is set.
*/
@ -169,6 +111,8 @@ void QtSettings::restore(QSettings &settings)
m_d->additionalPluginDirectory = settings.value(QStringLiteral("plugindir")).toString();
m_d->additionalIconThemeSearchPath = settings.value(QStringLiteral("iconthemepath")).toString();
TranslationFiles::additionalTranslationFilePath() = settings.value(QStringLiteral("trpath")).toString();
m_d->fontEngine = settings.value(QStringLiteral("fontengine")).toString();
m_d->enableDarkmode = settings.value(QStringLiteral("enabledarkmode")).toBool();
settings.endGroup();
}
@ -193,246 +137,85 @@ void QtSettings::save(QSettings &settings) const
settings.setValue(QStringLiteral("plugindir"), m_d->additionalPluginDirectory);
settings.setValue(QStringLiteral("iconthemepath"), m_d->additionalIconThemeSearchPath);
settings.setValue(QStringLiteral("trpath"), QVariant(TranslationFiles::additionalTranslationFilePath()));
settings.setValue(QStringLiteral("enforcefreetype"), m_d->fontEngine);
settings.setValue(QStringLiteral("enabledarkmode"), m_d->enableDarkmode);
settings.endGroup();
}
/*!
* \brief Returns the icon themes present in the specified \a searchPaths.
* \remarks The display name is the key and the actual icon theme name the value.
* This way the map is sorted correctly for display purposes.
* \brief Applies values from the current configuration which need to be set before the platform plugin has been
* instantiated.
*/
static QMap<QString, QString> scanIconThemes(const QStringList &searchPaths)
void QtSettings::applyPlatformSettings()
{
auto res = QMap<QString, QString>();
for (const auto &searchPath : searchPaths) {
const auto dir = QDir(searchPath).entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name);
for (const auto &iconTheme : dir) {
auto indexFile = QFile(searchPath % QChar('/') % iconTheme % QStringLiteral("/index.theme"));
auto index = QByteArray();
if (indexFile.open(QFile::ReadOnly) && !(index = indexFile.readAll()).isEmpty()) {
const auto iconThemeSection = index.indexOf("[Icon Theme]");
const auto nameStart = index.indexOf("Name=", iconThemeSection != -1 ? iconThemeSection : 0);
if (nameStart != -1) {
auto nameLength = index.indexOf("\n", nameStart) - nameStart - 5;
if (nameLength > 0) {
auto displayName = QString::fromUtf8(index.mid(nameStart + 5, nameLength));
if (displayName != iconTheme) {
displayName += QChar(' ') % QChar('(') % iconTheme % QChar(')');
}
res[displayName] = iconTheme;
continue;
}
}
}
res[iconTheme] = iconTheme;
}
}
return res;
}
/*!
* \brief Applies the current configuration.
* \brief Applies the current configuration except values which need to be set before the platform plugin has been
* instantiated.
* \remarks
* QApplication/QGuiApplication must be instantiated before calling this
* method. Hence it makes most sense to call this directly after instantiating
* QApplication/QGuiApplication.
*
* This function may be called multiple times. This supports restoring default
* settings (e.g. if use of a custom icon theme has been disabled again after it
* was enabled the default icon theme will be configured again).
* - Some settings take only affect after restarting the application.
* - QApplication/QGuiApplication must be instantiated before calling this
* method. Hence it makes most sense to call this directly after instantiating
* QApplication/QGuiApplication.
*/
void QtSettings::apply()
{
// apply environment
if (m_d->additionalPluginDirectory != m_d->previousPluginDirectory) {
if (!m_d->previousPluginDirectory.isEmpty()) {
QCoreApplication::removeLibraryPath(m_d->previousPluginDirectory);
}
if (!m_d->additionalPluginDirectory.isEmpty()) {
QCoreApplication::addLibraryPath(m_d->additionalPluginDirectory);
}
m_d->previousPluginDirectory = m_d->additionalPluginDirectory;
}
if (m_d->additionalIconThemeSearchPath != m_d->previousIconThemeSearchPath) {
auto paths = QIcon::themeSearchPaths();
if (!m_d->previousIconThemeSearchPath.isEmpty()) {
paths.removeAll(m_d->previousIconThemeSearchPath);
}
if (!m_d->additionalIconThemeSearchPath.isEmpty()) {
paths.append(m_d->additionalIconThemeSearchPath);
}
m_d->previousIconThemeSearchPath = m_d->additionalIconThemeSearchPath;
QIcon::setThemeSearchPaths(paths);
}
// read style sheet
auto styleSheet = QString();
QString styleSheet;
if (m_d->customStyleSheet && !m_d->styleSheetPath.isEmpty()) {
auto file = QFile(m_d->styleSheetPath);
QFile file(m_d->styleSheetPath);
if (!file.open(QFile::ReadOnly)) {
std::cerr << "Unable to open the specified stylesheet \"" << m_d->styleSheetPath.toLocal8Bit().data() << "\"." << std::endl;
cerr << "Unable to open the specified stylesheet \"" << m_d->styleSheetPath.toLocal8Bit().data() << "\"." << endl;
}
styleSheet.append(file.readAll());
if (file.error() != QFile::NoError) {
std::cerr << "Unable to read the specified stylesheet \"" << m_d->styleSheetPath.toLocal8Bit().data() << "\"." << std::endl;
cerr << "Unable to read the specified stylesheet \"" << m_d->styleSheetPath.toLocal8Bit().data() << "\"." << endl;
}
}
// apply appearance
if (m_d->customFont) {
if (!m_d->initialFont.has_value()) {
m_d->initialFont = QGuiApplication::font();
}
QGuiApplication::setFont(m_d->font);
} else if (m_d->initialFont.has_value()) {
QGuiApplication::setFont(m_d->initialFont.value());
}
#ifdef QT_UTILITIES_USE_FUSION_ON_WINDOWS_11
if (m_d->initialWidgetStyle.isEmpty()) {
// use Fusion on Windows 11 as the native style doesn't look good
// see https://bugreports.qt.io/browse/QTBUG-97668
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows11) {
m_d->initialWidgetStyle = QStringLiteral("Fusion");
}
}
#endif
if (m_d->customWidgetStyle) {
#if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0)
const auto *const currentStyle = QApplication::style();
if (m_d->initialWidgetStyle.isEmpty() && currentStyle) {
m_d->initialWidgetStyle = currentStyle->name();
}
#endif
QApplication::setStyle(m_d->widgetStyle);
} else if (!m_d->initialWidgetStyle.isEmpty()) {
QApplication::setStyle(m_d->initialWidgetStyle);
}
if (auto *const qapp = qobject_cast<QApplication *>(QApplication::instance())) {
qapp->setStyleSheet(styleSheet);
} else {
std::cerr << "Unable to apply the specified stylesheet \"" << m_d->styleSheetPath.toLocal8Bit().data()
<< "\" because no QApplication has been instantiated." << std::endl;
if (!styleSheet.isEmpty()) {
if (auto *qapp = qobject_cast<QApplication *>(QApplication::instance())) {
qapp->setStyleSheet(styleSheet);
} else {
cerr << "Unable to apply the specified stylesheet \"" << m_d->styleSheetPath.toLocal8Bit().data()
<< "\" because no QApplication has been instantiated." << endl;
}
}
if (m_d->customPalette) {
QGuiApplication::setPalette(m_d->palette);
} else {
QGuiApplication::setPalette(QPalette());
}
m_d->isPaletteDark = isPaletteDark();
if (m_d->customIconTheme) {
QIcon::setThemeName(m_d->iconTheme);
} else if (!m_d->initialIconTheme.isEmpty()) {
if (m_d->iconTheme != m_d->initialIconTheme) {
// set the icon theme back to what it was before changing anything (not sure how to read the current system icon theme again)
QIcon::setThemeName(m_d->initialIconTheme);
}
} else {
// use bundled default icon theme matching the current palette
// notes: - It is ok that search paths specified via CLI arguments are not set here yet. When doing so one should also
// specify the desired icon theme explicitly.
// - The icon themes "default" and "default-dark" come from QtConfig.cmake which makes the first non-dark bundled
// icon theme available as "default" and the first dark icon theme available as "default-dark". An icon theme
// is considered dark if it ends with "-dark".
const auto bundledIconThemes = scanIconThemes(QStringList(QStringLiteral(":/icons")));
if (m_d->isPaletteDark && bundledIconThemes.contains(QStringLiteral("default-dark"))) {
QIcon::setThemeName(QStringLiteral("default-dark"));
} else if (bundledIconThemes.contains(QStringLiteral("default"))) {
QIcon::setThemeName(QStringLiteral("default"));
}
}
// apply locale
m_d->previousLocale = QLocale();
QLocale::setDefault(m_d->customLocale ? QLocale(m_d->localeName) : m_d->defaultLocale);
// log some debug information on the first call if env variable set
static auto debugInfoLogged = false;
if (debugInfoLogged) {
return;
// apply environment
if (m_d->additionalPluginDirectory.isEmpty()) {
QCoreApplication::addLibraryPath(m_d->additionalPluginDirectory);
}
const auto debugLoggingEnabled = CppUtilities::isEnvVariableSet(PROJECT_VARNAME_UPPER "_LOG_QT_CONFIG");
if (debugLoggingEnabled.has_value() && debugLoggingEnabled.value()) {
if (const auto os = QOperatingSystemVersion::current(); os.type() != static_cast<decltype(os.type())>(QOperatingSystemVersion::Unknown)) {
const auto version = QVersionNumber(os.majorVersion(), os.minorVersion(), os.microVersion());
std::cerr << "OS name and version: " << os.name().toStdString() << ' ' << version.toString().toStdString() << '\n';
}
std::cerr << "Qt version: " << qVersion() << '\n';
std::cerr << "Qt platform (set QT_QPA_PLATFORM to override): " << QGuiApplication::platformName().toStdString() << '\n';
std::cerr << "Qt locale: " << QLocale().name().toStdString() << '\n';
std::cerr << "Qt library paths: " << QCoreApplication::libraryPaths().join(':').toStdString() << '\n';
std::cerr << "Qt theme search paths: " << QIcon::themeSearchPaths().join(':').toStdString() << '\n';
debugInfoLogged = true;
if (!m_d->additionalIconThemeSearchPath.isEmpty()) {
QIcon::setThemeSearchPaths(QIcon::themeSearchPaths() << m_d->additionalIconThemeSearchPath);
}
}
/*!
* \brief Re-applies default icon theme assuming the palette is dark or not depending on \a isPaletteDark.
*
* Re-assigns the appropriate default icon theme depending on the current palette. Call this function after the
* darkmode setting has changed without the current palette reflecting that but you want the darkmode setting take
* precedence over the palette (e.g. when using Qt Quick Material style under Android). If your application makes
* actually use of the palette and you want the palette take precedence than call \a reevaluatePaletteAndDefaultIconTheme()
* instead.
*
* Note that QtSettings::isPaletteDark() will return \a isPaletteDark after calling this function (even though the current
* palette is not actually reflecting that).
*
* \remarks
* - The default icon theme must have been assigned before using the apply() function.
* - This function has no effect if a custom icon theme is configured.
*/
void QtSettings::reapplyDefaultIconTheme(bool isPaletteDark)
{
if (isPaletteDark == m_d->isPaletteDark) {
return; // no need to do anything if there's no change
}
m_d->isPaletteDark = isPaletteDark;
if (auto iconTheme = QIcon::themeName(); iconTheme == QStringLiteral("default") || iconTheme == QStringLiteral("default-dark")) {
QIcon::setThemeName(m_d->isPaletteDark ? QStringLiteral("default-dark") : QStringLiteral("default"));
}
}
/*!
* \brief Re-evaluates whether the palette is dark and re-applies default icon theme.
*
* Re-assigns the appropriate default icon theme depending on the current palette. Call this function after the palette
* has changed.
*
* \remarks
* - The default icon theme must have been assigned before using the apply() function.
* - This function has no effect if a custom icon theme is configured.
*/
void QtSettings::reevaluatePaletteAndDefaultIconTheme()
{
reapplyDefaultIconTheme(QtUtilities::isPaletteDark());
}
/*!
* \brief Returns whether the palette is dark.
* \remarks
* Changes to the palette since the last call to apply() and reevaluatePaletteAndDefaultIconTheme() are not taken
* into account.
*/
bool QtSettings::isPaletteDark()
{
return m_d->isPaletteDark;
}
/*!
* \brief Returns whether the last apply() call has changed the default locale.
*/
bool QtSettings::hasLocaleChanged() const
{
return m_d->previousLocale != QLocale();
}
/*!
* \brief Returns a new OptionCatecory containing all Qt related option pages.
* \remarks
* - The QtSettings instance does not keep the ownership over the returned
* category.
* - The pages of the returned category require the QtSettings instance which
* hence must be present as long as all pages are destroyed.
* category.
* - The pages of the returned category require the QtSetings instance which
* hence must be present until all pages are destroyed.
*/
OptionCategory *QtSettings::category()
{
@ -456,13 +239,13 @@ QtAppearanceOptionPage::~QtAppearanceOptionPage()
bool QtAppearanceOptionPage::apply()
{
m_settings.font = ui()->fontComboBox->currentFont();
m_settings.font = ui()->fontComboBox->font();
m_settings.customFont = !ui()->fontCheckBox->isChecked();
m_settings.widgetStyle = ui()->widgetStyleComboBox->currentText();
m_settings.customWidgetStyle = !ui()->widgetStyleCheckBox->isChecked();
m_settings.styleSheetPath = ui()->styleSheetPathSelection->lineEdit()->text();
m_settings.customStyleSheet = !ui()->styleSheetCheckBox->isChecked();
m_settings.palette = m_settings.selectedPalette;
m_settings.palette = ui()->paletteToolButton->palette();
m_settings.customPalette = !ui()->paletteCheckBox->isChecked();
m_settings.iconTheme
= ui()->iconThemeComboBox->currentIndex() != -1 ? ui()->iconThemeComboBox->currentData().toString() : ui()->iconThemeComboBox->currentText();
@ -479,7 +262,7 @@ void QtAppearanceOptionPage::reset()
ui()->widgetStyleCheckBox->setChecked(!m_settings.customWidgetStyle);
ui()->styleSheetPathSelection->lineEdit()->setText(m_settings.styleSheetPath);
ui()->styleSheetCheckBox->setChecked(!m_settings.customStyleSheet);
m_settings.selectedPalette = m_settings.palette;
ui()->paletteToolButton->setPalette(m_settings.palette);
ui()->paletteCheckBox->setChecked(!m_settings.customPalette);
int iconThemeIndex = ui()->iconThemeComboBox->findData(m_settings.iconTheme);
if (iconThemeIndex != -1) {
@ -494,9 +277,6 @@ QWidget *QtAppearanceOptionPage::setupWidget()
{
// call base implementation first, so ui() is available
auto *widget = QtAppearanceOptionPageBase::setupWidget();
if (!m_settings.showNotices) {
ui()->label->hide();
}
// setup widget style selection
ui()->widgetStyleComboBox->addItems(QStyleFactory::keys());
@ -505,7 +285,7 @@ QWidget *QtAppearanceOptionPage::setupWidget()
ui()->styleSheetPathSelection->provideCustomFileMode(QFileDialog::ExistingFile);
// setup font selection
QObject::connect(ui()->fontPushButton, &QPushButton::clicked, widget, [this] {
QObject::connect(ui()->fontPushButton, &QPushButton::clicked, [this] {
if (!m_fontDialog) {
m_fontDialog = new QFontDialog(this->widget());
m_fontDialog->setCurrentFont(ui()->fontComboBox->font());
@ -516,19 +296,38 @@ QWidget *QtAppearanceOptionPage::setupWidget()
});
// setup palette selection
QObject::connect(ui()->paletteToolButton, &QToolButton::clicked, ui()->paletteToolButton,
[this] { m_settings.selectedPalette = PaletteEditor::getPalette(this->widget(), m_settings.selectedPalette); });
QObject::connect(ui()->paletteToolButton, &QToolButton::clicked,
[this] { ui()->paletteToolButton->setPalette(PaletteEditor::getPalette(this->widget(), ui()->paletteToolButton->palette())); });
// setup icon theme selection
const auto iconThemes = scanIconThemes(QIcon::themeSearchPaths() << QStringLiteral("/usr/share/icons/"));
auto *iconThemeComboBox = ui()->iconThemeComboBox;
for (auto i = iconThemes.begin(), end = iconThemes.end(); i != end; ++i) {
const auto &displayName = i.key();
const auto &id = i.value();
if (const auto existingItemIndex = iconThemeComboBox->findData(id); existingItemIndex != -1) {
iconThemeComboBox->setItemText(existingItemIndex, displayName);
} else {
iconThemeComboBox->addItem(displayName, id);
const QStringList searchPaths = QIcon::themeSearchPaths() << QStringLiteral("/usr/share/icons/");
for (const QString &searchPath : searchPaths) {
for (const QString &iconTheme : QDir(searchPath).entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name)) {
const int existingItemIndex = ui()->iconThemeComboBox->findData(iconTheme);
QFile indexFile(searchPath % QChar('/') % iconTheme % QStringLiteral("/index.theme"));
QByteArray index;
if (indexFile.open(QFile::ReadOnly) && !(index = indexFile.readAll()).isEmpty()) {
const int iconThemeSection = index.indexOf("[Icon Theme]");
const int nameStart = index.indexOf("Name=", iconThemeSection != -1 ? iconThemeSection : 0);
if (nameStart != -1) {
int nameLength = index.indexOf("\n", nameStart) - nameStart - 5;
if (nameLength > 0) {
QString displayName = index.mid(nameStart + 5, nameLength);
if (displayName != iconTheme) {
displayName += QChar(' ') % QChar('(') % iconTheme % QChar(')');
}
if (existingItemIndex != -1) {
ui()->iconThemeComboBox->setItemText(existingItemIndex, displayName);
} else {
ui()->iconThemeComboBox->addItem(displayName, iconTheme);
}
continue;
}
}
}
if (existingItemIndex == -1) {
ui()->iconThemeComboBox->addItem(iconTheme, iconTheme);
}
}
}
@ -562,29 +361,20 @@ QWidget *QtLanguageOptionPage::setupWidget()
{
// call base implementation first, so ui() is available
auto *widget = QtLanguageOptionPageBase::setupWidget();
if (m_settings.retranslatable) {
ui()->label->hide();
}
// add all available locales to combo box
auto *localeComboBox = ui()->localeComboBox;
const auto locales = QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript, QLocale::AnyCountry);
for (const QLocale &locale : locales) {
for (const QLocale &locale : QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript, QLocale::AnyCountry)) {
localeComboBox->addItem(locale.name());
}
auto *languageLabel = ui()->languageLabel;
QObject::connect(ui()->localeComboBox, &QComboBox::currentTextChanged, languageLabel, [languageLabel, localeComboBox] {
const auto selectedLocale = QLocale(localeComboBox->currentText());
const auto currentLocale = QLocale();
const auto territory =
#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
currentLocale.territoryToString(selectedLocale.territory());
#else
currentLocale.countryToString(selectedLocale.country());
#endif
QObject::connect(ui()->localeComboBox, &QComboBox::currentTextChanged, [languageLabel, localeComboBox] {
const QLocale selectedLocale(localeComboBox->currentText());
const QLocale currentLocale;
languageLabel->setText(QCoreApplication::translate("QtGui::QtLanguageOptionPage", "recognized by Qt as") % QStringLiteral(" <i>")
% currentLocale.languageToString(selectedLocale.language()) % QChar(',') % QChar(' ') % territory % QStringLiteral("</i>"));
% currentLocale.languageToString(selectedLocale.language()) % QChar(',') % QChar(' ')
% currentLocale.countryToString(selectedLocale.country()) % QStringLiteral("</i>"));
});
return widget;
}
@ -613,24 +403,6 @@ void QtEnvOptionPage::reset()
ui()->iconThemeSearchPathSelection->lineEdit()->setText(m_settings.additionalIconThemeSearchPath);
ui()->translationPathSelection->lineEdit()->setText(TranslationFiles::additionalTranslationFilePath());
}
QWidget *QtEnvOptionPage::setupWidget()
{
// call base implementation first, so ui() is available
return QtEnvOptionPageBase::setupWidget();
}
/*!
* \brief Returns a handle to the internal data.
* \remarks
* This is an opaque data structure. It can be used to construct option pages
* like QtLanguageOptionPage.
*/
QtSettings::operator QtSettingsData &() const
{
return *m_d.get();
}
} // namespace QtUtilities
INSTANTIATE_UI_FILE_BASED_OPTION_PAGE(QtAppearanceOptionPage)

View File

@ -15,11 +15,15 @@ struct QtSettingsData;
BEGIN_DECLARE_UI_FILE_BASED_OPTION_PAGE_CUSTOM_CTOR(QtAppearanceOptionPage)
public:
enum PresetFlags { Dark };
explicit QtAppearanceOptionPage(QtSettingsData &settings, QWidget *parentWidget = nullptr);
Q_SIGNALS:
void presetsApplied(PresetFlags flags);
private:
DECLARE_SETUP_WIDGETS
QtSettingsData & m_settings;
QtSettingsData &m_settings;
QFontDialog *m_fontDialog;
END_DECLARE_OPTION_PAGE
@ -29,7 +33,7 @@ explicit QtLanguageOptionPage(QtSettingsData &settings, QWidget *parentWidget =
private:
DECLARE_SETUP_WIDGETS
QtSettingsData & m_settings;
QtSettingsData &m_settings;
END_DECLARE_OPTION_PAGE
BEGIN_DECLARE_UI_FILE_BASED_OPTION_PAGE_CUSTOM_CTOR(QtEnvOptionPage)
@ -37,8 +41,7 @@ public:
explicit QtEnvOptionPage(QtSettingsData &settings, QWidget *parentWidget = nullptr);
private:
DECLARE_SETUP_WIDGETS
QtSettingsData & m_settings;
QtSettingsData &m_settings;
END_DECLARE_OPTION_PAGE
class QT_UTILITIES_EXPORT QtSettings {
@ -46,17 +49,11 @@ public:
QtSettings();
~QtSettings();
void disableNotices();
void setRetranslatable(bool retranslatable);
void restore(QSettings &settings);
void save(QSettings &settings) const;
void applyPlatformSettings();
void apply();
void reapplyDefaultIconTheme(bool isPaletteDark);
void reevaluatePaletteAndDefaultIconTheme();
bool isPaletteDark();
bool hasCustomFont() const;
bool hasLocaleChanged() const;
operator QtSettingsData &() const;
OptionCategory *category();

View File

@ -37,7 +37,7 @@ SettingsDialog::SettingsDialog(QWidget *parent)
{
m_ui->setupUi(this);
makeHeading(m_ui->headingLabel);
setStyleSheet(dialogStyleForPalette(palette()));
setStyleSheet(dialogStyle());
// setup models
m_categoryFilterModel->setSourceModel(m_categoryModel);
@ -155,20 +155,6 @@ void SettingsDialog::showCategory(OptionCategory *category)
updateTabWidget();
}
/*!
* \brief Allows to set the \a categories display name so that it is retranslated as needed.
* \remarks
* - The specified \a translator is supposed to return the display name to assign to \a category for the current
* locale. The \a translator is called immediately for the initial assignment and on language change events.
* - This function is experimental and might change or be removed completely in the next minor release.
*/
void SettingsDialog::translateCategory(OptionCategory *category, const std::function<QString()> &translator)
{
category->setDisplayName(translator());
connect(this, &SettingsDialog::retranslationRequired, category,
[category, translator = std::move(translator)] { category->setDisplayName(translator()); });
}
/*!
* \brief Enables *single-category mode* to show only the specified \a
* singleCategory.
@ -191,43 +177,6 @@ void SettingsDialog::setSingleCategory(OptionCategory *singleCategory)
}
}
/*!
* \brief Returns the tab-widget's corner widget.
*/
QWidget *SettingsDialog::cornerWidget(Qt::Corner corner) const
{
return m_ui->pagesTabWidget->cornerWidget(corner);
}
/*!
* \brief Sets the tab-widget's corner widget.
*/
void SettingsDialog::setCornerWidget(QWidget *widget, Qt::Corner corner)
{
m_ui->pagesTabWidget->setCornerWidget(widget, corner);
}
/*!
* \brief Adds a widget next to the heading.
*/
void SettingsDialog::addHeadingWidget(QWidget *widget)
{
m_ui->headingLayout->addWidget(widget);
}
/*!
* \brief Selects the specified page within the specified category.
*/
void SettingsDialog::selectPage(int categoryIndex, int pageIndex)
{
m_categoryFilterModel->setFilterFixedString(QString());
m_ui->filterLineEdit->clear();
showCategory(m_categoryModel->category(categoryIndex));
m_ui->categoriesListView->selectionModel()->select(
m_categoryFilterModel->mapFromSource(m_categoryModel->index(categoryIndex)), QItemSelectionModel::ClearAndSelect);
m_ui->pagesTabWidget->setCurrentIndex(pageIndex);
}
/*!
* \brief Updates the tab widget to show the pages for the current category.
*/
@ -238,35 +187,29 @@ void SettingsDialog::updateTabWidget()
return;
}
m_ui->pagesTabWidget->setUpdatesEnabled(false);
const auto searchKeyWord = m_ui->filterLineEdit->text();
const QString searchKeyWord = m_ui->filterLineEdit->text();
int index = 0, pageIndex = 0;
for (OptionPage *const page : m_currentCategory->pages()) {
if (page->matches(searchKeyWord)) {
// ensure the page's widget has no parent anymore; otherwise windowIcon() might return the parent's icon
auto *const widget = page->widget();
widget->setParent(nullptr);
// add the widget to the tab widget within a scroll area
QScrollArea *scrollArea;
if (index < m_ui->pagesTabWidget->count()) {
scrollArea = qobject_cast<QScrollArea *>(m_ui->pagesTabWidget->widget(index));
scrollArea->takeWidget();
m_ui->pagesTabWidget->setTabText(index, widget->windowTitle());
m_ui->pagesTabWidget->setTabIcon(index, widget->windowIcon());
m_ui->pagesTabWidget->setTabText(index, page->widget()->windowTitle());
m_ui->pagesTabWidget->setTabIcon(index, page->widget()->windowIcon());
} else {
scrollArea = new QScrollArea(m_ui->pagesTabWidget);
scrollArea->setFrameStyle(QFrame::NoFrame);
scrollArea->setBackgroundRole(QPalette::Base);
scrollArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
scrollArea->setWidgetResizable(true);
m_ui->pagesTabWidget->addTab(scrollArea, widget->windowTitle());
m_ui->pagesTabWidget->setTabIcon(index, widget->windowIcon());
m_ui->pagesTabWidget->addTab(scrollArea, page->widget()->windowTitle());
m_ui->pagesTabWidget->setTabIcon(index, page->widget()->windowIcon());
}
if (auto *const layout = widget->layout()) {
layout->setAlignment(Qt::AlignTop | Qt::AlignLeft);
if (page->widget()->layout()) {
page->widget()->layout()->setAlignment(Qt::AlignTop | Qt::AlignLeft);
}
scrollArea->setWidget(widget);
scrollArea->setWidget(page->widget());
++index;
}
if (pageIndex == m_currentCategory->currentIndex()) {
@ -274,31 +217,16 @@ void SettingsDialog::updateTabWidget()
}
++pageIndex;
}
// remove surplus tabs
while (index < m_ui->pagesTabWidget->count()) {
auto *const scrollArea = qobject_cast<QScrollArea *>(m_ui->pagesTabWidget->widget(index));
QScrollArea *const scrollArea = qobject_cast<QScrollArea *>(m_ui->pagesTabWidget->widget(index));
scrollArea->takeWidget();
m_ui->pagesTabWidget->removeTab(index);
delete scrollArea;
}
m_ui->pagesTabWidget->tabBar()->setHidden(!m_tabBarAlwaysVisible && m_ui->pagesTabWidget->count() == 1);
m_ui->pagesTabWidget->setUpdatesEnabled(true);
}
/*!
* \brief Updates the tab widget's tab texts to apply possible translation changes.
*/
void SettingsDialog::retranslateTabWidget()
{
for (auto index = 0; index < m_ui->pagesTabWidget->count(); ++index) {
const auto *const scrollArea = qobject_cast<const QScrollArea *>(m_ui->pagesTabWidget->widget(index));
const auto *const widget = scrollArea->widget();
m_ui->pagesTabWidget->setTabText(index, widget->windowTitle());
}
}
/*!
* \brief Applies all changes. Calls OptionCategory::applyAllPages() for each category.
* \remarks Pages which have not been shown yet must have not been initialized anyways
@ -355,22 +283,4 @@ void SettingsDialog::reset()
}
emit resetted();
}
bool SettingsDialog::event(QEvent *event)
{
const auto res = QDialog::event(event);
switch (event->type()) {
case QEvent::PaletteChange:
setStyleSheet(dialogStyleForPalette(palette()));
break;
case QEvent::LanguageChange:
m_ui->retranslateUi(this);
retranslateTabWidget();
emit retranslationRequired();
break;
default:;
}
return res;
}
} // namespace QtUtilities

View File

@ -31,30 +31,21 @@ public:
OptionCategory *category(int categoryIndex) const;
OptionPage *page(int categoryIndex, int pageIndex) const;
void showCategory(OptionCategory *category);
void translateCategory(OptionCategory *category, const std::function<QString()> &translator);
void setSingleCategory(OptionCategory *singleCategory);
QWidget *cornerWidget(Qt::Corner corner = Qt::TopRightCorner) const;
void setCornerWidget(QWidget *widget, Qt::Corner corner = Qt::TopRightCorner);
void addHeadingWidget(QWidget *widget);
void selectPage(int categoryIndex, int pageIndex);
public Q_SLOTS:
bool apply();
void reset();
Q_SIGNALS:
void applied();
void resetted();
void retranslationRequired();
protected:
bool event(QEvent *event) override;
void showEvent(QShowEvent *event) override;
private Q_SLOTS:
void currentCategoryChanged(const QModelIndex &index);
void updateTabWidget();
void retranslateTabWidget();
bool apply();
void reset();
private:
std::unique_ptr<Ui::SettingsDialog> m_ui;

View File

@ -35,6 +35,41 @@
<property name="bottomMargin">
<number>3</number>
</property>
<item row="0" column="1">
<widget class="QLabel" name="headingLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>500</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>No category selected</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QtUtilities::ClearLineEdit" name="filterLineEdit">
<property name="maximumSize">
<size>
<width>140</width>
<height>16777215</height>
</size>
</property>
<property name="placeholderText">
<string>Filter</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QTabWidget" name="pagesTabWidget">
<property name="currentIndex">
@ -61,39 +96,6 @@
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="headingLayout">
<item>
<widget class="QLabel" name="headingLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>No category selected</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QtUtilities::ClearLineEdit" name="filterLineEdit">
<property name="maximumSize">
<size>
<width>140</width>
<height>16777215</height>
</size>
</property>
<property name="placeholderText">
<string>Filter</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>

View File

@ -4,8 +4,8 @@
#include "../widgets/clearspinbox.h"
#include "../widgets/iconbutton.h"
#include <QHBoxLayout>
#include <QPushButton>
#include <QHBoxLayout>
#include <QtTest/QtTest>
using namespace QtUtilities;
@ -37,8 +37,7 @@ void ButtonOverlayTests::changeBasicConfiguration(ButtonOverlay &buttonOverlay)
{
buttonOverlay.setClearButtonEnabled(false);
QVERIFY2(!buttonOverlay.isClearButtonEnabled(), "clear button disabled");
buttonOverlay.enableInfoButton(
QIcon::fromTheme(QStringLiteral("data-information")).pixmap(IconButton::defaultPixmapSize), QStringLiteral("Some info"));
buttonOverlay.enableInfoButton(QIcon::fromTheme(QStringLiteral("data-information")).pixmap(IconButton::defaultPixmapSize), QStringLiteral("Some info"));
QVERIFY2(buttonOverlay.isInfoButtonEnabled(), "info button enabled");
}

View File

@ -2,8 +2,8 @@
#include "resources/config.h"
#include <QSignalSpy>
#include <QTest>
#include <QSignalSpy>
using namespace QtUtilities;
@ -61,17 +61,19 @@ void DBusNotificationTests::semiAutomaticTest()
auto envValueIsInt = false;
if (envValue.isEmpty() || (envValue.toInt(&envValueIsInt) == 0 && envValueIsInt)) {
QSKIP("Set the environment variable " PROJECT_VARNAME_UPPER "_ENABLE_SEMI_AUTOMATIC_NOTIFICATION_TESTS to run "
"the semi-automatic D-Bus notification test.");
"the semi-automatic D-Bus notification test.");
}
QVERIFY2(DBusNotification::isAvailable(), "D-Bus notifications are available");
DBusNotification n(QStringLiteral("Semi-automatic test"), NotificationIcon::Information, 10000);
QString clickedAction, error;
const auto actionConnection
= connect(&n, &DBusNotification::actionInvoked, [&clickedAction](const QString &actionName) { clickedAction = actionName; });
const auto errorConnection
= connect(&n, &DBusNotification::error, [&error]() { error = QStringLiteral("error occurred (TODO: pass an error message here)"); });
const auto actionConnection = connect(&n, &DBusNotification::actionInvoked, [&clickedAction] (const QString &actionName) {
clickedAction = actionName;
});
const auto errorConnection = connect(&n, &DBusNotification::error, [&error] () {
error = QStringLiteral("error occurred (TODO: pass an error message here)");
});
n.setApplicationName(QStringLiteral(APP_NAME " tests; " APP_VERSION));
n.show(QStringLiteral("Some message; will append more lines later"));
for (auto i = 1; i <= 10; ++i) {
@ -81,7 +83,7 @@ void DBusNotificationTests::semiAutomaticTest()
QCOMPARE(error, QString());
n.setImage(QIcon::fromTheme(QStringLiteral("document-open")).pixmap(64).toImage());
n.setTitle(n.title() + QStringLiteral(" - click action to continue"));
n.setActions(QStringList({ QStringLiteral("fail"), QStringLiteral("Let test fail"), QStringLiteral("pass"), QStringLiteral("Let test pass") }));
n.setActions(QStringList({QStringLiteral("fail"), QStringLiteral("Let test fail"), QStringLiteral("pass"), QStringLiteral("Let test pass")}));
QSignalSpy actionInvokedSpy(&n, &DBusNotification::actionInvoked);
n.update(QStringLiteral("Click on \"Let test pass\" to continue within 10 seconds"));
actionInvokedSpy.wait(10000);

View File

@ -1,7 +1,7 @@
#include "../settingsdialog/settingsdialog.h"
#include "../settingsdialog/optioncategory.h"
#include "../settingsdialog/optioncategorymodel.h"
#include "../settingsdialog/qtsettings.h"
#include "../settingsdialog/settingsdialog.h"
#include <QtTest/QtTest>
@ -22,14 +22,12 @@ void DialogsTests::testSettingsDialog()
settingsDlg.setSingleCategory(qtSettings.category());
// add another empty category
auto *const testCategory = new OptionCategory();
testCategory->setDisplayName(QStringLiteral("Test category"));
testCategory->setIcon(QIcon::fromTheme(QStringLiteral("preferences")));
settingsDlg.showCategory(nullptr); // ensure no current category is shown anymore
auto testCategory = OptionCategory();
testCategory.setDisplayName(QStringLiteral("Test category"));
testCategory.setIcon(QIcon::fromTheme(QStringLiteral("preferences")));
settingsDlg.setSingleCategory(nullptr);
auto *const qtCategory = qtSettings.category();
settingsDlg.categoryModel()->setCategories(QList<OptionCategory *>({ testCategory, qtCategory }));
settingsDlg.showCategory(qtCategory);
settingsDlg.categoryModel()->setCategories(QList<OptionCategory *>({&testCategory, qtSettings.category()}));
settingsDlg.showCategory(qtSettings.category());
settingsDlg.show();
}

View File

@ -9,18 +9,10 @@
<translation>Text löschen</translation>
</message>
</context>
<context>
<name>QtConfigArguments</name>
<message>
<location filename="../resources/qtconfigarguments.cpp" line="193"/>
<source>This application requires Windows 10, version 1809 or newer. The current Windows version is older so the application might not work correctly.</source>
<translation>Diese Anwendung benötigt mindestens Windows 10, version 1809 oder neuer. Die momentane Windows-Version ist älter. Deshalb wird die Anwendung möglicherweise nicht richtig funktionieren.</translation>
</message>
</context>
<context>
<name>QtGui::QtLanguageOptionPage</name>
<message>
<location filename="../settingsdialog/qtsettings.cpp" line="586"/>
<location filename="../settingsdialog/qtsettings.cpp" line="366"/>
<source>recognized by Qt as</source>
<translation>von Qt erkannt als</translation>
</message>
@ -28,39 +20,15 @@
<context>
<name>QtGui::QtOptionCategory</name>
<message>
<location filename="../settingsdialog/qtsettings.cpp" line="440"/>
<location filename="../settingsdialog/qtsettings.cpp" line="214"/>
<source>Qt</source>
<translation></translation>
</message>
</context>
<context>
<name>QtUtilities</name>
<message>
<location filename="../resources/resources.cpp" line="403"/>
<source>unable to access file</source>
<translation>Zugriff auf die Datei ist nicht möglich</translation>
</message>
<message>
<location filename="../resources/resources.cpp" line="406"/>
<source>file has invalid format</source>
<translation>Datei hat ungültiges Format</translation>
</message>
<message>
<location filename="../resources/resources.cpp" line="409"/>
<source>unknown error</source>
<translation>unbekannter Fehler</translation>
</message>
<message>
<location filename="../resources/resources.cpp" line="411"/>
<source>Unable to sync settings from &quot;%1&quot;: %2</source>
<translation>Settings können nicht unter &quot;%1&quot; synchronisiert werden: %2</translation>
</message>
</context>
<context>
<name>QtUtilities::AboutDialog</name>
<message>
<location filename="../aboutdialog/aboutdialog.ui" line="24"/>
<location filename="../aboutdialog/aboutdialog.cpp" line="139"/>
<source>About</source>
<translation>Über</translation>
</message>
@ -99,22 +67,22 @@
<translation type="vanished">verwendet Qt</translation>
</message>
<message>
<location filename="../aboutdialog/aboutdialog.cpp" line="62"/>
<location filename="../aboutdialog/aboutdialog.cpp" line="61"/>
<source>developed by %1</source>
<translation>entwickelt von %1</translation>
</message>
<message>
<location filename="../aboutdialog/aboutdialog.cpp" line="75"/>
<location filename="../aboutdialog/aboutdialog.cpp" line="71"/>
<source>Linked against:</source>
<translation>Gegen folgende Bibliotheken gelinkt:</translation>
</message>
<message>
<location filename="../aboutdialog/aboutdialog.cpp" line="80"/>
<location filename="../aboutdialog/aboutdialog.cpp" line="75"/>
<source>For updates and bug reports visit the &lt;a href=&quot;%1&quot; style=&quot;text-decoration: underline; color: palette(link);&quot;&gt;project website&lt;/a&gt;.</source>
<translation>Für Aktualisierung und Melden von Fehlern besuche die &lt;a href=&quot;%1&quot; style=&quot;text-decoration: underline; color: palette(link);&quot;&gt;Webseite des Projekts&lt;/a&gt;.</translation>
</message>
<message>
<location filename="../aboutdialog/aboutdialog.cpp" line="99"/>
<location filename="../aboutdialog/aboutdialog.cpp" line="91"/>
<source>Using &lt;a href=&quot;qtversion&quot;&gt;Qt %1&lt;/a&gt;</source>
<translation>Verwendet &lt;a href=&quot;qtversion&quot;&gt;Qt %1&lt;/a&gt;</translation>
</message>
@ -124,8 +92,8 @@
<message>
<location filename="../enterpassworddialog/enterpassworddialog.ui" line="12"/>
<location filename="../enterpassworddialog/enterpassworddialog.ui" line="51"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="183"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="198"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="190"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="205"/>
<source>Enter the password</source>
<translation>Passwort eingeben</translation>
</message>
@ -170,28 +138,28 @@
<translation>Bestätigen</translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="183"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="198"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="190"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="205"/>
<source>Enter the new password</source>
<translation>Neues Passwort festlegen</translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="289"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="290"/>
<source>You didn&apos;t enter a user name.</source>
<translation>Es wurde kein Benutzername eingegeben.</translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="291"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="292"/>
<source>You didn&apos;t enter a password.</source>
<translation>Es wurde kein Passwort eingegeben.</translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="296"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="297"/>
<source>You have to enter the new password twice to ensure you enterd it correct.</source>
<translation>Um sicher zu stellen, dass das neue Passwort richtig eingegeben wurde, muss es zweimal eingegeben werden.</translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="299"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="300"/>
<source>You mistyped the password.</source>
<translation>Erstes und zweites Passwort stimmen nicht überein.</translation>
</message>
@ -223,76 +191,26 @@
<source>Quick</source>
<translation>Einfach</translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="46"/>
<source>Save</source>
<translation>Speichern</translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="48"/>
<source>Load</source>
<translation>Laden</translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="155"/>
<source>Color palette configuration (*.ini)</source>
<translation>Farbpalettenkonfiguration (*.ini)</translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="162"/>
<source>Unable to load &quot;%1&quot;.</source>
<translation>Fehler beim Laden von &quot;%1&quot;.</translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="167"/>
<source>&quot;%1&quot; does not contain a valid palette.</source>
<translation>&quot;%1&quot; enthält keine gültige Farbpalette.</translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="180"/>
<source>Unable to write &quot;%1&quot;.</source>
<translation>Fehler beim Schreiben von &quot;%1&quot;.</translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="188"/>
<source>Load palette</source>
<translation>Palette laden</translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="200"/>
<source>Error reading palette</source>
<translation>Fehler beim Einlesen der Palette</translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="206"/>
<source>Save palette</source>
<translation>Palette speichern</translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="214"/>
<source>Error writing palette</source>
<translation>Fehler beim Schreiben der Palette</translation>
</message>
</context>
<context>
<name>QtUtilities::PaletteModel</name>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="416"/>
<location filename="../paletteeditor/paletteeditor.cpp" line="359"/>
<source>Color Role</source>
<translation>Farbrolle</translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="418"/>
<location filename="../paletteeditor/paletteeditor.cpp" line="361"/>
<source>Active</source>
<translation>Aktiv</translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="420"/>
<location filename="../paletteeditor/paletteeditor.cpp" line="363"/>
<source>Inactive</source>
<translation>Inaktiv</translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="422"/>
<location filename="../paletteeditor/paletteeditor.cpp" line="365"/>
<source>Disabled</source>
<translation>Deaktiviert</translation>
</message>
@ -300,24 +218,24 @@
<context>
<name>QtUtilities::PathSelection</name>
<message>
<location filename="../widgets/pathselection.cpp" line="87"/>
<location filename="../widgets/pathselection.cpp" line="144"/>
<location filename="../widgets/pathselection.cpp" line="56"/>
<location filename="../widgets/pathselection.cpp" line="76"/>
<source>Select ...</source>
<translation>Wählen ...</translation>
</message>
<message>
<location filename="../widgets/pathselection.cpp" line="92"/>
<location filename="../widgets/pathselection.cpp" line="81"/>
<source>Open</source>
<translation>Öffnen</translation>
</message>
<message>
<location filename="../widgets/pathselection.cpp" line="95"/>
<location filename="../widgets/pathselection.cpp" line="84"/>
<source>Explore</source>
<translation>Im Dateibrowser öffnen</translation>
</message>
<message>
<location filename="../widgets/pathselection.cpp" line="131"/>
<location filename="../widgets/pathselection.cpp" line="133"/>
<location filename="../widgets/pathselection.cpp" line="120"/>
<location filename="../widgets/pathselection.cpp" line="122"/>
<source>Select path</source>
<translation>Pfad auswählen</translation>
</message>
@ -481,38 +399,38 @@ Außerdem werden sie vielleicht vom QPA plugin überschrieben und funktionieren
<translation>Einstellungen</translation>
</message>
<message>
<location filename="../settingsdialog/settingsdialog.ui" line="75"/>
<location filename="../settingsdialog/settingsdialog.ui" line="53"/>
<location filename="../settingsdialog/settingsdialog.cpp" line="153"/>
<source>No category selected</source>
<translation>Keine Kategorie gewählt</translation>
</message>
<message>
<location filename="../settingsdialog/settingsdialog.ui" line="93"/>
<location filename="../settingsdialog/settingsdialog.ui" line="69"/>
<source>Filter</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog/settingsdialog.ui" line="134"/>
<location filename="../settingsdialog/settingsdialog.ui" line="136"/>
<source>Abort</source>
<translation>Abbrechen</translation>
</message>
<message>
<location filename="../settingsdialog/settingsdialog.ui" line="148"/>
<location filename="../settingsdialog/settingsdialog.ui" line="150"/>
<source>Apply</source>
<translation>Anwenden</translation>
</message>
<message>
<location filename="../settingsdialog/settingsdialog.ui" line="159"/>
<location filename="../settingsdialog/settingsdialog.ui" line="161"/>
<source>OK</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog/settingsdialog.cpp" line="320"/>
<location filename="../settingsdialog/settingsdialog.cpp" line="248"/>
<source>&lt;p&gt;&lt;b&gt;Errors occurred when applying changes:&lt;/b&gt;&lt;/p&gt;&lt;ul&gt;</source>
<translation>&lt;p&gt;&lt;b&gt;Beim Anwenden der Einstellungen sind Fehler aufgetreten:&lt;/b&gt;&lt;/p&gt;&lt;ul&gt;</translation>
</message>
<message>
<location filename="../settingsdialog/settingsdialog.cpp" line="325"/>
<location filename="../settingsdialog/settingsdialog.cpp" line="253"/>
<source>unknown error</source>
<translation>unbekannter Fehler</translation>
</message>
@ -524,22 +442,22 @@ Außerdem werden sie vielleicht vom QPA plugin überschrieben und funktionieren
<context>
<name>Utilities::windowTitle</name>
<message>
<location filename="../misc/dialogutils.cpp" line="36"/>
<location filename="../misc/dialogutils.cpp" line="34"/>
<source>Unsaved - %1</source>
<translation>Nicht gespeichert - %1</translation>
</message>
<message>
<location filename="../misc/dialogutils.cpp" line="39"/>
<location filename="../misc/dialogutils.cpp" line="37"/>
<source>%1 - %2 - %3</source>
<translation></translation>
</message>
<message>
<location filename="../misc/dialogutils.cpp" line="44"/>
<location filename="../misc/dialogutils.cpp" line="42"/>
<source>*Unsaved - %1</source>
<translation>*Nicht gespeichert - %1</translation>
</message>
<message>
<location filename="../misc/dialogutils.cpp" line="47"/>
<location filename="../misc/dialogutils.cpp" line="45"/>
<source>*%1 - %2 - %3</source>
<translation></translation>
</message>

View File

@ -9,18 +9,10 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QtConfigArguments</name>
<message>
<location filename="../resources/qtconfigarguments.cpp" line="193"/>
<source>This application requires Windows 10, version 1809 or newer. The current Windows version is older so the application might not work correctly.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QtGui::QtLanguageOptionPage</name>
<message>
<location filename="../settingsdialog/qtsettings.cpp" line="586"/>
<location filename="../settingsdialog/qtsettings.cpp" line="366"/>
<source>recognized by Qt as</source>
<translation type="unfinished"></translation>
</message>
@ -28,39 +20,15 @@
<context>
<name>QtGui::QtOptionCategory</name>
<message>
<location filename="../settingsdialog/qtsettings.cpp" line="440"/>
<location filename="../settingsdialog/qtsettings.cpp" line="214"/>
<source>Qt</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QtUtilities</name>
<message>
<location filename="../resources/resources.cpp" line="403"/>
<source>unable to access file</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../resources/resources.cpp" line="406"/>
<source>file has invalid format</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../resources/resources.cpp" line="409"/>
<source>unknown error</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../resources/resources.cpp" line="411"/>
<source>Unable to sync settings from &quot;%1&quot;: %2</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QtUtilities::AboutDialog</name>
<message>
<location filename="../aboutdialog/aboutdialog.ui" line="24"/>
<location filename="../aboutdialog/aboutdialog.cpp" line="139"/>
<source>About</source>
<translation type="unfinished"></translation>
</message>
@ -95,22 +63,22 @@
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../aboutdialog/aboutdialog.cpp" line="62"/>
<location filename="../aboutdialog/aboutdialog.cpp" line="61"/>
<source>developed by %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../aboutdialog/aboutdialog.cpp" line="75"/>
<location filename="../aboutdialog/aboutdialog.cpp" line="71"/>
<source>Linked against:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../aboutdialog/aboutdialog.cpp" line="80"/>
<location filename="../aboutdialog/aboutdialog.cpp" line="75"/>
<source>For updates and bug reports visit the &lt;a href=&quot;%1&quot; style=&quot;text-decoration: underline; color: palette(link);&quot;&gt;project website&lt;/a&gt;.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../aboutdialog/aboutdialog.cpp" line="99"/>
<location filename="../aboutdialog/aboutdialog.cpp" line="91"/>
<source>Using &lt;a href=&quot;qtversion&quot;&gt;Qt %1&lt;/a&gt;</source>
<translation type="unfinished"></translation>
</message>
@ -120,8 +88,8 @@
<message>
<location filename="../enterpassworddialog/enterpassworddialog.ui" line="12"/>
<location filename="../enterpassworddialog/enterpassworddialog.ui" line="51"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="183"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="198"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="190"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="205"/>
<source>Enter the password</source>
<translation type="unfinished"></translation>
</message>
@ -166,28 +134,28 @@
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="183"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="198"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="190"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="205"/>
<source>Enter the new password</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="289"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="290"/>
<source>You didn&apos;t enter a user name.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="291"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="292"/>
<source>You didn&apos;t enter a password.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="296"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="297"/>
<source>You have to enter the new password twice to ensure you enterd it correct.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="299"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="300"/>
<source>You mistyped the password.</source>
<translation type="unfinished"></translation>
</message>
@ -219,76 +187,26 @@
<source>Quick</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="46"/>
<source>Save</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="48"/>
<source>Load</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="155"/>
<source>Color palette configuration (*.ini)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="162"/>
<source>Unable to load &quot;%1&quot;.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="167"/>
<source>&quot;%1&quot; does not contain a valid palette.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="180"/>
<source>Unable to write &quot;%1&quot;.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="188"/>
<source>Load palette</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="200"/>
<source>Error reading palette</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="206"/>
<source>Save palette</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="214"/>
<source>Error writing palette</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QtUtilities::PaletteModel</name>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="416"/>
<location filename="../paletteeditor/paletteeditor.cpp" line="359"/>
<source>Color Role</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="418"/>
<location filename="../paletteeditor/paletteeditor.cpp" line="361"/>
<source>Active</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="420"/>
<location filename="../paletteeditor/paletteeditor.cpp" line="363"/>
<source>Inactive</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="422"/>
<location filename="../paletteeditor/paletteeditor.cpp" line="365"/>
<source>Disabled</source>
<translation type="unfinished"></translation>
</message>
@ -296,24 +214,24 @@
<context>
<name>QtUtilities::PathSelection</name>
<message>
<location filename="../widgets/pathselection.cpp" line="87"/>
<location filename="../widgets/pathselection.cpp" line="144"/>
<location filename="../widgets/pathselection.cpp" line="56"/>
<location filename="../widgets/pathselection.cpp" line="76"/>
<source>Select ...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../widgets/pathselection.cpp" line="92"/>
<location filename="../widgets/pathselection.cpp" line="81"/>
<source>Open</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../widgets/pathselection.cpp" line="95"/>
<location filename="../widgets/pathselection.cpp" line="84"/>
<source>Explore</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../widgets/pathselection.cpp" line="131"/>
<location filename="../widgets/pathselection.cpp" line="133"/>
<location filename="../widgets/pathselection.cpp" line="120"/>
<location filename="../widgets/pathselection.cpp" line="122"/>
<source>Select path</source>
<translation type="unfinished"></translation>
</message>
@ -464,38 +382,38 @@ These settings might be overwritten by your Qt platform integration plugin and h
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog/settingsdialog.ui" line="75"/>
<location filename="../settingsdialog/settingsdialog.ui" line="53"/>
<location filename="../settingsdialog/settingsdialog.cpp" line="153"/>
<source>No category selected</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog/settingsdialog.ui" line="93"/>
<location filename="../settingsdialog/settingsdialog.ui" line="69"/>
<source>Filter</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog/settingsdialog.ui" line="134"/>
<location filename="../settingsdialog/settingsdialog.ui" line="136"/>
<source>Abort</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog/settingsdialog.ui" line="148"/>
<location filename="../settingsdialog/settingsdialog.ui" line="150"/>
<source>Apply</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog/settingsdialog.ui" line="159"/>
<location filename="../settingsdialog/settingsdialog.ui" line="161"/>
<source>OK</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog/settingsdialog.cpp" line="320"/>
<location filename="../settingsdialog/settingsdialog.cpp" line="248"/>
<source>&lt;p&gt;&lt;b&gt;Errors occurred when applying changes:&lt;/b&gt;&lt;/p&gt;&lt;ul&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog/settingsdialog.cpp" line="325"/>
<location filename="../settingsdialog/settingsdialog.cpp" line="253"/>
<source>unknown error</source>
<translation type="unfinished"></translation>
</message>
@ -503,22 +421,22 @@ These settings might be overwritten by your Qt platform integration plugin and h
<context>
<name>Utilities::windowTitle</name>
<message>
<location filename="../misc/dialogutils.cpp" line="36"/>
<location filename="../misc/dialogutils.cpp" line="34"/>
<source>Unsaved - %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../misc/dialogutils.cpp" line="39"/>
<location filename="../misc/dialogutils.cpp" line="37"/>
<source>%1 - %2 - %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../misc/dialogutils.cpp" line="44"/>
<location filename="../misc/dialogutils.cpp" line="42"/>
<source>*Unsaved - %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../misc/dialogutils.cpp" line="47"/>
<location filename="../misc/dialogutils.cpp" line="45"/>
<source>*%1 - %2 - %3</source>
<translation type="unfinished"></translation>
</message>

View File

@ -1,527 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="zh_CN">
<context>
<name>QObject</name>
<message>
<location filename="../widgets/buttonoverlay.cpp" line="143"/>
<source>Clear</source>
<translation></translation>
</message>
</context>
<context>
<name>QtConfigArguments</name>
<message>
<location filename="../resources/qtconfigarguments.cpp" line="193"/>
<source>This application requires Windows 10, version 1809 or newer. The current Windows version is older so the application might not work correctly.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QtGui::QtLanguageOptionPage</name>
<message>
<location filename="../settingsdialog/qtsettings.cpp" line="586"/>
<source>recognized by Qt as</source>
<translation> Qt </translation>
</message>
</context>
<context>
<name>QtGui::QtOptionCategory</name>
<message>
<location filename="../settingsdialog/qtsettings.cpp" line="440"/>
<source>Qt</source>
<translation>Qt</translation>
</message>
</context>
<context>
<name>QtUtilities</name>
<message>
<location filename="../resources/resources.cpp" line="403"/>
<source>unable to access file</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../resources/resources.cpp" line="406"/>
<source>file has invalid format</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../resources/resources.cpp" line="409"/>
<source>unknown error</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../resources/resources.cpp" line="411"/>
<source>Unable to sync settings from &quot;%1&quot;: %2</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QtUtilities::AboutDialog</name>
<message>
<location filename="../aboutdialog/aboutdialog.ui" line="24"/>
<location filename="../aboutdialog/aboutdialog.cpp" line="139"/>
<source>About</source>
<translation></translation>
</message>
<message>
<location filename="../aboutdialog/aboutdialog.ui" line="127"/>
<source>application name</source>
<translation></translation>
</message>
<message>
<location filename="../aboutdialog/aboutdialog.ui" line="137"/>
<source>version</source>
<translation></translation>
</message>
<message>
<location filename="../aboutdialog/aboutdialog.ui" line="163"/>
<source>description</source>
<translation></translation>
</message>
<message>
<location filename="../aboutdialog/aboutdialog.ui" line="185"/>
<source>website link</source>
<translation></translation>
</message>
<message>
<location filename="../aboutdialog/aboutdialog.ui" line="226"/>
<source>creators</source>
<translation></translation>
</message>
<message>
<location filename="../aboutdialog/aboutdialog.ui" line="253"/>
<source>Using Qt</source>
<translation>使 Qt</translation>
</message>
<message>
<location filename="../aboutdialog/aboutdialog.cpp" line="62"/>
<source>developed by %1</source>
<translation> %1 </translation>
</message>
<message>
<location filename="../aboutdialog/aboutdialog.cpp" line="75"/>
<source>Linked against:</source>
<translation></translation>
</message>
<message>
<location filename="../aboutdialog/aboutdialog.cpp" line="80"/>
<source>For updates and bug reports visit the &lt;a href=&quot;%1&quot; style=&quot;text-decoration: underline; color: palette(link);&quot;&gt;project website&lt;/a&gt;.</source>
<translation>访&lt;a href=&quot;%1&quot; style=&quot;text-decoration: underline; color: Palette(link);&quot;&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../aboutdialog/aboutdialog.cpp" line="99"/>
<source>Using &lt;a href=&quot;qtversion&quot;&gt;Qt %1&lt;/a&gt;</source>
<translation>使 &lt;a href=&quot;qtversion&quot;&gt;Qt %1&lt;/a&gt;</translation>
</message>
</context>
<context>
<name>QtUtilities::EnterPasswordDialog</name>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.ui" line="12"/>
<location filename="../enterpassworddialog/enterpassworddialog.ui" line="51"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="183"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="198"/>
<source>Enter the password</source>
<translation></translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.ui" line="64"/>
<source>user name</source>
<translation></translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.ui" line="86"/>
<source>password</source>
<translation></translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.ui" line="102"/>
<source>repeat password</source>
<translation></translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.ui" line="130"/>
<source>show password</source>
<translation></translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.ui" line="137"/>
<source>don&apos;t use a password</source>
<translation>使</translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.ui" line="213"/>
<source>Capslock is active</source>
<translation></translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.ui" line="239"/>
<source>Abort</source>
<translation></translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.ui" line="254"/>
<source>Confirm</source>
<translation></translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="183"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="198"/>
<source>Enter the new password</source>
<translation></translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="289"/>
<source>You didn&apos;t enter a user name.</source>
<translation></translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="291"/>
<source>You didn&apos;t enter a password.</source>
<translation></translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="296"/>
<source>You have to enter the new password twice to ensure you enterd it correct.</source>
<translation></translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="299"/>
<source>You mistyped the password.</source>
<translation></translation>
</message>
</context>
<context>
<name>QtUtilities::PaletteEditor</name>
<message>
<location filename="../paletteeditor/paletteeditor.ui" line="20"/>
<source>Edit Palette</source>
<translation></translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.ui" line="53"/>
<source>Tune Palette</source>
<translation></translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.ui" line="84"/>
<source>Show Detai&amp;ls</source>
<translation>&amp;</translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.ui" line="91"/>
<source>&amp;Compute Details</source>
<translation>&amp;</translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.ui" line="101"/>
<source>Quick</source>
<translation></translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="46"/>
<source>Save</source>
<translation></translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="48"/>
<source>Load</source>
<translation></translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="155"/>
<source>Color palette configuration (*.ini)</source>
<translation> (*.ini)</translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="162"/>
<source>Unable to load &quot;%1&quot;.</source>
<translation> &quot;%1&quot;</translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="167"/>
<source>&quot;%1&quot; does not contain a valid palette.</source>
<translation>&quot;%1&quot; </translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="180"/>
<source>Unable to write &quot;%1&quot;.</source>
<translation> &quot;%1&quot;.</translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="188"/>
<source>Load palette</source>
<translation></translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="200"/>
<source>Error reading palette</source>
<translation></translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="206"/>
<source>Save palette</source>
<translation></translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="214"/>
<source>Error writing palette</source>
<translation></translation>
</message>
</context>
<context>
<name>QtUtilities::PaletteModel</name>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="416"/>
<source>Color Role</source>
<translation></translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="418"/>
<source>Active</source>
<translation></translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="420"/>
<source>Inactive</source>
<translation></translation>
</message>
<message>
<location filename="../paletteeditor/paletteeditor.cpp" line="422"/>
<source>Disabled</source>
<translation></translation>
</message>
</context>
<context>
<name>QtUtilities::PathSelection</name>
<message>
<location filename="../widgets/pathselection.cpp" line="87"/>
<location filename="../widgets/pathselection.cpp" line="144"/>
<source>Select ...</source>
<translation> ...</translation>
</message>
<message>
<location filename="../widgets/pathselection.cpp" line="92"/>
<source>Open</source>
<translation></translation>
</message>
<message>
<location filename="../widgets/pathselection.cpp" line="95"/>
<source>Explore</source>
<translation></translation>
</message>
<message>
<location filename="../widgets/pathselection.cpp" line="131"/>
<location filename="../widgets/pathselection.cpp" line="133"/>
<source>Select path</source>
<translation></translation>
</message>
</context>
<context>
<name>QtUtilities::QtAppearanceOptionPage</name>
<message>
<location filename="../settingsdialog/qtappearanceoptionpage.ui" line="6"/>
<source>Appearance</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog/qtappearanceoptionpage.ui" line="21"/>
<source>Use system default</source>
<translation>使</translation>
</message>
<message>
<location filename="../settingsdialog/qtappearanceoptionpage.ui" line="34"/>
<source>Font</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog/qtappearanceoptionpage.ui" line="71"/>
<source>More options ...</source>
<translation> ...</translation>
</message>
<message>
<location filename="../settingsdialog/qtappearanceoptionpage.ui" line="93"/>
<source>Widget style</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog/qtappearanceoptionpage.ui" line="132"/>
<source>Style sheet</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog/qtappearanceoptionpage.ui" line="162"/>
<source>Palette</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog/qtappearanceoptionpage.ui" line="175"/>
<source>select ...</source>
<translation> ...</translation>
</message>
<message>
<location filename="../settingsdialog/qtappearanceoptionpage.ui" line="195"/>
<source>Icon theme</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog/qtappearanceoptionpage.ui" line="249"/>
<source>These settings take effect after restarting the application.
These settings might be overwritten by your Qt platform integration plugin and hence have no effect.</source>
<translation>
Qt </translation>
</message>
</context>
<context>
<name>QtUtilities::QtEnvOptionPage</name>
<message>
<location filename="../settingsdialog/qtenvoptionpage.ui" line="14"/>
<source>Environment/paths</source>
<translation>Environment/paths</translation>
</message>
<message>
<location filename="../settingsdialog/qtenvoptionpage.ui" line="28"/>
<source>Additional plugin directory</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog/qtenvoptionpage.ui" line="38"/>
<source>Additional icon theme search path</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog/qtenvoptionpage.ui" line="48"/>
<source>Additional translation search path</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog/qtenvoptionpage.ui" line="79"/>
<source>These settings take effect after restarting the application.</source>
<translation></translation>
</message>
</context>
<context>
<name>QtUtilities::QtLanguageOptionPage</name>
<message>
<location filename="../settingsdialog/qtlanguageoptionpage.ui" line="6"/>
<source>Localization</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog/qtlanguageoptionpage.ui" line="43"/>
<source>Locale</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog/qtlanguageoptionpage.ui" line="53"/>
<source>Use system default</source>
<translation>使</translation>
</message>
<message>
<location filename="../settingsdialog/qtlanguageoptionpage.ui" line="98"/>
<source>These settings take effect after restarting the application.</source>
<translation></translation>
</message>
</context>
<context>
<name>QtUtilities::RecentMenuManager</name>
<message>
<location filename="../misc/recentmenumanager.cpp" line="35"/>
<source>&amp;Recent</source>
<translation>&amp;</translation>
</message>
<message>
<location filename="../misc/recentmenumanager.cpp" line="38"/>
<source>&amp;Clear list</source>
<translation>&amp;</translation>
</message>
<message>
<location filename="../misc/recentmenumanager.cpp" line="144"/>
<source>Recently opened files - </source>
<translation> - </translation>
</message>
<message>
<location filename="../misc/recentmenumanager.cpp" line="145"/>
<source>The selected file can&apos;t be found anymore. Do you want to delete the obsolete entry from the list?</source>
<translation></translation>
</message>
<message>
<location filename="../misc/recentmenumanager.cpp" line="148"/>
<source>keep entry</source>
<translation></translation>
</message>
<message>
<location filename="../misc/recentmenumanager.cpp" line="149"/>
<source>delete entry</source>
<translation></translation>
</message>
</context>
<context>
<name>QtUtilities::SettingsDialog</name>
<message>
<location filename="../settingsdialog/settingsdialog.ui" line="14"/>
<source>Settings</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog/settingsdialog.ui" line="75"/>
<location filename="../settingsdialog/settingsdialog.cpp" line="153"/>
<source>No category selected</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog/settingsdialog.ui" line="93"/>
<source>Filter</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog/settingsdialog.ui" line="134"/>
<source>Abort</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog/settingsdialog.ui" line="148"/>
<source>Apply</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog/settingsdialog.ui" line="159"/>
<source>OK</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog/settingsdialog.cpp" line="320"/>
<source>&lt;p&gt;&lt;b&gt;Errors occurred when applying changes:&lt;/b&gt;&lt;/p&gt;&lt;ul&gt;</source>
<translation>&lt;p&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;&lt;ul&gt;</translation>
</message>
<message>
<location filename="../settingsdialog/settingsdialog.cpp" line="325"/>
<source>unknown error</source>
<translation></translation>
</message>
</context>
<context>
<name>Utilities::windowTitle</name>
<message>
<location filename="../misc/dialogutils.cpp" line="36"/>
<source>Unsaved - %1</source>
<translation> - %1</translation>
</message>
<message>
<location filename="../misc/dialogutils.cpp" line="39"/>
<source>%1 - %2 - %3</source>
<translation>%1 - %2 - %3</translation>
</message>
<message>
<location filename="../misc/dialogutils.cpp" line="44"/>
<source>*Unsaved - %1</source>
<translation>* - %1</translation>
</message>
<message>
<location filename="../misc/dialogutils.cpp" line="47"/>
<source>*%1 - %2 - %3</source>
<translation>*%1 - %2 - %3</translation>
</message>
</context>
</TS>

View File

@ -53,7 +53,7 @@ PathSelection::PathSelection(QWidget *parent)
m_lineEdit->installEventFilter(this);
m_lineEdit->setCompleter(s_completer);
m_button->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
setTexts();
m_button->setText(tr("Select ..."));
auto *const layout = new QHBoxLayout(this);
layout->setSpacing(3);
@ -65,17 +65,6 @@ PathSelection::PathSelection(QWidget *parent)
connect(m_button, &QPushButton::clicked, this, &PathSelection::showFileDialog);
}
bool PathSelection::event(QEvent *event)
{
switch (event->type()) {
case QEvent::LanguageChange:
setTexts();
break;
default:;
}
return QWidget::event(event);
}
bool PathSelection::eventFilter(QObject *obj, QEvent *event)
{
#ifndef QT_NO_CONTEXTMENU
@ -138,10 +127,4 @@ void PathSelection::showFileDialog()
}
}
}
void PathSelection::setTexts()
{
m_button->setText(tr("Select ..."));
}
} // namespace QtUtilities

View File

@ -24,12 +24,10 @@ public:
void provideCustomFileDialog(QFileDialog *customFileDialog);
protected:
bool event(QEvent *event) override;
bool eventFilter(QObject *obj, QEvent *event) override;
private Q_SLOTS:
void showFileDialog();
void setTexts();
private:
ClearLineEdit *m_lineEdit;