feat(main): implement class QtScanSlicer
This commit is contained in:
parent
bf6f494642
commit
7be34dd161
1 changed files with 270 additions and 0 deletions
|
|
@ -173,3 +173,273 @@ def resolve_app_icon():
|
||||||
return candidate_icon
|
return candidate_icon
|
||||||
|
|
||||||
return QIcon()
|
return QIcon()
|
||||||
|
|
||||||
|
|
||||||
|
# QtScanSlicer: class definition for ScanSlicer behavior.
|
||||||
|
class QtScanSlicer(QMainWindow, ScanSlicerUiBuilderMixin, ScanSlicerControllerMixin):
|
||||||
|
CONTROL_PANEL_WIDTH = 370
|
||||||
|
STEPPER_WIDTH = 75
|
||||||
|
PANEL_CONTENT_MARGIN = 10
|
||||||
|
VERTICAL_SPACER_HEIGHT = 8
|
||||||
|
SECTION_TITLE_FONT_PX = 18
|
||||||
|
SECTION_TITLE_VPAD = 5
|
||||||
|
CHOICE_PARAM_OPTIONS = {
|
||||||
|
"detect_pipeline": [("Threshold", 0), ("Canny", 1)],
|
||||||
|
"bw_method": [("Simple", 0), ("Gauss", 1), ("Otsu", 2)],
|
||||||
|
"invert_mode": [("Auto", 0), ("Off", 1), ("On", 2)],
|
||||||
|
"morph_op": [("None", 0), ("Dilate", 1), ("Erode", 2), ("Open", 3), ("Close", 4)],
|
||||||
|
}
|
||||||
|
ADVANCED_PARAMS = {
|
||||||
|
"detect_pipeline",
|
||||||
|
"clahe_clip",
|
||||||
|
"gaussian",
|
||||||
|
"bw_adaptive_c",
|
||||||
|
"invert_mode",
|
||||||
|
"contour_approx_pct",
|
||||||
|
"bbox_max_size",
|
||||||
|
"aspect_ratio_min",
|
||||||
|
"aspect_ratio_max",
|
||||||
|
"border_ignore",
|
||||||
|
"iou_merge_thresh",
|
||||||
|
}
|
||||||
|
LOCK_ICON_DATA_URL = (
|
||||||
|
"data:image/svg+xml;base64,"
|
||||||
|
"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIg"
|
||||||
|
"dmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdp"
|
||||||
|
"ZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdW"
|
||||||
|
"NpZGUgbHVjaWRlLWxvY2staWNvbiBsdWNpZGUtbG9jayI+PHJlY3Qgd2lkdGg9IjE4IiBoZWlnaHQ9IjExIiB4"
|
||||||
|
"PSIzIiB5PSIxMSIgcng9IjIiIHJ5PSIyIi8+PHBhdGggZD0iTTcgMTFWN2E1IDUgMCAwIDEgMTAgMHY0Ii8+PC"
|
||||||
|
"9zdmc+"
|
||||||
|
)
|
||||||
|
SQUARIZE_ICON_DATA_URL = (
|
||||||
|
"data:image/svg+xml;base64,"
|
||||||
|
"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIg"
|
||||||
|
"dmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdp"
|
||||||
|
"ZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdW"
|
||||||
|
"NpZGUgbHVjaWRlLXNxdWFyZS1pY29uIGx1Y2lkZS1zcXVhcmUiPjxyZWN0IHdpZHRoPSIxOCIgaGVpZ2h0PSIx"
|
||||||
|
"OCIgeD0iMyIgeT0iMyIgcng9IjIiLz48L3N2Zz4="
|
||||||
|
)
|
||||||
|
ROTATE_ICON_DATA_URL = (
|
||||||
|
"data:image/svg+xml;base64,"
|
||||||
|
"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIg"
|
||||||
|
"dmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdp"
|
||||||
|
"ZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdW"
|
||||||
|
"NpZGUgbHVjaWRlLXJlZnJlc2gtY2N3LWRvdC1pY29uIGx1Y2lkZS1yZWZyZXNoLWNjdy1kb3QiPjxwYXRoIGQ9"
|
||||||
|
"Ik0yMSAxMmE5IDkgMCAwIDAtOS05IDkuNzUgOS43NSAwIDAgMC02Ljc0IDIuNzRMMyA4Ii8+PHBhdGggZD0i"
|
||||||
|
"TTMgM3Y1aDUiLz48cGF0aCBkPSJNMyAxMmE5IDkgMCAwIDAgOSA5IDkuNzUgOS43NSAwIDAgMCA2Ljc0LTIu"
|
||||||
|
"NzRMMjEgMTYiLz48cGF0aCBkPSJNMTYgMTZoNXY1Ii8+PGNpcmNsZSBjeD0iMTIiIGN5PSIxMiIgcj0iMSIv"
|
||||||
|
"Pjwvc3ZnPg=="
|
||||||
|
)
|
||||||
|
RESET_ROTATION_ICON_DATA_URL = (
|
||||||
|
"data:image/svg+xml;base64,"
|
||||||
|
"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIg"
|
||||||
|
"dmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdp"
|
||||||
|
"ZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdW"
|
||||||
|
"NpZGUgbHVjaWRlLXJvdGF0ZS1jdy1zcXVhcmUtaWNvbiBsdWNpZGUtcm90YXRlLWN3LXNxdWFyZSI+PHBhdGgg"
|
||||||
|
"ZD0iTTEyIDVINmEyIDIgMCAwIDAtMiAydjMiLz48cGF0aCBkPSJtOSA4IDMtMy0zLTMiLz48cGF0aCBkPSJNNC"
|
||||||
|
"AxNHY0YTIgMiAwIDAgMCAyIDJoMTJhMiAyIDAgMCAwIDItMlY3YTIgMiAwIDAgMC0yLTJoLTIiLz48L3N2Zz4="
|
||||||
|
)
|
||||||
|
REMOVE_ICON_DATA_URL = (
|
||||||
|
"data:image/svg+xml;base64,"
|
||||||
|
"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIg"
|
||||||
|
"dmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdp"
|
||||||
|
"ZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdW"
|
||||||
|
"NpZGUgbHVjaWRlLXNxdWFyZS14LWljb24gbHVjaWRlLXNxdWFyZS14Ij48cmVjdCB3aWR0aD0iMTgiIGhlaWdo"
|
||||||
|
"dD0iMTgiIHg9IjMiIHk9IjMiIHJ4PSIyIiByeT0iMiIvPjxwYXRoIGQ9Im0xNSA5LTYgNiIvPjxwYXRoIGQ9"
|
||||||
|
"Im05IDkgNiA2Ii8+PC9zdmc+"
|
||||||
|
)
|
||||||
|
LOCK_ALL_ICON_DATA_URL = (
|
||||||
|
"data:image/svg+xml;base64,"
|
||||||
|
"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIg"
|
||||||
|
"dmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdp"
|
||||||
|
"ZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdW"
|
||||||
|
"NpZGUgbHVjaWRlLWxvY2sta2V5aG9sZS1pY29uIGx1Y2lkZS1sb2NrLWtleWhvbGUiPjxjaXJjbGUgY3g9IjEy"
|
||||||
|
"IiBjeT0iMTYiIHI9IjEiLz48cmVjdCB4PSIzIiB5PSIxMCIgd2lkdGg9IjE4IiBoZWlnaHQ9IjEyIiByeD0i"
|
||||||
|
"MiIvPjxwYXRoIGQ9Ik03IDEwVjdhNSA1IDAgMCAxIDEwIDB2MyIvPjwvc3ZnPg=="
|
||||||
|
)
|
||||||
|
DETECT_ICON_DATA_URL = (
|
||||||
|
"data:image/svg+xml;base64,"
|
||||||
|
"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIg"
|
||||||
|
"dmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdp"
|
||||||
|
"ZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdW"
|
||||||
|
"NpZGUgbHVjaWRlLWV5ZS1pY29uIGx1Y2lkZS1leWUiPjxwYXRoIGQ9Ik0yLjA2MiAxMi4zNDhhMSAxIDAgMCAx"
|
||||||
|
"IDAtLjY5NiAxMC43NSAxMC43NSAwIDAgMSAxOS44NzYgMCAxIDEgMCAwIDEgMCAuNjk2IDEwLjc1IDEwLjc1ID"
|
||||||
|
"AgMCAxLTE5Ljg3NiAwIi8+PGNpcmNsZSBjeD0iMTIiIGN5PSIxMiIgcj0iMyIvPjwvc3ZnPg=="
|
||||||
|
)
|
||||||
|
PREVIEW_FILTER_ICON_DATA_URL = (
|
||||||
|
"data:image/svg+xml;base64,"
|
||||||
|
"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIg"
|
||||||
|
"dmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdp"
|
||||||
|
"ZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdW"
|
||||||
|
"NpZGUgbHVjaWRlLWV5ZS1vZmYtaWNvbiBsdWNpZGUtZXllLW9mZiI+PHBhdGggZD0iTTEwLjczMyA1LjA3NmEx"
|
||||||
|
"MC43NDQgMTAuNzQ0IDAgMCAxIDExLjIwNSA2LjU3NSAxIDEgMCAwIDEgMCAuNjk2IDEwLjc0NyAxMC43NDcgMC"
|
||||||
|
"AwIDEtMS40NDQgMi40OSIvPjxwYXRoIGQ9Ik0xNC4wODQgMTQuMTU4YTMgMyAwIDAgMS00LjI0Mi00LjI0MiIv"
|
||||||
|
"PjxwYXRoIGQ9Ik0xNy40NzkgMTcuNDk5YTEwLjc1IDEwLjc1IDAgMCAxLTE1LjQxNy01LjE1MSAxIDEgMCAwID"
|
||||||
|
"EgMC0uNjk2IDEwLjc1IDEwLjc1IDAgMCAxIDQuNDQ2LTUuMTQzIi8+PHBhdGggZD0ibTIgMiAyMCAyMCIvPjwv"
|
||||||
|
"c3ZnPg=="
|
||||||
|
)
|
||||||
|
ADD_BOX_ICON_DATA_URL = (
|
||||||
|
"data:image/svg+xml;base64,"
|
||||||
|
"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIg"
|
||||||
|
"dmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdp"
|
||||||
|
"ZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdW"
|
||||||
|
"NpZGUgbHVjaWRlLXNxdWFyZS1wbHVzLWljb24gbHVjaWRlLXNxdWFyZS1wbHVzIj48cmVjdCB3aWR0aD0iMTgi"
|
||||||
|
"IGhlaWdodD0iMTgiIHg9IjMiIHk9IjMiIHJ4PSIyIi8+PHBhdGggZD0iTTggMTJoOCIvPjxwYXRoIGQ9Ik0x"
|
||||||
|
"MiA4djgiLz48L3N2Zz4="
|
||||||
|
)
|
||||||
|
RESET_VIEW_ICON_DATA_URL = (
|
||||||
|
"data:image/svg+xml;base64,"
|
||||||
|
"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIg"
|
||||||
|
"dmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdp"
|
||||||
|
"ZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdW"
|
||||||
|
"NpZGUgbHVjaWRlLXZpZXctaWNvbiBsdWNpZGUtdmlldyI+PHBhdGggZD0iTTIxIDE3djJhMiAyIDAgMCAxLTIg"
|
||||||
|
"Mkg1YTIgMiAwIDAgMS0yLTJ2LTIiLz48cGF0aCBkPSJNMjEgN1Y1YTIgMiAwIDAgMC0yLTJINWEyIDIgMCAwID"
|
||||||
|
"AtMiAydjIiLz48Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIxIi8+PHBhdGggZD0iTTE4Ljk0NCAxMi4zM2Ex"
|
||||||
|
"IDEgMCAwIDAgMC0uNjYgNy41IDcuNSAwIDAgMC0xMy44ODggMCAxIDEgMCAwIDAgMCAuNjYgNy41IDcuNSAwID"
|
||||||
|
"AgMCAxMy44ODggMCIvPjwvc3ZnPg=="
|
||||||
|
)
|
||||||
|
PREV_IMAGE_ICON_DATA_URL = (
|
||||||
|
"data:image/svg+xml;base64,"
|
||||||
|
"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIg"
|
||||||
|
"dmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdp"
|
||||||
|
"ZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdW"
|
||||||
|
"NpZGUgbHVjaWRlLWNpcmNsZS1hcnJvdy1sZWZ0LWljb24gbHVjaWRlLWNpcmNsZS1hcnJvdy1sZWZ0Ij48Y2ly"
|
||||||
|
"Y2xlIGN4PSIxMiIgY3k9IjEyIiByPSIxMCIvPjxwYXRoIGQ9Im0xMiA4LTQgNCA0IDQiLz48cGF0aCBkPSJN"
|
||||||
|
"MTYgMTJIOCIvPjwvc3ZnPg=="
|
||||||
|
)
|
||||||
|
NEXT_IMAGE_ICON_DATA_URL = (
|
||||||
|
"data:image/svg+xml;base64,"
|
||||||
|
"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIg"
|
||||||
|
"dmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdp"
|
||||||
|
"ZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdW"
|
||||||
|
"NpZGUgbHVjaWRlLWNpcmNsZS1hcnJvdy1yaWdodC1pY29uIGx1Y2lkZS1jaXJjbGUtYXJyb3ctcmlnaHQiPjxj"
|
||||||
|
"aXJjbGUgY3g9IjEyIiBjeT0iMTIiIHI9IjEwIi8+PHBhdGggZD0ibTEyIDE2IDQtNC00LTQiLz48cGF0aCBk"
|
||||||
|
"PSJNOCAxMmg4Ii8+PC9zdmc+"
|
||||||
|
)
|
||||||
|
|
||||||
|
# __init__: function definition for ScanSlicer behavior.
|
||||||
|
def __init__(self, startup_dir=None):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
self.setWindowTitle("ScanSlicer")
|
||||||
|
app_icon = resolve_app_icon()
|
||||||
|
if not app_icon.isNull():
|
||||||
|
self.setWindowIcon(app_icon)
|
||||||
|
self.setStyleSheet(
|
||||||
|
"QPushButton { padding: 5px; }"
|
||||||
|
"QSpinBox { padding: 3px; }"
|
||||||
|
)
|
||||||
|
self.source_images = []
|
||||||
|
self.source_index = None
|
||||||
|
self.input_dir = None
|
||||||
|
self.output_dir = None
|
||||||
|
self.save_format = "png"
|
||||||
|
self.jpg_quality = 95
|
||||||
|
self.png_compression = 3
|
||||||
|
self.sort_mode = "name"
|
||||||
|
self.preview_filter_enabled = False
|
||||||
|
self.last_detected_boxes = None
|
||||||
|
self.last_preview_normal_image = None
|
||||||
|
self.last_preview_filter_image = None
|
||||||
|
|
||||||
|
self.params = AutoslicerParams()
|
||||||
|
self.autoslicer = Autoslicer(self.params)
|
||||||
|
self.autotune_profile = self.autoslicer.default_autotune_profile_name()
|
||||||
|
self.param_controls = {}
|
||||||
|
self.param_blocks = {}
|
||||||
|
self.show_advanced_params = False
|
||||||
|
self.updating_param_controls = False
|
||||||
|
self.processing_busy = False
|
||||||
|
self.controls_scroll = None
|
||||||
|
self.preview_toolbar = None
|
||||||
|
self.status_log_path = None
|
||||||
|
self.status_logging_enabled = True
|
||||||
|
self._status_last_event_pump_ts = 0.0
|
||||||
|
self._is_closing = False
|
||||||
|
self._pending_detection_new_image = False
|
||||||
|
self._worker_pool = None
|
||||||
|
self._detection_task = None
|
||||||
|
self._autotune_task = None
|
||||||
|
self._detection_running = False
|
||||||
|
self._autotune_running = False
|
||||||
|
self._detection_task_id = 0
|
||||||
|
self._autotune_task_id = 0
|
||||||
|
self._active_detection_task_id = None
|
||||||
|
self._active_autotune_task_id = None
|
||||||
|
|
||||||
|
root = QWidget(self)
|
||||||
|
self.setCentralWidget(root)
|
||||||
|
layout = QGridLayout(root)
|
||||||
|
|
||||||
|
header = self._build_header_controls(root)
|
||||||
|
layout.addWidget(header, 0, 0, 1, 2)
|
||||||
|
|
||||||
|
self.controls_scroll = self._build_controls_panel(root)
|
||||||
|
preview_panel = self._build_preview_panel(root)
|
||||||
|
|
||||||
|
layout.addWidget(self.controls_scroll, 1, 0)
|
||||||
|
layout.addWidget(preview_panel, 1, 1)
|
||||||
|
layout.setColumnStretch(1, 1)
|
||||||
|
layout.setRowStretch(1, 1)
|
||||||
|
|
||||||
|
self._build_status_bar()
|
||||||
|
|
||||||
|
self.initialize_status_log()
|
||||||
|
self.update_statusbar("Ready.")
|
||||||
|
self.update_quality_controls_state()
|
||||||
|
self.update_parameter_visibility()
|
||||||
|
self.update_output_dir_label()
|
||||||
|
self.refresh_active_box_toolbar()
|
||||||
|
|
||||||
|
if startup_dir:
|
||||||
|
self.open_directory(startup_dir)
|
||||||
|
|
||||||
|
# _build_header_controls: function definition for ScanSlicer behavior.
|
||||||
|
def _build_header_controls(self, parent):
|
||||||
|
header = QWidget(parent)
|
||||||
|
header_layout = QHBoxLayout(header)
|
||||||
|
header_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
header_layout.setSpacing(6)
|
||||||
|
|
||||||
|
title_label = QLabel("ScanSlicer")
|
||||||
|
title_font = QFont()
|
||||||
|
title_font.setPointSize(16)
|
||||||
|
title_font.setBold(True)
|
||||||
|
title_label.setFont(title_font)
|
||||||
|
title_label.setAlignment(Qt.AlignCenter)
|
||||||
|
|
||||||
|
header_layout.addStretch(1)
|
||||||
|
header_layout.addWidget(title_label)
|
||||||
|
header_layout.addStretch(1)
|
||||||
|
|
||||||
|
self.button_minimize = QPushButton("−", header)
|
||||||
|
self.button_minimize.setToolTip("Minimize")
|
||||||
|
self.button_minimize.clicked.connect(self.showMinimized)
|
||||||
|
header_layout.addWidget(self.button_minimize)
|
||||||
|
|
||||||
|
self.button_maximize = QPushButton("□", header)
|
||||||
|
self.button_maximize.setToolTip("Maximize/Restore")
|
||||||
|
self.button_maximize.clicked.connect(self.toggle_maximize_restore)
|
||||||
|
header_layout.addWidget(self.button_maximize)
|
||||||
|
|
||||||
|
self.button_quit = QPushButton("✕", header)
|
||||||
|
self.button_quit.setToolTip("Quit")
|
||||||
|
self.button_quit.clicked.connect(self.close)
|
||||||
|
header_layout.addWidget(self.button_quit)
|
||||||
|
return header
|
||||||
|
|
||||||
|
# toggle_maximize_restore: function definition for ScanSlicer behavior.
|
||||||
|
def toggle_maximize_restore(self):
|
||||||
|
if self.isMaximized():
|
||||||
|
self.showNormal()
|
||||||
|
return
|
||||||
|
self.showMaximized()
|
||||||
|
|
||||||
|
# closeEvent: function definition for ScanSlicer behavior.
|
||||||
|
def closeEvent(self, event):
|
||||||
|
self._is_closing = True
|
||||||
|
if hasattr(self, "autoslicer"):
|
||||||
|
self.autoslicer.abort_operation()
|
||||||
|
if hasattr(self, "_close_status_log"):
|
||||||
|
self._close_status_log()
|
||||||
|
super().closeEvent(event)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue