BonPrinter v1.2.0
Thermal Printer tool
Loading...
Searching...
No Matches
MainWindow Class Reference

The view-controller for main window. More...

Inheritance diagram for MainWindow:

Public Member Functions

None __init__ (self, UncaughtHook qt_exception_hook, LogConfig log_config, bool test_mode=False, bool authenticated=False, *Any args, **Any kwargs)
None block_ui (self)
 Blocks the main UI elements.
None btn_article_preview (self)
 Article Print Preview.
None btn_calc_clicked (self)
 Handle calc button clicked.
None btn_change_item (self, EConfigSelection e_config_selection)
 Handle change articles configuration.
None btn_change_user (self, EConfigSelection e_config_selection)
 Handle change user configuration.
None btn_clear_clicked (self)
 Handle clear button clicked.
None btn_combine_auto (self)
 Combine Reports manual to create single report from multiple other data.
None btn_combine_manual (self)
 Combine Reports manual to create single report from multiple other data.
None btn_item_clicked (self, int i_item_number)
 Handle item button/login (1-30) clicked.
None btn_item_held (self)
 Item button held.
None btn_item_pressed (self, int i_item_number)
 Handle item button/login (1-30) pressed.
None btn_item_released (self, int i_item_number)
 Handle item button/login (1-30) released.
None btn_lock_clicked (self, bool b_auto_logout=False)
 Handle lock button clicked.
None btn_multi_clicked (self)
 Handle multi button clicked.
None btn_open_folder (self)
 Handle Open output folder.
None btn_print_clicked (self, bool b_smartcard=False)
 Handle print button clicked.
None btn_print_file (self)
 Select and print markdown file from directory.
None btn_report_print (self, bool b_clear_report)
 Handle report or status button clicked.
None change_output_path (self)
 Handle change output path.
None clear_articles (self)
 Clear articles.
None clear_status (self, bool b_override=False)
 Clear status bar text and set active user as default.
None closeEvent (self, CLOSE_EVENT|None event)
 Default close Event Method to handle application close.
bool confirm_dialog (self, str|list[str] title_value, str s_icon_path=ICON_APP, Optional[list[str]] l_optional_text=None)
 Show confirm dialog to accept or cancel.
None edit_items_in_notepad (self, str s_file_name)
 Open item file in notepad.
None edit_user_in_notepad (self, str s_file_name)
 Open user file in notepad.
None open_report_dialog (self, bool b_clear_report, bool b_auto_print)
 Open report dialog.
float print_selected_articles (self, list[Item] l_item_log, datetime actual_datetime)
 Print selected articles.
None reset_config (self)
 Handle reset configuration.
None resizeEvent (self, RESIZE_EVENT|None _event)
 Default resize Event Method to handle change of window size.
None set_status (self, str|list[str] text_value, bool b_warning=False, Optional[int] i_timeout=None, bool b_highlight=False, bool b_thread=False)
 Logs a status message to status bar (with timer) and logging handler.
None set_ui (self, bool b_state)
 Blocks/Unblock the main UI elements.
None show_help_dialog (self)
 Show help dialog.
None show_item_btns (self)
 Update item buttons.
None show_login_btns (self)
 Update login buttons.
None show_number_btns (self)
 Update number buttons.
None show_unauthenticated_dialog (self)
 Show unauthenticated dialog.
None show_update_dialog (self, str newer_tool_version)
 Show Update dialog.
None show_welcome_dialog (self)
 Show welcome screen and choose admin password.
None unblock_ui (self)
 Unblock the main UI elements.
None update_menu (self)
 Update menu.
None update_screen (self)
 Update complete screen.
None update_table (self)
 Update table and print/clear button.

Public Attributes

 action_58mm
 action_80mm
 action_about_app
 action_article_preview
 action_articles_edit
 action_articles_export
 action_articles_import
 action_articles_new
 action_articles_pdf_import
 action_auto
 action_auto_export
 action_auto_import
 action_change_path
 action_combine_auto
 action_combine_manual
 action_create_billing
 action_dark
 action_enable_report
 action_english
 action_german
 action_help
 action_light
 action_log_debug
 action_log_error
 action_log_info
 action_log_warning
 action_none
 action_normal
 action_open_folder
 action_paper_change
 action_port_1
 action_port_10
 action_port_2
 action_port_3
 action_port_4
 action_port_5
 action_port_6
 action_port_7
 action_port_8
 action_port_9
 action_print_file
 action_reset
 action_show_interim
 action_show_price
 action_sound
 action_system
 action_user_edit
 action_user_export
 action_user_import
 action_user_new
 action_webserver
 ag_language
 ag_paper_width
 ag_port = None
 ag_theme
 ag_verbosity
bool b_btn_hold = False
bool b_warning_active = False
 btn_article_preview
 btn_calc
 btn_calc_clicked
 btn_change_item
 btn_change_user
 btn_clear
 btn_clear_clicked
 btn_combine_auto
 btn_combine_manual
 btn_lock
 btn_lock_clicked
 btn_multi
 btn_multi_clicked
 btn_open_folder
 btn_print
 btn_print_clicked
 btn_print_file
 btn_report_print
 btn_timer = create_timer(parent=self, callback=self.btn_item_held)
 change_output_path
bool close_window_dialog = True
 dialog_help = create_help_dialog(self)
bool gui_locked = False
int i_btn_hold_idx = 0
list l_action_com_port
list l_bnt_fnc
 menu_articles
 menu_com_port
 menu_combine_report
 menu_configuration
 menu_display_port
 menu_help
 menu_log_verbosity
 menu_paper_width
 menu_prints
 menu_settings
 menu_smartcard
 menubar
 model = Model(self, log_config)
 qt_exception_hook = qt_exception_hook
 reset_config
 show_help_dialog
 status_timer = create_timer(parent=self, callback=self.clear_status)
 statusbar_left = LABEL()
 statusbar_right = LABEL()
 table_items
 test_mode = test_mode
 text_total
 unblock_ui

Static Public Attributes

 resized = SIGNAL()

Detailed Description

The view-controller for main window.

Entry point of application. Provides general methods that may be called by any other controller.

Parameters
qt_exception_hook: exception hook
log_config: log configuration of the application
test_mode: status if application run in test mode for pytest
authenticated: status if you are authenticated to use this program

Definition at line 110 of file main_window.py.

Constructor & Destructor Documentation

◆ __init__()

None __init__ ( self,
UncaughtHook qt_exception_hook,
LogConfig log_config,
bool test_mode = False,
bool authenticated = False,
*Any args,
**Any kwargs )

Definition at line 121 of file main_window.py.

