class Program(Tk): """ Main GUI container """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # MENU AND APPEARANCE SETUP logger.info("GUI init") self.title("Auto Basya") self.configure(bg="grey") self.columnconfigure((0, ), weight=1) self.main_menu = Menu(self) self.config(menu=self.main_menu) self.options_menu = Menu(self.main_menu, tearoff=0) self.set_options_menu() self.backend = Backend() # MAIN VARIABLES self.pf_names = self.backend.get_pf_names() self.pf_count = len(self.pf_names) self.path_to_config = 'campaigns_config.yml' self.input_data = self.load_config() self.rows = {pf: row for row, pf in enumerate(self.pf_names)} self.vars = { pf: BooleanVar(value=(pf in self.input_data)) for pf in self.pf_names } self.frames = { pf: PlatformFrame(self, name=pf, row=self.rows[pf], init_states=self.input_data[pf]) for pf in self.input_data } # WELCOME MESSAGE self.welcome_lbl = None if not self.input_data: logger.info('Welcome Message') self.welcome_lbl = Label( self, text= u"Добро пожаловать в Авто Басю.\n\nПохоже, что это первый запуск программы (либо не было сохранено ни одной кампании).\n\nЧтобы приступить к работе, зайдите в\nНастройки > Платформы,\nчтобы выбрать платформы, с которыми предстоит работать, а также в\nНастройки > Google Таблица\nчтобы внести параметры Google таблицы, в которую предстоит экспортировать данные.", padx=10, pady=10) self.welcome_lbl.grid(row=0, column=0, padx=20, pady=30) # must be in the end of init self.set_footer() def set_options_menu(self): ''' Options menu setup ''' logger.info("options menu setup") self.main_menu.add_cascade(label="Настройки", menu=self.options_menu) self.options_menu.add_command(label="Платформы", command=self.pf_window) self.options_menu.add_command(label="Google Таблица", command=lambda: GSpreadWin(self.backend)) self.options_menu.add_command(label="Ограничения", command=Limitations) def pf_window(self): ''' Open platforms' checklist setting window ''' logger.info("platforms window call") pf_window = Toplevel(padx=10, pady=10) pf_window.title("Платформы") # Subject to change to grid tip = Label( pf_window, text= "Отметьте галочкой платформы, \nиз которых требуется экспортировать данные" ).pack() pf_checkboxes = Frame(pf_window) MAX_ROWS = 8 i = 0 for column in range(8): if i < self.pf_count: for row in range(MAX_ROWS): if i < self.pf_count: Checkbutton( pf_checkboxes, text=self.pf_names[i], variable=self.vars[self.pf_names[i]], command=lambda x=self.pf_names[i]: self. show_hide_pf(x), ).grid(sticky="w", row=row, column=column) i += 1 pf_checkboxes.pack(fill='both', expand=True) platforms_ok_btn = Button(pf_window, text="OK", command=pf_window.destroy).pack(pady=10) def show_hide_pf(self, pf): ''' Clears table for info inserting from widgets ''' if self.vars[pf].get(): logger.info(f"Call to create {pf} frame") if self.welcome_lbl: self.welcome_lbl.grid_forget() self.frames.update( {pf: PlatformFrame(self, name=pf, row=self.rows[pf])}) else: logger.info(f"Call to delete {pf} frame") self.frames[pf].grid_forget() self.frames.pop(pf) def save_values(self): ''' Saves entered info to internal dict ''' logger.info('Call to save input') self.input_data.clear() for pf in self.pf_names: if self.vars[pf].get(): self.input_data.update(self.frames[pf].get()) logger.info(f'Input {self.input_data} saved to internal dict') def save_config(self): '''Saves campaign parsing parameters to disk''' logger.info('Call to save config file') with open(self.path_to_config, 'w', encoding='utf-8') as f: yaml.dump(self.input_data, f, allow_unicode=True) logger.info('Input saved to disk') def load_config(self): '''Loads campaign parsing parameters''' logger.info('Call to load config') if path.exists(self.path_to_config): with open(self.path_to_config, 'r', encoding='utf-8') as y: conf = yaml.safe_load(y) logger.info(f'Config loaded {conf}') return conf logger.info('Returning empty config') return {} def set_footer(self): ''' Sets up footer of the GUI with two buttons ''' self.footer = Frame(self) save_start_btn = Button(self.footer, text="Сохранить и Запустить", command=self.save_start_process_btn, padx=5) save_btn = Button(self.footer, text="Сохранить", command=self.save_btn, padx=5) save_btn.grid(row=0, column=1, sticky='E', padx=5, pady=10) save_start_btn.grid(row=0, column=2, sticky='E', padx=5, pady=10) self.footer.columnconfigure((0, ), weight=1) self.footer.grid(row=self.pf_count, column=0, pady=2, sticky='nsew') def set_progress_bar(self): ''' Sets up progress bar to track the execution of the main process in the backend ''' # TO DO pass def save_start_process_btn(self): logger.info('Saving values to dict and to disk') self.save_values() self.save_config() self.set_progress_bar() logger.info('Running main backend process') logger.debug(f"Data given to backend: {self.input_data}") self.gs_warning = Label(self.footer, text="Не заданы настройки Google таблицы") if self.backend.gs_setting_complete(): self.gs_warning.grid_forget() self.backend.run(self.input_data) else: self.gs_warning.grid(row=0, column=0, sticky='E', padx=5, pady=10) Results_window(self.backend.get_result()) def save_btn(self): logger.info('Saving values to dict and to disk') self.save_values() self.save_config() def run(self): self.mainloop()