def _create_tool_bar(self): tools_toolbar = QToolBar('Tools') tools_toolbar.addAction(self.file_open) tools_toolbar.setFloatable(False) tools_toolbar.setMovable(False) self.addToolBar(tools_toolbar)
def setup(self): # icons self.homeIcon = Icon('home.svg', '#0A0').getIcon() self.csvIcon = Icon('file-csv.svg', '#D50').getIcon() self.dbIcon = Icon('database.svg', '#666').getIcon() # Setup ToolBar toolBar = QToolBar('Left Menu', self) toolBar.setFloatable(False) toolBar.setMovable(False) toolBar.setIconSize(QSize(64, 64)) toolBar.setStyleSheet('background-color: #004; color: #FFF;') # Tabs Properties self.TabContainer.setTabsClosable(True) self.TabContainer.tabCloseRequested.connect(self.closeTab) # Home home = QAction(self.homeIcon, 'Home', self) home.triggered.connect(self.onHome) self.TabContainer.addTab(self.home, self.homeIcon, 'Home') # CSV loadCSV = QAction(self.csvIcon, 'Load CSV', self) loadCSV.triggered.connect(self.onLoadCSV) # DB loadDB = QAction(self.dbIcon, 'Load From DataBase', self) loadDB.triggered.connect(self.onLoadDB) # Add to ToolBar toolBar.addAction(home) toolBar.addAction(loadCSV) toolBar.addAction(loadDB) self.addToolBar(Qt.LeftToolBarArea, toolBar)
def __init__(self, parentWidget, settings): QWidget.__init__(self, parentWidget) self.settings = settings toolbar = QToolBar(self) toolbar.setFloatable(False) toolbar.setMovable(False) addAction = QAction("+", toolbar) addAction.triggered.connect(self.addNotepad) toolbar.addAction(addAction) removeAction = QAction("-", toolbar) removeAction.triggered.connect(self.removeNotepad) toolbar.addAction(removeAction) self.browserView = TreeWidget(self) hLayout = QVBoxLayout(self) hLayout.setContentsMargins(0, 0, 0, 1) hLayout.addWidget(toolbar) hLayout.addWidget(self.browserView) self.currentItem = None self.browserView.itemSelectionChanged.connect(self.handleItemSelected)
def __init__(self, parent=None): super().__init__(parent) self.mTile = None self.mMapDocument = None self.mMapScene = MapScene(self) self.mMapView = MapView(self, MapViewMode.NoStaticContents) self.mToolManager = ToolManager(self) self.mApplyingChanges = False self.mSynchronizing = False self.setObjectName("TileCollisionEditor") widget = QWidget(self) layout = QVBoxLayout(widget) layout.setSpacing(0) layout.setContentsMargins(5, 5, 5, 5) self.mMapView.setScene(self.mMapScene) self.mMapView.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.mMapView.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) rectangleObjectsTool = CreateRectangleObjectTool(self) ellipseObjectsTool = CreateEllipseObjectTool(self) polygonObjectsTool = CreatePolygonObjectTool(self) polylineObjectsTool = CreatePolylineObjectTool(self) toolBar = QToolBar(self) toolBar.setMovable(False) toolBar.setFloatable(False) toolBar.setContextMenuPolicy(Qt.ActionsContextMenu) self.mToolManager = ToolManager(self) toolBar.addAction( self.mToolManager.registerTool(ObjectSelectionTool(self))) toolBar.addAction(self.mToolManager.registerTool( EditPolygonTool(self))) toolBar.addAction(self.mToolManager.registerTool(rectangleObjectsTool)) toolBar.addAction(self.mToolManager.registerTool(ellipseObjectsTool)) toolBar.addAction(self.mToolManager.registerTool(polygonObjectsTool)) toolBar.addAction(self.mToolManager.registerTool(polylineObjectsTool)) self.setCentralWidget(self.mMapView) self.addToolBar(toolBar) self.mMapScene.setSelectedTool(self.mToolManager.selectedTool()) self.mToolManager.selectedToolChanged.connect(self.setSelectedTool) zoomComboBox = QComboBox() self.statusBar().addPermanentWidget(zoomComboBox) zoomable = self.mMapView.zoomable() zoomable.connectToComboBox(zoomComboBox) undoShortcut = QShortcut(QKeySequence.Undo, self) redoShortcut = QShortcut(QKeySequence.Redo, self) cutShortcut = QShortcut(QKeySequence.Cut, self) copyShortcut = QShortcut(QKeySequence.Copy, self) pasteShortcut = QShortcut(QKeySequence.Paste, self) deleteShortcut = QShortcut(QKeySequence.Delete, self) deleteShortcut2 = QShortcut(QKeySequence.Back, self) undoShortcut.activated.connect(self.undo) redoShortcut.activated.connect(self.redo) cutShortcut.activated.connect(self.cut) copyShortcut.activated.connect(self.copy) pasteShortcut.activated.connect(self.paste) deleteShortcut.activated.connect(self.delete_) deleteShortcut2.activated.connect(self.delete_) self.retranslateUi() self.resize(300, 300) Utils.restoreGeometry(self)
def _createToolBar(self): tools = QToolBar() tools.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) tools.addAction(QIcon('Images/magnifier.png'), 'Search View', self.defaultView) tools.addAction(QIcon('Images/money-bag-dollar.png'), 'Bidding View', self.biddingView) tools.addAction(QIcon('Images/users.png'), 'Team View', self.teamView) tools.setFloatable(False) tools.setStyleSheet(""" QToolBar{ background-color: rgb(70, 72, 74); color: rgb(242, 243, 244); } QToolButton { background-color: rgb(80, 81, 82); color: rgb(242, 243, 244); border-width: 2px; spacing: 5px; padding: 3px; border-radius: 3px; } """) self.addToolBar(tools)
def __init__(self, parent): TitledToolbar.__init__(self, parent, 'Actions') toolbar = QToolBar(self) toolbar.setFloatable(False) toolbar.setMovable(False) self.saveAction = QAction(QIcon(":/icons/file-save.png"), "Save (Ctrl-S)", toolbar) self.saveAction.setShortcut(Qt.CTRL + Qt.Key_S) self.saveAction.triggered.connect(parent.save) toolbar.addAction(self.saveAction) self.nonprintableAction = QAction( QIcon(":/icons/view-nonprintable.png"), "View nonprintable chars", toolbar) self.nonprintableAction.setCheckable(True) self.nonprintableAction.triggered.connect(parent.toggleNonprintable) toolbar.addAction(self.nonprintableAction) self.undoAction = QAction(QIcon(":/icons/edit-undo.png"), "Undo (Ctrl-Z)", toolbar) # saveAction.setShortcut(Qt.CTRL + Qt.Key_Z); self.undoAction.triggered.connect(parent.undo) toolbar.addAction(self.undoAction) self.redoAction = QAction(QIcon(":/icons/edit-redo.png"), "Redo (Ctrl-Y)", toolbar) # saveAction.setShortcut(Qt.CTRL + Qt.Key_Y); self.redoAction.triggered.connect(parent.redo) toolbar.addAction(self.redoAction) self.backAction = QAction(QIcon(":/icons/view-back.png"), "Back", toolbar) self.backAction.setEnabled(False) self.backAction.triggered.connect(parent.navigateBack) toolbar.addAction(self.backAction) self.forwardAction = QAction(QIcon(":/icons/view-forward.png"), "Forward", toolbar) self.forwardAction.setEnabled(False) self.forwardAction.triggered.connect(parent.navigateForward) toolbar.addAction(self.forwardAction) insertImageAction = QAction(QIcon(":/icons/edit-insert-image.png"), "Insert Image", toolbar) insertImageAction.triggered.connect(parent.insertImage) toolbar.addAction(insertImageAction) insertFormulaAction = QAction("f(x)", toolbar) insertFormulaAction.triggered.connect(parent.insertFormula) toolbar.addAction(insertFormulaAction) findInPageAction = QAction(QIcon(":/icons/edit-find.png"), "Find in page (CTRL-F)", toolbar) findInPageAction.setShortcut(Qt.CTRL + Qt.Key_F) findInPageAction.triggered.connect(parent.findInPage) toolbar.addAction(findInPageAction) self.addWidget(toolbar)
def __init__(self, parent = None): super().__init__(parent) self.mTile = None self.mMapDocument = None self.mMapScene = MapScene(self) self.mMapView = MapView(self, MapViewMode.NoStaticContents) self.mToolManager = ToolManager(self) self.mApplyingChanges = False self.mSynchronizing = False self.setObjectName("TileCollisionEditor") widget = QWidget(self) layout = QVBoxLayout(widget) layout.setSpacing(0) layout.setContentsMargins(5, 5, 5, 5) self.mMapView.setScene(self.mMapScene) self.mMapView.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.mMapView.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) rectangleObjectsTool = CreateRectangleObjectTool(self) ellipseObjectsTool = CreateEllipseObjectTool(self) polygonObjectsTool = CreatePolygonObjectTool(self) polylineObjectsTool = CreatePolylineObjectTool(self) toolBar = QToolBar(self) toolBar.setMovable(False) toolBar.setFloatable(False) toolBar.setContextMenuPolicy(Qt.ActionsContextMenu) self.mToolManager = ToolManager(self) toolBar.addAction(self.mToolManager.registerTool(ObjectSelectionTool(self))) toolBar.addAction(self.mToolManager.registerTool(EditPolygonTool(self))) toolBar.addAction(self.mToolManager.registerTool(rectangleObjectsTool)) toolBar.addAction(self.mToolManager.registerTool(ellipseObjectsTool)) toolBar.addAction(self.mToolManager.registerTool(polygonObjectsTool)) toolBar.addAction(self.mToolManager.registerTool(polylineObjectsTool)) self.setCentralWidget(self.mMapView) self.addToolBar(toolBar) self.mMapScene.setSelectedTool(self.mToolManager.selectedTool()) self.mToolManager.selectedToolChanged.connect(self.setSelectedTool) zoomComboBox = QComboBox() self.statusBar().addPermanentWidget(zoomComboBox) zoomable = self.mMapView.zoomable() zoomable.connectToComboBox(zoomComboBox) undoShortcut = QShortcut(QKeySequence.Undo, self) redoShortcut = QShortcut(QKeySequence.Redo, self) cutShortcut = QShortcut(QKeySequence.Cut, self) copyShortcut = QShortcut(QKeySequence.Copy, self) pasteShortcut = QShortcut(QKeySequence.Paste, self) deleteShortcut = QShortcut(QKeySequence.Delete, self) deleteShortcut2 = QShortcut(QKeySequence.Back, self) undoShortcut.activated.connect(self.undo) redoShortcut.activated.connect(self.redo) cutShortcut.activated.connect(self.cut) copyShortcut.activated.connect(self.copy) pasteShortcut.activated.connect(self.paste) deleteShortcut.activated.connect(self.delete_) deleteShortcut2.activated.connect(self.delete_) self.retranslateUi() self.resize(300, 300) Utils.restoreGeometry(self)
def __init__(self, toolbar): TitledToolbar.__init__(self, toolbar, 'Text style') self.currentStyle = None toolbar = QToolBar(self) toolbar.setFloatable(False) toolbar.setMovable(False) self.styleToAction = {} textKeywordAction = QAction(QIcon(':/icons/format-keyword.png'), 'Notepad link', toolbar) textKeywordAction.setCheckable(True) selector = ('olink', None, None) textKeywordAction.setProperty('style', selector) self.styleToAction[selector] = textKeywordAction textKeywordAction.triggered.connect(self.styleSelected) toolbar.addAction(textKeywordAction) textLinkAction = QAction(QIcon(':/icons/format-link.png'), 'Internet link', toolbar) textLinkAction.setCheckable(True) selector = ('link', None, None) textLinkAction.setProperty('style', selector) self.styleToAction[selector] = textLinkAction textLinkAction.triggered.connect(self.styleSelected) toolbar.addAction(textLinkAction) textBoldAction = QAction(QIcon(':/icons/format-text-emphasized.png'), 'Emphasize', toolbar) textBoldAction.setCheckable(True) selector = ('emphasis', None, None) textBoldAction.setProperty('style', selector) self.styleToAction[selector] = textBoldAction textBoldAction.triggered.connect(self.styleSelected) toolbar.addAction(textBoldAction) textHighlightAction = QAction( QIcon(':/icons/format-text-highlight.png'), 'Highlight', toolbar) textHighlightAction.setCheckable(True) selector = ('emphasis', 'role', 'highlight') textHighlightAction.setProperty('style', selector) self.styleToAction[selector] = textHighlightAction textHighlightAction.triggered.connect(self.styleSelected) toolbar.addAction(textHighlightAction) textCodeAction = QAction(QIcon(':/icons/format-text-code.png'), 'Code', toolbar) textCodeAction.setCheckable(True) selector = ('code', None, None) textCodeAction.setProperty('style', selector) self.styleToAction[selector] = textCodeAction textCodeAction.triggered.connect(self.styleSelected) toolbar.addAction(textCodeAction) self.addWidget(toolbar)
def _create_toolbar(self, color_maps): toolbar = QToolBar() toolbar.setFloatable(False) toolbar.setMovable(False) self._layout_combo = LayoutCombo() self._layout_combo_action = QWidgetAction(self._layout_combo) self._layout_combo_action.setDefaultWidget(self._layout_combo) toolbar.addAction(self._layout_combo_action) self._layout_combo.layout_changed.connect( self._slice_view_widget.set_plot_layout) # self._colormap_combo = ColormapCombo(['seismic', 'spectral', 'RdGy', 'hot', 'jet', 'gray']) self._colormap_combo = ColormapCombo(color_maps) self._colormap_combo.currentIndexChanged[int].connect( self._colormap_changed) toolbar.addWidget(self._colormap_combo) self._save_button = QToolButton() self._save_button.setToolTip("Save as image") self._save_button.setIcon(resource_icon("table_export.png")) self._save_button.clicked.connect(self._save_figure) toolbar.addWidget(self._save_button) self._settings_button = QToolButton() self._settings_button.setToolTip("Toggle settings visibility") self._settings_button.setIcon(resource_icon("cog.png")) self._settings_button.setCheckable(True) self._settings_button.toggled.connect(self._show_settings) toolbar.addWidget(self._settings_button) self._help_button = QToolButton() self._help_button.setToolTip("View help") self._help_button.setIcon(resource_icon("help.png")) self._help_button.setCheckable(True) self._help_button.toggled.connect(self._show_help) toolbar.addWidget(self._help_button) def toggle_on_close(event): self._settings_button.setChecked(False) event.accept() def toggle_on_close_help(event): self._help_button.setChecked(False) event.accept() self._settings_window.closeEvent = toggle_on_close self._help_window.closeEvent = toggle_on_close_help self._colormap_combo.setCurrentIndex(45) self.set_default_layout() return toolbar
def __init__(self, parent = None): super().__init__(parent) self.mOpacityLabel = QLabel() self.mOpacitySlider = QSlider(Qt.Horizontal) self.mLayerView = LayerView() self.mMapDocument = None self.mUpdatingSlider = False self.mChangingLayerOpacity = False self.mUpdatingSlider = False self.setObjectName("layerDock") widget = QWidget(self) layout = QVBoxLayout(widget) layout.setContentsMargins(5, 5, 5, 5) opacityLayout = QHBoxLayout() self.mOpacitySlider.setRange(0, 100) self.mOpacitySlider.setEnabled(False) opacityLayout.addWidget(self.mOpacityLabel) opacityLayout.addWidget(self.mOpacitySlider) self.mOpacityLabel.setBuddy(self.mOpacitySlider) handler = MapDocumentActionHandler.instance() newLayerMenu = QMenu(self) newLayerMenu.addAction(handler.actionAddTileLayer()) newLayerMenu.addAction(handler.actionAddObjectGroup()) newLayerMenu.addAction(handler.actionAddImageLayer()) newIcon = QIcon(":/images/16x16/document-new.png") newLayerButton = QToolButton() newLayerButton.setPopupMode(QToolButton.InstantPopup) newLayerButton.setMenu(newLayerMenu) newLayerButton.setIcon(newIcon) Utils.setThemeIcon(newLayerButton, "document-new") buttonContainer = QToolBar() buttonContainer.setFloatable(False) buttonContainer.setMovable(False) buttonContainer.setIconSize(QSize(16, 16)) buttonContainer.addWidget(newLayerButton) buttonContainer.addAction(handler.actionMoveLayerUp()) buttonContainer.addAction(handler.actionMoveLayerDown()) buttonContainer.addAction(handler.actionDuplicateLayer()) buttonContainer.addAction(handler.actionRemoveLayer()) buttonContainer.addSeparator() buttonContainer.addAction(handler.actionToggleOtherLayers()) listAndToolBar = QVBoxLayout() listAndToolBar.setSpacing(0) listAndToolBar.addWidget(self.mLayerView) listAndToolBar.addWidget(buttonContainer) layout.addLayout(opacityLayout) layout.addLayout(listAndToolBar) self.setWidget(widget) self.retranslateUi() self.mOpacitySlider.valueChanged.connect(self.sliderValueChanged) self.updateOpacitySlider()
def __init__(self, parent=None): super().__init__(parent) self.mOpacityLabel = QLabel() self.mOpacitySlider = QSlider(Qt.Horizontal) self.mLayerView = LayerView() self.mMapDocument = None self.mUpdatingSlider = False self.mChangingLayerOpacity = False self.mUpdatingSlider = False self.setObjectName("layerDock") widget = QWidget(self) layout = QVBoxLayout(widget) layout.setContentsMargins(5, 5, 5, 5) opacityLayout = QHBoxLayout() self.mOpacitySlider.setRange(0, 100) self.mOpacitySlider.setEnabled(False) opacityLayout.addWidget(self.mOpacityLabel) opacityLayout.addWidget(self.mOpacitySlider) self.mOpacityLabel.setBuddy(self.mOpacitySlider) handler = MapDocumentActionHandler.instance() newLayerMenu = QMenu(self) newLayerMenu.addAction(handler.actionAddTileLayer()) newLayerMenu.addAction(handler.actionAddObjectGroup()) newLayerMenu.addAction(handler.actionAddImageLayer()) newIcon = QIcon(":/images/16x16/document-new.png") newLayerButton = QToolButton() newLayerButton.setPopupMode(QToolButton.InstantPopup) newLayerButton.setMenu(newLayerMenu) newLayerButton.setIcon(newIcon) Utils.setThemeIcon(newLayerButton, "document-new") buttonContainer = QToolBar() buttonContainer.setFloatable(False) buttonContainer.setMovable(False) buttonContainer.setIconSize(QSize(16, 16)) buttonContainer.addWidget(newLayerButton) buttonContainer.addAction(handler.actionMoveLayerUp()) buttonContainer.addAction(handler.actionMoveLayerDown()) buttonContainer.addAction(handler.actionDuplicateLayer()) buttonContainer.addAction(handler.actionRemoveLayer()) buttonContainer.addSeparator() buttonContainer.addAction(handler.actionToggleOtherLayers()) listAndToolBar = QVBoxLayout() listAndToolBar.setSpacing(0) listAndToolBar.addWidget(self.mLayerView) listAndToolBar.addWidget(buttonContainer) layout.addLayout(opacityLayout) layout.addLayout(listAndToolBar) self.setWidget(widget) self.retranslateUi() self.mOpacitySlider.valueChanged.connect(self.sliderValueChanged) self.updateOpacitySlider()
def __init__(self, toolbar): TitledToolbar.__init__(self, toolbar, 'Text style') self.currentStyle = None toolbar = QToolBar(self) toolbar.setFloatable(False) toolbar.setMovable(False) self.styleToAction = {} textKeywordAction = QAction(QIcon(':/icons/format-keyword.png'), 'Notepad link', toolbar) textKeywordAction.setCheckable(True); selector = ('olink', None, None) textKeywordAction.setProperty('style', selector) self.styleToAction[selector] = textKeywordAction textKeywordAction.triggered.connect(self.styleSelected) toolbar.addAction(textKeywordAction) textLinkAction = QAction(QIcon(':/icons/format-link.png'), 'Internet link', toolbar) textLinkAction.setCheckable(True); selector = ('link', None, None) textLinkAction.setProperty('style', selector) self.styleToAction[selector] = textLinkAction textLinkAction.triggered.connect(self.styleSelected) toolbar.addAction(textLinkAction) textBoldAction = QAction(QIcon(':/icons/format-text-emphasized.png'), 'Emphasize', toolbar) textBoldAction.setCheckable(True); selector = ('emphasis', None, None) textBoldAction.setProperty('style', selector) self.styleToAction[selector] = textBoldAction textBoldAction.triggered.connect(self.styleSelected) toolbar.addAction(textBoldAction) textHighlightAction = QAction(QIcon(':/icons/format-text-highlight.png'), 'Highlight', toolbar) textHighlightAction.setCheckable(True); selector = ('emphasis', 'role', 'highlight') textHighlightAction.setProperty('style', selector) self.styleToAction[selector] = textHighlightAction textHighlightAction.triggered.connect(self.styleSelected) toolbar.addAction(textHighlightAction) textCodeAction = QAction(QIcon(':/icons/format-text-code.png'), 'Code', toolbar) textCodeAction.setCheckable(True); selector = ('code', None, None) textCodeAction.setProperty('style', selector) self.styleToAction[selector] = textCodeAction textCodeAction.triggered.connect(self.styleSelected) toolbar.addAction(textCodeAction) self.addWidget(toolbar)
def __init__(self, parent): TitledToolbar.__init__(self, parent, 'Actions') toolbar = QToolBar(self) toolbar.setFloatable(False) toolbar.setMovable(False) self.saveAction = QAction(QIcon(":/icons/file-save.png"), "Save (Ctrl-S)", toolbar) self.saveAction.setShortcut(Qt.CTRL + Qt.Key_S); self.saveAction.triggered.connect(parent.save) toolbar.addAction(self.saveAction) self.nonprintableAction = QAction(QIcon(":/icons/view-nonprintable.png"), "View nonprintable chars", toolbar) self.nonprintableAction.setCheckable(True); self.nonprintableAction.triggered.connect(parent.toggleNonprintable) toolbar.addAction(self.nonprintableAction) self.undoAction = QAction(QIcon(":/icons/edit-undo.png"), "Undo (Ctrl-Z)", toolbar) # saveAction.setShortcut(Qt.CTRL + Qt.Key_Z); self.undoAction.triggered.connect(parent.undo) toolbar.addAction(self.undoAction) self.redoAction = QAction(QIcon(":/icons/edit-redo.png"), "Redo (Ctrl-Y)", toolbar) # saveAction.setShortcut(Qt.CTRL + Qt.Key_Y); self.redoAction.triggered.connect(parent.redo) toolbar.addAction(self.redoAction) self.backAction = QAction(QIcon(":/icons/view-back.png"), "Back", toolbar) self.backAction.setEnabled(False) self.backAction.triggered.connect(parent.navigateBack) toolbar.addAction(self.backAction) self.forwardAction = QAction(QIcon(":/icons/view-forward.png"), "Forward", toolbar) self.forwardAction.setEnabled(False) self.forwardAction.triggered.connect(parent.navigateForward) toolbar.addAction(self.forwardAction) insertImageAction = QAction(QIcon(":/icons/edit-insert-image.png"), "Insert Image", toolbar) insertImageAction.triggered.connect(parent.insertImage) toolbar.addAction(insertImageAction) insertFormulaAction = QAction("f(x)", toolbar) insertFormulaAction.triggered.connect(parent.insertFormula) toolbar.addAction(insertFormulaAction) findInPageAction = QAction(QIcon(":/icons/edit-find.png"), "Find in page (CTRL-F)", toolbar) findInPageAction.setShortcut(Qt.CTRL + Qt.Key_F); findInPageAction.triggered.connect(parent.findInPage) toolbar.addAction(findInPageAction) self.addWidget(toolbar)
def _createContractionToolbar(self): toolbar = QToolBar(parent=self) toolbar.setFloatable(True) toolbar.setMovable(True) toolbar.hide() action = toolbar.addAction('next') action.triggered.connect(self.next_hg) action = toolbar.addAction('previous') action.triggered.connect(self.previous_hg) action = toolbar.addAction('stop') action.triggered.connect(self.stopContractionPlayerSlot) self.contraction_toolbar = toolbar
def add_toolbar(self, title=None, toolbar=None): """Creates, adds and returns a QToolBar """ if 1 != bool(toolbar) + bool(title): raise ValueError('Just one of toolbar or title should be given') if not toolbar: toolbar = QToolBar(title) toolbar.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum) self.addTab(toolbar, toolbar.windowTitle()) # This style applies to QToolButtons that are immediate children # of the toolbar - it does not apply to QToolButtons that are # contained within QWidgets added to toolbar. toolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) toolbar.setMovable(False) toolbar.setFloatable(False) return toolbar
def add_toolbar(self, name: str, toolbar: QToolBar, text: str = 'untitled toolbar'): b = self.top_toolbar_tab.add_button(text) toolbar.tab_button = b b.clicked.connect(lambda: self.switch_toolbar(name)) self.addToolBarBreak(Qt.TopToolBarArea) self.addToolBar(toolbar) toolbar.setObjectName(name) self.toolbars[name] = toolbar toolbar.setMovable(False) toolbar.setFloatable(False) if self._current_toolbar_name != '': self.refresh_toolbar_appearance()
def __init__(self, parent=None): super().__init__(parent) self.mMapDocument = None self.mPropertyBrowser = PropertyBrowser() self.setObjectName("propertiesDock") self.mActionAddProperty = QAction(self) self.mActionAddProperty.setEnabled(False) self.mActionAddProperty.setIcon(QIcon(":/images/16x16/add.png")) self.mActionAddProperty.triggered.connect(self.addProperty) self.mActionRemoveProperty = QAction(self) self.mActionRemoveProperty.setEnabled(False) self.mActionRemoveProperty.setIcon(QIcon(":/images/16x16/remove.png")) self.mActionRemoveProperty.triggered.connect(self.removeProperty) self.mActionRenameProperty = QAction(self) self.mActionRenameProperty.setEnabled(False) self.mActionRenameProperty.setIcon(QIcon(":/images/16x16/rename.png")) self.mActionRenameProperty.triggered.connect(self.renameProperty) Utils.setThemeIcon(self.mActionAddProperty, "add") Utils.setThemeIcon(self.mActionRemoveProperty, "remove") Utils.setThemeIcon(self.mActionRenameProperty, "rename") toolBar = QToolBar() toolBar.setFloatable(False) toolBar.setMovable(False) toolBar.setIconSize(QSize(16, 16)) toolBar.addAction(self.mActionAddProperty) toolBar.addAction(self.mActionRemoveProperty) toolBar.addAction(self.mActionRenameProperty) widget = QWidget(self) layout = QVBoxLayout(widget) layout.setContentsMargins(5, 5, 5, 5) layout.setSpacing(0) layout.addWidget(self.mPropertyBrowser) layout.addWidget(toolBar) widget.setLayout(layout) self.setWidget(widget) manager = DocumentManager.instance() manager.currentDocumentChanged.connect(self.mapDocumentChanged) self.mPropertyBrowser.currentItemChangedSignal.connect( self.currentItemChanged) self.retranslateUi()
def __init__(self, parent = None): super().__init__(parent) self.mExpandedGroups = QMapList() self.mObjectsView = ObjectsView() self.mMapDocument = None self.setObjectName("ObjectsDock") self.mActionObjectProperties = QAction(self) self.mActionObjectProperties.setIcon(QIcon(":/images/16x16/document-properties.png")) Utils.setThemeIcon(self.mActionObjectProperties, "document-properties") self.mActionObjectProperties.triggered.connect(self.objectProperties) handler = MapDocumentActionHandler.instance() widget = QWidget(self) layout = QVBoxLayout(widget) layout.setContentsMargins(5, 5, 5, 5) layout.setSpacing(0) layout.addWidget(self.mObjectsView) self.mActionNewLayer = QAction(self) self.mActionNewLayer.setIcon(QIcon(":/images/16x16/document-new.png")) self.mActionNewLayer.triggered.connect(handler.actionAddObjectGroup().triggered) self.mActionMoveToGroup = QAction(self) self.mActionMoveToGroup.setIcon(QIcon(":/images/16x16/layer-object.png")) toolBar = QToolBar() toolBar.setFloatable(False) toolBar.setMovable(False) toolBar.setIconSize(QSize(16, 16)) toolBar.addAction(self.mActionNewLayer) toolBar.addAction(handler.actionDuplicateObjects()) toolBar.addAction(handler.actionRemoveObjects()) toolBar.addAction(self.mActionMoveToGroup) button = toolBar.widgetForAction(self.mActionMoveToGroup) self.mMoveToMenu = QMenu(self) button.setPopupMode(QToolButton.InstantPopup) button.setMenu(self.mMoveToMenu) self.mMoveToMenu.aboutToShow.connect(self.aboutToShowMoveToMenu) self.mMoveToMenu.triggered.connect(self.triggeredMoveToMenu) toolBar.addAction(self.mActionObjectProperties) layout.addWidget(toolBar) self.setWidget(widget) self.retranslateUi() DocumentManager.instance().documentAboutToClose.connect(self.documentAboutToClose)
def __init__(self, parent = None): super().__init__(parent) self.mMapDocument = None self.mPropertyBrowser = PropertyBrowser() self.setObjectName("propertiesDock") self.mActionAddProperty = QAction(self) self.mActionAddProperty.setEnabled(False) self.mActionAddProperty.setIcon(QIcon(":/images/16x16/add.png")) self.mActionAddProperty.triggered.connect(self.addProperty) self.mActionRemoveProperty = QAction(self) self.mActionRemoveProperty.setEnabled(False) self.mActionRemoveProperty.setIcon(QIcon(":/images/16x16/remove.png")) self.mActionRemoveProperty.triggered.connect(self.removeProperty) self.mActionRenameProperty = QAction(self) self.mActionRenameProperty.setEnabled(False) self.mActionRenameProperty.setIcon(QIcon(":/images/16x16/rename.png")) self.mActionRenameProperty.triggered.connect(self.renameProperty) Utils.setThemeIcon(self.mActionAddProperty, "add") Utils.setThemeIcon(self.mActionRemoveProperty, "remove") Utils.setThemeIcon(self.mActionRenameProperty, "rename") toolBar = QToolBar() toolBar.setFloatable(False) toolBar.setMovable(False) toolBar.setIconSize(QSize(16, 16)) toolBar.addAction(self.mActionAddProperty) toolBar.addAction(self.mActionRemoveProperty) toolBar.addAction(self.mActionRenameProperty) widget = QWidget(self) layout = QVBoxLayout(widget) layout.setContentsMargins(5, 5, 5, 5) layout.setSpacing(0) layout.addWidget(self.mPropertyBrowser) layout.addWidget(toolBar) widget.setLayout(layout) self.setWidget(widget) manager = DocumentManager.instance() manager.currentDocumentChanged.connect(self.mapDocumentChanged) self.mPropertyBrowser.currentItemChangedSignal.connect(self.currentItemChanged) self.retranslateUi()
def add_toolbar(self, name: str, toolbar: QToolBar, text: str = 'untitled toolbar'): """ 添加一个工具栏。 """ b = self.top_toolbar_tab.add_button(text) toolbar.tab_button = b b.clicked.connect(lambda: self.on_toolbar_switch_button_clicked(name)) if hasattr(self, 'toolbar_path'): self.insertToolBar(self.toolbar_path, toolbar) self.insertToolBarBreak(self.toolbar_path) else: self.addToolBarBreak(Qt.TopToolBarArea) self.addToolBar(toolbar) toolbar.setObjectName(name) self.toolbars[name] = toolbar toolbar.setMovable(False) toolbar.setFloatable(False) if self._current_toolbar_name != '': self.refresh_toolbar_appearance()
def __init__(self, style='default'): super(QRibbonWindow, self).__init__() self.style = style self.setObjectName('QRibbonWindow') self.tabs = [] self.groups = [] # 设置样式 self.default = default if self.style == 'default': _default = default.replace("{{margin}}", str(self.margin)) self.setStyleSheet(_default + '\n' + self.styleSheet()) # 去除右键菜单 self.setContextMenuPolicy(Qt.NoContextMenu) # 添加工具栏 toolBar = QToolBar(self) toolBar.setMouseTracking(True) self.ribbonWidget = QRibbonWidget(toolBar) toolBar.addWidget(self.ribbonWidget) toolBar.setAllowedAreas(Qt.NoToolBarArea) toolBar.setMovable(False) toolBar.setFloatable(False) self.addToolBar(toolBar) # 添加中心控件 self.centralWidget = QWidget(self) self.centralWidget.setMouseTracking(True) self.centralWidget.setObjectName("centralWidget") self.setCentralWidget(self.centralWidget) # 安装时间过滤器 self.installEventFilter(self) self.ribbonWidget.tabPanel.installEventFilter(self) self.minButton.installEventFilter(self) self.maxButton.installEventFilter(self) self.closeButton.installEventFilter(self) # 最小化、最大化、关闭按钮事件 self.minButton.clicked.connect(self.showMinimized) self.maxButton.clicked.connect(self.toggle_max) self.closeButton.clicked.connect(self.close)
class Record(object): def __init__(self): r = Record() r.foo = 'oof' setattr(r, 'bar', 'rab') r.foo 'oof' r.bar 'rab' names = 'id description price'.split() values = [666, 'duct tape', 3.45] s = Record() for name, value in zip(names, values): setattr(s, name, value) s.__dict__ # If you are suffering from dict withdrawal symptoms {'price': 3.45, 'id': 666, 'description': 'duct tape'} return self def appToolBar(self, QToolBar, cfg): 'Create a Toolbar from configurations file' pxcfg = here+'z-data_/desktop.yaml' self.config = config.instruct(pxcfg).select( 'docAddToolBar').override(cfg)# || self.createToolBar() for button, cfg in self.config['buttons'].items(): self.createButton(button, cfg) def createToolBar(self): self.toolbar = QToolBar() self.toolbar.setMovable(True) self.toolbar.setFloatable(True) self.toolbar.setOrientation(Qt.Vertical) return self def createButton(self, button, cfg): '' toolbutton = QToolButton() toolbutton.setText(cfg['DisplayName']) toolbutton.setCheckable(cfg['checkable']) toolbutton.setAutoExclusive(cfg['setAutoExclusive']) self.toolbar.addWidget(toolbutton) return self
def _create_toolbar(self): toolbar = QToolBar() toolbar.setFloatable(False) toolbar.setMovable(False) self.layout_combo = LayoutCombo() toolbar.addWidget(self.layout_combo) self.layout_combo.layout_changed.connect(self._plot_layout_changed) self._settings_button = QToolButton() self._settings_button.setToolTip("Toggle settings visibility") self._settings_button.setIcon(resource_icon("cog.png")) self._settings_button.setCheckable(True) self._settings_button.toggled.connect(self._show_settings) toolbar.addWidget(self._settings_button) def toggle_on_close(event): self._settings_button.setChecked(False) event.accept() self._settings_window.closeEvent = toggle_on_close return toolbar
class MainWindow_Ui(QMainWindow): def __init__(self, persepolis_setting): super().__init__() # MainWindow self.persepolis_setting = persepolis_setting icons = ':/' + \ str(self.persepolis_setting.value('settings/icons')) + '/' self.setWindowTitle("Persepolis Download Manager") self.setWindowIcon( QIcon.fromTheme('persepolis', QIcon(':/persepolis.svg'))) self.centralwidget = QWidget(self) self.verticalLayout = QVBoxLayout(self.centralwidget) # enable drag and drop self.setAcceptDrops(True) # frame self.frame = QFrame(self.centralwidget) # download_table_horizontalLayout download_table_horizontalLayout = QHBoxLayout() tabels_splitter = QSplitter(Qt.Horizontal) # category_tree self.category_tree_qwidget = QWidget(self) category_tree_verticalLayout = QVBoxLayout() self.category_tree = CategoryTreeView(self) category_tree_verticalLayout.addWidget(self.category_tree) self.category_tree_model = QStandardItemModel() self.category_tree.setModel(self.category_tree_model) category_table_header = ['Category'] self.category_tree_model.setHorizontalHeaderLabels( category_table_header) self.category_tree.header().setStretchLastSection(True) # queue_panel self.queue_panel_widget = QWidget(self) queue_panel_verticalLayout_main = QVBoxLayout(self.queue_panel_widget) # queue_panel_show_button self.queue_panel_show_button = QPushButton(self) queue_panel_verticalLayout_main.addWidget(self.queue_panel_show_button) # queue_panel_widget_frame self.queue_panel_widget_frame = QFrame(self) self.queue_panel_widget_frame.setFrameShape(QFrame.StyledPanel) self.queue_panel_widget_frame.setFrameShadow(QFrame.Raised) queue_panel_verticalLayout_main.addWidget( self.queue_panel_widget_frame) queue_panel_verticalLayout = QVBoxLayout(self.queue_panel_widget_frame) queue_panel_verticalLayout_main.setContentsMargins(50, -1, 50, -1) # start_end_frame self.start_end_frame = QFrame(self) # start time start_verticalLayout = QVBoxLayout(self.start_end_frame) self.start_checkBox = QCheckBox(self) start_verticalLayout.addWidget(self.start_checkBox) self.start_frame = QFrame(self) self.start_frame.setFrameShape(QFrame.StyledPanel) self.start_frame.setFrameShadow(QFrame.Raised) start_frame_verticalLayout = QVBoxLayout(self.start_frame) self.start_time_qDataTimeEdit = QDateTimeEdit(self.start_frame) self.start_time_qDataTimeEdit.setDisplayFormat('H:mm') start_frame_verticalLayout.addWidget(self.start_time_qDataTimeEdit) start_verticalLayout.addWidget(self.start_frame) # end time self.end_checkBox = QCheckBox(self) start_verticalLayout.addWidget(self.end_checkBox) self.end_frame = QFrame(self) self.end_frame.setFrameShape(QFrame.StyledPanel) self.end_frame.setFrameShadow(QFrame.Raised) end_frame_verticalLayout = QVBoxLayout(self.end_frame) self.end_time_qDateTimeEdit = QDateTimeEdit(self.end_frame) self.end_time_qDateTimeEdit.setDisplayFormat('H:mm') end_frame_verticalLayout.addWidget(self.end_time_qDateTimeEdit) start_verticalLayout.addWidget(self.end_frame) self.reverse_checkBox = QCheckBox(self) start_verticalLayout.addWidget(self.reverse_checkBox) queue_panel_verticalLayout.addWidget(self.start_end_frame) # limit_after_frame self.limit_after_frame = QFrame(self) # limit_checkBox limit_verticalLayout = QVBoxLayout(self.limit_after_frame) self.limit_checkBox = QCheckBox(self) limit_verticalLayout.addWidget(self.limit_checkBox) # limit_frame self.limit_frame = QFrame(self) self.limit_frame.setFrameShape(QFrame.StyledPanel) self.limit_frame.setFrameShadow(QFrame.Raised) limit_verticalLayout.addWidget(self.limit_frame) limit_frame_verticalLayout = QVBoxLayout(self.limit_frame) # limit_spinBox limit_frame_horizontalLayout = QHBoxLayout() self.limit_spinBox = QDoubleSpinBox(self) self.limit_spinBox.setMinimum(1) self.limit_spinBox.setMaximum(1023) limit_frame_horizontalLayout.addWidget(self.limit_spinBox) # limit_comboBox self.limit_comboBox = QComboBox(self) self.limit_comboBox.addItem("") self.limit_comboBox.addItem("") limit_frame_horizontalLayout.addWidget(self.limit_comboBox) limit_frame_verticalLayout.addLayout(limit_frame_horizontalLayout) # limit_pushButton self.limit_pushButton = QPushButton(self) limit_frame_verticalLayout.addWidget(self.limit_pushButton) # after_checkBox self.after_checkBox = QtWidgets.QCheckBox(self) limit_verticalLayout.addWidget(self.after_checkBox) # after_frame self.after_frame = QtWidgets.QFrame(self) self.after_frame.setFrameShape(QtWidgets.QFrame.StyledPanel) self.after_frame.setFrameShadow(QtWidgets.QFrame.Raised) limit_verticalLayout.addWidget(self.after_frame) after_frame_verticalLayout = QVBoxLayout(self.after_frame) # after_comboBox self.after_comboBox = QComboBox(self) self.after_comboBox.addItem("") after_frame_verticalLayout.addWidget(self.after_comboBox) # after_pushButton self.after_pushButton = QPushButton(self) after_frame_verticalLayout.addWidget(self.after_pushButton) queue_panel_verticalLayout.addWidget(self.limit_after_frame) category_tree_verticalLayout.addWidget(self.queue_panel_widget) # keep_awake_checkBox self.keep_awake_checkBox = QCheckBox(self) queue_panel_verticalLayout.addWidget(self.keep_awake_checkBox) self.category_tree_qwidget.setLayout(category_tree_verticalLayout) tabels_splitter.addWidget(self.category_tree_qwidget) # download table widget self.download_table_content_widget = QWidget(self) download_table_content_widget_verticalLayout = QVBoxLayout( self.download_table_content_widget) self.download_table = DownloadTableWidget(self) download_table_content_widget_verticalLayout.addWidget( self.download_table) tabels_splitter.addWidget(self.download_table_content_widget) self.download_table.setColumnCount(13) self.download_table.setSelectionBehavior(QAbstractItemView.SelectRows) self.download_table.setEditTriggers(QAbstractItemView.NoEditTriggers) self.download_table.verticalHeader().hide() # hide gid and download dictioanry section self.download_table.setColumnHidden(8, True) self.download_table.setColumnHidden(9, True) download_table_header = [ 'File Name', 'Status', 'Size', 'Downloaded', 'Percentage', 'Connections', 'Transfer rate', 'Estimate time left', 'Gid', 'Link', 'First try date', 'Last try date', 'Category' ] self.download_table.setHorizontalHeaderLabels(download_table_header) # fixing the size of download_table when window is Maximized! self.download_table.horizontalHeader().setSectionResizeMode(0) self.download_table.horizontalHeader().setStretchLastSection(True) tabels_splitter.setStretchFactor(0, 3) # category_tree width tabels_splitter.setStretchFactor(1, 10) # ratio of tables's width download_table_horizontalLayout.addWidget(tabels_splitter) self.frame.setLayout(download_table_horizontalLayout) self.verticalLayout.addWidget(self.frame) self.setCentralWidget(self.centralwidget) # menubar self.menubar = QMenuBar(self) self.menubar.setGeometry(QRect(0, 0, 600, 24)) self.setMenuBar(self.menubar) fileMenu = self.menubar.addMenu('&File') editMenu = self.menubar.addMenu('&Edit') viewMenu = self.menubar.addMenu('&View') downloadMenu = self.menubar.addMenu('&Download') queueMenu = self.menubar.addMenu('&Queue') helpMenu = self.menubar.addMenu('&Help') # viewMenu submenus sortMenu = viewMenu.addMenu('Sort by') # statusbar self.statusbar = QStatusBar(self) self.setStatusBar(self.statusbar) self.statusbar.showMessage("Persepolis Download Manager") # toolBar self.toolBar2 = QToolBar(self) self.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar2) self.toolBar2.setWindowTitle('Menu') self.toolBar2.setIconSize(QSize(32, 32)) self.toolBar2.setFloatable(False) self.toolBar2.setMovable(False) self.toolBar = QToolBar(self) self.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar) self.toolBar.setWindowTitle('Toolbar') self.toolBar.setIconSize(QSize(32, 32)) self.toolBar.setFloatable(False) self.toolBar.setMovable(False) #toolBar and menubar and actions self.stopAllAction = QAction(QIcon(icons + 'stop_all'), 'Stop all active downloads', self, statusTip='Stop all active downloads', triggered=self.stopAllDownloads) downloadMenu.addAction(self.stopAllAction) self.sort_file_name_Action = QAction('File name', self, triggered=self.sortByName) sortMenu.addAction(self.sort_file_name_Action) self.sort_file_size_Action = QAction('File size', self, triggered=self.sortBySize) sortMenu.addAction(self.sort_file_size_Action) self.sort_first_try_date_Action = QAction( 'First try date', self, triggered=self.sortByFirstTry) sortMenu.addAction(self.sort_first_try_date_Action) self.sort_last_try_date_Action = QAction('Last try date', self, triggered=self.sortByLastTry) sortMenu.addAction(self.sort_last_try_date_Action) self.sort_download_status_Action = QAction('Download status', self, triggered=self.sortByStatus) sortMenu.addAction(self.sort_download_status_Action) self.trayAction = QAction('Show system tray icon', self, statusTip="Show/Hide system tray icon", triggered=self.showTray) self.trayAction.setCheckable(True) viewMenu.addAction(self.trayAction) self.showMenuBarAction = QAction('Show menubar', self, statusTip='Show menubar', triggered=self.showMenuBar) self.showMenuBarAction.setCheckable(True) viewMenu.addAction(self.showMenuBarAction) self.showSidePanelAction = QAction('Show side panel', self, statusTip='Show side panel', triggered=self.showSidePanel) self.showSidePanelAction.setCheckable(True) viewMenu.addAction(self.showSidePanelAction) self.minimizeAction = QAction(QIcon(icons + 'minimize'), 'Minimize to system tray', self, shortcut="Ctrl+W", statusTip="Minimize to system tray", triggered=self.minMaxTray) viewMenu.addAction(self.minimizeAction) self.addlinkAction = QAction(QIcon(icons + 'add'), 'Add New Download Link', self, shortcut="Ctrl+N", statusTip="Add New Download Link", triggered=self.addLinkButtonPressed) fileMenu.addAction(self.addlinkAction) self.addtextfileAction = QAction( QIcon(icons + 'file'), 'Import links from text file', self, statusTip='Create a Text file and put links in it.line by line!', triggered=self.importText) fileMenu.addAction(self.addtextfileAction) self.resumeAction = QAction(QIcon(icons + 'play'), 'Resume Download', self, shortcut="Ctrl+R", statusTip="Resume Download", triggered=self.resumeButtonPressed) downloadMenu.addAction(self.resumeAction) self.pauseAction = QAction(QIcon(icons + 'pause'), 'Pause Download', self, shortcut="Ctrl+C", statusTip="Pause Download", triggered=self.pauseButtonPressed) downloadMenu.addAction(self.pauseAction) self.stopAction = QAction(QIcon(icons + 'stop'), 'Stop Download', self, shortcut="Ctrl+S", statusTip="Stop/Cancel Download", triggered=self.stopButtonPressed) downloadMenu.addAction(self.stopAction) self.removeAction = QAction(QIcon(icons + 'remove'), 'Remove Download', self, shortcut="Ctrl+D", statusTip="Remove Download", triggered=self.removeButtonPressed) downloadMenu.addAction(self.removeAction) self.propertiesAction = QAction(QIcon(icons + 'setting'), 'Properties', self, shortcut="Ctrl+P", statusTip="Properties", triggered=self.propertiesButtonPressed) downloadMenu.addAction(self.propertiesAction) self.progressAction = QAction(QIcon(icons + 'window'), 'Progress', self, shortcut="Ctrl+Z", statusTip="Progress", triggered=self.progressButtonPressed) downloadMenu.addAction(self.progressAction) self.openFileAction = QAction(QIcon(icons + 'file'), 'Open file', self, statusTip='Open file', triggered=self.openFile) fileMenu.addAction(self.openFileAction) self.openDownloadFolderAction = QAction( QIcon(icons + 'folder'), 'Open download folder', self, statusTip='Open download folder', triggered=self.openDownloadFolder) fileMenu.addAction(self.openDownloadFolderAction) self.deleteFileAction = QAction(QIcon(icons + 'trash'), 'Delete file', self, statusTip='Delete file', triggered=self.deleteFile) fileMenu.addAction(self.deleteFileAction) self.openDefaultDownloadFolderAction = QAction( QIcon(icons + 'folder'), 'Open default download folder', self, statusTip='Open default download folder', triggered=self.openDefaultDownloadFolder) fileMenu.addAction(self.openDefaultDownloadFolderAction) self.exitAction = QAction(QIcon(icons + 'exit'), 'Exit', self, shortcut="Ctrl+Q", statusTip="Exit", triggered=self.closeEvent) fileMenu.addAction(self.exitAction) self.selectAction = QAction('Select multiple items ', self, statusTip='Select multiple items', triggered=self.selectDownloads) self.selectAction.setCheckable(True) editMenu.addAction(self.selectAction) self.selectAllAction = QAction(QIcon(icons + 'select_all'), 'Select All', self, statusTip='Select All', triggered=self.selectAll) editMenu.addAction(self.selectAllAction) self.selectAllAction.setEnabled(False) self.removeSelectedAction = QAction( QIcon(icons + 'multi_remove'), 'Remove selected downloads form list', self, statusTip='Remove selected downloads form list', triggered=self.removeSelected) editMenu.addAction(self.removeSelectedAction) self.removeSelectedAction.setEnabled(False) self.deleteSelectedAction = QAction( QIcon(icons + 'multi_trash'), 'Delete selected download files', self, statusTip='Delete selected download files', triggered=self.deleteSelected) editMenu.addAction(self.deleteSelectedAction) self.deleteSelectedAction.setEnabled(False) self.createQueueAction = QAction(QIcon(icons + 'add_queue'), 'Create new queue', self, statusTip='Create new download queue', triggered=self.createQueue) queueMenu.addAction(self.createQueueAction) self.removeQueueAction = QAction(QIcon(icons + 'remove_queue'), 'Remove this queue', self, statusTip='Remove this queue', triggered=self.removeQueue) queueMenu.addAction(self.removeQueueAction) self.startQueueAction = QAction(QIcon(icons + 'start_queue'), 'Start this queue', self, statusTip='Start this queue', triggered=self.startQueue) queueMenu.addAction(self.startQueueAction) self.stopQueueAction = QAction(QIcon(icons + 'stop_queue'), 'Stop this queue', self, statusTip='Stop this queue', triggered=self.stopQueue) queueMenu.addAction(self.stopQueueAction) self.moveUpAction = QAction( QIcon(icons + 'up'), 'Move up this item', self, statusTip='Move currently selected item up by one row', triggered=self.moveUp) queueMenu.addAction(self.moveUpAction) self.moveDownAction = QAction( QIcon(icons + 'down'), 'Move down this item', self, statusTip='Move currently selected item down by one row', triggered=self.moveDown) queueMenu.addAction(self.moveDownAction) self.moveUpSelectedAction = QAction( QIcon(icons + 'multi_up'), 'Move up selected items', self, statusTip='Move currently selected items up by one row', triggered=self.moveUpSelected) queueMenu.addAction(self.moveUpSelectedAction) self.moveDownSelectedAction = QAction( QIcon(icons + 'multi_down'), 'Move down selected items', self, statusTip='Move currently selected items down by one row', triggered=self.moveDownSelected) queueMenu.addAction(self.moveDownSelectedAction) self.preferencesAction = QAction(QIcon(icons + 'preferences'), 'Preferences', self, statusTip='Preferences', triggered=self.openPreferences, menuRole=5) editMenu.addAction(self.preferencesAction) self.aboutAction = QAction(QIcon(icons + 'about'), 'About', self, statusTip='About', triggered=self.openAbout, menuRole=4) helpMenu.addAction(self.aboutAction) self.issueAction = QAction(QIcon(icons + 'about'), 'Report an issue', self, statusTip='Report an issue', triggered=self.reportIssue) helpMenu.addAction(self.issueAction) self.updateAction = QAction(QIcon(icons + 'about'), 'Check for newer version', self, statusTip='Check for newer release', triggered=self.newUpdate) helpMenu.addAction(self.updateAction) self.logAction = QAction(QIcon(icons + 'about'), 'Show log file', self, statusTip='Help', triggered=self.showLog) helpMenu.addAction(self.logAction) self.helpAction = QAction(QIcon(icons + 'about'), 'Help', self, statusTip='Help', triggered=self.persepolisHelp) helpMenu.addAction(self.helpAction) self.qmenu = MenuWidget(self) self.toolBar2.addWidget(self.qmenu) # labels self.queue_panel_show_button.setText("Hide options") self.start_checkBox.setText("Start Time") self.end_checkBox.setText("End Time") self.reverse_checkBox.setText("Download bottom of\n the list first") self.limit_checkBox.setText("Limit Speed") self.limit_comboBox.setItemText(0, "KB/S") self.limit_comboBox.setItemText(1, "MB/S") self.limit_pushButton.setText("Apply") self.after_checkBox.setText("After download") self.after_comboBox.setItemText(0, "Shut Down") self.keep_awake_checkBox.setText("Keep system awake!") self.keep_awake_checkBox.setToolTip( "<html><head/><body><p>This option is preventing system from going to sleep.\ This is necessary if your power manager is suspending system automatically. </p></body></html>" ) self.after_pushButton.setText("Apply") def changeIcon(self, icons): icons = ':/' + str(icons) + '/' action_icon_dict = { self.stopAllAction: 'stop_all', self.minimizeAction: 'minimize', self.addlinkAction: 'add', self.addtextfileAction: 'file', self.resumeAction: 'play', self.pauseAction: 'pause', self.stopAction: 'stop', self.removeAction: 'remove', self.propertiesAction: 'setting', self.progressAction: 'window', self.openFileAction: 'file', self.openDownloadFolderAction: 'folder', self.deleteFileAction: 'trash', self.openDefaultDownloadFolderAction: 'folder', self.exitAction: 'exit', self.selectAllAction: 'select_all', self.removeSelectedAction: 'multi_remove', self.deleteSelectedAction: 'multi_trash', self.createQueueAction: 'add_queue', self.removeQueueAction: 'remove_queue', self.startQueueAction: 'start_queue', self.stopQueueAction: 'stop_queue', self.moveUpAction: 'up', self.moveDownAction: 'down', self.preferencesAction: 'preferences', self.aboutAction: 'about', self.issueAction: 'about', self.updateAction: 'about', self.qmenu: 'menu' } for key in action_icon_dict.keys(): key.setIcon(QIcon(icons + str(action_icon_dict[key])))
class MainWindow(QMainWindow): """This is the main application window class it defines the GUI window for the browser """ def parse_config(self, file_config, options): self.config = {} options = vars(options) for key, metadata in CONFIG_OPTIONS.items(): options_val = options.get(key) file_val = file_config.get(key) env_val = os.environ.get(metadata.get("env", '')) default_val = metadata.get("default") vals = metadata.get("values") debug("key: {}, default: {}, file: {}, options: {}".format( key, default_val, file_val, options_val)) if vals: options_val = (options_val in vals and options_val) or None file_val = (file_val in vals and file_val) or None env_val = (env_val in vals and env_val) or None if metadata.get("is_file"): filename = options_val or env_val if not filename: self.config[key] = default_val else: try: with open(filename, 'r') as fh: self.config[key] = fh.read() except IOError: debug("Could not open file {} for reading.".format( filename)) self.config[key] = default_val else: set_values = [ val for val in (options_val, env_val, file_val) if val is not None ] if len(set_values) > 0: self.config[key] = set_values[0] else: self.config[key] = default_val if metadata.get("type") and self.config[key]: debug("{} cast to {}".format(key, metadata.get("type"))) self.config[key] = metadata.get("type")(self.config[key]) debug(repr(self.config)) def createAction(self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False, signal="triggered"): """Return a QAction given a number of common QAction attributes Just a shortcut function Originally borrowed from 'Rapid GUI Development with PyQT' by Mark Summerset """ action = QAction(text, self) if icon is not None: action.setIcon( QIcon.fromTheme(icon, QIcon(":/{}.png".format(icon)))) if shortcut is not None and not shortcut.isEmpty(): action.setShortcut(shortcut) tip += " ({})".format(shortcut.toString()) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: action.__getattr__(signal).connect(slot) if checkable: action.setCheckable() return action def __init__(self, options, parent=None): """Construct a MainWindow Object.""" super(MainWindow, self).__init__(parent) # Load config file self.setWindowTitle("Browser") debug("loading configuration from '{}'".format(options.config_file)) configfile = {} if options.config_file: configfile = yaml.safe_load(open(options.config_file, 'r')) self.parse_config(configfile, options) # self.popup will hold a reference to the popup window # if it gets opened self.popup = None # Stylesheet support if self.config.get("stylesheet"): try: with open(self.config.get("stylesheet")) as ss: self.setStyleSheet(ss.read()) except: debug(('Problem loading stylesheet file "{}", ' 'using default style.').format( self.config.get("stylesheet"))) self.setObjectName("global") # Set proxy server environment variable before creating web views if self.config.get("proxy_server"): os.environ["http_proxy"] = self.config.get("proxy_server") os.environ["https_proxy"] = self.config.get("proxy_server") # If the whitelist is activated, add the bookmarks and start_url if self.config.get("whitelist"): # we can just specify whitelist = True, # which should whitelist just the start_url and bookmark urls. if type(self.config.get("whitelist")) is not list: self.whitelist = [] self.whitelist.append( str(QUrl(self.config.get("start_url")).host())) bookmarks = self.config.get("bookmarks") if bookmarks: self.whitelist += [ str(QUrl(b.get("url")).host()) for k, b in bookmarks.items() ] self.whitelist = set(self.whitelist) # uniquify and optimize debug("Generated whitelist: " + str(self.whitelist)) # create the web engine profile self.create_webprofile() # Now construct the UI self.build_ui() # ## END OF CONSTRUCTOR ## # def create_webprofile(self): """Create a webengineprofile to use in all views.""" if self.config.get("privacy_mode"): webprofile = QWebEngineProfile() else: webprofile = QWebEngineProfile.defaultProfile() debug("Browser session is private: {}".format( webprofile.isOffTheRecord())) if self.config.get("user_agent"): webprofile.setHttpUserAgent(self.config["user_agent"]) debug('Set user agent to "{}"'.format(webprofile.httpUserAgent())) self.webprofile = webprofile def build_ui(self): """Set up the user interface for the main window. Unlike the constructor, this method is re-run whenever the browser is "reset" by the user. """ debug("build_ui") inactivity_timeout = self.config.get("timeout") quit_button_tooltip = ("Click here to quit" if self.config.get('quit_button_mode') == 'close' else "Click here when you are done" "\nIt will clear your browsing history" " and return you to the start page.") qb_mode_callbacks = {'close': self.close, 'reset': self.reset_browser} to_mode_callbacks = { 'close': self.close, 'reset': self.reset_browser, 'screensaver': self.screensaver } self.screensaver_active = False # ##Start GUI configuration## # self.browser_window = AdmWebView(self.config, webprofile=self.webprofile) self.browser_window.setObjectName("web_content") self.setCentralWidget(self.browser_window) # Icon theme setting QIcon.setThemeName(self.config.get("icon_theme")) self.setCentralWidget(self.browser_window) debug("loading {}".format(self.config.get("start_url"))) self.browser_window.setUrl(QUrl(self.config.get("start_url"))) # Window size settings window_size = self.config.get("window_size", '').lower() if window_size == 'full': self.showFullScreen() elif window_size == 'max': self.showMaximized() elif window_size: size = re.match(r"(\d+)x(\d+)", window_size) if size: width, height = size.groups() self.setFixedSize(int(width), int(height)) else: debug('Ignoring invalid window size "{}"'.format(window_size)) # Set up the top navigation bar if it's configured to exist if self.config.get("navigation"): self.navigation_bar = QToolBar("Navigation") self.navigation_bar.setObjectName("navigation") self.addToolBar(Qt.TopToolBarArea, self.navigation_bar) self.navigation_bar.setMovable(False) self.navigation_bar.setFloatable(False) # Standard navigation tools self.nav_items = { "back": self.browser_window.pageAction(AdmWebPage.Back), "forward": self.browser_window.pageAction(AdmWebPage.Forward), "refresh": self.browser_window.pageAction(AdmWebPage.Reload), "stop": self.browser_window.pageAction(AdmWebPage.Stop), "quit": self.createAction( self.config.get("quit_button_text"), qb_mode_callbacks.get(self.config.get("quit_button_mode"), self.reset_browser), QKeySequence("Alt+F"), None, quit_button_tooltip), "zoom_in": self.createAction( "Zoom In", self.zoom_in, QKeySequence("Alt++"), "zoom-in", "Increase the size of the text and images on the page"), "zoom_out": self.createAction( "Zoom Out", self.zoom_out, QKeySequence("Alt+-"), "zoom-out", "Decrease the size of text and images on the page") } if self.config.get("allow_printing"): self.nav_items["print"] = self.createAction( "Print", self.browser_window.print_webpage, QKeySequence("Ctrl+p"), "document-print", "Print this page") # Add all the actions to the navigation bar. for item in self.config.get("navigation_layout"): if item == "separator": self.navigation_bar.addSeparator() elif item == "spacer": # an expanding spacer. spacer = QWidget() spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) self.navigation_bar.addWidget(spacer) elif item == "bookmarks": # Insert bookmarks buttons here. self.bookmark_buttons = [] for bookmark in self.config.get("bookmarks", {}).items(): debug("Bookmark:\n" + bookmark.__str__()) # bookmark name will use the "name" attribute, # if present, or else just the key: bookmark_name = bookmark[1].get("name") or bookmark[0] # Create a button for the bookmark as a QAction, # which we'll add to the toolbar button = self.createAction( bookmark_name, (lambda url=bookmark[1].get( "url"): self.browser_window.load(QUrl(url))), QKeySequence.mnemonic(bookmark_name), None, bookmark[1].get("description")) self.navigation_bar.addAction(button) (self.navigation_bar.widgetForAction( button).setObjectName("navigation_button")) else: action = self.nav_items.get(item, None) if action: self.navigation_bar.addAction(action) (self.navigation_bar.widgetForAction( action).setObjectName("navigation_button")) # This removes the ability to toggle off the navigation bar: self.nav_toggle = self.navigation_bar.toggleViewAction() self.nav_toggle.setVisible(False) # End "if show_navigation is True" block # set hidden quit action # For reasons I haven't adequately ascertained, # this shortcut fails now and then claiming # "Ambiguous shortcut overload". # No idea why, as it isn't consistent. self.really_quit = self.createAction("", self.close, QKeySequence("Ctrl+Alt+Q"), None, "") self.addAction(self.really_quit) # Call a reset function after timeout if inactivity_timeout != 0: self.event_filter = InactivityFilter(inactivity_timeout) QCoreApplication.instance().installEventFilter(self.event_filter) self.browser_window.page().installEventFilter(self.event_filter) self.event_filter.timeout.connect( to_mode_callbacks.get(self.config.get("timeout_mode"), self.reset_browser)) else: self.event_filter = None # ##END OF UI SETUP## # def screensaver(self): """Enter "screensaver" mode This method puts the browser in screensaver mode, where a URL is displayed while the browser is idle. Activity causes the browser to return to the home screen. """ debug("screensaver started") self.screensaver_active = True if self.popup: self.popup.close() if self.config.get("navigation"): self.navigation_bar.hide() self.browser_window.setZoomFactor(self.config.get("zoom_factor")) self.browser_window.load(QUrl(self.config.get("screensaver_url"))) self.event_filter.timeout.disconnect() self.event_filter.activity.connect(self.reset_browser) def reset_browser(self): """Clear the history and reset the UI. Called whenever the inactivity filter times out, or when the user clicks the "finished" button in 'reset' mode. """ # Clear out the memory cache #QWebEngineSettings.clearMemoryCaches() self.browser_window.history().clear() # self.navigation_bar.clear() doesn't do its job, # so remove the toolbar first, then rebuild the UI. debug("RESET BROWSER") if self.event_filter: self.event_filter.blockSignals(True) if self.screensaver_active is True: self.screensaver_active = False self.event_filter.activity.disconnect() if self.event_filter: self.event_filter.blockSignals(False) if hasattr(self, "navigation_bar"): self.removeToolBar(self.navigation_bar) self.build_ui() def zoom_in(self): """Zoom in action callback. Note that we cap zooming in at a factor of 3x. """ if self.browser_window.zoomFactor() < 3.0: self.browser_window.setZoomFactor( self.browser_window.zoomFactor() + 0.1) self.nav_items["zoom_out"].setEnabled(True) else: self.nav_items["zoom_in"].setEnabled(False) def zoom_out(self): """Zoom out action callback. Note that we cap zooming out at 0.1x. """ if self.browser_window.zoomFactor() > 0.1: self.browser_window.setZoomFactor( self.browser_window.zoomFactor() - 0.1) self.nav_items["zoom_in"].setEnabled(True) else: self.nav_items["zoom_out"].setEnabled(False)
class AppWindow(QMainWindow): "The application's main window" move_listener = pyqtSignal() db_activity_checker = pyqtSignal() graphics_blur = QGraphicsBlurEffect() def __init__(self): super().__init__() app_constants.GENERAL_THREAD = QThread(self) app_constants.GENERAL_THREAD.finished.connect(app_constants.GENERAL_THREAD.deleteLater) app_constants.GENERAL_THREAD.start() self.setAcceptDrops(True) self.initUI() self.start_up() QTimer.singleShot(3000, self._check_update) self.setFocusPolicy(Qt.NoFocus) self.set_shortcuts() self.graphics_blur.setParent(self) #ex = settings.ExProperties() #d = pewnet.ExHenManager(ex.ipb_id, ex.ipb_pass) #item = d.from_gallery_url('http://exhentai.org/g/861957/02741dc584/') #def a(): print(item.file) #if not item.file: # item.file_rdy.connect(a) #else: # a() def set_shortcuts(self): quit = QShortcut(QKeySequence('Ctrl+Q'), self, self.close) def init_watchers(self): def remove_gallery(g): index = self.manga_list_view.find_index(g.id, True) if index: self.manga_list_view.remove_gallery([index]) def create_gallery(path): g_dia = gallerydialog.GalleryDialog(self, path) g_dia.SERIES.connect(self.manga_list_view.gallery_model.addRows) g_dia.show() def update_gallery(g): index = self.manga_list_view.find_index(g.id) if index: self.manga_list_view.replace_edit_gallery([g], index.row()) else: log_e('Could not find gallery to update from watcher') def created(path): c_popup = io_misc.CreatedPopup(path, self) c_popup.ADD_SIGNAL.connect(create_gallery) def modified(path, gallery): mod_popup = io_misc.ModifiedPopup(path, gallery, self) def deleted(path, gallery): d_popup = io_misc.DeletedPopup(path, gallery, self) d_popup.UPDATE_SIGNAL.connect(update_gallery) d_popup.REMOVE_SIGNAL.connect(remove_gallery) def moved(new_path, gallery): mov_popup = io_misc.MovedPopup(new_path, gallery, self) mov_popup.UPDATE_SIGNAL.connect(update_gallery) self.watchers = io_misc.Watchers() self.watchers.gallery_handler.CREATE_SIGNAL.connect(created) self.watchers.gallery_handler.MODIFIED_SIGNAL.connect(modified) self.watchers.gallery_handler.MOVED_SIGNAL.connect(moved) self.watchers.gallery_handler.DELETED_SIGNAL.connect(deleted) admin_db_method_invoker = pyqtSignal(str) def start_up(self): hello = ["Hello!", "Hi!", "Onii-chan!", "Senpai!", "Hisashiburi!", "Welcome!", "Okaerinasai!", "Welcome back!", "Hajimemashite!"] self.notification_bar.add_text("{} Please don't hesitate to report any bugs you find.".format(hello[random.randint(0, len(hello)-1)])+ " Go to Settings -> About -> Bug Reporting for more info!") level = 5 def normalize_first_time(): settings.set(level, 'Application', 'first time level') settings.save() def done(status=True): gallerydb.DatabaseEmitter.RUN = True if app_constants.FIRST_TIME_LEVEL != level: normalize_first_time() if app_constants.ENABLE_MONITOR and\ app_constants.MONITOR_PATHS and all(app_constants.MONITOR_PATHS): self.init_watchers() if app_constants.LOOK_NEW_GALLERY_STARTUP: if self.manga_list_view.gallery_model.db_emitter.count == app_constants.GALLERY_DATA: self.scan_for_new_galleries() else: self.manga_list_view.gallery_model.db_emitter.DONE.connect(self.scan_for_new_galleries) self.download_manager = pewnet.Downloader() app_constants.DOWNLOAD_MANAGER = self.download_manager self.download_manager.start_manager(4) if app_constants.FIRST_TIME_LEVEL < 4: log_i('Invoking first time level {}'.format(4)) settings.set([], 'Application', 'monitor paths') settings.set([], 'Application', 'ignore paths') app_constants.MONITOR_PATHS = [] app_constants.IGNORE_PATHS = [] settings.save() done() elif app_constants.FIRST_TIME_LEVEL < 5: log_i('Invoking first time level {}'.format(5)) app_widget = misc.ApplicationPopup(self) app_widget.note_info.setText("<font color='red'>IMPORTANT:</font> Application restart is required when done") app_widget.restart_info.hide() self.admin_db = gallerydb.AdminDB() self.admin_db.moveToThread(app_constants.GENERAL_THREAD) self.admin_db.DONE.connect(done) self.admin_db.DONE.connect(lambda: app_constants.NOTIF_BAR.add_text("Application requires a restart")) self.admin_db.DONE.connect(self.admin_db.deleteLater) self.admin_db.DATA_COUNT.connect(app_widget.prog.setMaximum) self.admin_db.PROGRESS.connect(app_widget.prog.setValue) self.admin_db_method_invoker.connect(self.admin_db.rebuild_db) self.admin_db_method_invoker.connect(app_widget.show) app_widget.adjustSize() db_p = os.path.join(os.path.split(database.db_constants.DB_PATH)[0], 'sadpanda.db') self.admin_db_method_invoker.emit(db_p) else: done() def initUI(self): self.center = QWidget() self.display = QStackedLayout() self._main_layout = QVBoxLayout() self._main_layout.setSpacing(0) self._main_layout.setContentsMargins(0,0,0,0) self._main_layout.addLayout(self.display) self.center.setLayout(self._main_layout) # init the manga view variables self.manga_display() log_d('Create manga display: OK') # init the chapter view variables #self.chapter_display() self.m_l_view_index = self.display.addWidget(self.manga_list_view) self.m_t_view_index = self.display.addWidget(self.manga_table_view) self.download_window = io_misc.GalleryDownloader(self) self.download_window.hide() # init toolbar self.init_toolbar() log_d('Create toolbar: OK') # init status bar self.init_stat_bar() log_d('Create statusbar: OK') self.tags_treeview = None if app_constants.TAGS_TREEVIEW_ON_START: def tags_tree_none(): self.tags_treeview = None self.tags_treeview = misc_db.DBOverview(self, True) self.tags_treeview.about_to_close.connect(tags_tree_none) self.tags_treeview.show() self.system_tray = misc.SystemTray(QIcon(app_constants.APP_ICO_PATH), self) app_constants.SYSTEM_TRAY = self.system_tray tray_menu = QMenu(self) self.system_tray.setContextMenu(tray_menu) self.system_tray.setToolTip('Happypanda {}'.format(app_constants.vs)) tray_quit = QAction('Quit', tray_menu) tray_update = tray_menu.addAction('Check for update') tray_update.triggered.connect(self._check_update) tray_menu.addAction(tray_quit) tray_quit.triggered.connect(self.close) self.system_tray.show() def tray_activate(r=None): if not r or r == QSystemTrayIcon.Trigger: self.showNormal() self.activateWindow() self.system_tray.messageClicked.connect(tray_activate) self.system_tray.activated.connect(tray_activate) log_d('Create system tray: OK') #self.display.addWidget(self.chapter_main) self.setCentralWidget(self.center) self.setWindowIcon(QIcon(app_constants.APP_ICO_PATH)) props = settings.win_read(self, 'AppWindow') if props.resize: x, y = props.resize self.resize(x, y) else: self.resize(app_constants.MAIN_W, app_constants.MAIN_H) posx, posy = props.pos self.move(posx, posy) self.init_spinners() self.show() log_d('Show window: OK') self.notification_bar = misc.NotificationOverlay(self) p = self.toolbar.pos() self.notification_bar.move(p.x(), p.y()+self.toolbar.height()) self.notification_bar.resize(self.width()) app_constants.NOTIF_BAR = self.notification_bar log_d('Create notificationbar: OK') log_d('Window Create: OK') def _check_update(self): class upd_chk(QObject): UPDATE_CHECK = pyqtSignal(str) def __init__(self, **kwargs): super().__init__(**kwargs) def fetch_vs(self): import requests import time log_d('Checking Update') time.sleep(1.5) try: if os.path.exists('cacert.pem'): r = requests.get("https://raw.githubusercontent.com/Pewpews/happypanda/master/VS.txt", verify='cacert.pem') else: r = requests.get("https://raw.githubusercontent.com/Pewpews/happypanda/master/VS.txt") a = r.text vs = a.strip() self.UPDATE_CHECK.emit(vs) except: log.exception('Checking Update: FAIL') self.UPDATE_CHECK.emit('this is a very long text which is sure to be over limit') def check_update(vs): log_i('Received version: {}\nCurrent version: {}'.format(vs, app_constants.vs)) if vs != app_constants.vs: if len(vs) < 10: self.notification_bar.begin_show() self.notification_bar.add_text("Version {} of Happypanda is".format(vs)+ " available. Click here to update!", False) self.notification_bar.clicked.connect(lambda: utils.open_web_link( 'https://github.com/Pewpews/happypanda/releases')) self.notification_bar.set_clickable(True) else: self.notification_bar.add_text("An error occurred while checking for new version") self.update_instance = upd_chk() thread = QThread(self) self.update_instance.moveToThread(thread) thread.started.connect(self.update_instance.fetch_vs) self.update_instance.UPDATE_CHECK.connect(check_update) self.update_instance.UPDATE_CHECK.connect(self.update_instance.deleteLater) thread.finished.connect(thread.deleteLater) thread.start() def _web_metadata_picker(self, gallery, title_url_list, queue, parent=None): if not parent: parent = self text = "Which gallery do you want to extract metadata from?" s_gallery_popup = misc.SingleGalleryChoices(gallery, title_url_list, text, parent) s_gallery_popup.USER_CHOICE.connect(queue.put) def get_metadata(self, gal=None): metadata_spinner = misc.Spinner(self) def move_md_spinner(): metadata_spinner.update_move( QPoint( self.pos().x()+self.width()-65, self.pos().y()+self.toolbar.height()+55)) metadata_spinner.set_text("Metadata") metadata_spinner.set_size(55) metadata_spinner.move(QPoint(self.pos().x()+self.width()-65, self.pos().y()+self.toolbar.height()+55)) self.move_listener.connect(move_md_spinner) thread = QThread(self) thread.setObjectName('App.get_metadata') fetch_instance = fetch.Fetch() if gal: if not isinstance(gal, list): galleries = [gal] else: galleries = gal else: if app_constants.CONTINUE_AUTO_METADATA_FETCHER: galleries = [g for g in self.manga_list_view.gallery_model._data if not g.exed] else: galleries = self.manga_list_view.gallery_model._data if not galleries: self.notification_bar.add_text('Looks like we\'ve already gone through all galleries!') return None fetch_instance.galleries = galleries self.notification_bar.begin_show() fetch_instance.moveToThread(thread) def done(status): self.notification_bar.end_show() fetch_instance.deleteLater() if not isinstance(status, bool): galleries = [] for tup in status: galleries.append(tup[0]) class GalleryContextMenu(QMenu): app_instance = self def __init__(self, parent=None): super().__init__(parent) show_in_library_act = self.addAction('Show in library') show_in_library_act.triggered.connect(self.show_in_library) def show_in_library(self): viewer = self.app_instance.manga_list_view index = viewer.find_index(self.gallery_widget.gallery.id, True) if index: self.app_instance.manga_table_view.scroll_to_index(index) self.app_instance.manga_list_view.scroll_to_index(index) g_popup = io_misc.GalleryPopup(('Fecthing metadata for these galleries failed.'+ ' Check happypanda.log for details.', galleries), self, menu=GalleryContextMenu()) #errors = {g[0].id: g[1] for g in status} #for g_item in g_popup.get_all_items(): # g_item.setToolTip(errors[g_item.gallery.id]) g_popup.graphics_blur.setEnabled(False) close_button = g_popup.add_buttons('Close')[0] close_button.clicked.connect(g_popup.close) fetch_instance.GALLERY_PICKER.connect(self._web_metadata_picker) fetch_instance.GALLERY_EMITTER.connect(self.manga_list_view.replace_edit_gallery) fetch_instance.AUTO_METADATA_PROGRESS.connect(self.notification_bar.add_text) thread.started.connect(fetch_instance.auto_web_metadata) fetch_instance.FINISHED.connect(done) fetch_instance.FINISHED.connect(metadata_spinner.close) fetch_instance.FINISHED.connect(lambda: self.move_listener.disconnect(move_md_spinner)) thread.finished.connect(thread.deleteLater) thread.start() metadata_spinner.show() def init_stat_bar(self): self.status_bar = self.statusBar() self.status_bar.setMaximumHeight(20) self.status_bar.setSizeGripEnabled(False) self.stat_info = QLabel() self.stat_info.setIndent(5) self.sort_main = QAction("Asc", self) sort_menu = QMenu() self.sort_main.setMenu(sort_menu) s_by_title = QAction("Title", sort_menu) s_by_artist = QAction("Artist", sort_menu) sort_menu.addAction(s_by_title) sort_menu.addAction(s_by_artist) self.status_bar.addPermanentWidget(self.stat_info) #self.status_bar.addAction(self.sort_main) self.temp_msg = QLabel() self.temp_timer = QTimer() self.manga_list_view.gallery_model.ROWCOUNT_CHANGE.connect(self.stat_row_info) self.manga_list_view.gallery_model.db_emitter.COUNT_CHANGE.connect(self.stat_row_info) self.manga_list_view.gallery_model.STATUSBAR_MSG.connect(self.stat_temp_msg) self.manga_list_view.STATUS_BAR_MSG.connect(self.stat_temp_msg) self.manga_table_view.STATUS_BAR_MSG.connect(self.stat_temp_msg) self.stat_row_info() app_constants.STAT_MSG_METHOD = self.stat_temp_msg def stat_temp_msg(self, msg): self.temp_timer.stop() self.temp_msg.setText(msg) self.status_bar.addWidget(self.temp_msg) self.temp_timer.timeout.connect(self.temp_msg.clear) self.temp_timer.setSingleShot(True) self.temp_timer.start(5000) def stat_row_info(self): r = self.manga_list_view.model().rowCount() t = self.manga_list_view.gallery_model.db_emitter.count self.stat_info.setText("Loaded {} of {} ".format(r, t)) def manga_display(self): "initiates the manga view and related things" #list view self.manga_list_view = gallery.MangaView(self) #table view self.manga_table_view = gallery.MangaTableView(self) self.manga_table_view.gallery_model = self.manga_list_view.gallery_model self.manga_table_view.sort_model = self.manga_list_view.sort_model self.manga_table_view.setModel(self.manga_table_view.sort_model) self.manga_table_view.sort_model.change_model(self.manga_table_view.gallery_model) self.manga_table_view.setColumnWidth(app_constants.FAV, 20) self.manga_table_view.setColumnWidth(app_constants.ARTIST, 200) self.manga_table_view.setColumnWidth(app_constants.TITLE, 400) self.manga_table_view.setColumnWidth(app_constants.TAGS, 300) self.manga_table_view.setColumnWidth(app_constants.TYPE, 60) self.manga_table_view.setColumnWidth(app_constants.CHAPTERS, 60) self.manga_table_view.setColumnWidth(app_constants.LANGUAGE, 100) self.manga_table_view.setColumnWidth(app_constants.LINK, 400) def init_spinners(self): # fetching spinner self.data_fetch_spinner = misc.Spinner(self) self.data_fetch_spinner.set_size(60) self.move_listener.connect( lambda: self.data_fetch_spinner.update_move( QPoint(self.pos().x()+self.width()//2, self.pos().y()+self.height()//2))) self.manga_list_view.gallery_model.ADD_MORE.connect(self.data_fetch_spinner.show) self.manga_list_view.gallery_model.db_emitter.START.connect(self.data_fetch_spinner.show) self.manga_list_view.gallery_model.ADDED_ROWS.connect(self.data_fetch_spinner.before_hide) self.manga_list_view.gallery_model.db_emitter.CANNOT_FETCH_MORE.connect(self.data_fetch_spinner.before_hide) ## deleting spinner #self.gallery_delete_spinner = misc.Spinner(self) #self.gallery_delete_spinner.set_size(40,40) ##self.gallery_delete_spinner.set_text('Removing...') #self.manga_list_view.gallery_model.rowsAboutToBeRemoved.connect(self.gallery_delete_spinner.show) #self.manga_list_view.gallery_model.rowsRemoved.connect(self.gallery_delete_spinner.before_hide) def search(self, srch_string): self.search_bar.setText(srch_string) self.search_backward.setVisible(True) self.manga_list_view.sort_model.init_search(srch_string) old_cursor_pos = self._search_cursor_pos[0] self.search_bar.end(False) if self.search_bar.cursorPosition() != old_cursor_pos+1: self.search_bar.setCursorPosition(old_cursor_pos) def favourite_display(self): "Switches to favourite display" self.manga_table_view.sort_model.fav_view() self.favourite_btn.selected = True self.library_btn.selected = False def catalog_display(self): "Switches to catalog display" self.manga_table_view.sort_model.catalog_view() self.library_btn.selected = True self.favourite_btn.selected = False def settings(self): sett = settingsdialog.SettingsDialog(self) sett.scroll_speed_changed.connect(self.manga_list_view.updateGeometries) #sett.show() def init_toolbar(self): self.toolbar = QToolBar() self.toolbar.setFixedHeight(25) self.toolbar.setWindowTitle("Show") # text for the contextmenu #self.toolbar.setStyleSheet("QToolBar {border:0px}") # make it user defined? self.toolbar.setMovable(False) self.toolbar.setFloatable(False) #self.toolbar.setIconSize(QSize(20,20)) self.toolbar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.toolbar.setIconSize(QSize(20,20)) spacer_start = QWidget() # aligns the first actions properly spacer_start.setFixedSize(QSize(10, 1)) self.toolbar.addWidget(spacer_start) self.favourite_btn = misc.ToolbarButton(self.toolbar, 'Favorites') self.toolbar.addWidget(self.favourite_btn) self.favourite_btn.clicked.connect(self.favourite_display) #need lambda to pass extra args self.library_btn = misc.ToolbarButton(self.toolbar, 'Library') self.toolbar.addWidget(self.library_btn) self.library_btn.clicked.connect(self.catalog_display) #need lambda to pass extra args self.library_btn.selected = True self.toolbar.addSeparator() gallery_menu = QMenu() gallery_action = QToolButton() gallery_action.setText('Gallery ') gallery_action.setPopupMode(QToolButton.InstantPopup) gallery_action.setToolTip('Contains various gallery related features') gallery_action.setMenu(gallery_menu) add_gallery_icon = QIcon(app_constants.PLUS_PATH) gallery_action_add = QAction(add_gallery_icon, "Add single gallery...", self) gallery_action_add.triggered.connect(self.manga_list_view.SERIES_DIALOG.emit) gallery_action_add.setToolTip('Add a single gallery thoroughly') gallery_menu.addAction(gallery_action_add) add_more_action = QAction(add_gallery_icon, "Add galleries...", self) add_more_action.setStatusTip('Add galleries from different folders') add_more_action.triggered.connect(lambda: self.populate(True)) gallery_menu.addAction(add_more_action) populate_action = QAction(add_gallery_icon, "Populate from directory/archive...", self) populate_action.setStatusTip('Populates the DB with galleries from a single folder or archive') populate_action.triggered.connect(self.populate) gallery_menu.addAction(populate_action) gallery_menu.addSeparator() metadata_action = QAction('Get metadata for all galleries', self) metadata_action.triggered.connect(self.get_metadata) gallery_menu.addAction(metadata_action) scan_galleries_action = QAction('Scan for new galleries', self) scan_galleries_action.triggered.connect(self.scan_for_new_galleries) scan_galleries_action.setStatusTip('Scan monitored folders for new galleries') gallery_menu.addAction(scan_galleries_action) gallery_action_random = gallery_menu.addAction("Open random gallery") gallery_action_random.triggered.connect(self.manga_list_view.open_random_gallery) self.toolbar.addWidget(gallery_action) misc_action = QToolButton() misc_action.setText('Tools ') misc_action_menu = QMenu() misc_action.setMenu(misc_action_menu) misc_action.setPopupMode(QToolButton.InstantPopup) misc_action.setToolTip("Contains misc. features") gallery_downloader = QAction("Gallery Downloader", misc_action_menu) gallery_downloader.triggered.connect(self.download_window.show) misc_action_menu.addAction(gallery_downloader) duplicate_check_simple = QAction("Simple Duplicate Finder", misc_action_menu) duplicate_check_simple.triggered.connect(lambda: self.manga_list_view.duplicate_check()) misc_action_menu.addAction(duplicate_check_simple) self.toolbar.addWidget(misc_action) spacer_middle = QWidget() # aligns buttons to the right spacer_middle.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.toolbar.addWidget(spacer_middle) sort_action = QToolButton() sort_action.setIcon(QIcon(app_constants.SORT_PATH)) sort_action.setMenu(misc.SortMenu(self.toolbar, self.manga_list_view)) sort_action.setPopupMode(QToolButton.InstantPopup) self.toolbar.addWidget(sort_action) self.grid_toggle_g_icon = QIcon(app_constants.GRID_PATH) self.grid_toggle_l_icon = QIcon(app_constants.LIST_PATH) self.grid_toggle = QToolButton() if self.display.currentIndex() == self.m_l_view_index: self.grid_toggle.setIcon(self.grid_toggle_l_icon) else: self.grid_toggle.setIcon(self.grid_toggle_g_icon) self.grid_toggle.setObjectName('gridtoggle') self.grid_toggle.clicked.connect(self.toggle_view) self.toolbar.addWidget(self.grid_toggle) spacer_mid2 = QWidget() spacer_mid2.setFixedSize(QSize(5, 1)) self.toolbar.addWidget(spacer_mid2) def set_search_case(b): app_constants.GALLERY_SEARCH_CASE = b settings.set(b, 'Application', 'gallery search case') settings.save() def set_search_strict(b): app_constants.GALLERY_SEARCH_STRICT = b settings.set(b, 'Application', 'gallery search strict') settings.save() self.search_bar = misc.LineEdit() search_options = self.search_bar.addAction(QIcon(app_constants.SEARCH_OPTIONS_PATH), QLineEdit.TrailingPosition) search_options_menu = QMenu(self) search_options.triggered.connect(lambda: search_options_menu.popup(QCursor.pos())) search_options.setMenu(search_options_menu) case_search_option = search_options_menu.addAction('Case Sensitive') case_search_option.setCheckable(True) case_search_option.setChecked(app_constants.GALLERY_SEARCH_CASE) case_search_option.toggled.connect(set_search_case) strict_search_option = search_options_menu.addAction('Match whole terms') strict_search_option.setCheckable(True) strict_search_option.setChecked(app_constants.GALLERY_SEARCH_STRICT) strict_search_option.toggled.connect(set_search_strict) self.search_bar.setObjectName('search_bar') self.search_timer = QTimer(self) self.search_timer.setSingleShot(True) self.search_timer.timeout.connect(lambda: self.search(self.search_bar.text())) self._search_cursor_pos = [0, 0] def set_cursor_pos(old, new): self._search_cursor_pos[0] = old self._search_cursor_pos[1] = new self.search_bar.cursorPositionChanged.connect(set_cursor_pos) if app_constants.SEARCH_AUTOCOMPLETE: completer = QCompleter(self) completer_view = misc.CompleterPopupView() completer.setPopup(completer_view) completer_view._setup() completer.setModel(self.manga_list_view.gallery_model) completer.setCaseSensitivity(Qt.CaseInsensitive) completer.setCompletionMode(QCompleter.PopupCompletion) completer.setCompletionRole(Qt.DisplayRole) completer.setCompletionColumn(app_constants.TITLE) completer.setFilterMode(Qt.MatchContains) self.search_bar.setCompleter(completer) self.search_bar.returnPressed.connect(lambda: self.search(self.search_bar.text())) if not app_constants.SEARCH_ON_ENTER: self.search_bar.textEdited.connect(lambda: self.search_timer.start(800)) self.search_bar.setPlaceholderText("Search title, artist, namespace & tags") self.search_bar.setMinimumWidth(150) self.search_bar.setMaximumWidth(500) self.search_bar.setFixedHeight(19) self.manga_list_view.sort_model.HISTORY_SEARCH_TERM.connect(lambda a: self.search_bar.setText(a)) self.toolbar.addWidget(self.search_bar) def search_history(_, back=True): # clicked signal passes a bool sort_model = self.manga_list_view.sort_model nav = sort_model.PREV if back else sort_model.NEXT history_term = sort_model.navigate_history(nav) if back: self.search_forward.setVisible(True) back = QShortcut(QKeySequence(QKeySequence.Back), self, lambda: search_history(None)) forward = QShortcut(QKeySequence(QKeySequence.Forward), self, lambda: search_history(None, False)) search_backbutton = QToolButton(self.toolbar) search_backbutton.setText(u'\u25C0') search_backbutton.setFixedWidth(15) search_backbutton.clicked.connect(search_history) self.search_backward = self.toolbar.addWidget(search_backbutton) self.search_backward.setVisible(False) search_forwardbutton = QToolButton(self.toolbar) search_forwardbutton.setText(u'\u25B6') search_forwardbutton.setFixedWidth(15) search_forwardbutton.clicked.connect(lambda: search_history(None, False)) self.search_forward = self.toolbar.addWidget(search_forwardbutton) self.search_forward.setVisible(False) spacer_end = QWidget() # aligns settings action properly spacer_end.setFixedSize(QSize(10, 1)) self.toolbar.addWidget(spacer_end) settings_act = QToolButton(self.toolbar) settings_act.setIcon(QIcon(app_constants.SETTINGS_PATH)) settings_act.clicked.connect(self.settings) self.toolbar.addWidget(settings_act) spacer_end2 = QWidget() # aligns About action properly spacer_end2.setFixedSize(QSize(5, 1)) self.toolbar.addWidget(spacer_end2) self.addToolBar(self.toolbar) def toggle_view(self): """ Toggles the current display view """ if self.display.currentIndex() == self.m_l_view_index: self.display.setCurrentIndex(self.m_t_view_index) self.grid_toggle.setIcon(self.grid_toggle_g_icon) else: self.display.setCurrentIndex(self.m_l_view_index) self.grid_toggle.setIcon(self.grid_toggle_l_icon) # TODO: Improve this so that it adds to the gallery dialog, # so user can edit data before inserting (make it a choice) def populate(self, mixed=None): "Populates the database with gallery from local drive'" if mixed: gallery_view = misc.GalleryListView(self, True) gallery_view.SERIES.connect(self.gallery_populate) gallery_view.show() else: msg_box = misc.BasePopup(self) l = QVBoxLayout() msg_box.main_widget.setLayout(l) l.addWidget(QLabel('Directory or Archive?')) l.addLayout(msg_box.buttons_layout) def from_dir(): path = QFileDialog.getExistingDirectory(self, "Choose a directory containing your galleries") if not path: return msg_box.close() app_constants.OVERRIDE_SUBFOLDER_AS_GALLERY = True self.gallery_populate(path, True) def from_arch(): path = QFileDialog.getOpenFileName(self, 'Choose an archive containing your galleries', filter=utils.FILE_FILTER) path = [path[0]] if not all(path) or not path: return msg_box.close() app_constants.OVERRIDE_SUBFOLDER_AS_GALLERY = True self.gallery_populate(path, True) buttons = msg_box.add_buttons('Directory', 'Archive', 'Close') buttons[2].clicked.connect(msg_box.close) buttons[0].clicked.connect(from_dir) buttons[1].clicked.connect(from_arch) msg_box.adjustSize() msg_box.show() def gallery_populate(self, path, validate=False): "Scans the given path for gallery to add into the DB" if len(path) is not 0: data_thread = QThread(self) data_thread.setObjectName('General gallery populate') loading = misc.Loading(self) self.g_populate_inst = fetch.Fetch() self.g_populate_inst.series_path = path loading.show() def finished(status): def hide_loading(): loading.hide() if status: if len(status) != 0: def add_gallery(gallery_list): def append_to_model(x): self.manga_list_view.sort_model.insertRows(x, None, len(x)) self.manga_list_view.sort_model.init_search( self.manga_list_view.sort_model.current_term) class A(QObject): done = pyqtSignal() prog = pyqtSignal(int) def __init__(self, obj, parent=None): super().__init__(parent) self.obj = obj self.galleries = [] def add_to_db(self): for y, x in enumerate(self.obj): gallerydb.add_method_queue( gallerydb.GalleryDB.add_gallery_return, False, x) self.galleries.append(x) y += 1 self.prog.emit(y) append_to_model(self.galleries) self.done.emit() loading.progress.setMaximum(len(gallery_list)) self.a_instance = A(gallery_list) thread = QThread(self) thread.setObjectName('Database populate') def loading_show(numb): if loading.isHidden(): loading.show() loading.setText('Populating database ({}/{})\nPlease wait...'.format( numb, loading.progress.maximum())) loading.progress.setValue(numb) loading.show() def loading_hide(): loading.close() self.manga_list_view.gallery_model.ROWCOUNT_CHANGE.emit() self.a_instance.moveToThread(thread) self.a_instance.prog.connect(loading_show) thread.started.connect(self.a_instance.add_to_db) self.a_instance.done.connect(loading_hide) self.a_instance.done.connect(self.a_instance.deleteLater) #a_instance.add_to_db() thread.finished.connect(thread.deleteLater) thread.start() #data_thread.quit hide_loading() log_i('Populating DB from gallery folder: OK') if validate: gallery_list = misc.GalleryListView(self) gallery_list.SERIES.connect(add_gallery) for ser in status: if ser.is_archive and app_constants.SUBFOLDER_AS_GALLERY: p = os.path.split(ser.path)[1] if ser.chapters[0].path: pt_in_arch = os.path.split(ser.path_in_archive) pt_in_arch = pt_in_arch[1] or pt_in_arch[0] text = '{}: {}'.format(p, pt_in_arch) else: text = p gallery_list.add_gallery(ser, text) else: gallery_list.add_gallery(ser, os.path.split(ser.path)[1]) #self.manga_list_view.gallery_model.populate_data() gallery_list.update_count() gallery_list.show() else: add_gallery(status) else: log_d('No new gallery was found') loading.setText("No new gallery found") #data_thread.quit else: log_e('Populating DB from gallery folder: Nothing was added!') loading.setText("<font color=red>Nothing was added. Check happypanda_log for details..</font>") loading.progress.setStyleSheet("background-color:red;") data_thread.quit QTimer.singleShot(8000, loading.close) def skipped_gs(s_list): "Skipped galleries" msg_box = QMessageBox(self) msg_box.setIcon(QMessageBox.Question) msg_box.setText('Do you want to view skipped paths?') msg_box.setStandardButtons(QMessageBox.Yes | QMessageBox.No) msg_box.setDefaultButton(QMessageBox.No) if msg_box.exec() == QMessageBox.Yes: list_wid = QTableWidget(self) list_wid.setAttribute(Qt.WA_DeleteOnClose) list_wid.setRowCount(len(s_list)) list_wid.setColumnCount(2) list_wid.setAlternatingRowColors(True) list_wid.setEditTriggers(list_wid.NoEditTriggers) list_wid.setHorizontalHeaderLabels(['Reason', 'Path']) list_wid.setSelectionBehavior(list_wid.SelectRows) list_wid.setSelectionMode(list_wid.SingleSelection) list_wid.setSortingEnabled(True) list_wid.verticalHeader().hide() list_wid.setAutoScroll(False) for x, g in enumerate(s_list): list_wid.setItem(x, 0, QTableWidgetItem(g[1])) list_wid.setItem(x, 1, QTableWidgetItem(g[0])) list_wid.resizeColumnsToContents() list_wid.setWindowTitle('{} skipped paths'.format(len(s_list))) list_wid.setWindowFlags(Qt.Window) list_wid.resize(900,400) list_wid.doubleClicked.connect(lambda i: utils.open_path( list_wid.item(i.row(), 1).text(), list_wid.item(i.row(), 1).text())) list_wid.show() def a_progress(prog): loading.progress.setValue(prog) loading.setText("Preparing galleries...") self.g_populate_inst.moveToThread(data_thread) self.g_populate_inst.DATA_COUNT.connect(loading.progress.setMaximum) self.g_populate_inst.PROGRESS.connect(a_progress) self.g_populate_inst.FINISHED.connect(finished) self.g_populate_inst.FINISHED.connect(self.g_populate_inst.deleteLater) self.g_populate_inst.SKIPPED.connect(skipped_gs) data_thread.finished.connect(data_thread.deleteLater) data_thread.started.connect(self.g_populate_inst.local) data_thread.start() #.g_populate_inst.local() log_i('Populating DB from directory/archive') def scan_for_new_galleries(self): available_folders = app_constants.ENABLE_MONITOR and\ app_constants.MONITOR_PATHS and all(app_constants.MONITOR_PATHS) if available_folders and not app_constants.SCANNING_FOR_GALLERIES: app_constants.SCANNING_FOR_GALLERIES = True self.notification_bar.add_text("Scanning for new galleries...") log_i('Scanning for new galleries...') try: class ScanDir(QObject): final_paths_and_galleries = pyqtSignal(list, list) finished = pyqtSignal() def __init__(self, parent=None): super().__init__(parent) self.scanned_data = [] def scan_dirs(self): paths = [] for p in app_constants.MONITOR_PATHS: if os.path.exists(p): dir_content = scandir.scandir(p) for d in dir_content: paths.append(d.path) else: log_e("Monitored path does not exists: {}".format(p.encode(errors='ignore'))) fetch_inst = fetch.Fetch(self) fetch_inst.series_path = paths def set_scanned_d(d): self.scanned_data = d fetch_inst.FINISHED.connect(set_scanned_d) fetch_inst.local() #contents = [] #for g in self.scanned_data: # contents.append(g) #paths = sorted(paths) #new_galleries = [] #for x in contents: # y = utils.b_search(paths, os.path.normcase(x.path)) # if not y: # new_galleries.append(x) galleries = [] final_paths = [] if self.scanned_data: for g in self.scanned_data: try: if g.is_archive: g.profile = utils.get_gallery_img(g.chapters[0].path, g.path) else: g.profile = utils.get_gallery_img(g.chapters[0].path) if not g.profile: raise Exception except: g.profile = app_constants.NO_IMAGE_PATH galleries.append(g) final_paths.append(g.path) self.final_paths_and_galleries.emit(final_paths, galleries) self.finished.emit() self.deleteLater() #if app_constants.LOOK_NEW_GALLERY_AUTOADD: # QTimer.singleShot(10000, self.gallery_populate(final_paths)) # return def show_new_galleries(final_paths, galleries): if final_paths and galleries: app_constants.OVERRIDE_MOVE_IMPORTED_IN_FETCH = True if app_constants.LOOK_NEW_GALLERY_AUTOADD: self.gallery_populate(final_paths) else: class NewGalleryMenu(QMenu): def __init__(self, parent=None): super().__init__(parent) ignore_act = self.addAction('Add to ignore list') ignore_act.triggered.connect(self.add_to_ignore) def add_to_ignore(self): gallery = self.gallery_widget.gallery app_constants.IGNORE_PATHS.append(gallery.path) settings.set(app_constants.IGNORE_PATHS, 'Application', 'ignore paths') if self.gallery_widget.parent_widget.gallery_layout.count() == 1: self.gallery_widget.parent_widget.close() else: self.gallery_widget.close() if len(galleries) == 1: self.notification_bar.add_text("{} new gallery was discovered in one of your monitored directories".format(len(galleries))) else: self.notification_bar.add_text("{} new galleries were discovered in one of your monitored directories".format(len(galleries))) text = "These new galleries were discovered! Do you want to add them?"\ if len(galleries) > 1 else "This new gallery was discovered! Do you want to add it?" g_popup = io_misc.GalleryPopup((text, galleries), self, NewGalleryMenu()) buttons = g_popup.add_buttons('Add', 'Close') def populate_n_close(): g_popup.close() self.gallery_populate(final_paths) buttons[0].clicked.connect(populate_n_close) buttons[1].clicked.connect(g_popup.close) def finished(): app_constants.SCANNING_FOR_GALLERIES = False thread = QThread(self) self.scan_inst = ScanDir() self.scan_inst.moveToThread(thread) self.scan_inst.final_paths_and_galleries.connect(show_new_galleries) self.scan_inst.finished.connect(finished) thread.started.connect(self.scan_inst.scan_dirs) #self.scan_inst.scan_dirs() thread.finished.connect(thread.deleteLater) thread.start() except: self.notification_bar.add_text('An error occured while attempting to scan for new galleries. Check happypanda.log.') log.exception('An error occured while attempting to scan for new galleries.') app_constants.SCANNING_FOR_GALLERIES = False def dragEnterEvent(self, event): if event.mimeData().hasUrls(): event.acceptProposedAction() else: self.notification_bar.add_text('File is not supported') def dropEvent(self, event): acceptable = [] unaccept = [] for u in event.mimeData().urls(): path = u.toLocalFile() if os.path.isdir(path) or path.endswith(utils.ARCHIVE_FILES): acceptable.append(path) else: unaccept.append(path) log_i('Acceptable dropped items: {}'.format(len(acceptable))) log_i('Unacceptable dropped items: {}'.format(len(unaccept))) log_d('Dropped items: {}\n{}'.format(acceptable, unaccept).encode(errors='ignore')) if acceptable: self.notification_bar.add_text('Adding dropped items...') log_i('Adding dropped items') l = len(acceptable) == 1 f_item = acceptable[0] if f_item.endswith(utils.ARCHIVE_FILES): f_item = utils.check_archive(f_item) else: f_item = utils.recursive_gallery_check(f_item) f_item_l = len(f_item) < 2 subfolder_as_c = not app_constants.SUBFOLDER_AS_GALLERY if l and subfolder_as_c or l and f_item_l: g_d = gallerydialog.GalleryDialog(self, acceptable[0]) g_d.SERIES.connect(self.manga_list_view.gallery_model.addRows) g_d.show() else: self.gallery_populate(acceptable, True) else: text = 'File not supported' if len(unaccept) < 2 else 'Files not supported' self.notification_bar.add_text(text) if unaccept: self.notification_bar.add_text('Some unsupported files did not get added') def resizeEvent(self, event): try: self.notification_bar.resize(event.size().width()) except AttributeError: pass self.move_listener.emit() return super().resizeEvent(event) def moveEvent(self, event): self.move_listener.emit() return super().moveEvent(event) def showEvent(self, event): return super().showEvent(event) def cleanup_exit(self): self.system_tray.hide() # watchers try: self.watchers.stop_all() except AttributeError: pass # settings settings.set(self.manga_list_view.current_sort, 'General', 'current sort') settings.set(app_constants.IGNORE_PATHS, 'Application', 'ignore paths') settings.win_save(self, 'AppWindow') # temp dir try: for root, dirs, files in scandir.walk('temp', topdown=False): for name in files: os.remove(os.path.join(root, name)) for name in dirs: os.rmdir(os.path.join(root, name)) log_d('Flush temp on exit: OK') except: log.exception('Flush temp on exit: FAIL') if self.tags_treeview: self.tags_treeview.close() self.download_window.close() # check if there is db activity if not gallerydb.method_queue.empty(): class DBActivityChecker(QObject): FINISHED = pyqtSignal() def __init__(self, **kwargs): super().__init__(**kwargs) def check(self): gallerydb.method_queue.join() self.FINISHED.emit() self.deleteLater() db_activity = DBActivityChecker() db_spinner = misc.Spinner(self) self.db_activity_checker.connect(db_activity.check) db_activity.moveToThread(app_constants.GENERAL_THREAD) db_activity.FINISHED.connect(db_spinner.close) db_spinner.set_size(50) db_spinner.set_text('Activity') db_spinner.move(QPoint(self.pos().x()+self.width()-70, self.pos().y()+self.height()-70)) self.move_listener.connect(lambda: db_spinner.update_move(QPoint(self.pos().x()+self.width()-70, self.pos().y()+self.height()-70))) db_spinner.show() self.db_activity_checker.emit() msg_box = QMessageBox(self) msg_box.setText('Database activity detected!') msg_box.setInformativeText("Closing now might result in data loss." + " Do you still want to close?\n(Wait for the activity spinner to hide before closing)") msg_box.setIcon(QMessageBox.Critical) msg_box.setStandardButtons(QMessageBox.Yes | QMessageBox.No) msg_box.setDefaultButton(QMessageBox.No) if msg_box.exec() == QMessageBox.Yes: return 1 else: return 2 else: return 0 def closeEvent(self, event): r_code = self.cleanup_exit() if r_code == 1: log_d('Force Exit App: OK') super().closeEvent(event) elif r_code == 2: log_d('Ignore Exit App') event.ignore() else: log_d('Normal Exit App: OK') super().closeEvent(event)
def __init__(self, parent): TitledToolbar.__init__(self, parent, 'Block style') self.currentStyle = None toolbar = QToolBar(self) toolbar.setFloatable(False) toolbar.setMovable(False) self.styleToIndex = {} self.styleToDropdown = {} ########################## d1 = IconDropDown(self, ':/icons/format-text-paragraph.png') d1.entrySelected.connect(self.styleSelected) selector = ('para', None, None) d1.addItem("Standard", selector) self.styleToDropdown[selector] = d1 self.styleToIndex[selector] = 0 selector = ('tip', None, None) d1.addItem('Tip', selector) self.styleToDropdown[selector] = d1 self.styleToIndex[selector] = 1 selector = ('warning', None, None) d1.addItem('Warning', selector) self.styleToDropdown[selector] = d1 self.styleToIndex[selector] = 2 selector = ('blockquote', None, None) d1.addItem('Quotation', selector) self.styleToDropdown[selector] = d1 self.styleToIndex[selector] = 3 ########################## d2 = IconDropDown(self, ':/icons/format-text-header.png') d2.entrySelected.connect(self.styleSelected) selector = ('title', 'level', '1') d2.addItem('Title 1', selector) self.styleToDropdown[selector] = d2 self.styleToIndex[selector] = 0 selector = ('title', 'level', '2') d2.addItem('Title 2', selector) self.styleToDropdown[selector] = d2 self.styleToIndex[selector] = 1 selector = ('title', 'level', '3') d2.addItem('Title 3', selector) self.styleToDropdown[selector] = d2 self.styleToIndex[selector] = 2 ########################## d3 = IconDropDown(self, ":/icons/format-list-unordered.png") d3.entrySelected.connect(self.styleSelected) selector = ('itemizedlist', 'level', '1') d3.addItem("Unordered List", selector) self.styleToDropdown[selector] = d3 self.styleToIndex[selector] = 0 selector = ('orderedlist', 'level', '1') d3.addItem("Ordered List", selector) self.styleToDropdown[selector] = d3 self.styleToIndex[selector] = 1 ########################## d4 = IconDropDown(self, ":/icons/format-text-code.png") d4.entrySelected.connect(self.styleSelected) selector = ('programlisting', 'language', 'cpp') d4.addItem("C++", selector) self.styleToDropdown[selector] = d4 self.styleToIndex[selector] = 0 selector = ('programlisting', 'language', 'java') d4.addItem("Java", selector) self.styleToDropdown[selector] = d4 self.styleToIndex[selector] = 1 selector = ('programlisting', 'language', 'python') d4.addItem("Python", selector) self.styleToDropdown[selector] = d4 self.styleToIndex[selector] = 2 selector = ('programlisting', 'language', 'sql') d4.addItem("SQL", selector) self.styleToDropdown[selector] = d4 self.styleToIndex[selector] = 3 selector = ('programlisting', 'language', 'xml') d4.addItem("XML", selector) self.styleToDropdown[selector] = d4 self.styleToIndex[selector] = 4 selector = ('programlisting', 'language', 'bash') d4.addItem("Bash", selector) self.styleToDropdown[selector] = d4 self.styleToIndex[selector] = 5 selector = ('screen', None, None) d4.addItem("Generic", selector) self.styleToDropdown[selector] = d4 self.styleToIndex[selector] = 6 toolbar.addWidget(d1) toolbar.addWidget(d2) toolbar.addWidget(d3) toolbar.addWidget(d4) intendLessAction = QAction(QIcon(":/icons/format-indent-less.png"), "", toolbar) intendLessAction.triggered.connect(self.indentLess) toolbar.addAction(intendLessAction) intendMoreAction = QAction(QIcon(":/icons/format-indent-more.png"), "", toolbar) intendMoreAction.triggered.connect(self.indentMore) toolbar.addAction(intendMoreAction) # Can not currently support tables because the QTextTableCell python # binding is missing methods to traverse the cell contents #insertTableAction = QAction("Table", toolbar) #insertTableAction.triggered.connect(self.insertTable) #toolbar.addAction(insertTableAction) self.addWidget(toolbar)
class MainWindow_Ui(QMainWindow): def __init__(self, persepolis_setting): super().__init__() # MainWindow self.persepolis_setting = persepolis_setting # add support for other languages locale = str(self.persepolis_setting.value('settings/locale')) QLocale.setDefault(QLocale(locale)) self.translator = QTranslator() if self.translator.load(':/translations/locales/ui_' + locale, 'ts'): QCoreApplication.installTranslator(self.translator) # set ui direction ui_direction = self.persepolis_setting.value('ui_direction') if ui_direction == 'rtl': self.setLayoutDirection(Qt.RightToLeft) elif ui_direction in 'ltr': self.setLayoutDirection(Qt.LeftToRight) icons = ':/' + \ str(self.persepolis_setting.value('settings/icons')) + '/' self.setWindowTitle(QCoreApplication.translate("mainwindow_ui_tr", "Persepolis Download Manager")) self.setWindowIcon(QIcon.fromTheme('persepolis', QIcon(':/persepolis.svg'))) self.centralwidget = QWidget(self) self.verticalLayout = QVBoxLayout(self.centralwidget) # enable drag and drop self.setAcceptDrops(True) # frame self.frame = QFrame(self.centralwidget) # download_table_horizontalLayout download_table_horizontalLayout = QHBoxLayout() horizontal_splitter = QSplitter(Qt.Horizontal) vertical_splitter = QSplitter(Qt.Vertical) # category_tree self.category_tree_qwidget = QWidget(self) category_tree_verticalLayout = QVBoxLayout() self.category_tree = CategoryTreeView(self) category_tree_verticalLayout.addWidget(self.category_tree) self.category_tree_model = QStandardItemModel() self.category_tree.setModel(self.category_tree_model) category_table_header = [QCoreApplication.translate("mainwindow_ui_tr", 'Category')] self.category_tree_model.setHorizontalHeaderLabels( category_table_header) self.category_tree.header().setStretchLastSection(True) self.category_tree.header().setDefaultAlignment(Qt.AlignCenter) # queue_panel self.queue_panel_widget = QWidget(self) queue_panel_verticalLayout_main = QVBoxLayout(self.queue_panel_widget) # queue_panel_show_button self.queue_panel_show_button = QPushButton(self) queue_panel_verticalLayout_main.addWidget(self.queue_panel_show_button) # queue_panel_widget_frame self.queue_panel_widget_frame = QFrame(self) self.queue_panel_widget_frame.setFrameShape(QFrame.StyledPanel) self.queue_panel_widget_frame.setFrameShadow(QFrame.Raised) queue_panel_verticalLayout_main.addWidget( self.queue_panel_widget_frame) queue_panel_verticalLayout = QVBoxLayout(self.queue_panel_widget_frame) queue_panel_verticalLayout_main.setContentsMargins(50, -1, 50, -1) # start_end_frame self.start_end_frame = QFrame(self) # start time start_verticalLayout = QVBoxLayout(self.start_end_frame) self.start_checkBox = QCheckBox(self) start_verticalLayout.addWidget(self.start_checkBox) self.start_frame = QFrame(self) self.start_frame.setFrameShape(QFrame.StyledPanel) self.start_frame.setFrameShadow(QFrame.Raised) start_frame_verticalLayout = QVBoxLayout(self.start_frame) self.start_time_qDataTimeEdit = QDateTimeEdit(self.start_frame) self.start_time_qDataTimeEdit.setDisplayFormat('H:mm') start_frame_verticalLayout.addWidget(self.start_time_qDataTimeEdit) start_verticalLayout.addWidget(self.start_frame) # end time self.end_checkBox = QCheckBox(self) start_verticalLayout.addWidget(self.end_checkBox) self.end_frame = QFrame(self) self.end_frame.setFrameShape(QFrame.StyledPanel) self.end_frame.setFrameShadow(QFrame.Raised) end_frame_verticalLayout = QVBoxLayout(self.end_frame) self.end_time_qDateTimeEdit = QDateTimeEdit(self.end_frame) self.end_time_qDateTimeEdit.setDisplayFormat('H:mm') end_frame_verticalLayout.addWidget(self.end_time_qDateTimeEdit) start_verticalLayout.addWidget(self.end_frame) self.reverse_checkBox = QCheckBox(self) start_verticalLayout.addWidget(self.reverse_checkBox) queue_panel_verticalLayout.addWidget(self.start_end_frame) # limit_after_frame self.limit_after_frame = QFrame(self) # limit_checkBox limit_verticalLayout = QVBoxLayout(self.limit_after_frame) self.limit_checkBox = QCheckBox(self) limit_verticalLayout.addWidget(self.limit_checkBox) # limit_frame self.limit_frame = QFrame(self) self.limit_frame.setFrameShape(QFrame.StyledPanel) self.limit_frame.setFrameShadow(QFrame.Raised) limit_verticalLayout.addWidget(self.limit_frame) limit_frame_verticalLayout = QVBoxLayout(self.limit_frame) # limit_spinBox limit_frame_horizontalLayout = QHBoxLayout() self.limit_spinBox = QDoubleSpinBox(self) self.limit_spinBox.setMinimum(1) self.limit_spinBox.setMaximum(1023) limit_frame_horizontalLayout.addWidget(self.limit_spinBox) # limit_comboBox self.limit_comboBox = QComboBox(self) self.limit_comboBox.addItem("") self.limit_comboBox.addItem("") limit_frame_horizontalLayout.addWidget(self.limit_comboBox) limit_frame_verticalLayout.addLayout(limit_frame_horizontalLayout) # limit_pushButton self.limit_pushButton = QPushButton(self) limit_frame_verticalLayout.addWidget(self.limit_pushButton) # after_checkBox self.after_checkBox = QCheckBox(self) limit_verticalLayout.addWidget(self.after_checkBox) # after_frame self.after_frame = QFrame(self) self.after_frame.setFrameShape(QFrame.StyledPanel) self.after_frame.setFrameShadow(QFrame.Raised) limit_verticalLayout.addWidget(self.after_frame) after_frame_verticalLayout = QVBoxLayout(self.after_frame) # after_comboBox self.after_comboBox = QComboBox(self) self.after_comboBox.addItem("") after_frame_verticalLayout.addWidget(self.after_comboBox) # after_pushButton self.after_pushButton = QPushButton(self) after_frame_verticalLayout.addWidget(self.after_pushButton) queue_panel_verticalLayout.addWidget(self.limit_after_frame) category_tree_verticalLayout.addWidget(self.queue_panel_widget) # keep_awake_checkBox self.keep_awake_checkBox = QCheckBox(self) queue_panel_verticalLayout.addWidget(self.keep_awake_checkBox) self.category_tree_qwidget.setLayout(category_tree_verticalLayout) horizontal_splitter.addWidget(self.category_tree_qwidget) # download table widget self.download_table_content_widget = QWidget(self) download_table_content_widget_verticalLayout = QVBoxLayout( self.download_table_content_widget) # download_table self.download_table = DownloadTableWidget(self) vertical_splitter.addWidget(self.download_table) horizontal_splitter.addWidget(self.download_table_content_widget) self.download_table.setColumnCount(13) self.download_table.setSelectionBehavior(QAbstractItemView.SelectRows) self.download_table.setEditTriggers(QAbstractItemView.NoEditTriggers) self.download_table.verticalHeader().hide() # hide gid and download dictioanry section self.download_table.setColumnHidden(8, True) self.download_table.setColumnHidden(9, True) download_table_header = [QCoreApplication.translate("mainwindow_ui_tr", 'File Name'), QCoreApplication.translate("mainwindow_ui_tr",'Status'), QCoreApplication.translate("mainwindow_ui_tr", 'Size'), QCoreApplication.translate("mainwindow_ui_tr", 'Downloaded'), QCoreApplication.translate("mainwindow_ui_tr", 'Percentage'), QCoreApplication.translate("mainwindow_ui_tr", 'Connections'), QCoreApplication.translate("mainwindow_ui_tr", 'Transfer rate'), QCoreApplication.translate("mainwindow_ui_tr",'Estimated time left'), 'Gid', QCoreApplication.translate("mainwindow_ui_tr",'Link'), QCoreApplication.translate("mainwindow_ui_tr", 'First try date'), QCoreApplication.translate("mainwindow_ui_tr", 'Last try date'), QCoreApplication.translate("mainwindow_ui_tr",'Category')] self.download_table.setHorizontalHeaderLabels(download_table_header) # fixing the size of download_table when window is Maximized! self.download_table.horizontalHeader().setSectionResizeMode(0) self.download_table.horizontalHeader().setStretchLastSection(True) horizontal_splitter.setStretchFactor(0, 3) # category_tree width horizontal_splitter.setStretchFactor(1, 10) # ratio of tables's width # video_finder_widget self.video_finder_widget = QWidget(self) video_finder_horizontalLayout = QHBoxLayout(self.video_finder_widget) self.muxing_pushButton = QPushButton(self) self.muxing_pushButton.setIcon(QIcon(icons + 'video_finder')) video_finder_horizontalLayout.addWidget(self.muxing_pushButton) video_finder_horizontalLayout.addSpacing(20) video_audio_verticalLayout = QVBoxLayout() self.video_label = QLabel(self) video_audio_verticalLayout.addWidget(self.video_label) self.audio_label = QLabel(self) video_audio_verticalLayout.addWidget(self.audio_label) video_finder_horizontalLayout.addLayout(video_audio_verticalLayout) status_muxing_verticalLayout = QVBoxLayout() self.video_finder_status_label = QLabel(self) status_muxing_verticalLayout.addWidget(self.video_finder_status_label) self.muxing_status_label = QLabel(self) status_muxing_verticalLayout.addWidget(self.muxing_status_label) video_finder_horizontalLayout.addLayout(status_muxing_verticalLayout) vertical_splitter.addWidget(self.video_finder_widget) download_table_content_widget_verticalLayout.addWidget(vertical_splitter) download_table_horizontalLayout.addWidget(horizontal_splitter) self.frame.setLayout(download_table_horizontalLayout) self.verticalLayout.addWidget(self.frame) self.setCentralWidget(self.centralwidget) # menubar self.menubar = QMenuBar(self) self.menubar.setGeometry(QRect(0, 0, 600, 24)) self.setMenuBar(self.menubar) fileMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", '&File')) editMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", '&Edit')) viewMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", '&View')) downloadMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", '&Download')) queueMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", '&Queue')) videoFinderMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", 'V&ideo Finder')) helpMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", '&Help')) # viewMenu submenus sortMenu = viewMenu.addMenu(QCoreApplication.translate("mainwindow_ui_tr", 'Sort by')) # statusbar self.statusbar = QStatusBar(self) self.setStatusBar(self.statusbar) self.statusbar.showMessage(QCoreApplication.translate("mainwindow_ui_tr", "Persepolis Download Manager")) # toolBar self.toolBar2 = QToolBar(self) self.addToolBar(Qt.TopToolBarArea, self.toolBar2) self.toolBar2.setWindowTitle(QCoreApplication.translate("mainwindow_ui_tr", 'Menu')) self.toolBar2.setFloatable(False) self.toolBar2.setMovable(False) self.toolBar = QToolBar(self) self.addToolBar(Qt.TopToolBarArea, self.toolBar) self.toolBar.setWindowTitle(QCoreApplication.translate("mainwindow_ui_tr", 'Toolbar')) self.toolBar.setFloatable(False) self.toolBar.setMovable(False) #toolBar and menubar and actions self.persepolis_setting.beginGroup('settings/shortcuts') # videoFinderAddLinkAction self.videoFinderAddLinkAction = QAction(QIcon(icons + 'video_finder'), QCoreApplication.translate("mainwindow_ui_tr", 'Find Video Links'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Download video or audio from Youtube, Vimeo, etc...'), triggered=self.showVideoFinderAddLinkWindow) self.videoFinderAddLinkAction_shortcut = QShortcut(self.persepolis_setting.value('video_finder_shortcut'), self, self.showVideoFinderAddLinkWindow) videoFinderMenu.addAction(self.videoFinderAddLinkAction) # stopAllAction self.stopAllAction = QAction(QIcon(icons + 'stop_all'), QCoreApplication.translate("mainwindow_ui_tr", 'Stop all active downloads'), self, statusTip='Stop all active downloads', triggered=self.stopAllDownloads) downloadMenu.addAction(self.stopAllAction) # sort_file_name_Action self.sort_file_name_Action = QAction( QCoreApplication.translate("mainwindow_ui_tr", 'File name'), self, triggered=self.sortByName) sortMenu.addAction(self.sort_file_name_Action) # sort_file_size_Action self.sort_file_size_Action = QAction( QCoreApplication.translate("mainwindow_ui_tr", 'File size'), self, triggered=self.sortBySize) sortMenu.addAction(self.sort_file_size_Action) # sort_first_try_date_Action self.sort_first_try_date_Action = QAction( QCoreApplication.translate("mainwindow_ui_tr", 'First try date'), self, triggered=self.sortByFirstTry) sortMenu.addAction(self.sort_first_try_date_Action) # sort_last_try_date_Action self.sort_last_try_date_Action = QAction( QCoreApplication.translate("mainwindow_ui_tr", 'Last try date'), self, triggered=self.sortByLastTry) sortMenu.addAction(self.sort_last_try_date_Action) # sort_download_status_Action self.sort_download_status_Action = QAction( QCoreApplication.translate("mainwindow_ui_tr", 'Download status'), self, triggered=self.sortByStatus) sortMenu.addAction(self.sort_download_status_Action) # trayAction self.trayAction = QAction(QCoreApplication.translate("mainwindow_ui_tr", 'Show system tray icon'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Show/Hide system tray icon"), triggered=self.showTray) self.trayAction.setCheckable(True) viewMenu.addAction(self.trayAction) # showMenuBarAction self.showMenuBarAction = QAction( QCoreApplication.translate("mainwindow_ui_tr", 'Show menubar'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Show menubar'), triggered=self.showMenuBar) self.showMenuBarAction.setCheckable(True) viewMenu.addAction(self.showMenuBarAction) # showSidePanelAction self.showSidePanelAction = QAction( QCoreApplication.translate("mainwindow_ui_tr", 'Show side panel'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Show side panel'), triggered=self.showSidePanel) self.showSidePanelAction.setCheckable(True) viewMenu.addAction(self.showSidePanelAction) # minimizeAction self.minimizeAction = QAction(QIcon(icons + 'minimize'), QCoreApplication.translate("mainwindow_ui_tr", 'Minimize to system tray'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Minimize to system tray"), triggered=self.minMaxTray) self.minimizeAction_shortcut = QShortcut(self.persepolis_setting.value('hide_window_shortcut'), self, self.minMaxTray) viewMenu.addAction(self.minimizeAction) # addlinkAction self.addlinkAction = QAction(QIcon(icons + 'add'), QCoreApplication.translate("mainwindow_ui_tr", 'Add New Download Link'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Add New Download Link"), triggered=self.addLinkButtonPressed) self.addlinkAction_shortcut = QShortcut(self.persepolis_setting.value('add_new_download_shortcut'), self, self.addLinkButtonPressed) fileMenu.addAction(self.addlinkAction) # importText self.addtextfileAction = QAction(QIcon(icons + 'file'), QCoreApplication.translate("mainwindow_ui_tr", 'Import links from text file'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Create a Text file and put links in it.line by line!'), triggered=self.importText) self.addtextfileAction_shortcut = QShortcut(self.persepolis_setting.value('import_text_shortcut'), self, self.importText) fileMenu.addAction(self.addtextfileAction) # resumeAction self.resumeAction = QAction(QIcon(icons + 'play'), QCoreApplication.translate("mainwindow_ui_tr", 'Resume Download'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Resume Download"), triggered=self.resumeButtonPressed) downloadMenu.addAction(self.resumeAction) # pauseAction self.pauseAction = QAction(QIcon(icons + 'pause'), QCoreApplication.translate("mainwindow_ui_tr", 'Pause Download'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Pause Download"), triggered=self.pauseButtonPressed) downloadMenu.addAction(self.pauseAction) # stopAction self.stopAction = QAction(QIcon(icons + 'stop'), QCoreApplication.translate("mainwindow_ui_tr", 'Stop Download'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Stop/Cancel Download"), triggered=self.stopButtonPressed) downloadMenu.addAction(self.stopAction) # propertiesAction self.propertiesAction = QAction(QIcon(icons + 'setting'), QCoreApplication.translate("mainwindow_ui_tr", 'Properties'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Properties"), triggered=self.propertiesButtonPressed) downloadMenu.addAction(self.propertiesAction) # progressAction self.progressAction = QAction(QIcon(icons + 'window'), QCoreApplication.translate("mainwindow_ui_tr", 'Progress'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Progress"), triggered=self.progressButtonPressed) downloadMenu.addAction(self.progressAction) # openFileAction self.openFileAction = QAction(QIcon( icons + 'file'), QCoreApplication.translate("mainwindow_ui_tr", 'Open file'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Open file'), triggered=self.openFile) fileMenu.addAction(self.openFileAction) # openDownloadFolderAction self.openDownloadFolderAction = QAction(QIcon( icons + 'folder'), QCoreApplication.translate("mainwindow_ui_tr", 'Open download folder'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Open download folder'), triggered=self.openDownloadFolder) fileMenu.addAction(self.openDownloadFolderAction) # openDefaultDownloadFolderAction self.openDefaultDownloadFolderAction = QAction(QIcon( icons + 'folder'), QCoreApplication.translate("mainwindow_ui_tr", 'Open default download folder'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Open default download folder'), triggered=self.openDefaultDownloadFolder) fileMenu.addAction(self.openDefaultDownloadFolderAction) # exitAction self.exitAction = QAction(QIcon(icons + 'exit'), QCoreApplication.translate("mainwindow_ui_tr", 'Exit'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Exit"), triggered=self.closeAction) self.exitAction_shortcut = QShortcut(self.persepolis_setting.value('quit_shortcut'), self, self.closeAction) fileMenu.addAction(self.exitAction) # clearAction self.clearAction = QAction(QIcon(icons + 'multi_remove'), QCoreApplication.translate("mainwindow_ui_tr", 'Clear download list'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Clear all items in download list'), triggered=self.clearDownloadList) editMenu.addAction(self.clearAction) # removeSelectedAction self.removeSelectedAction = QAction(QIcon(icons + 'remove'), QCoreApplication.translate("mainwindow_ui_tr", 'Remove selected downloads from list'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Remove selected downloads form list'), triggered=self.removeSelected) self.removeSelectedAction_shortcut = QShortcut(self.persepolis_setting.value('remove_shortcut'), self, self.removeSelected) editMenu.addAction(self.removeSelectedAction) self.removeSelectedAction.setEnabled(False) # deleteSelectedAction self.deleteSelectedAction = QAction(QIcon(icons + 'trash'), QCoreApplication.translate("mainwindow_ui_tr", 'Delete selected download files'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Delete selected download files'), triggered=self.deleteSelected) self.deleteSelectedAction_shortcut = QShortcut(self.persepolis_setting.value('delete_shortcut'), self, self.deleteSelected) editMenu.addAction(self.deleteSelectedAction) self.deleteSelectedAction.setEnabled(False) # moveSelectedDownloadsAction self.moveSelectedDownloadsAction = QAction(QIcon(icons + 'folder'), QCoreApplication.translate("mainwindow_ui_tr", 'move selected download files to another destination'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'move selected download files to another destination'), triggered=self.moveSelectedDownloads) editMenu.addAction(self.moveSelectedDownloadsAction) self.moveSelectedDownloadsAction.setEnabled(False) # createQueueAction self.createQueueAction = QAction(QIcon(icons + 'add_queue'), QCoreApplication.translate("mainwindow_ui_tr", 'Create new queue'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Create new download queue'), triggered=self.createQueue) queueMenu.addAction(self.createQueueAction) # removeQueueAction self.removeQueueAction = QAction(QIcon(icons + 'remove_queue'), QCoreApplication.translate("mainwindow_ui_tr", 'Remove this queue'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Remove this queue'), triggered=self.removeQueue) queueMenu.addAction(self.removeQueueAction) # startQueueAction self.startQueueAction = QAction(QIcon( icons + 'start_queue'), QCoreApplication.translate("mainwindow_ui_tr", 'Start this queue'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Start this queue'), triggered=self.startQueue) queueMenu.addAction(self.startQueueAction) # stopQueueAction self.stopQueueAction = QAction(QIcon( icons + 'stop_queue'), QCoreApplication.translate("mainwindow_ui_tr", 'Stop this queue'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Stop this queue'), triggered=self.stopQueue) queueMenu.addAction(self.stopQueueAction) # moveUpSelectedAction self.moveUpSelectedAction = QAction(QIcon(icons + 'multi_up'), QCoreApplication.translate("mainwindow_ui_tr", 'Move up selected items'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Move currently selected items up by one row'), triggered=self.moveUpSelected) self.moveUpSelectedAction_shortcut = QShortcut(self.persepolis_setting.value('move_up_selection_shortcut'), self, self.moveUpSelected) queueMenu.addAction(self.moveUpSelectedAction) # moveDownSelectedAction self.moveDownSelectedAction = QAction(QIcon(icons + 'multi_down'), QCoreApplication.translate("mainwindow_ui_tr", 'Move down selected items'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Move currently selected items down by one row'), triggered=self.moveDownSelected) self.moveDownSelectedAction_shortcut = QShortcut(self.persepolis_setting.value('move_down_selection_shortcut'), self, self.moveDownSelected) queueMenu.addAction(self.moveDownSelectedAction) # preferencesAction self.preferencesAction = QAction(QIcon(icons + 'preferences'), QCoreApplication.translate("mainwindow_ui_tr", 'Preferences'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Preferences'), triggered=self.openPreferences, menuRole=5) editMenu.addAction(self.preferencesAction) # aboutAction self.aboutAction = QAction(QIcon( icons + 'about'), QCoreApplication.translate("mainwindow_ui_tr", 'About'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'About'), triggered=self.openAbout, menuRole=4) helpMenu.addAction(self.aboutAction) # issueAction self.issueAction = QAction(QIcon(icons + 'about'), QCoreApplication.translate("mainwindow_ui_tr", 'Report an issue'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Report an issue'), triggered=self.reportIssue) helpMenu.addAction(self.issueAction) # updateAction self.updateAction = QAction(QIcon(icons + 'about'), QCoreApplication.translate("mainwindow_ui_tr", 'Check for newer version'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Check for newer release'), triggered=self.newUpdate) helpMenu.addAction(self.updateAction) # logAction self.logAction = QAction(QIcon(icons + 'about'), QCoreApplication.translate("mainwindow_ui_tr", 'Show log file'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Help'), triggered=self.showLog) helpMenu.addAction(self.logAction) # helpAction self.helpAction = QAction(QIcon(icons + 'about'), QCoreApplication.translate("mainwindow_ui_tr", 'Help'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Help'), triggered=self.persepolisHelp) helpMenu.addAction(self.helpAction) self.persepolis_setting.endGroup() self.qmenu = MenuWidget(self) self.toolBar2.addWidget(self.qmenu) # labels self.queue_panel_show_button.setText(QCoreApplication.translate("mainwindow_ui_tr", "Hide options")) self.start_checkBox.setText(QCoreApplication.translate("mainwindow_ui_tr", "Start Time")) self.end_checkBox.setText(QCoreApplication.translate("mainwindow_ui_tr", "End Time")) self.reverse_checkBox.setText(QCoreApplication.translate("mainwindow_ui_tr", "Download bottom of\n the list first")) self.limit_checkBox.setText(QCoreApplication.translate("mainwindow_ui_tr", "Limit Speed")) self.limit_comboBox.setItemText(0, "KiB/s") self.limit_comboBox.setItemText(1, "MiB/s") self.limit_pushButton.setText(QCoreApplication.translate("mainwindow_ui_tr", "Apply")) self.after_checkBox.setText(QCoreApplication.translate("mainwindow_ui_tr", "After download")) self.after_comboBox.setItemText(0, QCoreApplication.translate("mainwindow_ui_tr", "Shut Down")) self.keep_awake_checkBox.setText(QCoreApplication.translate("mainwindow_ui_tr", "Keep system awake!")) self.keep_awake_checkBox.setToolTip( QCoreApplication.translate("mainwindow_ui_tr", "<html><head/><body><p>This option is preventing system from going to sleep.\ This is necessary if your power manager is suspending system automatically. </p></body></html>")) self.after_pushButton.setText(QCoreApplication.translate("mainwindow_ui_tr", "Apply")) self.muxing_pushButton.setText(QCoreApplication.translate("mainwindow_ui_tr", "start muxing")) self.video_label.setText(QCoreApplication.translate("mainwindow_ui_tr", "<b>Video file status: </b>")) self.audio_label.setText(QCoreApplication.translate("mainwindow_ui_tr", "<b>Audio file status: </b>")) self.video_finder_status_label.setText(QCoreApplication.translate("mainwindow_ui_tr", "<b>Status: </b>")) self.muxing_status_label.setText(QCoreApplication.translate("mainwindow_ui_tr", "<b>Muxing status: </b>"))
class ToolbarUI(object): def __init__(self, main_window: QMainWindow): """ 工具导航 外观模式 :param main_window: """ self.main_window = main_window self.toolbar = QToolBar(self.main_window) # 子类 self.ui_list = [] self.server_start_ui = ServerStartUI(self.toolbar) # 服务器开关 self.file_manager_ui = FileManagerUI(self.toolbar) # 文件管理 self.terminal_ui = TerminalUI(self.toolbar) # 远程终端 self.remote_control_ui = RemoteControlUI(self.toolbar) # 远程控制 self.video_monitor_ui = VideoMonitorUI(self.toolbar) # 视频监控 self.voice_monitor_ui = VoiceMonitorUI(self.toolbar) # 语音监控 self.keyboard_ui = KeyboardUI(self.toolbar) # 键盘记录 self.make_client_ui = MakeClientUI(self.toolbar) # 创建客户端 self.service_manager_ui = ServiceManagerUI(self.toolbar) # 服务管理 self.exit_ui = ExitUI(self.toolbar, self.main_window) # 退出程序 # 子类信号 self.connect_list = [] self.server_start_connect = ServerStartConnect(self.server_start_ui) def options(self) -> None: """ 参数设置 :return: """ self.toolbar.setObjectName("toolBar") # 设置是否可以移动 self.toolbar.setMovable(True) # 设置是否可以悬浮在主窗口 self.toolbar.setFloatable(True) # 设置图标尺寸 self.toolbar.setIconSize(QSize(25, 25)) # 字体在右边 # self.tools_main.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) # 字体在下面 if settings.LOAD_EFFECT_ON: self.toolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) load_animation.load_animation(self.toolbar) # 窗口添加工具导航栏 self.main_window.addToolBar(Qt.TopToolBarArea, self.toolbar) def setup_ui(self) -> None: self.options() if not settings.TOOLBAR_SHOW: self.toolbar.hide() self.load_ui() self.load_connect() self.show_ui() # QDockWidget 位置发生变动 self.toolbar.orientationChanged.connect(self.orientation_changed) def orientation_changed(self, event) -> None: """ 位置变动事件 :param event: :return: """ if event: pass if settings.LOAD_EFFECT_ON: load_animation.load_animation(self.toolbar) # noinspection PyArgumentList def retranslate_ui(self) -> None: self.toolbar.setWindowTitle(_translate("ToolbarUI", "工具导航")) def load_ui(self) -> None: """ 加载模块 :return: """ self.ui_list.append(self.server_start_ui) self.ui_list.append(self.file_manager_ui) self.ui_list.append(self.terminal_ui) self.ui_list.append(self.remote_control_ui) self.ui_list.append(self.video_monitor_ui) self.ui_list.append(self.voice_monitor_ui) self.ui_list.append(self.keyboard_ui) self.ui_list.append(self.make_client_ui) self.ui_list.append(self.service_manager_ui) self.ui_list.append(self.exit_ui) def load_connect(self) -> None: """ 加载 链接信号 :return: """ self.connect_list.append(self.server_start_connect) def show_ui(self) -> None: """ 显示数据 :return: """ all_list = self.ui_list + self.connect_list for item in all_list: item.setup_ui() item.retranslate_ui()
def __init__(self, stampManager, parent = None): super().__init__(parent) self.mTileStampManager = stampManager self.mTileStampModel = stampManager.tileStampModel() self.mProxyModel = QSortFilterProxyModel(self.mTileStampModel) self.mFilterEdit = QLineEdit(self) self.mNewStamp = QAction(self) self.mAddVariation = QAction(self) self.mDuplicate = QAction(self) self.mDelete = QAction(self) self.mChooseFolder = QAction(self) self.setObjectName("TileStampsDock") self.mProxyModel.setSortLocaleAware(True) self.mProxyModel.setSortCaseSensitivity(Qt.CaseInsensitive) self.mProxyModel.setFilterCaseSensitivity(Qt.CaseInsensitive) self.mProxyModel.setSourceModel(self.mTileStampModel) self.mProxyModel.sort(0) self.mTileStampView = TileStampView(self) self.mTileStampView.setModel(self.mProxyModel) self.mTileStampView.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel) self.mTileStampView.header().setStretchLastSection(False) self.mTileStampView.header().setSectionResizeMode(0, QHeaderView.Stretch) self.mTileStampView.header().setSectionResizeMode(1, QHeaderView.ResizeToContents) self.mTileStampView.setContextMenuPolicy(Qt.CustomContextMenu) self.mTileStampView.customContextMenuRequested.connect(self.showContextMenu) self.mNewStamp.setIcon(QIcon(":images/16x16/document-new.png")) self.mAddVariation.setIcon(QIcon(":/images/16x16/add.png")) self.mDuplicate.setIcon(QIcon(":/images/16x16/stock-duplicate-16.png")) self.mDelete.setIcon(QIcon(":images/16x16/edit-delete.png")) self.mChooseFolder.setIcon(QIcon(":images/16x16/document-open.png")) Utils.setThemeIcon(self.mNewStamp, "document-new") Utils.setThemeIcon(self.mAddVariation, "add") Utils.setThemeIcon(self.mDelete, "edit-delete") Utils.setThemeIcon(self.mChooseFolder, "document-open") self.mFilterEdit.setClearButtonEnabled(True) self.mFilterEdit.textChanged.connect(self.mProxyModel.setFilterFixedString) self.mTileStampModel.stampRenamed.connect(self.ensureStampVisible) self.mNewStamp.triggered.connect(self.newStamp) self.mAddVariation.triggered.connect(self.addVariation) self.mDuplicate.triggered.connect(self.duplicate) self.mDelete.triggered.connect(self.delete_) self.mChooseFolder.triggered.connect(self.chooseFolder) self.mDuplicate.setEnabled(False) self.mDelete.setEnabled(False) self.mAddVariation.setEnabled(False) widget = QWidget(self) layout = QVBoxLayout(widget) layout.setContentsMargins(5, 5, 5, 5) buttonContainer = QToolBar() buttonContainer.setFloatable(False) buttonContainer.setMovable(False) buttonContainer.setIconSize(QSize(16, 16)) buttonContainer.addAction(self.mNewStamp) buttonContainer.addAction(self.mAddVariation) buttonContainer.addAction(self.mDuplicate) buttonContainer.addAction(self.mDelete) stretch = QWidget() stretch.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum) buttonContainer.addWidget(stretch) buttonContainer.addAction(self.mChooseFolder) listAndToolBar = QVBoxLayout() listAndToolBar.setSpacing(0) listAndToolBar.addWidget(self.mFilterEdit) listAndToolBar.addWidget(self.mTileStampView) listAndToolBar.addWidget(buttonContainer) layout.addLayout(listAndToolBar) selectionModel = self.mTileStampView.selectionModel() selectionModel.currentRowChanged.connect(self.currentRowChanged) self.setWidget(widget) self.retranslateUi()
class MainWindow(QMainWindow): """ """ def __init__(self): super(MainWindow, self).__init__() self.menu_bar = QMenuBar() self.file_menu = QMenu("文件(&F)", self.menu_bar) self.open_action = QAction("打开(O)", self.file_menu) self.open_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_O)) self.search_action = QAction("搜索(F)", self.file_menu) self.search_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_F)) self.search_action.triggered.connect(self.show_search_widget) self.close_action = QAction("关闭(C)", self.file_menu) self.close_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_C)) self.close_action.triggered.connect(self.answer_close_action_triggered) self.quit_action = QAction("退出(Q)", self.file_menu) self.quit_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_Q)) self.quit_action.triggered.connect(lambda: sys.exit()) self.play_menu = QMenu("播放(&L)", self.menu_bar) self.play_action = QAction("播放(P)", self.play_menu) self.stop_action = QAction("停止(S)", self.play_menu) self.pause_action = QAction("暂停(P)", self.play_menu) self.resume_action = QAction("恢复(R)", self.play_menu) self.rate_action = QAction("倍速(R)", self.play_menu) self.jump_action = QAction("跳转(J)", self.play_menu) self.mute_action = QAction("静音(M)", self.play_menu) self.volume_up_action = QAction("增大音量(U)", self.play_menu) self.volume_down_action = QAction("减小音量(D)", self.play_menu) self.enhance_menu = QMenu("增强(&E)", self.menu_bar) self.skin_menu = QMenu("换肤", self.enhance_menu) self.dark_skin_action = QAction("暗黑模式", self.skin_menu) self.dark_skin_action.setCheckable(True) self.dark_skin_action.triggered.connect( self.answer_dark_skin_action_triggered) self.white_skin_action = QAction("纯白模式", self.skin_menu) self.white_skin_action.setCheckable(True) self.white_skin_action.triggered.connect( self.answer_white_skin_action_triggered) self.blue_skin_action = QAction("浅蓝模式", self.skin_menu) self.blue_skin_action.setCheckable(True) self.blue_skin_action.triggered.connect( self.answer_blue_skin_action_triggered) self.skin_action_group = QActionGroup(self) self.skin_action_group.addAction(self.dark_skin_action) self.skin_action_group.addAction(self.white_skin_action) self.skin_action_group.addAction(self.blue_skin_action) self.language_menu = QMenu("语言", self.enhance_menu) self.zh_CN_action = QAction("简体中文", self.language_menu) self.zh_CN_action.setCheckable(True) self.zh_CN_action.triggered.connect(self.answer_zh_CN_action_triggered) self.en_action = QAction("English", self.language_menu) self.en_action.setCheckable(True) self.en_action.triggered.connect(self.answer_en_action_triggered) self.language_action_group = QActionGroup(self) self.language_action_group.addAction(self.zh_CN_action) self.language_action_group.addAction(self.en_action) self.font_action = QAction("字体(F)", self.enhance_menu) self.font_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_S)) self.font_action.triggered.connect(self.answer_font_action_triggered) self.hide_action = QAction("隐藏(V)", self.enhance_menu) self.hide_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_V)) self.hide_action.setCheckable(True) self.hide_action.triggered.connect(self.answer_hide_action_triggered) self.tool_menu = QMenu("工具(&T)", self.menu_bar) self.screenshot_action = QAction("截图(J)", self.tool_menu) self.screenshot_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_J)) self.screenshot_action.triggered.connect( self.answer_screenshot_action_triggered) self.gif_action = QAction("动图(G)", self.tool_menu) self.gif_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_G)) self.gif_action.triggered.connect(self.answer_gif_action_triggered) self.screen_record_action = QAction("录屏(L)", self.tool_menu) self.screen_record_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_L)) self.screen_record_action.triggered.connect( self.answer_screen_record_action_triggered) self.help_menu = QMenu("帮助(&H)", self.menu_bar) self.help_action = QAction("帮助文档(H)", self.help_menu) self.help_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_H)) self.help_action.triggered.connect(self.answer_help_action_triggered) self.change_log_action = QAction("更新日志(U)", self.help_menu) self.change_log_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_U)) self.change_log_action.triggered.connect( self.answer_change_log_action_triggered) self.check_version_action = QAction("检查版本(C)", self.help_menu) self.check_version_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_C)) self.check_version_action.triggered.connect( self.answer_check_version_action_triggered) self.about_action = QAction("关于软件(A)", self.help_menu) self.about_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_A)) self.about_action.triggered.connect(self.answer_about_action_triggered) self.tool_bar = QToolBar() self.tool_bar.setFloatable(False) self.tool_bar.setMovable(True) self.tool_bar.setIconSize(QSize(32, 32)) # self.tool_bar.setStyleSheet("QToolBar{border: 1px solid #313335; spacing:5px; }") self.addToolBar(Qt.TopToolBarArea, self.tool_bar) self.search_tool_action = QAction("", self.tool_bar) self.search_tool_action.setToolTip("信息搜索") self.search_tool_action.setIcon( QIcon("./resources/img/[email protected]")) self.search_widget = SearchWidget() self.search_tool_action.triggered.connect(self.show_search_widget) self.search_widget.watch_live_signal.connect( self.answer_watch_live_signal) self.attention_tool_action = QAction("", self.tool_bar) self.attention_tool_action.setToolTip("历史关注") self.attention_tool_action.setIcon( QIcon("./resources/img/[email protected]")) # self.attention_tool_action.triggered.connect(self.show_search_widget) self.pure_tool_action = QAction("", self.tool_bar) self.pure_tool_action.setToolTip("纯净模式") self.pure_tool_action.setIcon( QIcon("./resources/img/[email protected]")) # self.pure_tool_action.triggered.connect(self.show_search_widget) self.nlp_tool_action = QAction("", self.tool_bar) self.nlp_tool_action.setToolTip("智能字幕") self.nlp_tool_action.setIcon(QIcon("./resources/img/[email protected]")) # self.nlp_tool_action.triggered.connect(self.show_search_widget) self.note_tool_action = QAction("", self.tool_bar) self.note_tool_action.setToolTip("边看边记") self.note_tool_action.setIcon( QIcon("./resources/img/[email protected]")) # self.note_tool_action.triggered.connect(self.show_search_widget) self.live_widget = LiveWidget() self.init_ui() self._init_cfg() def init_ui(self): """ :return: """ # 菜单栏 self.file_menu.addAction(self.open_action) self.file_menu.addAction(self.search_action) self.file_menu.addSeparator() self.file_menu.addAction(self.close_action) self.file_menu.addAction(self.quit_action) self.play_menu.addAction(self.play_action) self.play_menu.addAction(self.stop_action) self.play_menu.addAction(self.pause_action) self.play_menu.addAction(self.resume_action) self.play_menu.addSeparator() self.play_menu.addAction(self.rate_action) self.play_menu.addAction(self.jump_action) self.play_menu.addSeparator() self.play_menu.addAction(self.mute_action) self.play_menu.addAction(self.volume_up_action) self.play_menu.addAction(self.volume_down_action) self.enhance_menu.addMenu(self.skin_menu) self.skin_menu.addAction(self.dark_skin_action) self.skin_menu.addAction(self.white_skin_action) self.skin_menu.addAction(self.blue_skin_action) self.enhance_menu.addMenu(self.language_menu) self.language_menu.addAction(self.zh_CN_action) self.language_menu.addAction(self.en_action) self.enhance_menu.addAction(self.font_action) self.enhance_menu.addSeparator() self.enhance_menu.addAction(self.hide_action) self.tool_menu.addAction(self.screenshot_action) self.tool_menu.addAction(self.gif_action) self.tool_menu.addAction(self.screen_record_action) self.tool_menu.addSeparator() self.help_menu.addAction(self.help_action) self.help_menu.addAction(self.change_log_action) self.help_menu.addAction(self.check_version_action) self.help_menu.addSeparator() self.help_menu.addAction(self.about_action) self.menu_bar.addMenu(self.file_menu) self.menu_bar.addMenu(self.play_menu) self.menu_bar.addMenu(self.enhance_menu) self.menu_bar.addMenu(self.tool_menu) self.menu_bar.addMenu(self.help_menu) self.setMenuBar(self.menu_bar) # 工具栏 self.tool_bar.addAction(self.search_tool_action) self.tool_bar.addSeparator() self.tool_bar.addAction(self.attention_tool_action) self.tool_bar.addSeparator() self.tool_bar.addAction(self.pure_tool_action) self.tool_bar.addSeparator() self.tool_bar.addAction(self.nlp_tool_action) self.tool_bar.addSeparator() self.tool_bar.addAction(self.note_tool_action) self.tool_bar.addSeparator() # 显示区域 self.setCentralWidget(self.live_widget) self.set_window_info() def _init_cfg(self): """ :return: """ # 工具栏可见性 visible = retrieve_content("preferences", "tool_bar_visible") if visible == "True": self.hide_action.setChecked(False) self.hide_action.triggered.emit(False) else: self.hide_action.setChecked(True) self.hide_action.triggered.emit(True) # 工具栏位置 position = retrieve_content("preferences", "tool_bar_position") # 皮肤设置 skin = retrieve_content("preferences", "skin") if skin == "dark": self.dark_skin_action.setChecked(True) self.dark_skin_action.triggered.emit() elif skin == "white": self.white_skin_action.setChecked(True) self.white_skin_action.triggered.emit() else: self.blue_skin_action.setChecked(True) self.blue_skin_action.triggered.emit() # 字体设置 font_family = retrieve_content("preferences", "font-family") font_style = retrieve_content("preferences", "font-style") font_size = retrieve_content("preferences", "font-size") font = QFont() font.setFamily(font_family) font.setStyleName(font_style) font.setPointSize(int(font_size)) qApp.setFont(font) qApp.processEvents() def set_window_info(self): """ :return: """ desktop_widget = QDesktopWidget() screen_rect = desktop_widget.screenGeometry() self.setGeometry(screen_rect) title = retrieve_content("software_info", "software_name") + " " + retrieve_content( "software_info", "software_version") self.setWindowTitle(title) self.setWindowIcon(QIcon('./resources/img/[email protected]')) self.showMaximized() def show_search_widget(self): """ :return: """ width, height = get_window_center_point(self.search_widget) self.search_widget.move(width, height) self.search_widget.exec_() @staticmethod def answer_help_action_triggered(): """ :return: """ desktop_services = QDesktopServices() desktop_services.openUrl( QUrl( "https://github.com/parzulpan/real-live/blob/master/resources/Help.md" )) @staticmethod def answer_change_log_action_triggered(): """ :return: """ desktop_services = QDesktopServices() desktop_services.openUrl( QUrl( "https://github.com/parzulpan/real-live/blob/master/resources/ChangeLog.md" )) @staticmethod def answer_check_version_action_triggered(): """ :return: """ # TODO: 获取GitHub API 进行检查并弹窗 desktop_services = QDesktopServices() desktop_services.openUrl( QUrl("https://github.com/parzulpan/real-live/releases")) @staticmethod def answer_about_action_triggered(): """ :return: """ about_widget = AboutWidget() width, height = get_window_center_point(about_widget) about_widget.move(width, height) about_widget.exec_() def answer_watch_live_signal(self, url): """ :param url: :return: """ # self.live_widget.vlc_widget.get_player() self.live_widget.vlc_widget.play_url(url) self.live_widget.set_player_widget(True) def answer_close_action_triggered(self): """ :return: """ self.live_widget.set_player_widget(False) # self.live_widget.vlc_widget.get_player() # self.live_widget.vlc_widget.release_player() self.live_widget.vlc_widget.stop() def answer_hide_action_triggered(self, checked): """ :param checked: :return: """ if checked: self.tool_bar.hide() update_contents("preferences", "tool_bar_visible", "False") else: self.tool_bar.show() update_contents("preferences", "tool_bar_visible", "True") def answer_tool_bar_top_level_changed(self, area): """ :return: """ print("top_level_changed") print(area) if self.tool_bar.allowedAreas() == Qt.LeftToolBarArea: print("LeftToolBarArea") elif self.tool_bar.allowedAreas() == Qt.RightToolBarArea: print("RightToolBarArea") elif self.tool_bar.allowedAreas() == Qt.BottomToolBarArea: print("BottomToolBarArea") elif self.tool_bar.allowedAreas() == Qt.TopToolBarArea: print("TopToolBarArea") else: print("else") @staticmethod def answer_screenshot_action_triggered(): """ :return: """ # dll = windll.LoadLibrary('./bin/OEScreenshot.dll') # dll = WinDLL('./bin/OEScreenshot.dll') # dll = cdll.LoadLibrary('./bin/OEScreenshot.dll') dll = CDLL('./bin/screenshot/OEScreenshot.dll') print(dll) def answer_gif_action_triggered(self): """ :return: """ pass def answer_screen_record_action_triggered(self): """ :return: """ pass @staticmethod def answer_dark_skin_action_triggered(checked): """ :param checked: :return: """ with open("./resources/qss/dark.qss", "r", encoding="utf-8") as f: qss = f.read() qApp.setStyleSheet(qss) update_contents("preferences", "skin", "dark") @staticmethod def answer_white_skin_action_triggered(checked): """ :param checked: :return: """ with open("./resources/qss/white.qss", "r", encoding="utf-8") as f: qss = f.read() qApp.setStyleSheet(qss) update_contents("preferences", "skin", "white") @staticmethod def answer_blue_skin_action_triggered(checked): """ :param checked: :return: """ with open("./resources/qss/blue.qss", "r", encoding="utf-8") as f: qss = f.read() qApp.setStyleSheet(qss) update_contents("preferences", "skin", "blue") def answer_font_action_triggered(self, checked): """ :param checked: :return: """ font = qApp.font() font, changed = QFontDialog().getFont(font, self, caption="字体设置") if changed: qApp.setFont(font) qApp.processEvents() update_contents("preferences", "font-family", font.family()) update_contents("preferences", "font-style", font.styleName()) update_contents("preferences", "font-size", str(font.pointSize())) def answer_zh_CN_action_triggered(self, checked): """ :param checked: :return: """ pass def answer_en_action_triggered(self, checked): """ :param checked: :return: """ pass def closeEvent(self, event) -> None: """ :param event: :return: """ print("closeEvent") self.live_widget.vlc_widget.release_player()
class AppWindow(QMainWindow): "The application's main window" def __init__(self): super().__init__() self.initUI() self.start_up() QTimer.singleShot(3000, self._check_update) def init_watchers(self): def remove_gallery(g): index = self.manga_list_view.find_index(g.id) if index: self.manga_list_view.remove_gallery([index]) def create_gallery(path): g_dia = gallerydialog.GalleryDialog(self, path) g_dia.SERIES.connect(self.manga_list_view.gallery_model.addRows) g_dia.show() def update_gallery(g): index = self.manga_list_view.find_index(g.id) if index: self.manga_list_view.replace_edit_gallery([g], index.row()) else: log_e("Could not find gallery to update from Watcher") def created(path): c_popup = file_misc.CreatedPopup(path, self) c_popup.ADD_SIGNAL.connect(create_gallery) def modified(path, gallery): mod_popup = file_misc.ModifiedPopup(path, gallery, self) def deleted(path, gallery): d_popup = file_misc.DeletedPopup(path, gallery, self) d_popup.UPDATE_SIGNAL.connect(update_gallery) d_popup.REMOVE_SIGNAL.connect(remove_gallery) def moved(new_path, gallery): mov_popup = file_misc.MovedPopup(new_path, gallery, self) mov_popup.UPDATE_SIGNAL.connect(update_gallery) self.watchers = file_misc.Watchers() self.watchers.gallery_handler.CREATE_SIGNAL.connect(created) self.watchers.gallery_handler.MODIFIED_SIGNAL.connect(modified) self.watchers.gallery_handler.MOVED_SIGNAL.connect(moved) self.watchers.gallery_handler.DELETED_SIGNAL.connect(deleted) if gui_constants.LOOK_NEW_GALLERY_STARTUP: self.notification_bar.add_text("Looking for new galleries...") try: class ScanDir(QObject): final_paths_and_galleries = pyqtSignal(list, list) def __init__(self, model_data, parent=None): super().__init__(parent) self.model_data = model_data def scan_dirs(self): db_data = self.model_data paths = [] for g in range(len(db_data)): paths.append(os.path.normcase(db_data[g].path)) contents = [] case_path = [] # needed for tile and artist parsing... e.g to avoid lowercase for m_path in gui_constants.MONITOR_PATHS: for p in os.listdir(m_path): abs_p = os.path.join(m_path, p) if os.path.isdir(abs_p) or p.endswith(utils.ARCHIVE_FILES): case_path.append(abs_p) contents.append(os.path.normcase(abs_p)) paths = sorted(paths) new_galleries = [] for c, x in enumerate(contents): y = utils.b_search(paths, x) if not y: # (path, number for case_path) new_galleries.append((x, c)) galleries = [] final_paths = [] if new_galleries: for g in new_galleries: gallery = gallerydb.Gallery() try: gallery.profile = utils.get_gallery_img(g[0]) except: gallery.profile = gui_constants.NO_IMAGE_PATH parser_dict = utils.title_parser(os.path.split(case_path[g[1]])[1]) gallery.title = parser_dict["title"] gallery.artist = parser_dict["artist"] galleries.append(gallery) final_paths.append(case_path[g[1]]) self.final_paths_and_galleries.emit(final_paths, galleries) # if gui_constants.LOOK_NEW_GALLERY_AUTOADD: # QTimer.singleShot(10000, self.gallery_populate(final_paths)) # return def show_new_galleries(final_paths, galleries): if final_paths and galleries: if gui_constants.LOOK_NEW_GALLERY_AUTOADD: self.gallery_populate(final_paths) else: if len(galleries) == 1: self.notification_bar.add_text( "{} new gallery was discovered in one of your monitored directories".format( len(galleries) ) ) else: self.notification_bar.add_text( "{} new galleries were discovered in one of your monitored directories".format( len(galleries) ) ) text = ( "These new galleries were discovered! Do you want to add them?" if len(galleries) > 1 else "This new gallery was discovered! Do you want to add it?" ) g_popup = file_misc.GalleryPopup((text, galleries), self) buttons = g_popup.add_buttons("Add", "Close") def populate_n_close(): self.gallery_populate(final_paths) g_popup.close() buttons[0].clicked.connect(populate_n_close) buttons[1].clicked.connect(g_popup.close) thread = QThread(self) self.scan_inst = ScanDir(self.manga_list_view.gallery_model._data) self.scan_inst.moveToThread(thread) self.scan_inst.final_paths_and_galleries.connect(show_new_galleries) self.scan_inst.final_paths_and_galleries.connect(lambda a: self.scan_inst.deleteLater()) thread.started.connect(self.scan_inst.scan_dirs) thread.finished.connect(thread.deleteLater) thread.start() except: self.notification_bar.add_text( "An error occured while attempting to scan for new galleries. Check happypanda.log." ) log.exception("An error occured while attempting to scan for new galleries.") def start_up(self): def normalize_first_time(): settings.set(2, "Application", "first time level") def done(): self.manga_list_view.gallery_model.init_data() if gui_constants.ENABLE_MONITOR and gui_constants.MONITOR_PATHS and all(gui_constants.MONITOR_PATHS): self.init_watchers() if gui_constants.FIRST_TIME_LEVEL != 2: normalize_first_time() if gui_constants.FIRST_TIME_LEVEL < 2: class FirstTime(file_misc.BasePopup): def __init__(self, parent=None): super().__init__(parent) main_layout = QVBoxLayout() info_lbl = QLabel( "Hi there! Some big changes are about to occur!\n" + "Please wait.. This will take at most a few minutes.\n" + "If not then try restarting the application." ) info_lbl.setAlignment(Qt.AlignCenter) main_layout.addWidget(info_lbl) prog = QProgressBar(self) prog.setMinimum(0) prog.setMaximum(0) prog.setTextVisible(False) main_layout.addWidget(prog) main_layout.addWidget(QLabel("Note: This popup will close itself when everything is ready")) self.main_widget.setLayout(main_layout) ft_widget = FirstTime(self) log_i("Invoking first time level 2") bridge = gallerydb.Bridge() thread = QThread(self) thread.setObjectName("Startup") bridge.moveToThread(thread) thread.started.connect(bridge.rebuild_galleries) bridge.DONE.connect(ft_widget.close) bridge.DONE.connect(self.setEnabled) bridge.DONE.connect(done) bridge.DONE.connect(bridge.deleteLater) thread.finished.connect(thread.deleteLater) thread.start() ft_widget.adjustSize() ft_widget.show() self.setEnabled(False) else: done() def initUI(self): self.center = QWidget() self.display = QStackedLayout() self.center.setLayout(self.display) # init the manga view variables self.manga_display() log_d("Create manga display: OK") # init the chapter view variables # self.chapter_display() self.m_l_view_index = self.display.addWidget(self.manga_list_main) self.m_t_view_index = self.display.addWidget(self.manga_table_view) # init toolbar self.init_toolbar() log_d("Create toolbar: OK") # init status bar self.init_stat_bar() log_d("Create statusbar: OK") self.system_tray = misc.SystemTray(QIcon(gui_constants.APP_ICO_PATH), self) gui_constants.SYSTEM_TRAY = self.system_tray tray_menu = QMenu(self) self.system_tray.setContextMenu(tray_menu) self.system_tray.setToolTip("Happypanda {}".format(gui_constants.vs)) tray_quit = QAction("Quit", tray_menu) tray_menu.addAction(tray_quit) tray_quit.triggered.connect(self.close) self.system_tray.show() log_d("Create system tray: OK") # self.display.addWidget(self.chapter_main) self.setCentralWidget(self.center) self.setWindowTitle("Happypanda") self.setWindowIcon(QIcon(gui_constants.APP_ICO_PATH)) props = settings.win_read(self, "AppWindow") if props.resize: x, y = props.resize self.resize(x, y) else: self.resize(gui_constants.MAIN_W, gui_constants.MAIN_H) posx, posy = props.pos self.move(posx, posy) self.show() log_d("Show window: OK") self.notification_bar = misc.NotificationOverlay(self) p = self.toolbar.pos() self.notification_bar.move(p.x(), p.y() + self.toolbar.height()) self.notification_bar.resize(self.width()) gui_constants.NOTIF_BAR = self.notification_bar log_d("Create notificationbar: OK") log_d("Window Create: OK") def _check_update(self): class upd_chk(QObject): UPDATE_CHECK = pyqtSignal(str) def __init__(self, **kwargs): super().__init__(**kwargs) def fetch_vs(self): import requests import time try: log_d("Checking Update") time.sleep(1.5) r = requests.get( "https://raw.githubusercontent.com/Pewpews/happypanda/master/VS.txt", verify="cacert.pem" ) a = r.text vs = a.strip() self.UPDATE_CHECK.emit(vs) except: log.exception("Checking Update: FAIL") self.UPDATE_CHECK.emit("this is a very long text which is is sure to be over limit") def check_update(vs): log_i("Received version: {}\nCurrent version: {}".format(vs, gui_constants.vs)) if vs != gui_constants.vs: if len(vs) < 10: self.notification_bar.add_text( "Version {} of Happypanda is".format(vs) + " available. Click here to update!", False ) self.notification_bar.clicked.connect( lambda: utils.open_web_link("https://github.com/Pewpews/happypanda/releases") ) self.notification_bar.set_clickable(True) else: self.notification_bar.add_text("An error occurred while checking for new version") self.update_instance = upd_chk() thread = QThread(self) self.update_instance.moveToThread(thread) thread.started.connect(self.update_instance.fetch_vs) self.update_instance.UPDATE_CHECK.connect(check_update) self.update_instance.UPDATE_CHECK.connect(self.update_instance.deleteLater) thread.finished.connect(thread.deleteLater) thread.start() def _web_metadata_picker(self, gallery, title_url_list, queue, parent=None): if not parent: parent = self text = "Which gallery do you want to extract metadata from?" s_gallery_popup = misc.SingleGalleryChoices(gallery, title_url_list, text, parent) s_gallery_popup.USER_CHOICE.connect(queue.put) def get_metadata(self, gal=None): thread = QThread(self) thread.setObjectName("App.get_metadata") fetch_instance = fetch.Fetch() if gal: galleries = [gal] else: if gui_constants.CONTINUE_AUTO_METADATA_FETCHER: galleries = [g for g in self.manga_list_view.gallery_model._data if not g.exed] else: galleries = self.manga_list_view.gallery_model._data if not galleries: self.notification_bar.add_text("Looks like we've already gone through all galleries!") return None fetch_instance.galleries = galleries self.notification_bar.begin_show() fetch_instance.moveToThread(thread) def done(status): self.notification_bar.end_show() fetch_instance.deleteLater() fetch_instance.GALLERY_PICKER.connect(self._web_metadata_picker) fetch_instance.GALLERY_EMITTER.connect(self.manga_list_view.replace_edit_gallery) fetch_instance.AUTO_METADATA_PROGRESS.connect(self.notification_bar.add_text) thread.started.connect(fetch_instance.auto_web_metadata) fetch_instance.FINISHED.connect(done) thread.finished.connect(thread.deleteLater) thread.start() # def style_tooltip(self): # palette = QToolTip.palette() # palette.setColor() def init_stat_bar(self): self.status_bar = self.statusBar() self.status_bar.setMaximumHeight(20) self.status_bar.setSizeGripEnabled(False) self.stat_info = QLabel() self.stat_info.setIndent(5) self.sort_main = QAction("Asc", self) sort_menu = QMenu() self.sort_main.setMenu(sort_menu) s_by_title = QAction("Title", sort_menu) s_by_artist = QAction("Artist", sort_menu) sort_menu.addAction(s_by_title) sort_menu.addAction(s_by_artist) self.status_bar.addPermanentWidget(self.stat_info) # self.status_bar.addAction(self.sort_main) self.temp_msg = QLabel() self.temp_timer = QTimer() self.manga_list_view.gallery_model.ROWCOUNT_CHANGE.connect(self.stat_row_info) self.manga_list_view.gallery_model.STATUSBAR_MSG.connect(self.stat_temp_msg) self.manga_list_view.STATUS_BAR_MSG.connect(self.stat_temp_msg) self.manga_table_view.STATUS_BAR_MSG.connect(self.stat_temp_msg) self.stat_row_info() def stat_temp_msg(self, msg): self.temp_timer.stop() self.temp_msg.setText(msg) self.status_bar.addWidget(self.temp_msg) self.temp_timer.timeout.connect(self.temp_msg.clear) self.temp_timer.setSingleShot(True) self.temp_timer.start(5000) def stat_row_info(self): r = self.manga_list_view.model().rowCount() t = self.manga_list_view.gallery_model._data_count self.stat_info.setText("Loaded {} of {} ".format(r, t)) def manga_display(self): "initiates the manga view" # list view self.manga_list_main = QWidget() # self.manga_list_main.setContentsMargins(-10, -12, -10, -10) self.manga_list_main.setContentsMargins(10, -9, -10, -10) # x, y, inverted_width, inverted_height self.manga_list_layout = QHBoxLayout() self.manga_list_main.setLayout(self.manga_list_layout) self.manga_list_view = gallery.MangaView(self) self.manga_list_view.clicked.connect(self.popup) self.manga_list_view.manga_delegate.POPUP.connect(self.popup) self.popup_window = self.manga_list_view.manga_delegate.popup_window self.manga_list_layout.addWidget(self.manga_list_view) # table view self.manga_table_main = QWidget() self.manga_table_layout = QVBoxLayout() self.manga_table_main.setLayout(self.manga_table_layout) self.manga_table_view = gallery.MangaTableView(self) self.manga_table_view.gallery_model = self.manga_list_view.gallery_model self.manga_table_view.sort_model = self.manga_list_view.sort_model self.manga_table_view.setModel(self.manga_table_view.sort_model) self.manga_table_view.sort_model.change_model(self.manga_table_view.gallery_model) self.manga_table_view.setColumnWidth(gui_constants.FAV, 20) self.manga_table_view.setColumnWidth(gui_constants.ARTIST, 200) self.manga_table_view.setColumnWidth(gui_constants.TITLE, 400) self.manga_table_view.setColumnWidth(gui_constants.TAGS, 300) self.manga_table_view.setColumnWidth(gui_constants.TYPE, 60) self.manga_table_view.setColumnWidth(gui_constants.CHAPTERS, 60) self.manga_table_view.setColumnWidth(gui_constants.LANGUAGE, 100) self.manga_table_view.setColumnWidth(gui_constants.LINK, 400) self.manga_table_layout.addWidget(self.manga_table_view) def search(self, srch_string): case_ins = srch_string.lower() if not gui_constants.ALLOW_SEARCH_REGEX: remove = "^$*+?{}\\|()[]" for x in remove: if x == "[" or x == "]": continue else: case_ins = case_ins.replace(x, ".") else: try: re.compile(case_ins) except re.error: return self.manga_list_view.sort_model.search(case_ins) def popup(self, index): if not self.popup_window.isVisible(): m_x = QCursor.pos().x() m_y = QCursor.pos().y() d_w = QDesktopWidget().width() d_h = QDesktopWidget().height() p_w = gui_constants.POPUP_WIDTH p_h = gui_constants.POPUP_HEIGHT index_rect = self.manga_list_view.visualRect(index) index_point = self.manga_list_view.mapToGlobal(index_rect.topRight()) # adjust so it doesn't go offscreen if d_w - m_x < p_w and d_h - m_y < p_h: # bottom self.popup_window.move(m_x - p_w + 5, m_y - p_h) elif d_w - m_x > p_w and d_h - m_y < p_h: self.popup_window.move(m_x + 5, m_y - p_h) elif d_w - m_x < p_w: self.popup_window.move(m_x - p_w + 5, m_y + 5) else: self.popup_window.move(index_point) self.popup_window.set_gallery(index.data(Qt.UserRole + 1)) self.popup_window.show() def favourite_display(self): "Switches to favourite display" if self.display.currentIndex() == self.m_l_view_index: self.manga_list_view.sort_model.fav_view() else: self.manga_table_view.sort_model.fav_view() def catalog_display(self): "Switches to catalog display" if self.display.currentIndex() == self.m_l_view_index: self.manga_list_view.sort_model.catalog_view() else: self.manga_table_view.sort_model.catalog_view() def settings(self): sett = settingsdialog.SettingsDialog(self) sett.scroll_speed_changed.connect(self.manga_list_view.updateGeometries) # sett.show() def init_toolbar(self): self.toolbar = QToolBar() self.toolbar.setFixedHeight(25) self.toolbar.setWindowTitle("Show") # text for the contextmenu # self.toolbar.setStyleSheet("QToolBar {border:0px}") # make it user defined? self.toolbar.setMovable(False) self.toolbar.setFloatable(False) # self.toolbar.setIconSize(QSize(20,20)) self.toolbar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) spacer_start = QWidget() # aligns the first actions properly spacer_start.setFixedSize(QSize(10, 1)) self.toolbar.addWidget(spacer_start) favourite_view_icon = QIcon(gui_constants.STAR_BTN_PATH) favourite_view_action = QAction(favourite_view_icon, "Favorites", self) favourite_view_action.setToolTip("Show only favourite galleries") favourite_view_action.triggered.connect(self.favourite_display) # need lambda to pass extra args self.toolbar.addAction(favourite_view_action) catalog_view_icon = QIcon(gui_constants.HOME_BTN_PATH) catalog_view_action = QAction(catalog_view_icon, "Library", self) catalog_view_action.setToolTip("Show all your galleries") # catalog_view_action.setText("Catalog") catalog_view_action.triggered.connect(self.catalog_display) # need lambda to pass extra args self.toolbar.addAction(catalog_view_action) self.toolbar.addSeparator() gallery_menu = QMenu() gallery_action = QToolButton() gallery_action.setText("Gallery ") gallery_action.setPopupMode(QToolButton.InstantPopup) gallery_action.setToolTip("Contains various gallery related features") gallery_action.setMenu(gallery_menu) add_gallery_icon = QIcon(gui_constants.PLUS_PATH) gallery_action_add = QAction(add_gallery_icon, "Add gallery", self) gallery_action_add.triggered.connect(self.manga_list_view.SERIES_DIALOG.emit) gallery_action_add.setToolTip("Add a single gallery thoroughly") gallery_menu.addAction(gallery_action_add) add_more_action = QAction(add_gallery_icon, "Add galleries...", self) add_more_action.setStatusTip("Add galleries from different folders") add_more_action.triggered.connect(lambda: self.populate(True)) gallery_menu.addAction(add_more_action) populate_action = QAction(add_gallery_icon, "Populate from folder...", self) populate_action.setStatusTip("Populates the DB with galleries from a single folder") populate_action.triggered.connect(self.populate) gallery_menu.addAction(populate_action) gallery_menu.addSeparator() metadata_action = QAction("Get metadata for all galleries", self) metadata_action.triggered.connect(self.get_metadata) gallery_menu.addAction(metadata_action) self.toolbar.addWidget(gallery_action) self.toolbar.addSeparator() misc_action = QToolButton() misc_action.setText("Misc ") misc_action_menu = QMenu() misc_action.setMenu(misc_action_menu) misc_action.setPopupMode(QToolButton.InstantPopup) misc_action.setToolTip("Contains misc. features") misc_action_random = QAction("Open random gallery", misc_action_menu) misc_action_random.triggered.connect(self.manga_list_view.open_random_gallery) misc_action_menu.addAction(misc_action_random) duplicate_check_simple = QAction("Simple duplicate finder", misc_action_menu) duplicate_check_simple.triggered.connect(lambda: self.manga_list_view.duplicate_check()) misc_action_menu.addAction(duplicate_check_simple) self.toolbar.addWidget(misc_action) spacer_middle = QWidget() # aligns buttons to the right spacer_middle.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.toolbar.addWidget(spacer_middle) self.grid_toggle_g_icon = QIcon(gui_constants.GRID_PATH) self.grid_toggle_l_icon = QIcon(gui_constants.LIST_PATH) self.grid_toggle = QToolButton() if self.display.currentIndex() == self.m_l_view_index: self.grid_toggle.setIcon(self.grid_toggle_l_icon) else: self.grid_toggle.setIcon(self.grid_toggle_g_icon) self.grid_toggle.setObjectName("gridtoggle") self.grid_toggle.clicked.connect(self.toggle_view) self.toolbar.addWidget(self.grid_toggle) self.search_bar = misc.LineEdit() if gui_constants.SEARCH_AUTOCOMPLETE: completer = QCompleter(self) completer.setModel(self.manga_list_view.gallery_model) completer.setCaseSensitivity(Qt.CaseInsensitive) completer.setCompletionMode(QCompleter.PopupCompletion) completer.setCompletionRole(Qt.DisplayRole) completer.setCompletionColumn(gui_constants.TITLE) completer.setFilterMode(Qt.MatchContains) self.search_bar.setCompleter(completer) if gui_constants.SEARCH_ON_ENTER: self.search_bar.returnPressed.connect(lambda: self.search(self.search_bar.text())) else: self.search_bar.textChanged[str].connect(self.search) self.search_bar.setPlaceholderText("Search title, artist, namespace & tags") self.search_bar.setMinimumWidth(150) self.search_bar.setMaximumWidth(500) self.toolbar.addWidget(self.search_bar) self.toolbar.addSeparator() settings_icon = QIcon(gui_constants.SETTINGS_PATH) settings_action = QAction("Set&tings", self) settings_action.triggered.connect(self.settings) self.toolbar.addAction(settings_action) spacer_end = QWidget() # aligns About action properly spacer_end.setFixedSize(QSize(10, 1)) self.toolbar.addWidget(spacer_end) self.addToolBar(self.toolbar) def toggle_view(self): """ Toggles the current display view """ if self.display.currentIndex() == self.m_l_view_index: self.display.setCurrentIndex(self.m_t_view_index) self.grid_toggle.setIcon(self.grid_toggle_g_icon) else: self.display.setCurrentIndex(self.m_l_view_index) self.grid_toggle.setIcon(self.grid_toggle_l_icon) # TODO: Improve this so that it adds to the gallery dialog, # so user can edit data before inserting (make it a choice) def populate(self, mixed=None): "Populates the database with gallery from local drive'" if mixed: gallery_view = misc.GalleryListView(self, True) gallery_view.SERIES.connect(self.gallery_populate) gallery_view.show() else: path = QFileDialog.getExistingDirectory(None, "Choose a folder containing your galleries") self.gallery_populate(path, True) def gallery_populate(self, path, validate=False): "Scans the given path for gallery to add into the DB" if len(path) is not 0: data_thread = QThread(self) data_thread.setObjectName("General gallery populate") loading = misc.Loading(self) if not loading.ON: misc.Loading.ON = True fetch_instance = fetch.Fetch() fetch_instance.series_path = path loading.show() def finished(status): def hide_loading(): loading.hide() if status: if len(status) != 0: def add_gallery(gallery_list): def append_to_model(x): self.manga_list_view.gallery_model.insertRows(x, None, len(x)) class A(QObject): done = pyqtSignal() prog = pyqtSignal(int) def __init__(self, obj, parent=None): super().__init__(parent) self.obj = obj self.galleries = [] def add_to_db(self): gui_constants.NOTIF_BAR.begin_show() gui_constants.NOTIF_BAR.add_text("Populating database...") for y, x in enumerate(self.obj): gui_constants.NOTIF_BAR.add_text( "Populating database {}/{}".format(y + 1, len(self.obj)) ) gallerydb.add_method_queue(gallerydb.GalleryDB.add_gallery_return, False, x) self.galleries.append(x) y += 1 self.prog.emit(y) append_to_model(self.galleries) gui_constants.NOTIF_BAR.end_show() self.done.emit() loading.progress.setMaximum(len(gallery_list)) a_instance = A(gallery_list) thread = QThread(self) thread.setObjectName("Database populate") def loading_show(): loading.setText("Populating database.\nPlease wait...") loading.show() def loading_hide(): loading.close() self.manga_list_view.gallery_model.ROWCOUNT_CHANGE.emit() def del_later(): try: a_instance.deleteLater() except NameError: pass a_instance.moveToThread(thread) a_instance.prog.connect(loading.progress.setValue) thread.started.connect(loading_show) thread.started.connect(a_instance.add_to_db) a_instance.done.connect(loading_hide) a_instance.done.connect(del_later) thread.finished.connect(thread.deleteLater) thread.start() data_thread.quit hide_loading() log_i("Populating DB from gallery folder: OK") if validate: gallery_list = misc.GalleryListView(self) gallery_list.SERIES.connect(add_gallery) for ser in status: gallery_list.add_gallery(ser, os.path.split(ser.path)[1]) # self.manga_list_view.gallery_model.populate_data() gallery_list.show() else: add_gallery(status) misc.Loading.ON = False else: log_d("No new gallery was found") loading.setText("No new gallery found") data_thread.quit misc.Loading.ON = False else: log_e("Populating DB from gallery folder: Nothing was added!") loading.setText("<font color=red>Nothing was added. Check happypanda_log for details..</font>") loading.progress.setStyleSheet("background-color:red;") data_thread.quit QTimer.singleShot(10000, loading.close) def fetch_deleteLater(): try: fetch_instance.deleteLater except NameError: pass def a_progress(prog): loading.progress.setValue(prog) loading.setText("Searching for galleries...") fetch_instance.moveToThread(data_thread) fetch_instance.DATA_COUNT.connect(loading.progress.setMaximum) fetch_instance.PROGRESS.connect(a_progress) data_thread.started.connect(fetch_instance.local) fetch_instance.FINISHED.connect(finished) fetch_instance.FINISHED.connect(fetch_deleteLater) data_thread.finished.connect(data_thread.deleteLater) data_thread.start() log_i("Populating DB from gallery folder") def resizeEvent(self, event): try: self.notification_bar.resize(event.size().width()) except AttributeError: pass return super().resizeEvent(event) def closeEvent(self, event): # watchers try: self.watchers.stop_all() except AttributeError: pass # settings settings.set(self.manga_list_view.current_sort, "General", "current sort") settings.win_save(self, "AppWindow") # temp dir try: for root, dirs, files in os.walk("temp", topdown=False): for name in files: os.remove(os.path.join(root, name)) for name in dirs: os.rmdir(os.path.join(root, name)) log_d("Empty temp on exit: OK") except: log_d("Empty temp on exit: FAIL") # error err = sys.exc_info() if all(err): log_c("Last error before exit:\n{}\n{}\n{}".format(err[0], err[1], err[2])) else: log_d("Normal Exit App: OK") super().closeEvent(event) app = QApplication.instance() app.quit() sys.exit()
class MainWindow_Ui(QMainWindow): def __init__(self): super().__init__() #MainWindow self.resize(600, 400) self.setMinimumSize(QSize(600, 400)) self.setMaximumSize(QSize(16777215, 16777215)) self.setWindowTitle("Persepolis Download Manager") self.setWindowIcon(QIcon.fromTheme('persepolis', QIcon(':/icon.svg'))) self.centralwidget = QWidget(self) self.verticalLayout = QVBoxLayout(self.centralwidget) #enable drag and drop self.setAcceptDrops(True) #frame self.frame = QFrame(self.centralwidget) self.frame.setGeometry(QRect(10, 10, 581, 251)) self.frame.setFrameShape(QFrame.StyledPanel) self.frame.setFrameShadow(QFrame.Raised) self.gridLayout = QGridLayout(self.frame) #tablewidget self.download_table = QTableWidget(self.frame) self.download_table.setGeometry(QRect(10, 10, 560, 231)) self.download_table.setSizeIncrement(QSize(0, 0)) self.download_table.setColumnCount(10) self.download_table.setSelectionBehavior(QAbstractItemView.SelectRows) self.download_table.setEditTriggers(QAbstractItemView.NoEditTriggers) self.download_table.verticalHeader().hide() #hide gid and download dictioanry section self.download_table.setColumnHidden(8, True) self.download_table.setColumnHidden(9, True) self.gridLayout.addWidget(self.download_table, 0, 0, 1, 1) self.verticalLayout.addWidget(self.frame) self.setCentralWidget(self.centralwidget) download_table_header = [ 'File Name', 'Status', 'Size', 'Downloaded', 'Percentage', 'Connections', 'Transfer rate', 'Estimate time left', 'Gid', 'Info' ] self.download_table.setHorizontalHeaderLabels(download_table_header) #fixing the size of download_table when window is Maximized! self.download_table.horizontalHeader().setSectionResizeMode(0) self.download_table.horizontalHeader().setStretchLastSection(True) #finding number od row that user selected! self.download_table.itemSelectionChanged.connect(self.selectedRow) #menubar self.menubar = QMenuBar(self) self.menubar.setGeometry(QRect(0, 0, 600, 24)) self.setMenuBar(self.menubar) fileMenu = self.menubar.addMenu('File') editMenu = self.menubar.addMenu('Edit') viewMenu = self.menubar.addMenu('View') downloadMenu = self.menubar.addMenu('Download') helpMenu = self.menubar.addMenu('Help') #statusbar self.statusbar = QStatusBar(self) self.setStatusBar(self.statusbar) self.statusbar.showMessage("Persepolis Download Manager") #toolBar self.toolBar = QToolBar(self) self.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar) self.toolBar.setWindowTitle("toolBar") self.toolBar.setIconSize(QSize(38, 38)) self.toolBar.setFloatable(False) self.toolBar.setMovable(False) #toolBar and menubar and actions self.stopAllAction = QAction(QIcon(icons + 'stop_all'), 'Stop all active downloads', self, statusTip='Stop all active downloads', triggered=self.stopAllDownloads) downloadMenu.addAction(self.stopAllAction) self.pauseAllAction = QAction(QIcon(icons + 'pause_all'), 'Pause all active downloads', self, statusTip='Pause all active downloads', triggered=self.pauseAllDownloads) downloadMenu.addAction(self.pauseAllAction) self.trayAction = QAction('Show system tray icon', self, statusTip="Show/Hide system tray icon", triggered=self.showTray) self.trayAction.setCheckable(True) self.trayAction.setChecked(True) viewMenu.addAction(self.trayAction) self.minimizeAction = QAction(QIcon(icons + 'minimize'), 'Minimize to system tray', self, shortcut="Ctrl+W", statusTip="Minimize to system tray", triggered=self.minMaxTray) viewMenu.addAction(self.minimizeAction) self.addlinkAction = QAction(QIcon(icons + 'add'), 'Add New Download Link', self, shortcut="Ctrl+N", statusTip="Add New Download Link", triggered=self.addLinkButtonPressed) fileMenu.addAction(self.addlinkAction) self.resumeAction = QAction(QIcon(icons + 'play'), 'Resume Download', self, shortcut="Ctrl+R", statusTip="Resume Download", triggered=self.resumeButtonPressed) downloadMenu.addAction(self.resumeAction) self.pauseAction = QAction(QIcon(icons + 'pause'), 'Pause Download', self, shortcut="Ctrl+C", statusTip="Pause Download", triggered=self.pauseButtonPressed) downloadMenu.addAction(self.pauseAction) self.stopAction = QAction(QIcon(icons + 'stop'), 'Stop Download', self, shortcut="Ctrl+S", statusTip="Stop/Cancel Download", triggered=self.stopButtonPressed) downloadMenu.addAction(self.stopAction) self.removeAction = QAction(QIcon(icons + 'remove'), 'Remove Download', self, shortcut="Ctrl+D", statusTip="Remove Download", triggered=self.removeButtonPressed) downloadMenu.addAction(self.removeAction) self.propertiesAction = QAction(QIcon(icons + 'setting'), 'Properties', self, shortcut="Ctrl+P", statusTip="Properties", triggered=self.propertiesButtonPressed) downloadMenu.addAction(self.propertiesAction) self.progressAction = QAction(QIcon(icons + 'window'), 'Progress', self, shortcut="Ctrl+Z", statusTip="Progress", triggered=self.progressButtonPressed) downloadMenu.addAction(self.progressAction) self.openFileAction = QAction(QIcon(icons + 'file'), 'Open file', self, statusTip='Open file', triggered=self.openFile) fileMenu.addAction(self.openFileAction) self.openDownloadFolderAction = QAction( QIcon(icons + 'folder'), 'Open download folder', self, statusTip='Open download folder', triggered=self.openDownloadFolder) fileMenu.addAction(self.openDownloadFolderAction) self.deleteFileAction = QAction(QIcon(icons + 'trash'), 'delete file', self, statusTip='delete file', triggered=self.deleteFile) fileMenu.addAction(self.deleteFileAction) self.openDefaultDownloadFolderAction = QAction( QIcon(icons + 'folder'), 'Open default download folder', self, statusTip='Open default download folder', triggered=self.openDefaultDownloadFolder) fileMenu.addAction(self.openDefaultDownloadFolderAction) self.exitAction = QAction(QIcon(icons + 'exit'), 'Exit', self, shortcut="Ctrl+Q", statusTip="Exit", triggered=self.closeEvent) fileMenu.addAction(self.exitAction) self.selectAction = QAction('Enable selectection mode', self, statusTip='Select Downloads', triggered=self.selectDownloads) self.selectAction.setCheckable(True) editMenu.addAction(self.selectAction) self.selectAllAction = QAction(QIcon(icons + 'select_all'), 'Select All', self, statusTip='Select All', triggered=self.selectAll) editMenu.addAction(self.selectAllAction) self.selectAllAction.setEnabled(False) self.removeSelectedAction = QAction( QIcon(icons + 'multi_remove'), 'Remove selected downloads form list', self, statusTip='Remove selected downloads form list', triggered=self.removeSelected) editMenu.addAction(self.removeSelectedAction) self.removeSelectedAction.setEnabled(False) self.deleteSelectedAction = QAction( QIcon(icons + 'multi_trash'), 'Delete selected download files', self, statusTip='Delete selected download files', triggered=self.deleteSelected) editMenu.addAction(self.deleteSelectedAction) self.deleteSelectedAction.setEnabled(False) self.preferencesAction = QAction(QIcon(icons + 'preferences'), 'Preferences', self, statusTip='Preferences', triggered=self.openPreferences) editMenu.addAction(self.preferencesAction) self.aboutAction = QAction(QIcon(icons + 'about'), 'About', self, statusTip='About', triggered=self.openAbout) helpMenu.addAction(self.aboutAction) for i in self.addlinkAction, self.resumeAction, self.pauseAction, self.stopAction, self.removeAction, self.deleteFileAction, self.propertiesAction, self.progressAction, self.exitAction: self.toolBar.addAction(i) self.toolBar.insertSeparator(self.addlinkAction) self.toolBar.insertSeparator(self.resumeAction) self.toolBar.insertSeparator(self.removeAction) self.toolBar.insertSeparator(self.exitAction) self.toolBar.addSeparator()
class MainWindow_Ui(QMainWindow): def __init__(self, persepolis_setting): super().__init__() # MainWindow self.persepolis_setting = persepolis_setting # add support for other languages locale = str(self.persepolis_setting.value('settings/locale')) QLocale.setDefault(QLocale(locale)) self.translator = QTranslator() if self.translator.load(':/translations/locales/ui_' + locale, 'ts'): QCoreApplication.installTranslator(self.translator) # set ui direction ui_direction = self.persepolis_setting.value('ui_direction') if ui_direction == 'rtl': self.setLayoutDirection(Qt.RightToLeft) elif ui_direction in 'ltr': self.setLayoutDirection(Qt.LeftToRight) icons = ':/' + \ str(self.persepolis_setting.value('settings/icons')) + '/' self.setWindowTitle(QCoreApplication.translate("mainwindow_ui_tr", "Persepolis Download Manager")) self.setWindowIcon(QIcon.fromTheme('persepolis', QIcon(':/persepolis.svg'))) self.centralwidget = QWidget(self) self.verticalLayout = QVBoxLayout(self.centralwidget) # enable drag and drop self.setAcceptDrops(True) # frame self.frame = QFrame(self.centralwidget) # download_table_horizontalLayout download_table_horizontalLayout = QHBoxLayout() tabels_splitter = QSplitter(Qt.Horizontal) # category_tree self.category_tree_qwidget = QWidget(self) category_tree_verticalLayout = QVBoxLayout() self.category_tree = CategoryTreeView(self) category_tree_verticalLayout.addWidget(self.category_tree) self.category_tree_model = QStandardItemModel() self.category_tree.setModel(self.category_tree_model) category_table_header = [QCoreApplication.translate("mainwindow_ui_tr", 'Category')] self.category_tree_model.setHorizontalHeaderLabels( category_table_header) self.category_tree.header().setStretchLastSection(True) self.category_tree.header().setDefaultAlignment(Qt.AlignCenter) # queue_panel self.queue_panel_widget = QWidget(self) queue_panel_verticalLayout_main = QVBoxLayout(self.queue_panel_widget) # queue_panel_show_button self.queue_panel_show_button = QPushButton(self) queue_panel_verticalLayout_main.addWidget(self.queue_panel_show_button) # queue_panel_widget_frame self.queue_panel_widget_frame = QFrame(self) self.queue_panel_widget_frame.setFrameShape(QFrame.StyledPanel) self.queue_panel_widget_frame.setFrameShadow(QFrame.Raised) queue_panel_verticalLayout_main.addWidget( self.queue_panel_widget_frame) queue_panel_verticalLayout = QVBoxLayout(self.queue_panel_widget_frame) queue_panel_verticalLayout_main.setContentsMargins(50, -1, 50, -1) # start_end_frame self.start_end_frame = QFrame(self) # start time start_verticalLayout = QVBoxLayout(self.start_end_frame) self.start_checkBox = QCheckBox(self) start_verticalLayout.addWidget(self.start_checkBox) self.start_frame = QFrame(self) self.start_frame.setFrameShape(QFrame.StyledPanel) self.start_frame.setFrameShadow(QFrame.Raised) start_frame_verticalLayout = QVBoxLayout(self.start_frame) self.start_time_qDataTimeEdit = QDateTimeEdit(self.start_frame) self.start_time_qDataTimeEdit.setDisplayFormat('H:mm') start_frame_verticalLayout.addWidget(self.start_time_qDataTimeEdit) start_verticalLayout.addWidget(self.start_frame) # end time self.end_checkBox = QCheckBox(self) start_verticalLayout.addWidget(self.end_checkBox) self.end_frame = QFrame(self) self.end_frame.setFrameShape(QFrame.StyledPanel) self.end_frame.setFrameShadow(QFrame.Raised) end_frame_verticalLayout = QVBoxLayout(self.end_frame) self.end_time_qDateTimeEdit = QDateTimeEdit(self.end_frame) self.end_time_qDateTimeEdit.setDisplayFormat('H:mm') end_frame_verticalLayout.addWidget(self.end_time_qDateTimeEdit) start_verticalLayout.addWidget(self.end_frame) self.reverse_checkBox = QCheckBox(self) start_verticalLayout.addWidget(self.reverse_checkBox) queue_panel_verticalLayout.addWidget(self.start_end_frame) # limit_after_frame self.limit_after_frame = QFrame(self) # limit_checkBox limit_verticalLayout = QVBoxLayout(self.limit_after_frame) self.limit_checkBox = QCheckBox(self) limit_verticalLayout.addWidget(self.limit_checkBox) # limit_frame self.limit_frame = QFrame(self) self.limit_frame.setFrameShape(QFrame.StyledPanel) self.limit_frame.setFrameShadow(QFrame.Raised) limit_verticalLayout.addWidget(self.limit_frame) limit_frame_verticalLayout = QVBoxLayout(self.limit_frame) # limit_spinBox limit_frame_horizontalLayout = QHBoxLayout() self.limit_spinBox = QDoubleSpinBox(self) self.limit_spinBox.setMinimum(1) self.limit_spinBox.setMaximum(1023) limit_frame_horizontalLayout.addWidget(self.limit_spinBox) # limit_comboBox self.limit_comboBox = QComboBox(self) self.limit_comboBox.addItem("") self.limit_comboBox.addItem("") limit_frame_horizontalLayout.addWidget(self.limit_comboBox) limit_frame_verticalLayout.addLayout(limit_frame_horizontalLayout) # limit_pushButton self.limit_pushButton = QPushButton(self) limit_frame_verticalLayout.addWidget(self.limit_pushButton) # after_checkBox self.after_checkBox = QtWidgets.QCheckBox(self) limit_verticalLayout.addWidget(self.after_checkBox) # after_frame self.after_frame = QtWidgets.QFrame(self) self.after_frame.setFrameShape(QtWidgets.QFrame.StyledPanel) self.after_frame.setFrameShadow(QtWidgets.QFrame.Raised) limit_verticalLayout.addWidget(self.after_frame) after_frame_verticalLayout = QVBoxLayout(self.after_frame) # after_comboBox self.after_comboBox = QComboBox(self) self.after_comboBox.addItem("") after_frame_verticalLayout.addWidget(self.after_comboBox) # after_pushButton self.after_pushButton = QPushButton(self) after_frame_verticalLayout.addWidget(self.after_pushButton) queue_panel_verticalLayout.addWidget(self.limit_after_frame) category_tree_verticalLayout.addWidget(self.queue_panel_widget) # keep_awake_checkBox self.keep_awake_checkBox = QCheckBox(self) queue_panel_verticalLayout.addWidget(self.keep_awake_checkBox) self.category_tree_qwidget.setLayout(category_tree_verticalLayout) tabels_splitter.addWidget(self.category_tree_qwidget) # download table widget self.download_table_content_widget = QWidget(self) download_table_content_widget_verticalLayout = QVBoxLayout( self.download_table_content_widget) self.download_table = DownloadTableWidget(self) download_table_content_widget_verticalLayout.addWidget( self.download_table) tabels_splitter.addWidget(self.download_table_content_widget) self.download_table.setColumnCount(13) self.download_table.setSelectionBehavior(QAbstractItemView.SelectRows) self.download_table.setEditTriggers(QAbstractItemView.NoEditTriggers) self.download_table.verticalHeader().hide() # hide gid and download dictioanry section self.download_table.setColumnHidden(8, True) self.download_table.setColumnHidden(9, True) download_table_header = [QCoreApplication.translate("mainwindow_ui_tr", 'File Name'), QCoreApplication.translate("mainwindow_ui_tr",'Status'), QCoreApplication.translate("mainwindow_ui_tr", 'Size'), QCoreApplication.translate("mainwindow_ui_tr", 'Downloaded'), QCoreApplication.translate("mainwindow_ui_tr", 'Percentage'), QCoreApplication.translate("mainwindow_ui_tr", 'Connections'), QCoreApplication.translate("mainwindow_ui_tr", 'Transfer rate'), QCoreApplication.translate("mainwindow_ui_tr",'Estimated time left'), 'Gid', QCoreApplication.translate("mainwindow_ui_tr",'Link'), QCoreApplication.translate("mainwindow_ui_tr", 'First try date'), QCoreApplication.translate("mainwindow_ui_tr", 'Last try date'), QCoreApplication.translate("mainwindow_ui_tr",'Category')] self.download_table.setHorizontalHeaderLabels(download_table_header) # fixing the size of download_table when window is Maximized! self.download_table.horizontalHeader().setSectionResizeMode(0) self.download_table.horizontalHeader().setStretchLastSection(True) tabels_splitter.setStretchFactor(0, 3) # category_tree width tabels_splitter.setStretchFactor(1, 10) # ratio of tables's width download_table_horizontalLayout.addWidget(tabels_splitter) self.frame.setLayout(download_table_horizontalLayout) self.verticalLayout.addWidget(self.frame) self.setCentralWidget(self.centralwidget) # menubar self.menubar = QMenuBar(self) self.menubar.setGeometry(QRect(0, 0, 600, 24)) self.setMenuBar(self.menubar) fileMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", '&File')) editMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", '&Edit')) viewMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", '&View')) downloadMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", '&Download')) queueMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", '&Queue')) videoFinderMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", 'V&ideo Finder')) helpMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", '&Help')) # viewMenu submenus sortMenu = viewMenu.addMenu(QCoreApplication.translate("mainwindow_ui_tr", 'Sort by')) # statusbar self.statusbar = QStatusBar(self) self.setStatusBar(self.statusbar) self.statusbar.showMessage(QCoreApplication.translate("mainwindow_ui_tr", "Persepolis Download Manager")) # toolBar self.toolBar2 = QToolBar(self) self.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar2) self.toolBar2.setWindowTitle(QCoreApplication.translate("mainwindow_ui_tr", 'Menu')) self.toolBar2.setFloatable(False) self.toolBar2.setMovable(False) self.toolBar = QToolBar(self) self.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar) self.toolBar.setWindowTitle(QCoreApplication.translate("mainwindow_ui_tr", 'Toolbar')) self.toolBar.setFloatable(False) self.toolBar.setMovable(False) #toolBar and menubar and actions self.videoFinderAddLinkAction = QAction(QIcon(icons + 'video_finder'), QCoreApplication.translate("mainwindow_ui_tr", 'Find Video Links'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Download video or audio from Youtube, Vimeo, etc...'), triggered=self.showVideoFinderAddLinkWindow) QShortcut(QKeySequence('Ctrl+I'), self, self.showVideoFinderAddLinkWindow) videoFinderMenu.addAction(self.videoFinderAddLinkAction) self.stopAllAction = QAction(QIcon(icons + 'stop_all'), QCoreApplication.translate("mainwindow_ui_tr", 'Stop all active downloads'), self, statusTip='Stop all active downloads', triggered=self.stopAllDownloads) downloadMenu.addAction(self.stopAllAction) self.sort_file_name_Action = QAction( QCoreApplication.translate("mainwindow_ui_tr", 'File name'), self, triggered=self.sortByName) sortMenu.addAction(self.sort_file_name_Action) self.sort_file_size_Action = QAction( QCoreApplication.translate("mainwindow_ui_tr", 'File size'), self, triggered=self.sortBySize) sortMenu.addAction(self.sort_file_size_Action) self.sort_first_try_date_Action = QAction( QCoreApplication.translate("mainwindow_ui_tr", 'First try date'), self, triggered=self.sortByFirstTry) sortMenu.addAction(self.sort_first_try_date_Action) self.sort_last_try_date_Action = QAction( QCoreApplication.translate("mainwindow_ui_tr", 'Last try date'), self, triggered=self.sortByLastTry) sortMenu.addAction(self.sort_last_try_date_Action) self.sort_download_status_Action = QAction( QCoreApplication.translate("mainwindow_ui_tr", 'Download status'), self, triggered=self.sortByStatus) sortMenu.addAction(self.sort_download_status_Action) self.trayAction = QAction(QCoreApplication.translate("mainwindow_ui_tr", 'Show system tray icon'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Show/Hide system tray icon"), triggered=self.showTray) self.trayAction.setCheckable(True) viewMenu.addAction(self.trayAction) self.showMenuBarAction = QAction( QCoreApplication.translate("mainwindow_ui_tr", 'Show menubar'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Show menubar'), triggered=self.showMenuBar) self.showMenuBarAction.setCheckable(True) viewMenu.addAction(self.showMenuBarAction) self.showSidePanelAction = QAction( QCoreApplication.translate("mainwindow_ui_tr", 'Show side panel'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Show side panel'), triggered=self.showSidePanel) self.showSidePanelAction.setCheckable(True) viewMenu.addAction(self.showSidePanelAction) self.minimizeAction = QAction(QIcon(icons + 'minimize'), QCoreApplication.translate("mainwindow_ui_tr", 'Minimize to system tray'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Minimize to system tray"), triggered=self.minMaxTray) QShortcut(QKeySequence('Ctrl+W'), self, self.minMaxTray) viewMenu.addAction(self.minimizeAction) self.addlinkAction = QAction(QIcon(icons + 'add'), QCoreApplication.translate("mainwindow_ui_tr", 'Add New Download Link'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Add New Download Link"), triggered=self.addLinkButtonPressed) QShortcut(QKeySequence('Ctrl+N'), self, self.addLinkButtonPressed) fileMenu.addAction(self.addlinkAction) self.addtextfileAction = QAction(QIcon(icons + 'file'), QCoreApplication.translate("mainwindow_ui_tr", 'Import links from text file'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Create a Text file and put links in it.line by line!'), triggered=self.importText) fileMenu.addAction(self.addtextfileAction) self.resumeAction = QAction(QIcon(icons + 'play'), QCoreApplication.translate("mainwindow_ui_tr", 'Resume Download'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Resume Download"), triggered=self.resumeButtonPressed) QShortcut(QKeySequence('Ctrl+R'), self, self.resumeButtonPressed) downloadMenu.addAction(self.resumeAction) self.pauseAction = QAction(QIcon(icons + 'pause'), QCoreApplication.translate("mainwindow_ui_tr", 'Pause Download'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Pause Download"), triggered=self.pauseButtonPressed) QShortcut(QKeySequence('Ctrl+C'), self, self.pauseButtonPressed) downloadMenu.addAction(self.pauseAction) self.stopAction = QAction(QIcon(icons + 'stop'), QCoreApplication.translate("mainwindow_ui_tr", 'Stop Download'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Stop/Cancel Download"), triggered=self.stopButtonPressed) QShortcut(QKeySequence('Ctrl+S'), self, self.stopButtonPressed) downloadMenu.addAction(self.stopAction) self.propertiesAction = QAction(QIcon(icons + 'setting'), QCoreApplication.translate("mainwindow_ui_tr", 'Properties'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Properties"), triggered=self.propertiesButtonPressed) QShortcut(QKeySequence('Ctrl+P'), self, self.propertiesButtonPressed) downloadMenu.addAction(self.propertiesAction) self.progressAction = QAction(QIcon(icons + 'window'), QCoreApplication.translate("mainwindow_ui_tr", 'Progress'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Progress"), triggered=self.progressButtonPressed) QShortcut(QKeySequence('Ctrl+Z'), self, self.progressButtonPressed) downloadMenu.addAction(self.progressAction) self.openFileAction = QAction(QIcon( icons + 'file'), QCoreApplication.translate("mainwindow_ui_tr", 'Open file'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Open file'), triggered=self.openFile) fileMenu.addAction(self.openFileAction) self.openDownloadFolderAction = QAction(QIcon( icons + 'folder'), QCoreApplication.translate("mainwindow_ui_tr", 'Open download folder'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Open download folder'), triggered=self.openDownloadFolder) fileMenu.addAction(self.openDownloadFolderAction) self.openDefaultDownloadFolderAction = QAction(QIcon( icons + 'folder'), QCoreApplication.translate("mainwindow_ui_tr", 'Open default download folder'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Open default download folder'), triggered=self.openDefaultDownloadFolder) fileMenu.addAction(self.openDefaultDownloadFolderAction) self.exitAction = QAction(QIcon(icons + 'exit'), QCoreApplication.translate("mainwindow_ui_tr", 'Exit'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Exit"), triggered=self.closeEvent) QShortcut(QKeySequence('Ctrl+Q'), self, self.closeEvent) fileMenu.addAction(self.exitAction) self.clearAction = QAction(QIcon(icons + 'multi_remove'), QCoreApplication.translate("mainwindow_ui_tr", 'Clear download list'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Clear all items in download list'), triggered=self.clearDownloadList) editMenu.addAction(self.clearAction) self.removeSelectedAction = QAction(QIcon(icons + 'remove'), QCoreApplication.translate("mainwindow_ui_tr", 'Remove selected downloads from list'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Remove selected downloads form list'), triggered=self.removeSelected) editMenu.addAction(self.removeSelectedAction) self.removeSelectedAction.setEnabled(False) self.deleteSelectedAction = QAction(QIcon(icons + 'trash'), QCoreApplication.translate("mainwindow_ui_tr", 'Delete selected download files'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Delete selected download files'), triggered=self.deleteSelected) editMenu.addAction(self.deleteSelectedAction) self.deleteSelectedAction.setEnabled(False) self.createQueueAction = QAction(QIcon(icons + 'add_queue'), QCoreApplication.translate("mainwindow_ui_tr", 'Create new queue'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Create new download queue'), triggered=self.createQueue) queueMenu.addAction(self.createQueueAction) self.removeQueueAction = QAction(QIcon(icons + 'remove_queue'), QCoreApplication.translate("mainwindow_ui_tr", 'Remove this queue'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Remove this queue'), triggered=self.removeQueue) queueMenu.addAction(self.removeQueueAction) self.startQueueAction = QAction(QIcon( icons + 'start_queue'), QCoreApplication.translate("mainwindow_ui_tr", 'Start this queue'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Start this queue'), triggered=self.startQueue) queueMenu.addAction(self.startQueueAction) self.stopQueueAction = QAction(QIcon( icons + 'stop_queue'), QCoreApplication.translate("mainwindow_ui_tr", 'Stop this queue'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Stop this queue'), triggered=self.stopQueue) queueMenu.addAction(self.stopQueueAction) self.moveUpSelectedAction = QAction(QIcon(icons + 'multi_up'), QCoreApplication.translate("mainwindow_ui_tr", 'Move up selected items'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Move currently selected items up by one row'), triggered=self.moveUpSelected) queueMenu.addAction(self.moveUpSelectedAction) self.moveDownSelectedAction = QAction(QIcon(icons + 'multi_down'), QCoreApplication.translate("mainwindow_ui_tr", 'Move down selected items'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Move currently selected items down by one row'), triggered=self.moveDownSelected) queueMenu.addAction(self.moveDownSelectedAction) self.preferencesAction = QAction(QIcon(icons + 'preferences'), QCoreApplication.translate("mainwindow_ui_tr", 'Preferences'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Preferences'), triggered=self.openPreferences, menuRole=5) editMenu.addAction(self.preferencesAction) self.aboutAction = QAction(QIcon( icons + 'about'), QCoreApplication.translate("mainwindow_ui_tr", 'About'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'About'), triggered=self.openAbout, menuRole=4) helpMenu.addAction(self.aboutAction) self.issueAction = QAction(QIcon(icons + 'about'), QCoreApplication.translate("mainwindow_ui_tr", 'Report an issue'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Report an issue'), triggered=self.reportIssue) helpMenu.addAction(self.issueAction) self.updateAction = QAction(QIcon(icons + 'about'), QCoreApplication.translate("mainwindow_ui_tr", 'Check for newer version'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Check for newer release'), triggered=self.newUpdate) helpMenu.addAction(self.updateAction) self.logAction = QAction(QIcon(icons + 'about'), QCoreApplication.translate("mainwindow_ui_tr", 'Show log file'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Help'), triggered=self.showLog) helpMenu.addAction(self.logAction) self.helpAction = QAction(QIcon(icons + 'about'), QCoreApplication.translate("mainwindow_ui_tr", 'Help'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Help'), triggered=self.persepolisHelp) helpMenu.addAction(self.helpAction) self.qmenu = MenuWidget(self) self.toolBar2.addWidget(self.qmenu) # labels self.queue_panel_show_button.setText(QCoreApplication.translate("mainwindow_ui_tr", "Hide options")) self.start_checkBox.setText(QCoreApplication.translate("mainwindow_ui_tr", "Start Time")) self.end_checkBox.setText(QCoreApplication.translate("mainwindow_ui_tr", "End Time")) self.reverse_checkBox.setText(QCoreApplication.translate("mainwindow_ui_tr", "Download bottom of\n the list first")) self.limit_checkBox.setText(QCoreApplication.translate("mainwindow_ui_tr", "Limit Speed")) self.limit_comboBox.setItemText(0, "KiB/s") self.limit_comboBox.setItemText(1, "MiB/s") self.limit_pushButton.setText(QCoreApplication.translate("mainwindow_ui_tr", "Apply")) self.after_checkBox.setText(QCoreApplication.translate("mainwindow_ui_tr", "After download")) self.after_comboBox.setItemText(0, QCoreApplication.translate("mainwindow_ui_tr", "Shut Down")) self.keep_awake_checkBox.setText(QCoreApplication.translate("mainwindow_ui_tr", "Keep system awake!")) self.keep_awake_checkBox.setToolTip( QCoreApplication.translate("mainwindow_ui_tr", "<html><head/><body><p>This option is preventing system from going to sleep.\ This is necessary if your power manager is suspending system automatically. </p></body></html>")) self.after_pushButton.setText(QCoreApplication.translate("mainwindow_ui_tr", "Apply")) def changeIcon(self, icons): icons = ':/' + str(icons) + '/' action_icon_dict = {self.stopAllAction: 'stop_all', self.minimizeAction: 'minimize', self.addlinkAction: 'add', self.addtextfileAction: 'file', self.resumeAction: 'play', self.pauseAction: 'pause', self.stopAction: 'stop', self.propertiesAction: 'setting', self.progressAction: 'window', self.openFileAction: 'file', self.openDownloadFolderAction: 'folder', self.openDefaultDownloadFolderAction: 'folder', self.exitAction: 'exit', self.removeSelectedAction: 'multi_remove', self.deleteSelectedAction: 'multi_trash', self.createQueueAction: 'add_queue', self.removeQueueAction: 'remove_queue', self.startQueueAction: 'start_queue', self.stopQueueAction: 'stop_queue', self.preferencesAction: 'preferences', self.aboutAction: 'about', self.issueAction: 'about', self.updateAction: 'about', self.videoFinderAddLinkAction: 'video_finder', self.qmenu: 'menu'} for key in action_icon_dict.keys(): key.setIcon(QIcon(icons + str(action_icon_dict[key])))
def __init__(self, stampManager, parent=None): super().__init__(parent) self.mTileStampManager = stampManager self.mTileStampModel = stampManager.tileStampModel() self.mProxyModel = QSortFilterProxyModel(self.mTileStampModel) self.mFilterEdit = QLineEdit(self) self.mNewStamp = QAction(self) self.mAddVariation = QAction(self) self.mDuplicate = QAction(self) self.mDelete = QAction(self) self.mChooseFolder = QAction(self) self.setObjectName("TileStampsDock") self.mProxyModel.setSortLocaleAware(True) self.mProxyModel.setSortCaseSensitivity(Qt.CaseInsensitive) self.mProxyModel.setFilterCaseSensitivity(Qt.CaseInsensitive) self.mProxyModel.setSourceModel(self.mTileStampModel) self.mProxyModel.sort(0) self.mTileStampView = TileStampView(self) self.mTileStampView.setModel(self.mProxyModel) self.mTileStampView.setVerticalScrollMode( QAbstractItemView.ScrollPerPixel) self.mTileStampView.header().setStretchLastSection(False) self.mTileStampView.header().setSectionResizeMode( 0, QHeaderView.Stretch) self.mTileStampView.header().setSectionResizeMode( 1, QHeaderView.ResizeToContents) self.mTileStampView.setContextMenuPolicy(Qt.CustomContextMenu) self.mTileStampView.customContextMenuRequested.connect( self.showContextMenu) self.mNewStamp.setIcon(QIcon(":images/16x16/document-new.png")) self.mAddVariation.setIcon(QIcon(":/images/16x16/add.png")) self.mDuplicate.setIcon(QIcon(":/images/16x16/stock-duplicate-16.png")) self.mDelete.setIcon(QIcon(":images/16x16/edit-delete.png")) self.mChooseFolder.setIcon(QIcon(":images/16x16/document-open.png")) Utils.setThemeIcon(self.mNewStamp, "document-new") Utils.setThemeIcon(self.mAddVariation, "add") Utils.setThemeIcon(self.mDelete, "edit-delete") Utils.setThemeIcon(self.mChooseFolder, "document-open") self.mFilterEdit.setClearButtonEnabled(True) self.mFilterEdit.textChanged.connect( self.mProxyModel.setFilterFixedString) self.mTileStampModel.stampRenamed.connect(self.ensureStampVisible) self.mNewStamp.triggered.connect(self.newStamp) self.mAddVariation.triggered.connect(self.addVariation) self.mDuplicate.triggered.connect(self.duplicate) self.mDelete.triggered.connect(self.delete_) self.mChooseFolder.triggered.connect(self.chooseFolder) self.mDuplicate.setEnabled(False) self.mDelete.setEnabled(False) self.mAddVariation.setEnabled(False) widget = QWidget(self) layout = QVBoxLayout(widget) layout.setContentsMargins(5, 5, 5, 5) buttonContainer = QToolBar() buttonContainer.setFloatable(False) buttonContainer.setMovable(False) buttonContainer.setIconSize(QSize(16, 16)) buttonContainer.addAction(self.mNewStamp) buttonContainer.addAction(self.mAddVariation) buttonContainer.addAction(self.mDuplicate) buttonContainer.addAction(self.mDelete) stretch = QWidget() stretch.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum) buttonContainer.addWidget(stretch) buttonContainer.addAction(self.mChooseFolder) listAndToolBar = QVBoxLayout() listAndToolBar.setSpacing(0) listAndToolBar.addWidget(self.mFilterEdit) listAndToolBar.addWidget(self.mTileStampView) listAndToolBar.addWidget(buttonContainer) layout.addLayout(listAndToolBar) selectionModel = self.mTileStampView.selectionModel() selectionModel.currentRowChanged.connect(self.currentRowChanged) self.setWidget(widget) self.retranslateUi()
class AppWindow(QMainWindow): "The application's main window" def __init__(self): super().__init__() self.center = QWidget() self.display = QStackedLayout() self.center.setLayout(self.display) # init the manga view variables self.manga_display() # init the chapter view variables self.chapter_display() # init toolbar self.init_toolbar() # init status bar self.init_stat_bar() self.display.addWidget(self.manga_main) self.display.addWidget(self.chapter_main) self.setCentralWidget(self.center) self.setWindowTitle("Happypanda") self.resize(1029, 650) self.show() def init_stat_bar(self): self.status_bar = self.statusBar() self.status_bar.setMaximumHeight(20) self.status_bar.setSizeGripEnabled(False) self.stat_info = QLabel() self.stat_info.setIndent(5) self.sort_main = QAction("Asc", self) sort_menu = QMenu() self.sort_main.setMenu(sort_menu) s_by_title = QAction("Title", sort_menu) s_by_artist = QAction("Artist", sort_menu) sort_menu.addAction(s_by_title) sort_menu.addAction(s_by_artist) self.status_bar.addPermanentWidget(self.stat_info) #self.status_bar.addAction(self.sort_main) self.temp_msg = QLabel() self.temp_timer = QTimer() self.manga_list_view.series_model.ROWCOUNT_CHANGE.connect(self.stat_row_info) self.manga_list_view.series_model.STATUSBAR_MSG.connect(self.stat_temp_msg) def stat_temp_msg(self, msg): self.temp_timer.stop() self.temp_msg.setText(msg) self.status_bar.addWidget(self.temp_msg) self.temp_timer.timeout.connect(self.temp_msg.clear) self.temp_timer.setSingleShot(True) self.temp_timer.start(5000) def stat_row_info(self): r = self.manga_list_view.series_model.rowCount() t = len(self.manga_list_view.series_model._data) self.stat_info.setText("<b>Showing {} of {} </b>".format(r, t)) def manga_display(self): "initiates the manga view" self.manga_main = QWidget() self.manga_main.setContentsMargins(-10, -12, -10, -10) self.manga_view = QHBoxLayout() self.manga_main.setLayout(self.manga_view) manga_delegate = series.CustomDelegate() manga_delegate.BUTTON_CLICKED.connect(self.setCurrentIndex) self.manga_list_view = series.MangaView() self.manga_list_view.setItemDelegate(manga_delegate) self.manga_view.addWidget(self.manga_list_view) def favourite_display(self): "initiates favourite display" pass def chapter_display(self): "Initiates chapter view" self.chapter_main = QWidget() self.chapter_main.setObjectName("chapter_main") # to allow styling this object self.chapter_layout = QHBoxLayout() self.chapter_main.setLayout(self.chapter_layout) #self.chapter_info.setContentsMargins(-8,-7,-7,-7) #self.chapter_info.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) self.chapter_info_view = series.ChapterInfo() self.chapter_layout.addWidget(self.chapter_info_view) chapter_list_view = series.ChapterView() self.chapter_layout.addWidget(chapter_list_view) #self.chapter.setCollapsible(0, True) #self.chapter.setCollapsible(1, False) def init_toolbar(self): self.toolbar = QToolBar() self.toolbar.setFixedHeight(30) self.toolbar.setWindowTitle("Show") # text for the contextmenu #self.toolbar.setStyleSheet("QToolBar {border:0px}") # make it user defined? self.toolbar.setMovable(False) self.toolbar.setFloatable(False) #self.toolbar.setIconSize(QSize(20,20)) self.toolbar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) spacer_start = QWidget() # aligns the first actions properly spacer_start.setFixedSize(QSize(10, 1)) self.toolbar.addWidget(spacer_start) favourite_view_icon = QIcon(gui_constants.STAR_BTN_PATH) favourite_view_action = QAction(favourite_view_icon, "Favourite", self) #favourite_view_action.setText("Manga View") favourite_view_action.triggered.connect(lambda: self.setCurrentIndex(1)) #need lambda to pass extra args self.toolbar.addAction(favourite_view_action) catalog_view_icon = QIcon(gui_constants.HOME_BTN_PATH) catalog_view_action = QAction(catalog_view_icon, "Library", self) #catalog_view_action.setText("Catalog") catalog_view_action.triggered.connect(lambda: self.setCurrentIndex(0)) #need lambda to pass extra args self.toolbar.addAction(catalog_view_action) self.toolbar.addSeparator() series_icon = QIcon(gui_constants.PLUS_PATH) series_action = QAction(series_icon, "Add series...", self) series_action.triggered.connect(self.manga_list_view.SERIES_DIALOG.emit) series_menu = QMenu() series_menu.addSeparator() populate_action = QAction("Populate from folder...", self) populate_action.triggered.connect(self.populate) series_menu.addAction(populate_action) series_action.setMenu(series_menu) self.toolbar.addAction(series_action) spacer_middle = QWidget() # aligns buttons to the right spacer_middle.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.toolbar.addWidget(spacer_middle) self.search_bar = QLineEdit() self.search_bar.setPlaceholderText("Search title, artist, genres") self.search_bar.setMaximumWidth(200) self.toolbar.addWidget(self.search_bar) self.toolbar.addSeparator() settings_icon = QIcon(gui_constants.SETTINGS_PATH) settings_action = QAction(settings_icon, "Set&tings", self) self.toolbar.addAction(settings_action) self.addToolBar(self.toolbar) spacer_end = QWidget() # aligns About action properly spacer_end.setFixedSize(QSize(10, 1)) self.toolbar.addWidget(spacer_end) def setCurrentIndex(self, number, index=None): """Changes the current display view. Params: number <- int (0 for manga view, 1 for chapter view Optional: index <- QModelIndex for chapter view Note: 0-based indexing """ if index is not None: self.chapter_info_view.display_manga(index) self.display.setCurrentIndex(number) else: self.display.setCurrentIndex(number) # TODO: Improve this so that it adds to the series dialog, # so user can edit data before inserting (make it a choice) def populate(self): "Populates the database with series from local drive'" msgbox = QMessageBox() msgbox.setText("<font color='red'><b>Use with care.</b></font> Choose a folder containing all your series'.") msgbox.setInformativeText("Oniichan, are you sure you want to do this?") msgbox.setStandardButtons(QMessageBox.Yes | QMessageBox.No) msgbox.setDefaultButton(QMessageBox.No) if msgbox.exec() == QMessageBox.Yes: path = QFileDialog.getExistingDirectory(None, "Choose a folder containing your series'") if len(path) is not 0: data_thread = QThread() loading_thread = QThread() loading = misc.Loading() if not loading.ON: misc.Loading.ON = True fetch_instance = fetch.Fetch() fetch_instance.series_path = path loading.show() def finished(status): if status: self.manga_list_view.series_model.populate_data() # TODO: make it spawn a dialog instead (from utils.py or misc.py) if loading.progress.maximum() == loading.progress.value(): misc.Loading.ON = False loading.hide() data_thread.quit else: loading.setText("<font color=red>An error occured. Try restarting..</font>") loading.progress.setStyleSheet("background-color:red") data_thread.quit def fetch_deleteLater(): try: fetch_instance.deleteLater except NameError: pass def thread_deleteLater(): #NOTE: Isn't this bad? data_thread.deleteLater def a_progress(prog): loading.progress.setValue(prog) loading.setText("Searching on local disk...\n(Will take a while on first time)") fetch_instance.moveToThread(data_thread) fetch_instance.DATA_COUNT.connect(loading.progress.setMaximum) fetch_instance.PROGRESS.connect(a_progress) data_thread.started.connect(fetch_instance.local) fetch_instance.FINISHED.connect(finished) fetch_instance.FINISHED.connect(fetch_deleteLater) fetch_instance.FINISHED.connect(thread_deleteLater) data_thread.start()
class GUI(QMainWindow): def __init__(self, config, app, splash): super().__init__() self.config = config self.app = app self.splash = splash log.set_up(logger, verbose=config.VERBOSE, logfile=config.LOG_FILE) self.resize(1024, 680) self.setWindowTitle(tr("Zuul GUI")) icon = QtGui.QIcon('assets/zuul.icns') self.setWindowIcon(icon) self.app.setWindowIcon(icon) def openPreference(): if self.config.initialize(openDialog=True): self.loadPlugins() # Add Preferences menu mainMenuBar = QMenuBar() newAct = QAction(tr("Preferences..."), self) newAct.triggered.connect(openPreference) fileMenu = mainMenuBar.addMenu(tr("Zuul GUI")) fileMenu.addAction(newAct) self.setMenuBar(mainMenuBar) self.currentBlock = None if self.refreshStatus(): self.loadPlugins() timer = QtCore.QTimer(self) timer.timeout.connect(self.refreshStatus) timer.start(self.config.POLL_INTERVAL) self.show() # init clientapi def initXcpApi(self): if hasattr(self, 'zulApi') and isinstance(self.zulApi, ZuuldAPI): return True else: try: self.zulApi = ZuuldAPI(self.config) return True except ConfigurationError as e: self.show() msgBox = QMessageBox(self) msgBox.setText(str(e)) msgBox.setModal(True) msgBox.show() return False def refreshStatus(self): if not self.initXcpApi(): return False try: serverInfo = self.zulApi.call( { 'method': 'get_running_info', 'params': [] }, return_dict=True) zuulLastBlock = serverInfo['last_block']['block_index'] walletLastBlock = self.zulApi.call( { 'method': 'wallet_last_block', 'params': {} }, return_dict=True) message = 'Server Last Block: {} | Wallet Last Block: {}' self.statusBar().showMessage( message.format(zuulLastBlock, walletLastBlock)) if self.currentBlock is not None and self.currentBlock != zuulLastBlock: self.notifyPlugins('new_block', {'block_index': zuulLastBlock}) self.currentBlock = zuulLastBlock return True # TODO except Exception as e: # if application startup then open preference dialog and exit if not hasattr(self, 'plugins'): if self.splash: self.splash.hide() self.config.initialize(openDialog=True) exit() # else fails silently, error are already shown by `api.ZuuldRPCError` # and refreshStatus is executed each self.config.POLL_INTERVAL second return False def notifyPlugins(self, messageName, messageData): logger.debug('Notify plugins `{}`: {}'.format(messageName, messageData)) if hasattr(self, 'plugins'): for plugin in self.plugins: if hasattr(plugin, 'onMessage'): plugin.onMessage(messageName, messageData) self.refreshToolbar() def refreshToolbar(self): pluginIndex = self.currentMenuItem.property('pluginIndex') actionValue = self.currentMenuItem.property('actionValue') self.initToolbar(selectedPluginIndex=pluginIndex, selectedActionValue=actionValue) self.currentMenuItem.setProperty('active', 'true') self.refreshStyleSheet() def initPlugins(self): # init QML plugin container if hasattr(self, 'stackedWidget'): del (self.stackedWidget) self.stackedWidget = QStackedWidget(self) self.plugins = [] for pluginName in self.config.PLUGINS: view = QQuickView() view.setFlags(Qt.SubWindow) # add clientapi into the plugin context context = view.rootContext() context.setContextProperty('zulApi', self.zulApi) context.setContextProperty('GUI', self) # load plugin translations if i18n subfolder exists i18nDir = 'plugins/{}/i18n'.format(pluginName) if os.path.exists(i18nDir): translator = QtCore.QTranslator() fileName = 'send_'.format(QtCore.QLocale.system().name()) #fileName = 'send_fr' translator.load(fileName, i18nDir) self.app.installTranslator(translator) # load QML file plugin_index_path = 'plugins/{}/index.qml'.format(pluginName) view.setSource(QUrl(plugin_index_path)) plugin = view.rootObject() self.plugins.append(plugin) # call plugin init callback plugin.init() # add the plugin in the container container = QWidget.createWindowContainer(view, self) self.stackedWidget.addWidget(container) def initToolbar(self, selectedPluginIndex=None, selectedActionValue=None): # init toolbar if hasattr(self, 'toolbar'): self.removeToolBar(self.toolbar) del (self.toolbar) self.toolbar = QToolBar() self.toolbar.setAutoFillBackground(True) self.toolbar.setObjectName('menu') self.toolbar.setMovable(False) self.toolbar.setFloatable(False) self.toolbar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon | Qt.AlignLeft) self.addToolBar(Qt.LeftToolBarArea, self.toolbar) self.currentMenuItem = None pluginIndex = 0 for plugin in self.plugins: # generate the left menu menu = plugin.property('menu') if isinstance(menu, QJSValue): menu = menu.toVariant() if menu and isinstance(menu, dict) and 'items' in menu and isinstance( menu['items'], list): # menu title if 'groupLabel' in menu: menuGroupLabel = QLabel(menu['groupLabel']) menuGroupLabel.setProperty('isGroupLabel', 'true') self.toolbar.addWidget(menuGroupLabel) # menu item items = [] for menuItem in menu['items']: if isinstance( menuItem, dict ) and 'label' in menuItem and 'value' in menuItem: items.append(MenuItem(menuItem['label'], self)) items[-1].setProperty('pluginIndex', pluginIndex) items[-1].setProperty('actionValue', menuItem['value']) items[-1].setProperty('isAction', 'true') self.toolbar.addWidget(items[-1]) if self.currentMenuItem is None or ( selectedPluginIndex == pluginIndex and selectedActionValue == menuItem['value']): self.currentMenuItem = items[-1] pluginIndex += 1 self.currentMenuItem.activate() def loadPlugins(self): if not self.initXcpApi(): return self.initPlugins() self.initToolbar() # display the plugin container self.refreshStyleSheet() self.setCentralWidget(self.stackedWidget) def refreshStyleSheet(self): self.setStyleSheet(''' QWidget, QQuickView, QToolBar, QMainWindow { font-size:14pt } QToolBar#menu { background-color: #ececec; border: 1px solid #ececec; border-right-color: #000; } QToolBar#menu QLabel { width:100%; text-align:left; padding:3px; margin:0; } QToolBar#menu QLabel[isAction="true"]:hover { background-color:#CCC; } QToolBar#menu QLabel[active="true"] { background-color:#CCC; } QToolBar#menu QLabel[isAction="true"] { padding-left: 15px; } QToolBar#menu QLabel[isGroupLabel="true"] { color:#888888; text-transform:uppercase; } ''') # used in QML to display a confirm dialog @pyqtSlot(QVariant, QVariant, result=QVariant) def confirm(self, title, text): result = QMessageBox.question(self, title, text) if result == QMessageBox.Yes: return True else: return False # used in QML to display a message dialog @pyqtSlot(QVariant, QVariant) def alert(self, title, text): QMessageBox.information(self, title, text) @pyqtSlot(QVariant) def copyToClipboard(self, text): clipboard = QApplication.clipboard() clipboard.setText(text)
class MainWindow(QMainWindow, ui_window.Ui_Window): emulator_found = QtCore.pyqtSignal(dict) emulators_loaded = QtCore.pyqtSignal() def __init__(self): super(MainWindow, self).__init__() self.setupUi(self) self.emulators = { } self.settings = QSettings('SanderTheDragon', 'Qtendo') self.ui_create() self.ui_connect() self.settings_load() def showEvent(self, ev): QMainWindow.showEvent(self, ev) self.statusBar.showMsg('Searching for emulators', 1000) Thread(target=self.find_emulators, daemon=True).start() def closeEvent(self, ev): QMainWindow.closeEvent(self, ev) self.settings_save() def ui_create(self): #Add toolbar self.toolBar = QToolBar() self.toolBar.addAction(self.actionPageEmulation) self.toolBar.setFloatable(False) self.toolBar.setMovable(False) self.toolBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.gridLayout.addWidget(self.toolBar, 1, 0) #Add a second toolbar on emulation page self.toolBarEmulation = QToolBar() self.toolBarEmulation.setFloatable(False) self.toolBarEmulation.setMovable(False) self.toolBarEmulation.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.pageEmulationLayout.addWidget(self.toolBarEmulation, 0, 0) #Add progress bar to status bar self.taskProgress = QProgressBar() self.taskProgress.setVal = lambda x: ( self.taskProgress.setVisible(True), self.taskProgress.setValue(x) ) self.taskProgress.setVal(0) self.taskProgress.setTextVisible(False) self.statusBar.addPermanentWidget(self.taskProgress) #Also print messages to terminal self.statusBar.showMsg = lambda msg, timeout: ( logging.info(msg), self.statusBar.showMessage(msg, timeout) ) #Styling self.setStyleSheet('QToolButton { padding-right: -3px; }') def ui_connect(self): #Menu actions self.actionQuit.triggered.connect(QCoreApplication.quit) self.actionSettings.triggered.connect(lambda: settings.SettingsDialog(parent=self).exec_()) self.actionAbout.triggered.connect(lambda: about.AboutDialog(parent=self).exec_()) #Toolbar actions self.actionPageEmulation.triggered.connect(lambda: self.stackedWidget.setCurrentIndex(0)) #Other signals self.emulator_found.connect(self.add_emulator) self.emulators_loaded.connect(self.reset_status) def settings_load(self): if self.settings.value('qtendo/window/restore', True, type=bool): self.restoreGeometry(self.settings.value('qtendo/window/geometry', type=QByteArray)) def settings_save(self): if self.settings.value('qtendo/window/restore', True, type=bool): self.settings.setValue('qtendo/window/geometry', self.saveGeometry()) def change_emulator(self, index): current = self.stackedWidgetEmulation.currentIndex() if current != index: emulator = self.emulators[list(self.emulators.keys())[current]] emulator['action'].setIcon(QIcon(emulator['action'].icon().pixmap(QSize(24, 24), QIcon.Disabled))) self.stackedWidgetEmulation.setCurrentIndex(index) emulator = self.emulators[list(self.emulators.keys())[index]] emulator['action'].setIcon(QIcon(':' + emulator['icon'])) def add_emulator(self, emulator): if len(emulator['path']) > 0: self.statusBar.showMsg('Found ' + emulator['name'], 1000) else: self.statusBar.showMsg('Failed to find ' + emulator['name'], 1000) self.emulators[emulator['name']] = emulator i = self.stackedWidgetEmulation.count() emulator['action'] = QAction() emulator['action'].setIcon(QIcon(':' + emulator['icon'])) if i > 0: self.toolBarEmulation.addSeparator() emulator['action'].setIcon(QIcon(emulator['action'].icon().pixmap(QSize(24, 24), QIcon.Disabled))) emulator['action'].setIconText(emulator['name']) emulator['action'].triggered.connect(lambda checked, index=i: self.change_emulator(index)) self.toolBarEmulation.addAction(emulator['action']) self.stackedWidgetEmulation.insertWidget(i, emulator['widget'](emulator)) if len(self.settings.value('emulation/emulator/' + emulator['name'].lower().replace(' ', '_') + '/path', emulator['path'], type=str)) == 0: self.toolBarEmulation.widgetForAction(emulator['action']).setStyleSheet('color: ' + QApplication.palette().color(QPalette.Disabled, QPalette.WindowText).name() + ';') emulator['reload_settings'] = self.reload_settings self.taskProgress.setVal(int((100.0 / float(emulator_count)) * float(i + 1))) def reset_status(self): self.statusBar.clearMessage() self.taskProgress.setValue(0) self.taskProgress.setVisible(False) def reload_settings(self): emulator = self.emulators[list(self.emulators.keys())[self.stackedWidgetEmulation.currentIndex()]] if len(self.settings.value('emulation/emulator/' + emulator['name'].lower().replace(' ', '_') + '/path', emulator['path'], type=str)) == 0: self.toolBarEmulation.widgetForAction(emulator['action']).setStyleSheet('color: ' + QApplication.palette().color(QPalette.Disabled, QPalette.WindowText).name() + ';') else: self.toolBarEmulation.widgetForAction(emulator['action']).setStyleSheet('') def find_emulators(self): #Search for FCEUX self.emulator_found.emit(fceux.find(None if not self.settings.contains('emulation/emulator/fceux/path') else self.settings.value('emulation/emulator/fceux/path', type=str))) #Search for ZSNES self.emulator_found.emit(zsnes.find(None if not self.settings.contains('emulation/emulator/zsnes/path') else self.settings.value('emulation/emulator/zsnes/path', type=str))) #Search for Mupen64Plus self.emulator_found.emit(mupen64plus.find(None if not self.settings.contains('emulation/emulator/mupen64plus/path') else self.settings.value('emulation/emulator/mupen64plus/path', type=str))) #Search for Dolphin Emulator self.emulator_found.emit(dolphin.find(None if not self.settings.contains('emulation/emulator/dolphin/path') else self.settings.value('emulation/emulator/dolphin/path', type=str))) #Search for Citra self.emulator_found.emit(citra.find(None if not self.settings.contains('emulation/emulator/citra/path') else self.settings.value('emulation/emulator/citra/path', type=str))) self.emulators_loaded.emit()
class MainWindow(QMainWindow): """This is the main application window class it defines the GUI window for the browser """ def parse_config(self, file_config, options): self.config = {} options = vars(options) for key, metadata in CONFIG_OPTIONS.items(): options_val = options.get(key) file_val = file_config.get(key) env_val = os.environ.get(metadata.get("env", '')) default_val = metadata.get("default") vals = metadata.get("values") debug("key: {}, default: {}, file: {}, options: {}".format( key, default_val, file_val, options_val )) if vals: options_val = (options_val in vals and options_val) or None file_val = (file_val in vals and file_val) or None env_val = (env_val in vals and env_val) or None if metadata.get("is_file"): filename = options_val or env_val if not filename: self.config[key] = default_val else: try: with open(filename, 'r') as fh: self.config[key] = fh.read() except IOError: debug("Could not open file {} for reading.".format( filename) ) self.config[key] = default_val else: set_values = [ val for val in (options_val, env_val, file_val) if val is not None ] if len(set_values) > 0: self.config[key] = set_values[0] else: self.config[key] = default_val if metadata.get("type") and self.config[key]: debug("{} cast to {}".format(key, metadata.get("type"))) self.config[key] = metadata.get("type")(self.config[key]) debug(repr(self.config)) def createAction(self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False, signal="triggered"): """Return a QAction given a number of common QAction attributes Just a shortcut function Originally borrowed from 'Rapid GUI Development with PyQT' by Mark Summerset """ action = QAction(text, self) if icon is not None: action.setIcon(QIcon.fromTheme( icon, QIcon(":/{}.png".format(icon)) )) if shortcut is not None and not shortcut.isEmpty(): action.setShortcut(shortcut) tip += " ({})".format(shortcut.toString()) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: action.__getattr__(signal).connect(slot) if checkable: action.setCheckable() return action def __init__(self, options, parent=None): """Construct a MainWindow Object.""" super(MainWindow, self).__init__(parent) # Load config file self.setWindowTitle("Browser") debug("loading configuration from '{}'".format(options.config_file)) configfile = {} if options.config_file: configfile = yaml.safe_load(open(options.config_file, 'r')) self.parse_config(configfile, options) # self.popup will hold a reference to the popup window # if it gets opened self.popup = None # Stylesheet support if self.config.get("stylesheet"): try: with open(self.config.get("stylesheet")) as ss: self.setStyleSheet(ss.read()) except: debug( """Problem loading stylesheet file "{}", """ """using default style.""" .format(self.config.get("stylesheet")) ) self.setObjectName("global") # If the whitelist is activated, add the bookmarks and start_url if self.config.get("whitelist"): # we can just specify whitelist = True, # which should whitelist just the start_url and bookmark urls. whitelist = self.config.get("whitelist") if type(whitelist) is not list: whitelist = [] whitelist.append(str(QUrl( self.config.get("start_url") ).host())) bookmarks = self.config.get("bookmarks") if bookmarks: whitelist += [ str(QUrl(b.get("url")).host()) for k, b in bookmarks.items() ] self.config["whitelist"] = set(whitelist) # uniquify and optimize debug("Generated whitelist: " + str(whitelist)) # If diagnostic is enabled, connect CTRL+ALT+? to show some diagnistic info if (self.config.get("enable_diagnostic")): self.diagnostic_action = self.createAction( "Show Diagnostic", self.show_diagnostic, QKeySequence("Ctrl+Alt+/"), tip='' ) self.addAction(self.diagnostic_action) self.build_ui() # ## END OF CONSTRUCTOR ## # def build_ui(self): """Set up the user interface for the main window. Unlike the constructor, this method is re-run whenever the browser is "reset" by the user. """ debug("build_ui") inactivity_timeout = self.config.get("timeout") quit_button_tooltip = ( self.config.get("quit_button_mode") == 'close' and "Click here to quit the browser." or """Click here when you are done. It will clear your browsing history""" """ and return you to the start page.""") qb_mode_callbacks = {'close': self.close, 'reset': self.reset_browser} to_mode_callbacks = {'close': self.close, 'reset': self.reset_browser, 'screensaver': self.screensaver} self.screensaver_active = False # ##Start GUI configuration## # self.browser_window = WcgWebView(self.config) self.browser_window.setObjectName("web_content") if ( self.config.get("icon_theme") is not None and QT_VERSION_STR > '4.6' ): QIcon.setThemeName(self.config.get("icon_theme")) self.setCentralWidget(self.browser_window) debug("loading {}".format(self.config.get("start_url"))) self.browser_window.setUrl(QUrl(self.config.get("start_url"))) if self.config.get("fullscreen"): self.showFullScreen() elif ( self.config.get("window_size") and self.config.get("window_size").lower() == 'max' ): self.showMaximized() elif self.config.get("window_size"): size = re.match(r"(\d+)x(\d+)", self.config.get("window_size")) if size: width, height = size.groups() self.setFixedSize(int(width), int(height)) else: debug('Ignoring invalid window size "{}"'.format( self.config.get("window_size") )) # Set up the top navigation bar if it's configured to exist if self.config.get("navigation"): self.navigation_bar = QToolBar("Navigation") self.navigation_bar.setObjectName("navigation") self.addToolBar(Qt.TopToolBarArea, self.navigation_bar) self.navigation_bar.setMovable(False) self.navigation_bar.setFloatable(False) # Standard navigation tools self.nav_items = {} self.nav_items["back"] = self.browser_window.pageAction(QWebPage.Back) self.nav_items["forward"] = self.browser_window.pageAction(QWebPage.Forward) self.nav_items["refresh"] = self.browser_window.pageAction(QWebPage.Reload) self.nav_items["stop"] = self.browser_window.pageAction(QWebPage.Stop) # The "I'm finished" button. self.nav_items["quit"] = self.createAction( self.config.get("quit_button_text"), qb_mode_callbacks.get(self.config.get("quit_button_mode"), self.reset_browser), QKeySequence("Alt+F"), None, quit_button_tooltip) # Zoom buttons self.nav_items["zoom_in"] = self.createAction( "Zoom In", self.zoom_in, QKeySequence("Alt++"), "zoom-in", "Increase the size of the text and images on the page") self.nav_items["zoom_out"] = self.createAction( "Zoom Out", self.zoom_out, QKeySequence("Alt+-"), "zoom-out", "Decrease the size of text and images on the page") if self.config.get("allow_printing"): self.nav_items["print"] = self.createAction( "Print", self.browser_window.print_webpage, QKeySequence("Ctrl+p"), "document-print", "Print this page") # Add all the actions to the navigation bar. for item in self.config.get("navigation_layout"): if item == "separator": self.navigation_bar.addSeparator() elif item == "spacer": # an expanding spacer. spacer = QWidget() spacer.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Preferred) self.navigation_bar.addWidget(spacer) elif item == "bookmarks": # Insert bookmarks buttons here. self.bookmark_buttons = [] for bookmark in self.config.get("bookmarks", {}).items(): debug("Bookmark:\n" + bookmark.__str__()) # bookmark name will use the "name" attribute, if present # or else just the key: bookmark_name = bookmark[1].get("name") or bookmark[0] # Create a button for the bookmark as a QAction, # which we'll add to the toolbar button = self.createAction( bookmark_name, lambda url=bookmark[1].get("url"): self.browser_window.load(QUrl(url)), QKeySequence.mnemonic(bookmark_name), None, bookmark[1].get("description") ) self.navigation_bar.addAction(button) self.navigation_bar.widgetForAction(button).setObjectName("navigation_button") else: action = self.nav_items.get(item, None) if action: self.navigation_bar.addAction(action) self.navigation_bar.widgetForAction(action).setObjectName("navigation_button") # This removes the ability to toggle off the navigation bar: self.nav_toggle = self.navigation_bar.toggleViewAction() self.nav_toggle.setVisible(False) # End "if show_navigation is True" block # set hidden quit action # For reasons I haven't adequately ascertained, # this shortcut fails now and then claiming # "Ambiguous shortcut overload". # No idea why, as it isn't consistent. self.really_quit = self.createAction( "", self.close, QKeySequence("Ctrl+Alt+Q"), None, "" ) self.addAction(self.really_quit) # Call a reset function after timeout if inactivity_timeout != 0: self.event_filter = InactivityFilter(inactivity_timeout) QCoreApplication.instance().installEventFilter(self.event_filter) self.browser_window.page().installEventFilter(self.event_filter) self.event_filter.timeout.connect( to_mode_callbacks.get(self.config.get("timeout_mode"), self.reset_browser)) else: self.event_filter = None # ##END OF UI SETUP## # def screensaver(self): """Enter "screensaver" mode This method puts the browser in screensaver mode, where a URL is displayed while the browser is idle. Activity causes the browser to return to the home screen. """ debug("screensaver started") self.screensaver_active = True if self.popup: self.popup.close() if self.config.get("navigation"): self.navigation_bar.hide() self.browser_window.setZoomFactor(self.config.get("zoom_factor")) self.browser_window.load(QUrl(self.config.get("screensaver_url"))) self.event_filter.timeout.disconnect() self.event_filter.activity.connect(self.reset_browser) def reset_browser(self): """Clear the history and reset the UI. Called whenever the inactivity filter times out, or when the user clicks the "finished" button in 'reset' mode. """ # Clear out the memory cache QWebSettings.clearMemoryCaches() self.browser_window.history().clear() # self.navigation_bar.clear() doesn't do its job, # so remove the toolbar first, then rebuild the UI. debug("RESET BROWSER") if self.event_filter: self.event_filter.blockSignals(True) if self.screensaver_active is True: self.screensaver_active = False self.event_filter.activity.disconnect() if self.event_filter: self.event_filter.blockSignals(False) if hasattr(self, "navigation_bar"): self.removeToolBar(self.navigation_bar) self.build_ui() def zoom_in(self): """Zoom in action callback. Note that we cap zooming in at a factor of 3x. """ if self.browser_window.zoomFactor() < 3.0: self.browser_window.setZoomFactor( self.browser_window.zoomFactor() + 0.1 ) self.nav_items["zoom_out"].setEnabled(True) else: self.nav_items["zoom_in"].setEnabled(False) def zoom_out(self): """Zoom out action callback. Note that we cap zooming out at 0.1x. """ if self.browser_window.zoomFactor() > 0.1: self.browser_window.setZoomFactor( self.browser_window.zoomFactor() - 0.1 ) self.nav_items["zoom_in"].setEnabled(True) else: self.nav_items["zoom_out"].setEnabled(False) def show_diagnostic(self): "Display a dialog box with some diagnostic info" data = { "OS": os.uname(), "USER": (os.environ.get("USER") or os.environ.get("USERNAME")), "Python": sys.version, "Qt": QT_VERSION_STR, "Script Date": ( datetime.datetime.fromtimestamp( os.stat(__file__).st_mtime).isoformat() ) } html = "\n".join([ "<h1>System Information</h1>", "<h2>Please click "", self.config.get("quit_button_text").replace("&", ''), "" when you are finished.</h2>", "<ul>", "\n".join([ "<li><b>{}</b>: {}</li>".format(k, v) for k, v in data.items() ]), "</ul>" ]) self.browser_window.setHtml(html)
def initUI(self): self.tboard = Board(self) self.tboard.setDraught(self) self.setCentralWidget(self.tboard) mainMenu = self.menuBar() gameMenu = mainMenu.addMenu(" Game") resetAction = QAction("Reset", self) resetAction.setShortcut("Ctrl+R") pvp = QAction("Player vs Player", self) pvp.setShortcut("Ctrl+P") pve = QAction("Player vs Ai", self) pve.setShortcut("Ctrl+A") gameMenu.addAction(resetAction) gameMenu.addAction(pvp) gameMenu.addAction(pve) resetAction.triggered.connect(self.resetGame) pvp.triggered.connect(self.playerGame) pve.triggered.connect(self.aiGame) self.statusbar = self.statusBar() self.tboard.msg2Statusbar[str].connect(self.statusbar.showMessage) toolbar = QToolBar() toolbar.setAllowedAreas(Qt.RightToolBarArea) toolbar.setIconSize(QSize(40, 40)) toolbar.setFloatable(False) toolbar.setMovable(False) magicWidget = QWidget() self.grid = QGridLayout() myFont = QFont() myFont.setBold(True) myFont.setPixelSize(15) self.playerLabel = QLabel("Player") self.playerLabel.setFont(myFont) self.playerTurn = self.turnLabel() self.opponentLabel = QLabel("Opponent") self.opponentLabel.setFont(myFont) self.opponentLabel.setContentsMargins(0, 30, 0, 0) self.opponentTurn = self.turnLabel() self.opponentTurn.setContentsMargins(0, 30, 0, 0) self.playerPawnLeft = QLabel(str(self.tboard.players[0].pawnLeft)) self.opponentPawnLeft = QLabel(str(self.tboard.players[1].pawnLeft)) self.playerPawnKilled = QLabel(str(self.tboard.players[0].pawnKilled)) self.opponentPawnKilled = QLabel(str( self.tboard.players[1].pawnKilled)) self.grid.addWidget(self.playerLabel, 0, 0) self.grid.addWidget(self.playerTurn, 0, 1) self.grid.addWidget(self.remainingLabel(), 1, 0) self.grid.addWidget(self.playerPawnLeft, 1, 1) self.grid.addWidget(self.killedLabel(), 2, 0) self.grid.addWidget(self.playerPawnKilled, 2, 1) self.grid.addWidget(self.opponentLabel, 3, 0) self.grid.addWidget(self.opponentTurn, 3, 1) self.grid.addWidget(self.remainingLabel(), 4, 0) self.grid.addWidget(self.opponentPawnLeft, 4, 1) self.grid.addWidget(self.killedLabel(), 5, 0) self.grid.addWidget(self.opponentPawnKilled, 5, 1) magicWidget.setLayout(self.grid) toolbar.addWidget(magicWidget) self.updateTurnLabel() self.addToolBar(Qt.RightToolBarArea, toolbar) self.resize(550, 400) self.center() self.setWindowTitle('Draught') self.show()
class App(QMainWindow): @property def QSETTINGS(self): return QSettings(QSettings.IniFormat, QSettings.UserScope, "mdviewer", "session") def __init__(self, parent=None, filename=""): QMainWindow.__init__(self, parent) self.filename = filename or os.path.join(app_dir, u"README.md") # Set environment variables self.set_env() # Configure Preview window self.set_window_title() self.resize(self.QSETTINGS.value("size", QSize(800,400))) self.move(self.QSETTINGS.value("pos", QPoint(0,0))) # Activate WebView self.web_view = QWebView() self.setCentralWidget(self.web_view) self.scroll_pos = {} # Configure and start file watcher thread self.thread1 = WatcherThread(self.filename) self.thread1.update.connect(self.update) self.watcher = QFileSystemWatcher([self.filename]) self.watcher.fileChanged.connect(self.thread1.run) self.thread1.run() self.web_view.loadFinished.connect(self.after_update) # Get style sheet self.stylesheet = self.QSETTINGS.value("stylesheet", "default.css") # Set GUI menus and toolbars self.set_menus() self.set_search_bar() def set_env(self): path, name = os.path.split(os.path.abspath(self.filename)) ext = os.path.splitext(name)[-1].lower() os.environ["MDVIEWER_EXT"] = ext[1:] os.environ["MDVIEWER_FILE"] = name os.environ["MDVIEWER_ORIGIN"] = path def set_window_title(self): _path, name = os.path.split(os.path.abspath(self.filename)) self.setWindowTitle(u"%s – MDviewer" % (name)) def update(self, text, warn): "Update Preview." self.web_view.settings().setAttribute(QWebSettings.JavascriptEnabled, True) self.web_view.settings().setAttribute(QWebSettings.PluginsEnabled, True) self.web_view.settings().setAttribute(QWebSettings.DeveloperExtrasEnabled, True) # Configure link behavior self.web_view.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks) self.web_view.linkClicked.connect(lambda url: self.handle_link_clicked(url)) # Save scroll position if not self.web_view.page().currentFrame().scrollPosition() == QPoint(0,0): self.scroll_pos[self.filename] = self.web_view.page().currentFrame().scrollPosition() # Update Preview self.web_view.setHtml(text, baseUrl=QUrl.fromLocalFile(os.path.join(os.getcwd(), self.filename))) # Load JavaScript and core CSS scr = os.path.join(app_dir, "mdviewer.js") css = os.path.join(app_dir, "mdviewer.css") add_resources = """ (function() { var head = document.querySelector("head"); var css = document.createElement("link"); css.rel = "stylesheet"; css.href = "%s"; css.id = "coreCSS"; head.appendChild(css); var script = document.createElement("script"); script.type = "text/javascript"; script.src = "%s"; script.id = "coreJS"; script.setAttribute("defer", ""); head.appendChild(script); })() """ % (css, scr) self.web_view.page().currentFrame().evaluateJavaScript(add_resources) # Display processor warnings if warn: QMessageBox.warning(self, "Processor message", warn) def after_update(self): "Restore scroll position." try: pos = self.scroll_pos[self.filename] except KeyError: pass else: self.web_view.page().currentFrame().evaluateJavaScript("window.scrollTo(%s, %s)" % (pos.x(), pos.y())) def open_file(self): filename, _filter = QFileDialog.getOpenFileName(self, "Open File", os.path.dirname(self.filename)) if filename != "": self.filename = self.thread1.filename = filename self.set_env() self.set_window_title() self.thread1.run() else: pass def save_html(self): filename, _filter = QFileDialog.getSaveFileName(self, "Save File", os.path.dirname(self.filename)) if filename != "": proc = Settings.get("processor_path", "pandoc") args = Settings.get("processor_args", "") args = ("%s" % (args)).split() + [self.filename] caller = QProcess() caller.start(proc, args) caller.waitForFinished() html = str(caller.readAllStandardOutput(), "utf8") with io.open(filename, "w", encoding="utf8") as f: f.writelines(html) f.close() else: pass def find(self, text, btn=""): page = self.web_view.page() back = page.FindFlags(1) if btn is self.prev else page.FindFlags(0) case = page.FindFlags(2) if self.case.isChecked() else page.FindFlags(0) wrap = page.FindFlags(4) if self.wrap.isChecked() else page.FindFlags(0) page.findText("", page.FindFlags(8)) page.findText(text, back | wrap | case) def set_search_bar(self): self.search_bar = QToolBar() self.search_bar.setMovable(False) self.search_bar.setFloatable(False) self.search_bar.setVisible(False) self.search_bar.layout().setSpacing(1) self.addToolBar(0x8, self.search_bar) self.text = QLineEdit(self) self.text.setClearButtonEnabled(True) self.text.setPlaceholderText(u"Search") self.case = QCheckBox(u"Case sensitive", self) self.wrap = QCheckBox(u"Wrap", self) self.next = QPushButton(u"Next", self) self.next.setToolTip(u"Find next") self.next.setShortcut(QKeySequence("Return")) self.next.setDisabled(True) self.prev = QPushButton(u"Previous", self) self.prev.setToolTip(u"Find previous") self.prev.setShortcut(QKeySequence("Shift+Return")) self.prev.setDisabled(True) self.done = QPushButton(u"Done", self) self.done.setToolTip(u"Hide Search bar") self.done.setShortcut(QKeySequence("Esc")) def _enable_nav(): if self.text.text() == "": self.next.setDisabled(True) self.prev.setDisabled(True) else: self.next.setDisabled(False) self.prev.setDisabled(False) def _toggle_btn(btn=""): self.text.setFocus() self.find(self.text.text(), btn) def _hide(): if self.search_bar.isVisible(): self.search_bar.hide() self.search_bar.addWidget(self.done) self.search_bar.addSeparator() self.search_bar.addWidget(self.case) self.search_bar.addWidget(self.wrap) self.search_bar.addWidget(self.text) self.search_bar.addSeparator() self.search_bar.addWidget(self.next) self.search_bar.addWidget(self.prev) for btn in (self.prev, self.next): btn.pressed[()].connect(lambda btn = btn: _toggle_btn(btn)) self.done.pressed.connect(_hide) self.text.textChanged.connect(self.find) self.text.textChanged.connect(_enable_nav) def show_search_bar(self): self.search_bar.show() self.text.setFocus() self.text.selectAll() def print_doc(self): dialog = QPrintPreviewDialog() dialog.paintRequested.connect(self.web_view.print_) dialog.exec_() def quit(self, QCloseEvent): self.QSETTINGS.setValue("size", self.size()) self.QSETTINGS.setValue("pos", self.pos()) self.QSETTINGS.setValue("stylesheet", self.stylesheet) QtWidgets.qApp.quit() def zoom_in(self): self.web_view.setZoomFactor(self.web_view.zoomFactor()+.1) def zoom_out(self): self.web_view.setZoomFactor(self.web_view.zoomFactor()-.1) def zoom_reset(self): self.web_view.setZoomFactor(1) def scroll_down(self): self.web_view.page().currentFrame().scroll(0, +self.web_view.page().viewportSize().height()) def scroll_up(self): self.web_view.page().currentFrame().scroll(0, -self.web_view.page().viewportSize().height()) def toggle_toc(self): self.web_view.page().currentFrame().evaluateJavaScript("toggleTOC()") def handle_link_clicked(self, url): if url.isLocalFile(): if url.toLocalFile() == os.path.abspath(self.filename) and url.hasFragment(): self.web_view.page().currentFrame().scrollToAnchor(url.fragment()) return else: QDesktopServices.openUrl(url) else: QDesktopServices.openUrl(url) @staticmethod def set_stylesheet(self, stylesheet="default.css"): path = os.path.join(css_dir, stylesheet) url = QUrl.fromLocalFile(path) self.web_view.settings().setUserStyleSheetUrl(url) self.stylesheet = stylesheet def about(self): msg_about = QMessageBox(0, "About MDviewer", u"MDviewer\n\nVersion: %s" % (VERSION), parent=self) msg_about.show() def report_issue(self): url = QUrl.fromUserInput("https://github.com/saf-dmitry/mdviewer/issues") QDesktopServices.openUrl(url) def set_menus(self): menubar = self.menuBar() file_menu = menubar.addMenu("&File") for d in ( {"name": u"&Open...", "shct": "Ctrl+O", "func": self.open_file}, {"name": u"&Save HTML...", "shct": "Ctrl+S", "func": self.save_html}, {"name": u"&Find...", "shct": "Ctrl+F", "func": self.show_search_bar}, {"name": u"&Print...", "shct": "Ctrl+P", "func": self.print_doc}, {"name": u"&Quit", "shct": "Ctrl+Q", "func": self.quit} ): action = QAction(d["name"], self) action.setShortcut(QKeySequence(d["shct"])) action.triggered.connect(d["func"]) file_menu.addAction(action) view_menu = menubar.addMenu("&View") for d in ( {"name": u"Zoom &In", "shct": "Ctrl++", "func": self.zoom_in}, {"name": u"Zoom &Out", "shct": "Ctrl+-", "func": self.zoom_out}, {"name": u"&Actual Size", "shct": "Ctrl+0", "func": self.zoom_reset} ): action = QAction(d["name"], self) action.setShortcut(QKeySequence(d["shct"])) action.triggered.connect(d["func"]) view_menu.addAction(action) style_menu = menubar.addMenu("&Style") style_menu.setStyleSheet("menu-scrollable: 1") style_menu.setDisabled(True) if os.path.exists(css_dir): files = sorted(os.listdir(css_dir)) files = [f for f in files if f.endswith(".css")] if len(files) > 0: style_menu.setDisabled(False) group = QActionGroup(self, exclusive=True) for i, f in enumerate(files, start=1): name = os.path.splitext(f)[0].replace("&", "&&") action = group.addAction(QtWidgets.QAction(name, self)) action.triggered.connect( lambda x, stylesheet = f: self.set_stylesheet(self, stylesheet)) if i < 10: action.setShortcut(QKeySequence("Ctrl+%d" % i)) action.setCheckable(True) style_menu.addAction(action) if f == self.stylesheet: action.trigger() help_menu = menubar.addMenu("&Help") for d in ( {"name": u"&About...", "func": self.about}, {"name": u"&Report an Issue", "func": self.report_issue}, ): action = QAction(d["name"], self) action.triggered.connect(d["func"]) help_menu.addAction(action) # Redefine reload action reload_action = self.web_view.page().action(QWebPage.Reload) reload_action.setShortcut(QKeySequence.Refresh) reload_action.triggered.connect(self.thread1.run) self.web_view.addAction(reload_action) # Define additional shortcuts QShortcut(QKeySequence("j"), self, activated=self.scroll_down) QShortcut(QKeySequence("k"), self, activated=self.scroll_up) QShortcut(QKeySequence("t"), self, activated=self.toggle_toc) def closeEvent(self, event): self.quit(event) event.accept()
class MainWindow_Ui(QMainWindow): def __init__(self): super().__init__() #MainWindow self.resize(600, 400) self.setMinimumSize(QSize(600, 400)) self.setMaximumSize(QSize(16777215, 16777215)) self.setWindowTitle("Persepolis Download Manager") self.setWindowIcon(QIcon('icon')) self.centralwidget = QWidget(self) self.verticalLayout = QVBoxLayout(self.centralwidget) #enable drag and drop self.setAcceptDrops(True) #frame self.frame = QFrame(self.centralwidget) self.frame.setGeometry(QRect(10, 10, 581, 251)) self.frame.setFrameShape(QFrame.StyledPanel) self.frame.setFrameShadow(QFrame.Raised) self.gridLayout = QGridLayout(self.frame) #tablewidget self.download_table = QTableWidget(self.frame) self.download_table.setGeometry(QRect(10, 10, 560, 231)) self.download_table.setSizeIncrement(QSize(0, 0)) self.download_table.setColumnCount(10) self.download_table.setSelectionBehavior(QAbstractItemView.SelectRows) self.download_table.setEditTriggers(QAbstractItemView.NoEditTriggers) self.download_table.verticalHeader().hide() self.download_table.setColumnHidden(8 , True) self.download_table.setColumnHidden(9 , True) self.gridLayout.addWidget(self.download_table, 0, 0, 1, 1) self.verticalLayout.addWidget(self.frame) self.setCentralWidget(self.centralwidget) download_table_header = ['File Name' , 'Status' , 'Size' , 'Downloaded' , 'Percentage' , 'Connections' , 'Transfer rate' , 'Estimate time left' , 'Gid' , 'Info'] self.download_table.setHorizontalHeaderLabels(download_table_header) #fixing the size of download_table when window is Maximized! self.download_table.horizontalHeader().setSectionResizeMode(0) self.download_table.horizontalHeader().setStretchLastSection(True) #finding number od row that user selected! self.download_table.itemSelectionChanged.connect(self.selectedRow) #menubar self.menubar = QMenuBar(self) self.menubar.setGeometry(QRect(0, 0, 600, 24)) self.setMenuBar(self.menubar) fileMenu = self.menubar.addMenu('File') editMenu = self.menubar.addMenu('Edit') viewMenu = self.menubar.addMenu('View') downloadMenu = self.menubar.addMenu('Download') helpMenu = self.menubar.addMenu('Help') #statusbar self.statusbar = QStatusBar(self) self.setStatusBar(self.statusbar) self.statusbar.showMessage("Persepolis Download Manager") #toolBar self.toolBar = QToolBar(self) self.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar) self.toolBar.setWindowTitle("toolBar") self.toolBar.setIconSize(QSize(38 , 38)) self.toolBar.setFloatable(False) self.toolBar.setMovable(False) #toolBar and menubar and actions self.stopAllAction = QAction(QIcon(icons + 'stop_all') , 'Stop all active downloads' , self , statusTip = 'Stop all active downloads', triggered = self.stopAllDownloads ) downloadMenu.addAction(self.stopAllAction) self.pauseAllAction = QAction(QIcon(icons + 'pause_all') , 'Pause all active downloads' , self , statusTip = 'Pause all active downloads', triggered = self.pauseAllDownloads ) downloadMenu.addAction(self.pauseAllAction) self.minimizeAction = QAction(QIcon(icons + 'minimize') , 'Minimize to system tray' , self , shortcut = "Ctrl+W" , statusTip = "Minimize to system tray" , triggered = self.minMaxTray) viewMenu.addAction(self.minimizeAction) self.addlinkAction = QAction(QIcon(icons + 'add') , 'Add New Download Link' , self , shortcut = "Ctrl+N" , statusTip = "Add New Download Link" , triggered = self.addLinkButtonPressed) fileMenu.addAction(self.addlinkAction) self.resumeAction = QAction(QIcon(icons + 'play') , 'Resume Download' , self , shortcut = "Ctrl+R" , statusTip = "Resume Download" , triggered = self.resumeButtonPressed) downloadMenu.addAction(self.resumeAction) self.pauseAction = QAction(QIcon(icons + 'pause') , 'Pause Download' , self , shortcut = "Ctrl+C" , statusTip = "Pause Download" , triggered = self.pauseButtonPressed) downloadMenu.addAction(self.pauseAction) self.stopAction = QAction(QIcon(icons + 'stop') , 'Stop Download' , self , shortcut = "Ctrl+S" , statusTip = "Stop/Cancel Download" , triggered = self.stopButtonPressed) downloadMenu.addAction(self.stopAction) self.removeAction = QAction(QIcon(icons + 'trash') , 'Remove Download' , self , shortcut = "Ctrl+D" , statusTip = "Remove Download" , triggered = self.removeButtonPressed) downloadMenu.addAction(self.removeAction) self.propertiesAction = QAction(QIcon(icons + 'setting') , 'Properties' , self , shortcut = "Ctrl+P" , statusTip = "Properties" , triggered = self.propertiesButtonPressed ) downloadMenu.addAction(self.propertiesAction) self.progressAction = QAction(QIcon(icons + 'window') , 'Progress' , self , shortcut = "Ctrl+Z" , statusTip = "Progress" , triggered = self.progressButtonPressed ) downloadMenu.addAction(self.progressAction) self.exitAction = QAction(QIcon(icons + 'exit') , 'Exit' , self , shortcut = "Ctrl+Q" , statusTip = "Exit" , triggered = self.close) fileMenu.addAction(self.exitAction) self.preferencesAction = QAction(QIcon(icons + 'preferences') , 'Preferences' , self , statusTip = 'Preferences' , triggered = self.openPreferences) editMenu.addAction(self.preferencesAction) self.aboutAction = QAction(QIcon(icons + 'about') , 'About' , self , statusTip = 'About' , triggered = self.openAbout) helpMenu.addAction(self.aboutAction) for i in self.addlinkAction,self.resumeAction, self.pauseAction , self.stopAction, self.removeAction , self.propertiesAction, self.progressAction , self.exitAction : self.toolBar.addAction(i) self.toolBar.insertSeparator(self.addlinkAction) self.toolBar.insertSeparator(self.resumeAction) self.toolBar.insertSeparator(self.removeAction) self.toolBar.insertSeparator(self.exitAction) self.toolBar.addSeparator()
class Ui_MainWindow(object): def setupUi(self, main_window): main_window.setObjectName("mainWindow") main_window.resize(1024, 768) main_window.setMinimumSize(QSize(1024, 768)) main_window.setToolButtonStyle(Qt.ToolButtonIconOnly) self.central_widget = QWidget(main_window) self.central_widget.setObjectName("central_widget") self.horizontalLayout = QHBoxLayout(self.central_widget) self.horizontalLayout.setObjectName("horizontalLayout") self.topDownSplitter = QSplitter(self.central_widget) self.topDownSplitter.setOrientation(Qt.Vertical) self.topDownSplitter.setOpaqueResize(True) self.topDownSplitter.setHandleWidth(5) self.topDownSplitter.setObjectName("topDownSplitter") self.leftRightSplitter = QSplitter(self.topDownSplitter) self.leftRightSplitter.setOrientation(Qt.Horizontal) self.leftRightSplitter.setObjectName("leftRightSplitter") self.leftPanel = QFrame(self.leftRightSplitter) sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.leftPanel.sizePolicy().hasHeightForWidth()) self.leftPanel.setSizePolicy(sizePolicy) self.leftPanel.setMinimumSize(QSize(245, 550)) self.leftPanel.setMaximumSize(QSize(245, 16777215)) self.leftPanel.setFrameShape(QFrame.StyledPanel) self.leftPanel.setFrameShadow(QFrame.Raised) self.leftPanel.setObjectName("leftPanel") self.leftPanelVLayout = QVBoxLayout(self.leftPanel) self.leftPanelVLayout.setObjectName("leftPanelVLayout") self.colorPickerFrame = QFrame(self.leftPanel) self.colorPickerFrame.setMinimumSize(QSize(0, 0)) self.colorPickerFrame.setMaximumSize(QSize(16777215, 16777215)) self.colorPickerFrame.setFrameShape(QFrame.StyledPanel) self.colorPickerFrame.setFrameShadow(QFrame.Raised) self.colorPickerFrame.setObjectName("colorPickerFrame") self.leftPanelVLayout.addWidget(self.colorPickerFrame) self.leftPanelVLayout.setStretch(0, 5) self.mainPanel = QFrame(self.leftRightSplitter) sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.mainPanel.sizePolicy().hasHeightForWidth()) self.mainPanel.setSizePolicy(sizePolicy) self.mainPanel.setMinimumSize(QSize(320, 240)) self.mainPanel.setAutoFillBackground(False) self.mainPanel.setFrameShape(QFrame.StyledPanel) self.mainPanel.setFrameShadow(QFrame.Raised) self.mainPanel.setObjectName("mainPanel") self.verticalLayout = QVBoxLayout(self.mainPanel) self.verticalLayout.setObjectName("verticalLayout") self.canvasFrame = QFrame(self.mainPanel) sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.canvasFrame.sizePolicy().hasHeightForWidth()) self.canvasFrame.setSizePolicy(sizePolicy) self.canvasFrame.setMinimumSize(310, 230) self.canvasFrame.setFrameShape(QFrame.StyledPanel) self.canvasFrame.setFrameShadow(QFrame.Raised) self.canvasFrame.setObjectName("canvasFrame") self.verticalLayout.addWidget(self.canvasFrame) self.verticalLayout.setStretch(0, 12) self.rightPanel = QFrame(self.leftRightSplitter) sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.rightPanel.sizePolicy().hasHeightForWidth()) self.rightPanel.setSizePolicy(sizePolicy) self.rightPanel.setMinimumSize(QSize(245, 550)) self.rightPanel.setMaximumSize(QSize(340, 16777215)) self.rightPanel.setFrameShape(QFrame.StyledPanel) self.rightPanel.setFrameShadow(QFrame.Raised) self.rightPanel.setObjectName("rightPanel") self.rightPanelLayout = QVBoxLayout(self.rightPanel) self.rightPanelLayout.setObjectName("rightPanelLayout") self.previewFrame = QFrame(self.rightPanel) self.previewFrame.setMaximumSize(320, 500) self.previewFrame.setFrameShape(QFrame.StyledPanel) self.previewFrame.setFrameShadow(QFrame.Raised) self.previewFrame.setObjectName("previewFrame") self.rightPanelLayout.addWidget(self.previewFrame) self.layerListFrame = QFrame(self.rightPanel) self.layerListFrame.setFrameShape(QFrame.StyledPanel) self.layerListFrame.setFrameShadow(QFrame.Raised) self.layerListFrame.setObjectName("layerListFrame") self.rightPanelLayout.addWidget(self.layerListFrame) self.animationBarFrame = QFrame(self.topDownSplitter) sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.animationBarFrame.sizePolicy().hasHeightForWidth()) self.animationBarFrame.setSizePolicy(sizePolicy) self.animationBarFrame.setMinimumSize(QSize(600, 100)) self.animationBarFrame.setMaximumSize(QSize(16777215, 100)) self.animationBarFrame.setFrameShape(QFrame.StyledPanel) self.animationBarFrame.setFrameShadow(QFrame.Raised) self.animationBarFrame.setObjectName("animationBarFrame") self.horizontalLayout.addWidget(self.topDownSplitter) main_window.setCentralWidget(self.central_widget) self.toolBar = QToolBar(main_window) sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.toolBar.sizePolicy().hasHeightForWidth()) self.toolBar.setSizePolicy(sizePolicy) self.toolBar.setMovable(False) self.toolBar.setFloatable(False) self.toolBar.setObjectName("toolBar") main_window.addToolBar(Qt.TopToolBarArea, self.toolBar) self.actionNew = QAction(main_window) self.actionNew.setObjectName("actionNew") self.actionQuit = QAction(main_window) self.actionQuit.setObjectName("actionQuit") self.actionOpen = QAction(main_window) self.actionOpen.setObjectName("actionOpen") self.actionSave = QAction(main_window) self.actionSave.setObjectName("actionSave") self.actionSaveAs = QAction(main_window) self.actionSaveAs.setObjectName("actionSaveAs") self.actionClose = QAction(main_window) self.actionClose.setObjectName("actionClose") self.actionExport = QAction(main_window) self.actionExport.setObjectName("actionExport") self.actionImport = QAction(main_window) self.actionImport.setObjectName("actionImport") self.toolBar.addAction(self.actionNew) self.toolBar.addAction(self.actionOpen) self.toolBar.addAction(self.actionImport) self.toolBar.addAction(self.actionSave) self.toolBar.addAction(self.actionSaveAs) self.toolBar.addAction(self.actionExport) self.toolBar.addAction(self.actionClose) self.toolBar.addAction(self.actionQuit) self.retranslateUi(main_window) QMetaObject.connectSlotsByName(main_window) def retranslateUi(self, main_window): _translate = QCoreApplication.translate main_window.setWindowTitle(_translate("MainWindow", "SpriteMator")) self.toolBar.setWindowTitle(_translate("MainWindow", "toolBar")) self.actionNew.setText(_translate("MainWindow", "New")) self.actionNew.setIconText(_translate("MainWindow", "New")) self.actionNew.setToolTip(_translate("MainWindow", "New Sprite")) self.actionNew.setShortcut(_translate("MainWindow", "Ctrl+N")) self.actionQuit.setText(_translate("MainWindow", "Quit")) self.actionQuit.setToolTip( _translate("MainWindow", "Close Application")) self.actionQuit.setShortcut(_translate("MainWindow", "Esc")) self.actionOpen.setText(_translate("MainWindow", "Open")) self.actionOpen.setToolTip(_translate("MainWindow", "Open Sprite")) self.actionOpen.setShortcut(_translate("MainWindow", "Ctrl+O")) self.actionSave.setText(_translate("MainWindow", "Save")) self.actionSave.setToolTip(_translate("MainWindow", "Save Sprite")) self.actionSave.setShortcut(_translate("MainWindow", "Ctrl+S")) self.actionSaveAs.setText(_translate("MainWindow", "SaveAs")) self.actionSaveAs.setToolTip( _translate("MainWindow", "Save Sprite with another name")) self.actionSaveAs.setShortcut(_translate("MainWindow", "Ctrl+Shift+S")) self.actionClose.setText(_translate("MainWindow", "Close")) self.actionClose.setToolTip(_translate("MainWindow", "Close Sprite")) self.actionClose.setShortcut(_translate("MainWindow", "Ctrl+Q")) self.actionExport.setText(_translate("MainWindow", "Export")) self.actionExport.setToolTip( _translate( "MainWindow", "Export Sprite animations : Either as separate images or as a spritesheet" )) self.actionExport.setShortcut(_translate("MainWindow", "Ctrl+E")) self.actionImport.setText(_translate("MainWindow", "Import")) self.actionImport.setToolTip( _translate("MainWindow", "Create a Sprite from one or more images")) self.actionImport.setShortcut(_translate("MainWindow", "Ctrl+I"))