122 authenticated: bool = False, *args: Any, **kwargs: Any) -> None: # pylint: disable=keyword-arg-before-vararg
123 log.debug("Initializing Main Window")
124 super().__init__(*args, **kwargs)
125 self.test_mode = test_mode
126 self.qt_exception_hook = qt_exception_hook
127 self.close_window_dialog = True
128 self.gui_locked = False
129 self.b_warning_active = False
130 self.setupUi(self)
131 config_window(self, title=__title__)
132 self.dialog_help = create_help_dialog(self)
133
134 # split statusbar
135 self.statusbar_left = LABEL()
136 self.statusbar_right = LABEL()
137 config_statusbar(statusbar=self.statusbar, lbl_left=self.statusbar_left, lbl_right=self.statusbar_right)
138
139 # Init settings
140 log.debug("Initializing main configuration")
141
142 # TODO Instanzen nach Module auslagern
143 self.l_action_com_port = [self.action_port_1,
144 self.action_port_2,
145 self.action_port_3,
146 self.action_port_4,
147 self.action_port_5,
148 self.action_port_6,
149 self.action_port_7,
150 self.action_port_8,
151 self.action_port_9,
152 self.action_port_10]
153 self.ag_port = None
154
155 self.model = Model(self, log_config)
156 log_config.ui = self # set ui here because object generates before main window
157
158 self.model.c_monitor.update_darkmode_status(self.model.c_monitor.e_style)
159
160 self.model.c_sound.update_sound_status(read_sound_settings())
161 self.status_timer = create_timer(parent=self, callback=self.clear_status) # statusbar timer
162
163 # Action Group Log Verbosity
164 self.ag_verbosity = group_menu(self,
165 [self.action_log_error, self.action_log_warning, self.action_log_info, self.action_log_debug],
166 self.model.log_config.i_log_level,
167 [logging.ERROR, logging.WARNING, logging.INFO, logging.DEBUG])
168
169 # Action Group paper width
170 self.ag_paper_width = group_menu(self,
171 [self.action_58mm, self.action_80mm],
172 self.model.c_printer.i_paper_width,
173 [EPaper.WIDTH_58_MM, EPaper.WIDTH_80_MM])
174
175 # Sound
176 config_menu(self.action_sound, checked=self.model.c_sound.b_sound)
177
178 # Show Price
179 config_menu(self.action_show_price, checked=self.model.b_show_price)
180
181 # Enable Print Report
182 config_menu(self.action_enable_report, checked=self.model.b_enable_report)
183
184 # Action Group theme
185 self.ag_theme = group_menu(self,
186 [self.action_auto, self.action_light, self.action_dark, self.action_system],
187 self.model.c_monitor.e_style,
188 [ETheme.AUTO, ETheme.LIGHT, ETheme.DARK, ETheme.SYSTEM])
189
190 # Action Group language
191 self.ag_language = group_menu(self,
192 [self.action_english, self.action_german],
193 self.model.c_language.e_language,
194 [ELanguages.ENGLISH, ELanguages.GERMAN])
195
196 # Connect Callbacks
197 # button connections
198 self.l_bnt_fnc: list[BUTTON] = [self.btn_item1, self.btn_item2, self.btn_item3, self.btn_item4, self.btn_item5,
199 self.btn_item6, self.btn_item7, self.btn_item8, self.btn_item9, self.btn_item10,
200 self.btn_item11, self.btn_item12, self.btn_item13, self.btn_item14, self.btn_item15,
201 self.btn_item16, self.btn_item17, self.btn_item18, self.btn_item19, self.btn_item20,
202 self.btn_item21, self.btn_item22, self.btn_item23, self.btn_item24, self.btn_item25,
203 self.btn_item26, self.btn_item27, self.btn_item28, self.btn_item29, self.btn_item30,
204 self.btn_item31, self.btn_item32, self.btn_item33, self.btn_item34, self.btn_item35,
205 self.btn_item36, self.btn_item37, self.btn_item38, self.btn_item39, self.btn_item40,
206 self.btn_item41, self.btn_item42, self.btn_item43, self.btn_item44, self.btn_item45,
207 self.btn_item46, self.btn_item47, self.btn_item48, self.btn_item49, self.btn_item50,
208 self.btn_item51, self.btn_item52, self.btn_item53, self.btn_item54, self.btn_item55,
209 self.btn_item56]
210 self.b_btn_hold = False
211 self.i_btn_hold_idx = 0
212 self.btn_timer = create_timer(parent=self, callback=self.btn_item_held) # timer for button held
213 for i, btn in enumerate(self.l_bnt_fnc):
214 connect_button(btn,
215 clicked_fnc=self.btn_item_clicked,
216 pressed_fnc=self.btn_item_pressed,
217 released_fnc=self.btn_item_released,
218 index=i)
219 connect_button(self.btn_multi, self.btn_multi_clicked)
220 connect_button(self.btn_calc, self.btn_calc_clicked)
221 connect_button(self.btn_clear, self.btn_clear_clicked)
222 connect_button(self.btn_print, self.btn_print_clicked)
223 connect_button(self.btn_lock, self.btn_lock_clicked)
224
225 # Menu buttons
226 connect_menu(self.action_show_interim, self.btn_report_print, False)
227 connect_menu(self.action_open_folder, self.btn_open_folder)
228 connect_menu(self.action_combine_manual, self.btn_combine_manual)
229 connect_menu(self.action_combine_auto, self.btn_combine_auto)
230 connect_menu(self.action_print_file, self.btn_print_file)
231 connect_menu(self.action_article_preview, self.btn_article_preview)
232 connect_menu(self.action_enable_report, self.model.update_enable_report_status)
233 connect_menu(self.action_create_billing, self.btn_report_print, True)
234 # User
235 connect_menu(self.action_user_edit, self.btn_change_user, EConfigSelection.EDIT)
236 connect_menu(self.action_user_import, self.btn_change_user, EConfigSelection.IMPORT)
237 connect_menu(self.action_user_export, self.btn_change_user, EConfigSelection.EXPORT)
238 connect_menu(self.action_user_new, self.btn_change_user, EConfigSelection.RESET)
239 # Items
240 connect_menu(self.action_articles_edit, self.btn_change_item, EConfigSelection.EDIT)
241 connect_menu(self.action_articles_import, self.btn_change_item, EConfigSelection.IMPORT)
242 connect_menu(self.action_articles_export, self.btn_change_item, EConfigSelection.EXPORT)
243 connect_menu(self.action_articles_new, self.btn_change_item, EConfigSelection.RESET)
244 # Other Config
245 connect_menu(self.action_change_path, self.change_output_path)
246 # COM Port (max number of supported ports: 10 TODO use variable number of ports (not only 10) but is buggy)
247 connect_menu(self.action_none, self.model.c_printer.update_com_port, None)
248 connect_menu_com_port(self.action_port_1, self.model.c_printer.update_com_port)
249 connect_menu_com_port(self.action_port_2, self.model.c_printer.update_com_port)
250 connect_menu_com_port(self.action_port_3, self.model.c_printer.update_com_port)
251 connect_menu_com_port(self.action_port_4, self.model.c_printer.update_com_port)
252 connect_menu_com_port(self.action_port_5, self.model.c_printer.update_com_port)
253 connect_menu_com_port(self.action_port_6, self.model.c_printer.update_com_port)
254 connect_menu_com_port(self.action_port_7, self.model.c_printer.update_com_port)
255 connect_menu_com_port(self.action_port_8, self.model.c_printer.update_com_port)
256 connect_menu_com_port(self.action_port_9, self.model.c_printer.update_com_port)
257 connect_menu_com_port(self.action_port_10, self.model.c_printer.update_com_port)
258 # Paper
259 connect_menu(self.action_58mm, self.model.c_printer.update_paper_width, EPaper.WIDTH_58_MM.value)
260 connect_menu(self.action_80mm, self.model.c_printer.update_paper_width, EPaper.WIDTH_80_MM.value)
261 # Sound
262 connect_menu(self.action_sound, self.model.c_sound.update_sound_status)
263 # Dark Mode
264 connect_menu(self.action_auto, self.model.c_monitor.update_darkmode_status, ETheme.AUTO)
265 connect_menu(self.action_light, self.model.c_monitor.update_darkmode_status, ETheme.LIGHT)
266 connect_menu(self.action_dark, self.model.c_monitor.update_darkmode_status, ETheme.DARK)
267 config_menu(self.action_normal, show=False)
268 connect_menu(self.action_system, self.model.c_monitor.update_darkmode_status, ETheme.SYSTEM)
269 # Language
270 connect_menu(self.action_english, self.model.c_language.update_language, ELanguages.ENGLISH)
271 connect_menu(self.action_german, self.model.c_language.update_language, ELanguages.GERMAN)
272 # Show Price
273 connect_menu(self.action_show_price, self.model.update_show_price_status)
274 # Verbosity
275 connect_menu(self.action_log_error, self.model.log_config.update_log_level, logging.ERROR)
276 connect_menu(self.action_log_warning, self.model.log_config.update_log_level, logging.WARNING)
277 connect_menu(self.action_log_info, self.model.log_config.update_log_level, logging.INFO)
278 connect_menu(self.action_log_debug, self.model.log_config.update_log_level, logging.DEBUG)
279 # Paper change
280 # Help
281 connect_menu(self.action_help, self.show_help_dialog)
282 connect_menu(self.action_about_app, show_about_dialog, self)
283 connect_menu(self.action_reset, self.reset_config)
284
285 filter_menubar(self.menubar, self)
286
287 # initialize screen
288 self.model.c_report.create_report(b_clear_report=False, b_startup_check=True) # check for valid report at startup
289 config_window(self, fullscreen=False, resize_callback=self.model.c_monitor.resize_window)
290 self.model.c_monitor.resize_window()
291 self.update_screen()
292 if not authenticated:
293 self.show_unauthenticated_dialog()
294 elif self.test_mode:
295 self.model.c_config.read_user_file("user_example.ini")
296 self.model.c_config.read_item_file("articles_example.ini")
297 else:
298 newer_tool_version = get_tool_update_status()
299 if (newer_tool_version is not None) and (compare_versions(read_update_version(), newer_tool_version)):
300 self.show_update_dialog(newer_tool_version)
301 if self.model.c_config.d_user == D_DEFAULT_USER:
302 self.show_welcome_dialog()
303 self.clear_status(b_override=True)
304

Member Function Documentation

◆ block_ui()

None block_ui ( self)

Blocks the main UI elements.

Definition at line 369 of file main_window.py.

369 def block_ui(self) -> None:
370 """!
371 @brief Blocks the main UI elements.
372 """
373 log.debug("Block UI")
374 self.set_ui(False)
375 self.gui_locked = True
376 self.set_status("")
377

◆ btn_article_preview()

None btn_article_preview ( self)

Article Print Preview.

Definition at line 1344 of file main_window.py.

1344 def btn_article_preview(self) -> None:
1345 """!
1346 @brief Article Print Preview
1347 """
1348 self.block_ui()
1349 l_preview_text = []
1350 i_break_line = int(self.model.c_printer.i_line_break / 2)
1351 line_text = "Name".ljust(i_break_line) + " | Group | Price "
1352 line_text += "| Cut"
1353 l_preview_text.append(line_text)
1354 line_text = "-" * (i_break_line + 50)
1355 l_preview_text.append(line_text)
1356
1357 for i_item_pos in range(I_ITEM_ARRAY_SIZE):
1358 i_item_number = i_item_pos + 1
1359 name = self.model.c_config.get_item_name(i_item_number)
1360 b_show = True
1361 if name != "" and b_show:
1362 group = self.model.c_config.get_item_group(i_item_number)
1363 f_item_price = self.model.c_config.get_item_price(i_item_number)
1364 s_item_price = f"{f_item_price:.2f} {S_UNIT_SYMBOL}"
1365 s_item_price = s_item_price.rjust(8)
1366 line_text = f"{name.ljust(i_break_line)[:i_break_line]}"
1367 line_text += f" | {group}"
1368 line_text += f" |{s_item_price}"
1369 line_text += f"| {name[i_break_line:]}"
1370 l_preview_text.append(line_text)
1371
1372 preview_text = '\n'.join(l_preview_text)
1373 show_report_dialog(self, report_text=preview_text)
1374 self.unblock_ui()
1375

◆ btn_calc_clicked()

None btn_calc_clicked ( self)

Handle calc button clicked.

Definition at line 952 of file main_window.py.

952 def btn_calc_clicked(self) -> None:
953 """!
954 @brief Handle calc button clicked.
955 """
956 log.debug("Calc button clicked")
957 b_last_calc = bool(self.model.c_auth.e_view == EWindowView.CALC)
958 match self.model.c_auth.e_view:
959 case EWindowView.CALC:
960 if self.model.c_calc.s_text_total == "":
961 self.model.c_calc.s_text_total = str(0) # if calc btn clicked without input
962 self.model.c_calc.f_payed = float(self.model.c_calc.s_text_total)
963 if self.model.c_calc.f_total > self.model.c_calc.f_payed:
964 self.set_status(["Not enough Money", "Nicht genug Geld"], b_highlight=True)
965 self.model.c_calc.f_back = self.model.c_calc.f_payed - self.model.c_calc.f_total
966 self.model.c_auth.e_view = EWindowView.MAIN
967 case _:
968 self.model.c_calc.s_text_total = ""
969 self.model.c_calc.f_back = None
970 self.model.c_auth.e_view = EWindowView.CALC
971 if self.model.c_sound.b_sound:
972 self.model.c_sound.c_sound_touch.play()
973 self.model.c_calc.b_hold_last_print = True
974 self.update_screen()
975 if b_last_calc: # Disable and set CLR button TODO update screen setzen
976 config_btn(self.btn_clear, enable=False, text=self.model.c_language.get_language_text(L_CLEAR), fg="grey", icon="")
977

◆ btn_change_item()

None btn_change_item ( self,
EConfigSelection e_config_selection )

Handle change articles configuration.

Parameters
e_config_selection: mode of articles change (edit/import/export/reset)

Definition at line 1221 of file main_window.py.

1221 def btn_change_item(self, e_config_selection: EConfigSelection) -> None:
1222 """!
1223 @brief Handle change articles configuration.
1224 @param e_config_selection : mode of articles change (edit/import/export/reset)
1225 """
1226 match e_config_selection:
1227 case EConfigSelection.RESET | EConfigSelection.EDIT:
1228 if e_config_selection == EConfigSelection.RESET:
1229 s_deposit_name = None
1230 d_articles_dict = get_default_item_config(s_deposit_name)
1231 b_reset = self.confirm_dialog(["Reset articles", "Artikel zurücksetzen"], s_icon_path=ICON_ARTICLES_RESET_LIGHT)
1232 else:
1233 d_articles_dict = self.model.c_config.d_item
1234 b_reset = True
1235 if b_reset:
1236 write_config_to_file(S_ITEM_TEMP_FILE, d_articles_dict)
1237 self.block_ui()
1238 self.edit_items_in_notepad(S_ITEM_TEMP_FILE)
1239 case EConfigSelection.IMPORT:
1240 l_title = ["Select article configuration file to import", "Wähle eine Artikel Konfigurationsdatei zum importieren"]
1241 config_import_file = open_file(parent=self, title=self.model.c_language.get_language_text(l_title),
1242 directory=self.model.get_last_path(), filetypes=INI_FILE_TYPES)
1243 if isinstance(config_import_file, str):
1244 if config_import_file:
1245 self.model.set_last_path(os.path.dirname(config_import_file))
1246 b_imported = self.model.c_config.read_item_file(config_import_file)
1247 if b_imported:
1248 self.set_status([f"Articles configuration imported: {config_import_file}",
1249 f"Artikel Konfigurationsdaten importiert: {config_import_file}"])
1250 else:
1251 self.set_status("Config import file is not string", True) # state not possible
1252 case EConfigSelection.EXPORT:
1253 l_title = ["Export article configuration file", "Artikel Konfigurationsdatei exportieren"]
1254 config_export_file = save_file(parent=self, title=self.model.c_language.get_language_text(l_title),
1255 directory=f"{self.model.get_last_path()}/{S_ITEM_FILE}",
1256 filetypes=INI_FILE_TYPES)
1257 if config_export_file:
1258 self.model.set_last_path(os.path.dirname(config_export_file))
1259 write_config_to_file(config_export_file, self.model.c_config.d_item)
1260 self.set_status([f"Articles configuration exported: {config_export_file}",
1261 f"Artikel Konfigurationsdaten exportiert: {config_export_file}"])
1262 case EConfigSelection.PDF_IMPORT:
1263 pass
1264 case _:
1265 self.set_status(f"Invalid articles menu: {e_config_selection}", True) # state not possible
1266

