Skip to content

Add theme settings #50

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Sep 28, 2024
4 changes: 4 additions & 0 deletions src/app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,17 @@ qt_add_executable(${APP_TARGET}
libraryinfo.h
)

set_source_files_properties(qml/Colors.qml PROPERTIES QT_QML_SINGLETON_TYPE TRUE)

qt_add_qml_module(${APP_TARGET}
URI ScratchCPP
VERSION 1.0
QML_FILES
qml/main.qml
qml/Colors.qml
qml/dialogs/AboutDialog.qml
qml/dialogs/ProjectSettingsDialog.qml
qml/dialogs/PreferencesDialog.qml
)

set(QML_IMPORT_PATH "${QML_IMPORT_PATH};${CMAKE_CURRENT_LIST_DIR}"
Expand Down
11 changes: 11 additions & 0 deletions src/app/appmenubar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,17 @@ AppMenuBar::AppMenuBar(QObject *parent) :
m_editMenu->addItem(m_projectSettingsItem);
connect(m_projectSettingsItem, &MenuItemModel::clicked, this, &AppMenuBar::projectSettingsTriggered);

// Edit -> (separator)
m_editSeparator = new MenuItemModel(m_editMenu);
m_editSeparator->setIsSeparator(true);
m_editMenu->addItem(m_editSeparator);

// Edit -> Preferences
m_preferencesItem = new MenuItemModel(m_editMenu);
m_preferencesItem->setText(tr("Preferences..."));
m_editMenu->addItem(m_preferencesItem);
connect(m_preferencesItem, &MenuItemModel::clicked, this, &AppMenuBar::preferencesTriggered);

// Help menu
m_helpMenu = new MenuModel(m_model);
m_helpMenu->setTitle(tr("&Help"));
Expand Down
3 changes: 3 additions & 0 deletions src/app/appmenubar.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class AppMenuBar : public QObject
void fps60ModeChanged();
void muteChanged();
void projectSettingsTriggered();
void preferencesTriggered();
void aboutAppTriggered();

private:
Expand All @@ -72,6 +73,8 @@ class AppMenuBar : public QObject
uicomponents::MenuItemModel *m_fps60ModeItem = nullptr;
uicomponents::MenuItemModel *m_muteItem = nullptr;
uicomponents::MenuItemModel *m_projectSettingsItem = nullptr;
uicomponents::MenuItemModel *m_editSeparator = nullptr;
uicomponents::MenuItemModel *m_preferencesItem = nullptr;

uicomponents::MenuModel *m_helpMenu = nullptr;
uicomponents::MenuItemModel *m_aboutAppItem = nullptr;
Expand Down
29 changes: 29 additions & 0 deletions src/app/qml/Colors.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: GPL-3.0-or-later

pragma Singleton
import QtQuick
import ScratchCPP.Ui

QtObject {
readonly property list<color> darkAccentColors: [
Qt.rgba(0.85, 0.31, 0.33, 1),
Qt.rgba(0.85, 0.62, 0.31, 1),
Qt.rgba(0.85, 0.84, 0.31, 1),
Qt.rgba(0.39, 0.85, 0.31, 1),
Qt.rgba(0.31, 0.75, 0.85, 1),
Qt.rgba(0.32, 0.32, 0.85, 1),
Qt.rgba(0.68, 0.31, 0.85, 1),
]

readonly property list<color> lightAccentColors: [
Qt.rgba(0.75, 0.08, 0.09, 1),
Qt.rgba(0.75, 0.47, 0.08, 1),
Qt.rgba(0.75, 0.74, 0.08, 1),
Qt.rgba(0.17, 0.75, 0.08, 1),
Qt.rgba(0.08, 0.63, 0.75, 1),
Qt.rgba(0.08, 0.08, 0.75, 1),
Qt.rgba(0.54, 0.08, 0.75, 1),
]

readonly property color defaultAccentColor: ThemeEngine.theme == ThemeEngine.DarkTheme ? darkAccentColors[1] : lightAccentColors[1]
}
91 changes: 91 additions & 0 deletions src/app/qml/dialogs/PreferencesDialog.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// SPDX-License-Identifier: GPL-3.0-or-later

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import ScratchCPP.Global
import ScratchCPP.Ui
import ScratchCPP.UiComponents

import ".."

CustomDialog {
title: qsTr("Preferences")
standardButtons: Dialog.Cancel | Dialog.Ok
onOpened: Settings.freeze()
onAccepted: Settings.saveChanges()
onRejected: {
Settings.discardChanges();
ThemeEngine.reloadTheme();
}

QtObject {
id: priv
property int accentColorIndex: -1
}

contentItem: ColumnLayout {
// Themes
Label {
text: qsTr("Themes")
font.pointSize: 14
font.bold: true
}

RowLayout {
RadioButton {
text: qsTr("Light")
checked: ThemeEngine.theme === ThemeEngine.LightTheme
onCheckedChanged: if(checked) ThemeEngine.theme = ThemeEngine.LightTheme
}

RadioButton {
text: qsTr("Dark")
checked: ThemeEngine.theme === ThemeEngine.DarkTheme
onCheckedChanged: if(checked) ThemeEngine.theme = ThemeEngine.DarkTheme
}
}

RowLayout {
Label {
text: qsTr("Accent color:")
}

Repeater {
id: accentColors
model: ThemeEngine.theme == ThemeEngine.DarkTheme ? Colors.darkAccentColors : Colors.lightAccentColors

ColorButton {
required property color modelData
required property int index
color: modelData
checked: {
if(ThemeEngine.accentColor === modelData) {
priv.accentColorIndex = index;
return true;
} else {
return false;
}
}
autoExclusive: true
checkable: true
onPressed: ThemeEngine.accentColor = modelData;
}
}
}

Connections {
target: ThemeEngine

function onThemeChanged() {
console.log(priv.accentColorIndex, ThemeEngine.theme);

if(ThemeEngine.theme == ThemeEngine.DarkTheme) {
ThemeEngine.accentColor = Colors.darkAccentColors[priv.accentColorIndex];
} else {
ThemeEngine.accentColor = Colors.lightAccentColors[priv.accentColorIndex];
}
}
}
}
}
15 changes: 13 additions & 2 deletions src/app/qml/main.qml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ ApplicationWindow {
visible: true
title: Qt.application.displayName
color: Material.background
Material.accent: "orange"
Material.theme: Material.Dark
Material.accent: ThemeEngine.accentColor
Material.theme: ThemeEngine.theme == ThemeEngine.DarkTheme ? Material.Dark : Material.Light
onActiveFocusItemChanged: UiEngine.activeFocusItem = activeFocusItem

menuBar: CustomMenuBar {
Expand All @@ -44,6 +44,10 @@ ApplicationWindow {
projectSettingsDialog.open();
}

function onPreferencesTriggered() {
preferencesDialog.open();
}

function onAboutAppTriggered() {
aboutDialog.open();
}
Expand All @@ -57,6 +61,8 @@ ApplicationWindow {
projectPlayer: player
}

PreferencesDialog { id: preferencesDialog }

CustomMessageDialog {
id: unsupportedBlocksDialog
title: qsTr("Warning")
Expand Down Expand Up @@ -166,4 +172,9 @@ ApplicationWindow {
}
}
}

Component.onCompleted: {
if(ThemeEngine.accentColor === Qt.rgba(0, 0, 0, 0))
ThemeEngine.accentColor = Colors.defaultAccentColor;
}
}
6 changes: 6 additions & 0 deletions src/global/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@ set(MODULE_SRC
globalmodule.cpp
globalmodule.h
iappinfo.h
ifilepaths.h
isettings.h
modularity/ioc.h
modularity/modulesioc.h
modularity/imoduleexportinterface.h
modularity/imodulesetup.h
internal/appinfo.cpp
internal/appinfo.h
internal/filepaths.cpp
internal/filepaths.h
internal/settings.cpp
internal/settings.h
)

include(${PROJECT_SOURCE_DIR}/build/module.cmake)
Expand Down
10 changes: 10 additions & 0 deletions src/global/globalmodule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

#include "globalmodule.h"
#include "internal/appinfo.h"
#include "internal/filepaths.h"
#include "internal/settings.h"

using namespace scratchcpp;

Expand All @@ -19,4 +21,12 @@ void GlobalModule::registerExports()
QQmlEngine::setObjectOwnership(m_appInfo.get(), QQmlEngine::CppOwnership);
qmlRegisterSingletonInstance<AppInfo>("ScratchCPP.Ui", 1, 0, "AppInfo", m_appInfo.get());
modularity::ioc()->registerExport<IAppInfo>(m_appInfo);

modularity::ioc()->registerExport<FilePaths>(FilePaths::instance());

m_settings = std::make_shared<Settings>();

QQmlEngine::setObjectOwnership(m_settings.get(), QQmlEngine::CppOwnership);
qmlRegisterSingletonInstance<Settings>("ScratchCPP.Global", 1, 0, "Settings", m_settings.get());
modularity::ioc()->registerExport<Settings>(m_settings);
}
2 changes: 2 additions & 0 deletions src/global/globalmodule.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ namespace scratchcpp
{

class AppInfo;
class Settings;

class GlobalModule : public modularity::IModuleSetup
{
Expand All @@ -20,6 +21,7 @@ class GlobalModule : public modularity::IModuleSetup

private:
std::shared_ptr<AppInfo> m_appInfo;
std::shared_ptr<Settings> m_settings;
};

} // namespace scratchcpp
20 changes: 20 additions & 0 deletions src/global/ifilepaths.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: GPL-3.0-or-later

#pragma once

#include <QString>

#include "modularity/ioc.h"

namespace scratchcpp
{

class IFilePaths : MODULE_EXPORT_INTERFACE
{
public:
virtual ~IFilePaths() { }

virtual QString configLocation() const = 0;
};

} // namespace scratchcpp
20 changes: 20 additions & 0 deletions src/global/internal/filepaths.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: GPL-3.0-or-later

#include <QStandardPaths>
#include <QCoreApplication>

#include "filepaths.h"

using namespace scratchcpp;

std::shared_ptr<FilePaths> FilePaths::m_instance = std::make_shared<FilePaths>();

std::shared_ptr<FilePaths> FilePaths::instance()
{
return m_instance;
}

QString scratchcpp::FilePaths::configLocation() const
{
return QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/" + qApp->applicationName() + "/config.ini";
}
23 changes: 23 additions & 0 deletions src/global/internal/filepaths.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: GPL-3.0-or-later

#pragma once

#include <QObject>

#include "ifilepaths.h"

namespace scratchcpp
{

class FilePaths : public IFilePaths
{
public:
static std::shared_ptr<FilePaths> instance();

QString configLocation() const override;

private:
static std::shared_ptr<FilePaths> m_instance;
};

} // namespace scratchcpp
Loading
Loading