Basically this is just a commit to save progress in case I need to reset to this point. Things are mostly working, but I found a serious UX problem that requires a lot of changes to the infrastructure.
This commit is contained in:
216
src/ui/channel_manager.py
Normal file
216
src/ui/channel_manager.py
Normal file
@@ -0,0 +1,216 @@
|
||||
"""
|
||||
Channel management dialog - manage autojoin channels for a server
|
||||
"""
|
||||
|
||||
import logging
|
||||
from PySide6.QtWidgets import (
|
||||
QDialog, QVBoxLayout, QHBoxLayout, QTableWidget, QTableWidgetItem,
|
||||
QPushButton, QLabel, QHeaderView, QMessageBox
|
||||
)
|
||||
from PySide6.QtCore import Qt
|
||||
from PySide6.QtGui import QKeyEvent
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ChannelManagerDialog(QDialog):
|
||||
"""Dialog to manage channels for a server."""
|
||||
|
||||
def __init__(self, parent, config_manager, server_config, irc_client=None):
|
||||
"""
|
||||
Initialize channel manager dialog.
|
||||
|
||||
Args:
|
||||
parent: Parent window
|
||||
config_manager: ConfigManager instance
|
||||
server_config: ServerConfig for the server
|
||||
irc_client: Optional IRCClient instance for joining channels
|
||||
"""
|
||||
super().__init__(parent)
|
||||
self.config_manager = config_manager
|
||||
self.server_config = server_config
|
||||
self.irc_client = irc_client
|
||||
|
||||
self.setWindowTitle(f"Manage Channels - {server_config.name}")
|
||||
self.resize(600, 400)
|
||||
|
||||
self.setup_ui()
|
||||
self.load_channels()
|
||||
|
||||
def setup_ui(self):
|
||||
"""Set up the user interface."""
|
||||
layout = QVBoxLayout()
|
||||
self.setLayout(layout)
|
||||
|
||||
# Info label
|
||||
info_label = QLabel(f"Channels for {self.server_config.name}")
|
||||
info_label.setAccessibleName(f"Channels for {self.server_config.name}")
|
||||
layout.addWidget(info_label)
|
||||
|
||||
# Table widget
|
||||
self.table = QTableWidget()
|
||||
self.table.setAccessibleName("Channel list table")
|
||||
self.table.setColumnCount(2)
|
||||
self.table.setHorizontalHeaderLabels(["Autojoin", "Channel"])
|
||||
|
||||
# Make first column narrow for checkbox
|
||||
header = self.table.horizontalHeader()
|
||||
header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
|
||||
header.setSectionResizeMode(1, QHeaderView.Stretch)
|
||||
|
||||
# Enable keyboard navigation
|
||||
self.table.setFocusPolicy(Qt.StrongFocus)
|
||||
self.table.setSelectionBehavior(QTableWidget.SelectRows)
|
||||
self.table.setSelectionMode(QTableWidget.SingleSelection)
|
||||
|
||||
# Connect signals
|
||||
self.table.itemActivated.connect(self.on_item_activated)
|
||||
self.table.itemChanged.connect(self.on_item_changed)
|
||||
|
||||
layout.addWidget(self.table)
|
||||
|
||||
# Buttons
|
||||
button_layout = QHBoxLayout()
|
||||
|
||||
join_button = QPushButton("Join Channel")
|
||||
join_button.setAccessibleName("Join selected channel")
|
||||
join_button.clicked.connect(self.on_join_clicked)
|
||||
button_layout.addWidget(join_button)
|
||||
|
||||
remove_button = QPushButton("Remove Channel")
|
||||
remove_button.setAccessibleName("Remove selected channel from list")
|
||||
remove_button.clicked.connect(self.on_remove_clicked)
|
||||
button_layout.addWidget(remove_button)
|
||||
|
||||
button_layout.addStretch()
|
||||
|
||||
close_button = QPushButton("Close")
|
||||
close_button.setAccessibleName("Close dialog")
|
||||
close_button.clicked.connect(self.accept)
|
||||
button_layout.addWidget(close_button)
|
||||
|
||||
layout.addLayout(button_layout)
|
||||
|
||||
def load_channels(self):
|
||||
"""Load channels from config into table."""
|
||||
self.table.setRowCount(0)
|
||||
self.table.blockSignals(True) # Prevent itemChanged from firing during load
|
||||
|
||||
for channel_data in self.server_config.known_channels:
|
||||
channel_name = channel_data.get('name', '')
|
||||
autojoin = channel_data.get('autojoin', False)
|
||||
|
||||
if channel_name:
|
||||
self.add_channel_row(channel_name, autojoin)
|
||||
|
||||
self.table.blockSignals(False)
|
||||
logger.info(f"Loaded {self.table.rowCount()} channels")
|
||||
|
||||
def add_channel_row(self, channel_name, autojoin):
|
||||
"""Add a channel row to the table."""
|
||||
row = self.table.rowCount()
|
||||
self.table.insertRow(row)
|
||||
|
||||
# Autojoin checkbox
|
||||
checkbox_item = QTableWidgetItem()
|
||||
checkbox_item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled | Qt.ItemIsSelectable)
|
||||
checkbox_item.setCheckState(Qt.Checked if autojoin else Qt.Unchecked)
|
||||
checkbox_item.setData(Qt.UserRole, channel_name) # Store channel name
|
||||
# Add accessible text for screen readers
|
||||
checkbox_item.setText("Checked" if autojoin else "Unchecked")
|
||||
self.table.setItem(row, 0, checkbox_item)
|
||||
|
||||
# Channel name
|
||||
name_item = QTableWidgetItem(channel_name)
|
||||
name_item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
|
||||
name_item.setData(Qt.UserRole, channel_name)
|
||||
self.table.setItem(row, 1, name_item)
|
||||
|
||||
def on_item_changed(self, item):
|
||||
"""Handle checkbox state change."""
|
||||
if item.column() != 0: # Only handle autojoin column
|
||||
return
|
||||
|
||||
channel_name = item.data(Qt.UserRole)
|
||||
new_state = item.checkState() == Qt.Checked
|
||||
|
||||
logger.info(f"Autojoin changed for {channel_name}: {new_state}")
|
||||
|
||||
# Update config
|
||||
self.config_manager.set_channel_autojoin(
|
||||
self.server_config.name,
|
||||
channel_name,
|
||||
new_state
|
||||
)
|
||||
|
||||
# Update text for screen readers
|
||||
item.setText("Checked" if new_state else "Unchecked")
|
||||
|
||||
def on_item_activated(self, item):
|
||||
"""Handle Enter key or double-click on item."""
|
||||
# Get channel name from the row
|
||||
channel_name = self.table.item(item.row(), 1).data(Qt.UserRole)
|
||||
logger.info(f"Item activated: {channel_name}")
|
||||
|
||||
# Join the channel if IRC client is available
|
||||
if self.irc_client:
|
||||
self.join_channel(channel_name)
|
||||
|
||||
def on_join_clicked(self):
|
||||
"""Handle Join button click."""
|
||||
current_row = self.table.currentRow()
|
||||
if current_row < 0:
|
||||
QMessageBox.warning(self, "No Selection", "Please select a channel to join.")
|
||||
return
|
||||
|
||||
channel_name = self.table.item(current_row, 1).data(Qt.UserRole)
|
||||
self.join_channel(channel_name)
|
||||
|
||||
def join_channel(self, channel_name):
|
||||
"""Join a channel."""
|
||||
if not self.irc_client:
|
||||
QMessageBox.warning(
|
||||
self,
|
||||
"Not Connected",
|
||||
"Cannot join channel - not connected to server."
|
||||
)
|
||||
return
|
||||
|
||||
logger.info(f"Joining channel: {channel_name}")
|
||||
self.irc_client.send_raw(f"JOIN {channel_name}")
|
||||
|
||||
# Close dialog after joining
|
||||
self.accept()
|
||||
|
||||
def on_remove_clicked(self):
|
||||
"""Handle Remove button click."""
|
||||
current_row = self.table.currentRow()
|
||||
if current_row < 0:
|
||||
QMessageBox.warning(self, "No Selection", "Please select a channel to remove.")
|
||||
return
|
||||
|
||||
channel_name = self.table.item(current_row, 1).data(Qt.UserRole)
|
||||
|
||||
reply = QMessageBox.question(
|
||||
self,
|
||||
"Remove Channel",
|
||||
f"Remove {channel_name} from the channel list?",
|
||||
QMessageBox.Yes | QMessageBox.No,
|
||||
QMessageBox.No
|
||||
)
|
||||
|
||||
if reply == QMessageBox.Yes:
|
||||
self.config_manager.remove_channel_from_server(
|
||||
self.server_config.name,
|
||||
channel_name
|
||||
)
|
||||
self.table.removeRow(current_row)
|
||||
logger.info(f"Removed channel: {channel_name}")
|
||||
|
||||
def keyPressEvent(self, event: QKeyEvent):
|
||||
"""Handle key press events."""
|
||||
if event.key() == Qt.Key_Escape:
|
||||
logger.info("Escape pressed, closing dialog")
|
||||
self.accept()
|
||||
else:
|
||||
super().keyPressEvent(event)
|
||||
Reference in New Issue
Block a user