◆ btn_change_user()

None btn_change_user ( self,
EConfigSelection e_config_selection )

Handle change user configuration.

Parameters
e_config_selection: mode of user change (edit/import/export/reset)

Definition at line 1164 of file main_window.py.

1164 def btn_change_user(self, e_config_selection: EConfigSelection) -> None:
1165 """!
1166 @brief Handle change user configuration.
1167 @param e_config_selection : mode of user change (edit/import/export/reset)
1168 """
1169 match e_config_selection:
1170 case EConfigSelection.RESET | EConfigSelection.EDIT:
1171 if e_config_selection == EConfigSelection.RESET:
1172 d_user_dict = D_DEFAULT_USER.copy() # copy that admin not delete in global data
1173 d_user_dict[EUser.ADMIN.value][S_PW] = DEFAULT_CODE
1174 b_reset = self.confirm_dialog(["Reset user", "Benutzer zurücksetzen"], s_icon_path=ICON_USER_RESET_LIGHT)
1175 else:
1176 d_user_dict = self.model.c_config.d_user.copy() # copy that admin not delete in global data
1177 b_reset = True
1178 if b_reset:
1179 if not self.model.c_auth.check_user_login(EUser.ADMIN): # only Admin can view his PW
1180 if EUser.ADMIN.value in d_user_dict:
1181 del d_user_dict[EUser.ADMIN.value]
1182 else:
1183 self.set_status(["No Admin user in config data",
1184 "Kein Admin Nutzer in den Konfigurationsdaten hinterlegt"], True)
1185 write_config_to_file(S_USER_TEMP_FILE, d_user_dict)
1186 self.block_ui()
1187 self.edit_user_in_notepad(S_USER_TEMP_FILE)
1188 case EConfigSelection.IMPORT:
1189 l_title = ["Select user configuration file to import", "Wähle eine Benutzer Konfigurationsdatei zum importieren"]
1190 config_import_file = open_file(parent=self, title=self.model.c_language.get_language_text(l_title),
1191 directory=self.model.get_last_path(), filetypes=INI_FILE_TYPES)
1192 if isinstance(config_import_file, str):
1193 if config_import_file:
1194 self.model.set_last_path(os.path.dirname(config_import_file))
1195 b_imported = self.model.c_config.read_user_file(config_import_file)
1196 if b_imported:
1197 self.set_status([f"User configuration imported: {config_import_file}",
1198 f"Benutzer Konfigurationsdaten importiert: {config_import_file}"])
1199 else:
1200 self.set_status("Config import file is not string", True) # state not possible
1201 case EConfigSelection.EXPORT:
1202 l_title = ["Export user configuration file", "Benutzer Konfigurationsdatei exportieren"]
1203 config_export_file = save_file(parent=self, title=self.model.c_language.get_language_text(l_title),
1204 directory=f"{self.model.get_last_path()}/{S_USER_FILE}",
1205 filetypes=INI_FILE_TYPES)
1206 if config_export_file:
1207 self.model.set_last_path(os.path.dirname(config_export_file))
1208 write_config_to_file(config_export_file, self.model.c_config.d_user)
1209 self.set_status([f"User configuration exported: {config_export_file}",
1210 f"Benutzer Konfigurationsdaten exportiert: {config_export_file}"])
1211 case _:
1212 self.set_status(f"Invalid user menu: {e_config_selection}", True) # state not possible
1213

◆ btn_clear_clicked()

None btn_clear_clicked ( self)

Handle clear button clicked.

Definition at line 1001 of file main_window.py.

1001 def btn_clear_clicked(self) -> None:
1002 """!
1003 @brief Handle clear button clicked.
1004 """
1005 log.debug("Clear button clicked")
1006 b_ec_pressed = False
1007 if self.model.c_auth.b_login_state:
1008 match self.model.c_auth.e_view:
1009 case EWindowView.MULTI | EWindowView.CALC:
1010 self.model.c_calc.s_text_total = ""
1011 case _:
1012 btn_text = get_btn_text(self.btn_clear)
1013 if self.model.c_language.get_language_text(L_CLEAR) == btn_text:
1014 self.clear_articles()
1015 else:
1016 pass
1017 else: # user view
1018 if self.model.c_auth.s_pw != "":
1019 self.model.c_auth.s_pw = ""
1020 if self.model.c_auth.s_login_user is not None:
1021 self.model.c_calc.s_text_total = self.model.c_auth.s_login_user
1022 else:
1023 self.model.c_calc.s_text_total = ""
1024 self.set_status("None user input password", True) # state not possible
1025 else:
1026 self.model.c_auth.s_login_user = None
1027 self.model.c_calc.s_text_total = ""
1028 # play sound
1029 if self.model.c_sound.b_sound:
1030 sound = self.model.c_sound.c_sound_touch if b_ec_pressed else self.model.c_sound.c_sound_clear
1031 sound.play()
1032 if b_ec_pressed or (self.model.c_auth.e_view == EWindowView.CALC):
1033 self.model.c_calc.b_hold_last_print = True
1034 self.update_screen()
1035

◆ btn_combine_auto()

None btn_combine_auto ( self)

Combine Reports manual to create single report from multiple other data.

Definition at line 1303 of file main_window.py.

1303 def btn_combine_auto(self) -> None:
1304 """!
1305 @brief Combine Reports manual to create single report from multiple other data.
1306 """
1307 l_title = ["Select directory to combine", "Wähle ein Verzeichnis zum kombinieren"]
1308 directory = open_directory(parent=self, title=self.model.c_language.get_language_text(l_title), directory=self.model.get_last_path())
1309 if directory:
1310 self.model.set_last_path(directory)
1311 l_files = []
1312
1313 for root, _dirs, files in os.walk(directory):
1314 for file in files:
1315 if file.endswith(".csv"):
1316 l_files.append(os.path.join(root, file))
1317
1318 if l_files:
1319 self.model.c_report.create_report(l_files=l_files, b_combine=True, b_clear_report=False,
1320 s_path=self.model.get_last_path(), b_open_folder=True)
1321 else:
1322 self.set_status(["No CSV files found", "Keine CSV Dateien gefunden"])
1323

◆ btn_combine_manual()

None btn_combine_manual ( self)

Combine Reports manual to create single report from multiple other data.

Definition at line 1287 of file main_window.py.

1287 def btn_combine_manual(self) -> None:
1288 """!
1289 @brief Combine Reports manual to create single report from multiple other data.
1290 """
1291 l_title = ["Select report files to combine", "Wähle Berichte zum kombinieren"]
1292 l_select_files = open_file(parent=self, title=self.model.c_language.get_language_text(l_title),
1293 directory=self.model.get_last_path(), filetypes=LOG_FILE_TYPES,
1294 multiple=True)
1295 if isinstance(l_select_files, list):
1296 if l_select_files:
1297 self.model.set_last_path(os.path.dirname(l_select_files[0]))
1298 self.model.c_report.create_report(l_files=l_select_files, b_combine=True, b_clear_report=False,
1299 s_path=self.model.get_last_path(), b_open_folder=True)
1300 else:
1301 self.set_status("Combine files are not list", True) # state not possible
1302

◆ btn_item_clicked()

None btn_item_clicked ( self,
int i_item_number )

Handle item button/login (1-30) clicked.

Parameters
i_item_number: button index that was clicked

Definition at line 834 of file main_window.py.

834 def btn_item_clicked(self, i_item_number: int) -> None:
835 """!
836 @brief Handle item button/login (1-30) clicked.
837 @param i_item_number : button index that was clicked
838 """
839 log.debug("Item button %s clicked", i_item_number)
840 if self.model.c_auth.b_login_state: # item mode
841 if not self.b_btn_hold:
842 match self.model.c_auth.e_view:
843 case EWindowView.MULTI | EWindowView.CALC:
844 s_name = L_LOGIN_KEYS[i_item_number]
845 match s_name:
846 case EUser.ADMIN:
847 s_name = S_DOT
848 case EUser.HOST:
849 s_name = S_DOUBLE_NULL
850 case _:
851 if (len(s_name) == 1) and s_name.isnumeric():
852 pass # use this number
853 else:
854 self.set_status("Invalid Multiple Button pressed", True) # state not possible
855 s_name = ""
856 self.model.c_calc.s_text_total += s_name
857 self.show_number_btns()
858 case _:
859 b_add_item = True
860 if self.model.c_calc.i_multi > 0:
861 i_factor = self.model.c_calc.i_multi
862 self.model.c_calc.i_multi = 0
863 else:
864 i_factor = 1
865 if b_add_item:
866 i_item_index = i_item_number
867 self.model.c_report.l_bar_items[i_item_index] += i_factor # add item
868 self.model.c_calc.f_total = 0
869 if self.model.c_sound.b_sound:
870 self.model.c_sound.c_sound_touch.play()
871 if self.model.c_auth.e_view == EWindowView.CALC: # hold items in calculator mode
872 self.model.c_calc.b_hold_last_print = True
873 self.update_table()
874 else: # login mode
875 s_key = L_LOGIN_KEYS[i_item_number]
876 if len(s_key) == 1: # number pressed
877 if self.model.c_auth.s_login_user is None:
878 self.set_status("None user input password", True) # state not possible
879 return
880 self.model.c_auth.s_pw += s_key
881 pw = self.model.c_config.get_user_pw(self.model.c_auth.s_login_user)
882 if len(self.model.c_auth.s_pw) == len(pw):
883 if self.model.c_auth.s_pw == pw:
884 self.model.c_auth.log_in()
885 else:
886 self.model.c_calc.s_text_total = self.model.c_auth.s_login_user
887 self.model.c_auth.s_pw = ""
888 else:
889 self.model.c_calc.s_text_total = "*" * len(self.model.c_auth.s_pw)
890 else: # user pressed
891 self.model.c_auth.s_pw = ""
892 self.model.c_auth.s_login_user = s_key
893 self.model.c_calc.s_text_total = s_key
894 pw = self.model.c_config.get_user_pw(s_key)
895 if pw == "":
896 self.model.c_auth.log_in() # no pw for no user
897 self.model.c_calc.f_total = 0
898 if self.model.c_sound.b_sound:
899 if self.model.c_auth.b_login_state:
900 self.model.c_sound.c_sound_unlock.play()
901 else:
902 self.model.c_sound.c_sound_touch.play()
903 self.update_screen()
904 self.b_btn_hold = False
905

◆ btn_item_held()

None btn_item_held ( self)

Item button held.

Definition at line 924 of file main_window.py.

