feat: Enhanced Activity Bar with drag, resize, opacity, and customization
Activity Bar Improvements: - Draggable: Grab left handle to move anywhere on screen - Resizable: Grab right handle to change width (400-1600px) - Background Opacity: Now actually works (20-100%) - Search toggle: Right-click menu to show/hide search box - Clock toggle: Right-click menu to show/hide clock - Reset Position: Right-click menu to reset to default position - Settings dialog: Added opacity slider, width, search/clock toggles Config additions: - x, y: Custom position - width: Bar width (400-1600) - background_opacity: 20-100% - show_search: Toggle search visibility - show_clock: Toggle clock visibility Bug Fixes: - OverlayController now inherits QObject (fixes 'cannot be converted' error) - Activity bar saves position when dragged - Activity bar saves width when resized
This commit is contained in:
parent
159f7a4a05
commit
4b5096a859
|
|
@ -27,11 +27,17 @@ from core.icon_manager import get_icon_manager
|
||||||
class ActivityBarConfig:
|
class ActivityBarConfig:
|
||||||
"""Activity bar configuration."""
|
"""Activity bar configuration."""
|
||||||
enabled: bool = True
|
enabled: bool = True
|
||||||
position: str = "bottom" # top, bottom
|
position: str = "bottom" # top, bottom, custom
|
||||||
|
x: int = 100 # custom X position
|
||||||
|
y: int = 800 # custom Y position
|
||||||
|
width: int = 800 # custom width
|
||||||
icon_size: int = 32
|
icon_size: int = 32
|
||||||
auto_hide: bool = True
|
auto_hide: bool = False # Disabled by default for easier use
|
||||||
auto_hide_delay: int = 3000 # milliseconds
|
auto_hide_delay: int = 3000 # milliseconds
|
||||||
auto_show_on_focus: bool = False # DISABLED by default - causes UI freezing
|
auto_show_on_focus: bool = False
|
||||||
|
background_opacity: int = 90 # 0-100
|
||||||
|
show_search: bool = True
|
||||||
|
show_clock: bool = True
|
||||||
pinned_plugins: List[str] = None
|
pinned_plugins: List[str] = None
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
|
|
@ -42,10 +48,16 @@ class ActivityBarConfig:
|
||||||
return {
|
return {
|
||||||
'enabled': self.enabled,
|
'enabled': self.enabled,
|
||||||
'position': self.position,
|
'position': self.position,
|
||||||
|
'x': self.x,
|
||||||
|
'y': self.y,
|
||||||
|
'width': self.width,
|
||||||
'icon_size': self.icon_size,
|
'icon_size': self.icon_size,
|
||||||
'auto_hide': self.auto_hide,
|
'auto_hide': self.auto_hide,
|
||||||
'auto_hide_delay': self.auto_hide_delay,
|
'auto_hide_delay': self.auto_hide_delay,
|
||||||
'auto_show_on_focus': self.auto_show_on_focus,
|
'auto_show_on_focus': self.auto_show_on_focus,
|
||||||
|
'background_opacity': self.background_opacity,
|
||||||
|
'show_search': self.show_search,
|
||||||
|
'show_clock': self.show_clock,
|
||||||
'pinned_plugins': self.pinned_plugins
|
'pinned_plugins': self.pinned_plugins
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -54,9 +66,16 @@ class ActivityBarConfig:
|
||||||
return cls(
|
return cls(
|
||||||
enabled=data.get('enabled', True),
|
enabled=data.get('enabled', True),
|
||||||
position=data.get('position', 'bottom'),
|
position=data.get('position', 'bottom'),
|
||||||
|
x=data.get('x', 100),
|
||||||
|
y=data.get('y', 800),
|
||||||
|
width=data.get('width', 800),
|
||||||
icon_size=data.get('icon_size', 32),
|
icon_size=data.get('icon_size', 32),
|
||||||
auto_hide=data.get('auto_hide', True),
|
auto_hide=data.get('auto_hide', False),
|
||||||
auto_hide_delay=data.get('auto_hide_delay', 3000),
|
auto_hide_delay=data.get('auto_hide_delay', 3000),
|
||||||
|
auto_show_on_focus=data.get('auto_show_on_focus', False),
|
||||||
|
background_opacity=data.get('background_opacity', 90),
|
||||||
|
show_search=data.get('show_search', True),
|
||||||
|
show_clock=data.get('show_clock', True),
|
||||||
pinned_plugins=data.get('pinned_plugins', [])
|
pinned_plugins=data.get('pinned_plugins', [])
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -115,19 +134,21 @@ class WindowsTaskbar(QFrame):
|
||||||
self._drag_offset = QPoint()
|
self._drag_offset = QPoint()
|
||||||
|
|
||||||
def _setup_ui(self):
|
def _setup_ui(self):
|
||||||
"""Setup Windows taskbar-style UI."""
|
"""Setup Windows taskbar-style UI with draggable and resizable features."""
|
||||||
# Main layout with minimal margins
|
# Main layout with minimal margins
|
||||||
layout = QHBoxLayout(self)
|
self.main_layout = QHBoxLayout(self)
|
||||||
layout.setContentsMargins(8, 4, 8, 4)
|
self.main_layout.setContentsMargins(8, 4, 8, 4)
|
||||||
layout.setSpacing(4)
|
self.main_layout.setSpacing(4)
|
||||||
|
|
||||||
# Style: No background, just floating elements
|
# Apply opacity from config
|
||||||
self.setStyleSheet("""
|
self._apply_opacity()
|
||||||
WindowsTaskbar {
|
|
||||||
background: transparent;
|
# === DRAG HANDLE (invisible, left side) ===
|
||||||
border: none;
|
self.drag_handle = QFrame()
|
||||||
}
|
self.drag_handle.setFixedSize(8, 40)
|
||||||
""")
|
self.drag_handle.setStyleSheet("background: transparent; cursor: move;")
|
||||||
|
self.drag_handle.setToolTip("Drag to move")
|
||||||
|
self.main_layout.addWidget(self.drag_handle)
|
||||||
|
|
||||||
# === START BUTTON (Windows-style icon) ===
|
# === START BUTTON (Windows-style icon) ===
|
||||||
self.start_btn = QPushButton()
|
self.start_btn = QPushButton()
|
||||||
|
|
@ -150,7 +171,7 @@ class WindowsTaskbar(QFrame):
|
||||||
""")
|
""")
|
||||||
self.start_btn.setToolTip("Open App Drawer")
|
self.start_btn.setToolTip("Open App Drawer")
|
||||||
self.start_btn.clicked.connect(self._toggle_drawer)
|
self.start_btn.clicked.connect(self._toggle_drawer)
|
||||||
layout.addWidget(self.start_btn)
|
self.main_layout.addWidget(self.start_btn)
|
||||||
|
|
||||||
# === SEARCH BOX (Windows 11 style) ===
|
# === SEARCH BOX (Windows 11 style) ===
|
||||||
self.search_box = QLineEdit()
|
self.search_box = QLineEdit()
|
||||||
|
|
@ -179,31 +200,39 @@ class WindowsTaskbar(QFrame):
|
||||||
""")
|
""")
|
||||||
self.search_box.returnPressed.connect(self._on_search)
|
self.search_box.returnPressed.connect(self._on_search)
|
||||||
self.search_box.textChanged.connect(self._on_search_text_changed)
|
self.search_box.textChanged.connect(self._on_search_text_changed)
|
||||||
layout.addWidget(self.search_box)
|
self.main_layout.addWidget(self.search_box)
|
||||||
|
|
||||||
|
# Search visibility
|
||||||
|
self.search_box.setVisible(self.config.show_search)
|
||||||
|
|
||||||
# Separator
|
# Separator
|
||||||
separator = QFrame()
|
separator = QFrame()
|
||||||
separator.setFixedSize(1, 24)
|
separator.setFixedSize(1, 24)
|
||||||
separator.setStyleSheet("background: rgba(255, 255, 255, 0.1);")
|
separator.setStyleSheet("background: rgba(255, 255, 255, 0.1);")
|
||||||
layout.addWidget(separator)
|
self.main_layout.addWidget(separator)
|
||||||
|
|
||||||
# === PINNED PLUGINS AREA (expandable) ===
|
# === PINNED PLUGINS AREA (expandable) ===
|
||||||
self.pinned_container = QWidget()
|
self.pinned_container = QWidget()
|
||||||
self.pinned_layout = QHBoxLayout(self.pinned_container)
|
self.pinned_layout = QHBoxLayout(self.pinned_container)
|
||||||
self.pinned_layout.setContentsMargins(0, 0, 0, 0)
|
self.pinned_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
self.pinned_layout.setSpacing(4)
|
self.pinned_layout.setSpacing(4)
|
||||||
layout.addWidget(self.pinned_container)
|
self.main_layout.addWidget(self.pinned_container)
|
||||||
|
|
||||||
# Spacer to push icons together
|
# Spacer to push icons together
|
||||||
layout.addStretch()
|
self.main_layout.addStretch()
|
||||||
|
|
||||||
|
# === CLOCK AREA ===
|
||||||
|
self.clock_widget = QWidget()
|
||||||
|
clock_layout = QHBoxLayout(self.clock_widget)
|
||||||
|
clock_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
clock_layout.setSpacing(4)
|
||||||
|
|
||||||
# === SYSTEM TRAY AREA ===
|
|
||||||
# Clock icon
|
# Clock icon
|
||||||
self.clock_icon = QLabel()
|
self.clock_icon = QLabel()
|
||||||
clock_pixmap = self.icon_manager.get_pixmap("clock", size=14)
|
clock_pixmap = self.icon_manager.get_pixmap("clock", size=14)
|
||||||
self.clock_icon.setPixmap(clock_pixmap)
|
self.clock_icon.setPixmap(clock_pixmap)
|
||||||
self.clock_icon.setStyleSheet("padding-right: 4px;")
|
self.clock_icon.setStyleSheet("padding-right: 4px;")
|
||||||
layout.addWidget(self.clock_icon)
|
clock_layout.addWidget(self.clock_icon)
|
||||||
|
|
||||||
# Clock time
|
# Clock time
|
||||||
self.clock_label = QLabel("12:00")
|
self.clock_label = QLabel("12:00")
|
||||||
|
|
@ -213,7 +242,19 @@ class WindowsTaskbar(QFrame):
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
""")
|
""")
|
||||||
self.clock_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
self.clock_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||||
layout.addWidget(self.clock_label)
|
clock_layout.addWidget(self.clock_label)
|
||||||
|
|
||||||
|
self.main_layout.addWidget(self.clock_widget)
|
||||||
|
|
||||||
|
# Clock visibility
|
||||||
|
self.clock_widget.setVisible(self.config.show_clock)
|
||||||
|
|
||||||
|
# === RESIZE HANDLE (right side) ===
|
||||||
|
self.resize_handle = QFrame()
|
||||||
|
self.resize_handle.setFixedSize(8, 40)
|
||||||
|
self.resize_handle.setStyleSheet("background: transparent; cursor: size-hor-cursor;")
|
||||||
|
self.resize_handle.setToolTip("Drag to resize")
|
||||||
|
self.main_layout.addWidget(self.resize_handle)
|
||||||
|
|
||||||
# Start clock update timer
|
# Start clock update timer
|
||||||
self.clock_timer = QTimer(self)
|
self.clock_timer = QTimer(self)
|
||||||
|
|
@ -227,6 +268,9 @@ class WindowsTaskbar(QFrame):
|
||||||
|
|
||||||
# Refresh pinned plugins
|
# Refresh pinned plugins
|
||||||
self._refresh_pinned_plugins()
|
self._refresh_pinned_plugins()
|
||||||
|
|
||||||
|
# Set initial size and position
|
||||||
|
self._apply_size_and_position()
|
||||||
|
|
||||||
def _create_plugin_button(self, plugin_id: str, plugin_class) -> QPushButton:
|
def _create_plugin_button(self, plugin_id: str, plugin_class) -> QPushButton:
|
||||||
"""Create a pinned plugin button (taskbar icon style)."""
|
"""Create a pinned plugin button (taskbar icon style)."""
|
||||||
|
|
@ -352,6 +396,83 @@ class WindowsTaskbar(QFrame):
|
||||||
plugins_layout.addStretch()
|
plugins_layout.addStretch()
|
||||||
layout.addWidget(plugins_widget)
|
layout.addWidget(plugins_widget)
|
||||||
|
|
||||||
|
def mousePressEvent(self, event: QMouseEvent):
|
||||||
|
"""Handle mouse press for dragging."""
|
||||||
|
if event.button() == Qt.MouseButton.LeftButton:
|
||||||
|
# Check if clicking on drag handle
|
||||||
|
if self.drag_handle.geometry().contains(event.pos()):
|
||||||
|
self._dragging = True
|
||||||
|
self._drag_offset = event.globalPosition().toPoint() - self.frameGeometry().topLeft()
|
||||||
|
event.accept()
|
||||||
|
# Check if clicking on resize handle
|
||||||
|
elif self.resize_handle.geometry().contains(event.pos()):
|
||||||
|
self._resizing = True
|
||||||
|
self._resize_start_x = event.globalPosition().x()
|
||||||
|
self._resize_start_width = self.width()
|
||||||
|
event.accept()
|
||||||
|
else:
|
||||||
|
super().mousePressEvent(event)
|
||||||
|
|
||||||
|
def mouseMoveEvent(self, event: QMouseEvent):
|
||||||
|
"""Handle mouse move for dragging and resizing."""
|
||||||
|
if self._dragging:
|
||||||
|
new_pos = event.globalPosition().toPoint() - self._drag_offset
|
||||||
|
self.move(new_pos)
|
||||||
|
# Save position
|
||||||
|
self.config.x = new_pos.x()
|
||||||
|
self.config.y = new_pos.y()
|
||||||
|
self._save_config()
|
||||||
|
event.accept()
|
||||||
|
elif getattr(self, '_resizing', False):
|
||||||
|
delta = event.globalPosition().x() - self._resize_start_x
|
||||||
|
new_width = max(400, self._resize_start_width + delta)
|
||||||
|
self.setFixedWidth(int(new_width))
|
||||||
|
self.config.width = int(new_width)
|
||||||
|
self._save_config()
|
||||||
|
event.accept()
|
||||||
|
else:
|
||||||
|
super().mouseMoveEvent(event)
|
||||||
|
|
||||||
|
def mouseReleaseEvent(self, event: QMouseEvent):
|
||||||
|
"""Handle mouse release."""
|
||||||
|
if event.button() == Qt.MouseButton.LeftButton:
|
||||||
|
self._dragging = False
|
||||||
|
self._resizing = False
|
||||||
|
super().mouseReleaseEvent(event)
|
||||||
|
|
||||||
|
def _apply_opacity(self):
|
||||||
|
"""Apply background opacity from config."""
|
||||||
|
opacity = self.config.background_opacity / 100.0
|
||||||
|
# Create a background widget with opacity
|
||||||
|
bg_color = f"rgba(20, 31, 35, {opacity})"
|
||||||
|
self.setStyleSheet(f"""
|
||||||
|
WindowsTaskbar {{
|
||||||
|
background: {bg_color};
|
||||||
|
border: 1px solid rgba(255, 140, 66, 0.1);
|
||||||
|
border-radius: 12px;
|
||||||
|
}}
|
||||||
|
""")
|
||||||
|
|
||||||
|
def _apply_size_and_position(self):
|
||||||
|
"""Apply saved size and position."""
|
||||||
|
self.setFixedHeight(56)
|
||||||
|
self.setFixedWidth(self.config.width)
|
||||||
|
|
||||||
|
if self.config.position == "custom":
|
||||||
|
self.move(self.config.x, self.config.y)
|
||||||
|
elif self.config.position == "bottom":
|
||||||
|
screen = QApplication.primaryScreen().geometry()
|
||||||
|
self.move(
|
||||||
|
(screen.width() - self.config.width) // 2,
|
||||||
|
screen.height() - 80
|
||||||
|
)
|
||||||
|
elif self.config.position == "top":
|
||||||
|
screen = QApplication.primaryScreen().geometry()
|
||||||
|
self.move(
|
||||||
|
(screen.width() - self.config.width) // 2,
|
||||||
|
20
|
||||||
|
)
|
||||||
|
|
||||||
def _create_drawer_item(self, plugin_id: str, plugin_class) -> QPushButton:
|
def _create_drawer_item(self, plugin_id: str, plugin_class) -> QPushButton:
|
||||||
"""Create a drawer item (like Start menu app)."""
|
"""Create a drawer item (like Start menu app)."""
|
||||||
icon_name = getattr(plugin_class, 'icon_name', 'grid')
|
icon_name = getattr(plugin_class, 'icon_name', 'grid')
|
||||||
|
|
@ -433,16 +554,52 @@ class WindowsTaskbar(QFrame):
|
||||||
}
|
}
|
||||||
""")
|
""")
|
||||||
|
|
||||||
settings_action = menu.addAction("Settings")
|
# Toggle search
|
||||||
settings_action.triggered.connect(self._show_settings)
|
search_action = menu.addAction("☑ Search" if self.config.show_search else "☐ Search")
|
||||||
|
search_action.triggered.connect(self._toggle_search)
|
||||||
|
|
||||||
|
# Toggle clock
|
||||||
|
clock_action = menu.addAction("☑ Clock" if self.config.show_clock else "☐ Clock")
|
||||||
|
clock_action.triggered.connect(self._toggle_clock)
|
||||||
|
|
||||||
menu.addSeparator()
|
menu.addSeparator()
|
||||||
|
|
||||||
|
# Settings
|
||||||
|
settings_action = menu.addAction("Settings...")
|
||||||
|
settings_action.triggered.connect(self._show_settings)
|
||||||
|
|
||||||
|
# Reset position
|
||||||
|
reset_action = menu.addAction("Reset Position")
|
||||||
|
reset_action.triggered.connect(self._reset_position)
|
||||||
|
|
||||||
|
menu.addSeparator()
|
||||||
|
|
||||||
|
# Hide
|
||||||
hide_action = menu.addAction("Hide")
|
hide_action = menu.addAction("Hide")
|
||||||
hide_action.triggered.connect(self.hide)
|
hide_action.triggered.connect(self.hide)
|
||||||
|
|
||||||
menu.exec(self.mapToGlobal(position))
|
menu.exec(self.mapToGlobal(position))
|
||||||
|
|
||||||
|
def _toggle_search(self):
|
||||||
|
"""Toggle search box visibility."""
|
||||||
|
self.config.show_search = not self.config.show_search
|
||||||
|
self.search_box.setVisible(self.config.show_search)
|
||||||
|
self._save_config()
|
||||||
|
|
||||||
|
def _toggle_clock(self):
|
||||||
|
"""Toggle clock visibility."""
|
||||||
|
self.config.show_clock = not self.config.show_clock
|
||||||
|
self.clock_widget.setVisible(self.config.show_clock)
|
||||||
|
self._save_config()
|
||||||
|
|
||||||
|
def _reset_position(self):
|
||||||
|
"""Reset bar position to default."""
|
||||||
|
self.config.position = "bottom"
|
||||||
|
self.config.x = 100
|
||||||
|
self.config.y = 800
|
||||||
|
self._apply_size_and_position()
|
||||||
|
self._save_config()
|
||||||
|
|
||||||
def _show_settings(self):
|
def _show_settings(self):
|
||||||
"""Show settings dialog."""
|
"""Show settings dialog."""
|
||||||
dialog = TaskbarSettingsDialog(self.config, self)
|
dialog = TaskbarSettingsDialog(self.config, self)
|
||||||
|
|
@ -457,15 +614,15 @@ class WindowsTaskbar(QFrame):
|
||||||
# Set auto-hide timer
|
# Set auto-hide timer
|
||||||
self.hide_timer.setInterval(self.config.auto_hide_delay)
|
self.hide_timer.setInterval(self.config.auto_hide_delay)
|
||||||
|
|
||||||
# Position bar
|
# Apply opacity
|
||||||
screen = QApplication.primaryScreen().geometry()
|
self._apply_opacity()
|
||||||
if self.config.position == "bottom":
|
|
||||||
self.move((screen.width() - 600) // 2, screen.height() - 60)
|
|
||||||
else: # top
|
|
||||||
self.move((screen.width() - 600) // 2, 10)
|
|
||||||
|
|
||||||
# Size
|
# Apply size and position
|
||||||
self.setFixedSize(600, 50)
|
self._apply_size_and_position()
|
||||||
|
|
||||||
|
# Show/hide search and clock
|
||||||
|
self.search_box.setVisible(self.config.show_search)
|
||||||
|
self.clock_widget.setVisible(self.config.show_clock)
|
||||||
|
|
||||||
def _auto_hide(self):
|
def _auto_hide(self):
|
||||||
"""Auto-hide when mouse leaves."""
|
"""Auto-hide when mouse leaves."""
|
||||||
|
|
@ -484,24 +641,6 @@ class WindowsTaskbar(QFrame):
|
||||||
self.hide_timer.start()
|
self.hide_timer.start()
|
||||||
super().leaveEvent(event)
|
super().leaveEvent(event)
|
||||||
|
|
||||||
def mousePressEvent(self, event: QMouseEvent):
|
|
||||||
"""Start dragging."""
|
|
||||||
if event.button() == Qt.MouseButton.LeftButton:
|
|
||||||
self._dragging = True
|
|
||||||
self._drag_offset = event.globalPosition().toPoint() - self.frameGeometry().topLeft()
|
|
||||||
event.accept()
|
|
||||||
|
|
||||||
def mouseMoveEvent(self, event: QMouseEvent):
|
|
||||||
"""Drag window."""
|
|
||||||
if self._dragging:
|
|
||||||
new_pos = event.globalPosition().toPoint() - self._drag_offset
|
|
||||||
self.move(new_pos)
|
|
||||||
|
|
||||||
def mouseReleaseEvent(self, event: QMouseEvent):
|
|
||||||
"""Stop dragging."""
|
|
||||||
if event.button() == Qt.MouseButton.LeftButton:
|
|
||||||
self._dragging = False
|
|
||||||
|
|
||||||
def _load_config(self) -> ActivityBarConfig:
|
def _load_config(self) -> ActivityBarConfig:
|
||||||
"""Load configuration."""
|
"""Load configuration."""
|
||||||
config_path = Path("config/activity_bar.json")
|
config_path = Path("config/activity_bar.json")
|
||||||
|
|
@ -526,36 +665,85 @@ class TaskbarSettingsDialog(QDialog):
|
||||||
def __init__(self, config: ActivityBarConfig, parent=None):
|
def __init__(self, config: ActivityBarConfig, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.config = config
|
self.config = config
|
||||||
self.setWindowTitle("Taskbar Settings")
|
self.setWindowTitle("Activity Bar Settings")
|
||||||
self.setMinimumSize(350, 300)
|
self.setMinimumSize(400, 450)
|
||||||
self._setup_ui()
|
self._setup_ui()
|
||||||
|
|
||||||
def _setup_ui(self):
|
def _setup_ui(self):
|
||||||
"""Setup settings UI."""
|
"""Setup settings UI."""
|
||||||
from PyQt6.QtWidgets import QVBoxLayout, QFormLayout, QDialogButtonBox
|
from PyQt6.QtWidgets import QVBoxLayout, QFormLayout, QDialogButtonBox, QGroupBox
|
||||||
|
|
||||||
layout = QVBoxLayout(self)
|
layout = QVBoxLayout(self)
|
||||||
|
|
||||||
form = QFormLayout()
|
# Appearance Group
|
||||||
|
appear_group = QGroupBox("Appearance")
|
||||||
|
appear_form = QFormLayout(appear_group)
|
||||||
|
|
||||||
# Auto-hide
|
# Opacity
|
||||||
self.autohide_cb = QCheckBox("Auto-hide when not in use")
|
self.opacity_slider = QSlider(Qt.Orientation.Horizontal)
|
||||||
self.autohide_cb.setChecked(self.config.auto_hide)
|
self.opacity_slider.setRange(20, 100)
|
||||||
form.addRow(self.autohide_cb)
|
self.opacity_slider.setValue(self.config.background_opacity)
|
||||||
|
self.opacity_label = QLabel(f"{self.config.background_opacity}%")
|
||||||
# Position
|
self.opacity_slider.valueChanged.connect(lambda v: self.opacity_label.setText(f"{v}%"))
|
||||||
self.position_combo = QComboBox()
|
opacity_layout = QHBoxLayout()
|
||||||
self.position_combo.addItems(["Bottom", "Top"])
|
opacity_layout.addWidget(self.opacity_slider)
|
||||||
self.position_combo.setCurrentText(self.config.position.title())
|
opacity_layout.addWidget(self.opacity_label)
|
||||||
form.addRow("Position:", self.position_combo)
|
appear_form.addRow("Background Opacity:", opacity_layout)
|
||||||
|
|
||||||
# Icon size
|
# Icon size
|
||||||
self.icon_size = QSpinBox()
|
self.icon_size = QSpinBox()
|
||||||
self.icon_size.setRange(24, 48)
|
self.icon_size.setRange(24, 48)
|
||||||
self.icon_size.setValue(self.config.icon_size)
|
self.icon_size.setValue(self.config.icon_size)
|
||||||
form.addRow("Icon Size:", self.icon_size)
|
appear_form.addRow("Icon Size:", self.icon_size)
|
||||||
|
|
||||||
layout.addLayout(form)
|
layout.addWidget(appear_group)
|
||||||
|
|
||||||
|
# Features Group
|
||||||
|
features_group = QGroupBox("Features")
|
||||||
|
features_form = QFormLayout(features_group)
|
||||||
|
|
||||||
|
# Show search
|
||||||
|
self.show_search_cb = QCheckBox("Show search box")
|
||||||
|
self.show_search_cb.setChecked(self.config.show_search)
|
||||||
|
features_form.addRow(self.show_search_cb)
|
||||||
|
|
||||||
|
# Show clock
|
||||||
|
self.show_clock_cb = QCheckBox("Show clock")
|
||||||
|
self.show_clock_cb.setChecked(self.config.show_clock)
|
||||||
|
features_form.addRow(self.show_clock_cb)
|
||||||
|
|
||||||
|
layout.addWidget(features_group)
|
||||||
|
|
||||||
|
# Position Group
|
||||||
|
pos_group = QGroupBox("Position")
|
||||||
|
pos_form = QFormLayout(pos_group)
|
||||||
|
|
||||||
|
# Position
|
||||||
|
self.position_combo = QComboBox()
|
||||||
|
self.position_combo.addItems(["Bottom", "Top", "Custom"])
|
||||||
|
self.position_combo.setCurrentText(self.config.position.title())
|
||||||
|
pos_form.addRow("Position:", self.position_combo)
|
||||||
|
|
||||||
|
# Width
|
||||||
|
self.width_spin = QSpinBox()
|
||||||
|
self.width_spin.setRange(400, 1600)
|
||||||
|
self.width_spin.setValue(self.config.width)
|
||||||
|
pos_form.addRow("Width:", self.width_spin)
|
||||||
|
|
||||||
|
layout.addWidget(pos_group)
|
||||||
|
|
||||||
|
# Behavior Group
|
||||||
|
behav_group = QGroupBox("Behavior")
|
||||||
|
behav_form = QFormLayout(behav_group)
|
||||||
|
|
||||||
|
# Auto-hide
|
||||||
|
self.autohide_cb = QCheckBox("Auto-hide when not in use")
|
||||||
|
self.autohide_cb.setChecked(self.config.auto_hide)
|
||||||
|
behav_form.addRow(self.autohide_cb)
|
||||||
|
|
||||||
|
layout.addWidget(behav_group)
|
||||||
|
|
||||||
|
layout.addStretch()
|
||||||
|
|
||||||
# Buttons
|
# Buttons
|
||||||
buttons = QDialogButtonBox(
|
buttons = QDialogButtonBox(
|
||||||
|
|
@ -570,9 +758,16 @@ class TaskbarSettingsDialog(QDialog):
|
||||||
return ActivityBarConfig(
|
return ActivityBarConfig(
|
||||||
enabled=True,
|
enabled=True,
|
||||||
position=self.position_combo.currentText().lower(),
|
position=self.position_combo.currentText().lower(),
|
||||||
|
x=self.config.x,
|
||||||
|
y=self.config.y,
|
||||||
|
width=self.width_spin.value(),
|
||||||
icon_size=self.icon_size.value(),
|
icon_size=self.icon_size.value(),
|
||||||
auto_hide=self.autohide_cb.isChecked(),
|
auto_hide=self.autohide_cb.isChecked(),
|
||||||
auto_hide_delay=self.config.auto_hide_delay,
|
auto_hide_delay=self.config.auto_hide_delay,
|
||||||
|
auto_show_on_focus=self.config.auto_show_on_focus,
|
||||||
|
background_opacity=self.opacity_slider.value(),
|
||||||
|
show_search=self.show_search_cb.isChecked(),
|
||||||
|
show_clock=self.show_clock_cb.isChecked(),
|
||||||
pinned_plugins=self.config.pinned_plugins
|
pinned_plugins=self.config.pinned_plugins
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -180,7 +180,8 @@ class EUUtilityApp:
|
||||||
# Get overlay controller with window manager
|
# Get overlay controller with window manager
|
||||||
self.overlay_controller = get_overlay_controller(
|
self.overlay_controller = get_overlay_controller(
|
||||||
self.activity_bar,
|
self.activity_bar,
|
||||||
getattr(self, 'window_manager', None)
|
getattr(self, 'window_manager', None),
|
||||||
|
parent=self.app # Pass QApplication as parent
|
||||||
)
|
)
|
||||||
|
|
||||||
# Set mode from settings (default: game focused - Blish HUD style)
|
# Set mode from settings (default: game focused - Blish HUD style)
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ Modes:
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from PyQt6.QtCore import QTimer, pyqtSignal
|
from PyQt6.QtCore import QTimer, pyqtSignal, QObject
|
||||||
|
|
||||||
|
|
||||||
class OverlayMode(Enum):
|
class OverlayMode(Enum):
|
||||||
|
|
@ -57,7 +57,7 @@ class OverlayConfig:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class OverlayController:
|
class OverlayController(QObject):
|
||||||
"""
|
"""
|
||||||
Controls activity bar visibility based on selected mode.
|
Controls activity bar visibility based on selected mode.
|
||||||
|
|
||||||
|
|
@ -69,7 +69,8 @@ class OverlayController:
|
||||||
|
|
||||||
visibility_changed = pyqtSignal(bool) # is_visible
|
visibility_changed = pyqtSignal(bool) # is_visible
|
||||||
|
|
||||||
def __init__(self, activity_bar, window_manager=None):
|
def __init__(self, activity_bar, window_manager=None, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
self.activity_bar = activity_bar
|
self.activity_bar = activity_bar
|
||||||
self.window_manager = window_manager
|
self.window_manager = window_manager
|
||||||
self.config = OverlayConfig()
|
self.config = OverlayConfig()
|
||||||
|
|
@ -240,11 +241,11 @@ class OverlayController:
|
||||||
# Singleton instance
|
# Singleton instance
|
||||||
_overlay_controller = None
|
_overlay_controller = None
|
||||||
|
|
||||||
def get_overlay_controller(activity_bar=None, window_manager=None):
|
def get_overlay_controller(activity_bar=None, window_manager=None, parent=None):
|
||||||
"""Get or create the overlay controller singleton."""
|
"""Get or create the overlay controller singleton."""
|
||||||
global _overlay_controller
|
global _overlay_controller
|
||||||
if _overlay_controller is None:
|
if _overlay_controller is None:
|
||||||
if activity_bar is None:
|
if activity_bar is None:
|
||||||
raise ValueError("activity_bar required for first initialization")
|
raise ValueError("activity_bar required for first initialization")
|
||||||
_overlay_controller = OverlayController(activity_bar, window_manager)
|
_overlay_controller = OverlayController(activity_bar, window_manager, parent)
|
||||||
return _overlay_controller
|
return _overlay_controller
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue