2929from PyQt5 import QtCore , QtWidgets
3030# specifically import from PyQt5.QtGui and QWidgets for startup time improvement :
3131from PyQt5 .QtWidgets import QMainWindow , QHBoxLayout , QVBoxLayout , QApplication , QSplashScreen
32- from PyQt5 .QtGui import QPixmap
33- from PyQt5 .QtQml import QQmlEngine , qmlRegisterSingletonType , qmlRegisterType
32+ from PyQt5 .QtGui import QPixmap , QFontDatabase
33+ from PyQt5 .QtQml import QQmlEngine , qmlRegisterSingletonType , qmlRegisterType , QQmlComponent
3434from PyQt5 .QtQuickWidgets import QQuickWidget
3535from PyQt5 .QtCore import QObject
3636
3939# importing friture.exceptionhandler also installs a temporary exception hook
4040from friture .exceptionhandler import errorBox , fileexcepthook
4141import friture
42+ from friture .playback .playback_control_view_model import PlaybackControlViewModel
4243from friture .ui_friture import Ui_MainWindow
4344from friture .about import About_Dialog # About dialog
4445from friture .settings import Settings_Dialog # Setting dialog
4546from friture .audiobuffer import AudioBuffer # audio ring buffer class
4647from friture .audiobackend import AudioBackend # audio backend class
4748from friture .dockmanager import DockManager
48- from friture .tileLayout import TileLayout
49+ from friture .tilelayout import TileLayout
4950from friture .level_view_model import LevelViewModel
5051from friture .level_data import LevelData
5152from friture .levels import Levels_Widget
53+ from friture .main_window_view_model import MainWindowViewModel
5254from friture .store import GetStore , Store
5355from friture .scope_data import Scope_Data
5456from friture .axis import Axis
6466from friture .spectrum_data import Spectrum_Data
6567from friture .plotFilledCurve import PlotFilledCurve
6668from friture .filled_curve import FilledCurve
67- from friture .qml_tools import qml_url , raise_if_error
69+ from friture .qml_tools import qml_url , raise_if_error , component_raise_if_error
6870from friture .generators .sine import Sine_Generator_Settings_View_Model
6971from friture .generators .white import White_Generator_Settings_View_Model
7072from friture .generators .pink import Pink_Generator_Settings_View_Model
@@ -109,6 +111,8 @@ def __init__(self):
109111 qmlRegisterType (Spectrum_Data , 'Friture' , 1 , 0 , 'SpectrumData' )
110112 qmlRegisterType (LevelData , 'Friture' , 1 , 0 , 'LevelData' )
111113 qmlRegisterType (LevelViewModel , 'Friture' , 1 , 0 , 'LevelViewModel' )
114+ qmlRegisterType (PlaybackControlViewModel , 'Friture' , 1 , 0 , 'PlaybackControlViewModel' )
115+ qmlRegisterType (MainWindowViewModel , 'Friture' , 1 , 0 , 'MainWindowViewModel' )
112116 qmlRegisterType (Axis , 'Friture' , 1 , 0 , 'Axis' )
113117 qmlRegisterType (Curve , 'Friture' , 1 , 0 , 'Curve' )
114118 qmlRegisterType (FilledCurve , 'Friture' , 1 , 0 , 'FilledCurve' )
@@ -152,36 +156,44 @@ def __init__(self):
152156 self .about_dialog = About_Dialog (self , self .slow_timer )
153157 self .settings_dialog = Settings_Dialog (self )
154158
155- self .level_widget = Levels_Widget (self , self .qml_engine )
156- self .level_widget .set_buffer (self .audiobuffer )
157- self .audiobuffer .new_data_available .connect (self .level_widget .handle_new_data )
158-
159- self .hboxLayout = QHBoxLayout (self .ui .centralwidget )
160- self .hboxLayout .setContentsMargins (0 , 0 , 0 , 0 )
161- self .hboxLayout .addWidget (self .level_widget )
162-
163- self .vboxLayout = QVBoxLayout ()
164- self .hboxLayout .addLayout (self .vboxLayout )
165-
166159 self .centralQuickWidget = QQuickWidget (self .qml_engine , self )
167160 self .centralQuickWidget .setObjectName ("centralQuickWidget" )
168161 self .centralQuickWidget .setSizePolicy (QtWidgets .QSizePolicy .Expanding , QtWidgets .QSizePolicy .Expanding )
169162 self .centralQuickWidget .setResizeMode (QQuickWidget .SizeRootObjectToView )
170- self .centralQuickWidget .setSource (qml_url ("CentralWidget.qml" ))
171- self .vboxLayout .addWidget (self .centralQuickWidget )
163+ self .centralQuickWidget .setSource (qml_url ("FritureHost.qml" ))
172164
173165 raise_if_error (self .centralQuickWidget )
174166
175- central_widget_root = self .centralQuickWidget .rootObject ()
176- self .main_grid_layout = central_widget_root .findChild (QObject , "main_tile_layout" )
177- assert self .main_grid_layout is not None , "Main grid layout not found in CentralWidget.qml"
167+ self .hboxLayout = QHBoxLayout (self .ui .centralwidget )
168+ self .hboxLayout .setContentsMargins (0 , 0 , 0 , 0 )
169+ self .hboxLayout .addWidget (self .centralQuickWidget )
170+
171+ qml_component = QQmlComponent (self .qml_engine )
172+ qml_component .loadUrl (qml_url ("MainWindow.qml" ))
173+ component_raise_if_error (qml_component )
174+
175+ self ._main_window_view_model = MainWindowViewModel (self .qml_engine )
176+
177+ context = self .qml_engine .rootContext ()
178+ central_widget_root = qml_component .createWithInitialProperties (
179+ {
180+ "main_window_view_model" : self ._main_window_view_model ,
181+ "fixedFont" : QFontDatabase .systemFont (QFontDatabase .FixedFont ).family ()
182+ },
183+ context ) # type: ignore
184+ central_widget_root .setParent (self .qml_engine )
185+ central_widget_root .setParentItem (self .centralQuickWidget .rootObject ()) # type: ignore
186+
187+ self .main_tile_layout = central_widget_root .findChild (QObject , "main_tile_layout" )
188+ assert self .main_tile_layout is not None , "Main tile layout not found in CentralWidget.qml"
189+
190+ self .level_widget = Levels_Widget (self , self ._main_window_view_model .level_view_model )
191+ self .level_widget .set_buffer (self .audiobuffer )
192+ self .audiobuffer .new_data_available .connect (self .level_widget .handle_new_data )
178193
179- self .playback_widget = PlaybackControlWidget (
180- self , self .qml_engine , self .player )
181- self .playback_widget .setVisible (self .settings_dialog .show_playback )
182- self .vboxLayout .addWidget (self .playback_widget )
194+ self .playback_widget = PlaybackControlWidget (self , self .player , self ._main_window_view_model .playback_control_view_model )
183195
184- self .dockmanager = DockManager (self , self .main_grid_layout )
196+ self .dockmanager = DockManager (self , self .main_tile_layout )
185197
186198 # timer ticks
187199 self .display_timer .timeout .connect (self .dockmanager .canvasUpdate )
@@ -193,7 +205,7 @@ def __init__(self):
193205 self .ui .actionSettings .triggered .connect (self .settings_called )
194206 self .ui .actionAbout .triggered .connect (self .about_called )
195207 self .ui .actionNew_dock .triggered .connect (self .dockmanager .new_dock )
196- self .playback_widget .recording_toggled .connect (self .timer_toggle )
208+ self .playback_widget .recording_toggled .connect (self .timer_changed )
197209
198210 # settings changes
199211 self .settings_dialog .show_playback_changed .connect (self .show_playback_changed )
@@ -237,7 +249,7 @@ def settings_called(self):
237249 self .settings_dialog .show ()
238250
239251 def show_playback_changed (self , show : bool ) -> None :
240- self .playback_widget . setVisible ( show )
252+ self ._main_window_view_model . playback_control_enabled = show
241253
242254 # slot
243255 def about_called (self ):
@@ -341,6 +353,23 @@ def timer_toggle(self):
341353 AudioBackend ().restart ()
342354 self .dockmanager .restart ()
343355
356+ # slot
357+ def timer_changed (self , recording : bool ):
358+ if not recording and self .display_timer .isActive ():
359+ self .logger .info ("Timer stop" )
360+ self .display_timer .stop ()
361+ self .ui .actionStart .setText ("Start" )
362+ self .playback_widget .stop_recording ()
363+ AudioBackend ().pause ()
364+ self .dockmanager .pause ()
365+
366+ if recording and not self .display_timer .isActive ():
367+ self .logger .info ("Timer start" )
368+ self .display_timer .start ()
369+ self .ui .actionStart .setText ("Stop" )
370+ self .playback_widget .start_recording ()
371+ AudioBackend ().restart ()
372+ self .dockmanager .restart ()
344373
345374def qt_message_handler (mode , context , message ):
346375 logger = logging .getLogger (__name__ )
0 commit comments