924 def btn_item_held(self) -> None:
925 """!
926 @brief Item button held.
927 """
928 log.debug("Item held")
929 self.b_btn_hold = True
930 self.model.c_report.l_marked_items[self.i_btn_hold_idx] = not self.model.c_report.l_marked_items[self.i_btn_hold_idx]
931 self.update_screen()
932

◆ btn_item_pressed()

None btn_item_pressed ( self,
int i_item_number )

Handle item button/login (1-30) pressed.

Parameters
i_item_number: button index that was pressed

Definition at line 906 of file main_window.py.

906 def btn_item_pressed(self, i_item_number: int) -> None:
907 """!
908 @brief Handle item button/login (1-30) pressed.
909 @param i_item_number : button index that was pressed
910 """
911 log.debug("Item button %s pressed", i_item_number)
912 if self.model.c_auth.b_login_state and (self.model.c_auth.e_view == EWindowView.MAIN):
913 self.btn_timer.start(I_BTN_LONG_PRESS_TIME)
914 self.i_btn_hold_idx = i_item_number
915

◆ btn_item_released()

None btn_item_released ( self,
int i_item_number )

Handle item button/login (1-30) released.

Parameters
i_item_number: button index that was released

Definition at line 916 of file main_window.py.

916 def btn_item_released(self, i_item_number: int) -> None:
917 """!
918 @brief Handle item button/login (1-30) released.
919 @param i_item_number : button index that was released
920 """
921 log.debug("Item button %s released", i_item_number)
922 self.btn_timer.stop()
923

◆ btn_lock_clicked()

None btn_lock_clicked ( self,
bool b_auto_logout = False )

Handle lock button clicked.

Parameters
b_auto_logout: [True] automatic logout (timeout); [False] manual logout

Definition at line 1114 of file main_window.py.

1114 def btn_lock_clicked(self, b_auto_logout: bool = False) -> None:
1115 """!
1116 @brief Handle lock button clicked.
1117 @param b_auto_logout : [True] automatic logout (timeout); [False] manual logout
1118 """
1119 if b_auto_logout:
1120 log.debug("Auto logout")
1121 else:
1122 log.debug("Lock button clicked")
1123 if self.model.c_sound.b_sound:
1124 self.model.c_sound.c_sound_touch.play()
1125 self.model.c_calc.s_text_total = ""
1126 self.model.c_auth.log_out()
1127 self.update_screen()
1128

◆ btn_multi_clicked()

None btn_multi_clicked ( self)

Handle multi button clicked.

Definition at line 933 of file main_window.py.

933 def btn_multi_clicked(self) -> None:
934 """!
935 @brief Handle multi button clicked.
936 """
937 log.debug("Multi button clicked")
938 match self.model.c_auth.e_view:
939 case EWindowView.MULTI:
940 if self.model.c_calc.s_text_total == "":
941 self.model.c_calc.s_text_total = str(0) # if multi btn clicked without input
942 self.model.c_calc.i_multi = int(self.model.c_calc.s_text_total)
943 self.model.c_auth.e_view = EWindowView.MAIN
944 case _:
945 self.model.c_calc.s_text_total = ""
946 self.model.c_calc.i_multi = 0
947 self.model.c_auth.e_view = EWindowView.MULTI
948 if self.model.c_sound.b_sound:
949 self.model.c_sound.c_sound_touch.play()
950 self.update_screen()
951

◆ btn_open_folder()

None btn_open_folder ( self)

Handle Open output folder.

Definition at line 1274 of file main_window.py.

1274 def btn_open_folder(self) -> None:
1275 """!
1276 @brief Handle Open output folder.
1277 """
1278 path = self.model.s_output_path
1279 if os.path.exists(path):
1280 log.debug("Open Folder: %s", path)
1281 self.set_status([f"Open Folder: {path}", f"Öffne Ordner: {path}"])
1282 with subprocess.Popen("explorer " + path.replace("/", "\\")):
1283 pass
1284 else:
1285 self.set_status([f"Folder not exist: {path}", f"Ordner existiert nicht: {path}"], True)
1286

◆ btn_print_clicked()

None btn_print_clicked ( self,
bool b_smartcard = False )

Handle print button clicked.

Parameters
b_smartcard: status if print triggered by smart card

Definition at line 1060 of file main_window.py.

1060 def btn_print_clicked(self, b_smartcard: bool = False) -> None:
1061 """!
1062 @brief Handle print button clicked.
1063 @param b_smartcard : status if print triggered by smart card
1064 """
1065 log.debug("Print button clicked")
1066 btn_text = get_btn_text(self.btn_print)
1067 if btn_text != self.model.c_language.get_language_text(L_OPEN):
1068 if self.model.c_printer.b_select_com_port_available or self.model.c_printer.s_select_com_port is None:
1069 i_user_pos = self.model.c_auth.get_user_position()
1070 if i_user_pos is not None:
1071 i_number_of_items = sum(self.model.c_report.l_bar_items)
1072 if i_number_of_items != 0:
1073 if i_number_of_items <= I_MAX_ITEMS_TO_PRINT:
1074 l_item_log: list[Item] = []
1075 now = datetime.now()
1076 self.model.c_calc.f_total = 0.0
1077 # add articles
1078 self.model.c_calc.f_total += self.print_selected_articles(l_item_log, now)
1079 # open drawer
1080 if self.model.c_config.get_auto_open() and (self.model.c_auth.check_user_login(EUser.LOCAL)): # No auto open for free user
1081 self.model.c_printer.open_drawer()
1082 self.model.c_printer.add_to_queue(l_item_log, i_user_pos, self.model.c_calc.f_total)
1083 if self.model.c_sound.b_sound:
1084 self.model.c_sound.c_sound_print.play()
1085 background_color = "lightgreen" if self.model.c_monitor.is_light_theme() else "darkgreen"
1086 config_text(self.text_total, bg=background_color, fg="black")
1087 if b_smartcard:
1088 self.model.c_auth.s_login_user = EUser.USER.value # set back to user after smartcard print
1089 elif self.model.c_auth.check_user_login(EUser.B): # logout user after print
1090 self.model.c_auth.log_out()
1091 elif self.model.c_auth.check_user_login(EUser.FREE): # check free user auto logout
1092 if self.model.c_config.get_free_auto_logout():
1093 self.model.c_auth.log_out()
1094 self.model.c_calc.b_hold_last_print = True
1095 self.model.c_report.clear_print_items()
1096 else:
1097 self.set_status([f"Maximal {I_MAX_ITEMS_TO_PRINT} articles allowed to print",
1098 f"Maximal {I_MAX_ITEMS_TO_PRINT} Artikel möglich zu drucken"], b_highlight=True)
1099 else:
1100 self.set_status(["No Items to print", "Keine Artikel zu drucken"], True)
1101 self.update_screen()
1102 else:
1103 self.set_status([f"No Print: {self.model.c_printer.s_select_com_port} not available",
1104 f"Kein Druck: {self.model.c_printer.s_select_com_port} nicht verfügbar"], True)
1105 else:
1106 if not self.model.c_auth.check_user_login(EUser.B):
1107 self.model.c_printer.open_drawer()
1108 self.set_status(["Open cash drawer", "Öffne Kassenschublade"])
1109 else:
1110 self.set_status("Stuff cant open cash drawer", True) # state not possible
1111 if self.model.c_sound.b_sound:
1112 self.model.c_sound.c_sound_touch.play()
1113

◆ btn_print_file()

None btn_print_file ( self)

Select and print markdown file from directory.

Definition at line 1324 of file main_window.py.

1324 def btn_print_file(self) -> None:
1325 """!
1326 @brief Select and print markdown file from directory.
1327 """
1328 if self.model.c_printer.s_select_com_port is not None:
1329 l_title = ["Select file to print", "Datei zum Drucken auswählen"]
1330 select_file = open_file(parent=self, title=self.model.c_language.get_language_text(l_title),
1331 directory=self.model.get_last_path(), filetypes=REPORT_FILE_TYPES)
1332 if isinstance(select_file, str):
1333 if select_file:
1334 with open(select_file, mode="r", encoding="utf-8") as file:
1335 text = file.read()
1336 self.model.c_printer.add_to_report(text)
1337 self.set_status([f"Print file: {select_file}", f"Datei wird gedruckt: {select_file}"])
1338 else:
1339 self.set_status("Print file is not string", True) # state not possible
1340 else:
1341 self.set_status(["File cannot be printed. Printer not available.",
1342 "Datei kann nicht gedruckt werden. Drucker nicht verfügbar."], b_warning=True)
1343

◆ btn_report_print()

None btn_report_print ( self,
bool b_clear_report )

Handle report or status button clicked.

Parameters
b_clear_report: [True] create report and clear log; [False] show only status

Definition at line 1129 of file main_window.py.

1129 def btn_report_print(self, b_clear_report: bool) -> None:
1130 """!
1131 @brief Handle report or status button clicked.
1132 @param b_clear_report : [True] create report and clear log; [False] show only status
1133 """
1134 b_call_report = True
1135 if b_clear_report:
1136 b_call_report = self.confirm_dialog(["Create Report & clear", "Bericht erstellen & löschen"], s_icon_path=ICON_REPORT_LIGHT)
1137 if b_call_report:
1138 self.set_status(["Show Status", "Zwischenstand anzeigen"])
1139 self.model.c_report.create_report(b_clear_report=b_clear_report, d_item=self.model.c_config.d_item, b_open_folder=B_NOTEPAD_REPORT)
1140 self.block_ui()
1141 if B_NOTEPAD_REPORT:
1142 with open(S_REPORT_TEMP_FILE, mode="w", encoding="utf-8") as file:
1143 file.write(self.model.c_report.s_report_text)
1144 self.model.notepad_worker.open_report_file(S_REPORT_TEMP_FILE, ENotepadSelection.STATUS, self.unblock_ui)
1145
1146 if self.model.c_printer.s_select_com_port is not None:
1147 if b_clear_report and (not self.model.c_auth.check_user_login(EUser.ADMIN)): # no auto print for admin
1148 b_print_report = True
1149 else:
1150 if B_NOTEPAD_REPORT:
1151 b_print_report = self.confirm_dialog(["Print out status", "Status drucken"], s_icon_path=ICON_PRINTER_LIGHT)
1152 else:
1153 b_print_report = False
1154 if b_print_report:
1155 self.model.c_printer.add_to_report(self.model.c_report.s_report_text)
1156 else:
1157 b_print_report = False
1158
1159 if not B_NOTEPAD_REPORT:
1160 self.open_report_dialog(b_clear_report, b_print_report)
1161 self.unblock_ui()
1162 self.update_menu()
1163

◆ change_output_path()

None change_output_path ( self)

Handle change output path.

Definition at line 1376 of file main_window.py.

1376 def change_output_path(self) -> None:
1377 """!
1378 @brief Handle change output path.
1379 """
1380 l_title = ["Set output path", "Wähle ein Ausgabeverzeichnis"]
1381 s_path = open_directory(parent=self, title=self.model.c_language.get_language_text(l_title), directory=self.model.s_output_path)
1382 if s_path: # if not canceled
1383 self.model.set_last_path(s_path)
1384 self.model.update_output_path(s_path)
1385

◆ clear_articles()

None clear_articles ( self)

Clear articles.

