""" EquipmentDialog - диалог управления оборудованием (tkinter) """ import tkinter as tk from tkinter import ttk, messagebox from threading import Thread class EquipmentDialog(tk.Toplevel): """Диалог для управления оборудованием""" def __init__(self, parent, config_service): super().__init__(parent) self.parent = parent self.config_service = config_service self.cameras = self.config_service.get_cameras() self.lenses = self.config_service.get_lenses() self.telescopes = self.config_service.get_telescopes() self.selected_camera = None self.selected_lens = None self.selected_telescope = None self.title("Manage Equipment") self.geometry("750x500") self.minsize(700, 450) self.transient(parent) self.grab_set() self._create_ui() self._center_window() def _create_ui(self): # Notebook for tabs notebook = ttk.Notebook(self) notebook.pack(fill='both', expand=True, padx=10, pady=10) # Tab 1: Cameras cameras_frame = ttk.Frame(notebook) notebook.add(cameras_frame, text="Cameras") self._create_cameras_tab(cameras_frame) # Tab 2: Lenses lenses_frame = ttk.Frame(notebook) notebook.add(lenses_frame, text="Lenses") self._create_lenses_tab(lenses_frame) # Tab 3: Telescopes telescopes_frame = ttk.Frame(notebook) notebook.add(telescopes_frame, text="Telescopes") self._create_telescopes_tab(telescopes_frame) # Close button btn_frame = ttk.Frame(self) btn_frame.pack(pady=10) ttk.Button(btn_frame, text="Close", command=self.destroy).pack() def _center_window(self): self.update_idletasks() x = self.parent.winfo_x() + (self.parent.winfo_width() // 2) - (self.winfo_width() // 2) y = self.parent.winfo_y() + (self.parent.winfo_height() // 2) - (self.winfo_height() // 2) self.geometry(f'+{x}+{y}') def _create_cameras_tab(self, parent): # Listbox list_frame = ttk.Frame(parent) list_frame.pack(fill='both', expand=True, padx=10, pady=10) scrollbar = ttk.Scrollbar(list_frame) scrollbar.pack(side='right', fill='y') self.cameras_listbox = tk.Listbox(list_frame, yscrollcommand=scrollbar.set, bg='#2d2d2d', fg='#e0e0e0', selectbackground='#4CAF50', selectforeground='white', font=('Segoe UI', 10)) self.cameras_listbox.pack(fill='both', expand=True) scrollbar.config(command=self.cameras_listbox.yview) for camera in self.cameras: self.cameras_listbox.insert('end', camera) self.cameras_listbox.bind('<>', self._on_camera_select) # Buttons btn_frame = ttk.Frame(parent) btn_frame.pack(pady=10) ttk.Button(btn_frame, text="Add Camera", command=self._add_camera).pack(side='left', padx=5) self.remove_camera_btn = ttk.Button(btn_frame, text="Remove", command=self._remove_camera, state='disabled') self.remove_camera_btn.pack(side='left', padx=5) self.edit_camera_btn = ttk.Button(btn_frame, text="Edit", command=self._edit_camera, state='disabled') self.edit_camera_btn.pack(side='left', padx=5) def _on_camera_select(self, event): selection = self.cameras_listbox.curselection() if selection: self.selected_camera = self.cameras_listbox.get(selection[0]) self.remove_camera_btn.config(state='normal') self.edit_camera_btn.config(state='normal') def _add_camera(self): dialog = tk.Toplevel(self) dialog.title("Add Camera") dialog.geometry("350x120") dialog.transient(self) dialog.grab_set() ttk.Label(dialog, text="Camera name:", font=('Segoe UI', 10)).pack(pady=15) entry = ttk.Entry(dialog, width=40) entry.pack(pady=5) entry.focus() def save(): new_camera = entry.get().strip() if new_camera: if new_camera in self.cameras: messagebox.showerror("Error", "Camera already exists!", parent=dialog) return self.cameras.append(new_camera) self.config_service.add_camera(new_camera) self.cameras_listbox.insert('end', new_camera) dialog.destroy() else: messagebox.showwarning("Warning", "Please enter camera name!", parent=dialog) ttk.Button(dialog, text="OK", command=save).pack(pady=10) dialog.bind('', lambda e: save()) def _remove_camera(self): if self.selected_camera: reply = messagebox.askyesno("Remove Camera", f"Remove '{self.selected_camera}'?", parent=self) if reply: self.cameras.remove(self.selected_camera) self.config_service.remove_camera(self.selected_camera) self.cameras_listbox.delete(0, 'end') for camera in self.cameras: self.cameras_listbox.insert('end', camera) self.selected_camera = None self.remove_camera_btn.config(state='disabled') self.edit_camera_btn.config(state='disabled') def _edit_camera(self): if self.selected_camera: dialog = tk.Toplevel(self) dialog.title("Edit Camera") dialog.geometry("350x120") dialog.transient(self) dialog.grab_set() ttk.Label(dialog, text="New camera name:", font=('Segoe UI', 10)).pack(pady=15) entry = ttk.Entry(dialog, width=40) entry.insert(0, self.selected_camera) entry.pack(pady=5) entry.focus() def save(): new_name = entry.get().strip() if new_name and new_name != self.selected_camera: if new_name in self.cameras: messagebox.showerror("Error", "Camera already exists!", parent=dialog) return idx = self.cameras.index(self.selected_camera) self.cameras[idx] = new_name self.config_service.remove_camera(self.selected_camera) self.config_service.add_camera(new_name) self.cameras_listbox.delete(0, 'end') for camera in self.cameras: self.cameras_listbox.insert('end', camera) self.selected_camera = new_name dialog.destroy() elif new_name == self.selected_camera: dialog.destroy() else: messagebox.showwarning("Warning", "Please enter a name!", parent=dialog) ttk.Button(dialog, text="Save", command=save).pack(pady=10) dialog.bind('', lambda e: save()) def _create_lenses_tab(self, parent): # Listbox list_frame = ttk.Frame(parent) list_frame.pack(fill='both', expand=True, padx=10, pady=10) scrollbar = ttk.Scrollbar(list_frame) scrollbar.pack(side='right', fill='y') self.lenses_listbox = tk.Listbox(list_frame, yscrollcommand=scrollbar.set, bg='#2d2d2d', fg='#e0e0e0', selectbackground='#4CAF50', selectforeground='white', font=('Segoe UI', 10)) self.lenses_listbox.pack(fill='both', expand=True) scrollbar.config(command=self.lenses_listbox.yview) for lens in self.lenses: self.lenses_listbox.insert('end', lens) self.lenses_listbox.bind('<>', self._on_lens_select) # Buttons btn_frame = ttk.Frame(parent) btn_frame.pack(pady=10) ttk.Button(btn_frame, text="Add Lens", command=self._add_lens).pack(side='left', padx=5) self.remove_lens_btn = ttk.Button(btn_frame, text="Remove", command=self._remove_lens, state='disabled') self.remove_lens_btn.pack(side='left', padx=5) self.edit_lens_btn = ttk.Button(btn_frame, text="Edit", command=self._edit_lens, state='disabled') self.edit_lens_btn.pack(side='left', padx=5) def _on_lens_select(self, event): selection = self.lenses_listbox.curselection() if selection: self.selected_lens = self.lenses_listbox.get(selection[0]) self.remove_lens_btn.config(state='normal') self.edit_lens_btn.config(state='normal') def _add_lens(self): dialog = tk.Toplevel(self) dialog.title("Add Lens") dialog.geometry("350x120") dialog.transient(self) dialog.grab_set() ttk.Label(dialog, text="Lens name:", font=('Segoe UI', 10)).pack(pady=15) entry = ttk.Entry(dialog, width=40) entry.pack(pady=5) entry.focus() def save(): new_lens = entry.get().strip() if new_lens: if new_lens in self.lenses: messagebox.showerror("Error", "Lens already exists!", parent=dialog) return self.lenses.append(new_lens) self.config_service.add_lens(new_lens) self.lenses_listbox.insert('end', new_lens) dialog.destroy() else: messagebox.showwarning("Warning", "Please enter lens name!", parent=dialog) ttk.Button(dialog, text="OK", command=save).pack(pady=10) dialog.bind('', lambda e: save()) def _remove_lens(self): if self.selected_lens: reply = messagebox.askyesno("Remove Lens", f"Remove '{self.selected_lens}'?", parent=self) if reply: self.lenses.remove(self.selected_lens) self.config_service.remove_lens(self.selected_lens) self.lenses_listbox.delete(0, 'end') for lens in self.lenses: self.lenses_listbox.insert('end', lens) self.selected_lens = None self.remove_lens_btn.config(state='disabled') self.edit_lens_btn.config(state='disabled') def _edit_lens(self): if self.selected_lens: dialog = tk.Toplevel(self) dialog.title("Edit Lens") dialog.geometry("350x120") dialog.transient(self) dialog.grab_set() ttk.Label(dialog, text="New lens name:", font=('Segoe UI', 10)).pack(pady=15) entry = ttk.Entry(dialog, width=40) entry.insert(0, self.selected_lens) entry.pack(pady=5) entry.focus() def save(): new_name = entry.get().strip() if new_name and new_name != self.selected_lens: if new_name in self.lenses: messagebox.showerror("Error", "Lens already exists!", parent=dialog) return idx = self.lenses.index(self.selected_lens) self.lenses[idx] = new_name self.config_service.remove_lens(self.selected_lens) self.config_service.add_lens(new_name) self.lenses_listbox.delete(0, 'end') for lens in self.lenses: self.lenses_listbox.insert('end', lens) self.selected_lens = new_name dialog.destroy() elif new_name == self.selected_lens: dialog.destroy() else: messagebox.showwarning("Warning", "Please enter a name!", parent=dialog) ttk.Button(dialog, text="Save", command=save).pack(pady=10) dialog.bind('', lambda e: save()) def _create_telescopes_tab(self, parent): # Listbox list_frame = ttk.Frame(parent) list_frame.pack(fill='both', expand=True, padx=10, pady=10) scrollbar = ttk.Scrollbar(list_frame) scrollbar.pack(side='right', fill='y') self.telescopes_listbox = tk.Listbox(list_frame, yscrollcommand=scrollbar.set, bg='#2d2d2d', fg='#e0e0e0', selectbackground='#4CAF50', selectforeground='white', font=('Segoe UI', 10)) self.telescopes_listbox.pack(fill='both', expand=True) scrollbar.config(command=self.telescopes_listbox.yview) for telescope in self.telescopes: self.telescopes_listbox.insert('end', telescope) self.telescopes_listbox.bind('<>', self._on_telescope_select) # Buttons btn_frame = ttk.Frame(parent) btn_frame.pack(pady=10) ttk.Button(btn_frame, text="Add Telescope", command=self._add_telescope).pack(side='left', padx=5) self.remove_telescope_btn = ttk.Button(btn_frame, text="Remove", command=self._remove_telescope, state='disabled') self.remove_telescope_btn.pack(side='left', padx=5) self.edit_telescope_btn = ttk.Button(btn_frame, text="Edit", command=self._edit_telescope, state='disabled') self.edit_telescope_btn.pack(side='left', padx=5) def _on_telescope_select(self, event): selection = self.telescopes_listbox.curselection() if selection: self.selected_telescope = self.telescopes_listbox.get(selection[0]) self.remove_telescope_btn.config(state='normal') self.edit_telescope_btn.config(state='normal') def _add_telescope(self): dialog = tk.Toplevel(self) dialog.title("Add Telescope") dialog.geometry("400x320") dialog.transient(self) dialog.grab_set() ttk.Label(dialog, text="Telescope name:").pack(pady=(15, 5)) name_entry = ttk.Entry(dialog, width=40) name_entry.pack() ttk.Label(dialog, text="Aperture (f/):").pack(pady=(10, 5)) aperture_entry = ttk.Entry(dialog, width=20) aperture_entry.insert(0, "5.0") aperture_entry.pack() ttk.Label(dialog, text="Focal length (mm):").pack(pady=(10, 5)) focal_entry = ttk.Entry(dialog, width=20) focal_entry.insert(0, "1000") focal_entry.pack() ttk.Label(dialog, text="Diameter (mm):").pack(pady=(10, 5)) diameter_entry = ttk.Entry(dialog, width=20) diameter_entry.insert(0, "200") diameter_entry.pack() def save(): name = name_entry.get().strip() if not name: messagebox.showerror("Error", "Please enter telescope name!", parent=dialog) return try: aperture = float(aperture_entry.get()) focal = int(focal_entry.get()) diameter = int(diameter_entry.get()) except ValueError: messagebox.showerror("Error", "Invalid numeric values!", parent=dialog) return telescope_info = f"{name} (f/{aperture}, F={focal}mm, D={diameter}mm)" if telescope_info in self.telescopes: messagebox.showerror("Error", "Telescope already exists!", parent=dialog) return self.telescopes.append(telescope_info) self.config_service.add_telescope(telescope_info) self.telescopes_listbox.insert('end', telescope_info) dialog.destroy() btn_frame = ttk.Frame(dialog) btn_frame.pack(pady=20) ttk.Button(btn_frame, text="OK", command=save).pack(side='left', padx=10) ttk.Button(btn_frame, text="Cancel", command=dialog.destroy).pack(side='left', padx=10) def _remove_telescope(self): if self.selected_telescope: reply = messagebox.askyesno("Remove Telescope", f"Remove '{self.selected_telescope}'?", parent=self) if reply: self.telescopes.remove(self.selected_telescope) self.config_service.remove_telescope(self.selected_telescope) self.telescopes_listbox.delete(0, 'end') for telescope in self.telescopes: self.telescopes_listbox.insert('end', telescope) self.selected_telescope = None self.remove_telescope_btn.config(state='disabled') self.edit_telescope_btn.config(state='disabled') def _edit_telescope(self): if self.selected_telescope: import re match = re.search(r'(.+?) \(f/([\d\.]+), F=(\d+)mm, D=(\d+)mm\)', self.selected_telescope) if match: old_name = match.group(1) old_aperture = match.group(2) old_focal = match.group(3) old_diameter = match.group(4) else: old_name = self.selected_telescope old_aperture = "5.0" old_focal = "1000" old_diameter = "200" dialog = tk.Toplevel(self) dialog.title("Edit Telescope") dialog.geometry("400x320") dialog.transient(self) dialog.grab_set() ttk.Label(dialog, text="Telescope name:").pack(pady=(15, 5)) name_entry = ttk.Entry(dialog, width=40) name_entry.insert(0, old_name) name_entry.pack() ttk.Label(dialog, text="Aperture (f/):").pack(pady=(10, 5)) aperture_entry = ttk.Entry(dialog, width=20) aperture_entry.insert(0, old_aperture) aperture_entry.pack() ttk.Label(dialog, text="Focal length (mm):").pack(pady=(10, 5)) focal_entry = ttk.Entry(dialog, width=20) focal_entry.insert(0, old_focal) focal_entry.pack() ttk.Label(dialog, text="Diameter (mm):").pack(pady=(10, 5)) diameter_entry = ttk.Entry(dialog, width=20) diameter_entry.insert(0, old_diameter) diameter_entry.pack() def save(): new_name = name_entry.get().strip() try: aperture = float(aperture_entry.get()) focal = int(focal_entry.get()) diameter = int(diameter_entry.get()) except ValueError: messagebox.showerror("Error", "Invalid numeric values!", parent=dialog) return new_info = f"{new_name} (f/{aperture}, F={focal}mm, D={diameter}mm)" if new_info != self.selected_telescope and new_info in self.telescopes: messagebox.showerror("Error", "Telescope already exists!", parent=dialog) return idx = self.telescopes.index(self.selected_telescope) self.telescopes[idx] = new_info self.config_service.remove_telescope(self.selected_telescope) self.config_service.add_telescope(new_info) self.telescopes_listbox.delete(0, 'end') for telescope in self.telescopes: self.telescopes_listbox.insert('end', telescope) dialog.destroy() btn_frame = ttk.Frame(dialog) btn_frame.pack(pady=20) ttk.Button(btn_frame, text="Save", command=save).pack(side='left', padx=10) ttk.Button(btn_frame, text="Cancel", command=dialog.destroy).pack(side='left', padx=10)