From eaccc9a17ad37661943f9ebd3c6a6419febe307e Mon Sep 17 00:00:00 2001
From: Matthias Puchner <github@mpuchner.de>
Date: Wed, 25 Aug 2021 07:32:07 +0200
Subject: [PATCH] include stylesheets in qrc; add style setting via UI and app
 settings

---
 GUI/Application/Application.cpp         | 53 +++++++++++++++-
 GUI/Application/Application.h           |  4 ++
 GUI/Application/ApplicationSettings.cpp | 13 +++-
 GUI/Application/ApplicationSettings.h   |  4 ++
 GUI/gui.qrc                             |  4 ++
 GUI/main/main.cpp                       |  2 +
 GUI/mainwindow/actionmanager.cpp        | 17 ++++++
 GUI/mainwindow/mainwindow.cpp           | 27 +--------
 GUI/styles/Base.stylesheet              | 46 ++++++++++++++
 GUI/styles/Dark.stylesheet              | 80 +++++++++++++++++++++++++
 GUI/styles/Light.stylesheet             | 65 ++++++++++++++++++++
 GUI/styles/Native.stylesheet            | 20 +++++++
 12 files changed, 307 insertions(+), 28 deletions(-)
 create mode 100644 GUI/styles/Base.stylesheet
 create mode 100644 GUI/styles/Dark.stylesheet
 create mode 100644 GUI/styles/Light.stylesheet
 create mode 100644 GUI/styles/Native.stylesheet

diff --git a/GUI/Application/Application.cpp b/GUI/Application/Application.cpp
index 6cb304a9c39..a3596a9a17b 100644
--- a/GUI/Application/Application.cpp
+++ b/GUI/Application/Application.cpp
@@ -13,10 +13,61 @@
 //  ************************************************************************************************
 
 #include "GUI/Application/Application.h"
+#include "GUI/utils/Helpers.h"
+#include "GUI/utils/hostosinfo.h"
+#include <QFile>
+#include <QIcon>
 
-Application::Application(int& argc, char** argv) : QApplication(argc, argv) {}
+Application::Application(int& argc, char** argv)
+    : QApplication(argc, argv), m_currentStyle(ApplicationSettings::Style::native)
+{
+    setApplicationName("BornAgain");
+    setApplicationVersion(GUI::Helpers::getBornAgainVersionString());
+    setOrganizationName("Forschungszentrum Jülich, Scientific Computing Group at MLZ Garching");
+
+    if (!GUI::Utils::OS::HostOsInfo::isMacHost())
+        QApplication::setWindowIcon(QIcon(":/images/BornAgain.ico"));
+}
 
 ApplicationSettings& Application::settings()
 {
     return m_settings;
 }
+
+void Application::loadStyle(ApplicationSettings::Style style)
+{
+    QString stylesheet;
+
+    switch (style) {
+    case ApplicationSettings::Style::light: {
+        QFile base(":/styles/Base.stylesheet");
+        base.open(QFile::ReadOnly);
+        QFile light(":/styles/Light.stylesheet");
+        light.open(QFile::ReadOnly);
+        stylesheet = base.readAll() + light.readAll();
+        break;
+    }
+    case ApplicationSettings::Style::dark: {
+        QFile base(":/styles/Base.stylesheet");
+        base.open(QFile::ReadOnly);
+        QFile dark(":/styles/Dark.stylesheet");
+        dark.open(QFile::ReadOnly);
+        stylesheet = base.readAll() + dark.readAll();
+        break;
+    }
+    default: {
+        QFile native(":/styles/Native.stylesheet");
+        native.open(QFile::ReadOnly);
+        stylesheet = native.readAll();
+        break;
+    }
+    }
+
+    setStyleSheet(stylesheet);
+    m_currentStyle = style;
+}
+
+ApplicationSettings::Style Application::currentStyle()
+{
+    return m_currentStyle;
+}
diff --git a/GUI/Application/Application.h b/GUI/Application/Application.h
index ffa5de8bfae..d029d43956b 100644
--- a/GUI/Application/Application.h
+++ b/GUI/Application/Application.h
@@ -26,8 +26,12 @@ public:
 
     ApplicationSettings& settings();
 
+    void loadStyle(ApplicationSettings::Style style);
+    ApplicationSettings::Style currentStyle();
+
 private:
     ApplicationSettings m_settings;
