Window.py PySide6 Custom QMainWindow — Frameless Window with Animated Panels

Window.py defines the AbdhWindow class, a fully customized QMainWindow subclass for the PySideAbdhUI framework. It provides a frameless window with a hand-crafted titlebar, collapsible left and right side-panel systems, smooth property-based animations for all transitions, and a manual edge/corner resize implementation that replaces the broken QSizeGrip approach commonly used in Qt frameless windows. The entire module is designed to serve as the top-level application shell into which other framework components (pages, navigation, widgets) are plugged.

The key design philosophy behind AbdhWindow is that the window should never be auto-resized by Qt's internal layout system when child widgets change their sizeHint. To enforce this, a size-lock mechanism pins the window to its current dimensions (by setting both minimum and maximum size) and only unlocks it during user-initiated operations such as edge-drag resizing or maximize/restore animations. This eliminates the common problem of the window growing uncontrollably when a tree widget or other dynamic content expands.

Architecture & Layout

The window uses a QGridLayout with a 2-row × 3-column structure. This grid layout is the foundation for positioning the titlebar, side panels, and the main content area. Every widget is placed at a specific cell in the grid, and column stretch factors control how extra horizontal space is distributed. The following diagram illustrates the layout:

+-------+------------------------+---------+ | [0,0] | [0,1] | [0,2] | | | | | | Left | Titlebar | Right | | Panel | (spans cols 0-2) | Panel | | (rows | | (rows | | 0-1) |------------------------| 0-1) | | | [1,1] | | | | | | | | Stacked Widget | | | | (Main Content Area) | | | | (col stretch = 1) | | +-------+------------------------+---------+ Column 0: Left panel — fixed width, no stretch Column 1: Content area — expanding, stretch = 1 Column 2: Right panel — variable width, no stretch

The titlebar spans all three columns in row 0. The left panel occupies column 0 across both rows. The right panel occupies column 2 across both rows. The central stacked widget (which hosts the application pages) sits at [1,1] and receives all extra horizontal space via setColumnStretch(1, 1). This ensures that when the window is resized, only the content area grows or shrinks, while the side panels maintain their fixed or animated widths.

Note: The titlebar is added to the grid after the other widgets but visually sits on top because QGridLayout Z-order follows insertion order — later additions are drawn on top. This ensures the titlebar overlaps the top edge of both side panels for a seamless visual appearance.

Dependencies

The module relies on the following external and internal dependencies. Understanding these imports is essential for comprehending the full functionality available to AbdhWindow:

ModuleComponents UsedPurpose
os os.path.exists Checking if a stylesheet file exists before loading it.
PySide6.QtWidgets QSizePolicy, QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QGridLayout, QPushButton, QLabel, QFrame Core widget and layout classes for building the entire UI structure.
PySide6.QtCore Qt, QPropertyAnimation, QParallelAnimationGroup, QEasingCurve, QRect, QSize, QPoint, QEvent Animation framework, geometry types, event types, and alignment/flags.
PySide6.QtGui QPainter, QBrush, QColor, QPixmap, QPainterPath, QMouseEvent, QIcon Custom painting (rounded corners), image handling, mouse event types, icons.
.Widgets StackedWidget Internal custom stacked widget with page navigation (back/forward).
.utils get_icon Internal utility for loading SVG/icon resources by name.

Class: AbdhWindow

AbdhWindow inherits from QMainWindow Inherits QMainWindow and is the primary top-level window class of the PySideAbdhUI framework. It completely replaces the native window chrome with a custom frameless implementation, providing:

Class Attributes

These constants define the visual dimensions and behavior thresholds for the window. They are class-level attributes shared across all instances of AbdhWindow:

AttributeTypeDefaultDescription
control_button_size QSize QSize(40, 32) Dimensions for the window control buttons (minimize, maximize, close) in the titlebar.
logo_size QSize QSize(32, 32) Dimensions for the application logo displayed in the top-left of the titlebar.
pane_width int 250 The full expanded width of side panels (both left and right) when they are open.
pane_min_width int 48 The collapsed width of the left panel in overlay mode — just enough to show icons.
titlebar_height int 42 Fixed height of the custom titlebar widget in pixels.
RESIZE_MARGIN int 8 Pixel distance from the window edge within which the cursor is considered to be near an edge for resizing. This defines the invisible resize grab zone.
MIN_WINDOW_WIDTH int 400 Absolute minimum width the window can be resized to. Prevents the window from becoming unusably narrow.
MIN_WINDOW_HEIGHT int 300 Absolute minimum height the window can be resized to. Ensures content remains visible.

Constructor: __init__

AbdhWindow.__init__(self) Public

Initializes the window by calling super().__init__(), then configures the frameless window appearance and sets up all internal state variables. The constructor does not build any UI widgets — that is deferred to the initUI() method.

Key initialization steps:

  1. Frameless window flag — Sets Qt.WindowType.FramelessWindowHint to remove the native window border, and Qt.WindowType.Window to ensure it is still treated as a top-level window.
  2. Translucent background — Enables WA_TranslucentBackground so the rounded-corner painting in paintEvent produces actual transparency at the corners.
  3. Golden ratio sizing — Calculates the initial window size as screen_dimension × 1.618 × 0.5, giving approximately 80.9% of the screen dimension. This creates a visually pleasing initial window size.
  4. Centered positioning — The window is positioned at the horizontal center and slightly above vertical center (70% of calculated Y) for a more natural screen placement.
  5. State initialization — All resize state, drag state, panel state, and size-lock flags are set to their default values.

Important: Calling show() before initUI() will raise a RuntimeError. The show() method is overridden to check self.initialized before proceeding.

Size Lock System

The size-lock system is a critical architectural feature that prevents Qt's layout engine from automatically growing the window when internal widgets change their size hints. This is a common problem in Qt applications where, for example, a QTreeWidget with expanding nodes pushes the window boundary outward. The solution implemented here is to lock the window to its exact current size by setting both minimumSize and maximumSize to the current dimensions. When the layout recalculates, it finds that the window cannot grow, so it reflows inside the locked boundary instead.

The system works as a state machine: the window is normally locked, and is only briefly unlocked during animations (maximize/restore, fade-in) or edge-drag resizing. After each operation completes, the window is re-locked at its new size.

_lock_size(self) Private

Locks the window to its current size by setting both minimumSize and maximumSize to the current self.size(). This is the only reliable way to prevent Qt's layout system from auto-growing the window when internal widgets change their sizeHint. The layout will reflow inside the locked window boundary instead of pushing it outward.

Also sets self._size_locked = True for tracking purposes.

_unlock_size(self) Private

Relaxes the size constraints so that user-initiated resize operations (edge drag, maximize/restore animations) can change the window size. The minimum size is set to MIN_WINDOW_WIDTH × MIN_WINDOW_HEIGHT (400×300) and the maximum size is set to QWIDGETSIZE_MAX (16777215×16777215). After the operation completes, the window must be re-locked by calling _lock_size().

_connect_lock_after_animation(self, animation: QPropertyAnimation) Private

Convenience method that connects an animation's finished signal to _lock_size, ensuring the window is automatically re-locked as soon as the animation completes. Any previous _lock_size connection on this animation is disconnected first to avoid duplicate calls, which could cause issues if the same animation object is reused.

ParameterTypeDescription
animationQPropertyAnimationThe animation whose finished signal should trigger a size lock.

UI Initialization

initUI(self, app_title: str = 'PySideAbdhUI Application', direction=Qt.LayoutDirection.LeftToRight, logo: QPixmap = None) Public

Constructs and assembles the entire window UI. This method must be called after constructing the AbdhWindow instance and before calling show(). It creates all widgets, layouts, and connections that make up the window.

ParameterTypeDefaultDescription
app_titlestr'PySideAbdhUI Application'The text displayed in the titlebar and used as the window title.
directionQt.LayoutDirectionLeftToRightThe layout direction for the main widget, supporting RTL languages.
logoQPixmapNoneAn optional logo pixmap displayed in the titlebar. If None, the logo label remains empty.

