Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,11 @@ Notepad++
.mypy_cache

# Macos
.DS_Store
.DS_Store

# UV
.venv/

# Temporary test scripts
test_*.py
test_*.qml
13 changes: 7 additions & 6 deletions friture/ControlBar.qml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ RowLayout {
objectName: "controlBar"
spacing: 0

SystemPalette { id: systemPalette; colorGroup: SystemPalette.Active }

required property var viewModel
required property var main_window_view_model

readonly property color iconColor: main_window_view_model.window_text_color

ComboBox {
id: widgetSelector
Expand Down Expand Up @@ -37,31 +38,31 @@ RowLayout {
id: settingsButton
icon.source: "qrc:/images-src/dock-settings.svg"
ToolTip.text: "Customize the audio widget"
icon.color: systemPalette.windowText
icon.color: controlBar.iconColor
onClicked: viewModel.onSettingsClicked()
}

ToolButton {
id: movePreviousButton
icon.source: "qrc:/images-src/dock-move-previous.svg"
ToolTip.text: "Move widget to previous slot"
icon.color: systemPalette.windowText
icon.color: controlBar.iconColor
onClicked: viewModel.onMovePreviousClicked()
}

ToolButton {
id: moveNextButton
icon.source: "qrc:/images-src/dock-move-next.svg"
ToolTip.text: "Move widget to next slot"
icon.color: systemPalette.windowText
icon.color: controlBar.iconColor
onClicked: viewModel.onMoveNextClicked()
}

ToolButton {
id: closeButton
icon.source: "qrc:/images-src/dock-close.svg"
ToolTip.text: "Close the audio widget"
icon.color: systemPalette.windowText
icon.color: controlBar.iconColor
onClicked: viewModel.onCloseClicked()
}

Expand Down
7 changes: 4 additions & 3 deletions friture/Dock.qml
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.2
import Friture 1.0

Rectangle {
SystemPalette { id: systemPalette; colorGroup: SystemPalette.Active }
color: systemPalette.window
required property MainWindowViewModel main_window_view_model

color: main_window_view_model.window_color

property string fixedFont

Expand All @@ -28,4 +30,3 @@ Rectangle {
}
}
}

14 changes: 12 additions & 2 deletions friture/FritureMainWindow.qml
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,26 @@ import QtQuick.Controls 2.15
import QtQuick.Layouts 1.2
import Friture 1.0

Rectangle { // eventually move to ApplicationWindow
Control { // eventually move to ApplicationWindow
id: mainWindow
anchors.fill: parent

// Explicitly bind the Qt Quick Controls 2 palette to the actual Python QApplication palette!
// This perfectly fixes Light/Dark theme rendering and native hover states without custom hardcoded colors.
palette.window: main_window_view_model.window_color
palette.windowText: main_window_view_model.window_text_color
palette.base: main_window_view_model.base_color
palette.text: main_window_view_model.text_color
palette.button: main_window_view_model.button_color
palette.buttonText: main_window_view_model.button_text_color

// title: qsTr("Friture") // ApplicationWindow
// icon.source: "qrc:/images-src/window-icon.svg" // ApplicationWindow

required property MainWindowViewModel main_window_view_model
required property string fixedFont

ColumnLayout { // remove once we use ApplicationWindow
contentItem: ColumnLayout { // remove once we use ApplicationWindow
anchors.fill: parent
spacing: 0

Expand Down
43 changes: 42 additions & 1 deletion friture/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
from PyQt5 import QtCore
# specifically import from PyQt5.QtGui and QWidgets for startup time improvement :
from PyQt5.QtWidgets import QMainWindow, QApplication, QSplashScreen, QWidget
from PyQt5.QtGui import QPixmap, QFontDatabase
from PyQt5.QtGui import QPixmap, QFontDatabase, QPalette, QColor
from PyQt5.QtQml import QQmlEngine, qmlRegisterSingletonType, qmlRegisterType
from PyQt5.QtCore import QObject
from PyQt5.QtQuick import QQuickView
Expand Down Expand Up @@ -83,6 +83,35 @@
# (and text painting is costly)
SLOW_TIMER_PERIOD_MS = 1000

def apply_theme(app: QApplication, theme_index: int):
if theme_index == 2: # Dark
app.setStyle("Fusion")
dark_palette = QPalette()
dark_palette.setColor(QPalette.Window, QColor(53, 53, 53))
dark_palette.setColor(QPalette.WindowText, QtCore.Qt.white)
dark_palette.setColor(QPalette.Base, QColor(25, 25, 25))
dark_palette.setColor(QPalette.AlternateBase, QColor(53, 53, 53))
dark_palette.setColor(QPalette.ToolTipBase, QtCore.Qt.white)
dark_palette.setColor(QPalette.ToolTipText, QtCore.Qt.white)
dark_palette.setColor(QPalette.Text, QtCore.Qt.white)
dark_palette.setColor(QPalette.Button, QColor(53, 53, 53))
dark_palette.setColor(QPalette.ButtonText, QtCore.Qt.white)
dark_palette.setColor(QPalette.BrightText, QtCore.Qt.red)
dark_palette.setColor(QPalette.Link, QColor(42, 130, 218))
dark_palette.setColor(QPalette.Highlight, QColor(42, 130, 218))
dark_palette.setColor(QPalette.HighlightedText, QtCore.Qt.black)
app.setPalette(dark_palette)
if hasattr(app, 'paletteChanged'):
app.paletteChanged.emit(dark_palette)
elif theme_index == 1: # Light
app.setStyle("Fusion")
app.setPalette(app.style().standardPalette())
if hasattr(app, 'paletteChanged'):
app.paletteChanged.emit(app.style().standardPalette())
else: # System Default
app.setPalette(app.style().standardPalette())
if hasattr(app, 'paletteChanged'):
app.paletteChanged.emit(app.style().standardPalette())

class Friture(QMainWindow, ):

Expand Down Expand Up @@ -162,6 +191,7 @@ def __init__(self):

self.quick_view = QQuickView(self.qml_engine, None)
self.quick_view.setResizeMode(QQuickView.SizeRootObjectToView)
self.quick_view.setColor(QApplication.instance().palette().window().color())
self.quick_view.setInitialProperties({
"main_window_view_model": self._main_window_view_model,
"fixedFont": QFontDatabase.systemFont(QFontDatabase.FixedFont).family()
Expand Down Expand Up @@ -199,6 +229,7 @@ def __init__(self):
# settings changes
self.settings_dialog.show_playback_changed.connect(self.show_playback_changed)
self.settings_dialog.history_length_changed.connect(self.player.set_history_seconds)
self.settings_dialog.theme_changed.connect(self.theme_changed)

# restore the settings and widgets geometries
self.restoreAppState()
Expand Down Expand Up @@ -231,6 +262,12 @@ def settings_called(self):
def show_playback_changed(self, show: bool) -> None:
self._main_window_view_model.playback_control_enabled = show

def theme_changed(self, theme_index: int) -> None:
app = QApplication.instance()
apply_theme(app, theme_index)
self.quick_view.setColor(app.palette().window().color())
self._main_window_view_model.theme_index = theme_index

# slot
def about_called(self):
self.about_dialog.show()
Expand Down Expand Up @@ -483,6 +520,10 @@ def main():
if "QT_QUICK_CONTROLS_STYLE" not in os.environ:
os.environ["QT_QUICK_CONTROLS_STYLE"] = "Fusion"

settings = QtCore.QSettings("Friture", "Friture")
theme_index = settings.value("AudioBackend/theme", 0, type=int)
apply_theme(app, theme_index)

# Splash screen
if not program_arguments.no_splash:
pixmap = QPixmap(":/images/splash.png")
Expand Down
10 changes: 8 additions & 2 deletions friture/dock.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ def __init__(

self.dockmanager: 'DockManager' = parent.dockmanager
self.audiobuffer = parent.audiobuffer
self._main_window_view_model = parent._main_window_view_model

self.setObjectName(name)

Expand All @@ -67,11 +68,16 @@ def __init__(
component_raise_if_error(dock_component)

context = self.qml_engine.rootContext()
self.dock_qml = dock_component.createWithInitialProperties({}, context)
self.dock_qml = dock_component.createWithInitialProperties(
{"main_window_view_model": self._main_window_view_model}, context
)
self.dock_qml.setParent(self.qml_engine)
self.dock_qml.setParentItem(self.parent().main_tile_layout) # type: ignore

initialProperties = {"viewModel": self.controlbar_viewmodel}
initialProperties = {
"viewModel": self.controlbar_viewmodel,
"main_window_view_model": self._main_window_view_model
}
component = QQmlComponent(self.qml_engine)
component.loadUrl(qml_url("ControlBar.qml"))

Expand Down
10 changes: 8 additions & 2 deletions friture/filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,14 @@ def octave_filter_bank(forward, feedback, x, zis=None):
# filter for the octave


def octave_filter_bank_decimation(blow, alow, forward, feedback, x, zis):
def octave_filter_bank_decimation(blow, alow, forward, feedback, x, zis=None):
# This function filters the waveform x with the array of filters
# specified by the forward and feedback parameters. Each row
# of the forward and feedback parameters are the parameters
# to the Matlab builtin function "filter".
if zis is None:
zis = octave_filter_bank_decimation_filtic(blow, alow, forward, feedback)

bands_per_octave = len(forward)
filter_count = NOCTAVE * bands_per_octave

Expand All @@ -102,7 +105,10 @@ def octave_filter_bank_decimation(blow, alow, forward, feedback, x, zis):

for j in range(0, NOCTAVE):
for i in range(0, bands_per_octave)[::-1]:
filt, zf = pyx_lfilter_float64_1D(forward[i], feedback[i], x_dec, zis[m])
filt, zf = pyx_lfilter_float64_1D(array(forward[i], dtype='float64'),
array(feedback[i], dtype='float64'),
array(x_dec, dtype='float64'),
array(zis[m], dtype='float64'))
m += 1
# zf can be reused to restart the filter
zfs += [zf]
Expand Down
2 changes: 1 addition & 1 deletion friture/filter_design.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ def main():
low_freq = 20.

impulse = zeros(N)
impulse[N / 2] = 1
impulse[N // 2] = 1
f = 1000.
# impulse = sin(2*pi*f*arange(0, N/fs, 1./fs))

Expand Down
36 changes: 18 additions & 18 deletions friture/friture_rc.py
Original file line number Diff line number Diff line change
Expand Up @@ -14624,41 +14624,41 @@
\x00\x00\x00\x12\x00\x02\x00\x00\x00\x11\x00\x00\x00\x03\
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x2c\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
\x00\x00\x01\x98\x66\x36\x95\x94\
\x00\x00\x01\x9e\x98\x3f\x1d\x11\
\x00\x00\x00\x4c\x00\x01\x00\x00\x00\x01\x00\x00\x0b\xac\
\x00\x00\x01\x98\x66\x36\x95\x94\
\x00\x00\x01\x9e\x98\x3f\x1d\x15\
\x00\x00\x00\x70\x00\x00\x00\x00\x00\x01\x00\x00\x1b\x93\
\x00\x00\x01\x98\x66\x36\x95\x94\
\x00\x00\x01\x9e\x98\x3f\x1d\x15\
\x00\x00\x00\x84\x00\x00\x00\x00\x00\x01\x00\x00\x2c\xa2\
\x00\x00\x01\x98\x66\x36\x95\x94\
\x00\x00\x01\x9e\x98\x3f\x1d\x15\
\x00\x00\x00\x9c\x00\x00\x00\x00\x00\x01\x00\x00\x4e\x77\
\x00\x00\x01\x98\x66\x36\x95\x94\
\x00\x00\x01\x9e\x98\x3f\x1d\x15\
\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x01\x00\x00\x5a\x27\
\x00\x00\x01\x98\x66\x36\x95\x94\
\x00\x00\x01\x9e\x98\x3f\x1d\x15\
\x00\x00\x00\xd8\x00\x00\x00\x00\x00\x01\x00\x00\x64\x42\
\x00\x00\x01\x98\x66\x36\x95\x94\
\x00\x00\x01\x9e\x98\x3f\x1d\x11\
\x00\x00\x00\xf0\x00\x00\x00\x00\x00\x01\x00\x00\x7d\xa9\
\x00\x00\x01\x98\x66\x36\x95\x94\
\x00\x00\x01\x9e\x98\x3f\x1d\x15\
\x00\x00\x01\x0e\x00\x00\x00\x00\x00\x01\x00\x00\xa1\x01\
\x00\x00\x01\x98\x76\xfb\xfd\x24\
\x00\x00\x01\x9e\x98\x3f\x1d\x11\
\x00\x00\x01\x40\x00\x01\x00\x00\x00\x01\x00\x00\xa9\x50\
\x00\x00\x01\x98\x66\x36\x95\x94\
\x00\x00\x01\x9e\x98\x3f\x1d\x15\
\x00\x00\x01\x58\x00\x00\x00\x00\x00\x01\x00\x00\xb3\x7f\
\x00\x00\x01\x98\x66\x36\x95\x94\
\x00\x00\x01\x9e\x98\x3f\x1d\x15\
\x00\x00\x01\x7a\x00\x00\x00\x00\x00\x01\x00\x00\xe1\xf1\
\x00\x00\x01\x98\x66\x36\x95\x94\
\x00\x00\x01\x9e\x98\x3f\x1d\x15\
\x00\x00\x01\x98\x00\x01\x00\x00\x00\x01\x00\x01\x06\xa0\
\x00\x00\x01\x98\x66\x36\x95\x94\
\x00\x00\x01\x9e\x98\x3f\x1d\x15\
\x00\x00\x01\xae\x00\x01\x00\x00\x00\x01\x00\x01\x12\xd4\
\x00\x00\x01\x98\x66\x36\x95\x94\
\x00\x00\x01\x9e\x98\x3f\x1d\x15\
\x00\x00\x01\xc8\x00\x00\x00\x00\x00\x01\x00\x01\x18\x43\
\x00\x00\x01\x98\x66\x36\x95\x94\
\x00\x00\x01\x9e\x98\x3f\x1d\x15\
\x00\x00\x01\xf0\x00\x00\x00\x00\x00\x01\x00\x01\x34\xba\
\x00\x00\x01\x98\x66\x36\x95\x94\
\x00\x00\x01\x9e\x98\x3f\x1d\x11\
\x00\x00\x02\x12\x00\x00\x00\x00\x00\x01\x00\x01\x3f\x5a\
\x00\x00\x01\x98\x76\xfb\xfd\x24\
\x00\x00\x01\x9e\x98\x3f\x1d\x11\
\x00\x00\x02\x3c\x00\x00\x00\x00\x00\x01\x00\x01\x47\xa9\
\x00\x00\x01\x98\x66\x36\x95\x98\
\x00\x00\x01\x9e\x98\x3f\x1d\x1d\
"

qt_version = [int(v) for v in QtCore.qVersion().split('.')]
Expand Down
Loading