Setting QML style and Material theme, variant.

main
Ben Niemann 2021-11-23 09:36:05 +01:00
parent 724f8bf3d8
commit 970305eee2
11 changed files with 221 additions and 13 deletions

View File

@ -158,6 +158,7 @@ in stdenv.mkDerivation {
nixpkgs.fmt
qt5.qmake
qt5.qtbase
qt5.qtquickcontrols2.dev
qt5.qttools.dev
] ++ lib.lists.optional withTests [
nixpkgs.gtest.dev

View File

@ -22,6 +22,7 @@ import argparse
import asyncio
import contextlib
import functools
import os
import os.path
import signal
import sys
@ -40,6 +41,7 @@ from . import ui_base
from . import project
from . import node_db
from . import qml
from . import qt_helper
from . import ui_rc
logger = None # type: logging.Logger
@ -57,6 +59,9 @@ class QEventLoopPolicy(asyncio.DefaultEventLoopPolicy):
class App(ui_base.PropertyContainer, QtCore.QObject):
needsRestart, needsRestartChanged = ui_base.Property('needsRestart', bool)
displayMultisampling, displayMultisamplingChanged = ui_base.Property('displayMultisampling', bool)
displayStyle, displayStyleChanged = ui_base.Property('displayStyle', str)
displayMaterialTheme, displayMaterialThemeChanged = ui_base.Property('displayMaterialTheme', str)
displayMaterialVariant, displayMaterialVariantChanged = ui_base.Property('displayMaterialVariant', str)
def __init__(self) -> None:
super().__init__()
@ -137,6 +142,12 @@ class App(ui_base.PropertyContainer, QtCore.QObject):
with self.settingsGroup('display') as settings:
self.displayMultisampling = (settings.value('multisampling', 'true') == 'true')
self.displayMultisamplingChanged.connect(self.__displayMultisamplingChanged)
self.displayStyle = settings.value('style', 'Material')
self.displayStyleChanged.connect(self.__displayStyleChanged)
self.displayMaterialTheme = settings.value('materialTheme', 'System')
self.displayMaterialThemeChanged.connect(self.__displayMaterialThemeChanged)
self.displayMaterialVariant = settings.value('materialVariant', 'Normal')
self.displayMaterialVariantChanged.connect(self.__displayMaterialVariantChanged)
if self.displayMultisampling:
logger.info("Enable multisampling.")
@ -144,6 +155,9 @@ class App(ui_base.PropertyContainer, QtCore.QObject):
format.setSamples(16)
QtGui.QSurfaceFormat.setDefaultFormat(format)
os.environ["QT_QUICK_CONTROLS_STYLE"] = self.displayStyle
os.environ["QT_QUICK_CONTROLS_MATERIAL_VARIANT"] = self.displayMaterialVariant
self.__qmlEngine = QtQml.QQmlEngine(self.__qtApp)
self.__qmlEngine.warnings.connect(self.__qmlEngineWarnings)
self.__qmlEngine.setOutputWarningsToStandardError(False)
@ -258,6 +272,17 @@ class App(ui_base.PropertyContainer, QtCore.QObject):
self.__settings.setValue('display/multisampling', 'true' if v else 'false')
self.needsRestart = True
def __displayStyleChanged(self, v):
self.__settings.setValue('display/style', v)
self.needsRestart = True
def __displayMaterialThemeChanged(self, v):
self.__settings.setValue('display/materialTheme', v)
def __displayMaterialVariantChanged(self, v):
self.__settings.setValue('display/materialVariant', v)
self.needsRestart = True
def quit(self, exit_code: int = 0) -> None:
self.__exit_code = exit_code
self.__quit.set()

View File

@ -26,12 +26,11 @@ import QtQuick.Controls 2.15
import "." as Noisicaa
import "matrix.js" as Transform
Rectangle {
Control {
id: root
property QtObject d
color: "#ffffff"
property color bgColor: ApplicationWindow.window.color
Menu {
id: contextMenu
@ -160,7 +159,7 @@ Rectangle {
property real step: 20 * d.zoom
property real offsetx: d.offset.x % step
property real offsety: d.offset.y % step
property color color: Qt.tint(root.bgColor, "#20808080")
visible: step > 5
Repeater {
@ -171,7 +170,7 @@ Rectangle {
ShapePath {
fillColor: "transparent"
strokeWidth: 1
strokeColor: "#f8f8f8"
strokeColor: grid.color
startX: 0
startY: 0
PathLine {
@ -190,7 +189,7 @@ Rectangle {
ShapePath {
fillColor: "transparent"
strokeWidth: 1
strokeColor: "#f8f8f8"
strokeColor: grid.color
startX: 0
startY: 0
PathLine {
@ -375,8 +374,9 @@ Rectangle {
}
Rectangle {
color: "#ffffff"
border { width: 1; color: "#000000" }
color: root.bgColor
border.width: 1
border.color: Qt.tint(root.bgColor, "#a0808080")
anchors {
left: parent.left
leftMargin: 20
@ -391,6 +391,7 @@ Rectangle {
anchors.fill: parent
anchors.margins: 2
clip: true
color: parent.color
property var complete: false
property rect contentRect: d.contentRect
@ -403,8 +404,10 @@ Rectangle {
var t = new Transform.Matrix();
if (d.nodes.rowCount() == 0) {
minimapView.visible = false;
return;
}
minimapView.visible = true;
var sx = width / contentRect.width;
var sy = height / contentRect.height;

View File

@ -1,5 +1,6 @@
import QtQuick 2.12
import QtQuick.Controls 2.15
import QtQuick.Controls.Material 2.12
ApplicationWindow {
id: root
@ -9,8 +10,7 @@ ApplicationWindow {
width: 1000
height: 800
Component.onCompleted: {
}
Material.theme: d.app.displayMaterialTheme
onClosing: function (event) {
d.closeProject()

View File

@ -25,6 +25,7 @@ from PySide2.QtCore import Qt
from PySide2 import QtCore
from noisicaa.ui import ui_base
from noisicaa.ui import qt_helper
logger = logging.getLogger(__name__)
@ -33,12 +34,18 @@ class SettingsDialog(ui_base.CommonMixin, ui_base.PropertyContainer, QtCore.QObj
modified, modifiedChanged = ui_base.Property('modified', bool)
audioBackendIndex, audioBackendIndexChanged = ui_base.Property('audioBackendIndex', int)
displayMultisampling, displayMultisamplingChanged = ui_base.Property('displayMultisampling', bool)
displayStyleIndex, displayStyleIndexChanged = ui_base.Property('displayStyleIndex', int)
displayMaterialThemeIndex, displayMaterialThemeIndexChanged = ui_base.Property('displayMaterialThemeIndex', int)
displayMaterialVariantIndex, displayMaterialVariantIndexChanged = ui_base.Property('displayMaterialVariantIndex', int)
def __init__(self, **kwargs) -> None:
super().__init__(**kwargs)
self.audioBackendIndexChanged.connect(self.__setModified)
self.displayMultisamplingChanged.connect(self.__setModified)
self.displayStyleIndexChanged.connect(self.__setModified)
self.displayMaterialThemeIndexChanged.connect(self.__setModified)
self.displayMaterialVariantIndexChanged.connect(self.__setModified)
def __setModified(self, *args):
self.modified = True
@ -47,13 +54,39 @@ class SettingsDialog(ui_base.CommonMixin, ui_base.PropertyContainer, QtCore.QObj
def audioBackendList(self):
return ['jack', 'dummy']
@ui_base.ConstProperty(list)
def displayStyleList(self):
return qt_helper.availableQuickStyles()
@ui_base.ConstProperty(list)
def displayMaterialThemeList(self):
return ['Light', 'Dark', 'System']
@ui_base.ConstProperty(list)
def displayMaterialVariantList(self):
return ['Normal', 'Dense']
@QtCore.Slot()
def reset(self):
with self.app.settingsGroup('audio') as settings:
self.audioBackendIndex = self.audioBackendList.index(settings.value('backend', 'jack'))
try:
self.audioBackendIndex = self.audioBackendList.index(settings.value('backend', 'jack'))
except ValueError:
self.audioBackendIndex = 0
self.displayMultisampling = self.app.displayMultisampling
try:
self.displayStyleIndex = self.displayStyleList.index(self.app.displayStyle)
except ValueError:
self.displayStyleIndex = 0
try:
self.displayMaterialThemeIndex = self.displayMaterialThemeList.index(self.app.displayMaterialTheme)
except ValueError:
self.displayMaterialThemeIndex = 0
try:
self.displayMaterialVariantIndex = self.displayMaterialVariantList.index(self.app.displayMaterialVariant)
except ValueError:
self.displayMaterialVariantIndex = 0
self.modified = False
@QtCore.Slot()
@ -63,5 +96,8 @@ class SettingsDialog(ui_base.CommonMixin, ui_base.PropertyContainer, QtCore.QObj
self.app.updateAudioBackend()
self.app.displayMultisampling = self.displayMultisampling
self.app.displayStyle = self.displayStyleList[self.displayStyleIndex]
self.app.displayMaterialTheme = self.displayMaterialThemeList[self.displayMaterialThemeIndex]
self.app.displayMaterialVariant = self.displayMaterialVariantList[self.displayMaterialVariantIndex]
self.modified = False

View File

@ -94,6 +94,37 @@ Dialog {
checked: d.displayMultisampling
onToggled: d.displayMultisampling = checked;
}
Label {
text: "Style"
}
ComboBox {
model: d.displayStyleList
currentIndex: d.displayStyleIndex
onActivated: d.displayStyleIndex = currentIndex;
}
Label {
visible: d.displayStyleList[d.displayStyleIndex] == "Material"
text: "Theme"
}
ComboBox {
visible: d.displayStyleList[d.displayStyleIndex] == "Material"
model: d.displayMaterialThemeList
currentIndex: d.displayMaterialThemeIndex
onActivated: d.displayMaterialThemeIndex = currentIndex;
}
Label {
visible: d.displayStyleList[d.displayStyleIndex] == "Material"
text: "Variant"
}
ComboBox {
visible: d.displayStyleList[d.displayStyleIndex] == "Material"
model: d.displayMaterialVariantList
currentIndex: d.displayMaterialVariantIndex
onActivated: d.displayMaterialVariantIndex = currentIndex;
}
}
}
}

View File

@ -0,0 +1,41 @@
/*
* @begin:license
*
* Copyright (c) 2015-2021, Ben Niemann <pink@odahoda.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* @end:license
*/
#include <vector>
#include <string>
#include <QStringList>
#include <QQuickStyle>
namespace noisicaa::ui {
// QtQuickControls2.QQuickStyle is not available in PySide2
std::vector<std::string> c_availableQuickStyles() {
std::vector<std::string> result;
QStringList styles = QQuickStyle::availableStyles();
for (auto i = styles.constBegin(); i < styles.constEnd(); ++i) {
result.emplace_back(i->toLocal8Bit().constData());
}
return result;
}
}

View File

@ -0,0 +1,30 @@
/*
* @begin:license
*
* Copyright (c) 2015-2021, Ben Niemann <pink@odahoda.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* @end:license
*/
#include <vector>
#include <string>
namespace noisicaa::ui {
std::vector<std::string> c_availableQuickStyles();
}

View File

@ -0,0 +1,30 @@
# @begin:license
#
# Copyright (c) 2015-2019, Benjamin Niemann <pink@odahoda.de>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# @end:license
from libcpp.string cimport string
from libcpp.vector cimport vector
cdef extern from "noisicaa/ui/qt_helper.h" namespace "noisicaa::ui" nogil:
vector[string] c_availableQuickStyles()
def availableQuickStyles():
cdef vector[string] styles = c_availableQuickStyles()
return [s.decode('utf-8') for s in styles]

View File

@ -22,7 +22,18 @@ from waflib.Tools import qt5
def build(ctx):
ctx.shlib(
features='qt5 cxx cxxshlib',
uselib='QT5CORE QT5GUI QT5QUICK QT5QUICKCONTROLS2',
source=['qt_helper.cpp'],
# moc = [
# 'beziercurve.h',
# ],
target = 'noisicaa-ui-qt_helper',
)
ctx.py_module('__init__.py')
ctx.cy_module('qt_helper.pyx', use=['noisicaa-ui-qt_helper'])
ctx.py_module('main.py')
ctx.py_module('ui_base.py')
ctx.py_module('project.py')

View File

@ -82,7 +82,7 @@ def configure(ctx):
raise ConfigurationError("--with-coverage requires --with-tests")
ctx.load('compiler_cxx')
ctx.qt5_vars = ['Qt5Core', 'Qt5Gui', 'Qt5Widgets', 'Qt5Svg', 'Qt5Quick', 'Qt5Qml'];
ctx.qt5_vars = ['Qt5Core', 'Qt5Gui', 'Qt5Widgets', 'Qt5Svg', 'Qt5Quick', 'Qt5QuickControls2', 'Qt5Qml'];
ctx.load('qt5')
ctx.load('python')
ctx.load('build_utils.waf.local_rpath', tooldir='.')