Initialization sequence:

  1. Central widget — Creates a QWidget with the CSS class window-background-layer and sets it as the central widget with zero content margins.
  2. Grid layout — Creates a QGridLayout with zero margins and zero spacing for a pixel-perfect layout.
  3. Left panel — Creates a QFrame with CSS class left-sidebar-background-layer, fixed width of pane_width (250px), and a QVBoxLayout with top margin equal to titlebar_height to avoid overlap.
  4. Right panel — Creates a QFrame with CSS class right-sidebar-background-layer, starting at zero width (collapsed by default), with a QVBoxLayout and a stretch at the bottom for flexible content placement.
  5. Toggle button — Creates the hamburger-menu toggle button that expands/collapses the left panel, and a pin button that switches between pinned and overlay modes.
  6. Stacked widget — Creates a StackedWidget (custom class from .Widgets) for hosting application pages with back/forward navigation.
  7. Titlebar — Calls _create_titlebar() to build the custom titlebar with all control buttons.
  8. Grid placement — Adds all widgets to the grid layout in the correct positions with proper alignment and span values.
  9. Column stretch — Sets column stretch factors: 0 for left panel, 1 for content, 0 for right panel.
  10. Mouse tracking — Enables mouse tracking for edge-resize cursor feedback.
  11. Animation setup — Creates the main QPropertyAnimation object for maximize/restore with OutQuad easing and 175ms duration.
  12. Event filter — Installs a global event filter on QApplication.instance() to detect clicks outside panels and manage resize cursors.

Note: After initUI() completes, self.initialized is set to True, which allows the show() method to proceed. If show() is called without initialization, a RuntimeError is raised.

show(self) Override

Overrides the default QMainWindow.show() to add an initialization guard. If initUI() has not been called yet (self.initialized is False), it raises a RuntimeError with a descriptive message. Otherwise, it calls super().show() to display the window normally.

Panel Toggling

The left panel supports two distinct modes of operation, each providing a different user experience for sidebar interaction. The right panel operates as a simple toggle (open/close). Understanding these modes is essential for correctly integrating the window into an application.

Left Panel Modes

toggle_overlay(self) Public

Toggles the left panel between pinned and overlay mode. When switching to overlay mode, the panel is removed from the grid and re-added with col-span = 2, its width is fixed to pane_min_width, and the stacked widget receives a left margin to avoid content occlusion. When switching back to pinned mode, the panel is re-added with col-span = 1 and the stacked widget's left margin is reset to 0. The pin button is hidden in overlay mode since pinning is only relevant in the expanded state.

animate_content(self, frame: QFrame, stack: StackedWidget) Public

Animates the left panel open/closed with a smooth width transition. The behavior differs depending on whether the panel is in overlay or pinned mode:

  • Overlay mode: Calls toggle_frame() for a simple width toggle between 0 and pane_width.
  • Pinned mode: Creates a QParallelAnimationGroup that simultaneously animates both minimumWidth and maximumWidth of the panel. This dual-animation approach prevents layout conflicts where Qt might auto-adjust one property while the other is being animated. The animation uses InOutQuad easing over 400ms for a natural feel.

After the animation completes, the stacked widget's width constraints are reset (minimum to 0, maximum to QWIDGETSIZE_MAX) so it can freely expand when the window is resized. The expanded flag is toggled and the pin button visibility is updated accordingly.

ParameterTypeDescription
frameQFrameThe left panel frame to animate (typically self.left_panel).
stackStackedWidgetThe stacked content widget whose constraints are reset after animation.
toggle_frame(self, sender: QFrame, min: int) Public

A generic panel toggle method that animates any QFrame between collapsed and expanded widths. If the frame's current width is less than pane_width, it animates open to pane_width; otherwise, it animates closed to the given min value. The animation uses OutCubic easing over 400ms for a smooth deceleration effect.

Before starting a new animation, any running animation on the sender is stopped to prevent conflicts. The animation object is scheduled for deletion after it finishes via deleteLater().

ParameterTypeDescription
senderQFrameThe panel frame to toggle (e.g., self.right_panel).
minintThe collapsed width to animate to. Typically 0 for the right panel or pane_min_width for the left panel.

Known Limitation: This method only animates minimumWidth, not maximumWidth. A commented-out alternative implementation that animates both properties in parallel exists in the source code but is not currently active. This can cause layout jitter if internal widgets have large size hints.

open_settings(self) Public

Convenience method that calls toggle_frame(self.right_panel, 0) to toggle the right (settings) panel open or closed. The collapsed width is 0, meaning the panel completely disappears when closed.

Animation System

AbdhWindow uses Qt's QPropertyAnimation framework extensively for smooth visual transitions. All animations are property-based, meaning they interpolate a specific Qt property of a widget over time. The following animation types are used:

Animation TypePropertyEasing CurveDurationContext
Geometry b"geometry" OutQuad 175 ms Maximize/restore transitions
Minimum width b"minimumWidth" InOutQuad 400 ms Left panel expand/collapse (pinned mode)
Maximum width b"maximumWidth" InOutQuad 400 ms Left panel expand/collapse (pinned mode, parallel)
Minimum width b"minimumWidth" OutCubic 400 ms Generic panel toggle (toggle_frame)
Window opacity b"windowOpacity" OutQuad 500 ms Fade-in on first show
Geometry b"geometry" OutQuad 500 ms Slide-in on first show (parallel with opacity)

The QParallelAnimationGroup is used in the left panel pinned-mode animation to run the minimum and maximum width animations simultaneously, preventing layout conflicts. The fade-in animation also runs opacity and geometry animations in parallel for a combined fade-and-slide effect.

animate_fadeIn(self) Private

Performs a combined fade-in and slide-in animation when the window is shown for the first time. Two animations run in parallel:

  • Opacity animation: Transitions windowOpacity from 0.0 to 1.0 over 500ms with OutQuad easing, creating a smooth fade-in from transparent to fully opaque.
  • Geometry animation: Starts the window 50 pixels above its final position and slides it down to the target geometry over 500ms with OutQuad easing, creating a subtle slide-in effect.

Before starting, the size lock is unlocked so the geometry animation can move the window. After the geometry animation finishes, the size is re-locked via _connect_lock_after_animation(). This method is called from showEvent() only when self.first_show is True.

Maximize / Restore

The maximize/restore system provides animated full-screen and windowed transitions without using the native window manager's maximize function. This is necessary because the window is frameless and the native maximize behavior would not respect the custom rounded corners and layout. The system stores the "original" (pre-maximize) geometry and animates between it and the full available screen geometry.

toggle_maximize_restore(self) Public

Toggles between maximized and restored states. If currently maximized, it calls animate_restore() and changes the maximize button icon to a single square. If currently windowed, it calls animate_maximize() and changes the icon to a double-square. The is_maximized flag is toggled after the call.

animate_maximize(self) Private

Animates the window from its current geometry to the full available screen geometry (excluding the taskbar). Before animating, the current geometry is saved as original_geometry — but with bounds checking to ensure the stored geometry is valid. Specifically, if the window is already wider/taller than the screen or positioned off-screen, the geometry is clamped to ensure a valid restore target.

The animation uses the main self.animation object with OutQuad easing over 175ms. After completion, the window is re-locked via _connect_lock_after_animation().

animate_restore(self) Private

Animates the window from its current (maximized) geometry back to the stored original_geometry. Uses the same self.animation object with OutQuad easing over 175ms. After completion, the window is re-locked.

Edge & Corner Resize

Since the window is frameless, there is no native border to grab for resizing. The AbdhWindow class implements a complete manual resize system that detects when the cursor is near the window's edges or corners, changes the cursor shape accordingly, and handles mouse drag to resize the window from any of 8 directions (4 edges + 4 corners). This replaces the commonly used QSizeGrip approach, which only provides a single bottom-right resize handle and has known issues with frameless windows.

_get_resize_direction(self, pos) -> str | None Private

Determines which edge or corner the cursor is near based on the mouse position relative to the window boundaries. The RESIZE_MARGIN (8 pixels) defines the invisible grab zone around the window perimeter. Corners take priority over edges in the detection logic.

ParameterTypeDescription
posQPointThe mouse position in window-local coordinates.
Returns: One of 'top_left', 'top_right', 'bottom_left', 'bottom_right', 'left', 'right', 'top', 'bottom', or None if the cursor is not near any edge.
_cursor_for_direction(self, direction) -> Qt.CursorShape Private

Maps a resize direction string to the appropriate Qt cursor shape. Horizontal edges use SizeHorCursor, vertical edges use SizeVerCursor, and diagonal corners use SizeFDiagCursor or SizeBDiagCursor depending on the diagonal direction. Returns ArrowCursor for unrecognized directions.