Definition at line 978 of file main_window.py.

978 def clear_articles(self) -> None:
979 """!
980 @brief Clear articles.
981 """
982 i_select_item = None
983 selected_row = get_selected_table_row(self.table_items)
984 selected_column = get_selected_table_column(self.table_items)
985 if selected_row is not None:
986 for i_pos, table_pos in enumerate(self.model.c_report.l_table_position):
987 if table_pos == selected_row:
988 i_select_item = i_pos
989 break
990 if i_select_item is None:
991 self.model.c_report.clear_print_items()
992 else:
993 if self.model.c_report.l_bar_items[i_select_item] != 0:
994 if selected_column == 2: # clear all counts if price column selected
995 self.model.c_report.l_bar_items[i_select_item] = 0 # delete all item counts
996 else:
997 self.model.c_report.l_bar_items[i_select_item] -= 1 # delete single item
998 else:
999 self.set_status(f"Not possible to delete single item at position {selected_row}", True) # state not possible
1000

◆ clear_status()

None clear_status ( self,
bool b_override = False )

Clear status bar text and set active user as default.

Parameters
b_override: status if actual status should override

Definition at line 508 of file main_window.py.

508 def clear_status(self, b_override: bool = False) -> None:
509 """!
510 @brief Clear status bar text and set active user as default
511 @param b_override : status if actual status should override
512 """
513 if not self.gui_locked:
514 if not self.status_timer.isActive() or (b_override and not self.b_warning_active):
515 user = self.model.c_auth.s_login_user
516 if user and user[0] == EUser.B.name:
517 user_name = self.model.c_config.get_user_name(user)
518 if user_name != "":
519 user_name = f" ({user_name})"
520 else:
521 user_name = ""
522 if user:
523 user = user.replace("\n", " ") # prevent word wrapping for user in statusbar
524 s_user_text = f"{self.model.c_language.get_language_text(L_MENU_USER)}: {user}{user_name}"
525 config_label(self.statusbar_left, text=s_user_text, bg=DEFAULT_STYLE)
526 self.b_warning_active = False
527

◆ closeEvent()

None closeEvent ( self,
CLOSE_EVENT | None event )

Default close Event Method to handle application close.

Parameters
event: arrived event

Definition at line 312 of file main_window.py.

312 def closeEvent(self, event: CLOSE_EVENT | None) -> None: # pylint: disable=invalid-name
313 """!
314 @brief Default close Event Method to handle application close
315 @param event : arrived event
316 """
317 if event is None:
318 return
319 log.debug("Close Event")
320 save_window_state(get_window_geometry(self), get_window_state(self))
321 if not self.close_window_dialog or self.qt_exception_hook.crash_arrived or self.test_mode or self.confirm_dialog(["Close Program", "Programm schließen"]):
322 log.debug("Application closed")
323 self.model.c_printer.terminate()
324 event.accept()
325 else:
326 event.ignore()
327

◆ confirm_dialog()

bool confirm_dialog ( self,
str | list[str] title_value,
str s_icon_path = ICON_APP,
Optional[list[str]] l_optional_text = None )

Show confirm dialog to accept or cancel.

Parameters
title_value: dialog title
s_icon_path: icon of dialog
l_optional_text: optional text
Returns
return accept status

Definition at line 328 of file main_window.py.

328 def confirm_dialog(self, title_value: str | list[str], s_icon_path: str = ICON_APP, l_optional_text: Optional[list[str]] = None) -> bool:
329 """!
330 @brief Show confirm dialog to accept or cancel.
331 @param title_value : dialog title
332 @param s_icon_path : icon of dialog
333 @param l_optional_text : optional text
334 @return return accept status
335 """
336 title = self.model.c_language.get_language_text(title_value) if isinstance(title_value, list) else title_value
337 fix_text = self.model.c_language.get_language_text(L_YOU_SURE)
338 if l_optional_text is None:
339 text = fix_text
340 else:
341 text = fix_text + "\n\n" + self.model.c_language.get_language_text(l_optional_text)
342 b_accept, _ = open_message_box(parent=self,
343 title=title,
344 text=text,
345 btn_yes=self.model.c_language.get_language_text(L_YES),
346 btn_cancel=self.model.c_language.get_language_text(L_CANCEL),
347 window_icon=s_icon_path)
348 return b_accept
349

◆ edit_items_in_notepad()

None edit_items_in_notepad ( self,
str s_file_name )

Open item file in notepad.

Parameters
s_file_name: file name to open in notepad

Definition at line 1267 of file main_window.py.

1267 def edit_items_in_notepad(self, s_file_name: str) -> None:
1268 """!
1269 @brief Open item file in notepad.
1270 @param s_file_name : file name to open in notepad
1271 """
1272 self.model.notepad_worker.open_report_file(s_file_name, ENotepadSelection.ARTICLES, lambda: self.model.c_config.read_item_file(s_file_name, True))
1273

◆ edit_user_in_notepad()

None edit_user_in_notepad ( self,
str s_file_name )

Open user file in notepad.

Parameters
s_file_name: file name to open in notepad

Definition at line 1214 of file main_window.py.

1214 def edit_user_in_notepad(self, s_file_name: str) -> None:
1215 """!
1216 @brief Open user file in notepad.
1217 @param s_file_name : file name to open in notepad
1218 """
1219 self.model.notepad_worker.open_report_file(s_file_name, ENotepadSelection.USER, lambda: self.model.c_config.read_user_file(s_file_name, True))
1220

◆ open_report_dialog()

None open_report_dialog ( self,
bool b_clear_report,
bool b_auto_print )

Open report dialog.

Parameters
b_clear_report: [True] create report and clear log; [False] show only status
b_auto_print: status if report was printed automatic

Definition at line 528 of file main_window.py.

528 def open_report_dialog(self, b_clear_report: bool, b_auto_print: bool) -> None:
529 """!
530 @brief Open report dialog.
531 @param b_clear_report : [True] create report and clear log; [False] show only status
532 @param b_auto_print : status if report was printed automatic
533 """
534 show_report_dialog(self, b_clear_report, b_auto_print)
535

◆ print_selected_articles()

float print_selected_articles ( self,
list[Item] l_item_log,
datetime actual_datetime )

Print selected articles.

Parameters
l_item_log: add printed articles to this list
actual_datetime: date for printed items
Returns
total price

Definition at line 1036 of file main_window.py.

1036 def print_selected_articles(self, l_item_log: list[Item], actual_datetime: datetime) -> float:
1037 """!
1038 @brief Print selected articles.
1039 @param l_item_log : add printed articles to this list
1040 @param actual_datetime : date for printed items
1041 @return total price
1042 """
1043 f_total_price = 0.0
1044 for i_item_pos, entry in enumerate(self.model.c_report.l_bar_items):
1045 if entry != 0: # items present and not free user for deposit
1046 i_item_number = i_item_pos + 1
1047 name = self.model.c_config.get_item_name(i_item_number)
1048 f_single_price = self.model.c_config.get_item_price(i_item_number)
1049 group = self.model.c_config.get_item_group(i_item_number)
1050 number = i_item_number
1051 b_print = self.model.c_config.get_print_article_status()
1052 if b_print:
1053 b_print = self.model.c_config.get_item_print_status(i_item_pos + 1)
1054 b_free_user = self.model.c_auth.check_user_login(EUser.FREE)
1055 f_price = 0.0 if b_free_user else f_single_price * entry
1056 f_total_price += f_price
1057 l_item_log.append(create_item(entry, name, number, group, f_single_price, f_price, self.model.c_auth.s_login_user, actual_datetime, b_print))
1058 return f_total_price
1059

◆ reset_config()

None reset_config ( self)

Handle reset configuration.

Definition at line 1386 of file main_window.py.

1386 def reset_config(self) -> None:
1387 """!
1388 @brief Handle reset configuration.
1389 """
1390 log.debug("Reset clicked")
1391 b_reset, ok = reset_config_dialog(self)
1392 if b_reset:
1393 self.close_window_dialog = False
1394 close_app(self)
1395 elif ok:
1396 self.set_status(["Invalid Password", "Passwort ungültig"])

◆ resizeEvent()

None resizeEvent ( self,
RESIZE_EVENT | None _event )

Default resize Event Method to handle change of window size.

Parameters
_event: arrived event

Definition at line 305 of file main_window.py.

305 def resizeEvent(self, _event: RESIZE_EVENT | None) -> None:
306 """!
307 @brief Default resize Event Method to handle change of window size
308 @param _event : arrived event
309 """
310 emit_signal(self.resized)
311

◆ set_status()

None set_status ( self,
str | list[str] text_value,
bool b_warning = False,
Optional[int] i_timeout = None,
bool b_highlight = False,
bool b_thread = False )

Logs a status message to status bar (with timer) and logging handler.

Parameters
text_value: text to set
b_warning: [True] Text is a warning; [False] normal info
b_highlight: [True] highlight text; [False] normal text
i_timeout: timeout for statustext in "ms". If None use default time
b_thread: call from thread to prevent timer activations (not allowed from thread)

Definition at line 466 of file main_window.py.

466 def set_status(self, text_value: str | list[str], b_warning: bool = False, i_timeout: Optional[int] = None, b_highlight: bool = False, b_thread: bool = False) -> None:
467 """!
468 @brief Logs a status message to status bar (with timer) and logging handler
469 @param text_value : text to set
470 @param b_warning : [True] Text is a warning; [False] normal info
471 @param b_highlight : [True] highlight text; [False] normal text
472 @param i_timeout : timeout for statustext in "ms". If None use default time
473 @param b_thread : call from thread to prevent timer activations (not allowed from thread)
474 """
475 text = self.model.c_language.get_language_text(text_value) if isinstance(text_value, list) else text_value
476 if b_warning:
477 log.warning(text)
478 else:
479 log.info(text)
480
481 if self.gui_locked:
482 locked_text = self.model.c_language.get_language_text(["Window Locked!",
483 "Das Fenster ist gesperrt!"])
484 config_label(self.statusbar_left, text=locked_text, bg=LOCKED_STYLE)
485 else:
486 if not (not b_warning and self.b_warning_active):
487 if hasattr(self, "status_timer"):
488 if not b_thread: # start/stop time from thread is not allowed
489 if i_timeout is None:
490 if b_warning:
491 i_timeout = STATUS_WARNING_TEXT_TIME
492 else:
493 i_timeout = STATUS_HIGHLIGHT_TEXT_TIME if b_highlight else STATUS_TEXT_TIME
494 if i_timeout is None:
495 self.status_timer.stop()
496 else:
497 self.status_timer.start(i_timeout)
498 if b_warning:
499 foreground = None
500 background = WARNING_STYLE if self.model.c_monitor.is_light_theme() else WARNING_STYLE_DARK
501 self.b_warning_active = True
502 else:
503 foreground = HIGHLIGHT_STYLE if b_highlight else None
504 background = DEFAULT_STYLE
505 self.b_warning_active = False
506 config_label(self.statusbar_left, text=text, bg=background, fg=foreground)
507

◆ set_ui()

None set_ui ( self,
bool b_state )

Blocks/Unblock the main UI elements.

Parameters
b_state: state if UI should blocked or unblocked, True: Enable, False: Disable

Definition at line 350 of file main_window.py.

