BonPrinter v1.2.0
Thermal Printer tool
Loading...
Searching...
No Matches
gui_toolkit.py
Go to the documentation of this file.
1"""!
2********************************************************************************
3@file gui_toolkit.py
4@brief individual GUI toolkit function and selection
5********************************************************************************
6"""
7
8# autopep8: off
9import sys
10import os
11from typing import Any, Optional, TYPE_CHECKING
12
13
14import markdown # pylint: disable=wrong-import-position
15import qdarktheme # pylint: disable=wrong-import-position
16import pygame # pylint: disable=wrong-import-position
17
18from PyQt6.QtGui import QIcon, QPixmap, QFont, QAction, QActionGroup, QStatusTipEvent, QColor, QResizeEvent, QCloseEvent # pylint: disable=wrong-import-position
19from PyQt6.QtWidgets import QMainWindow, QMessageBox, QAbstractItemView, QTableWidgetItem, QPushButton, QLabel, QTextBrowser, QStatusBar, QTabWidget, \
20 QHeaderView, QInputDialog, QLineEdit, QApplication, QDialog, QFileDialog, QMenuBar, QTableWidget, QCheckBox, QWidget, QMenu # pylint: disable=wrong-import-position
21from PyQt6.QtCore import QSharedMemory, Qt, QThread, QSettings, QObject, pyqtSignal, pyqtBoundSignal, QSize, QRect, QEvent, QTimer, QByteArray # pylint: disable=wrong-import-position
22
23from Source.Views.mainwindow_ui import Ui_MainWindow # pylint: disable=wrong-import-position
24from Source.Views.dialogs.dialog_splash_ui import Ui_SplashScreen # pylint: disable=wrong-import-position
25from Source.Views.dialogs.dialog_about_ui import Ui_AboutDialog # pylint: disable=wrong-import-position
26from Source.Views.dialogs.dialog_help_ui import Ui_HelpDialog # pylint: disable=wrong-import-position
27from Source.Views.dialogs.dialog_report_ui import Ui_ReportDialog # pylint: disable=wrong-import-position
28from Source.Views.dialogs.dialog_article_size_ui import Ui_ArticleSizeDialog # pylint: disable=wrong-import-position
29if TYPE_CHECKING:
30 from Source.Controller.main_window import MainWindow
31# autopep8: on
32
33
34APPLICATION = QApplication
35SHARED_MEMORY = QSharedMemory
36WINDOW_TYPE = QMainWindow
37THREAD = QThread
38SIGNAL = pyqtSignal
39SIGNAL_BOUND = pyqtBoundSignal
40SETTINGS = QSettings
41OBJECT = QObject
42LABEL = QLabel
43WIDGET = QWidget
44ACTION = QAction
45RESIZE_EVENT = QResizeEvent
46CLOSE_EVENT = QCloseEvent
47DIALOG = QDialog
48FONT = QFont
49BYTE_ARRAY = QByteArray
50BUTTON = QPushButton
51MAIN_WINDOW = Ui_MainWindow
52SPLASH_SCREEN = Ui_SplashScreen
53HELP_DIALOG = Ui_HelpDialog
54ABOUT_DIALOG = Ui_AboutDialog
55REPORT_DIALOG = Ui_ReportDialog
56ARTICLE_SIZE_DIALOG = Ui_ArticleSizeDialog
57
58I_MENU_FONT_SIZE = 14
59I_MENU_BAR_HEIGHT = 30
60
61
62
65
66def check_app_already_open(shared_memory: QSharedMemory) -> bool:
67 """!
68 @brief Check if application is already open
69 @param shared_memory : shared memory
70 @return status if application is already open
71 """
72 b_already_open = not shared_memory.create(1)
73 return b_already_open
74
75
76def run_app(window: "APPLICATION | DIALOG | MainWindow", app: Optional[APPLICATION | DIALOG], close_event: bool = False) -> None:
77 """!
78 @brief Run application
79 @param window : window
80 @param app : app
81 @param close_event: close complete application
82 """
83 if window is not None:
84 if not isinstance(window, APPLICATION):
85 window.show()
86 if app is not None:
87 if close_event:
88 sys.exit(app.exec())
89 else:
90 app.exec()
91
92
93def close_app(window: "DIALOG | MainWindow") -> None:
94 """!
95 @brief Close application
96 @param window : window to close
97 """
98 window.close()
99
100
101def connect_signal(signal: SIGNAL_BOUND, function: Any) -> None:
102 """!
103 @brief Connect signal.
104 @param signal : signal variable
105 @param function : function to connect
106 """
107 signal.connect(function)
108
109
110def disconnect_signal(signal: SIGNAL_BOUND) -> None:
111 """!
112 @brief Disconnect signal.
113 @param signal : signal variable
114 """
115 signal.disconnect()
116
117
118def emit_signal(signal: SIGNAL_BOUND) -> None:
119 """!
120 @brief Emit signal.
121 @param signal : signal to call
122 """
123 signal.emit()
124
125
126
129
130def config_window(window: "DIALOG | MainWindow", title: Optional[str] = None, frameless: bool = False, icon: Optional[str] = None, fullscreen: Optional[bool] = None,
131 min_width: Optional[int] = None, min_height: Optional[int] = None, geometry: Optional[QByteArray] = None, state: Optional[QByteArray] = None,
132 fix_size: bool = False, resize: Optional[tuple[int, int]] = None, move: Optional[tuple[int, int]] = None, style: Optional[str] = None,
133 resize_callback: Any = None, show: Optional[bool] = None, thread: Optional[bool] = False) -> None:
134 """!
135 @brief Configure Window
136 @param window : window
137 @param title : windows title
138 @param icon : window icon
139 @param fullscreen : fullscreen status
140 @param min_width : minimum window width
141 @param min_height : minimum window height
142 @param geometry : window geometry
143 @param state : window state
144 @param fix_size : state if window is resizable
145 @param resize : resize size
146 @param move : move window
147 @param style : window style
148 @param resize_callback : resize callback function
149 @param frameless : no window flags and frameless
150 @param show : show/close window
151 @param thread : run window in Thread
152 """
153 if title is not None:
154 window.setWindowTitle(title)
155 if frameless:
156 window.setWindowFlag(Qt.WindowType.FramelessWindowHint)
157 else:
158 if icon is not None:
159 window.setWindowIcon(QIcon(icon))
160 if fullscreen is not None:
161 if fullscreen:
162 if not window.isFullScreen():
163 window.showFullScreen()
164 else:
165 if window.isFullScreen():
166 window.showNormal()
167 if min_width is not None:
168 window.setMinimumWidth(min_width)
169 if min_height is not None:
170 window.setMinimumHeight(min_height)
171 if geometry is not None:
172 window.restoreGeometry(geometry)
173 if state is not None:
174 if not isinstance(window, DIALOG):
175 window.restoreState(state)
176 if fix_size:
177 window.setFixedSize(window.size())
178 if resize is not None:
179 width, height = resize
180 window.resize(width, height)
181 if move is not None:
182 x, y = move
183 window.move(x, y)
184 if style is not None:
185 window.setStyleSheet(style)
186 if resize_callback is not None:
187 if not isinstance(window, DIALOG):
188 window.resized.connect(resize_callback)
189 if show is not None:
190 if show:
191 window.show()
192 else:
193 window.close()
194
195
196def config_app(app: APPLICATION, icon: Optional[str] = None, process_events: Optional[bool] = False) -> None:
197 """!
198 @brief Configure Application
199 @param app : application
200 @param icon : window icon
201 @param process_events : process event status
202 """
203 if icon is not None:
204 app.setWindowIcon(QIcon(icon))
205 if process_events:
206 app.processEvents()
207
208
209def get_window_size(window: "MainWindow | QDialog") -> tuple[int, int]:
210 """!
211 @brief Get window size
212 @param window : window
213 @return windows width and height
214 """
215 width = window.frameGeometry().width()
216 height = window.frameGeometry().height()
217 return width, height
218
219
220def get_window_position(window: "MainWindow | QDialog") -> tuple[int, int]:
221 """!
222 @brief Get window position
223 @param window : window
224 @return windows x and y position
225 """
226 x = window.x()
227 y = window.y()
228 return x, y
229
230
231def get_window_geometry(window: WINDOW_TYPE) -> BYTE_ARRAY:
232 """!
233 @brief Get window geometry for safe
234 @param window : window
235 @return window geometry
236 """
237 window_geometry = window.saveGeometry()
238 return window_geometry
239
240
241def get_window_state(window: WINDOW_TYPE) -> BYTE_ARRAY:
242 """!
243 @brief Get window state for safe
244 @param window : window
245 @return window geometry
246 """
247 window_geometry = window.saveState()
248 return window_geometry
249
250
251def get_fullscreen_status(window: WINDOW_TYPE) -> bool:
252 """!
253 @brief Get fullscreen status
254 @param window : window
255 @return fullscreen status
256 """
257 fullscreen = bool(window.isFullScreen())
258 return fullscreen
259
260
261def get_style(dark_mode: bool = False) -> str:
262 """!
263 @brief Get Style
264 @param dark_mode : style status for dark mode
265 @return style
266 """
267 style: str
268 if dark_mode:
269 style = qdarktheme.load_stylesheet("dark", corner_shape="rounded")
270 else:
271 style = qdarktheme.load_stylesheet("light", corner_shape="rounded")
272 return style
273
274
275
278
279def filter_menubar(menubar: QMenuBar, gui: WINDOW_TYPE) -> None:
280 """!
281 @brief Menubar filter
282 @param menubar : menubar
283 @param gui : gui
284 @return event filter TODO kein richtiger return
285 """
286 class StatusTipFilter(QObject):
287 """!
288 @brief Event Filter.
289 """
290
291 def eventFilter(self, watched: Optional[QObject], event: Optional[QEvent]) -> bool: # pylint: disable=invalid-name
292 """!
293 @brief Filter to prevent tip event (statusbar message no longer disappears on menu hover).
294 @param watched : object
295 @param event : arrived event
296 @return return event filter
297 """
298 if isinstance(event, QStatusTipEvent):
299 b_return = True
300 else:
301 b_return = super().eventFilter(watched, event)
302 return b_return
303
304 menubar.installEventFilter(StatusTipFilter(gui))
305
306
307def connect_menu(menu: QMenu | QAction, function: Any, index: Any = "") -> None:
308 """!
309 @brief Connect menu.
310 @param menu : connect function to this menu
311 @param function : function to connect
312 @param index : index to connect function with parameter
313 """
314 if index == "":
315 menu.triggered.connect(function)
316 else:
317 menu.triggered.connect(lambda: function(index))
318
319
320def get_menu_text(menu: QAction) -> str:
321 """!
322 @brief Get text from menu
323 @param menu : menu to get text
324 @return text from menu
325 """
326 menu_text = menu.text()
327 return menu_text
328
329
330def config_menu(menu: QMenu | QAction, enable: Optional[bool] = None, show: Optional[bool] = None,
331 text: Optional[str] = None, checked: Optional[bool] = None, icon: Optional[str] = None) -> None:
332 """!
333 @brief Configure menu.
334 @param menu : menu to configure
335 @param enable : enable status
336 @param show : show status
337 @param text : menu text
338 @param checked : checked status
339 @param icon : path for menu icon
340 """
341 if enable is not None:
342 menu.setEnabled(enable)
343 if show is not None:
344 if isinstance(menu, QMenu):
345 menu_action = menu.menuAction()
346 if menu_action is not None:
347 menu_action.setVisible(show)
348 else:
349 menu.setVisible(show)
350 if text is not None:
351 if isinstance(menu, QMenu):
352 menu.setTitle(text)
353 else:
354 menu.setText(text)
355 font = QFont()
356 font.setPointSize(I_MENU_FONT_SIZE)
357 menu.setFont(font)
358 if checked is not None:
359 if isinstance(menu, QAction):
360 menu.setChecked(checked)
361 if icon is not None:
362 menu.setIcon(QIcon(icon))
363
364
365def group_menu(parent: "MainWindow", l_actions: list[QAction], actual_value: Any, l_match_values: list[Any]) -> QActionGroup:
366 """!
367 @brief Set action group.
368 @param parent : parent window controller
369 @param l_actions: list with actions to add
370 @param actual_value : actual setting value
371 @param l_match_values : list with possible match values to check default setting
372 @return action group object
373 """
374 action_group = QActionGroup(parent)
375 for action in l_actions:
376 action_group.addAction(action)
377 for i, match_value in enumerate(l_match_values):
378 if match_value == actual_value:
379 l_actions[i].setChecked(True)
380 break
381 return action_group
382
383
384def group_available_menu(parent: "MainWindow", l_actions: list[QAction], actual_value: Any,
385 l_match_values: list[Any], none_action: QAction) -> tuple[QActionGroup, bool]:
386 """!
387 @brief Set action group.
388 @param parent : parent window controller
389 @param l_actions: list with actions to add
390 @param actual_value : actual setting value
391 @param l_match_values : list with possible match values to check default setting
392 @param none_action : none action is set if actual_value is None
393 @return action group object
394 """
395 action_group = QActionGroup(parent)
396 action_group.addAction(none_action)
397 all_actions_add = True
398 config_menu(none_action, text="None")
399 if actual_value is None:
400 none_action.setChecked(True)
401 b_action_present = True
402 else:
403 none_action.setChecked(False)
404 b_action_present = False
405 i_action_index = 0
406 for value in l_match_values:
407 if i_action_index < len(l_actions):
408 config_menu(l_actions[i_action_index], enable=True, show=True, text=value)
409 action_group.addAction(l_actions[i_action_index])
410 if actual_value == value:
411 b_action_present = True
412 config_menu(l_actions[i_action_index])
413 l_actions[i_action_index].setChecked(True)
414 else:
415 l_actions[i_action_index].setChecked(False)
416 i_action_index += 1
417 else:
418 all_actions_add = False
419 break
420 for i_index in range(i_action_index, len(l_actions)):
421 if (i_index == i_action_index) and (not b_action_present):
422 config_menu(l_actions[i_index], enable=False, show=True, text=actual_value)
423 l_actions[i_index].setChecked(True)
424 else:
425 config_menu(l_actions[i_index], enable=False, show=False)
426 action_group.addAction(l_actions[i_index])
427 return action_group, all_actions_add
428
429
430
433
434def connect_button(btn: QPushButton, clicked_fnc: Any = None, pressed_fnc: Any = None,
435 released_fnc: Any = None, index: Any = "") -> None:
436 """!
437 @brief Connect widget.
438 @param btn : connect function to this button
439 @param clicked_fnc : function to connect button clicked
440 @param pressed_fnc : function to connect button pressed
441 @param released_fnc : function to connect button released
442 @param index : index to connect function with parameter
443 """
444 if clicked_fnc is not None:
445 if index == "":
446 btn.clicked.connect(clicked_fnc)
447 else:
448 btn.clicked.connect(lambda: clicked_fnc(index))
449 if pressed_fnc is not None:
450 if index == "":
451 btn.pressed.connect(pressed_fnc)
452 else:
453 btn.pressed.connect(lambda: pressed_fnc(index))
454 if released_fnc is not None:
455 if index == "":
456 btn.released.connect(released_fnc)
457 else:
458 btn.released.connect(lambda: released_fnc(index))
459
460
461def config_btn(btn: QPushButton, enable: Optional[bool] = None, show: Optional[bool] = None, text: Optional[str] = None,
462 fg: Optional[str] = None, bg: Optional[str] = None, style: Optional[str] = None, icon: Optional[str] = None,
463 size: Optional[tuple[int, int, int, int]] = None, font: Optional[QFont] = None, icon_size: Optional[int] = None) -> None:
464 """!
465 @brief Configure button.
466 @param btn : button to configure
467 @param enable : enable status
468 @param show : show status
469 @param text : button text
470 @param fg : foreground color
471 @param bg : background color
472 @param style : button style
473 @param icon : icon in button
474 @param size : button size and position
475 @param font : button text font
476 @param icon_size : icon size
477 """
478 if enable is not None:
479 btn.setEnabled(enable)
480 if show is not None:
481 if show:
482 btn.show()
483 else:
484 btn.hide()
485 if text is not None:
486 btn.setText(text)
487 if style is None:
488 if fg is not None:
489 btn.setStyleSheet(f"color: {fg};")
490 if bg is not None:
491 btn.setStyleSheet(f"background-color: {bg};")
492 else:
493 btn.setStyleSheet(style)
494 if icon is not None:
495 if icon:
496 image = QIcon()
497 image.addPixmap(QPixmap(icon), QIcon.Mode.Normal, QIcon.State.Off)
498 btn.setIcon(image)
499 else:
500 btn.setIcon(QIcon()) # delete icon from button
501 if icon_size is not None:
502 btn.setIconSize(QSize(icon_size, icon_size))
503 if size is not None:
504 x, y, width, height = size
505 btn.setGeometry(QRect(x, y, width, height))
506 if font is not None:
507 btn.setFont(font)
508
509
510def get_btn_text(btn: QPushButton) -> str:
511 """!
512 @brief Get button text
513 @param btn : button to get text
514 @return button text
515 """
516 btn_text = btn.text()
517 return btn_text
518
519
520
523
524def config_label(label: QLabel, text: Optional[str] = None, fg: Optional[str] = None, bg: Optional[str] = None,
525 size: Optional[tuple[int, int, int, int]] = None, font: Optional[QFont] = None, central: bool = False,
526 open_link: Optional[str] = None, show: Optional[bool] = None) -> None:
527 """!
528 @brief Configure label.
529 @param label : label widget to set
530 @param text : text to set
531 @param fg : foreground color
532 @param bg : background color
533 @param size : text size and position
534 @param font : text font
535 @param central : central alignment
536 @param open_link : open link
537 @param show : show text
538 """
539 if text is not None:
540 if open_link is not None:
541 text += f"<a href=\"{open_link}\">{open_link}</a>"
542 label.setText(text)
543 if bg is not None: # call before set foreground to prevent override.
544 label.setStyleSheet(f"background-color: {bg};")
545 if fg is not None:
546 label.setStyleSheet(f"color: {fg};")
547 if size is not None:
548 x, y, width, height = size
549 label.setGeometry(QRect(x, y, width, height))
550 if font is not None:
551 label.setFont(font)
552 if central:
553 label.setAlignment(Qt.AlignmentFlag.AlignCenter)
554 if open_link is not None:
555 label.setOpenExternalLinks(bool(open_link))
556 if show is not None:
557 if show:
558 label.show()
559 else:
560 label.hide()
561
562
563
566
567def config_text(label: QTextBrowser, text: Optional[str] = None, fg: Optional[str] = None, bg: Optional[str] = None,
568 size: Optional[tuple[int, int, int, int]] = None, font: Optional[QFont] = None) -> None:
569 """!
570 @brief Configure text.
571 @param label : label widget to set
572 @param text : text to set
573 @param fg : foreground color
574 @param bg : background color
575 @param size : text size and position
576 @param font : text font
577 """
578 if text is not None:
579 label.setText(text)
580 if fg is not None:
581 label.setStyleSheet(f"color: {fg};")
582 if bg is not None:
583 label.setStyleSheet(f"background-color: {bg};")
584 if size is not None:
585 x, y, width, height = size
586 label.setGeometry(QRect(x, y, width, height))
587 if font is not None:
588 label.setFont(font)
589
590
591def get_text(label: QTextBrowser) -> str:
592 """!
593 @brief Configure text.
594 @param label : label widget to set
595 @return text from label
596 """
597 text = label.toPlainText()
598 return text
599
600
601
604
605def config_statusbar(statusbar: QStatusBar, lbl_left: Optional[QLabel] = None, lbl_right: Optional[QLabel] = None,
606 text: Optional[str] = None, fg: Optional[str] = None, bg: Optional[str] = None) -> None:
607 """!
608 @brief Configure statusbar.
609 @param statusbar : statusbar widget
610 @param lbl_left : statusbar label left
611 @param lbl_right : statusbar label right
612 @param text : statusbar text
613 @param fg : front color
614 @param bg : background color
615 """
616 if (lbl_left is None) and (lbl_right is None):
617 if text is not None:
618 statusbar.showMessage(text)
619 if bg is not None:
620 statusbar.setStyleSheet(f"background-color: {bg};") # call before set foreground to prevent override.
621 if fg is not None:
622 statusbar.setStyleSheet(f"color: {fg};")
623 else:
624 if lbl_left is not None:
625 statusbar.addWidget(lbl_left)
626 if lbl_right is not None:
627 statusbar.addPermanentWidget(lbl_right)
628
629
630
633
634def config_table(table: QTableWidget, clear_selection: bool = False, single_row_selection: Optional[bool] = None,
635 row_description: Optional[list[str]] = None, font: Optional[QFont] = None,
636 size: Optional[tuple[int, int, int, int]] = None, min_section_size: Optional[int] = None,
637 row_count: Optional[int] = None, auto_size: bool = False) -> None:
638 """!
639 @brief Configure table
640 @param table : table to configure
641 @param clear_selection : clear selected table item
642 @param single_row_selection : only one line can select
643 @param row_description : row description text
644 @param font : row description font
645 @param size :row description size
646 @param min_section_size : default vertical size
647 @param row_count : number of rows to set
648 @param auto_size : do auto size of horizontal entries
649 """
650 if single_row_selection is not None:
651 if single_row_selection:
652 table.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection) # only one line can select
653 else:
654 table.setSelectionMode(QAbstractItemView.SelectionMode.NoSelection) # no table selection possible
655 if clear_selection:
656 table.clearSelection() # clear selected table entry to delete single items
657 if row_description is not None:
658 table.setColumnCount(len(row_description))
659 for i, value in enumerate(row_description):
660 item = QTableWidgetItem()
661 table.setHorizontalHeaderItem(i, item)
662 horizontal_header_item = table.horizontalHeaderItem(i)
663 if horizontal_header_item is not None:
664 horizontal_header_item.setText(value)
665 if font is not None:
666 horizontal_header_item.setFont(font)
667 if size is not None:
668 x, y, width, height = size
669 table.setGeometry(QRect(x, y, width, height))
670 if min_section_size is not None:
671 # first call setMinimumSectionSize to set actual correct size
672 vertical_header = table.verticalHeader()
673 if vertical_header is not None:
674 vertical_header.setMinimumSectionSize(min_section_size) # minimum vertical size
675 vertical_header.setDefaultSectionSize(min_section_size) # default vertical size
676 if row_count is not None:
677 table.setRowCount(row_count)
678 if auto_size:
679 # Update font before auto width
680 if font is not None:
681 for row in range(table.rowCount()): # set font size of table entries
682 for col in range(table.columnCount()):
683 table_item = table.item(row, col)
684 if table_item is not None:
685 table_item.setFont(font)
686 table.resizeColumnsToContents() # auto column width
687 header = table.horizontalHeader()
688 if header is not None:
689 header.setSectionResizeMode(1, QHeaderView.ResizeMode.Stretch) # fill middle row
690 vertical_header = table.verticalHeader()
691 if vertical_header is not None:
692 vertical_header.setVisible(False)
693 table.scrollToBottom() # scroll to bottom to show deposit anyway
694
695
696def insert_table_item(table: QTableWidget, i_entry_index: int, l_item_param: list[str],
697 font: Optional[QFont] = None, fg: Optional[str] = None, bg: Optional[str] = None) -> None:
698 """!
699 @brief Insert table item
700 @param table : insert item to this table
701 @param i_entry_index : table index of the new item
702 @param l_item_param : item parameter to insert to table
703 @param font : font of table item
704 @param fg : foreground color
705 @param bg : foreground color
706 """
707 for j, param in enumerate(l_item_param):
708 row_cnt = table.rowCount()
709 if row_cnt <= i_entry_index:
710 table.insertRow(i_entry_index)
711 item = QTableWidgetItem(param)
712 if fg is not None:
713 item.setForeground(QColor(fg))
714 if bg is not None:
715 item.setBackground(QColor(bg))
716 if j == 1:
717 item.setTextAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter)
718 else:
719 item.setTextAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
720 if font is not None:
721 item.setFont(font)
722 table.setItem(i_entry_index, j, item)
723
724
725def get_selected_table_row(table: QTableWidget) -> int | None:
726 """!
727 @brief Get selected table row
728 @param table : get selected row of this table
729 @return selected table row index
730 """
731 selected_items = table.selectedItems()
732 if selected_items:
733 selected_row = selected_items[0].row()
734 else:
735 selected_row = None
736 return selected_row
737
738
739def get_selected_table_column(table: QTableWidget) -> int | None:
740 """!
741 @brief Get selected table column
742 @param table : get selected column of this table
743 @return selected table column index
744 """
745 selected_items = table.selectedItems()
746 if selected_items:
747 selected_column = selected_items[0].column()
748 else:
749 selected_column = None
750 return selected_column
751
752
753
756
757def create_dialog(parent: "MainWindow | None", icon: Optional[str] = None, minmax: bool = False, frameless: bool = False) -> DIALOG:
758 """!
759 @brief Create dialog
760 @param parent : parent window controller
761 @param icon : table header to set
762 @param minmax : min and max window flag
763 @param frameless : no window flags and frameless
764 @return dialog
765 """
766 dialog = QDialog(parent)
767 dialog.setWindowFlag(Qt.WindowType.WindowContextHelpButtonHint, False)
768 dialog.setWindowFlag(Qt.WindowType.WindowMinMaxButtonsHint, minmax)
769 if frameless:
770 dialog.setWindowFlag(Qt.WindowType.FramelessWindowHint)
771 else:
772 if icon is not None:
773 dialog.setWindowIcon(QIcon(icon))
774 return dialog
775
776
777def config_tab(tab: QTextBrowser | None, tab_index: Optional[int] = None, text: Optional[str] = None,
778 main_tab: Optional[QTabWidget] = None, tab_name: Optional[str] = None) -> None:
779 """!
780 @brief Select Tab index
781 @param tab : tab to config
782 @param tab_index : tab index to set
783 @param text : text to set
784 @param main_tab : main tab
785 @param tab_name : tab name
786 """
787 if main_tab is not None:
788 if tab_index is not None:
789 main_tab.setCurrentIndex(tab_index)
790 if tab_name is not None:
791 main_tab.setTabText(tab_index, tab_name)
792 if text is not None:
793 if tab is not None:
794 html = markdown.markdown(text)
795 tab.setHtml(html)
796
797
798def open_message_box(parent: "MainWindow | None", title: str, text: str, btn_yes: Optional[str] = None, btn_no: Optional[str] = None,
799 btn_ok: Optional[str] = None, btn_close: Optional[str] = None, btn_cancel: Optional[str] = None, btn_special: Optional[str] = None,
800 check_box: Optional[str] = None, window_icon: Optional[str] = None, detailed_text: Optional[str] = None, execute: bool = True) -> tuple[bool, bool]:
801 """!
802 @brief Open message box
803 @param parent : parent window controller
804 @param title : box title
805 @param text : box text
806 @param btn_yes : button yes
807 @param btn_no : button no
808 @param btn_ok : button okay
809 @param btn_close : button close
810 @param btn_cancel : button cancel
811 @param btn_special : special button (user defined) name
812 @param check_box : name for check box
813 @param window_icon : box icon
814 @param detailed_text : detailed text
815 @param execute : execute message box
816 @return accept status of message box and check box status
817 """
818 if execute:
819 dialog = QMessageBox(parent)
820 dialog.setWindowTitle(title)
821 if window_icon is not None:
822 dialog.setWindowIcon(QIcon(window_icon))
823 dialog.setText(text)
824 if detailed_text:
825 dialog.setIcon(QMessageBox.Icon.Critical)
826 else:
827 dialog.setIcon(QMessageBox.Icon.Question if btn_cancel else QMessageBox.Icon.Information)
828 if btn_yes is not None:
829 dialog.addButton(QMessageBox.StandardButton.Yes)
830 if isinstance(btn_yes, str):
831 btn = dialog.button(QMessageBox.StandardButton.Yes)
832 if btn is not None:
833 btn.setText(btn_yes)
834 if btn_no is not None:
835 dialog.addButton(QMessageBox.StandardButton.No)
836 if isinstance(btn_no, str):
837 btn = dialog.button(QMessageBox.StandardButton.No)
838 if btn is not None:
839 btn.setText(btn_no)
840 if btn_ok is not None:
841 dialog.addButton(QMessageBox.StandardButton.Ok)
842 if isinstance(btn_ok, str):
843 btn = dialog.button(QMessageBox.StandardButton.Ok)
844 if btn is not None:
845 btn.setText(btn_ok)
846 if btn_close is not None:
847 dialog.addButton(QMessageBox.StandardButton.Close)
848 if isinstance(btn_close, str):
849 btn = dialog.button(QMessageBox.StandardButton.Close)
850 if btn is not None:
851 btn.setText(btn_close)
852 if btn_cancel is not None:
853 dialog.addButton(QMessageBox.StandardButton.Cancel)
854 if isinstance(btn_cancel, str):
855 btn = dialog.button(QMessageBox.StandardButton.Cancel)
856 if btn is not None:
857 btn.setText(btn_cancel)
858 if btn_special is not None:
859 if isinstance(btn_special, str):
860 dialog.addButton(btn_special, QMessageBox.ButtonRole.ResetRole)
861 if detailed_text is not None:
862 dialog.setDetailedText(detailed_text)
863 if check_box is not None:
864 box = QCheckBox(check_box)
865 dialog.setCheckBox(box)
866 else:
867 box = None
868 dialog.close()
869 choice = dialog.exec()
870 if box is not None:
871 is_checked = box.isChecked()
872 else:
873 is_checked = False
874 b_accept = choice not in [QMessageBox.StandardButton.No, QMessageBox.StandardButton.Close, QMessageBox.StandardButton.Cancel]
875 else:
876 b_accept = False
877 is_checked = False
878 return b_accept, is_checked
879
880
881def input_dialog(parent: "MainWindow | None", title: str, label: str, default_input: str = "", show_input: bool = True,
882 password_input: bool = False, icon: Optional[str] = None) -> tuple[str, bool]:
883 """!
884 @brief Open input dialog
885 @param parent : parent window controller
886 @param title : dialog title
887 @param label : dialog label
888 @param default_input : default input text
889 @param show_input : show input text status
890 @param password_input : show input text as password status
891 @param icon : dialog icon
892 @return input text
893 @todo Button Text an Sprachauswahl anpassen
894 """
895
896 if show_input:
897 if password_input:
898 echo = QLineEdit.EchoMode.Password
899 else:
900 echo = QLineEdit.EchoMode.Normal
901 else:
902 echo = QLineEdit.EchoMode.NoEcho
903 input_text, ok = QInputDialog.getText(parent, title, label, echo=echo, text=default_input)
904 return input_text, bool(ok)
905
906
907def open_directory(parent: "MainWindow", title: str, directory: str | None) -> str:
908 """!
909 @brief Open directory
910 @param parent : parent window controller
911 @param title : dialog title
912 @param directory : open file dialog in this directory
913 @return selected path
914 """
915 s_path = QFileDialog.getExistingDirectory(parent=parent,
916 caption=title,
917 directory=directory)
918 return s_path
919
920
921def open_file(parent: "MainWindow", title: str, directory: Optional[str] = None,
922 filetypes: Optional[tuple[str, str]] = None, multiple: bool = False) -> str | list[str]:
923 """!
924 @brief Open file
925 @param parent : parent window controller
926 @param title : dialog title
927 @param directory : open file dialog in this directory
928 @param filetypes : file types to select
929 @param multiple : status if multiple files can selected
930 @return selected file
931 """
932 file_dialog = QFileDialog.getOpenFileNames if multiple else QFileDialog.getOpenFileName
933 if filetypes is not None:
934 filter_name, filter_type = filetypes
935 type_filter = f"{filter_name} ({filter_type})"
936 else:
937 type_filter = None
938 s_file_name_path, _ = file_dialog(parent=parent, caption=title,
939 directory=directory,
940 filter=type_filter)
941 return s_file_name_path
942
943
944def save_file(parent: "MainWindow", title: str, directory: str, filetypes: tuple[str, str]) -> str:
945 """!
946 @brief Save file
947 @param parent : parent window controller
948 @param title : dialog title
949 @param directory : open file dialog in this directory
950 @param filetypes : file type to save
951 @return path to save file
952 """
953 filter_name, filter_type = filetypes
954 s_file_name_path, _ = QFileDialog.getSaveFileName(parent=parent, caption=title,
955 directory=directory,
956 filter=f"{filter_name} ({filter_type})")
957 return s_file_name_path
958
959
960
963
964def create_sound(sound_path: str) -> pygame.mixer.Sound:
965 """!
966 @brief Create sound
967 @param sound_path : path to sound file
968 @return sound object
969 """
970 # TODO use QSoundEffect is bug solved
971 pygame.mixer.init() # only initialized by first call
972 sound = pygame.mixer.Sound(sound_path)
973 return sound
974
975
976
979
980def copy_to_clipboard(text: str) -> None:
981 """!
982 @brief Copy text to clipboard
983 @param text : text to copy
984 """
985 cb = QApplication.clipboard()
986 if cb is not None:
987 cb.clear()
988 cb.setText(text)
989
990
991
994
995def create_timer(parent: QWidget, callback: Any = None) -> QTimer:
996 """!
997 @brief Create timer
998 @param parent : parent window
999 @param callback : timeout callback function
1000 @return timer
1001 """
1002
1003 timer = QTimer(parent)
1004 timer.setSingleShot(True)
1005 if callback is not None:
1006 timer.timeout.connect(callback)
1007 return timer
1008
1009
1010
1013
1014def config_icon(widget: QLabel, icon: Optional[str] = None, icon_size: Optional[tuple[int, int]] = None) -> None:
1015 """!
1016 @brief Configure icon
1017 @param widget : set icon of this widget
1018 @param icon : icon to set
1019 @param icon_size : icon size
1020 """
1021 if icon is not None:
1022 widget.setPixmap(QPixmap(icon))
1023
1024
1025def get_stylesheet(widget: Any) -> str:
1026 """!
1027 @brief Create Stylesheet
1028 @param widget : get style of this widget
1029 @return style
1030 """
1031 style: str = widget.styleSheet()
1032 return style
1033
1034
1035def create_font(font_style: Any, font_size: int) -> QFont:
1036 """!
1037 @brief Create font
1038 @param font_style : font style
1039 @param font_size : font size
1040 @return font
1041 """
1042 font = QFont(font_style, font_size)
1043 return font
str get_text(QTextBrowser label)
Configure text.
None connect_signal(SIGNAL_BOUND signal, Any function)
Connect signal.
None config_table(QTableWidget table, bool clear_selection=False, Optional[bool] single_row_selection=None, Optional[list[str]] row_description=None, Optional[QFont] font=None, Optional[tuple[int, int, int, int]] size=None, Optional[int] min_section_size=None, Optional[int] row_count=None, bool auto_size=False)
Table ##.
None config_label(QLabel label, Optional[str] text=None, Optional[str] fg=None, Optional[str] bg=None, Optional[tuple[int, int, int, int]] size=None, Optional[QFont] font=None, bool central=False, Optional[str] open_link=None, Optional[bool] show=None)
Label ##.
DIALOG create_dialog("MainWindow | None" parent, Optional[str] icon=None, bool minmax=False, bool frameless=False)
Dialogs ##.
str get_menu_text(QAction menu)
Get text from menu.
str save_file("MainWindow" parent, str title, str directory, tuple[str, str] filetypes)
Save file.
None connect_button(QPushButton btn, Any clicked_fnc=None, Any pressed_fnc=None, Any released_fnc=None, Any index="")
Button ##.
int|None get_selected_table_row(QTableWidget table)
Get selected table row.
None copy_to_clipboard(str text)
Clipboard ##.
None disconnect_signal(SIGNAL_BOUND signal)
Disconnect signal.
None insert_table_item(QTableWidget table, int i_entry_index, list[str] l_item_param, Optional[QFont] font=None, Optional[str] fg=None, Optional[str] bg=None)
Insert table item.
None connect_menu(QMenu|QAction menu, Any function, Any index="")
Connect menu.
None config_icon(QLabel widget, Optional[str] icon=None, Optional[tuple[int, int]] icon_size=None)
Other ##.
QTimer create_timer(QWidget parent, Any callback=None)
Timer ##.
BYTE_ARRAY get_window_geometry(WINDOW_TYPE window)
Get window geometry for safe.
str get_stylesheet(Any widget)
Create Stylesheet.
int|None get_selected_table_column(QTableWidget table)
Get selected table column.
tuple[int, int] get_window_position("MainWindow | QDialog" window)
Get window position.
None filter_menubar(QMenuBar menubar, WINDOW_TYPE gui)
Menu ##.
tuple[bool, bool] open_message_box("MainWindow | None" parent, str title, str text, Optional[str] btn_yes=None, Optional[str] btn_no=None, Optional[str] btn_ok=None, Optional[str] btn_close=None, Optional[str] btn_cancel=None, Optional[str] btn_special=None, Optional[str] check_box=None, Optional[str] window_icon=None, Optional[str] detailed_text=None, bool execute=True)
Open message box.
pygame.mixer.Sound create_sound(str sound_path)
Sound ##.
None config_tab(QTextBrowser|None tab, Optional[int] tab_index=None, Optional[str] text=None, Optional[QTabWidget] main_tab=None, Optional[str] tab_name=None)
Select Tab index.
bool check_app_already_open(QSharedMemory shared_memory)
Application ##.
str|list[str] open_file("MainWindow" parent, str title, Optional[str] directory=None, Optional[tuple[str, str]] filetypes=None, bool multiple=False)
Open file.
None config_window("DIALOG | MainWindow" window, Optional[str] title=None, bool frameless=False, Optional[str] icon=None, Optional[bool] fullscreen=None, Optional[int] min_width=None, Optional[int] min_height=None, Optional[QByteArray] geometry=None, Optional[QByteArray] state=None, bool fix_size=False, Optional[tuple[int, int]] resize=None, Optional[tuple[int, int]] move=None, Optional[str] style=None, Any resize_callback=None, Optional[bool] show=None, Optional[bool] thread=False)
Window ##.
str open_directory("MainWindow" parent, str title, str|None directory)
Open directory.
tuple[str, bool] input_dialog("MainWindow | None" parent, str title, str label, str default_input="", bool show_input=True, bool password_input=False, Optional[str] icon=None)
Open input dialog.
tuple[QActionGroup, bool] group_available_menu("MainWindow" parent, list[QAction] l_actions, Any actual_value, list[Any] l_match_values, QAction none_action)
Set action group.
QActionGroup group_menu("MainWindow" parent, list[QAction] l_actions, Any actual_value, list[Any] l_match_values)
Set action group.
None close_app("DIALOG | MainWindow" window)
Close application.
None config_menu(QMenu|QAction menu, Optional[bool] enable=None, Optional[bool] show=None, Optional[str] text=None, Optional[bool] checked=None, Optional[str] icon=None)
Configure menu.
bool get_fullscreen_status(WINDOW_TYPE window)
Get fullscreen status.
None config_app(APPLICATION app, Optional[str] icon=None, Optional[bool] process_events=False)
Configure Application.
None run_app("APPLICATION | DIALOG | MainWindow" window, Optional[APPLICATION|DIALOG] app, bool close_event=False)
Run application.
str get_style(bool dark_mode=False)
Get Style.
None config_btn(QPushButton btn, Optional[bool] enable=None, Optional[bool] show=None, Optional[str] text=None, Optional[str] fg=None, Optional[str] bg=None, Optional[str] style=None, Optional[str] icon=None, Optional[tuple[int, int, int, int]] size=None, Optional[QFont] font=None, Optional[int] icon_size=None)
Configure button.
None emit_signal(SIGNAL_BOUND signal)
Emit signal.
tuple[int, int] get_window_size("MainWindow | QDialog" window)
Get window size.
str get_btn_text(QPushButton btn)
Get button text.
None config_text(QTextBrowser label, Optional[str] text=None, Optional[str] fg=None, Optional[str] bg=None, Optional[tuple[int, int, int, int]] size=None, Optional[QFont] font=None)
Text ##.
BYTE_ARRAY get_window_state(WINDOW_TYPE window)
Get window state for safe.
QFont create_font(Any font_style, int font_size)
Create font.
None config_statusbar(QStatusBar statusbar, Optional[QLabel] lbl_left=None, Optional[QLabel] lbl_right=None, Optional[str] text=None, Optional[str] fg=None, Optional[str] bg=None)
Status bar ##.