88from activity_browser .ui import widgets
99
1010
11- class MainWindow (QtWidgets .QMainWindow ):
12- _instance = None
13-
14- def __new__ (cls ):
15- if cls ._instance is None :
16- cls ._instance = super ().__new__ (cls )
17- cls ._instance ._initialized = False
18- return cls ._instance
19-
11+ class MainWindow (widgets .ABMainWindow ):
2012
2113 def __init__ (self , parent = None ):
2214 from activity_browser .app .menu_bar import MenuBar
23-
24- if self ._initialized :
25- return
26- self ._initialized = True
27-
2815 super ().__init__ (parent )
2916
30- self .setLocale (QtCore .QLocale (QtCore .QLocale .English , QtCore .QLocale .UnitedStates ))
3117 self .setWindowTitle ("Activity Browser" )
32- self .setDockNestingEnabled (True )
3318
3419 # Layout: extra items outside main layout
3520 self .menu_bar = MenuBar (self )
3621 self .setMenuBar (self .menu_bar )
3722
38- self .central_widget = widgets .CentralTabWidget (self )
39- self .central_widget .setTabsClosable (True )
23+ self .central_widget = widgets .ABCentralPagesWidget (self )
4024 self .setCentralWidget (self .central_widget )
41-
42- # Initialize all base pages upfront (name -> widget instance)
43- self .base_pages = {}
25+
4426 for page_name , page_class in app .pages .base_pages .items ():
45- page_instance = page_class ()
46- page_instance .setObjectName (page_name )
47- self .base_pages [page_name ] = page_instance
48-
49- # Connect tab close signal
50- self .central_widget .tabCloseRequested .connect (self ._on_tab_close_requested )
27+ page_instance = page_class (parent = self .central_widget )
28+ self .central_widget .addPage (page_instance )
29+ self .menu_bar .view_menu .addAction (page_instance .toggleViewAction ())
30+
31+ self .menu_bar .view_menu .addSeparator ()
5132
5233 self .connect_signals ()
53- self .destroyed .connect (lambda : logger .warning ("MainWindow destroyed" ))
5434
55- def event (self , event ):
56- if event .type () == QtCore .QEvent .Type .DeferredDelete :
57- for page in self .base_pages .values ():
58- logger .debug (f"Destroying base page { page .__class__ .__name__ } : { id (page )} " )
59- try :
60- page .deleteLater ()
61- except RuntimeError :
62- # page already deleted
63- pass
64- return super ().event (event )
35+ def connect_signals (self ):
36+ app .signals .project .changed .connect (self .sync )
37+ app .signals .settings .changed .connect (self .apply_settings )
6538
6639 def sync (self ):
6740 logger .log ("SYNC" , f"{ self .__class__ .__name__ } : { id (self )} " )
6841 self .sync_panes ()
6942 self .sync_pages ()
7043
7144 self .setWindowTitle (f"Activity Browser - { bd .projects .current } " )
45+ self .central_widget .setCurrentIndex (0 )
7246
7347 def sync_panes (self ):
7448 self .clearPanes ()
7549
76- dws = []
77-
78- # Iterate through the default panes and add them as dock widgets
50+ # Iterate through the base panes and add them
51+ panes = []
7952 for pane_name , pane_class in app .panes .base_panes .items ():
8053 pane = pane_class (parent = self )
81- dockwidget = pane . getDockWidget ( self )
82- dws . append ( dockwidget )
54+ panes . append ( pane )
55+ self . addPane ( pane )
8356
84- # Add the dock widget to the left dock area
85- self .addDockWidget (QtCore .Qt .LeftDockWidgetArea , dockwidget )
86- # Add the toggle view action to the menu bar
87- self .menu_bar .view_menu .addAction (dockwidget .toggleViewAction ())
57+ self .menu_bar .view_menu .addAction (pane .toggleViewAction ())
8858
8959 # Hide the dock widget if it is marked as hidden
9060 if pane_name not in app .settings ["startup" ]["shown_panes" ]:
91- dockwidget .hide ()
92-
93- # Synchronize the pane
94- pane .sync ()
61+ pane .hide ()
9562
9663 # Tabify the dock widgets for better organization
64+ dws = [pane .getDockWidget () for pane in panes ]
9765 for dw in dws :
9866 if dw == dws [0 ]:
9967 continue
@@ -105,118 +73,23 @@ def sync_panes(self):
10573 def sync_pages (self ):
10674 """
10775 Synchronizes the central widget pages with the shown_pages setting.
108-
76+
10977 This method shows only those pages that are configured to be shown at startup.
11078 Pages are pre-initialized and just added/removed from tabs.
11179 """
11280 # Get shown pages from settings
11381 shown_pages = app .settings ["startup" ].get ("shown_pages" , [])
114-
82+
11583 # Remove all pages from tabs first
116- while self .central_widget .count () > 0 :
117- self .central_widget .removeTab (0 )
118-
84+ for i in range ( self .central_widget .count ()) :
85+ self .central_widget .closeTab (0 )
86+
11987 # Add only the pages that should be shown
12088 for page_name in shown_pages :
121- if page_name in self .base_pages :
122- page_instance = self .base_pages [page_name ]
123- # Base pages should show minimize button instead of close
124- self .central_widget .addTab (page_instance , page_name , show_minimize = True )
125-
126- def show_page (self , page_name : str ):
127- """
128- Show a page by adding it to the tabs.
129-
130- Args:
131- page_name: The name of the page to show
132- """
133- if page_name not in self .base_pages :
134- return
135-
136- page_widget = self .base_pages [page_name ]
137-
138- # Check if page is already in tabs
139- index = self .central_widget .indexOf (page_widget )
140- if index >= 0 :
141- # Already shown, just switch to it
142- self .central_widget .setCurrentIndex (index )
143- else :
144- # Add to tabs with minimize button
145- self .central_widget .addTab (page_widget , page_name , show_minimize = True )
146- self .central_widget .setCurrentWidget (page_widget )
147-
148- def hide_page (self , page_name : str ):
149- """
150- Hide a page by removing it from the tabs (but not destroying it).
151-
152- Args:
153- page_name: The name of the page to hide
154- """
155- if page_name not in self .base_pages :
156- return
157-
158- page_widget = self .base_pages [page_name ]
159- index = self .central_widget .indexOf (page_widget )
160- if index >= 0 :
161- self .central_widget .removeTab (index )
162-
163- def toggle_page (self , page_name : str ):
164- """
165- Toggle a page shown/hidden.
166-
167- Args:
168- page_name: The name of the page to toggle
169- """
170- if page_name not in self .base_pages :
171- return
172-
173- page_widget = self .base_pages [page_name ]
174- index = self .central_widget .indexOf (page_widget )
175-
176- if index >= 0 :
177- # Page is shown, hide it
178- self .hide_page (page_name )
179- else :
180- # Page is hidden, show it
181- self .show_page (page_name )
182-
183- def is_page_visible (self , page_name : str ) -> bool :
184- """
185- Check if a page is currently visible in the tabs.
186-
187- Args:
188- page_name: The name of the page to check
189-
190- Returns:
191- bool: True if the page is visible, False otherwise
192- """
193- if page_name not in self .base_pages :
194- return False
195-
196- page_widget = self .base_pages [page_name ]
197- return self .central_widget .indexOf (page_widget ) >= 0
198-
199- def _on_tab_close_requested (self , index : int ):
200- """
201- Handle when user clicks the close button on a tab.
202- For base pages, we just hide them instead of destroying them.
203-
204- Args:
205- index: The index of the tab to close
206- """
207- widget = self .central_widget .widget (index )
208- if widget is None :
209- return
210-
211- # Check if this is a base page
212- page_name = widget .objectName ()
213- if page_name in self .base_pages :
214- # Just remove from tabs, don't destroy
215- self .central_widget .removeTab (index )
216- else :
217- # For non-base pages, remove and destroy
218- self .central_widget .removeTab (index )
219- widget .deleteLater ()
89+ if page_name in app .pages .base_pages :
90+ page = self .findChild (app .pages .base_pages [page_name ])
91+ if page :
92+ self .central_widget .addPage (page )
22093
22194 def apply_settings (self , load = False ):
22295
@@ -243,35 +116,15 @@ def apply_settings(self, load=False):
243116 # apply pane tab position
244117 position = app .settings ["appearance" ]["pane_tab_position" ]
245118 if position == "top" :
246- qt_position = QtWidgets .QTabWidget .North
119+ qt_position = QtWidgets .QTabWidget .TabPosition . North
247120 if position == "bottom" :
248- qt_position = QtWidgets .QTabWidget .South
121+ qt_position = QtWidgets .QTabWidget .TabPosition . South
249122 if position == "left" :
250- qt_position = QtWidgets .QTabWidget .West
123+ qt_position = QtWidgets .QTabWidget .TabPosition . West
251124 if position == "right" :
252- qt_position = QtWidgets .QTabWidget .East
125+ qt_position = QtWidgets .QTabWidget .TabPosition . East
253126 self .setTabPosition (QtCore .Qt .DockWidgetArea .AllDockWidgetAreas , qt_position )
254127
255- def connect_signals (self ):
256- app .signals .project .changed .connect (self .sync )
257- app .signals .settings .changed .connect (self .apply_settings )
258-
259- def clearPanes (self ):
260- for pane in self .panes ():
261- logger .debug (f"Clearing pane { pane .__class__ .__name__ } : { id (pane )} " )
262- pane .deleteLater ()
263-
264- def panes (self ):
265- """
266- Return a list of all panes in the main window.
267- """
268- from activity_browser .ui import widgets
269- QtWidgets .QApplication .processEvents ()
270- return self .findChildren (widgets .ABAbstractPane )
271-
272- def set_titlebar (self ):
273- self .setWindowTitle (f"Activity Browser - { bd .projects .current } " )
274-
275128 def dialog_on_exception (self , exception : Exception ):
276129 QtWidgets .QMessageBox .critical (
277130 self ,
0 commit comments