350 def set_ui(self, b_state: bool) -> None:
351 """!
352 @brief Blocks/Unblock the main UI elements.
353 @param b_state : state if UI should blocked or unblocked, True: Enable, False: Disable
354 """
355 if not b_state:
356 for btn in self.l_bnt_fnc:
357 config_btn(btn, enable=b_state)
358
359 config_btn(self.btn_print, enable=b_state)
360 config_btn(self.btn_clear, enable=b_state)
361 config_btn(self.btn_multi, enable=b_state)
362 config_btn(self.btn_calc, enable=b_state)
363 config_btn(self.btn_lock, enable=b_state)
364 config_menu(self.menu_prints, enable=b_state)
365 config_menu(self.menu_configuration, enable=b_state)
366 config_menu(self.menu_settings, enable=b_state)
367 config_menu(self.menu_help, enable=b_state)
368

◆ show_help_dialog()

None show_help_dialog ( self)

Show help dialog.

Definition at line 458 of file main_window.py.

458 def show_help_dialog(self) -> None:
459 """!
460 @brief Show help dialog.
461 """
462 log.debug("Starting help dialog")
463 icon = ICON_HELP_LIGHT if self.model.c_monitor.is_light_theme() else ICON_HELP_DARK
464 config_window(self.dialog_help, title=self.model.c_language.get_language_text(L_MENU_HELP), icon=icon, show=True)
465

◆ show_item_btns()

None show_item_btns ( self)

Update item buttons.

Definition at line 536 of file main_window.py.

536 def show_item_btns(self) -> None:
537 """!
538 @brief Update item buttons.
539 """
540 log.debug("Update item buttons")
541 for i, btn in enumerate(self.l_bnt_fnc):
542 i_pos = i + 1
543 if i < self.model.c_config.item_number_size:
544 if self.model.c_auth.check_user_login(L_CONFIG_USER):
545 # show only disabled numbers
546 config_btn(btn, enable=False, show=True, text=str(i_pos))
547 else:
548 s_item_name = self.model.c_config.get_item_button_name(i_pos)
549 s_visible_user = self.model.c_config.get_item_visible_user(i_pos)
550 if (s_item_name != "") and ((s_visible_user is None) or self.model.c_auth.check_user_login(s_visible_user)):
551 if self.model.b_show_price:
552 f_item_price = self.model.c_config.get_item_price(i_pos)
553 s_item_name += f"\n{f_item_price:.2f} {S_UNIT_SYMBOL}"
554 config_btn(btn, enable=True, show=True, text=s_item_name)
555 else:
556 config_btn(btn, show=False)
557 if self.model.c_report.l_marked_items[i]:
558 background_color = "orange"
559 elif self.model.c_auth.check_user_login(EUser.FREE):
560 background_color = "lightgreen" if self.model.c_monitor.is_light_theme() else "darkgreen"
561 else:
562 select_bg = self.model.c_config.get_item_background(i_pos)
563 if select_bg:
564 background_color = select_bg
565 else:
566 background_color = None
567 if background_color is None:
568 config_btn(btn, style=self.model.c_monitor.default_button_stylesheet)
569 else:
570 config_btn(btn, bg=background_color)
571 else:
572 config_btn(btn, show=False)
573 config_btn(self.btn_lock, enable=True)
574

◆ show_login_btns()

None show_login_btns ( self)

Update login buttons.

Definition at line 575 of file main_window.py.

575 def show_login_btns(self) -> None:
576 """!
577 @brief Update login buttons.
578 """
579 log.debug("Update login buttons")
580 for i, btn in enumerate(self.l_bnt_fnc):
581 if i < ItemNumber.MIN:
582 pressed_button = L_LOGIN_KEYS[i]
583 s_name = pressed_button
584 if not pressed_button.isdigit():
585 user_name = self.model.c_config.get_user_name(L_LOGIN_KEYS[i])
586 if user_name != "":
587 s_name = "\n".join([s_name + ":"] + user_name.split())
588 config_btn(btn, enable=True, show=True, text=s_name)
589 background_color = None
590 match pressed_button:
591 case EUser.ADMIN:
592 background_color = "red"
593 case EUser.HOST:
594 background_color = "brown"
595 case EUser.FREE:
596 background_color = "green"
597 case EUser.LOCAL:
598 background_color = "blue"
599 case EUser.USER:
600 background_color = "lightgray" if self.model.c_monitor.is_light_theme() else "#141414"
601 case _:
602 if pressed_button[0] == EUser.B:
603 background_color = "lightblue" if self.model.c_monitor.is_light_theme() else "darkblue"
604 if background_color is None:
605 config_btn(btn, style=self.model.c_monitor.default_button_stylesheet)
606 else:
607 config_btn(btn, bg=background_color)
608
609 # enable user button if activated
610 pw = self.model.c_config.get_user_pw(pressed_button)
611 b_enable_user = bool((pressed_button in self.model.c_config.d_user)
612 and (S_PW in self.model.c_config.d_user[pressed_button])
613 and (pw.isdigit() or pw == ""))
614 match pressed_button:
615 case EUser.ADMIN:
616 b_enable_user = True # admin is already enabled to be able to reset config data
617 case EUser.HOST | EUser.FREE | EUser.LOCAL:
618 pass # b_enable_user is correct
619 case EUser.USER:
620 b_enable_user = False
621 case _:
622 if pressed_button[0] == EUser.B:
623 pass # b_enable_user is correct
624 else:
625 b_enable_user = bool(self.model.c_auth.s_login_user is not None) # numbers are enabled for select user
626 config_btn(btn, enable=b_enable_user)
627 else:
628 config_btn(btn, show=False)
629 config_btn(self.btn_lock, enable=False)
630 config_btn(self.btn_print, enable=False)
631

◆ show_number_btns()

None show_number_btns ( self)

Update number buttons.

Definition at line 632 of file main_window.py.

632 def show_number_btns(self) -> None:
633 """!
634 @brief Update number buttons.
635 """
636 log.debug("Update number buttons")
637 for i, btn in enumerate(self.l_bnt_fnc):
638 if i < ItemNumber.MIN:
639 s_name = L_LOGIN_KEYS[i]
640 match s_name:
641 case EUser.ADMIN:
642 s_name = S_DOT
643 b_show = bool(self.model.c_auth.e_view == EWindowView.CALC)
644 case EUser.HOST:
645 s_name = S_DOUBLE_NULL
646 b_show = True
647 case _:
648 b_show = bool((len(s_name) == 1) and s_name.isnumeric())
649 b_enable = bool((s_name not in L_SPECIAL_BTNS)
650 or ((self.model.c_calc.s_text_total != "") and ((s_name != S_DOT) or (S_DOT not in self.model.c_calc.s_text_total))))
651 config_btn(btn, text=s_name, enable=b_enable, style=self.model.c_monitor.default_button_stylesheet, show=b_show)
652 else:
653 config_btn(btn, show=False)
654 config_btn(self.btn_lock, enable=True)
655 match self.model.c_auth.e_view:
656 case EWindowView.MULTI:
657 config_btn(self.btn_multi, enable=True, show=True)
658 config_btn(self.btn_calc, enable=False, show=False)
659 case EWindowView.CALC:
660 config_btn(self.btn_multi, enable=False, show=False)
661 config_btn(self.btn_calc, enable=True, show=True)
662 case _:
663 self.set_status("Invalid Number Button Code", True) # state not possible
664 config_btn(self.btn_print, show=False)
665

◆ show_unauthenticated_dialog()

None show_unauthenticated_dialog ( self)

Show unauthenticated dialog.

Definition at line 437 of file main_window.py.

437 def show_unauthenticated_dialog(self) -> None:
438 """!
439 @brief Show unauthenticated dialog.
440 """
441 s_text = self.model.c_language.get_language_text(["Unauthenticated use", "Unauthentifizierte Verwendung"])
442 l_text = ["You are not entitled to test a pre-release version."
443 + "\n\nUse a published version:"
444 + f"\n{__home__}",
445 "Sie sind nicht berechtigt, eine Vorabversion zu testen."
446 + "\n\nVerwenden Sie eine veröffentlichte Version:"
447 + f"\n{__home__}"]
448 b_accept, _ = open_message_box(parent=self,
449 title=s_text,
450 text=self.model.c_language.get_language_text(l_text),
451 btn_close=self.model.c_language.get_language_text(L_CLOSE),
452 btn_special=self.model.c_language.get_language_text(L_COPY_URL),
453 window_icon=ICON_APP)
454 if b_accept:
455 copy_to_clipboard(__home__)
456 sys.exit() # exit application without close dialog
457

◆ show_update_dialog()

None show_update_dialog ( self,
str newer_tool_version )

Show Update dialog.

Parameters
newer_tool_version: newest tool version

Definition at line 389 of file main_window.py.

389 def show_update_dialog(self, newer_tool_version: str) -> None:
390 """!
391 @brief Show Update dialog.
392 @param newer_tool_version : newest tool version
393 """
394 l_text = [f"New version available! \nUpdate to version {newer_tool_version}?",
395 f"Neue Version verfügbar! \nUpdate auf Version {newer_tool_version} durchführen?"]
396 l_remember = ["Don't show again",
397 "Nicht mehr anzeigen"]
398 s_title = self.model.c_language.get_language_text(["Update Service", "Update-Dienst"])
399 b_update, is_checked = open_message_box(parent=self,
400 title=s_title,
401 text=self.model.c_language.get_language_text(l_text),
402 btn_yes=self.model.c_language.get_language_text(L_YES),
403 btn_no=self.model.c_language.get_language_text(L_NO),
404 check_box=self.model.c_language.get_language_text(l_remember),
405 window_icon=ICON_APP)
406 if is_checked:
407 write_update_version(newer_tool_version) # write newest version for don't remember again
408 if b_update:
409 copy_to_clipboard(S_UPDATE_URL)
410 webbrowser.open_new_tab(S_UPDATE_URL)
411 sys.exit() # exit application without close dialog
412

◆ show_welcome_dialog()

None show_welcome_dialog ( self)

Show welcome screen and choose admin password.

Definition at line 413 of file main_window.py.

413 def show_welcome_dialog(self) -> None:
414 """!
415 @brief Show welcome screen and choose admin password.
416 """
417 l_text = ["To change user and articles configuration, see the Help menu."
418 + "\n\nIf the Admin password is lost, all data can be reset:"
419 + "\n1. Select Admin User to show hidden menu"
420 + "\n2. Help→Reset"
421 + f"\n3. Enter reset code: {base64.b64decode(RESET_CODE).decode('utf-8')}"
422 + "\n\nChoose an Admin password (numbers only):",
423 "Um die Benutzer- und Artikelkonfiguration zu ändern, siehe im Menü Hilfe"
424 + "\n\nWenn das Admin-Passwort verloren geht, können alle Daten zurückgesetzt werden:"
425 + "\n1. Wählen Sie Admin User, um das ausgeblendete Menü anzuzeigen"
426 + "\n2. Help→Reset"
427 + f"\n3. Reset-Code eingeben: {base64.b64decode(RESET_CODE).decode('utf-8')}"
428 + "\n\nWählen Sie ein Admin-Passwort (nur Zahlen):"]
429 s_title = self.model.c_language.get_language_text(["Welcome to", "Willkommen zu"])
430 password, ok = input_dialog(self, f"{s_title} {__title__}", self.model.c_language.get_language_text(l_text), DEFAULT_CODE, icon=ICON_APP)
431 if ok and (password.isdigit() or password == ""):
432 self.model.c_config.d_user[EUser.ADMIN.value][S_PW] = str(password)
433 self.model.c_config.store_user_data()
434 else:
435 sys.exit() # exit application without close dialog
436