+    ApplicationSettings::Style m_currentStyle;
 };
 
 #define baApp (static_cast<Application*>(qApp))
diff --git a/GUI/Application/ApplicationSettings.cpp b/GUI/Application/ApplicationSettings.cpp
index 36d4af6b867..ab3234f7a21 100644
--- a/GUI/Application/ApplicationSettings.cpp
+++ b/GUI/Application/ApplicationSettings.cpp
@@ -17,7 +17,8 @@
 
 namespace {
 const QString S_CREATE_NEW_PROJECT_ON_STARTUP = "CreateNewProjectOnStartup";
-}
+const QString S_STYLE = "Style";
+} // namespace
 
 bool ApplicationSettings::useNativeFileDialog() const
 {
@@ -37,3 +38,13 @@ void ApplicationSettings::setCreateNewProjectOnStartup(bool b)
 {
     QSettings().setValue(S_CREATE_NEW_PROJECT_ON_STARTUP, b);
 }
+
+ApplicationSettings::Style ApplicationSettings::styleToUse() const
+{
+    return static_cast<Style>(QSettings().value(S_STYLE, static_cast<int>(Style::native)).toInt());
+}
+
+void ApplicationSettings::setStyleToUse(Style style)
+{
+    QSettings().setValue(S_STYLE, static_cast<int>(style));
+}
diff --git a/GUI/Application/ApplicationSettings.h b/GUI/Application/ApplicationSettings.h
index 5a5be8e2878..463d5828c94 100644
--- a/GUI/Application/ApplicationSettings.h
+++ b/GUI/Application/ApplicationSettings.h
@@ -21,9 +21,13 @@
 
 class ApplicationSettings {
 public:
+    enum class Style { native, light, dark };
+
     bool useNativeFileDialog() const;
     bool createNewProjectOnStartup() const;
     void setCreateNewProjectOnStartup(bool b);
+    Style styleToUse() const;
+    void setStyleToUse(Style style);
 };
 
 #endif // BORNAGAIN_GUI_APPLICATION_APPLICATIONSETTINGS_H
diff --git a/GUI/gui.qrc b/GUI/gui.qrc
index 07c9f6b5d71..b8df348712a 100644
--- a/GUI/gui.qrc
+++ b/GUI/gui.qrc
@@ -58,5 +58,9 @@
         <file>images/1D_OK.png</file>
         <file>images/2D_OK.png</file>
         <file>images/warning_16x16.png</file>
+        <file>styles/Native.stylesheet</file>
+        <file>styles/Base.stylesheet</file>
+        <file>styles/Dark.stylesheet</file>
+        <file>styles/Light.stylesheet</file>
     </qresource>
 </RCC>
diff --git a/GUI/main/main.cpp b/GUI/main/main.cpp
index 2fc554eea5c..c136fbf08ef 100644
--- a/GUI/main/main.cpp
+++ b/GUI/main/main.cpp
@@ -40,6 +40,8 @@ int main(int argc, char* argv[])
 
     register1DDataLoaders();
 
+    app.loadStyle(app.settings().styleToUse());
+
     MainWindow win;
     if (options.find("geometry"))
         win.resize(options.mainWindowSize());
diff --git a/GUI/mainwindow/actionmanager.cpp b/GUI/mainwindow/actionmanager.cpp
index ea5ee660d35..0c503aca104 100644
--- a/GUI/mainwindow/actionmanager.cpp
+++ b/GUI/mainwindow/actionmanager.cpp
@@ -251,6 +251,23 @@ void ActionManager::onAboutToShowSettingsMenu()
             [](bool b) { baApp->settings().setCreateNewProjectOnStartup(b); });
 
     m_settingsMenu->setToolTipsVisible(true);
+
+    m_settingsMenu->addSeparator();
+
+    QActionGroup* styleActions = new QActionGroup(this);
+    const auto addStyleAction = [=](const QString& text, ApplicationSettings::Style style) {
+        auto action = m_settingsMenu->addAction(text, [=]() {
+            baApp->settings().setStyleToUse(style);
+            baApp->loadStyle(style);
+        });
+        action->setCheckable(true);
+        action->setChecked(baApp->currentStyle() == style);
+        styleActions->addAction(action);
+    };
+
+    addStyleAction("Native style", ApplicationSettings::Style::native);
+    addStyleAction("Light style", ApplicationSettings::Style::light);
+    addStyleAction("Dark style", ApplicationSettings::Style::dark);
 }
 
 void ActionManager::onAboutToShowViewMenu()
diff --git a/GUI/mainwindow/mainwindow.cpp b/GUI/mainwindow/mainwindow.cpp
index 9516ef9081b..0a1322e2f84 100644
--- a/GUI/mainwindow/mainwindow.cpp
+++ b/GUI/mainwindow/mainwindow.cpp
@@ -224,14 +224,6 @@ void MainWindow::closeEvent(QCloseEvent* event)
 
 void MainWindow::initApplication()
 {
-    QCoreApplication::setApplicationName("BornAgain");
-    QCoreApplication::setApplicationVersion(GUI::Helpers::getBornAgainVersionString());
-    QCoreApplication::setOrganizationName(
-        "Forschungszentrum Jülich, Scientific Computing Group at MLZ Garching");
-
-    if (!GUI::Utils::OS::HostOsInfo::isMacHost())
-        QApplication::setWindowIcon(QIcon(":/images/BornAgain.ico"));
-
     setDockNestingEnabled(true);
     setAcceptDrops(true);
 
@@ -413,26 +405,9 @@ void MainWindow::onAboutToCloseDocument()
 
 QToolButton* MainWindow::createViewSelectionButton() const
 {
-    const QString viewSelectionButtonStyle =
-        "QToolButton { border: none; color: white; background-color: qlineargradient(x1: 0, "
-        "y1: 0, x2: 1, y2: 0, stop : 0 #153b4c, stop : 1 #347a9c);}        "
-        "QToolButton:pressed { "
-        " color: black; background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 "
-        "#97a8b0, stop: "
-        "1 #dae7ed); }"
-        "QToolButton:hover { "
-        " color: white; background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 "
-        "#254b5c, stop: 1 #448aac); }"
-        "QToolButton:checked { "
-        " color: black; background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 "
-        "#97a8b0, stop: "
-        "1 #dae7ed);"
-        "} ";
-
     QToolButton* btn = new QToolButton;
-    btn->setObjectName("ViewSelectionButton"); // good for addressing in a style sheet
+    btn->setObjectName("ViewSelectionButton"); // for addressing in style sheet
     btn->setCheckable(true);
     btn->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
-    btn->setStyleSheet(viewSelectionButtonStyle);
     return btn;
 }
diff --git a/GUI/styles/Base.stylesheet b/GUI/styles/Base.stylesheet
new file mode 100644
index 00000000000..50c6885f9ce
--- /dev/null
+++ b/GUI/styles/Base.stylesheet
@@ -0,0 +1,46 @@
+QToolButton#ViewSelectionButton 
+{ 
+    border: none; 
+}
+
+QToolButton#GroupBoxToggler 
+{
+    font: bold 15px; 
+    margin-left: 0px; 
+    margin-bottom: 10px
+}
+
+QWidget[stylable="true"] QGroupBox 
+{ 
+    padding-top: 35px;
+    border: none;
+    font: bold 15px; 
+    margin-top: 3ex; 
+    padding-bottom: 10px;
+    padding-left: 10px; 
+    spacing: 15px
+}
+
+QWidget[stylable="true"] QGroupBox[collapsible="true"] 
+{ 
+    padding-top: 0px;
+}
+
+QWidget[stylable="true"] QGroupBox::title 
+{ 
+    margin-top:10px; 
+    margin-left: 10px; 
+}
+
+QWidget[stylable="true"] .QPushButton
+{
+    padding: 10px;
+    border-radius: 6px;
+    margin-left: 20px;
+    border: 2px solid;
+}
+
+QWidget[stylable="true"] QListWidget
+{
+    border: none;
+}
diff --git a/GUI/styles/Dark.stylesheet b/GUI/styles/Dark.stylesheet
new file mode 100644
index 00000000000..9761599f881
--- /dev/null
+++ b/GUI/styles/Dark.stylesheet
@@ -0,0 +1,80 @@
+QToolButton#ViewSelectionButton 
+{ 
+    color: white; background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop : 0 rgb(18,25,29), stop : 1 rgb(71,96,107));
+}
+
+QToolButton#ViewSelectionButton:pressed
+{  
+    color: black; background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #97a8b0, stop: 1 #dae7ed); 
+}
+
+QToolButton#ViewSelectionButton:hover 
+{  
+    color: white; background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #254b5c, stop: 1 #448aac); 
+}
+
+QToolButton#ViewSelectionButton:checked 
+{  
+    color: black; background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #97a8b0, stop: 1 #dae7ed);
+} 
+
+
+QWidget[stylable="true"]
+{ 
+    background-color: rgb(18,25,29); 
+    color: rgb(213,220,223);
+}
+
+QWidget[stylable="true"] QWidget
+{ 
+    background-color: rgb(18,25,29); 
+    color: rgb(213,220,223);
+}
+
+
+QToolButton#GroupBoxToggler 
+{
+    color: rgb(213,220,223);
+    background-color: rgb(29,39,44);
+}
+
+QWidget[stylable="true"] QGroupBox 
+{ 
+    background-color: rgb(18,25,29); 
+}
+
+QWidget[stylable="true"] QGroupBox::title 
+{ 
+    color: rgb(48, 113, 145)
+}
+
+QWidget[stylable="true"] .QPushButton
+{
+    background: rgb(78,105,118); 
+    border-color: rgb(50,119,152);
+}
+
+QWidget[stylable="true"] .QPushButton:hover
+{
+    background: rgb(98,125,138); 
+}
+
+
+WelcomeView QCommandLinkButton:hover
+{
+    background: rgb(188,218,233); 
+    border: none;
+}
+
+
+QWidget#widgetForRecentProjects
+{
+    background-color: rgb(18,25,29); 
+}
+
+QMenuBar
+{
+   background-color: rgb(18,25,29); 
+   color: rgb(213,220,223);
+}
+
diff --git a/GUI/styles/Light.stylesheet b/GUI/styles/Light.stylesheet
new file mode 100644
index 00000000000..b4e4cba9e12
--- /dev/null
+++ b/GUI/styles/Light.stylesheet
@@ -0,0 +1,65 @@
+QToolButton#ViewSelectionButton 
+{ 
+    color: white; background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop : 0 #153b4c, stop : 1 #347a9c);
+}
+
+QToolButton#ViewSelectionButton:pressed
+{  
+    color: black; background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #97a8b0, stop: 1 #dae7ed); 
+}
+
+QToolButton#ViewSelectionButton:hover 
+{  
+    color: white; background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #254b5c, stop: 1 #448aac); 
+}
+
+QToolButton#ViewSelectionButton:checked 
+{  
+    color: black; background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #97a8b0, stop: 1 #dae7ed);
+} 
+
+
+QWidget[stylable="true"]
+{ 
+    background-color: white; 
+}
+
+QToolButton#GroupBoxToggler 
+{
+    color: rgb(48, 113, 145);
+    background-color: rgb(222,232,237);
+}
+
+QWidget[stylable="true"] QGroupBox 
+{ 
+    background-color: white; 
+}
+
+QWidget[stylable="true"] QGroupBox::title 
+{ 
+    color: rgb(48, 113, 145);
+}
+
+QWidget[stylable="true"] .QPushButton
+{
+    background: rgb(188,218,233); 
+    border-color:rgb(50,119,152);
+}
+
+QWidget[stylable="true"] .QPushButton:hover
+{
+    background: rgb(208,238,252); 
+}
+
+
+WelcomeView QCommandLinkButton:hover
+{
+    background: rgb(188,218,233); 
+    border: none;
+}
+
+
+QWidget#widgetForRecentProjects
+{
+    background: white;
+}
diff --git a/GUI/styles/Native.stylesheet b/GUI/styles/Native.stylesheet
new file mode 100644
index 00000000000..d958f1973c2
--- /dev/null
+++ b/GUI/styles/Native.stylesheet
@@ -0,0 +1,20 @@
+QToolButton#ViewSelectionButton 
+{ 
+    border: none; 
+    color: white; background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop : 0 #153b4c, stop : 1 #347a9c);
+}
+
+QToolButton#ViewSelectionButton:pressed
+{  
+    color: black; background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #97a8b0, stop: 1 #dae7ed); 
+}
+
+QToolButton#ViewSelectionButton:hover 
+{  
+    color: white; background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #254b5c, stop: 1 #448aac); 
+}
+
+QToolButton#ViewSelectionButton:checked 
+{  
+    color: black; background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #97a8b0, stop: 1 #dae7ed);
+} 
-- 
GitLab