DirectionCursor ShapeVisual
left, rightSizeHorCursorHorizontal double arrow ↔
top, bottomSizeVerCursorVertical double arrow ↕
top_left, bottom_rightSizeFDiagCursorForward diagonal ↖↘
top_right, bottom_leftSizeBDiagCursorBackward diagonal ↗↙
_do_resize(self, global_pos) Private

Performs the actual resize based on the stored direction and the mouse position delta. It calculates the new geometry by adjusting the appropriate edges of the stored _resize_start_geo rectangle. Each direction flag in _resize_dir (e.g., 'left', 'top') is checked independently, which allows corner resizing to modify two edges simultaneously.

Minimum size constraints (MIN_WINDOW_WIDTH and MIN_WINDOW_HEIGHT) are enforced: if resizing would make the window smaller than the minimum, the corresponding edge is not moved. After setting the geometry, the main layout is explicitly activated via self.main_widget.layout().activate() to force an immediate reflow so the stacked widget expands/contracts to fill the new window size.

ParameterTypeDescription
global_posQPointThe current global mouse position.

Event System

AbdhWindow overrides several Qt event handlers and installs a global event filter to implement its frameless window behavior. The event system handles: first-show fade-in animation, custom painting of rounded corners, cursor management for edge resizing, auto-closing panels on outside clicks, window dragging from the titlebar, and edge/corner resizing.

Mouse Events

mousePressEvent(self, event: QMouseEvent) Override

Handles left-button mouse press events with two distinct behaviors:

  1. Edge/corner resize initiation: If the cursor is near an edge or corner (determined by _get_resize_direction()) and the window is not maximized, the resize state is initialized. The size lock is unlocked, the resize direction and starting geometry/position are stored, and the resize cursor is locked for the entire drag operation.
  2. Titlebar drag initiation: If the click is not near an edge, the drag start position is stored as the offset between the global cursor position and the window's top-left corner. This offset is used in mouseMoveEvent() to move the window smoothly.
mouseDoubleClickEvent(self, event) Override

Handles double-click events on the titlebar area. If the double-click occurs within the titlebar height (self.titlebar_height) from the top of the window, it triggers toggle_maximize_restore(). This mimics the standard Windows/macOS behavior of double-clicking the titlebar to maximize/restore the window.

mouseMoveEvent(self, event: QMouseEvent) Override

Handles left-button mouse move events with two behaviors:

  1. Resizing: If self._resizing is True, calls _do_resize() with the current global position to update the window geometry.
  2. Titlebar dragging: If a drag start position exists and the cursor is within the titlebar's Y range, the window is moved to follow the cursor. If the window is maximized, it is first restored to windowed mode before dragging begins, allowing the user to "pull" the window out of maximized state — a common UX pattern.

Note: Cursor management for hover (no button pressed) is handled in eventFilter(), not here. mouseMoveEvent only fires when the mouse is over the window's own area — child widgets consume the events. The event filter catches ALL mouse-move events so the resize cursor is always shown/hidden correctly.

mouseReleaseEvent(self, event) Override

Handles left-button mouse release events. If the user was resizing (self._resizing is True), the resize state is reset and the window is re-locked to its new size via _lock_size(). The cursor is also unset, allowing the eventFilter to set the correct cursor on the next hover move. The drag start position is always cleared on release.

showEvent(self, event) Override

Triggers the fade-in animation when the window is shown for the first time. If self.first_show is True, it sets it to False and calls animate_fadeIn(). Subsequent show events (e.g., after minimizing and restoring) do not trigger the animation.

paintEvent(self, event) Override

Custom paint event that draws a rounded rectangle over the entire window area. This is necessary because the window is frameless with a translucent background, so without custom painting the corners would show the desktop or other windows behind. The method uses QPainter with antialiasing to draw a QPainterPath containing a rounded rect (8px radius), filled with the window palette's background color.

leaveEvent(self, event) Override

Resets the cursor to the default arrow when the mouse leaves the window entirely. This prevents the resize cursor from persisting when the mouse moves away from the window edge without being over any child widget.

Global Event Filter

eventFilter(self, obj, event) -> bool Override

A global event filter installed on QApplication.instance() that handles two critical functions that cannot be implemented in regular event handlers:

1. Cursor Management (MouseMove, no buttons)

When the mouse moves without any buttons pressed, the filter checks if the cursor is near a window edge or corner. If so, it sets the appropriate resize cursor. If not, it unsets the cursor. This must be in the event filter (not mouseMoveEvent) because mouseMoveEvent only fires when the mouse is directly over the window's own area — not over child widgets. Without the event filter, the resize cursor would get "stuck" or appear over child widgets that inherit the parent's cursor. The filter is only active when the window is not maximized and is visible.

2. Auto-Close Panels on Outside Click (MouseButtonPress)

When a mouse button press is detected anywhere in the application, the filter checks whether the click target is one of the control buttons (toggle, pin, settings, maximize, minimize, close). If it is, the event is passed through normally. Otherwise:

  • Right panel: If the right panel is open (width > 0) and the click is outside its geometry, it is auto-closed via toggle_frame().
  • Left panel (overlay mode): If the left panel is in overlay mode and expanded, and the click is outside its geometry, it is auto-collapsed via animate_content().

Helper Methods

_create_titlebar(self, title_text: str, title_logo: QPixmap) -> QWidget Private

Builds the custom titlebar widget with all its child widgets and layout. The titlebar is a QWidget with object name Titlebar, fixed height of titlebar_height (42px), and a QHBoxLayout containing the following widgets from left to right:

WidgetPropertyIconSignal
Logo labelCSS class: default
Back buttongrouped_miniarrow-leftstacked_widget.go_back
Forward buttongrouped_miniarrow-rightstacked_widget.go_next
Title labelcaption
Stretch
Settings buttongrouped_minisettingstoggle_frame(right_panel, 0)
Minimize buttongrouped_miniminusshowMinimized
Maximize buttongrouped_minisquaretoggle_maximize_restore
Close buttonclosebuttonxclose

All buttons use the grouped_mini CSS class (except the close button which uses closebutton) and are aligned to the top of the titlebar. The layout direction is forced to LeftToRight regardless of the application's layout direction, ensuring the window controls always appear on the right side.

ParameterTypeDescription
title_textstrThe text displayed in the title label.
title_logoQPixmapOptional logo pixmap; scaled to logo_size (32×32) with aspect ratio preservation.
Returns: QWidget — The fully constructed titlebar widget.
switch_settings_button(self, on: bool = True) Public

Shows or hides the settings button in the titlebar. This is useful when a particular page or application state does not require a settings panel.

ParameterTypeDefaultDescription
onboolTrueIf True, the settings button is visible; if False, it is hidden.
switch_navigations(self, on: bool = True) Public

Shows or hides both the back and forward navigation buttons in the titlebar simultaneously. This is useful for pages that do not support navigation history.

ParameterTypeDefaultDescription
onboolTrueIf True, both navigation buttons are visible; if False, both are hidden.
set_direction(self, direction: Qt.LayoutDirection = Qt.LayoutDirection.LeftToRight) Public

Sets the layout direction of the stacked widget, enabling right-to-left (RTL) support for languages like Arabic or Hebrew. The titlebar and side panels are not affected — they maintain their forced LeftToRight direction.

ParameterTypeDefaultDescription
directionQt.LayoutDirectionLeftToRightThe layout direction for the content area.
update_navigation_buttons(self, can_go_back: bool, can_go_forward: bool) Public

Independently controls the visibility of the back and forward navigation buttons. This is typically called after a page navigation event to reflect the current navigation history state — the back button is visible only if there is a previous page to return to, and the forward button is visible only if there is a next page.

ParameterTypeDescription
can_go_backboolIf True, the back button is shown; otherwise hidden.
can_go_forwardboolIf True, the forward button is shown; otherwise hidden.
add_right_panel_item(self, item: QWidget) Public

Inserts a widget into the right panel layout, positioned before the bottom stretch. The stretch was added during initialization with addStretch(1), so new items are inserted at index count - 1 to appear above the stretch. This ensures that content is always pushed to the top of the panel with flexible space at the bottom.

ParameterTypeDescription
itemQWidgetThe widget to add to the right panel.
add_left_panel_item(self, item: QWidget) Public

Appends a widget to the end of the left panel layout. Widgets are added in order from top to bottom, after the toggle and pin buttons that were added during initUI().

ParameterTypeDescription
itemQWidgetThe widget to add to the left panel.
left_panel_item(self, index: int) -> QWidget Public

Returns the widget at the given index in the left panel layout. This is useful for accessing or modifying previously added panel items.

ParameterTypeDescription
indexintThe zero-based index of the item in the left panel layout.
Returns: QWidget — The widget at the specified index.

Page & Style Helpers

add_page(self, page_widget: QWidget) Public

Adds a page widget to the central stacked widget. Pages are managed by the StackedWidget class, which provides navigation history (back/forward) functionality. The first page added becomes the initially visible page. Each subsequent page is hidden until navigated to via the stacked widget's methods.

ParameterTypeDescription
page_widgetQWidgetThe page widget to add. It should contain the full UI for one application screen.
apply_style(self, style_sheet: str) Public

Applies a Qt style sheet string directly to the window. This is the programmatic way to set styles, useful for dynamically generated or modified style sheets. The style sheet affects the window and all its child widgets.

ParameterTypeDescription
style_sheetstrA valid Qt style sheet (QSS) string to apply.
load_style(self, file_name: str = 'default') -> str | None Public

Loads a Qt style sheet from an external file and applies it to the window. The file is read as UTF-8 text. If the file does not exist, a warning is printed to the console and None is returned. This method is useful for separating style definitions from application code and allowing runtime theme switching.

ParameterTypeDefaultDescription
file_namestr'default'Path to the QSS file to load.
Returns: The style sheet string if the file was found and loaded successfully; None otherwise.

Full Method Index

Complete reference of all methods in the AbdhWindow class, organized by visibility and category:

MethodVisibilityCategoryBrief Description
__init__PublicConstructorInitialize window state and frameless flags
initUIPublicInitializationBuild the entire UI structure
showOverrideInitializationShow with initialization guard
_lock_sizePrivateSize LockLock window to current size
_unlock_sizePrivateSize LockUnlock for user-initiated resize
_connect_lock_after_animationPrivateSize LockAuto-lock after animation finishes
toggle_overlayPublicPanelToggle pinned/overlay mode for left panel
animate_contentPublicPanelAnimate left panel open/close
toggle_framePublicPanelGeneric panel toggle with animation
open_settingsPublicPanelToggle right (settings) panel
toggle_maximize_restorePublicMaximizeToggle between maximized and restored
animate_maximizePrivateMaximizeAnimate to full-screen geometry
animate_restorePrivateMaximizeAnimate to stored windowed geometry
animate_fadeInPrivateAnimationFade-in + slide-in on first show
_get_resize_directionPrivateResizeDetect edge/corner from cursor position
_cursor_for_directionPrivateResizeMap direction to cursor shape
_do_resizePrivateResizeApply geometry change during drag
mousePressEventOverrideEventInitiate resize or titlebar drag
mouseDoubleClickEventOverrideEventMaximize/restore on titlebar double-click
mouseMoveEventOverrideEventPerform resize or window drag
mouseReleaseEventOverrideEventEnd resize, re-lock size
showEventOverrideEventTrigger fade-in on first show
paintEventOverrideEventDraw rounded rectangle background
leaveEventOverrideEventReset cursor when mouse leaves
eventFilterOverrideEventCursor management + auto-close panels
_create_titlebarPrivateHelperBuild custom titlebar widget
switch_settings_buttonPublicHelperShow/hide settings button
switch_navigationsPublicHelperShow/hide back & forward buttons
set_directionPublicHelperSet content layout direction (RTL support)
update_navigation_buttonsPublicHelperIndividually control nav button visibility
add_right_panel_itemPublicHelperAdd widget to right panel
add_left_panel_itemPublicHelperAdd widget to left panel
left_panel_itemPublicHelperGet widget at index in left panel
add_pagePublicPage/StyleAdd page to stacked widget
apply_stylePublicPage/StyleApply QSS string to window
load_stylePublicPage/StyleLoad and apply QSS from file

CSS Class Reference: The window uses CSS class properties (not object names) to match stylesheet selectors. Key CSS classes used include: window-background-layer (main widget), left-sidebar-background-layer (left panel), right-sidebar-background-layer (right panel), grouped_mini (small control buttons), closebutton (close button), and caption (title label). The titlebar widget uses objectName Titlebar instead.