Skip to content

Commit

Permalink
feat: Sorting list
Browse files Browse the repository at this point in the history
  • Loading branch information
dsafxP committed Dec 14, 2024
1 parent ee30b77 commit 8b17798
Showing 1 changed file with 87 additions and 39 deletions.
126 changes: 87 additions & 39 deletions gui.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import tkinter as tk
from tkinter import ttk
import asyncio
import threading
from app.fetcher import fetch_game_servers
Expand All @@ -12,13 +13,26 @@ def __init__(self, root):
# Set a custom icon
self.root.iconbitmap("img/SFDicon.ico") # Replace with your .ico file path

# Create the Listbox to display server names
self.listbox = tk.Listbox(self.root, width=80, height=15)
self.listbox.pack(fill=tk.BOTH, expand=True) # Make it fill the entire window
# Create the Treeview to display server data with sorting capabilities
self.treeview = ttk.Treeview(self.root, columns=("Game Name", "Game Mode", "Players", "Password", "Version"), show="headings")
self.treeview.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

# Create a Text widget to display the server details
self.details_text = tk.Text(self.root, height=8, wrap=tk.WORD)
self.details_text.pack(fill=tk.X, padx=10, pady=10) # Fill horizontally, with padding
# Define column headings and configure column widths
self.treeview.heading("Game Name", text="Game Name", command=lambda: self.sort_treeview("Game Name"))
self.treeview.heading("Game Mode", text="Game Mode", command=lambda: self.sort_treeview("Game Mode"))
self.treeview.heading("Players", text="Players", command=lambda: self.sort_treeview("Players"))
self.treeview.heading("Password", text="Password", command=lambda: self.sort_treeview("Password"))
self.treeview.heading("Version", text="Version", command=lambda: self.sort_treeview("Version"))

self.treeview.column("Game Name", width=100, anchor=tk.W)
self.treeview.column("Game Mode", width=100, anchor=tk.W)
self.treeview.column("Players", width=100, anchor=tk.W)
self.treeview.column("Password", width=100, anchor=tk.W)
self.treeview.column("Version", width=100, anchor=tk.W)

# Create a frame for the detailed information below the list
self.details_frame = tk.Frame(self.root)
self.details_frame.pack(fill=tk.X, padx=10, pady=10)

self.servers = None

Expand All @@ -28,8 +42,8 @@ def __init__(self, root):
# Start the periodic fetch operation
self.start_auto_fetch()

# Bind left-click on the listbox to display server details
self.listbox.bind('<Button-1>', self.on_server_select)
# Bind left-click on the Treeview to display server details
self.treeview.bind('<ButtonRelease-1>', self.on_server_select)

def fetch_servers(self):
"""Fetch servers in a new thread so the UI doesn't freeze."""
Expand All @@ -40,49 +54,83 @@ def run_fetch_game_servers(self):
asyncio.run(fetch_game_servers(callback=self.update_server_list))

def update_server_list(self, servers):
"""Update the Listbox with the server list."""
"""Update the Treeview with the server list."""
self.servers = servers # Store the server list as an attribute for later use
self.listbox.delete(0, tk.END) # Clear the listbox before updating
for item in self.treeview.get_children():
self.treeview.delete(item) # Clear the existing entries in the Treeview

if not servers:
self.listbox.insert(tk.END, "No servers found.")
self.treeview.insert("", "end", values=("No servers found", "", "", ""))
else:
for server in servers:
self.listbox.insert(tk.END, server.game_name)
self.treeview.insert("", "end", values=(
server.game_name,
server.get_game_mode(),
f"{server.players}/{server.max_players}",
"Yes" if server.has_password else "No",
server.version
))

def on_server_select(self, event):
"""Handle left-click on a server in the listbox."""
selected_index = self.listbox.curselection() # Get the index of the selected item
if selected_index:
# Get the selected server object (using the index)
selected_server = self.servers[selected_index[0]]

# Show detailed information in the Text widget
server_details = (
f"Game Name: {selected_server.game_name}\n"
f"Game Mode: {selected_server.get_game_mode()}\n"
f"Address (IPv4): {selected_server.address_ipv4}\n"
#f"Address (IPv6): {selected_server.address_ipv6}\n"
#f"LIP: {selected_server.lip}\n"
f"Port: {selected_server.port}\n"
f"Map Name: {selected_server.map_name}\n"
f"Players: {selected_server.players}/{selected_server.max_players}\n"
f"Bots: {selected_server.bots}\n"
f"Password Protected: {'Yes' if selected_server.has_password else 'No'}\n"
f"Version: {selected_server.version}\n"
#f"Version Number: {selected_server.version_nr}\n"
#f"Application Instance: {selected_server.application_instance}\n"
)

# Clear and insert the server details in the Text widget
self.details_text.delete(1.0, tk.END)
self.details_text.insert(tk.END, server_details)
"""Handle left-click on a server in the Treeview."""
selected_item = self.treeview.selection() # Get the selected item
if selected_item:
# Get the corresponding server object for the selected item
selected_server = None
for item in selected_item:
# Find the server object based on the item value (server game name or other unique info)
for server in self.servers:
if server.game_name == self.treeview.item(item)["values"][0]: # Match by game name (or any unique identifier)
selected_server = server
break

if selected_server:
# Create detailed information for the selected server
server_details = (
f"Game Name: {selected_server.game_name}\n"
f"Game Mode: {selected_server.get_game_mode()}\n"
f"Address (IPv4): {selected_server.address_ipv4}\n"
f"Port: {selected_server.port}\n"
f"Map Name: {selected_server.map_name}\n"
f"Players: {selected_server.players}/{selected_server.max_players}\n"
f"Bots: {selected_server.bots}\n"
f"Password Protected: {'Yes' if selected_server.has_password else 'No'}\n"
f"Version: {selected_server.version}\n"
)

# Clear previous details in the frame
for widget in self.details_frame.winfo_children():
widget.destroy()

# Create a Label for the server details and pack it in the frame
details_label = tk.Label(self.details_frame, text=server_details, justify=tk.LEFT)
details_label.pack(fill=tk.X, padx=10, pady=5)


def sort_treeview(self, col):
"""Sort the Treeview by the selected column."""
column_index = self.treeview["columns"].index(col)
items = [(self.treeview.item(item)["values"], item) for item in self.treeview.get_children()]

if col == "Players":
# Sort by the current players (extracted from the format current_players/max_players)
items.sort(key=lambda x: int(x[0][2].split('/')[0]), reverse=True) # Sorting by current players
elif col == "Password":
# Sort by password status (No should come before yes)
items.sort(key=lambda x: x[0][3] == "Yes", reverse=False) # False (No) comes first
else:
# Default sorting for other columns (Game Name, Game Mode, Version)
items.sort(key=lambda x: x[0][column_index]) # Alphabetical sorting for text columns

# Re-insert sorted items into the Treeview
for i, (_, item) in enumerate(items):
self.treeview.move(item, '', i)

def start_auto_fetch(self):
"""Start a periodic task to fetch game servers automatically."""
self.fetch_servers() # Fetch servers immediately
self.root.after(self.fetch_interval,
self.start_auto_fetch) # Set the next fetch after the interval
self.start_auto_fetch) # Set the next fetch after the interval

def run_gui():
"""Set up the main Tkinter GUI window and start the application."""
Expand Down

0 comments on commit 8b17798

Please sign in to comment.