windows fixes

This commit is contained in:
2025-11-24 07:12:47 +01:00
parent 4fdceb46ff
commit 3cd75d97f6
2 changed files with 103 additions and 75 deletions

BIN
icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

178
main.py
View File

@@ -518,13 +518,15 @@ class IRCPanel(wx.Panel):
sizer = wx.BoxSizer(wx.VERTICAL)
# Use a better font for chat
# Use a better font for chat with white theme
self.text_ctrl = wx.TextCtrl(self, style=wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_RICH2 | wx.TE_AUTO_URL)
self.text_ctrl.SetBackgroundColour(wx.Colour(30, 30, 30))
self.text_ctrl.SetForegroundColour(wx.Colour(220, 220, 220))
# Load Fira Code font
self.font = self.load_fira_code_font()
# White theme colors
self.text_ctrl.SetBackgroundColour(wx.Colour(255, 255, 255)) # White background
self.text_ctrl.SetForegroundColour(wx.Colour(0, 0, 0)) # Black text
# Load appropriate font
self.font = self.load_system_font()
self.text_ctrl.SetFont(self.font)
sizer.Add(self.text_ctrl, 1, wx.EXPAND | wx.ALL, 0)
@@ -560,39 +562,46 @@ class IRCPanel(wx.Panel):
self.SetAcceleratorTable(accel_tbl)
self.Bind(wx.EVT_MENU, self.on_search, id=wx.ID_FIND)
def load_fira_code_font(self):
"""Load Fira Code font from resources"""
def load_system_font(self):
"""Load appropriate system font with high DPI support"""
try:
# Try to use Fira Code if available
font_path = get_resource_path("FiraCode-Regular.ttf")
# Get system DPI scale factor
dc = wx.ClientDC(self)
dpi_scale = dc.GetPPI().GetWidth() / 96.0 # 96 is standard DPI
if os.path.exists(font_path):
# On wxPython 4.1+, we can try to add the font to the font manager
try:
font_collection = wx.private.FontCollection()
if font_collection.AddFont(font_path):
font = wx.Font(10, wx.FONTFAMILY_TELETYPE, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL,
False, "Fira Code")
if font.IsOk():
logger.info("Successfully loaded Fira Code font")
return font
except Exception:
pass
# Fallback: try to create font by name
font = wx.Font(wx.FontInfo(10).Family(wx.FONTFAMILY_TELETYPE).FaceName("Fira Code"))
if font.IsOk():
logger.info("Using Fira Code font via FaceName")
return font
# Calculate base font size based on DPI
base_size = 10
if dpi_scale > 1.5:
font_size = int(base_size * 1.5) # 150% scaling
elif dpi_scale > 1.25:
font_size = int(base_size * 1.25) # 125% scaling
else:
logger.warning("FiraCode-Regular.ttf not found in resources")
font_size = base_size
# Try system fonts in order of preference
font_families = [
(wx.FONTFAMILY_TELETYPE, "Consolas"),
(wx.FONTFAMILY_TELETYPE, "Courier New"),
(wx.FONTFAMILY_TELETYPE, "Monaco"),
(wx.FONTFAMILY_TELETYPE, "DejaVu Sans Mono"),
(wx.FONTFAMILY_TELETYPE, "Liberation Mono"),
]
for family, face_name in font_families:
font = wx.Font(font_size, family, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, face_name)
if font.IsOk():
logger.info(f"Using font: {face_name} at {font_size}pt")
return font
# Fallback to default monospace
font = wx.Font(font_size, wx.FONTFAMILY_TELETYPE, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
logger.info("Using system monospace font as fallback")
return font
except Exception as e:
logger.error(f"Error loading Fira Code font: {e}")
# Fall back to system monospace font
font = wx.Font(10, wx.FONTFAMILY_TELETYPE, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
logger.info("Using system monospace font as fallback")
return font
logger.error(f"Error loading system font: {e}")
# Ultimate fallback
return wx.Font(10, wx.FONTFAMILY_TELETYPE, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
def set_target(self, target):
self.target = target
@@ -635,7 +644,7 @@ class IRCPanel(wx.Panel):
if message_color:
attr.SetTextColour(message_color)
else:
attr.SetTextColour(wx.Colour(220, 220, 220))
attr.SetTextColour(wx.Colour(0, 0, 0)) # Black text for white theme
attr.SetFont(self.font)
self.text_ctrl.SetDefaultStyle(attr)
@@ -658,10 +667,10 @@ class IRCPanel(wx.Panel):
try:
if is_action:
message = f"{timestamp}* {username} {content}"
self.add_message(message, f"* {username}", username_color, wx.Colour(255, 150, 255), italic=True)
self.add_message(message, f"* {username}", username_color, wx.Colour(128, 0, 128), italic=True) # Dark purple for actions
else:
message = f"{timestamp}<{username}> {content}"
self.add_message(message, f"<{username}>", username_color, wx.Colour(220, 220, 220))
self.add_message(message, f"<{username}>", username_color, wx.Colour(0, 0, 0)) # Black text
except Exception as e:
logger.error(f"Error adding formatted message: {e}")
@@ -669,7 +678,7 @@ class IRCPanel(wx.Panel):
"""Add system message without username coloring"""
try:
if color is None:
color = wx.Colour(180, 180, 255)
color = wx.Colour(0, 0, 128) # Dark blue for system messages
self.add_message(message, None, None, color, bold, False, False)
except Exception as e:
logger.error(f"Error adding system message: {e}")
@@ -868,6 +877,9 @@ class IRCFrame(wx.Frame):
def __init__(self):
super().__init__(None, title="wxIRC", size=(1200, 700))
# Apply white theme
self.apply_white_theme()
# Show privacy notice first
self.show_privacy_notice()
@@ -891,21 +903,21 @@ class IRCFrame(wx.Frame):
self.away = False
self.timestamps = True
# User color mapping
# User color mapping - darker colors for white theme
self.user_colors = {}
self.available_colors = [
wx.Colour(255, 150, 150), # Light red
wx.Colour(150, 255, 150), # Light green
wx.Colour(150, 200, 255), # Light blue
wx.Colour(255, 255, 150), # Light yellow
wx.Colour(255, 150, 255), # Light magenta
wx.Colour(150, 255, 255), # Light cyan
wx.Colour(255, 200, 150), # Light orange
wx.Colour(200, 150, 255), # Light purple
wx.Colour(255, 200, 200), # Pink
wx.Colour(200, 255, 200), # Mint
wx.Colour(200, 200, 255), # Lavender
wx.Colour(255, 255, 200), # Cream
wx.Colour(178, 34, 34), # Firebrick red
wx.Colour(0, 100, 0), # Dark green
wx.Colour(0, 0, 139), # Dark blue
wx.Colour(139, 69, 19), # Saddle brown
wx.Colour(139, 0, 139), # Dark magenta
wx.Colour(0, 139, 139), # Dark cyan
wx.Colour(210, 105, 30), # Chocolate
wx.Colour(75, 0, 130), # Indigo
wx.Colour(178, 34, 34), # Firebrick
wx.Colour(0, 128, 128), # Teal
wx.Colour(72, 61, 139), # Dark slate blue
wx.Colour(139, 0, 0), # Dark red
]
self.color_index = 0
@@ -939,6 +951,19 @@ class IRCFrame(wx.Frame):
self.Bind(wx.EVT_MENU, self.on_find_previous, id=1002)
self.Bind(wx.EVT_MENU, self.on_quick_escape, id=1003)
def apply_white_theme(self):
"""Apply white theme to the application"""
try:
# Set system colors for white theme
self.SetBackgroundColour(wx.Colour(255, 255, 255))
self.SetForegroundColour(wx.Colour(0, 0, 0))
# Set system settings for light theme
sys_settings = wx.SystemSettings()
except Exception as e:
logger.error(f"Error applying white theme: {e}")
def show_privacy_notice(self):
"""Show privacy notice dialog at startup"""
dlg = PrivacyNoticeDialog(self)
@@ -1002,13 +1027,14 @@ class IRCFrame(wx.Frame):
return None
def setup_ui(self):
"""Setup UI components"""
"""Setup UI components with white theme"""
panel = wx.Panel(self)
panel.SetBackgroundColour(wx.Colour(255, 255, 255)) # White background
main_sizer = wx.BoxSizer(wx.HORIZONTAL)
# Left sidebar
# Left sidebar - light gray for contrast
left_panel = wx.Panel(panel)
left_panel.SetBackgroundColour(wx.Colour(45, 45, 45))
left_panel.SetBackgroundColour(wx.Colour(240, 240, 240)) # Light gray
left_sizer = wx.BoxSizer(wx.VERTICAL)
conn_box = wx.StaticBox(left_panel, label="Connection")
@@ -1068,6 +1094,7 @@ class IRCFrame(wx.Frame):
# Center - Notebook
self.notebook = wx.Notebook(panel)
self.notebook.SetBackgroundColour(wx.Colour(255, 255, 255))
# Server panel
server_panel = IRCPanel(self.notebook, self)
@@ -1075,9 +1102,9 @@ class IRCFrame(wx.Frame):
self.notebook.AddPage(server_panel, "Server")
self.channels["SERVER"] = server_panel
# Right sidebar - Users
# Right sidebar - Users - light gray for contrast
right_panel = wx.Panel(panel)
right_panel.SetBackgroundColour(wx.Colour(45, 45, 45))
right_panel.SetBackgroundColour(wx.Colour(240, 240, 240)) # Light gray
right_sizer = wx.BoxSizer(wx.VERTICAL)
users_box = wx.StaticBox(right_panel, label="Users")
@@ -1232,7 +1259,7 @@ class IRCFrame(wx.Frame):
if hasattr(event, 'arguments') and event.arguments:
event_info += f" - {' '.join(event.arguments)}"
self.log_server(event_info, wx.Colour(180, 180, 255), italic=True)
self.log_server(event_info, wx.Colour(0, 0, 128), italic=True) # Dark blue for raw events
except Exception as e:
logger.error(f"Error in all_events handler: {e}")
@@ -1259,19 +1286,19 @@ class IRCFrame(wx.Frame):
try:
self.port = int(self.port_ctrl.GetValue())
except ValueError:
self.safe_ui_update(self.log_server, "Invalid port number", wx.Colour(255, 100, 100))
self.safe_ui_update(self.log_server, "Invalid port number", wx.Colour(255, 0, 0))
self.is_connecting = False
return
self.nick = self.nick_ctrl.GetValue()
if not self.server or not self.nick:
self.safe_ui_update(self.log_server, "Server and nick are required", wx.Colour(255, 100, 100))
self.safe_ui_update(self.log_server, "Server and nick are required", wx.Colour(255, 0, 0))
self.is_connecting = False
return
self.safe_ui_update(self.connect_btn.Enable, False)
self.safe_ui_update(self.log_server, f"Connecting to {self.server}:{self.port} as {self.nick}...", wx.Colour(150, 150, 255))
self.safe_ui_update(self.log_server, f"Connecting to {self.server}:{self.port} as {self.nick}...", wx.Colour(0, 0, 128))
def connect_thread():
try:
@@ -1320,7 +1347,7 @@ class IRCFrame(wx.Frame):
self.reactor.process_forever()
except Exception as e:
logger.error(f"Reactor loop error: {e}")
self.safe_ui_update(self.log_server, f"Connection error: {e}", wx.Colour(255, 100, 100))
self.safe_ui_update(self.log_server, f"Connection error: {e}", wx.Colour(255, 0, 0))
self.safe_ui_update(self.on_disconnect_cleanup)
def on_connect_success(self):
@@ -1334,7 +1361,7 @@ class IRCFrame(wx.Frame):
def on_connect_failed(self, error_msg):
"""Handle connection failure"""
self.is_connecting = False
self.log_server(error_msg, wx.Colour(255, 100, 100))
self.log_server(error_msg, wx.Colour(255, 0, 0))
self.connect_btn.Enable(True)
self.SetStatusText("Connection failed")
logger.error(f"Connection failed: {error_msg}")
@@ -1376,7 +1403,7 @@ class IRCFrame(wx.Frame):
self.safe_ui_update(self.connect_btn.SetLabel, "Connect")
self.safe_ui_update(self.connect_btn.Enable, True)
self.safe_ui_update(self.SetStatusText, "Disconnected")
self.safe_ui_update(self.log_server, "Disconnected from server", wx.Colour(255, 100, 100))
self.safe_ui_update(self.log_server, "Disconnected from server", wx.Colour(255, 0, 0))
def on_join_channel(self, event):
try:
@@ -1388,7 +1415,7 @@ class IRCFrame(wx.Frame):
self.channel_input.Clear()
except Exception as e:
logger.error(f"Error joining channel: {e}")
self.safe_ui_update(self.log_server, f"Error joining channel: {e}", wx.Colour(255, 100, 100))
self.safe_ui_update(self.log_server, f"Error joining channel: {e}", wx.Colour(255, 0, 0))
def on_channel_select(self, event):
try:
@@ -1505,7 +1532,7 @@ class IRCFrame(wx.Frame):
self.channels[target].add_formatted_message(timestamp, self.nick, message, user_color)
except Exception as e:
logger.error(f"Error sending message: {e}")
self.safe_ui_update(self.log_server, f"Error sending message: {e}", wx.Colour(255, 100, 100))
self.safe_ui_update(self.log_server, f"Error sending message: {e}", wx.Colour(255, 0, 0))
def handle_command(self, target, message):
try:
@@ -1528,7 +1555,7 @@ Available commands:
/quit [message] - Disconnect from server
/help - Show this help
"""
self.log_server(help_text, wx.Colour(200, 255, 200))
self.log_server(help_text, wx.Colour(0, 100, 0)) # Dark green for help
elif cmd == "me":
if self.is_connected():
self.connection.action(target, args)
@@ -1568,10 +1595,10 @@ Available commands:
self.away = bool(args)
self.safe_ui_update(self.away_item.Check, self.away)
else:
self.safe_ui_update(self.log_server, f"Unknown command: {cmd}. Use /help for available commands.", wx.Colour(255, 100, 100))
self.safe_ui_update(self.log_server, f"Unknown command: {cmd}. Use /help for available commands.", wx.Colour(255, 0, 0))
except Exception as e:
logger.error(f"Error handling command: {e}")
self.safe_ui_update(self.log_server, f"Error executing command: {e}", wx.Colour(255, 100, 100))
self.safe_ui_update(self.log_server, f"Error executing command: {e}", wx.Colour(255, 0, 0))
def part_channel(self, channel):
try:
@@ -1767,13 +1794,14 @@ COMMANDS (type /help in chat for full list):
/nick newname - Change nickname
/away [message] - Set away status
"""
self.log_server(help_text, wx.Colour(200, 255, 200), bold=True)
self.log_server(help_text, wx.Colour(0, 100, 0), bold=True) # Dark green for help
# IRC Event Handlers - All use thread-safe UI updates
def on_welcome(self, connection, event):
try:
self.log_server("Connected to server!", wx.Colour(100, 255, 100), bold=True)
self.log_server(f"Welcome message: {' '.join(event.arguments)}", wx.Colour(150, 255, 150))
self.log_server("Connected to server!", wx.Colour(0, 128, 0), bold=True) # Dark green
self.log_server(f"Welcome message: {' '.join(event.arguments)}", wx.Colour(0, 100, 0))
# Auto-join channels
for channel in self.auto_join_channels:
@@ -1792,7 +1820,7 @@ COMMANDS (type /help in chat for full list):
if nick == self.nick:
self.safe_ui_update(self.add_channel, channel)
self.log_server(f"Joined channel {channel}", wx.Colour(100, 255, 100))
self.log_server(f"Joined channel {channel}", wx.Colour(0, 128, 0)) # Dark green
self.log_channel_message(channel, nick, f"{nick} joined", is_system=True)
@@ -1900,7 +1928,7 @@ COMMANDS (type /help in chat for full list):
if old_nick == self.nick:
self.nick = new_nick
self.log_server(f"You are now known as {new_nick}", wx.Colour(150, 200, 255), bold=True)
self.log_server(f"You are now known as {new_nick}", wx.Colour(0, 0, 128), bold=True) # Dark blue
for channel in self.channel_users:
if old_nick in self.channel_users[channel]:
@@ -1928,13 +1956,13 @@ COMMANDS (type /help in chat for full list):
nick = event.source.nick if hasattr(event.source, 'nick') else str(event.source)
message = event.arguments[0]
self.log_server(f"-{nick}- {message}", wx.Colour(255, 150, 255), italic=True)
self.log_server(f"-{nick}- {message}", wx.Colour(128, 0, 128), italic=True) # Dark purple for notices
except Exception as e:
logger.error(f"Error in notice handler: {e}")
def on_disconnect(self, connection, event):
try:
self.log_server("Disconnected from server", wx.Colour(255, 100, 100), bold=True)
self.log_server("Disconnected from server", wx.Colour(255, 0, 0), bold=True) # Red for disconnect
self.safe_ui_update(self.on_disconnect_cleanup)
except Exception as e:
logger.error(f"Error in disconnect handler: {e}")