Compare commits

...

38 Commits

Author SHA1 Message Date
Martchus 6016ec4bff Set the desktop file name via `SET_QT_APPLICATION_INFO` 2024-04-08 12:37:39 +02:00
Martchus 4feedbb057 Bump patch version 2024-04-08 12:36:51 +02:00
Martchus ded20b34a6 Add helper to react to darkmode changes 2024-03-31 22:48:22 +02:00
Martchus d20130d770 Update translations 2024-03-31 13:45:35 +02:00
Martchus a7d2611400 Allow re-applying the default icon theme independently of palette
This is useful under Android where the palette is apparently not set to
something matching the darkmode setting but the Qt Quick Material style
nevertheless seems to follow the darkmode setting. So we just want to take
the darkmode setting into account for assigning the appropriate icon theme
and ignore the palette.
2024-03-31 13:42:38 +02:00
Martchus 264386acad Bump minor version 2024-03-31 13:28:49 +02:00
Martchus 8ee322abb7 Deprecate the CMake module `AndroidApk` 2024-03-17 00:42:19 +01:00
Martchus bbd42e167d Adapt default QQC2 style definitions for Qt 6
The casing is important, otherwise this results in the error
`module "material" is not installed`.
2024-03-16 23:17:30 +01:00
Martchus 63ffbc4a6f Avoid warning after `QOperatingSystemVersion::OSType` was moved
This is now `QOperatingSystemVersionBase::OSType` causing a warning about
an implicit conversion. Making an explicit cast to whatever type
`os.type()` actually returns (depends on the Qt version) this warning does
not occur anymore and the code should still compile with any Qt version.
2024-03-15 23:54:17 +01:00
Martchus 600470e609 Bump patch version 2024-03-15 23:50:29 +01:00
Martchus 7a07077daf Apply change of `global.h` template 2024-02-22 19:42:13 +01:00
Martchus 7e7f8a5740 Fix configuring macro for network information plugins
The actual name of these plugins differs from the name of the CMake target.
2024-02-16 17:40:16 +01:00
Martchus 6dd98369b8 Allow configuring network information plugins 2024-02-15 21:51:48 +01:00
Martchus 6e103e09ad Update copyright date 2024-02-15 21:47:03 +01:00
Martchus 5bb21d2ead Bump patch version 2024-02-15 21:46:54 +01:00
Martchus 010f5d8408 No longer enforce Fusion style on Windows 11 as of Qt 6.7
It looks like Qt 6.7 is going to provide a style for Windows 11 that will
fix the mentioned bug.
2023-12-15 15:56:09 +01:00
Martchus a30509a743 Add `ModernWindowsStyle` to list of style plugins
It looks like `WindowsVistaStyle`-plugin is going to be renamed
to `ModernWindowsStyle`-plugin. This plugin is going to provide the old
style `windowsvista` and the new style `windows11`.

I haven't seen any changelogs yet but that's what it looks like so far:
https://code.qt.io/cgit/qt/qtbase.git/tree/src/plugins/styles/modernwindows?h=6.7
2023-12-15 15:42:21 +01:00
Martchus 02a5617e36 Bump patch version 2023-12-15 15:36:07 +01:00
Martchus 5a7dac58ac Update translations 2023-11-18 22:08:45 +01:00
Martchus adf64a3d0d Apply clang-format 2023-11-18 22:05:36 +01:00
Martchus f52c7b8214 Fix error message when Qt/KF module is not found 2023-11-18 22:04:25 +01:00
Martchus 88310af665 Show a warning if the current Windows version is not supported 2023-11-18 22:03:27 +01:00
Martchus 265d3739c8 Bump patch version 2023-11-18 22:02:16 +01:00
Martchus 0eaa556a66 Update translations 2023-10-29 21:23:28 +01:00
Martchus 671617bf10 Apply cmake-format 2023-10-29 21:23:18 +01:00
Martchus c347bbfe1f Fix compilation against Qt < 6.1 2023-10-29 21:23:01 +01:00
Martchus c43ba340df Allow configuring OpenGL and Wayland support when linking against static Qt 2023-10-27 21:27:05 +02:00
Martchus cfa8347f19 Update translations 2023-10-15 16:57:52 +02:00
Martchus 458d98a279 Allow logging a few useful Qt-related information by setting env variable
Log Qt-related info when the environment variable
QT_UTILITIES_LOG_QT_CONFIG is set.
2023-10-14 20:44:59 +02:00
Martchus dcc6f71f1e Avoid unqualified `std` calls in `qtsettings.cpp` 2023-10-14 20:09:31 +02:00
Martchus a1f50456e8 Use `QLocale::territory()` instead of deprecated `QLocale::country()` 2023-10-14 20:03:37 +02:00
Martchus d546777f8c Make X11 optional 2023-10-11 18:11:07 +02:00
Martchus 91b9eed2d0 Ensure `use_package` is defined when configuring capslock detection 2023-09-19 12:36:44 +02:00
Martchus d47a5a93ed Update translations 2023-09-11 21:27:56 +02:00
Martchus 6bce4c40f2 Improve configuration and code of capslock detection
* Define `X_AVAILABLE` if that's the case so the X11-specific code can
  actually ever be effective
* Make the default for `CAPSLOCK_DETECTION` simply depending on whether it
  can be configured instead of making it platform dependent
* Simplify code and avoid warnings in X11-specific code
2023-09-11 21:27:41 +02:00
Martchus 472e32bfc2 Apply cmake-format 2023-09-11 21:20:43 +02:00
Martchus 56865f3a89 Add one hard-coded fallback search paths for icon themes
The `CMAKE_INSTALL_DATAROOTDIR` variable might be overridden by the project
to point to some custom location (e.g. `share/games` instead of `share`)
but this doesn't mean we will be able to find icons there.

Since icons are almost always under `/usr/share/icons` it makes sense to
add that location as one last hard-coded fallback to avoid having to
specify `BUILTIN_ICON_THEMES_SEARCH_PATH` in that common case.
2023-09-06 17:32:53 +02:00
Martchus 490345b2ca Bump patch version 2023-09-06 17:29:24 +02:00
19 changed files with 320 additions and 112 deletions

View File

@ -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 13)
set(META_VERSION_MINOR 14)
set(META_VERSION_PATCH 1)
set(META_APP_VERSION ${META_VERSION_MAJOR}.${META_VERSION_MINOR}.${META_VERSION_PATCH})
@ -116,28 +116,35 @@ 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}")
# configure platform specific capslock detection for enterpassworddialog.cpp
if (WIN32
OR (UNIX
AND NOT APPLE
AND NOT ANDROID))
set(ENABLE_CAPSLOCK_DETECTION_BY_DEFAULT ON)
else ()
set(ENABLE_CAPSLOCK_DETECTION_BY_DEFAULT OFF)
# 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 ()
option(CAPSLOCK_DETECTION "enables capslock detection" ${ENABLE_CAPSLOCK_DETECTION_BY_DEFAULT})
if (CAPSLOCK_DETECTION)
if (WIN32)
# WinAPI provides functions to provide capslock detection
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)
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)
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 ()
endif ()
option(CAPSLOCK_DETECTION "enables capslock detection" ${HAVE_PLATFORM_SPECIFIC_CAPSLOCK_DETECTION})
if (CAPSLOCK_DETECTION)
if (NOT HAVE_PLATFORM_SPECIFIC_CAPSLOCK_DETECTION)
message(FATAL_ERROR "No backend for capslock detection found (WinAPI or X11 must be provided)")
endif ()
@ -169,19 +176,6 @@ 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")
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()
# include modules to apply configuration
include(BasicConfig)
include(QtGuiConfig)

View File

@ -12,6 +12,6 @@ core, gui, widgets
Some header files also require further Qt modules.
## Copyright notice and license
Copyright © 2015-2023 Marius Kittler
Copyright © 2015-2024 Marius Kittler
All code is licensed under [GPL-2-or-later](LICENSE).

View File

@ -1,5 +1,8 @@
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.")
# adds a target to create an Android APK with the help of androiddeployqt if target platform is Android
if (NOT ANDROID)

View File

@ -112,6 +112,12 @@ if (NOT DEFINED TLS_SUPPORT)
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)
@ -177,7 +183,34 @@ if (STATIC_LINKAGE OR QT_TARGET_TYPE STREQUAL STATIC_LIBRARY)
XcbIntegration
ONLY_PLUGINS)
endif ()
if (TARGET "${QT_PACKAGE_PREFIX}::QWaylandIntegrationPlugin")
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}"
@ -188,6 +221,23 @@ if (STATIC_LINKAGE OR QT_TARGET_TYPE STREQUAL STATIC_LIBRARY)
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}"
@ -196,10 +246,7 @@ if (STATIC_LINKAGE OR QT_TARGET_TYPE STREQUAL STATIC_LIBRARY)
MODULE
WaylandClient
PLUGINS
WaylandXdgShellIntegration
WaylandWlShellIntegration
WaylandIviShellIntegration
WaylandQtShellIntegration
${QT_CONFIG_WAYLAND_CLIENT_PLUGINS}
ONLY_PLUGINS
PLUGINS_OPTIONAL)
endif ()
@ -233,9 +280,41 @@ if (STATIC_LINKAGE OR QT_TARGET_TYPE STREQUAL STATIC_LIBRARY)
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 WindowsVistaStyle MacStyle AndroidStyle)
set(KNOWN_WIDGET_STYLE_PLUGINS ModernWindowsStyle WindowsVistaStyle MacStyle AndroidStyle)
set(USED_WIDGET_STYLE_PLUGINS)
if (Widgets IN_LIST QT_MODULES)
foreach (WIDGET_STYLE_PLUGIN ${KNOWN_WIDGET_STYLE_PLUGINS})
@ -521,6 +600,9 @@ if (REQUIRED_ICONS)
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")

View File

@ -75,7 +75,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 ${ARGS_PREFIX}${ARGS_MODULE} does not provide the target ${TARGET}.")
message(FATAL_ERROR "The CMake module ${ARGS_PREFIX}${ARGS_MODULE} does not provide the target ${TARGET}.")
endif ()
if ("${TARGET}" IN_LIST "${ARGS_LIBRARIES_VARIABLE}")
continue()

View File

@ -13,5 +13,6 @@
#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,8 +12,7 @@
#include <QMessageBox>
#include <QStyle>
#ifdef QT_UTILITIES_PLATFORM_SPECIFIC_CAPSLOCK_DETECTION
#if defined(Q_OS_WIN32)
#if defined(QT_UTILITIES_PLATFORM_SPECIFIC_CAPSLOCK_DETECTION) && defined(Q_OS_WIN32)
#include <windows.h>
#elif defined(X_AVAILABLE)
#include <X11/XKBlib.h>
@ -22,7 +21,6 @@
#undef FocusIn
#undef FocusOut
#endif
#endif
namespace QtUtilities {
@ -52,12 +50,7 @@ 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);
@ -330,22 +323,17 @@ void EnterPasswordDialog::confirm()
*/
bool EnterPasswordDialog::isCapslockPressed()
{
#ifdef QT_UTILITIES_PLATFORM_SPECIFIC_CAPSLOCK_DETECTION
// platform dependent method of determining if CAPS LOCK is pressed
#if defined(Q_OS_WIN32)
#if defined(QT_UTILITIES_PLATFORM_SPECIFIC_CAPSLOCK_DETECTION) && defined(Q_OS_WIN32)
return GetKeyState(VK_CAPITAL) == 1;
#elif defined(X_AVAILABLE)
Display *d = XOpenDisplay((char *)0);
bool caps_state = false;
auto *const d = XOpenDisplay(nullptr);
auto capsState = false;
if (d) {
unsigned n;
XkbGetIndicatorState(d, XkbUseCoreKbd, &n);
caps_state = (n & 0x01) == 1;
capsState = (n & 0x01) == 1;
}
return caps_state;
#else
return false;
#endif
return capsState;
#else
return false;
#endif

View File

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

View File

@ -69,4 +69,27 @@ std::optional<bool> isDarkModeEnabled()
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,10 +3,13 @@
#include "../global.h"
#include <QMetaObject>
#include <QPalette>
#include <functional>
#include <optional>
QT_FORWARD_DECLARE_CLASS(QObject)
QT_FORWARD_DECLARE_CLASS(QString)
namespace QtUtilities {
@ -14,6 +17,8 @@ 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

View File

@ -24,6 +24,7 @@ IMPORT_IMAGE_FORMAT_PLUGINS
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

@ -17,6 +17,12 @@
#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>
@ -180,5 +186,14 @@ 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,6 +9,13 @@
#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)
@ -16,6 +23,8 @@
#endif
#endif
#endif
namespace CppUtilities {
class QT_UTILITIES_EXPORT QtConfigArguments {

View File

@ -16,6 +16,18 @@ 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.
@ -26,6 +38,7 @@ 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()
/*!

View File

@ -12,19 +12,25 @@
#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))
#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
@ -33,8 +39,6 @@
#include <memory>
#include <optional>
using namespace std;
namespace QtUtilities {
struct QtSettingsData {
@ -91,7 +95,7 @@ inline QtSettingsData::QtSettingsData()
* system-default.
*/
QtSettings::QtSettings()
: m_d(make_unique<QtSettingsData>())
: m_d(std::make_unique<QtSettingsData>())
{
}
@ -266,11 +270,11 @@ void QtSettings::apply()
if (m_d->customStyleSheet && !m_d->styleSheetPath.isEmpty()) {
auto file = QFile(m_d->styleSheetPath);
if (!file.open(QFile::ReadOnly)) {
cerr << "Unable to open the specified stylesheet \"" << m_d->styleSheetPath.toLocal8Bit().data() << "\"." << endl;
std::cerr << "Unable to open the specified stylesheet \"" << m_d->styleSheetPath.toLocal8Bit().data() << "\"." << std::endl;
}
styleSheet.append(file.readAll());
if (file.error() != QFile::NoError) {
cerr << "Unable to read the specified stylesheet \"" << m_d->styleSheetPath.toLocal8Bit().data() << "\"." << endl;
std::cerr << "Unable to read the specified stylesheet \"" << m_d->styleSheetPath.toLocal8Bit().data() << "\"." << std::endl;
}
}
@ -306,8 +310,8 @@ void QtSettings::apply()
if (auto *const 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;
std::cerr << "Unable to apply the specified stylesheet \"" << m_d->styleSheetPath.toLocal8Bit().data()
<< "\" because no QApplication has been instantiated." << std::endl;
}
if (m_d->customPalette) {
QGuiApplication::setPalette(m_d->palette);
@ -340,6 +344,52 @@ void QtSettings::apply()
// 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;
}
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;
}
}
/*!
* \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"));
}
}
/*!
@ -354,14 +404,7 @@ void QtSettings::apply()
*/
void QtSettings::reevaluatePaletteAndDefaultIconTheme()
{
const auto isPaletteDark = QtUtilities::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"));
}
reapplyDefaultIconTheme(QtUtilities::isPaletteDark());
}
/*!
@ -532,11 +575,16 @@ QWidget *QtLanguageOptionPage::setupWidget()
auto *languageLabel = ui()->languageLabel;
QObject::connect(ui()->localeComboBox, &QComboBox::currentTextChanged, languageLabel, [languageLabel, localeComboBox] {
const QLocale selectedLocale(localeComboBox->currentText());
const QLocale currentLocale;
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
languageLabel->setText(QCoreApplication::translate("QtGui::QtLanguageOptionPage", "recognized by Qt as") % QStringLiteral(" <i>")
% currentLocale.languageToString(selectedLocale.language()) % QChar(',') % QChar(' ')
% currentLocale.countryToString(selectedLocale.country()) % QStringLiteral("</i>"));
% currentLocale.languageToString(selectedLocale.language()) % QChar(',') % QChar(' ') % territory % QStringLiteral("</i>"));
});
return widget;
}

View File

@ -19,7 +19,7 @@ explicit QtAppearanceOptionPage(QtSettingsData &settings, QWidget *parentWidget
private:
DECLARE_SETUP_WIDGETS
QtSettingsData &m_settings;
QtSettingsData & m_settings;
QFontDialog *m_fontDialog;
END_DECLARE_OPTION_PAGE
@ -29,7 +29,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)
@ -38,7 +38,7 @@ explicit QtEnvOptionPage(QtSettingsData &settings, QWidget *parentWidget = nullp
private:
DECLARE_SETUP_WIDGETS
QtSettingsData &m_settings;
QtSettingsData & m_settings;
END_DECLARE_OPTION_PAGE
class QT_UTILITIES_EXPORT QtSettings {
@ -51,6 +51,7 @@ public:
void restore(QSettings &settings);
void save(QSettings &settings) const;
void apply();
void reapplyDefaultIconTheme(bool isPaletteDark);
void reevaluatePaletteAndDefaultIconTheme();
bool isPaletteDark();
bool hasCustomFont() const;

View File

@ -9,10 +9,18 @@
<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="537"/>
<location filename="../settingsdialog/qtsettings.cpp" line="586"/>
<source>recognized by Qt as</source>
<translation>von Qt erkannt als</translation>
</message>
@ -20,7 +28,7 @@
<context>
<name>QtGui::QtOptionCategory</name>
<message>
<location filename="../settingsdialog/qtsettings.cpp" line="397"/>
<location filename="../settingsdialog/qtsettings.cpp" line="440"/>
<source>Qt</source>
<translation></translation>
</message>
@ -116,8 +124,8 @@
<message>
<location filename="../enterpassworddialog/enterpassworddialog.ui" line="12"/>
<location filename="../enterpassworddialog/enterpassworddialog.ui" line="51"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="190"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="205"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="183"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="198"/>
<source>Enter the password</source>
<translation>Passwort eingeben</translation>
</message>
@ -162,28 +170,28 @@
<translation>Bestätigen</translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="190"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="205"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="183"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="198"/>
<source>Enter the new password</source>
<translation>Neues Passwort festlegen</translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="296"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="289"/>
<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="298"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="291"/>
<source>You didn&apos;t enter a password.</source>
<translation>Es wurde kein Passwort eingegeben.</translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="303"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="296"/>
<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="306"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="299"/>
<source>You mistyped the password.</source>
<translation>Erstes und zweites Passwort stimmen nicht überein.</translation>
</message>

View File

@ -9,10 +9,18 @@
<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="537"/>
<location filename="../settingsdialog/qtsettings.cpp" line="586"/>
<source>recognized by Qt as</source>
<translation type="unfinished"></translation>
</message>
@ -20,7 +28,7 @@
<context>
<name>QtGui::QtOptionCategory</name>
<message>
<location filename="../settingsdialog/qtsettings.cpp" line="397"/>
<location filename="../settingsdialog/qtsettings.cpp" line="440"/>
<source>Qt</source>
<translation type="unfinished"></translation>
</message>
@ -112,8 +120,8 @@
<message>
<location filename="../enterpassworddialog/enterpassworddialog.ui" line="12"/>
<location filename="../enterpassworddialog/enterpassworddialog.ui" line="51"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="190"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="205"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="183"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="198"/>
<source>Enter the password</source>
<translation type="unfinished"></translation>
</message>
@ -158,28 +166,28 @@
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="190"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="205"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="183"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="198"/>
<source>Enter the new password</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="296"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="289"/>
<source>You didn&apos;t enter a user name.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="298"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="291"/>
<source>You didn&apos;t enter a password.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="303"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="296"/>
<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="306"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="299"/>
<source>You mistyped the password.</source>
<translation type="unfinished"></translation>
</message>

View File

@ -9,10 +9,18 @@
<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="537"/>
<location filename="../settingsdialog/qtsettings.cpp" line="586"/>
<source>recognized by Qt as</source>
<translation> Qt </translation>
</message>
@ -20,7 +28,7 @@
<context>
<name>QtGui::QtOptionCategory</name>
<message>
<location filename="../settingsdialog/qtsettings.cpp" line="397"/>
<location filename="../settingsdialog/qtsettings.cpp" line="440"/>
<source>Qt</source>
<translation>Qt</translation>
</message>
@ -112,8 +120,8 @@
<message>
<location filename="../enterpassworddialog/enterpassworddialog.ui" line="12"/>
<location filename="../enterpassworddialog/enterpassworddialog.ui" line="51"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="190"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="205"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="183"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="198"/>
<source>Enter the password</source>
<translation></translation>
</message>
@ -158,28 +166,28 @@
<translation></translation>
</message>
<message>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="190"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="205"/>
<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="296"/>
<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="298"/>
<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="303"/>
<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="306"/>
<location filename="../enterpassworddialog/enterpassworddialog.cpp" line="299"/>
<source>You mistyped the password.</source>
<translation></translation>
</message>