Пример #1
0
    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)
Пример #4
0
    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()
Пример #5
0
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>'
            '+/&#45; oder Q/E &#45; Bildanzeige vergößern/verkleinern<br>'
            '&lt;/&gt; oder A/D          &#45; Nächste/Vorherige Bilddatei im Ordner<br>'
            'STRG+/STRG&#45; oder W/S  &#45; Transparenz erhöhen/verringern<br><br>'
            'Leertaste oder X &#45; Bildanzeige ein&#45;/ausschalten<br>'
            'F &#45; DeltaGen Viewer Sync ein&#45;/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
Пример #6
0
    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)
Пример #8
0
    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)