diff --git a/.gitignore b/.gitignore
index 19aa9e681..a0ade0b76 100644
--- a/.gitignore
+++ b/.gitignore
@@ -166,3 +166,7 @@ $RECYCLE.BIN/
*.udb
__pycache__
+
+# Temporary svg cursor files
+/src/app/valentina/share/resources/cursor/svg/light/
+/src/app/valentina/share/resources/cursor/svg/dark/
diff --git a/dist/macx/puzzle/Info.plist b/dist/macx/puzzle/Info.plist
index 45d697081..f6977f8e5 100755
--- a/dist/macx/puzzle/Info.plist
+++ b/dist/macx/puzzle/Info.plist
@@ -66,7 +66,5 @@
- NSRequiresAquaSystemAppearance
-
diff --git a/dist/macx/tape/Info.plist b/dist/macx/tape/Info.plist
index 0c9ff74e5..41c3199f6 100755
--- a/dist/macx/tape/Info.plist
+++ b/dist/macx/tape/Info.plist
@@ -102,7 +102,5 @@
- NSRequiresAquaSystemAppearance
-
diff --git a/dist/macx/valentina/Info.plist b/dist/macx/valentina/Info.plist
index 593fe35c4..d84c7d10c 100755
--- a/dist/macx/valentina/Info.plist
+++ b/dist/macx/valentina/Info.plist
@@ -160,7 +160,5 @@
- NSRequiresAquaSystemAppearance
-
diff --git a/scripts/generate_tool_cursor.sh b/scripts/generate_tool_cursor.sh
index 978b1f539..21bf4e33b 100755
--- a/scripts/generate_tool_cursor.sh
+++ b/scripts/generate_tool_cursor.sh
@@ -15,19 +15,31 @@
# I have spent hour before understand why i don't see PNG inside SVG in Nautilus.
PATTERN=*@2x.png
-TOOLICONPATH=../src/app/valentina/share/resources/toolicon/32x32/ # PNG tool icon should be here
-TOOLICONS=`ls $TOOLICONPATH$PATTERN`
-OUTPATH=../src/app/valentina/share/resources/cursor/svg # Seek SVG templates here
+TOOLICONPATH=../src/app/valentina/share/resources/toolicon/ # PNG tool icon should be here
+OUTPATH=../src/app/valentina/share/resources/cursor
+COLOR_SCHEMES=("light" "dark")
-for var in $TOOLICONS
+for scheme in "${COLOR_SCHEMES[@]}"
do
- basename=${var##*/} # remove the path from a path-string
- basename=${basename%.png} # remove the extension from a path-string
- basename=${basename%@2x} # remove optional @2x suffix
- if [ ! -f $basename@2x.png ]; then # always prefere hidpi version
- sed "s/<>/$basename@2x/" $OUTPATH/template_cursor.svg > $OUTPATH/${basename}_cursor.svg
- else
- sed "s/<>/$basename/" $OUTPATH/template_cursor.svg > $OUTPATH/${basename}_cursor.svg
- fi
+ # Create a subdirectory for the current scheme if it doesn't exist
+ mkdir -p "$OUTPATH/$scheme"
+
+ TOOLICONS=`ls $TOOLICONPATH${scheme}/$PATTERN`
+
+ for var in $TOOLICONS
+ do
+ basename=${var##*/} # remove the path from a path-string
+ basename=${basename%.png} # remove the extension from a path-string
+ basename=${basename%@2x} # remove optional @2x suffix
+ if [ ! -f $basename@2x.png ]; then # always prefere hidpi version
+ sed "s/<>/$basename@2x/" $OUTPATH/svg/template_cursor_${scheme}.svg > $OUTPATH/svg/${scheme}/${basename}_cursor.svg
+ else
+ sed "s/<>/$basename/" $OUTPATH/svg/template_cursor_${scheme}.svg > $OUTPATH/svg/${scheme}/${basename}_cursor.svg
+ fi
+
+ # Generate PNG files from the SVGs
+ inkscape --export-filename "$OUTPATH/$scheme/${basename}_cursor@2x.png" --export-width 64 --export-height 64 "$OUTPATH/svg/$scheme/${basename}_cursor.svg"
+ inkscape --export-filename "$OUTPATH/$scheme/${basename}_cursor.png" --export-width 32 --export-height 32 "$OUTPATH/svg/$scheme/${basename}_cursor.svg"
+ done
done
diff --git a/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.cpp b/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.cpp
index b29eb9034..eb112b885 100644
--- a/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.cpp
+++ b/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.cpp
@@ -34,6 +34,7 @@
#endif // QT_VERSION < QT_VERSION_CHECK(5, 7, 0)
#include "../vganalytics/vganalytics.h"
+#include "../vmisc/theme/vtheme.h"
//---------------------------------------------------------------------------------------------------------------------
PuzzlePreferencesConfigurationPage::PuzzlePreferencesConfigurationPage(QWidget *parent)
@@ -49,7 +50,12 @@ PuzzlePreferencesConfigurationPage::PuzzlePreferencesConfigurationPage(QWidget *
VPSettings *settings = VPApplication::VApp()->PuzzleSettings();
// Theme
- ui->darkModeCheck->setChecked(settings->GetDarkMode());
+ SetThemeModeComboBox();
+ int index = ui->comboBoxThemeMode->findData(static_cast(settings->GetThemeMode()));
+ if (index != -1)
+ {
+ ui->comboBoxThemeMode->setCurrentIndex(index);
+ }
// Native dialogs
ui->checkBoxDontUseNativeDialog->setChecked(settings->IsDontUseNativeDialog());
@@ -110,10 +116,11 @@ auto PuzzlePreferencesConfigurationPage::Apply() -> QStringList
settings->SetToolBarStyle(ui->toolBarStyleCheck->isChecked());
- if (settings->GetDarkMode() != ui->darkModeCheck->isChecked())
+ auto themeMode = static_cast(ui->comboBoxThemeMode->currentData().toInt());
+ if (settings->GetThemeMode() != themeMode)
{
- settings->SetDarkMode(ui->darkModeCheck->isChecked());
- preferences.append(tr("dark mode"));
+ settings->SetThemeMode(themeMode);
+ VTheme::Instance()->ResetThemeSettings();
}
if (settings->IsDontUseNativeDialog() != ui->checkBoxDontUseNativeDialog->isChecked())
@@ -190,3 +197,12 @@ void PuzzlePreferencesConfigurationPage::changeEvent(QEvent *event)
// remember to call base class implementation
QWidget::changeEvent(event);
}
+
+//---------------------------------------------------------------------------------------------------------------------
+void PuzzlePreferencesConfigurationPage::SetThemeModeComboBox()
+{
+ ui->comboBoxThemeMode->clear();
+ ui->comboBoxThemeMode->addItem(tr("System", "theme"), static_cast(VThemeMode::System));
+ ui->comboBoxThemeMode->addItem(tr("Dark", "theme"), static_cast(VThemeMode::Dark));
+ ui->comboBoxThemeMode->addItem(tr("Light", "theme"), static_cast(VThemeMode::Light));
+}
diff --git a/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.h b/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.h
index 64b5a8c7b..15fabd428 100644
--- a/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.h
+++ b/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.h
@@ -57,6 +57,8 @@ private:
Q_DISABLE_COPY_MOVE(PuzzlePreferencesConfigurationPage) // NOLINT
Ui::PuzzlePreferencesConfigurationPage *ui;
bool m_langChanged{false};
+
+ void SetThemeModeComboBox();
};
#endif // PUZZLEPREFERENCESCONFIGURATIONPAGE_H
diff --git a/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.ui b/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.ui
index f90d997a1..19fe06636 100644
--- a/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.ui
+++ b/src/app/puzzle/dialogs/configpages/puzzlepreferencesconfigurationpage.ui
@@ -46,7 +46,7 @@
- QFormLayout::ExpandingFieldsGrow
+ QFormLayout::AllNonFixedFieldsGrow
-
@@ -87,11 +87,24 @@
-
-
-
- Activate dark mode
-
-
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Theme:
+
+
+
+ -
+
+
+
-
@@ -237,8 +250,8 @@ This option will take an affect after restart.
0
0
- 503
- 627
+ 497
+ 633
@@ -249,7 +262,7 @@ This option will take an affect after restart.
- QFormLayout::ExpandingFieldsGrow
+ QFormLayout::AllNonFixedFieldsGrow
-
@@ -313,7 +326,7 @@ This option will take an affect after restart.
- QFormLayout::ExpandingFieldsGrow
+ QFormLayout::AllNonFixedFieldsGrow
-
@@ -377,7 +390,7 @@ This option will take an affect after restart.
- QFormLayout::ExpandingFieldsGrow
+ QFormLayout::AllNonFixedFieldsGrow
-
diff --git a/src/app/puzzle/dialogs/configpages/puzzlepreferenceslayoutpage.ui b/src/app/puzzle/dialogs/configpages/puzzlepreferenceslayoutpage.ui
index f70b15e50..659be6fb9 100644
--- a/src/app/puzzle/dialogs/configpages/puzzlepreferenceslayoutpage.ui
+++ b/src/app/puzzle/dialogs/configpages/puzzlepreferenceslayoutpage.ui
@@ -43,7 +43,7 @@
-
- QFormLayout::ExpandingFieldsGrow
+ QFormLayout::AllNonFixedFieldsGrow
-
@@ -327,6 +327,12 @@
-
+
+
+ 0
+ 0
+
+
Pieces gap
@@ -341,6 +347,12 @@
-
+
+
+ 0
+ 0
+
+
Line width:
@@ -429,7 +441,7 @@
-
- QFormLayout::ExpandingFieldsGrow
+ QFormLayout::AllNonFixedFieldsGrow
-
diff --git a/src/app/puzzle/dialogs/dialogpuzzlepreferences.cpp b/src/app/puzzle/dialogs/dialogpuzzlepreferences.cpp
index 09928fcec..c434c7501 100644
--- a/src/app/puzzle/dialogs/dialogpuzzlepreferences.cpp
+++ b/src/app/puzzle/dialogs/dialogpuzzlepreferences.cpp
@@ -27,19 +27,19 @@
*************************************************************************/
#include "dialogpuzzlepreferences.h"
-#include "ui_dialogpuzzlepreferences.h"
#include "../vpapplication.h"
#include "configpages/puzzlepreferencesconfigurationpage.h"
-#include "configpages/puzzlepreferencespathpage.h"
#include "configpages/puzzlepreferenceslayoutpage.h"
+#include "configpages/puzzlepreferencespathpage.h"
+#include "ui_dialogpuzzlepreferences.h"
#include
#include
#include
//---------------------------------------------------------------------------------------------------------------------
-DialogPuzzlePreferences::DialogPuzzlePreferences(QWidget *parent) :
- QDialog(parent),
+DialogPuzzlePreferences::DialogPuzzlePreferences(QWidget *parent)
+ : QDialog(parent),
ui(new Ui::DialogPuzzlePreferences),
m_configurationPage(new PuzzlePreferencesConfigurationPage),
m_layoutPage(new PuzzlePreferencesLayoutPage),
@@ -78,8 +78,8 @@ DialogPuzzlePreferences::~DialogPuzzlePreferences()
//---------------------------------------------------------------------------------------------------------------------
void DialogPuzzlePreferences::showEvent(QShowEvent *event)
{
- QDialog::showEvent( event );
- if ( event->spontaneous() )
+ QDialog::showEvent(event);
+ if (event->spontaneous())
{
return;
}
@@ -96,7 +96,7 @@ void DialogPuzzlePreferences::showEvent(QShowEvent *event)
resize(sz);
}
- m_isInitialized = true;//first show windows are held
+ m_isInitialized = true; // first show windows are held
}
//---------------------------------------------------------------------------------------------------------------------
@@ -120,6 +120,24 @@ void DialogPuzzlePreferences::changeEvent(QEvent *event)
// retranslate designer form (single inheritance approach)
ui->retranslateUi(this);
}
+
+ if (event->type() == QEvent::PaletteChange)
+ {
+ QStyle *style = QApplication::style();
+
+ QPushButton *bOk = ui->buttonBox->button(QDialogButtonBox::Ok);
+ SCASSERT(bOk != nullptr)
+ bOk->setIcon(style->standardIcon(QStyle::SP_DialogOkButton));
+
+ QPushButton *bApply = ui->buttonBox->button(QDialogButtonBox::Apply);
+ SCASSERT(bApply != nullptr)
+ bApply->setIcon(style->standardIcon(QStyle::SP_DialogApplyButton));
+
+ QPushButton *bCancel = ui->buttonBox->button(QDialogButtonBox::Cancel);
+ SCASSERT(bCancel != nullptr)
+ bCancel->setIcon(style->standardIcon(QStyle::SP_DialogCancelButton));
+ }
+
// remember to call base class implementation
QDialog::changeEvent(event);
}
@@ -135,8 +153,9 @@ void DialogPuzzlePreferences::Apply()
if (not preferences.isEmpty())
{
- const QString text = tr("Followed %n option(s) require restart to take effect: %1.", "",
- static_cast(preferences.size())).arg(preferences.join(QStringLiteral(", ")));
+ const QString text =
+ tr("Followed %n option(s) require restart to take effect: %1.", "", static_cast(preferences.size()))
+ .arg(preferences.join(QStringLiteral(", ")));
QMessageBox::information(this, QCoreApplication::applicationName(), text);
}
diff --git a/src/app/puzzle/main.cpp b/src/app/puzzle/main.cpp
index 9b6d3028c..31e4a2525 100644
--- a/src/app/puzzle/main.cpp
+++ b/src/app/puzzle/main.cpp
@@ -29,16 +29,16 @@
#include // For QT_REQUIRE_VERSION
#include
-#include "vpapplication.h"
#include "../vmisc/def.h"
+#include "vpapplication.h"
#if defined(APPIMAGE) && defined(Q_OS_LINUX)
#if QT_VERSION < QT_VERSION_CHECK(5, 12, 0)
-# include "../vmisc/backport/qscopeguard.h"
+#include "../vmisc/backport/qscopeguard.h"
#else
-# include
+#include
#endif
-# include "../vmisc/appimage.h"
+#include "../vmisc/appimage.h"
#endif // defined(APPIMAGE) && defined(Q_OS_LINUX)
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
@@ -50,18 +50,22 @@ auto main(int argc, char *argv[]) -> int
#if defined(APPIMAGE) && defined(Q_OS_LINUX)
/* Fix path to ICU_DATA when run AppImage.*/
char *exe_dir = IcuDataPath("/../share/icu");
- auto FreeMemory = qScopeGuard([exe_dir] {free(exe_dir);});
+ auto FreeMemory = qScopeGuard([exe_dir] { free(exe_dir); });
#endif // defined(APPIMAGE) && defined(Q_OS_LINUX)
Q_INIT_RESOURCE(puzzleicon); // NOLINT
- Q_INIT_RESOURCE(theme); // NOLINT
- Q_INIT_RESOURCE(icon); // NOLINT
- Q_INIT_RESOURCE(schema); // NOLINT
- Q_INIT_RESOURCE(flags); // NOLINT
- Q_INIT_RESOURCE(style); // NOLINT
- Q_INIT_RESOURCE(cursor); // NOLINT
+ Q_INIT_RESOURCE(icon); // NOLINT
+ Q_INIT_RESOURCE(schema); // NOLINT
+ Q_INIT_RESOURCE(flags); // NOLINT
+ Q_INIT_RESOURCE(breeze); // NOLINT
+ Q_INIT_RESOURCE(cursor); // NOLINT
+#if defined(Q_OS_MACX)
+ Q_INIT_RESOURCE(mac_theme); // NOLINT
+#else
+ Q_INIT_RESOURCE(win_theme); // NOLINT
+#endif
- QT_REQUIRE_VERSION(argc, argv, "5.4.0")// clazy:exclude=qstring-arg,qstring-allocations NOLINT
+ QT_REQUIRE_VERSION(argc, argv, "5.4.0") // clazy:exclude=qstring-arg,qstring-allocations NOLINT
#if defined(Q_OS_WIN)
VAbstractApplication::WinAttachConsole();
@@ -69,9 +73,9 @@ auto main(int argc, char *argv[]) -> int
#ifndef Q_OS_MAC // supports natively
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- InitHighDpiScaling(argc, argv);
+ VAbstractApplication::InitHighDpiScaling(argc, argv);
#endif
-#endif //ndef Q_OS_MAC
+#endif // ndef Q_OS_MAC
#ifdef Q_OS_MAC
#if MACOS_LAYER_BACKING_AFFECTED
@@ -82,7 +86,7 @@ auto main(int argc, char *argv[]) -> int
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
XERCES_CPP_NAMESPACE::XMLPlatformUtils::Initialize();
- auto Terminate = qScopeGuard([](){ XERCES_CPP_NAMESPACE::XMLPlatformUtils::Terminate(); });
+ auto Terminate = qScopeGuard([]() { XERCES_CPP_NAMESPACE::XMLPlatformUtils::Terminate(); });
#endif
VPApplication app(argc, argv);
diff --git a/src/app/puzzle/vpapplication.cpp b/src/app/puzzle/vpapplication.cpp
index 52796e45a..cb1dbec28 100644
--- a/src/app/puzzle/vpapplication.cpp
+++ b/src/app/puzzle/vpapplication.cpp
@@ -27,6 +27,7 @@
*************************************************************************/
#include "vpapplication.h"
+#include "../fervor/fvupdater.h"
#include "../ifc/exception/vexceptionbadid.h"
#include "../ifc/exception/vexceptionconversionerror.h"
#include "../ifc/exception/vexceptionemptyparameter.h"
@@ -34,6 +35,9 @@
#include "../ifc/exception/vexceptionwrongid.h"
#include "../vganalytics/def.h"
#include "../vganalytics/vganalytics.h"
+#include "../vmisc/qt_dispatch/qt_dispatch.h"
+#include "../vmisc/theme/vapplicationstyle.h"
+#include "../vmisc/theme/vtheme.h"
#include "../vmisc/vsysexits.h"
#include "version.h"
#include "vpmainwindow.h"
@@ -42,11 +46,14 @@
#include "../vmisc/diagnostic.h"
#endif // QT_VERSION < QT_VERSION_CHECK(5, 5, 0)
-#include "../fervor/fvupdater.h"
-#include "../vmisc/qt_dispatch/qt_dispatch.h"
-
+#include
+#include
+#include
+#include
#include
#include
+#include
+#include
QT_WARNING_PUSH
QT_WARNING_DISABLE_CLANG("-Wmissing-prototypes")
@@ -56,12 +63,6 @@ Q_LOGGING_CATEGORY(pApp, "p.application") // NOLINT
QT_WARNING_POP
-#include
-#include
-#include
-#include
-#include
-
#if !defined(BUILD_REVISION) && defined(QBS_BUILD)
#include
#define BUILD_REVISION VCS_REPO_STATE_REVISION
@@ -274,12 +275,13 @@ VPApplication::VPApplication(int &argc, char **argv)
// The first inside own bundle where info.plist is works fine, but the second,
// when we run inside Valentina's bundle, require direct setting the icon.
setWindowIcon(QIcon(":/puzzleicon/64x64/logo.png"));
+ VTheme::Instance()->StoreDefaultThemeName(QIcon::themeName());
}
//---------------------------------------------------------------------------------------------------------------------
VPApplication::~VPApplication()
{
- if (IsAppInGUIMode() && settings->IsCollectStatistic())
+ if (VPApplication::IsAppInGUIMode() && settings->IsCollectStatistic())
{
auto *statistic = VGAnalytics::Instance();
@@ -433,16 +435,8 @@ void VPApplication::InitOptions()
CheckSystemLocale();
- static const char *GENERIC_ICON_TO_CHECK = "document-open";
- if (not QIcon::hasThemeIcon(GENERIC_ICON_TO_CHECK))
- {
- // If there is no default working icon theme then we should
- // use an icon theme that we provide via a .qrc file
- // This case happens under Windows and Mac OS X
- // This does not happen under GNOME or KDE
- QIcon::setThemeName(QStringLiteral("win.icon.theme"));
- }
- ActivateDarkMode();
+ VTheme::SetIconTheme();
+ VTheme::InitThemeMode();
auto *statistic = VGAnalytics::Instance();
QString clientID = settings->GetClientID();
@@ -480,26 +474,6 @@ auto VPApplication::PuzzleSettings() -> VPSettings *
return qobject_cast(settings);
}
-//---------------------------------------------------------------------------------------------------------------------
-void VPApplication::ActivateDarkMode()
-{
- VPSettings *settings = PuzzleSettings();
- if (settings->GetDarkMode())
- {
- QFile f(QStringLiteral(":qdarkstyle/style.qss"));
- if (!f.exists())
- {
- qDebug() << "Unable to set stylesheet, file not found\n";
- }
- else
- {
- f.open(QFile::ReadOnly | QFile::Text);
- QTextStream ts(&f);
- VPApplication::VApp()->setStyleSheet(ts.readAll());
- }
- }
-}
-
//---------------------------------------------------------------------------------------------------------------------
void VPApplication::ParseCommandLine(const SocketConnection &connection, const QStringList &arguments)
{
@@ -525,6 +499,17 @@ void VPApplication::ParseCommandLine(const SocketConnection &connection, const Q
qCDebug(pApp, "Can't establish connection to the server '%s'", qUtf8Printable(serverName));
StartLocalServer(serverName);
LoadTranslation(PuzzleSettings()->GetLocale());
+
+ QString styleOpt = cmd->OptionStyle();
+ if (styleOpt != QLatin1String("native"))
+ {
+ QStyle *style = QStyleFactory::create(styleOpt);
+ if (style != nullptr)
+ {
+ style = new VApplicationStyle(style);
+ setStyle(style);
+ }
+ }
}
ProcessArguments(cmd);
diff --git a/src/app/puzzle/vpapplication.h b/src/app/puzzle/vpapplication.h
index a079811cc..92c8b5164 100644
--- a/src/app/puzzle/vpapplication.h
+++ b/src/app/puzzle/vpapplication.h
@@ -29,29 +29,34 @@
#define VPAPPLICATION_H
#include "../vmisc/def.h"
-#include "vpsettings.h"
#include "../vmisc/vabstractapplication.h"
#include "vpcommandline.h"
+#include "vpsettings.h"
template class QWeakPointer;
class VPMainWindow;
class QLocalServer;
class DialogPuzzlePreferences;
-enum class SocketConnection : bool {Client = false, Server = true};
+enum class SocketConnection : bool
+{
+ Client = false,
+ Server = true
+};
class VPApplication : public VAbstractApplication
{
Q_OBJECT // NOLINT
+
public:
VPApplication(int &argc, char **argv);
~VPApplication() override;
- auto notify(QObject * receiver, QEvent * event) -> bool override;
+ auto notify(QObject *receiver, QEvent *event) -> bool override;
auto IsAppInGUIMode() const -> bool override;
auto MainWindow() -> VPMainWindow *;
- auto MainWindows() -> QList;
+ auto MainWindows() -> QList;
auto NewMainWindow() -> VPMainWindow *;
auto NewMainWindow(const VPCommandLinePtr &cmd) -> VPMainWindow *;
@@ -61,7 +66,6 @@ public:
void OpenSettings() override;
auto PuzzleSettings() -> VPSettings *;
- void ActivateDarkMode();
void ParseCommandLine(const SocketConnection &connection, const QStringList &arguments);
void ProcessArguments(const VPCommandLinePtr &cmd);
@@ -87,8 +91,8 @@ private slots:
private:
// cppcheck-suppress unknownMacro
- Q_DISABLE_COPY_MOVE(VPApplication) //NOLINT
- QList > m_mainWindows{};
+ Q_DISABLE_COPY_MOVE(VPApplication) // NOLINT
+ QList> m_mainWindows{};
QLocalServer *m_localServer{nullptr};
QWeakPointer m_preferencesDialog{};
diff --git a/src/app/puzzle/vpcommandline.cpp b/src/app/puzzle/vpcommandline.cpp
index b46769519..c8d4360eb 100644
--- a/src/app/puzzle/vpcommandline.cpp
+++ b/src/app/puzzle/vpcommandline.cpp
@@ -26,14 +26,16 @@
**
*************************************************************************/
#include "vpcommandline.h"
-#include "vpcommands.h"
-#include "../vmisc/vsysexits.h"
#include "../vmisc/literals.h"
+#include "../vmisc/vsysexits.h"
+#include "vpcommands.h"
#include
-std::shared_ptr VPCommandLine::instance = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
+std::shared_ptr VPCommandLine::instance =
+ nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
-#define translate(context, source) QCoreApplication::translate((context), source)// NOLINT(cppcoreguidelines-macro-usage)
+#define translate(context, source) \
+ QCoreApplication::translate((context), source) // NOLINT(cppcoreguidelines-macro-usage)
//---------------------------------------------------------------------------------------------------------------------
auto VPCommandLine::OptionRawLayouts() const -> QStringList
@@ -65,7 +67,19 @@ void VPCommandLine::ShowHelp(int exitCode)
parser.showHelp(exitCode);
}
-//----------------------------------------------------------------------------------------------
+//----------------------------------------------------------------------------------------------------------------------
+auto VPCommandLine::OptionStyle() const -> QString
+{
+ QString value = OptionValue(LONG_OPTION_STYLE);
+ if (value.isEmpty())
+ {
+ return QStringLiteral("native");
+ }
+
+ return value;
+}
+
+//----------------------------------------------------------------------------------------------------------------------
VPCommandLine::VPCommandLine()
{
parser.setApplicationDescription(translate("Puzzle", "Valentina's manual layout editor."));
@@ -96,7 +110,7 @@ void VPCommandLine::ProcessInstance(VPCommandLinePtr &instance, const QStringLis
//-------------------------------------------------------------------------------------------
void VPCommandLine::InitCommandLineOptions()
{
- //keep in mind order here - that is how user will see it, so group-up for usability
+ // keep in mind order here - that is how user will see it, so group-up for usability
//=================================================================================================================
parser.addOptions({
{{SINGLE_OPTION_RAW_LAYOUT, LONG_OPTION_RAW_LAYOUT},
@@ -106,6 +120,7 @@ void VPCommandLine::InitCommandLineOptions()
translate("VCommandLine", "Disable high dpi scaling. Call this option if has problem with scaling (by default "
"scaling enabled). Alternatively you can use the %1 environment variable.")
.arg(QStringLiteral("QT_AUTO_SCREEN_SCALE_FACTOR=0"))},
+ {LONG_OPTION_STYLE, tr("Application style") + QString(" `Fusion`, `Windows`, `native`, ..."), "", "native"},
});
}
@@ -126,5 +141,3 @@ auto VPCommandLine::OptionValues(const QString &option) const -> QStringList
{
return parser.values(option);
}
-
-
diff --git a/src/app/puzzle/vpcommandline.h b/src/app/puzzle/vpcommandline.h
index 4191f9d90..6185492a9 100644
--- a/src/app/puzzle/vpcommandline.h
+++ b/src/app/puzzle/vpcommandline.h
@@ -65,6 +65,8 @@ public:
Q_NORETURN void ShowHelp(int exitCode = 0);
+ auto OptionStyle() const -> QString;
+
protected:
VPCommandLine();
diff --git a/src/app/puzzle/vpcommands.cpp b/src/app/puzzle/vpcommands.cpp
index 8d1759905..06530b629 100644
--- a/src/app/puzzle/vpcommands.cpp
+++ b/src/app/puzzle/vpcommands.cpp
@@ -29,8 +29,9 @@
#include
-const QString LONG_OPTION_RAW_LAYOUT = QStringLiteral("rawLayout"); // NOLINT
-const QString SINGLE_OPTION_RAW_LAYOUT = QStringLiteral("r"); // NOLINT
+const QString LONG_OPTION_RAW_LAYOUT = QStringLiteral("rawLayout"); // NOLINT
+const QString SINGLE_OPTION_RAW_LAYOUT = QStringLiteral("r"); // NOLINT
+const QString LONG_OPTION_STYLE = QStringLiteral("style"); // NOLINT
//---------------------------------------------------------------------------------------------------------------------
/**
@@ -39,9 +40,5 @@ const QString SINGLE_OPTION_RAW_LAYOUT = QStringLiteral("r"); // NOLINT
*/
auto AllKeys() -> QStringList
{
- return
- {
- LONG_OPTION_RAW_LAYOUT,
- SINGLE_OPTION_RAW_LAYOUT
- };
+ return {LONG_OPTION_RAW_LAYOUT, SINGLE_OPTION_RAW_LAYOUT, LONG_OPTION_STYLE};
}
diff --git a/src/app/puzzle/vpcommands.h b/src/app/puzzle/vpcommands.h
index adbacf7ff..2d43208e6 100644
--- a/src/app/puzzle/vpcommands.h
+++ b/src/app/puzzle/vpcommands.h
@@ -28,12 +28,14 @@
#ifndef VPCOMMANDS_H
#define VPCOMMANDS_H
-
#include
extern const QString LONG_OPTION_RAW_LAYOUT;
extern const QString SINGLE_OPTION_RAW_LAYOUT;
+extern const QString LONG_OPTION_STYLE;
+extern const QString LONG_OPTION_STYLESHEET;
+
auto AllKeys() -> QStringList;
#endif // VPCOMMANDS_H
diff --git a/src/app/tape/dialogs/configpages/tapepreferencesconfigurationpage.cpp b/src/app/tape/dialogs/configpages/tapepreferencesconfigurationpage.cpp
index bf73d574b..f15340bca 100644
--- a/src/app/tape/dialogs/configpages/tapepreferencesconfigurationpage.cpp
+++ b/src/app/tape/dialogs/configpages/tapepreferencesconfigurationpage.cpp
@@ -36,6 +36,7 @@
#endif // QT_VERSION < QT_VERSION_CHECK(5, 7, 0)
#include "../qmuparser/qmudef.h"
#include "../vganalytics/vganalytics.h"
+#include "../vmisc/theme/vtheme.h"
//---------------------------------------------------------------------------------------------------------------------
TapePreferencesConfigurationPage::TapePreferencesConfigurationPage(QWidget *parent)
@@ -57,7 +58,12 @@ TapePreferencesConfigurationPage::TapePreferencesConfigurationPage(QWidget *pare
ui->osOptionCheck->setChecked(settings->GetOsSeparator());
// Theme
- ui->darkModeCheck->setChecked(settings->GetDarkMode());
+ SetThemeModeComboBox();
+ int index = ui->comboBoxThemeMode->findData(static_cast(settings->GetThemeMode()));
+ if (index != -1)
+ {
+ ui->comboBoxThemeMode->setCurrentIndex(index);
+ }
// Native dialogs
ui->checkBoxDontUseNativeDialog->setChecked(settings->IsDontUseNativeDialog());
@@ -78,7 +84,7 @@ TapePreferencesConfigurationPage::TapePreferencesConfigurationPage(QWidget *pare
});
// set default pattern making system
- int index = ui->systemCombo->findData(settings->GetPMSystemCode());
+ index = ui->systemCombo->findData(settings->GetPMSystemCode());
if (index != -1)
{
ui->systemCombo->setCurrentIndex(index);
@@ -113,10 +119,11 @@ auto TapePreferencesConfigurationPage::Apply() -> QStringList
settings->SetToolBarStyle(ui->toolBarStyleCheck->isChecked());
- if (settings->GetDarkMode() != ui->darkModeCheck->isChecked())
+ auto themeMode = static_cast(ui->comboBoxThemeMode->currentData().toInt());
+ if (settings->GetThemeMode() != themeMode)
{
- settings->SetDarkMode(ui->darkModeCheck->isChecked());
- preferences.append(tr("dark mode"));
+ settings->SetThemeMode(themeMode);
+ VTheme::Instance()->ResetThemeSettings();
}
if (settings->IsDontUseNativeDialog() != ui->checkBoxDontUseNativeDialog->isChecked())
@@ -183,3 +190,12 @@ void TapePreferencesConfigurationPage::RetranslateUi()
ui->systemCombo->setCurrentIndex(ui->systemCombo->findData(code));
}
}
+
+//---------------------------------------------------------------------------------------------------------------------
+void TapePreferencesConfigurationPage::SetThemeModeComboBox()
+{
+ ui->comboBoxThemeMode->clear();
+ ui->comboBoxThemeMode->addItem(tr("System", "theme"), static_cast(VThemeMode::System));
+ ui->comboBoxThemeMode->addItem(tr("Dark", "theme"), static_cast(VThemeMode::Dark));
+ ui->comboBoxThemeMode->addItem(tr("Light", "theme"), static_cast(VThemeMode::Light));
+}
diff --git a/src/app/tape/dialogs/configpages/tapepreferencesconfigurationpage.h b/src/app/tape/dialogs/configpages/tapepreferencesconfigurationpage.h
index afb46f610..606c8f6f3 100644
--- a/src/app/tape/dialogs/configpages/tapepreferencesconfigurationpage.h
+++ b/src/app/tape/dialogs/configpages/tapepreferencesconfigurationpage.h
@@ -31,6 +31,10 @@
#include
+#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
+#include "../vmisc/defglobal.h"
+#endif
+
namespace Ui
{
class TapePreferencesConfigurationPage;
@@ -57,6 +61,7 @@ private:
bool m_systemChanged;
void RetranslateUi();
+ void SetThemeModeComboBox();
};
#endif // TAPEPREFERENCESCONFIGURATIONPAGE_H
diff --git a/src/app/tape/dialogs/configpages/tapepreferencesconfigurationpage.ui b/src/app/tape/dialogs/configpages/tapepreferencesconfigurationpage.ui
index 272d598d6..5f063158a 100644
--- a/src/app/tape/dialogs/configpages/tapepreferencesconfigurationpage.ui
+++ b/src/app/tape/dialogs/configpages/tapepreferencesconfigurationpage.ui
@@ -46,7 +46,7 @@
- QFormLayout::ExpandingFieldsGrow
+ QFormLayout::AllNonFixedFieldsGrow
-
@@ -85,7 +85,7 @@
- QFormLayout::ExpandingFieldsGrow
+ QFormLayout::AllNonFixedFieldsGrow
-
@@ -182,11 +182,24 @@
-
-
-
- Activate dark mode
-
-
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Theme:
+
+
+
+ -
+
+
+
-
diff --git a/src/app/tape/dialogs/configpages/tapepreferencespathpage.h b/src/app/tape/dialogs/configpages/tapepreferencespathpage.h
index 6e47c8fce..9c79e917e 100644
--- a/src/app/tape/dialogs/configpages/tapepreferencespathpage.h
+++ b/src/app/tape/dialogs/configpages/tapepreferencespathpage.h
@@ -31,6 +31,10 @@
#include
+#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
+#include "../vmisc/defglobal.h"
+#endif
+
namespace Ui
{
class TapePreferencesPathPage;
diff --git a/src/app/tape/dialogs/dialogtapepreferences.cpp b/src/app/tape/dialogs/dialogtapepreferences.cpp
index e08a7d3de..dcbdc14ed 100644
--- a/src/app/tape/dialogs/dialogtapepreferences.cpp
+++ b/src/app/tape/dialogs/dialogtapepreferences.cpp
@@ -27,10 +27,10 @@
*************************************************************************/
#include "dialogtapepreferences.h"
-#include "ui_dialogtapepreferences.h"
#include "../mapplication.h"
#include "configpages/tapepreferencesconfigurationpage.h"
#include "configpages/tapepreferencespathpage.h"
+#include "ui_dialogtapepreferences.h"
#include
#include
@@ -38,10 +38,10 @@
//---------------------------------------------------------------------------------------------------------------------
DialogTapePreferences::DialogTapePreferences(QWidget *parent)
- :QDialog(parent),
- ui(new Ui::DialogTapePreferences),
- m_configurationPage(new TapePreferencesConfigurationPage),
- m_pathPage(new TapePreferencesPathPage)
+ : QDialog(parent),
+ ui(new Ui::DialogTapePreferences),
+ m_configurationPage(new TapePreferencesConfigurationPage),
+ m_pathPage(new TapePreferencesPathPage)
{
ui->setupUi(this);
@@ -75,8 +75,8 @@ DialogTapePreferences::~DialogTapePreferences()
//---------------------------------------------------------------------------------------------------------------------
void DialogTapePreferences::showEvent(QShowEvent *event)
{
- QDialog::showEvent( event );
- if ( event->spontaneous() )
+ QDialog::showEvent(event);
+ if (event->spontaneous())
{
return;
}
@@ -93,7 +93,7 @@ void DialogTapePreferences::showEvent(QShowEvent *event)
resize(sz);
}
- m_isInitialized = true;//first show windows are held
+ m_isInitialized = true; // first show windows are held
}
//---------------------------------------------------------------------------------------------------------------------
@@ -117,6 +117,24 @@ void DialogTapePreferences::changeEvent(QEvent *event)
// retranslate designer form (single inheritance approach)
ui->retranslateUi(this);
}
+
+ if (event->type() == QEvent::PaletteChange)
+ {
+ QStyle *style = QApplication::style();
+
+ QPushButton *bOk = ui->buttonBox->button(QDialogButtonBox::Ok);
+ SCASSERT(bOk != nullptr)
+ bOk->setIcon(style->standardIcon(QStyle::SP_DialogOkButton));
+
+ QPushButton *bApply = ui->buttonBox->button(QDialogButtonBox::Apply);
+ SCASSERT(bApply != nullptr)
+ bApply->setIcon(style->standardIcon(QStyle::SP_DialogApplyButton));
+
+ QPushButton *bCancel = ui->buttonBox->button(QDialogButtonBox::Cancel);
+ SCASSERT(bCancel != nullptr)
+ bCancel->setIcon(style->standardIcon(QStyle::SP_DialogCancelButton));
+ }
+
// remember to call base class implementation
QDialog::changeEvent(event);
}
@@ -131,8 +149,9 @@ void DialogTapePreferences::Apply()
if (not preferences.isEmpty())
{
- const QString text = tr("Followed %n option(s) require restart to take effect: %1.", "",
- static_cast(preferences.size())).arg(preferences.join(QStringLiteral(", ")));
+ const QString text =
+ tr("Followed %n option(s) require restart to take effect: %1.", "", static_cast(preferences.size()))
+ .arg(preferences.join(QStringLiteral(", ")));
QMessageBox::information(this, QCoreApplication::applicationName(), text);
}
diff --git a/src/app/tape/main.cpp b/src/app/tape/main.cpp
index ea0fe9adf..967ce3893 100644
--- a/src/app/tape/main.cpp
+++ b/src/app/tape/main.cpp
@@ -33,11 +33,11 @@
#if defined(APPIMAGE) && defined(Q_OS_LINUX)
#if QT_VERSION < QT_VERSION_CHECK(5, 12, 0)
-# include "../vmisc/backport/qscopeguard.h"
+#include "../vmisc/backport/qscopeguard.h"
#else
-# include
+#include
#endif
-# include "../vmisc/appimage.h"
+#include "../vmisc/appimage.h"
#endif // defined(APPIMAGE) && defined(Q_OS_LINUX)
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
@@ -49,17 +49,21 @@ auto main(int argc, char *argv[]) -> int
#if defined(APPIMAGE) && defined(Q_OS_LINUX)
/* Fix path to ICU_DATA when run AppImage.*/
char *exe_dir = IcuDataPath("/../share/icu");
- auto FreeMemory = qScopeGuard([exe_dir] {free(exe_dir);});
+ auto FreeMemory = qScopeGuard([exe_dir] { free(exe_dir); });
#endif // defined(APPIMAGE) && defined(Q_OS_LINUX)
Q_INIT_RESOURCE(tapeicon); // NOLINT
- Q_INIT_RESOURCE(theme); // NOLINT
- Q_INIT_RESOURCE(icon); // NOLINT
- Q_INIT_RESOURCE(schema); // NOLINT
- Q_INIT_RESOURCE(flags); // NOLINT
- Q_INIT_RESOURCE(style); // NOLINT
+ Q_INIT_RESOURCE(icon); // NOLINT
+ Q_INIT_RESOURCE(schema); // NOLINT
+ Q_INIT_RESOURCE(flags); // NOLINT
+ Q_INIT_RESOURCE(breeze); // NOLINT
+#if defined(Q_OS_MACX)
+ Q_INIT_RESOURCE(mac_theme); // NOLINT
+#else
+ Q_INIT_RESOURCE(win_theme); // NOLINT
+#endif
- QT_REQUIRE_VERSION(argc, argv, "5.4.0")// clazy:exclude=qstring-arg,qstring-allocations NOLINT
+ QT_REQUIRE_VERSION(argc, argv, "5.4.0") // clazy:exclude=qstring-arg,qstring-allocations NOLINT
#if defined(Q_OS_WIN)
VAbstractApplication::WinAttachConsole();
@@ -68,14 +72,14 @@ auto main(int argc, char *argv[]) -> int
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
XERCES_CPP_NAMESPACE::XMLPlatformUtils::Initialize();
- auto Terminate = qScopeGuard([](){ XERCES_CPP_NAMESPACE::XMLPlatformUtils::Terminate(); });
+ auto Terminate = qScopeGuard([]() { XERCES_CPP_NAMESPACE::XMLPlatformUtils::Terminate(); });
#endif
#ifndef Q_OS_MAC // supports natively
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- InitHighDpiScaling(argc, argv);
+ VAbstractApplication::InitHighDpiScaling(argc, argv);
#endif
-#endif //Q_OS_MAC
+#endif // Q_OS_MAC
#ifdef Q_OS_MAC
#if MACOS_LAYER_BACKING_AFFECTED
diff --git a/src/app/tape/mapplication.cpp b/src/app/tape/mapplication.cpp
index 486847138..31cd39a01 100644
--- a/src/app/tape/mapplication.cpp
+++ b/src/app/tape/mapplication.cpp
@@ -35,6 +35,8 @@
#include "../vganalytics/def.h"
#include "../vganalytics/vganalytics.h"
#include "../vmisc/projectversion.h"
+#include "../vmisc/theme/vapplicationstyle.h"
+#include "../vmisc/theme/vtheme.h"
#include "../vmisc/vsysexits.h"
#include "tmainwindow.h"
#include "version.h"
@@ -57,6 +59,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -100,6 +103,8 @@ Q_GLOBAL_STATIC_WITH_ARGS(const QString, SINGLE_OPTION_UNITS, (QChar('u')))
Q_GLOBAL_STATIC_WITH_ARGS(const QString, LONG_OPTION_TEST, (QLatin1String("test"))) // NOLINT
+Q_GLOBAL_STATIC_WITH_ARGS(const QString, LONG_OPTION_STYLE, (QLatin1String("style"))) // NOLINT
+
QT_WARNING_POP
} // namespace
@@ -316,6 +321,7 @@ MApplication::MApplication(int &argc, char **argv)
// The first inside own bundle where info.plist is works fine, but the second,
// when we run inside Valentina's bundle, require direct setting the icon.
setWindowIcon(QIcon(":/tapeicon/64x64/logo.png"));
+ VTheme::Instance()->StoreDefaultThemeName(QIcon::themeName());
}
//---------------------------------------------------------------------------------------------------------------------
@@ -476,16 +482,9 @@ void MApplication::InitOptions()
CheckSystemLocale();
- static const char *GENERIC_ICON_TO_CHECK = "document-open";
- if (not QIcon::hasThemeIcon(GENERIC_ICON_TO_CHECK))
- {
- // If there is no default working icon theme then we should
- // use an icon theme that we provide via a .qrc file
- // This case happens under Windows and Mac OS X
- // This does not happen under GNOME or KDE
- QIcon::setThemeName(QStringLiteral("win.icon.theme"));
- }
- ActivateDarkMode();
+ VTheme::SetIconTheme();
+ VTheme::InitThemeMode();
+
QResource::registerResource(diagramsPath());
auto *statistic = VGAnalytics::Instance();
@@ -503,27 +502,6 @@ void MApplication::InitOptions()
statistic->Enable(settings->IsCollectStatistic());
}
-//---------------------------------------------------------------------------------------------------------------------
-// Dark mode
-void MApplication::ActivateDarkMode()
-{
- VTapeSettings *settings = TapeSettings();
- if (settings->GetDarkMode())
- {
- QFile f(QStringLiteral(":qdarkstyle/style.qss"));
- if (!f.exists())
- {
- qDebug() << "Unable to set stylesheet, file not found\n";
- }
- else
- {
- f.open(QFile::ReadOnly | QFile::Text);
- QTextStream ts(&f);
- qApp->setStyleSheet(ts.readAll()); // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast)
- }
- }
-}
-
//---------------------------------------------------------------------------------------------------------------------
void MApplication::InitTrVars()
{
@@ -710,6 +688,22 @@ void MApplication::ParseCommandLine(const SocketConnection &connection, const QS
qCDebug(mApp, "Can't establish connection to the server '%s'", qUtf8Printable(serverName));
StartLocalServer(serverName);
LoadTranslation(TapeSettings()->GetLocale());
+
+ QString styleOpt = parser.value(*LONG_OPTION_STYLE);
+ if (styleOpt.isEmpty())
+ {
+ styleOpt = QLatin1String("native");
+ }
+
+ if (styleOpt != QLatin1String("native"))
+ {
+ QStyle *style = QStyleFactory::create(styleOpt);
+ if (style != nullptr)
+ {
+ style = new VApplicationStyle(style);
+ setStyle(style);
+ }
+ }
}
const QStringList args = parser.positionalArguments();
@@ -822,6 +816,7 @@ void MApplication::InitParserOptions(QCommandLineParser &parser)
tr("Disable high dpi scaling. Call this option if has problem with scaling (by default scaling enabled). "
"Alternatively you can use the %1 environment variable.")
.arg("QT_AUTO_SCREEN_SCALE_FACTOR=0")},
+ {*LONG_OPTION_STYLE, tr("Application style") + QString(" `Fusion`, `Windows`, `native`, ..."), "", "native"},
});
}
diff --git a/src/app/tape/mapplication.h b/src/app/tape/mapplication.h
index 51a0a6b70..b4a8796b6 100644
--- a/src/app/tape/mapplication.h
+++ b/src/app/tape/mapplication.h
@@ -29,16 +29,20 @@
#ifndef MAPPLICATION_H
#define MAPPLICATION_H
-#include "../vpatterndb/vtranslatevars.h"
-#include "vtapesettings.h"
#include "../vmisc/vabstractapplication.h"
+#include "../vpatterndb/vtranslatevars.h"
#include "dialogs/dialogmdatabase.h"
+#include "vtapesettings.h"
class TMainWindow;
class QLocalServer;
class QCommandLineParser;
-enum class SocketConnection : bool {Client = false, Server = true};
+enum class SocketConnection : bool
+{
+ Client = false,
+ Server = true
+};
class MApplication : public VAbstractApplication
{
@@ -48,12 +52,12 @@ public:
MApplication(int &argc, char **argv);
~MApplication() override;
- auto notify(QObject * receiver, QEvent * event) -> bool override;
+ auto notify(QObject *receiver, QEvent *event) -> bool override;
auto IsTestMode() const -> bool;
auto IsAppInGUIMode() const -> bool override;
auto MainWindow() -> TMainWindow *;
- auto MainWindows() -> QList;
+ auto MainWindows() -> QList;
auto NewMainWindow() -> TMainWindow *;
void InitOptions();
@@ -62,7 +66,6 @@ public:
void OpenSettings() override;
auto TapeSettings() -> VTapeSettings *;
- void ActivateDarkMode();
static auto diagramsPath() -> QString;
@@ -90,7 +93,7 @@ private slots:
private:
// cppcheck-suppress unknownMacro
Q_DISABLE_COPY_MOVE(MApplication) // NOLINT
- QList > m_mainWindows{};
+ QList> m_mainWindows{};
QLocalServer *m_localServer{nullptr};
VTranslateVars *m_trVars{nullptr};
QPointer m_dataBase{};
@@ -107,7 +110,7 @@ private:
static void ParseDimensionAOption(QCommandLineParser &parser, int &dimensionAValue, bool &flagDimensionA);
static void ParseDimensionBOption(QCommandLineParser &parser, int &dimensionBValue, bool &flagDimensionB);
static void ParseDimensionCOption(QCommandLineParser &parser, int &dimensionCValue, bool &flagDimensionC);
- static void ParseUnitsOption(QCommandLineParser &parser, Unit &unit , bool &flagUnits);
+ static void ParseUnitsOption(QCommandLineParser &parser, Unit &unit, bool &flagUnits);
};
//---------------------------------------------------------------------------------------------------------------------
diff --git a/src/app/tape/tmainwindow.cpp b/src/app/tape/tmainwindow.cpp
index 82fa749ac..4b7663cbe 100644
--- a/src/app/tape/tmainwindow.cpp
+++ b/src/app/tape/tmainwindow.cpp
@@ -1946,15 +1946,13 @@ void TMainWindow::DeployFormula()
{
ui->plainTextEditFormula->setFixedHeight(DIALOG_MAX_FORMULA_HEIGHT);
// Set icon from theme (internal for Windows system)
- ui->pushButtonGrow->setIcon(
- QIcon::fromTheme(QStringLiteral("go-next"), QIcon(":/icons/win.icon.theme/16x16/actions/go-next.png")));
+ ui->pushButtonGrow->setIcon(QIcon::fromTheme(QStringLiteral("go-next")));
}
else
{
ui->plainTextEditFormula->setFixedHeight(m_formulaBaseHeight);
// Set icon from theme (internal for Windows system)
- ui->pushButtonGrow->setIcon(
- QIcon::fromTheme(QStringLiteral("go-down"), QIcon(":/icons/win.icon.theme/16x16/actions/go-down.png")));
+ ui->pushButtonGrow->setIcon(QIcon::fromTheme(QStringLiteral("go-down")));
}
// I found that after change size of formula field, it was filed for angle formula, field for formula became black.
diff --git a/src/app/valentina/core/vapplication.cpp b/src/app/valentina/core/vapplication.cpp
index 7704ae7ac..0fa4a43d4 100644
--- a/src/app/valentina/core/vapplication.cpp
+++ b/src/app/valentina/core/vapplication.cpp
@@ -39,6 +39,8 @@
#include "../vganalytics/def.h"
#include "../vganalytics/vganalytics.h"
#include "../vmisc/qt_dispatch/qt_dispatch.h"
+#include "../vmisc/theme/vapplicationstyle.h"
+#include "../vmisc/theme/vtheme.h"
#include "../vmisc/vsysexits.h"
#include "../vmisc/vvalentinasettings.h"
@@ -50,12 +52,15 @@
#include
#include
#include
+#include
#include
#include
#include
+#include
#include
#include
-#include
+#include
+#include
#include
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
@@ -378,6 +383,7 @@ VApplication::VApplication(int &argc, char **argv)
setApplicationVersion(APP_VERSION_STR);
// making sure will create new instance...just in case we will ever do 2 objects of VApplication
VCommandLine::Reset();
+ VTheme::Instance()->StoreDefaultThemeName(QIcon::themeName());
}
//---------------------------------------------------------------------------------------------------------------------
@@ -523,26 +529,6 @@ auto VApplication::notify(QObject *receiver, QEvent *event) -> bool
return false;
}
-//---------------------------------------------------------------------------------------------------------------------
-void VApplication::ActivateDarkMode()
-{
- VValentinaSettings *settings = ValentinaSettings();
- if (settings->GetDarkMode())
- {
- QFile f(QStringLiteral(":qdarkstyle/style.qss"));
- if (!f.exists())
- {
- qDebug() << "Unable to set stylesheet, file not found\n";
- }
- else
- {
- f.open(QFile::ReadOnly | QFile::Text);
- QTextStream ts(&f);
- qApp->setStyleSheet(ts.readAll()); // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast)
- }
- }
-}
-
//---------------------------------------------------------------------------------------------------------------------
auto VApplication::TapeFilePath() -> QString
{
@@ -696,18 +682,21 @@ void VApplication::InitOptions()
if (VApplication::IsGUIMode()) // By default console version uses system locale
{
LoadTranslation(ValentinaSettings()->GetLocale());
- }
- static const char *GENERIC_ICON_TO_CHECK = "document-open";
- if (not QIcon::hasThemeIcon(GENERIC_ICON_TO_CHECK))
- {
- // If there is no default working icon theme then we should
- // use an icon theme that we provide via a .qrc file
- // This case happens under Windows and Mac OS X
- // This does not happen under GNOME or KDE
- QIcon::setThemeName(QStringLiteral("win.icon.theme"));
+ VTheme::SetIconTheme();
+ VTheme::InitThemeMode();
+
+ QString styleOpt = VApplication::CommandLine()->OptStyle();
+ if (styleOpt != QLatin1String("native"))
+ {
+ QStyle *style = QStyleFactory::create(styleOpt);
+ if (style != nullptr)
+ {
+ style = new VApplicationStyle(style);
+ setStyle(style);
+ }
+ }
}
- ActivateDarkMode();
auto *statistic = VGAnalytics::Instance();
QString clientID = settings->GetClientID();
diff --git a/src/app/valentina/core/vapplication.h b/src/app/valentina/core/vapplication.h
index 35e956699..b1ae7d81f 100644
--- a/src/app/valentina/core/vapplication.h
+++ b/src/app/valentina/core/vapplication.h
@@ -30,11 +30,11 @@
#define VAPPLICATION_H
#include "../vmisc/vabstractvalapplication.h"
+#include "../vmisc/vlockguard.h"
#include "../vpatterndb/vtranslatevars.h"
#include "vcmdexport.h"
-#include "../vmisc/vlockguard.h"
-class VApplication;// use in define
+class VApplication; // use in define
/**
* @brief The VApplication class reimplamentation QApplication class.
@@ -42,12 +42,13 @@ class VApplication;// use in define
class VApplication : public VAbstractValApplication
{
Q_OBJECT // NOLINT
+
public:
- VApplication(int &argc, char ** argv);
+ VApplication(int &argc, char **argv);
~VApplication() override;
static void NewValentina(const QString &fileName = QString());
- auto notify(QObject * receiver, QEvent * event) -> bool override;
+ auto notify(QObject *receiver, QEvent *event) -> bool override;
void InitOptions();
@@ -62,7 +63,6 @@ public:
static auto LabelLanguages() -> QStringList;
void StartLogging();
- void ActivateDarkMode();
auto LogFile() -> QTextStream *;
auto TrVars() -> const VTranslateVars * override;
@@ -85,7 +85,7 @@ private:
// cppcheck-suppress unknownMacro
Q_DISABLE_COPY_MOVE(VApplication) // NOLINT
VTranslateVars *m_trVars{nullptr};
- QTimer *m_autoSaveTimer{nullptr};
+ QTimer *m_autoSaveTimer{nullptr};
QSharedPointer> m_lockLog{};
std::shared_ptr m_out{nullptr};
diff --git a/src/app/valentina/core/vcmdexport.cpp b/src/app/valentina/core/vcmdexport.cpp
index 9fc083ec0..140cd53f9 100644
--- a/src/app/valentina/core/vcmdexport.cpp
+++ b/src/app/valentina/core/vcmdexport.cpp
@@ -30,11 +30,11 @@
#include "../dialogs/dialoglayoutsettings.h"
#include "../dialogs/dialogsavelayout.h"
#include "../ifc/xml/vdomdocument.h"
+#include "../vlayout/vlayoutgenerator.h"
#include "../vmisc/commandoptions.h"
+#include "../vmisc/dialogs/dialogexporttocsv.h"
#include "../vmisc/vsysexits.h"
#include "../vmisc/vvalentinasettings.h"
-#include "../vmisc/dialogs/dialogexporttocsv.h"
-#include "../vlayout/vlayoutgenerator.h"
#include
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
@@ -45,7 +45,8 @@
VCommandLinePtr VCommandLine::instance = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
-#define translate(context, source) QCoreApplication::translate((context), (source)) // NOLINT(cppcoreguidelines-macro-usage)
+#define translate(context, source) \
+ QCoreApplication::translate((context), (source)) // NOLINT(cppcoreguidelines-macro-usage)
namespace
{
@@ -56,7 +57,7 @@ auto Lo2Px(const QString &src, const DialogLayoutSettings &converter, bool *ok)
}
//---------------------------------------------------------------------------------------------------------------------
-auto Pg2Px(const QString& src, const DialogLayoutSettings& converter, bool *ok) -> qreal
+auto Pg2Px(const QString &src, const DialogLayoutSettings &converter, bool *ok) -> qreal
{
return converter.PageToPixels(src.toDouble(ok));
}
@@ -87,7 +88,7 @@ auto VCommandLine::FormatSize(const QString &key) const -> VAbstractLayoutDialog
//---------------------------------------------------------------------------------------------------------------------
auto VCommandLine::DefaultGenerator() const -> VLayoutGeneratorPtr
{
- //this functions covers all options found into layout setup dialog, nothing to add here, unless dialog extended
+ // this functions covers all options found into layout setup dialog, nothing to add here, unless dialog extended
VLayoutGeneratorPtr res(new VLayoutGenerator());
DialogLayoutSettings diag(res.get(), nullptr, true);
@@ -100,16 +101,16 @@ auto VCommandLine::DefaultGenerator() const -> VLayoutGeneratorPtr
if (!diag.SelectTemplate(OptPaperSize()))
{
qCritical() << translate("VCommandLine", "Unknown page templated selected.") << "\n";
- const_cast(this)->parser.showHelp(V_EX_USAGE);
+ const_cast(this)->parser.showHelp(V_EX_USAGE);
}
if (IsOptionSet(LONG_OPTION_PAGEH))
- { //at this point we already sure 3 are set or none
+ { // at this point we already sure 3 are set or none
if (!diag.SelectPaperUnit(OptionValue(LONG_OPTION_PAGEUNITS)))
{
qCritical() << translate("VCommandLine", "Unsupported paper units.") << "\n";
- const_cast(this)->parser.showHelp(V_EX_USAGE);
+ const_cast(this)->parser.showHelp(V_EX_USAGE);
}
bool ok = false;
@@ -117,7 +118,7 @@ auto VCommandLine::DefaultGenerator() const -> VLayoutGeneratorPtr
if (not ok)
{
qCritical() << translate("VCommandLine", "Invalid page height value.") << "\n";
- const_cast(this)->parser.showHelp(V_EX_USAGE);
+ const_cast(this)->parser.showHelp(V_EX_USAGE);
}
diag.SetPaperHeight(height);
@@ -126,7 +127,7 @@ auto VCommandLine::DefaultGenerator() const -> VLayoutGeneratorPtr
if (not ok)
{
qCritical() << translate("VCommandLine", "Invalid page width value.") << "\n";
- const_cast(this)->parser.showHelp(V_EX_USAGE);
+ const_cast(this)->parser.showHelp(V_EX_USAGE);
}
diag.SetPaperWidth(width);
}
@@ -143,7 +144,7 @@ auto VCommandLine::DefaultGenerator() const -> VLayoutGeneratorPtr
if (!diag.SelectLayoutUnit(OptionValue(LONG_OPTION_SHIFTUNITS)))
{
qCritical() << translate("VCommandLine", "Unsupported layout units.") << "\n";
- const_cast(this)->parser.showHelp(V_EX_USAGE);
+ const_cast(this)->parser.showHelp(V_EX_USAGE);
}
}
@@ -154,7 +155,7 @@ auto VCommandLine::DefaultGenerator() const -> VLayoutGeneratorPtr
if (not ok)
{
qCritical() << translate("VCommandLine", "Invalid gap width.") << "\n";
- const_cast(this)->parser.showHelp(V_EX_USAGE);
+ const_cast(this)->parser.showHelp(V_EX_USAGE);
}
diag.SetLayoutWidth(width);
}
@@ -184,7 +185,7 @@ auto VCommandLine::DefaultGenerator() const -> VLayoutGeneratorPtr
}
//---------------------------------------------------------------------------------------------------------------------
-auto VCommandLine::Get(const QCoreApplication& app) -> VCommandLinePtr
+auto VCommandLine::Get(const QCoreApplication &app) -> VCommandLinePtr
{
if (instance == nullptr)
{
@@ -192,10 +193,9 @@ auto VCommandLine::Get(const QCoreApplication& app) -> VCommandLinePtr
}
instance->parser.process(app);
- //fixme: in case of additional options/modes which will need to disable GUI - add it here too
- instance->isGuiEnabled = not (instance->IsExportEnabled()
- || instance->IsTestModeEnabled()
- || instance->IsExportFMEnabled());
+ // fixme: in case of additional options/modes which will need to disable GUI - add it here too
+ instance->isGuiEnabled =
+ not(instance->IsExportEnabled() || instance->IsTestModeEnabled() || instance->IsExportFMEnabled());
return instance;
}
@@ -213,7 +213,7 @@ auto VCommandLine::IsTestModeEnabled() const -> bool
if (r && parser.positionalArguments().size() != 1)
{
qCritical() << translate("VCommandLine", "Test option can be used with single input file only.") << "/n";
- const_cast(this)->parser.showHelp(V_EX_USAGE);
+ const_cast(this)->parser.showHelp(V_EX_USAGE);
}
return r;
}
@@ -238,7 +238,7 @@ auto VCommandLine::IsExportEnabled() const -> bool
if (r && parser.positionalArguments().size() != 1)
{
qCritical() << translate("VCommandLine", "Export options can be used with single input file only.") << "/n";
- const_cast(this)->parser.showHelp(V_EX_USAGE);
+ const_cast(this)->parser.showHelp(V_EX_USAGE);
}
return r;
}
@@ -250,7 +250,7 @@ auto VCommandLine::IsExportFMEnabled() const -> bool
if (r && parser.positionalArguments().size() != 1)
{
qCritical() << translate("VCommandLine", "Export options can be used with single input file only.") << "/n";
- const_cast(this)->parser.showHelp(V_EX_USAGE);
+ const_cast(this)->parser.showHelp(V_EX_USAGE);
}
return r;
}
@@ -265,7 +265,7 @@ auto VCommandLine::OptPaperSize() const -> VAbstractLayoutDialog::PaperSizeTempl
auto VCommandLine::OptGroup() const -> Cases
{
int r = OptionValue(LONG_OPTION_GROUPPING).toInt();
- if ( r < 0 || r >= static_cast(Cases::UnknownCase))
+ if (r < 0 || r >= static_cast(Cases::UnknownCase))
{
r = 0;
}
@@ -276,10 +276,9 @@ auto VCommandLine::OptGroup() const -> Cases
auto VCommandLine::OptMeasurePath() const -> QString
{
QString measure;
- if (IsOptionSet(LONG_OPTION_MEASUREFILE)
- && (IsExportEnabled() || IsTestModeEnabled()))
- //todo: don't want yet to allow user set measure file for general loading,
- //because need to fix multiply opened windows as well
+ if (IsOptionSet(LONG_OPTION_MEASUREFILE) && (IsExportEnabled() || IsTestModeEnabled()))
+ // todo: don't want yet to allow user set measure file for general loading,
+ // because need to fix multiply opened windows as well
{
measure = OptionValue(LONG_OPTION_MEASUREFILE);
}
@@ -410,14 +409,14 @@ auto VCommandLine::OptUserMaterials() const -> QMap
{
QMap userMaterials;
const QStringList values = OptionValues(LONG_OPTION_USER_MATERIAL);
- for(const auto &value : values)
+ for (const auto &value : values)
{
const QStringList parts = value.split('@');
if (parts.size() != 2)
{
qCritical() << translate("VCommandLine", "Invalid user material '%1'. Separator is missing.").arg(value)
<< "\n";
- const_cast(this)->parser.showHelp(V_EX_USAGE);
+ const_cast(this)->parser.showHelp(V_EX_USAGE);
}
bool ok = false;
@@ -427,7 +426,7 @@ auto VCommandLine::OptUserMaterials() const -> QMap
{
qCritical() << translate("VCommandLine", "Invalid user material '%1'. Wrong material number.").arg(value)
<< "\n";
- const_cast(this)->parser.showHelp(V_EX_USAGE);
+ const_cast(this)->parser.showHelp(V_EX_USAGE);
}
userMaterials.insert(number, ConstLast(parts));
@@ -473,13 +472,13 @@ auto VCommandLine::OptDimensionA() const -> int
bool ok = false;
int dimensionAValue = value.toInt(&ok);
- if(ok && dimensionAValue > 0)
+ if (ok && dimensionAValue > 0)
{
return dimensionAValue;
}
qCritical() << translate("VCommandLine", "Invalid dimension A value.") << "\n";
- const_cast(this)->parser.showHelp(V_EX_USAGE);
+ const_cast(this)->parser.showHelp(V_EX_USAGE);
}
//---------------------------------------------------------------------------------------------------------------------
@@ -489,13 +488,13 @@ auto VCommandLine::OptDimensionB() const -> int
bool ok = false;
int dimensionBValue = value.toInt(&ok);
- if(ok && dimensionBValue > 0)
+ if (ok && dimensionBValue > 0)
{
return dimensionBValue;
}
qCritical() << translate("VCommandLine", "Invalid dimension B value.") << "\n";
- const_cast(this)->parser.showHelp(V_EX_USAGE);
+ const_cast(this)->parser.showHelp(V_EX_USAGE);
}
//---------------------------------------------------------------------------------------------------------------------
@@ -505,13 +504,13 @@ auto VCommandLine::OptDimensionC() const -> int
bool ok = false;
int dimensionCValue = value.toInt(&ok);
- if(ok && dimensionCValue > 0)
+ if (ok && dimensionCValue > 0)
{
return dimensionCValue;
}
qCritical() << translate("VCommandLine", "Invalid dimension C value.") << "\n";
- const_cast(this)->parser.showHelp(V_EX_USAGE);
+ const_cast(this)->parser.showHelp(V_EX_USAGE);
}
//---------------------------------------------------------------------------------------------------------------------
@@ -528,7 +527,7 @@ auto VCommandLine::TiledPageMargins() const -> QMarginsF
if (not supportedUnits.contains(value))
{
qCritical() << translate("VCommandLine", "Unsupported paper units.") << "\n";
- const_cast(this)->parser.showHelp(V_EX_USAGE);
+ const_cast(this)->parser.showHelp(V_EX_USAGE);
}
unit = StrToUnits(value);
}
@@ -540,7 +539,7 @@ auto VCommandLine::TiledPageMargins() const -> QMarginsF
if (not ok)
{
qCritical() << translate("VCommandLine", "Invalid tiled page left margin.") << "\n";
- const_cast(this)->parser.showHelp(V_EX_USAGE);
+ const_cast(this)->parser.showHelp(V_EX_USAGE);
}
margins.setLeft(margin);
}
@@ -552,7 +551,7 @@ auto VCommandLine::TiledPageMargins() const -> QMarginsF
if (not ok)
{
qCritical() << translate("VCommandLine", "Invalid tiled page right margin.") << "\n";
- const_cast(this)->parser.showHelp(V_EX_USAGE);
+ const_cast(this)->parser.showHelp(V_EX_USAGE);
}
margins.setLeft(margin);
}
@@ -564,7 +563,7 @@ auto VCommandLine::TiledPageMargins() const -> QMarginsF
if (not ok)
{
qCritical() << translate("VCommandLine", "Invalid tiled page top margin.") << "\n";
- const_cast(this)->parser.showHelp(V_EX_USAGE);
+ const_cast(this)->parser.showHelp(V_EX_USAGE);
}
margins.setLeft(margin);
}
@@ -576,7 +575,7 @@ auto VCommandLine::TiledPageMargins() const -> QMarginsF
if (not ok)
{
qCritical() << translate("VCommandLine", "Invalid tiled page bottom margin.") << "\n";
- const_cast(this)->parser.showHelp(V_EX_USAGE);
+ const_cast(this)->parser.showHelp(V_EX_USAGE);
}
margins.setLeft(margin);
}
@@ -597,43 +596,58 @@ auto VCommandLine::OptTiledPageOrientation() const -> PageOrientation
}
//---------------------------------------------------------------------------------------------------------------------
+auto VCommandLine::OptStyle() const -> QString
+{
+ QString style = OptionValue(LONG_OPTION_STYLE);
+ if (style.isEmpty())
+ {
+ return QStringLiteral("native");
+ }
+
+ return style;
+}
+
+//----------------------------------------------------------------------------------------------------------------------
void VCommandLine::InitCommandLineOptions()
{
- //keep in mind order here - that is how user will see it, so group-up for usability
- //=================================================================================================================
+ // keep in mind order here - that is how user will see it, so group-up for usability
+ //==================================================================================================================
parser.addOptions({
{{SINGLE_OPTION_BASENAME, LONG_OPTION_BASENAME},
translate("VCommandLine", "The base filename of exported layout files. Use it to enable console export mode."),
translate("VCommandLine", "The base filename of layout files")},
{{SINGLE_OPTION_DESTINATION, LONG_OPTION_DESTINATION},
translate("VCommandLine", "The path to output destination folder. By default the directory at which the "
- "application was started."),
+ "application was started."),
translate("VCommandLine", "The destination folder")},
{{SINGLE_OPTION_MEASUREFILE, LONG_OPTION_MEASUREFILE},
translate("VCommandLine", "Path to custom measure file (export mode)."),
translate("VCommandLine", "The measure file")},
{{SINGLE_OPTION_NESTING_TIME, LONG_OPTION_NESTING_TIME},
translate("VCommandLine", "