◆ unblock_ui()

None unblock_ui ( self)

Unblock the main UI elements.

Definition at line 378 of file main_window.py.

378 def unblock_ui(self) -> None:
379 """!
380 @brief Unblock the main UI elements.
381 """
382 log.debug("Unblock UI")
383 self.set_ui(True)
384 self.gui_locked = False
385 self.update_screen()
386 self.status_timer.stop() # stop timer to deactivate unlock diagnostic directly after clear status
387 self.clear_status()
388

◆ update_menu()

None update_menu ( self)

Update menu.

Definition at line 776 of file main_window.py.

776 def update_menu(self) -> None:
777 """!
778 @brief Update menu.
779 """
780 b_admin_settings = bool(self.model.c_auth.b_login_state and (self.model.c_auth.check_user_login(EUser.ADMIN)))
781 b_printer_available = bool(self.model.c_printer.s_select_com_port is not None)
782 b_edit_user = self.model.c_auth.b_login_state and (self.model.c_auth.check_user_login(L_CONFIG_USER))
783 b_log_exist = self.model.c_report.check_sales_exist()
784 b_print_menu = (self.model.b_enable_report or self.model.c_auth.check_user_login(EUser.ADMIN)) and self.model.c_auth.b_login_state and (not self.model.c_auth.check_user_login(EUser.FREE))
785 config_menu(self.menu_prints, show=b_print_menu)
786 config_menu(self.action_show_interim, enable=b_log_exist, show=self.model.b_enable_report)
787 config_menu(self.action_open_folder, show=b_edit_user)
788 config_menu(self.menu_combine_report, show=b_edit_user)
789 config_menu(self.action_print_file, enable=b_printer_available, show=b_edit_user)
790 config_menu(self.action_article_preview, show=b_edit_user)
791 config_menu(self.action_enable_report, show=b_admin_settings)
792 config_menu(self.action_create_billing, enable=b_log_exist, show=b_edit_user and self.model.b_enable_report)
793 config_menu(self.action_auto_export, show=False)
794 config_menu(self.menu_configuration, show=b_edit_user)
795 config_menu(self.action_user_import, enable=b_admin_settings)
796 config_menu(self.action_user_export, enable=b_admin_settings)
797 config_menu(self.action_user_new, enable=b_admin_settings)
798 config_menu(self.menu_articles, enable=b_admin_settings)
799 config_menu(self.action_articles_pdf_import, show=False)
800 config_menu(self.action_change_path, enable=b_admin_settings)
801 config_menu(self.action_webserver, show=False)
802 config_menu(self.menu_com_port, enable=b_admin_settings)
803 config_menu(self.menu_paper_width, enable=b_admin_settings)
804 config_menu(self.menu_smartcard, show=False)
805 config_menu(self.menu_display_port, show=False)
806 config_menu(self.action_auto_import, show=False)
807 config_menu(self.menu_log_verbosity, show=b_admin_settings)
808 config_menu(self.action_paper_change, show=False)
809 config_menu(self.action_reset, show=self.model.c_auth.check_user_login(EUser.ADMIN))
810

◆ update_screen()

None update_screen ( self)

Update complete screen.

Definition at line 811 of file main_window.py.

811 def update_screen(self) -> None:
812 """!
813 @brief Update complete screen.
814 """
815 log.debug("Update screen")
816 if not self.gui_locked:
817 self.model.c_monitor.check_for_style_change() # check every complete update cycle if style changed
818 if self.model.c_auth.b_login_state:
819 match self.model.c_auth.e_view:
820 case EWindowView.MULTI | EWindowView.CALC:
821 self.show_number_btns()
822 case _:
823 self.show_item_btns()
824 else:
825 self.model.c_report.clear_print_items()
826 self.show_login_btns()
827 self.update_table()
828 self.update_menu()
829 if self.model.c_config.item_number_size != ItemNumber.MIN: # update only required in extended item view for different button rows
830 self.model.c_monitor.resize_window()
831 else:
832 log.debug("Screen is locked - no update")
833

◆ update_table()

None update_table ( self)

Update table and print/clear button.

Definition at line 666 of file main_window.py.

666 def update_table(self) -> None:
667 """!
668 @brief Update table and print/clear button.
669 """
670 log.debug("Update table")
671 self.model.c_auth.refresh_timer() # refresh timer for every button click
672 clear_text = self.model.c_language.get_language_text(L_CLEAR)
673 l_row_description = self.model.c_language.get_table_row_description()
674 b_items_in_list = False
675 b_update_clear_btn = True
676 table = self.table_items
677 config_table(table, single_row_selection=not self.model.c_calc.b_hold_last_print,
678 row_description=l_row_description,
679 font=self.model.c_monitor.table_font, auto_size=True) # auto to set correct for style change
680 if self.model.c_calc.b_hold_last_print:
681 if self.model.c_auth.e_view == EWindowView.CALC: # hold items in calculator mode
682 b_clear_btn_enable = bool((self.model.c_calc.s_text_total != "") or (self.model.c_calc.i_multi > 0)) # enable status in multi/calc mode
683 fg_color = "red" if b_clear_btn_enable else "grey"
684 config_btn(self.btn_clear, enable=b_clear_btn_enable, text=clear_text, fg=fg_color, icon="")
685 background_color = "lightgreen" if self.model.c_monitor.is_light_theme() else "darkgreen"
686 config_text(self.text_total, bg=background_color, fg="black") # update color if theme changed while hold
687 self.model.c_calc.b_hold_last_print = False
688 else:
689 i = 0
690 f_total = 0.0
691 for i_item_pos, entry in enumerate(self.model.c_report.l_bar_items):
692 self.model.c_report.l_table_position[i_item_pos] = None
693 if entry != 0:
694 b_items_in_list = True
695 fg = None
696 item_name = self.model.c_config.get_item_name(i_item_pos + 1)
697 if self.model.c_auth.check_user_login(EUser.FREE):
698 f_price = 0.0
699 else:
700 f_item_price = self.model.c_config.get_item_price(i_item_pos + 1)
701 f_price = f_item_price * entry
702 f_total += f_price
703 bg = "orange" if self.model.c_report.l_marked_items[i_item_pos] else None
704 insert_table_item(table, i, [str(entry),
705 item_name,
706 f"{f_price:.2f} {S_UNIT_SYMBOL}"],
707 font=self.model.c_monitor.table_font,
708 fg=fg,
709 bg=bg)
710 self.model.c_report.l_table_position[i_item_pos] = i # save table position of item to delete single entries
711 i += 1
712
713 config_table(table, row_count=i, auto_size=True)
714
715 if self.model.c_auth.b_login_state and (self.model.c_auth.e_view == EWindowView.MAIN):
716 self.model.c_calc.s_text_total = f"{f_total:.2f} {S_UNIT_SYMBOL}"
717 if self.model.c_monitor.is_light_theme():
718 config_text(self.text_total, bg="white", fg="black")
719 else:
720 config_text(self.text_total, bg="black", fg="white")
721 if get_selected_table_column(self.table_items) != 0: # clear selected table position not if first column is selected
722 config_table(table, clear_selection=True) # clear selection at end of update to prevent that last single item marker jump to next
723
724 # update print button text
725 open_text = self.model.c_language.get_language_text(L_OPEN)
726 b_items_in_list = b_items_in_list or (sum(self.model.c_report.l_bar_items) != 0)
727 if self.model.c_printer.b_select_com_port_available:
728 if b_items_in_list or not self.model.c_auth.b_login_state:
729 s_btn_print_text = self.model.c_language.get_language_text(L_PRINT)
730 else:
731 s_btn_print_text = open_text
732 else:
733 s_btn_print_text = self.model.c_language.get_language_text(L_SAVE)
734
735 # set total text
736 if self.model.c_calc.i_multi > 1:
737 text = f"{self.model.c_calc.i_multi} x"
738 elif self.model.c_calc.f_back is not None:
739 to_pay_text = self.model.c_language.get_language_text(["to pay", "zu zahlen"])
740 given_text = self.model.c_language.get_language_text(["Given", "Gegeben"])
741 s_given_sum = f"{float(self.model.c_calc.f_payed):.2f}"
742 back_text = self.model.c_language.get_language_text(["Back", "Zurück"])
743 s_back_sum = f"{self.model.c_calc.f_back:.2f}" if (self.model.c_calc.f_back >= 0) else "---"
744 text = f"{to_pay_text}: {self.model.c_calc.f_total:.2f} {S_UNIT_SYMBOL}"
745 text += f"\n{given_text}: {s_given_sum} {S_UNIT_SYMBOL}"
746 text += f"\n{back_text}: {s_back_sum} {S_UNIT_SYMBOL}"
747 self.model.c_calc.f_back = None
748 self.model.c_calc.f_total = 0
749 else:
750 text = str(self.model.c_calc.s_text_total)
751 config_text(self.text_total, text=text)
752
753 # enable/disable/show/hide table buttons
754 b_no_config_user = not self.model.c_auth.check_user_login(L_CONFIG_USER)
755 b_sell_user = bool(self.model.c_auth.b_login_state and b_no_config_user)
756 config_btn(self.btn_multi, enable=b_sell_user)
757 config_btn(self.btn_calc, enable=(self.model.c_auth.check_user_login(EUser.LOCAL) and self.model.c_auth.b_login_state and (self.model.c_calc.f_total != 0)))
758 if b_update_clear_btn:
759 match self.model.c_auth.e_view:
760 case EWindowView.CALC | EWindowView.MULTI:
761 b_clear_btn_enable = bool((self.model.c_calc.s_text_total != "") or (self.model.c_calc.i_multi > 0)) # enable status in multi/calc mode
762 case _:
763 b_clear_btn_enable = bool(b_items_in_list or ((not self.model.c_auth.b_login_state) and (self.model.c_calc.s_text_total != "")))
764 fg_color = "red" if b_clear_btn_enable else "grey"
765 config_btn(self.btn_clear, enable=b_clear_btn_enable, text=clear_text, fg=fg_color, icon="")
766 b_enable_print = bool((not self.model.c_auth.check_user_login(EUser.USER))
767 and (b_items_in_list or ((s_btn_print_text == open_text) and self.model.c_auth.b_login_state and not self.model.c_auth.check_user_login(EUser.B))))
768 config_btn(self.btn_print, enable=b_enable_print, text=s_btn_print_text)
769 if self.model.c_auth.e_view == EWindowView.MAIN:
770 config_btn(self.btn_multi, show=True)
771 config_btn(self.btn_calc, show=True)
772 config_btn(self.btn_clear, show=True)
773 config_btn(self.btn_print, show=True)
774 self.model.c_monitor.resize_window(b_update_only_total_font=True) # update only total text font size for pay back
775

Member Data Documentation

◆ action_58mm

action_58mm

Definition at line 259 of file main_window.py.

◆ action_80mm

action_80mm

Definition at line 260 of file main_window.py.

◆ action_about_app

action_about_app

Definition at line 282 of file main_window.py.

◆ action_article_preview

action_article_preview

Definition at line 231 of file main_window.py.

◆ action_articles_edit

action_articles_edit

Definition at line 240 of file main_window.py.

◆ action_articles_export

action_articles_export

Definition at line 242 of file main_window.py.

◆ action_articles_import

action_articles_import

Definition at line 241 of file main_window.py.

◆ action_articles_new

action_articles_new

Definition at line 243 of file main_window.py.

◆ action_articles_pdf_import

action_articles_pdf_import

Definition at line 799 of file main_window.py.

◆ action_auto

action_auto

Definition at line 264 of file main_window.py.

◆ action_auto_export

action_auto_export

Definition at line 793 of file main_window.py.

◆ action_auto_import

action_auto_import

Definition at line 806 of file main_window.py.

◆ action_change_path

action_change_path

Definition at line 245 of file main_window.py.

◆ action_combine_auto

action_combine_auto

Definition at line 229 of file main_window.py.

◆ action_combine_manual

action_combine_manual

Definition at line 228 of file main_window.py.

◆ action_create_billing

action_create_billing

Definition at line 233 of file main_window.py.

◆ action_dark

action_dark

Definition at line 266 of file main_window.py.

◆ action_enable_report

action_enable_report

Definition at line 182 of file main_window.py.

◆ action_english

action_english

Definition at line 270 of file main_window.py.

◆ action_german

action_german

Definition at line 271 of file main_window.py.

◆ action_help

action_help

Definition at line 281 of file main_window.py.

◆ action_light

action_light

Definition at line 265 of file main_window.py.

◆ action_log_debug

action_log_debug

Definition at line 278 of file main_window.py.

◆ action_log_error

action_log_error

Definition at line 275 of file main_window.py.

◆ action_log_info

action_log_info

Definition at line 277 of file main_window.py.

◆ action_log_warning

action_log_warning

Definition at line 276 of file main_window.py.

◆ action_none

action_none

Definition at line 247 of file main_window.py.

◆ action_normal

action_normal

Definition at line 267 of file main_window.py.

◆ action_open_folder

action_open_folder

Definition at line 227 of file main_window.py.

◆ action_paper_change

action_paper_change

Definition at line 808 of file main_window.py.

◆ action_port_1

action_port_1

Definition at line 248 of file main_window.py.

◆ action_port_10

action_port_10

Definition at line 257 of file main_window.py.

◆ action_port_2

action_port_2

Definition at line 249 of file main_window.py.

◆ action_port_3

action_port_3

Definition at line 250 of file main_window.py.

◆ action_port_4

action_port_4

Definition at line 251 of file main_window.py.

◆ action_port_5

action_port_5

Definition at line 252 of file main_window.py.

◆ action_port_6

action_port_6

Definition at line 253 of file main_window.py.

◆ action_port_7

action_port_7

Definition at line 254 of file main_window.py.

◆ action_port_8

action_port_8

Definition at line 255 of file main_window.py.

◆ action_port_9

action_port_9

Definition at line 256 of file main_window.py.

◆ action_print_file

action_print_file

Definition at line 230 of file main_window.py.

◆ action_reset

action_reset

Definition at line 283 of file main_window.py.

◆ action_show_interim

action_show_interim

Definition at line 226 of file main_window.py.

◆ action_show_price

action_show_price

Definition at line 179 of file main_window.py.

◆ action_sound

action_sound

Definition at line 176 of file main_window.py.

◆ action_system

action_system

Definition at line 268 of file main_window.py.

◆ action_user_edit

action_user_edit

Definition at line 235 of file main_window.py.

◆ action_user_export

action_user_export

Definition at line 237 of file main_window.py.

◆ action_user_import

action_user_import

Definition at line 236 of file main_window.py.

◆ action_user_new

action_user_new

Definition at line 238 of file main_window.py.

◆ action_webserver

action_webserver

Definition at line 801 of file main_window.py.

◆ ag_language

ag_language
Initial value:
= group_menu(self,
[self.action_english, self.action_german],
self.model.c_language.e_language,
[ELanguages.ENGLISH, ELanguages.GERMAN])

Definition at line 191 of file main_window.py.

◆ ag_paper_width

ag_paper_width
Initial value:
= group_menu(self,
[self.action_58mm, self.action_80mm],
self.model.c_printer.i_paper_width,
[EPaper.WIDTH_58_MM, EPaper.WIDTH_80_MM])

Definition at line 170 of file main_window.py.

◆ ag_port

ag_port = None

Definition at line 153 of file main_window.py.

◆ ag_theme

ag_theme
Initial value:
= group_menu(self,
[self.action_auto, self.action_light, self.action_dark, self.action_system],
self.model.c_monitor.e_style,
[ETheme.AUTO, ETheme.LIGHT, ETheme.DARK, ETheme.SYSTEM])

Definition at line 185 of file main_window.py.

◆ ag_verbosity

ag_verbosity
Initial value:
= group_menu(self,
[self.action_log_error, self.action_log_warning, self.action_log_info, self.action_log_debug],
self.model.log_config.i_log_level,
[logging.ERROR, logging.WARNING, logging.INFO, logging.DEBUG])

Definition at line 164 of file main_window.py.

◆ b_btn_hold

bool b_btn_hold = False

Definition at line 210 of file main_window.py.

◆ b_warning_active

b_warning_active = False

Definition at line 129 of file main_window.py.

◆ btn_article_preview

btn_article_preview

Definition at line 231 of file main_window.py.

◆ btn_calc

btn_calc

Definition at line 220 of file main_window.py.

◆ btn_calc_clicked

btn_calc_clicked

Definition at line 220 of file main_window.py.

◆ btn_change_item

btn_change_item

Definition at line 240 of file main_window.py.

◆ btn_change_user

btn_change_user

Definition at line 235 of file main_window.py.

◆ btn_clear

btn_clear

Definition at line 221 of file main_window.py.

◆ btn_clear_clicked

btn_clear_clicked

Definition at line 221 of file main_window.py.

◆ btn_combine_auto

btn_combine_auto

Definition at line 229 of file main_window.py.

◆ btn_combine_manual

btn_combine_manual

Definition at line 228 of file main_window.py.

◆ btn_lock

btn_lock

Definition at line 223 of file main_window.py.

◆ btn_lock_clicked

btn_lock_clicked

Definition at line 223 of file main_window.py.

◆ btn_multi

btn_multi

Definition at line 219 of file main_window.py.

◆ btn_multi_clicked

btn_multi_clicked

Definition at line 219 of file main_window.py.

◆ btn_open_folder

btn_open_folder

Definition at line 227 of file main_window.py.

◆ btn_print

btn_print

Definition at line 222 of file main_window.py.

◆ btn_print_clicked

btn_print_clicked

Definition at line 222 of file main_window.py.

◆ btn_print_file

btn_print_file

Definition at line 230 of file main_window.py.

◆ btn_report_print

btn_report_print

Definition at line 226 of file main_window.py.

◆ btn_timer

btn_timer = create_timer(parent=self, callback=self.btn_item_held)

Definition at line 212 of file main_window.py.

◆ change_output_path

change_output_path

Definition at line 245 of file main_window.py.

◆ close_window_dialog

bool close_window_dialog = True

Definition at line 127 of file main_window.py.

◆ dialog_help

dialog_help = create_help_dialog(self)

Definition at line 132 of file main_window.py.

◆ gui_locked

bool gui_locked = False

Definition at line 128 of file main_window.py.

◆ i_btn_hold_idx

int i_btn_hold_idx = 0

Definition at line 211 of file main_window.py.

◆ l_action_com_port

list l_action_com_port
Initial value:
= [self.action_port_1,
self.action_port_2,
self.action_port_3,
self.action_port_4,
self.action_port_5,
self.action_port_6,
self.action_port_7,
self.action_port_8,
self.action_port_9,
self.action_port_10]

Definition at line 143 of file main_window.py.

◆ l_bnt_fnc

l_bnt_fnc
Initial value:
= [self.btn_item1, self.btn_item2, self.btn_item3, self.btn_item4, self.btn_item5,
self.btn_item6, self.btn_item7, self.btn_item8, self.btn_item9, self.btn_item10,
self.btn_item11, self.btn_item12, self.btn_item13, self.btn_item14, self.btn_item15,
self.btn_item16, self.btn_item17, self.btn_item18, self.btn_item19, self.btn_item20,
self.btn_item21, self.btn_item22, self.btn_item23, self.btn_item24, self.btn_item25,
self.btn_item26, self.btn_item27, self.btn_item28, self.btn_item29, self.btn_item30,
self.btn_item31, self.btn_item32, self.btn_item33, self.btn_item34, self.btn_item35,
self.btn_item36, self.btn_item37, self.btn_item38, self.btn_item39, self.btn_item40,
self.btn_item41, self.btn_item42, self.btn_item43, self.btn_item44, self.btn_item45,
self.btn_item46, self.btn_item47, self.btn_item48, self.btn_item49, self.btn_item50,
self.btn_item51, self.btn_item52, self.btn_item53, self.btn_item54, self.btn_item55,
self.btn_item56]

Definition at line 198 of file main_window.py.

◆ menu_articles

menu_articles

Definition at line 798 of file main_window.py.

◆ menu_com_port

menu_com_port

Definition at line 802 of file main_window.py.

◆ menu_combine_report

menu_combine_report

Definition at line 788 of file main_window.py.

◆ menu_configuration

menu_configuration

Definition at line 365 of file main_window.py.

◆ menu_display_port

menu_display_port

Definition at line 805 of file main_window.py.

◆ menu_help

menu_help

Definition at line 367 of file main_window.py.

◆ menu_log_verbosity

menu_log_verbosity

Definition at line 807 of file main_window.py.

◆ menu_paper_width

menu_paper_width

Definition at line 803 of file main_window.py.

◆ menu_prints

menu_prints

Definition at line 364 of file main_window.py.

◆ menu_settings

menu_settings

Definition at line 366 of file main_window.py.

◆ menu_smartcard

menu_smartcard

Definition at line 804 of file main_window.py.

◆ menubar

menubar

Definition at line 285 of file main_window.py.

◆ model

model = Model(self, log_config)

Definition at line 155 of file main_window.py.

◆ qt_exception_hook

qt_exception_hook = qt_exception_hook

Definition at line 126 of file main_window.py.

◆ reset_config

reset_config

Definition at line 283 of file main_window.py.

◆ resized

resized = SIGNAL()
static

Definition at line 119 of file main_window.py.

◆ show_help_dialog

show_help_dialog

Definition at line 281 of file main_window.py.

◆ status_timer

status_timer = create_timer(parent=self, callback=self.clear_status)

Definition at line 161 of file main_window.py.

◆ statusbar_left

statusbar_left = LABEL()

Definition at line 135 of file main_window.py.

◆ statusbar_right

statusbar_right = LABEL()

Definition at line 136 of file main_window.py.

◆ table_items

table_items

Definition at line 721 of file main_window.py.

◆ test_mode

test_mode = test_mode

Definition at line 125 of file main_window.py.

◆ text_total

text_total

Definition at line 686 of file main_window.py.

◆ unblock_ui

unblock_ui

Definition at line 1144 of file main_window.py.


The documentation for this class was generated from the following file: