def __init__(self, parent, idx): super(PresetWizardPage, self).__init__(parent) self.parent, self.app, self.ui = parent, parent.app, parent.ui self.idx, self.id = idx, None self.__used_pr_family = set() self.clean_up_on_start, self.display_clean_up_msg = True, False self.pkg_count, self.pr_count = 0, 0 self.preset_name = dict(base_name='', options='', user_text='') self.load_ui() self.iterate_children = iterate_item_childs(self.treeWidget_Pkg) self.load_xml_content = None for widget in [self.treeWidget_Preset, self.treeWidget_Opt, self.treeWidget_Pkg]: # Info Overlay widget.info_overlay = InfoOverlay(widget) # Add filter txt widgets as attribute widget.filter_txt_widget = self.lineEditPreset # Connect text filter widget.preset_txt_filter = self.parent.TxtFiltering(self.parent.tree_filter_thread, widget, column=[0]) self.lineEditPreset.textChanged.connect(widget.preset_txt_filter.filter_txt) # Add tree Key events widget.tree_keys = TreeKeyEvents(widget, self.ui, False, no_edit=True) widget.tree_keys.add_event_filter() # Tree events self.treeWidget_Preset.itemSelectionChanged.connect(self.preset_tree_selection_timer) self.treeWidget_Opt.itemSelectionChanged.connect(self.opt_tree_selection_changed) self.tree_drag_drop_events = PresetTreeEvents(self, self.treeWidget_Preset) # Button events self.hideBtn.toggled.connect(self.toggle_hide_or_lock_btn) self.lockBtn.toggled.connect(self.toggle_hide_or_lock_btn) self.hideColBtn.toggled.connect(self.show_columns) self.fillPresetBtn.pressed.connect(self.auto_fill_preset) # Events self.lineEditPresetTitle.textEdited.connect(self.update_preset_name_user_text) # Wizard events self.parent.currentIdChanged.connect(self.page_changed) # Setup timers self.ready_timer = QtCore.QTimer() self.ready_timer.setSingleShot(True) self.ready_timer.setInterval(self.complete_delay) self.ready_timer.timeout.connect(self.delay_completed) self.selection_timer = QtCore.QTimer() self.selection_timer.setSingleShot(True) self.selection_timer.setInterval(self.selection_delay) self.selection_timer.timeout.connect(self.preset_tree_selection_changed) self.fill_btn_timer = QtCore.QTimer() self.fill_btn_timer.setSingleShot(True) self.fill_btn_timer.setInterval(self.fill_btn_delay) self.fill_btn_timer.timeout.connect(self.fill_btn_delay_completed)
def load_ui(self): # Load page template load_ui_file(self, WIZARD_PAGE_SOURCE) # Setup tree widget overlay self.treeWidget_Src.info_overlay = InfoOverlay(self.treeWidget_Src) self.treeWidget_Src.overlay = Overlay(self.treeWidget_Src) self.treeWidget_Src.missing_ids = set() # Dummy Attribute self.open_file_dialog = OpenPresetFile(self.app, None, self.ui, self.treeWidget_Src, self.openBtn) self.openBtn.pressed.connect(self.load_session_file) self.saveBtn.pressed.connect(self.save_session_user) self.reloadBtn.pressed.connect(self.load_session) self.parent.save_empty.connect(self.save_empty) self.parent.save_error.connect(self.save_error) # Setup filter text edit widget self.plainTextEditFilter.hide() # Show package filter as ; seperated string __filter_string = self.load_pkg_filter_string() self.plainTextEditFilter.setPlainText(__filter_string)
def load_ui(self): load_ui_file(self, WIZARD_PAGE_RESULT) # Set logo pixmap logo = QPixmap(Itemstyle.ICON_PATH['qob_icon_sw']) logo = logo.scaled(96, 96, QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation) self.setPixmap(QtWidgets.QWizard.LogoPixmap, logo) self.setTitle(QobMsg.result_title) self.setSubTitle(QobMsg.result_sub) self.treeWidget_Result.info_overlay = InfoOverlay( self.treeWidget_Result) self.saveBtn.pressed.connect(self.save_session_user) self.parent.save_empty.connect(self.save_empty) self.parent.save_error.connect(self.save_error)
def __init__(self, app, ui): super(KnechtImageViewer, self).__init__( flags=Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint | Qt.CustomizeWindowHint ) global LOGGER LOGGER = init_logging(__name__) self.app, self.ui = app, ui self.setWindowIcon(QIcon(QPixmap(self.ICON))) self.setAutoFillBackground(True) self.setAttribute(Qt.WA_TranslucentBackground) self.setAttribute(Qt.WA_AcceptDrops, True) self.setWindowTitle('Image Viewer') self.setStyleSheet("QWidget{background-color: darkgray;}") self.setFocusPolicy(Qt.StrongFocus) self.animation = AnimateWindowOpacity(self, 200) self.img_dir = Path('.') self.current_img = None self.img_list = list() self.img_index = 0 self.img_size_factor = 1.0 self.img_size = QSize(*self.DEFAULT_SIZE) self.img_loader = None # will be the loader thread # Save window position for drag self.oldPos = self.pos() self.current_opacity = 1.0 self.setWindowOpacity(1.0) self.control = ControllerWidget(self) # DG Send thread controller self.dg_thread = KnechtImageViewerSendController(self) # Image canvas self.setLayout(QtWidgets.QHBoxLayout()) self.layout().setContentsMargins(0, 0, 0, 0) self.layout().setSpacing(0) self.img_canvas = QtWidgets.QLabel(self) self.layout().addWidget(self.img_canvas) self.img_canvas.setSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Ignored) self.img_canvas.setScaledContents(True) self.img_canvas.setObjectName('img_canvas') self.set_default_image() # Overlay self.overlay = InfoOverlay(self.img_canvas) # App logic self.path_dlg = SetDirectoryPath(app, ui, mode='file', line_edit=self.control.line_edit, tool_button=self.control.path_btn, parent=self) self.path_dlg.path_changed.connect(self.set_img_path) self.slider_timeout.timeout.connect(self.set_opacity_from_slider) self.control.slider.sliderReleased.connect(self.slider_timeout.start) self.control.slider.valueChanged.connect(self.slider_timeout.start) self.control.size_box.currentIndexChanged.connect(self.combo_box_size) self.control.bck_btn.pressed.connect(self.iterate_bck) self.control.fwd_btn.pressed.connect(self.iterate_fwd) self.control.min_btn.released.connect(self.minimize) self.control.toggle_btn.pressed.connect(self.toggle_img_canvas) self.control.toggle_dg_btn.pressed.connect(self.dg_toggle_sync) self.control.toggle_pull_btn.pressed.connect(self.dg_toggle_pull) self.control.help_btn.pressed.connect(self.display_shortcut_overlay) self.shortcuts = ViewerShortcuts(self, self.control) self.shortcuts.set_shortcuts(self) self.shortcuts.set_shortcuts(self.control) self.file_dropped.connect(self.path_dropped) self.control.file_dropped.connect(self.path_dropped) self.load_timeout.timeout.connect(self.kill_load_thread) self.place_in_screen_center()
class KnechtImageViewer(FileDropWidget): button_timeout = QTimer() button_timeout.setInterval(100) button_timeout.setSingleShot(True) shortcut_timeout = QTimer() shortcut_timeout.setInterval(50) shortcut_timeout.setSingleShot(True) slider_timeout = QTimer() slider_timeout.setInterval(20) slider_timeout.setSingleShot(True) load_timeout = QTimer() load_timeout.setInterval(5000) load_timeout.setSingleShot(True) DEFAULT_SIZE = (800, 450) MARGIN = 400 MAX_SIZE = QSize(4096, 4096) MAX_SIZE_FACTOR = 2.5 MIN_SIZE_FACTOR = 0.25 SIZE_INCREMENT = 0.25 EXTRA_SIZE_FACTORS = [0.6666666, 1.3333333] ICON = Itemstyle.ICON_PATH['img'] FILE_TYPES = ['.png', '.jpg', '.jpeg', '.tif', '.tga', '.hdr', '.exr'] def __init__(self, app, ui): super(KnechtImageViewer, self).__init__( flags=Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint | Qt.CustomizeWindowHint ) global LOGGER LOGGER = init_logging(__name__) self.app, self.ui = app, ui self.setWindowIcon(QIcon(QPixmap(self.ICON))) self.setAutoFillBackground(True) self.setAttribute(Qt.WA_TranslucentBackground) self.setAttribute(Qt.WA_AcceptDrops, True) self.setWindowTitle('Image Viewer') self.setStyleSheet("QWidget{background-color: darkgray;}") self.setFocusPolicy(Qt.StrongFocus) self.animation = AnimateWindowOpacity(self, 200) self.img_dir = Path('.') self.current_img = None self.img_list = list() self.img_index = 0 self.img_size_factor = 1.0 self.img_size = QSize(*self.DEFAULT_SIZE) self.img_loader = None # will be the loader thread # Save window position for drag self.oldPos = self.pos() self.current_opacity = 1.0 self.setWindowOpacity(1.0) self.control = ControllerWidget(self) # DG Send thread controller self.dg_thread = KnechtImageViewerSendController(self) # Image canvas self.setLayout(QtWidgets.QHBoxLayout()) self.layout().setContentsMargins(0, 0, 0, 0) self.layout().setSpacing(0) self.img_canvas = QtWidgets.QLabel(self) self.layout().addWidget(self.img_canvas) self.img_canvas.setSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Ignored) self.img_canvas.setScaledContents(True) self.img_canvas.setObjectName('img_canvas') self.set_default_image() # Overlay self.overlay = InfoOverlay(self.img_canvas) # App logic self.path_dlg = SetDirectoryPath(app, ui, mode='file', line_edit=self.control.line_edit, tool_button=self.control.path_btn, parent=self) self.path_dlg.path_changed.connect(self.set_img_path) self.slider_timeout.timeout.connect(self.set_opacity_from_slider) self.control.slider.sliderReleased.connect(self.slider_timeout.start) self.control.slider.valueChanged.connect(self.slider_timeout.start) self.control.size_box.currentIndexChanged.connect(self.combo_box_size) self.control.bck_btn.pressed.connect(self.iterate_bck) self.control.fwd_btn.pressed.connect(self.iterate_fwd) self.control.min_btn.released.connect(self.minimize) self.control.toggle_btn.pressed.connect(self.toggle_img_canvas) self.control.toggle_dg_btn.pressed.connect(self.dg_toggle_sync) self.control.toggle_pull_btn.pressed.connect(self.dg_toggle_pull) self.control.help_btn.pressed.connect(self.display_shortcut_overlay) self.shortcuts = ViewerShortcuts(self, self.control) self.shortcuts.set_shortcuts(self) self.shortcuts.set_shortcuts(self.control) self.file_dropped.connect(self.path_dropped) self.control.file_dropped.connect(self.path_dropped) self.load_timeout.timeout.connect(self.kill_load_thread) self.place_in_screen_center() def changeEvent(self, event): if event.type() == QEvent.WindowStateChange: if event.oldState() and Qt.WindowMinimized: self.restore() elif event.oldState() == Qt.WindowNoState: LOGGER.debug('Image Viewer minimized.') def restore(self): self.showNormal() self.control.showNormal() self.activateWindow() # Gain window focus def minimize(self): self.showMinimized() self.control.showMinimized() def display_shortcut_overlay(self): self.overlay.display_exit() self.overlay.display( 'Shortcuts<br>' '+/- oder Q/E - Bildanzeige vergößern/verkleinern<br>' '</> oder A/D - Nächste/Vorherige Bilddatei im Ordner<br>' 'STRG+/STRG- oder W/S - Transparenz erhöhen/verringern<br><br>' 'Leertaste oder X - Bildanzeige ein-/ausschalten<br>' 'F - DeltaGen Viewer Sync ein-/ausschalten<br>' '<img src=":/type/img_free.png" width="24" height="24" style="float: left;' 'vertical-align: middle;" />' '- DeltaGen Viewer Fenster periodisch fokussieren. Experimentell!<br><br>' 'Pfad auswählen oder Dateien in das Fenster ziehen.', duration=6000, immediate=True) def set_default_image(self): self.current_img = QPixmap(Itemstyle.ICON_PATH['img_viewer']) self.img_canvas.setStyleSheet('background: rgba(0, 0, 0, 0);') self.img_canvas.setPixmap(self.current_img) self.img_size = self.current_img.size() self.img_size_factor = 1.0 idx = self.control.size_box.findData(1.0) self.control.size_box.setCurrentIndex(idx) self.control.line_edit.setText('') self.control.grabber_top.setText(self.windowTitle()) self.change_viewer_size() # ------ DeltaGen Sync ------- def dg_toggle_btn(self, enabled: bool): """ Called by thread signal """ self.control.toggle_dg_btn.setEnabled(enabled) def dg_check_btn(self, checked: bool): """ Called by thread signal """ self.control.toggle_dg_btn.setChecked(checked) def dg_toggle_pull(self): """ Toggles pulling of the viewer window in front on/off """ self.dg_thread.toggle_pull() def dg_toggle_sync(self): if not self.control.toggle_dg_btn.isEnabled(): return self.dg_thread.start() self.dg_thread.toggle_sync() # ------ IMAGES ------- def path_dropped(self, file_url): self.path_dlg.set_path(Path(file_url)) self.restore() # Gain window focus on file drop def set_img_path(self, file_path: Path): if file_path.is_file(): self.img_dir = file_path.parent else: self.img_dir = file_path self.path_dlg.set_path_text(self.img_dir) self.list_img_files(file_path) self.iterate_images() def list_img_files(self, current_file: Path): self.img_index = 0 self.img_list = list() for img_file in self.img_dir.glob('*.*'): if f'{img_file.suffix}'.casefold() in self.FILE_TYPES: self.img_list.append(img_file) if current_file in self.img_list: current_idx = self.img_list.index(current_file) self.img_index = current_idx LOGGER.debug('Current file set to: %s', current_idx) def iterate_fwd(self): if not self.check_image_loader(): return self.img_index += 1 self.iterate_images() def iterate_bck(self): if not self.check_image_loader(): return self.img_index -= 1 self.iterate_images() def iterate_images(self): if not self.img_list or self.button_timeout.isActive(): if not self.img_list: self.set_default_image() self.overlay.display_exit() self.overlay.display('Kein unterstützen Bilddaten im Ordner gefunden oder ' 'kein Bildordner gewählt.', 3000) return if self.img_index < 0: self.img_index = len(self.img_list) - 1 if self.img_index >= len(self.img_list): self.img_index = 0 img_path = self.img_list[self.img_index] self.create_image_load_thread(img_path) self.button_timeout.start() def check_image_loader(self): if self.img_loader is not None and self.img_loader.isRunning(): self.overlay.display_exit() self.overlay.display('Bildverarbeitung ist beschäftigt. Später erneut versuchen.', 5000, immediate=True) return False return True def create_image_load_thread(self, img_path): if not self.img_loader: self.img_loader = KnechtLoadImage(self, img_path) self.img_loader.start() self.load_timeout.start() def kill_load_thread(self): LOGGER.error('Image load timeout exceeded. Trying to kill load thread.') if self.img_loader is not None and self.img_loader.isRunning(): self.img_loader.exit() LOGGER.error('Waiting for Image loader to exit.') self.img_loader.wait(msecs=3000) if self.img_loader.isRunning(): LOGGER.error('Image loader exit took too long. Trying to terminate the QThread.') self.img_loader.terminate() img_path = self.img_list[self.img_index] # Thread terminated, application should be restarted self.close() self.ui.generic_error_msg(f'Das Laden der Datei <br>{img_path.as_posix()}<br>' f'ist fehlgeschlagen! Der Ladeprozess musste unsanft beendet werden.<br><br>' f'Um Speicherlecks und Fehler bei Zugriffsberechtigungen zu vermeiden<br>' f'sollte diese Anwendung möglichst bald neu gestartet werden.' ) if self.img_loader.isRunning(): LOGGER.error('Could not terminate Image loader QThread.') self.image_load_failed() self.img_loader = None def image_load_failed(self, error_msg=''): img_path = self.img_list[self.img_index] if not error_msg: error_msg = img_path.as_posix() LOGGER.error('Could not load image file:\n%s', error_msg) self.set_default_image() self.overlay.display_exit() self.overlay.display(f'<span style="font-size: 11pt;">' f'Datei <b>{img_path.name}</b> konnt nicht geladen werden!' f'</span>', 5000, immediate=True) self.img_loader = None self.load_timeout.stop() def image_loaded(self, image): if not image: self.image_load_failed() return self.current_img = image self.img_canvas.setPixmap(self.current_img) self.img_size = self.current_img.size() self.change_viewer_size() self.overlay.display_exit() img_path = self.img_list[self.img_index] self.overlay.display(f'<span style="font-size: 11pt;">' f'{self.img_index + 1:02d}/{len(self.img_list):02d} - ' f'<b>{img_path.name}</b> - ' f'{self.img_size.width()}x{self.img_size.height()}px' f'</span>', 1200, immediate=True) self.img_loader = None img_name = img_path.name if len(img_name) >= 85: img_name = f'{img_name[:65]}~{img_name[-20:]}' self.control.grabber_top.setText(f'{self.windowTitle()} - {img_name}') self.load_timeout.stop() # ------ RESIZE ------- def combo_box_size(self, idx): self.set_img_size_factor_from_combo_box() self.change_viewer_size() def set_img_size_factor_from_combo_box(self): data = self.control.size_box.currentData() if data: self.img_size_factor = data def set_size_box_index(self, add_idx: int=0): cb = self.control.size_box new_idx = min(cb.count() - 1, max(cb.currentIndex() + add_idx, 0)) cb.setCurrentIndex(new_idx) def increase_size(self): self.set_size_box_index(1) self.set_img_size_factor_from_combo_box() self.change_viewer_size() def decrease_size(self): self.set_size_box_index(-1) self.set_img_size_factor_from_combo_box() self.change_viewer_size() def change_viewer_size(self): self.img_size_factor = max(self.MIN_SIZE_FACTOR, min(self.img_size_factor, self.MAX_SIZE_FACTOR)) w = round(self.img_size.width() * self.img_size_factor) h = round(self.img_size.height() * self.img_size_factor) new_size = QSize(w, h) self.resize_image_viewer(new_size) def resize_image_viewer(self, new_size: QSize): width = max(50, min(new_size.width(), self.MAX_SIZE.width())) height = max(50, min(new_size.height(), self.MAX_SIZE.height())) new_size = QSize(width, height) self.dg_thread.request_sync() self.resize(new_size) # ------ OPACITY ------- def increase_window_opacity(self): opacity = self.windowOpacity() + 0.15 self.update_opacity_slider() self.set_window_opacity(opacity) def decrease_window_opacity(self): opacity = self.windowOpacity() - 0.15 self.update_opacity_slider() self.set_window_opacity(opacity) def update_opacity_slider(self): self.control.slider.setValue(round(self.windowOpacity() * self.control.slider.maximum())) def set_opacity_from_slider(self): opacity = self.control.slider.value() * 0.1 self.set_window_opacity(opacity) def set_window_opacity(self, opacity): if self.shortcut_timeout.isActive(): return opacity = max(0.05, min(1.0, opacity)) self.current_opacity = opacity self.setWindowOpacity(opacity) self.shortcut_timeout.start() # ------ VISIBILITY ------- def toggle_img_canvas(self): if self.shortcut_timeout.isActive(): return if self.control.toggle_btn.isChecked(): self.setWindowOpacity(0.0) else: self.setWindowOpacity(self.current_opacity) self.shortcut_timeout.start() def hide_all(self): self.control.hide() self.hide() def show_all(self): self.place_inside_screen() self.control.show() self.show() self.display_shortcut_overlay() self.control.opacity_animation.setup_animation(duration=800) self.control.opacity_animation.play() self.animation.setup_animation(duration=800) self.current_opacity = 1.0 self.control.slider.setValue(self.control.slider.maximum()) self.animation.play() # ------ OVERRIDES ------- def moveEvent(self, event): if self.moved_out_of_limit(): event.ignore() return event.accept() def resizeEvent(self, event): if self.moved_out_of_limit(): event.ignore() return event.accept() def moved_out_of_limit(self): limit = self.calculate_screen_limits() pos = self.geometry().topLeft() if not self.is_inside_limit(limit, pos): x = min(limit.width(), max(limit.x(), pos.x())) y = min(limit.height(), max(limit.y(), pos.y())) self.move(x, y) return True return False def place_inside_screen(self): limit = self.calculate_screen_limits() pos = self.geometry().topLeft() if not self.is_inside_limit(limit, pos): self.place_in_screen_center() def place_in_screen_center(self): screen = self.app.desktop().availableGeometry(self) center_x = screen.center().x() - self.geometry().width() / 2 center_y = screen.center().y() - self.geometry().height() / 2 self.move(center_x, center_y) def calculate_screen_limits(self): screen = QRect(self.app.desktop().x(), self.app.desktop().y(), self.app.desktop().width(), self.app.desktop().availableGeometry().height()) width_margin = self.geometry().width() / 2 height_margin = self.geometry().height() / 2 # Case where secondary screen has negative values desktop_width = screen.x() + screen.width() min_x = screen.x() - width_margin min_y = screen.y() - height_margin max_x = desktop_width - width_margin max_y = screen.height() - height_margin return QRect(min_x, min_y, max_x, max_y) def closeEvent(self, QCloseEvent): self.dg_thread.exit() self.control.close() QCloseEvent.accept() def mousePressEvent(self, event): self.oldPos = event.globalPos() def mouseMoveEvent(self, event): delta = QPoint(event.globalPos() - self.oldPos) self.move(self.x() + delta.x(), self.y() + delta.y()) self.oldPos = event.globalPos() self.dg_thread.request_sync() @staticmethod def is_inside_limit(limit: QRect, pos: QPoint): if pos.x() < limit.x() or pos.x() > limit.width(): return False elif pos.y() < limit.y() or pos.y() > limit.height(): return False return True
def __init__(self, app_class): super(MainWindow, self).__init__() # Avoid UIC Debug messages log_level = LOGGER.getEffectiveLevel() logging.root.setLevel(40) # Load Ui file loadUi(UI_FILE_PRESET_EDITOR, self) # Add LED Overlay to tabWidget # Spams the log with Debug messages, so initialize in this block self.led_ovr = LedCornerWidget(parent=self.tabWidget) logging.root.setLevel(log_level) # Windows taskbar progress indicator self.taskbar_btn = QWinTaskbarButton(self) self.progress = QWinTaskbarProgress() # Clipboard self.clipboard = [] self.clipboard_src = None # Undo Redo Menu self.actionUndo.setText('Rückgängig\tCtrl+Z') self.actionRedo.setText('Wiederherstellen\tCtrl+Y') self.actionUndo.setEnabled(False) self.actionRedo.setEnabled(False) # Add version to Window title self.ver = InfoMessage.ver self.title = self.windowTitle() self.set_window_title() self.load_settings() # Unsaved changes status self.unsaved_changes_present = False self.unsaved_changes_auto_save = True # App class so we can override the window exit method [x] with the exit method of the app class self.app_class = app_class self.tree_widget_list = [ self.treeWidget_SrcPreset, self.treeWidget_DestPreset, self.treeWidget_Variants, self.treeWidget_render ] # Set tree column width to content resize and sort ascending by order tree_setup_header_format(self.tree_widget_list) # Icons self.icon = dict() for icon_name, icon_path in Itemstyle.ICON_PATH.items(): self.icon[icon_name] = QIcon(icon_path) # Tree iterator instance self.iter_tree = iterate_item_childs(self.treeWidget_DestPreset) # Make reference modules instance available to the working classes self.find_reference_items = FindReferenceItems(self, self.iter_tree) self.add_selected_top_level_items = CopySelectedToDest(self) # Worker class instances self.sort_tree_widget = SortTree(self, self.treeWidget_SrcPreset) self.context_menus = [] self.widget_pairs = [ (self.treeWidget_SrcPreset, self.pushButton_Src_sort, self.lineEdit_Src_filter, [1, 2]), (self.treeWidget_DestPreset, self.pushButton_Dest_sort, self.lineEdit_Dest_filter, [1, 2]), (self.treeWidget_Variants, self.pushButton_Var_sort, self.lineEdit_Var_filter, 1), (self.treeWidget_render, self.pushButton_Ren_sort, self.lineEdit_Ren_filter, 1) ] # Init widget pairs for w_tuple in self.widget_pairs: tree_widget, sort_button, line_edit, filter_col = w_tuple # Sorting and reference highlight tree_widget.sortBtn = sort_button # Store Id's to missing items as strings # so we avoid to assign them to new items tree_widget.missing_ids = set() # Store topLevelItem names tree_widget.unique_names = set() # Default Filter column tree_widget.filter_column = filter_col # Store LineEdit text filter widget as tree attribute tree_widget.filter_txt_widget = line_edit # Init Filter tree_widget.filter = filter_on_timer(line_edit, tree_widget, filter_column=filter_col) line_edit.textChanged.connect(tree_widget.filter.start_timer) # Default preset visibility tree_widget.toggle_preset_vis = False # Info Overlay tree_widget.info_overlay = InfoOverlay(tree_widget) # Animated overlay tree_widget.overlay = Overlay(tree_widget) # Update overlay position on event tree_widget.overlayPos.connect(tree_widget.overlay.update_position) # Context menu tree_widget.context = TreeContextMenu(tree_widget, self) # Bind keys tree_widget.keys = TreeKeyEvents(tree_widget, self, self.app_class) tree_widget.keys.add_event_filter() # Report conflict shortcut tree_widget.report_conflict = self.report_conflict # Forbid editing in SrcWidget self.treeWidget_SrcPreset.keys.no_edit = True # Search Replace dialog self.search_replace = SearchReplace(self, [ self.treeWidget_SrcPreset, self.treeWidget_DestPreset, self.treeWidget_Variants ], current_tree=1) # Copy variants key events variant_keys_tree = CopyVariantsKeyEvents(self.treeWidget_Variants, self) variants_keys_txt = CopyVariantsKeyEvents( self.plainTextEdit_addVariant_Setname, self) variant_keys_add = CopyVariantsKeyEvents( self.plainTextEdit_addVariant_Variant, self) # Internal drag_drop worker self.treeWidget_DestPreset.internal_drag_drop.setup_ui(self) self.treeWidget_Variants.internal_drag_drop.setup_ui(self) self.treeWidget_render.internal_drag_drop.setup_ui(self, True) # hide variants type column self.treeWidget_Variants.header().hideSection(ItemColumn.TYPE) # Reset treeWidgets splitter to equal sizes self.presetTreeSplitter.setSizes([100, 100]) # Detect inactivity for automatic session save self.idle_timer.timeout.connect(self.set_inactive) self.__idle = False self.app_class.installEventFilter(self)
def __init__(self, app, ui): super(PathRenderService, self).__init__() self.app, self.ui = app, ui self.search_thread = GetPfadAeffchenService() self.search_thread.result.connect(self.search_service_result) # --------- Connect button --------- self.ui.pathConnectBtn.pressed.connect(self.switch_service_on_off) self.ui.pathConnectBtn.animation = AnimatedButton( self.ui.pathConnectBtn, 900) self.switch_btn_timer.timeout.connect(self.switch_button_timeout) # Highlight connect button on tab change/click self.ui.tabWidget.tabBarClicked.connect(self.tab_bar_clicked) # --------- Refresh button ------------ self.ui.pathRefreshBtn.pressed.connect(self.request_job_queue) self.refresh_btn_timer.timeout.connect(self.refresh_btn_timeout) # --------- Validate Job Name --------- self.ui.pathJobNameLineEdit.editingFinished.connect( self.validate_job_name) # --------- Job Options --------- self.ui.checkBoxCsbIgnoreHidden.toggled.connect( self.update_csb_import_option) self.ui.checkBoxMayaDeleteHidden.toggled.connect( self.update_maya_delete_hidden_option) self.ui.checkBoxUseSceneSettings.toggled.connect( self.update_use_scene_settings) self.csb_ignore_hidden = '1' self.maya_delete_hidden = '1' self.use_scene_settings = '0' # --------- Set scene file --------- self.scene_file = Path('.') args = ( 'Szenendatei *.csb oder *.mb auswählen', # title 'DeltaGen CSB, Maya binary (*.csb;*.mb)', # filter ) self.file_dialog = SetDirectoryPath( app, ui, mode='file', line_edit=self.ui.pathSceneLineEdit, tool_button=self.ui.pathSceneBtn, dialog_args=args, reject_invalid_path_edits=True) self.file_dialog.path_changed.connect(self.update_scene_file) self.file_dialog.invalid_path_entered.connect( self.invalid_scene_path_entered) # --------- Set output dir --------- self.output_dir = Path('.') args = ('Ausgabe Verzeichnis auswählen', ) self.dir_dialog = SetDirectoryPath( app, ui, line_edit=self.ui.pathOutputLineEdit, tool_button=self.ui.pathOutputBtn, dialog_args=args, ) self.dir_dialog.path_changed.connect(self.update_output_dir) # --------- Add job button --------- self.ui.pathJobSendBtn.pressed.connect(self.create_job) self.ui.pathJobSendBtn.setEnabled(False) # --------- Help button --------- self.ui.pathBtnHelp.pressed.connect(self.open_help) # --------- Job Manager Tree Widget ------------ self.ui.widgetJobManager.manager_open_item = self.manager_open_item self.ui.widgetJobManager.itemDoubleClicked.connect( self.manager_open_item) self.ui.widgetJobManager.manager_open_scene_btn = self.manager_open_scene_btn self.ui.widgetJobManager.manager_delete_render_file = self.manager_delete_render_file # --------- Job Manager Context Menu ------------ self.context_menu = JobManagerContextMenu(self.ui.widgetJobManager, self.ui) self.context_menu.move_job.connect(self.manager_move_job) self.context_menu.cancel_job.connect(self.manager_cancel_job) self.context_menu.force_psd.connect(self.manager_force_psd_creation) # Sort Job Manager columns self.ui.label_PfadAeffchen.mouseDoubleClickEvent = self.manager_sort_header # Update job Manager self.update_job_manager_timer.timeout.connect(self.request_job_queue) self.update_job_alive_timer.timeout.connect(self.alive_blink) self.ui.widgetJobManager.overlay = InfoOverlay( self.ui.widgetJobManager) self.first_update = True self.ovr = self.ui.widgetJobManager.overlay # --------- Status Browser ------------ self.text_browser = self.ui.renderServiceBrowser self.text_browser.ovr = Overlay(self.text_browser) # Set splitter size self.ui.jobStatusSplitter.setSizes([200, 100]) # Prepare message sending # Service address self.service_host = None self.send_thread = None self.msg_queue = Queue(maxsize=64) self.keep_alive_timer.timeout.connect(self.end_send_thread) self.job_queue = None self.app.aboutToQuit.connect(self.quit_app)
def __init__(self, parent, pr_fam_set, model_list, file, fakom_reader: bool = False, wizard: bool = False): super(VplusWindow, self).__init__() self.ui = parent.open_dialog.ui self.parent = parent self.fakom_reader, self.wizard = fakom_reader, wizard # Filename self.filename = os.path.basename(file) # List of lists of Models [Value, Name] self.model_list = model_list # List of lists of PR-Familys [Name, Description] self.pr_fam_set = pr_fam_set # Update with document PR-Familys [Name] self.doc_pr_fam_list = [] # Avoid UIC Debug messages log_level = LOGGER.getEffectiveLevel() logging.root.setLevel(20) loadUi(UI_FILE_EXCEL_WINDOW, self) logging.root.setLevel(log_level) # Overlay instances self.treeWidget_PR_fam.info_overlay = InfoOverlay( self.treeWidget_PR_fam) self.treeWidget_Models.info_overlay = InfoOverlay( self.treeWidget_Models) # Lock model selection in wizard Vplus import if not fakom_reader and wizard: self.treeWidget_Models.setEnabled(False) # Populate tree widgets self.create_pr_family_tree(PR_FAM_INT + PR_FAM_EXT) self.create_model_tree() # Set options for special Fakom Reader or wizard cases self.setup_options() # Ok | Cancel btns self.buttonBox.accepted.connect(self.exit_accept) # self.buttonBox.rejected.connect(self.exit_abort) # Filter btns self.skip_filter = False self.btn_filter_all.stateChanged.connect(self.set_btn_filter) self.btn_filter_int.stateChanged.connect(self.set_btn_filter) self.btn_filter_ext.stateChanged.connect(self.set_btn_filter) # Reset initial checkbox status self.set_options() # Option Checkboxes self.check_short_names.stateChanged.connect(self.set_options) self.check_read_trim.stateChanged.connect(self.set_options) self.check_short_pkg_names.stateChanged.connect(self.set_options) self.check_read_options.stateChanged.connect(self.set_options) self.check_read_packages.stateChanged.connect(self.set_options) # Add filter txt widgets as attributes self.treeWidget_Models.filter_txt_widget = self.lineEdit_filter_Models self.treeWidget_PR_fam.filter_txt_widget = self.lineEdit_filter_PR_Fam # Setup filter threads and connect line Edits self.treeWidget_Models.filter = filter_on_timer( self.lineEdit_filter_Models, self.treeWidget_Models, filter_column=[0, 1]) self.lineEdit_filter_Models.textChanged.connect( self.treeWidget_Models.filter.start_timer) self.treeWidget_PR_fam.filter = filter_on_timer( self.lineEdit_filter_PR_Fam, self.treeWidget_PR_fam, filter_column=[0, 1]) self.lineEdit_filter_PR_Fam.textChanged.connect( self.treeWidget_PR_fam.filter.start_timer) # Create line_edit filtering thread # self.tree_filter_thread = TreeFilterThread() # self.tree_filter_thread.create_thread() # # Connect text filter class PR Family # self.pr_fam_txt_filter = self.txt_filtering(self.tree_filter_thread, self.treeWidget_PR_fam, column=[0, 1]) # self.lineEdit_filter_PR_Fam.textChanged.connect(self.pr_fam_txt_filter.filter_txt) # # Connect text filter class Models # self.model_txt_filter = self.txt_filtering(self.tree_filter_thread, self.treeWidget_Models, column=[0, 1]) # self.lineEdit_filter_Models.textChanged.connect(self.model_txt_filter.filter_txt) # Add Key events self.model_tree_keys = TreeKeyEvents(self.treeWidget_Models, self.parent, False, no_edit=True) self.model_tree_keys.add_event_filter() self.prfam_tree_keys = TreeKeyEvents(self.treeWidget_PR_fam, self.parent, False, no_edit=True) self.prfam_tree_keys.add_event_filter() # Context Menu ui = self.parent.open_dialog.ui self.pr_menu = SelectionContextMenu(self.treeWidget_PR_fam, ui) self.mod_menu = SelectionContextMenu(self.treeWidget_Models, ui) # Store filename LoadVplus.last_file = self.filename
def __init__(self, parent): super(FakomWizardPage, self).__init__(parent) self.parent = parent self.selected_ids = set() self.ui, self.app = parent.ui, parent.app # Load page template load_ui_file(self, WIZARD_PAGE_FAKOM) self.setButtonText(QtWidgets.QWizard.BackButton, QobMsg.back_fakom) # Info Overlay self.fakomTree.info_overlay = InfoOverlay(self.fakomTree) self.treeWidget_Selected.info_overlay = InfoOverlay( self.treeWidget_Selected) # Add filter txt widgets as attribute self.fakomTree.filter_txt_widget = self.lineEditFilter # Connect text filter self.fakom_txt_filter = self.parent.TxtFiltering( self.parent.tree_filter_thread, self.fakomTree, column=[0], pattern=1) self.lineEditFilter.textChanged.connect( self.fakom_txt_filter.filter_txt) # Add Key events self.fakom_tree_keys = TreeKeyEvents(self.fakomTree, self.ui, self.app, wizard=True, no_edit=True) self.fakom_tree_keys.add_event_filter() # Selection context menu self.fakom_menu = SelectionContextMenu(self.fakomTree, self.ui, checkable=False) self.fakom_menu.all_deselected.connect(self.context_all_deselected) # Tree helpers self.iter_childs = iterate_item_childs(self.fakomTree) self.fakomTree.hideColumn(1) self.fakomTree.hideColumn(2) self.fakomTree.hideColumn(3) self.treeWidget_Selected.hideColumn(1) self.splitterSizes = self.treeSplitter.sizes() self.last_selection_size = 0 # Selection update timer self.s_timer.timeout.connect(self.selection_changed) # Warning delay timer self.warn_display_delay.timeout.connect(self.warn_fakom) # Events self.fakomTree.itemSelectionChanged.connect(self.s_timer.start) self.treeWidget_Selected.itemClicked.connect( self.display_tree_item_clicked) self.checkBox_models.toggled.connect(self.list_by_model) self.checkBoxSort.toggled.connect(self.sort_btn_toggled)