def __init__(self): QWidget.__init__(self) self.setMinimumSize(1000,500) self.html = QWebView() vbox=QVBoxLayout() toolbar=QToolBar() toolbar.setIconSize(QSize(48, 48)) back = QAction(QIcon(os.path.join(get_image_file_path(),"left.png")), _("back"), self) back.triggered.connect(self.html.back) toolbar.addAction(back) home = QAction(QIcon(os.path.join(get_image_file_path(),"home.png")), _("home"), self) home.triggered.connect(self.home) toolbar.addAction(home) self.tb_url=QLineEdit() self.tb_url.returnPressed.connect(self.browse) toolbar.addWidget(self.tb_url) vbox.addWidget(toolbar) self.default_url = "http://www.gpvdm.com/welcome.html" self.tb_url.setText(self.default_url) self.browse() vbox.addWidget(self.html) self.setLayout(vbox) return
def __init__(self): super(PugdebugExpressionViewer, self).__init__() # Action for adding a new expression self.add_action = QAction(QIcon.fromTheme('list-add'), "&Add", self) self.add_action.triggered.connect(self.handle_add_action) # Action for deleting selected expressions self.delete_action = QAction( QIcon.fromTheme('list-remove'), "&Delete", self ) self.delete_action.setShortcut(QKeySequence("Del")) self.delete_action.triggered.connect(self.handle_delete_action) self.toolbar = QToolBar() self.toolbar.setIconSize(QSize(16, 16)) self.toolbar.addAction(self.add_action) self.toolbar.addAction(self.delete_action) self.tree = QTreeWidget() self.tree.setColumnCount(3) self.tree.setHeaderLabels(['Expression', 'Type', 'Value']) self.tree.setSelectionMode(QAbstractItemView.ContiguousSelection) self.tree.setContextMenuPolicy(Qt.CustomContextMenu) self.tree.customContextMenuRequested.connect(self.show_context_menu) layout = QVBoxLayout() layout.addWidget(self.toolbar) layout.addWidget(self.tree) self.setLayout(layout) self.restore_state() self.tree.itemChanged.connect(self.handle_item_changed)
def initUI(self): self.setWindowTitle("Children of the Goddess") # definisco l'azione ala chiusura exitAction = QAction(QIcon('exit.png'), 'Exit', self) exitAction.setShortcut('Ctrl+Q') exitAction.setStatusTip('Exit application') exitAction.triggered.connect(self.close) # creo la barra dei menu e aggiungo i menu menubar = self.menuBar() menubar.setNativeMenuBar(False) fileMenu = menubar.addMenu('&File') fileMenu.addAction(exitAction) # creo la toolbar toolbar = QToolBar() toolbar.addAction(exitAction) self.addToolBar(Qt.RightToolBarArea, toolbar) # toolbar di default sul lato destro della finestra # cambio posizione e dimensioni della finestra e ne definisco il titiolo infine la faccio apparire self.resize(600, 400) qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) self.setWindowTitle('Main window') self.show()
def __init__(self, parent, *args): QToolBar.__init__(self, parent, *args) self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum)) self._dock = parent self.aClose = QToolBar.addAction(self, self.style().standardIcon(QStyle.SP_TitleBarCloseButton), "") closeIcon = self.style().standardIcon(QStyle.SP_DockWidgetCloseButton) if not closeIcon.availableSizes(): # SP_DockWidgetCloseButton is missing on Fedora. Why??? Using fallback closeIcon = self.style().standardIcon( QStyle.SP_DialogCloseButton) self.aClose = QToolBar.addAction(self, closeIcon, "") self.setMovable(False) self.setFloatable(False) self.aClose.triggered.connect(self._dock.close) textHeight = QFontMetrics(self.font()).height() self.setIconSize(QSize(textHeight, textHeight)) # a fake spacer widget self._spacer = QWidget(self) self._spacer.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.MinimumExpanding)) self.addWidget(self._spacer)
def __init__(self,index): QWidget.__init__(self) vbox=QVBoxLayout() self.index=index toolbar=QToolBar() toolbar.setIconSize(QSize(48, 48)) self.load_type=tb_pulse_load_type(self.index) #self.load_type.connect("changed", self.draw_callback) toolbar.addWidget(self.load_type) vbox.addWidget(toolbar) self.diode = QPixmap(os.path.join(get_image_file_path(),"diode.png")) self.ideal_diode = QPixmap(os.path.join(get_image_file_path(),"ideal_diode.png")) self.load = QPixmap(os.path.join(get_image_file_path(),"load.png")) self.ideal_load = QPixmap(os.path.join(get_image_file_path(),"ideal_load.png")) self.voc = QPixmap(os.path.join(get_image_file_path(),"voc.png")) self.darea = QWidget() vbox.addWidget(self.darea) self.setLayout(vbox) self.load_type.changed.connect(self.repaint) return
def __init__(self, area, parent, name=""): QToolBar.__init__(self, parent) self._area = area if not name: name = self.tr("Dock Widgets Toolbar") self.setObjectName(name) self.setWindowTitle(name) self.setFloatable(False) self.setMovable(False) # self.setAllowedAreas(self.TRANSPOSED_AREA[self._area]) self.parent().addToolBar(self.TRANSPOSED_AREA[self._area], self) self._dockToButtonAction = {} # Dock widgets for d in self._dockWidgets(): b = verticalButton(self) b.setDefaultAction(d.toggleViewAction()) # d.setStyleSheet("QDockWidget::title{background-color: red;}") # d.setTitleBarWidget(QLabel(d.windowTitle())) d.setStyleSheet(style.dockSS()) a = self.addWidget(b) self._dockToButtonAction[d] = a self.addSeparator() # Other widgets self.otherWidgets = [] self.currentGroup = None self.setStyleSheet(style.toolBarSS()) self.layout().setContentsMargins(0,0,0,0)
def __init__ (self, parent): super().__init__(parent) self.search = SearchWidget(self) self.search.searched.connect(self.populatelist) self.nodelist = QListWidget(self) self.nodelist.setSortingEnabled(True) self.nodelist.setIconSize(QSize(*(FlGlob.mainwindow.style.boldheight,)*2)) self.nodelist.currentItemChanged.connect(self.selectnode) self.nodelist.itemSelectionChanged.connect(self.onselectionchange) self.nodelist.itemActivated.connect(self.activatenode) self.nodelist.setSelectionMode(QAbstractItemView.ExtendedSelection) remwidget = QToolBar(self) remselected = QAction("Remove Selected", self) remselected.setIcon(QIcon.fromTheme("edit-delete")) remselected.setToolTip("Remove selected") remselected.triggered.connect(self.remselected) self.remselaction = remselected remtrash = QAction("Remove Trash", self) remtrash.setIcon(QIcon.fromTheme("edit-clear")) remtrash.setToolTip("Clear all trash") remtrash.triggered.connect(self.remtrash) self.remtrashaction = remtrash remwidget.addAction(remselected) remwidget.addAction(remtrash) layout = QVBoxLayout(self) layout.addWidget(self.search) layout.addWidget(self.nodelist) layout.addWidget(remwidget) self.view = None self.active = False self.setEnabled(False)
def __init__(self, server): QToolBar.__init__(self) self.hpc_window = QWidget() #self.hpc_window.show() self.myserver=server self.win_list=windows() self.win_list.load() self.win_list.set_window(self,"hpc_window") self.setIconSize(QSize(42, 42)) self.cluster_button = QAction(QIcon(os.path.join(get_image_file_path(),"not_connected.png")), _("Connect to cluster"), self) self.cluster_button.triggered.connect(self.callback_cluster_connect) self.addAction(self.cluster_button) self.node_view=QWidget() self.node_view_vbox=QVBoxLayout() self.node_view.setLayout(self.node_view_vbox) self.bar=[] self.button=[] self.slider=[] self.label=[] self.init_job_window()
def initUI(self): # definisco le azioni exitAction = QAction(QIcon('exit.png'), 'Exit', self) exitAction.setShortcut('Ctrl+Q') exitAction.setStatusTip('Exit application') exitAction.triggered.connect(self.close) # creo la barra dei menu e aggiungo i menu menubar = self.menuBar() menubar.setNativeMenuBar(False) fileMenu = menubar.addMenu('&File') fileMenu.addAction(exitAction) # creo la toolbar toolbar = QToolBar() toolbar.addAction(exitAction) self.addToolBar(Qt.RightToolBarArea, toolbar) # toolbar di default sul lato destro della finestra # aggiungo il widget centrale self.setCentralWidget(LoginWindow(self)) # cambio posizione e dimensioni della finestra e ne definisco il titiolo infine la faccio apparire self.resize(600, 400) qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) self.setWindowTitle('Main window') self.show() # imposto la statusbar per scrivere che l'app è pronta self.statusBar().showMessage('Ready')
def __init__(self, page, parent=None): super(HelpForm, self).__init__(parent) self.setAttribute(Qt.WA_DeleteOnClose) self.setWindowModality(Qt.WindowModal) # actions backAction = QAction(QIcon(":/back.png"), "&Back", self) backAction.setShortcut(QKeySequence.Back) homeAction = QAction(QIcon(":/home.png"), "&Home", self) homeAction.setShortcut("Home") self.pageLabel = QLabel() #toolbar toolBar = QToolBar() toolBar.addAction(backAction) toolBar.addAction(homeAction) toolBar.addWidget(self.pageLabel) self.textBrowser = QTextBrowser() # layout layout = QVBoxLayout() layout.addWidget(toolBar) layout.addWidget(self.textBrowser, 1) self.setLayout(layout) # signals and slots backAction.triggered.connect(self.textBrowser.backward) homeAction.triggered.connect(self.textBrowser.home) self.textBrowser.sourceChanged.connect(self.updatePageTitle) self.textBrowser.setSearchPaths([":/help"]) self.textBrowser.setSource(QUrl(page)) self.resize(400, 600) self.setWindowTitle("{0} Help".format( QApplication.applicationName()))
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 init(self): self.main_vbox = QVBoxLayout() toolbar=QToolBar() toolbar.setIconSize(QSize(32, 32)) self.tb_save = QAction(QIcon(os.path.join(get_image_file_path(),"save.svg")), "Save image", self) self.tb_save.setStatusTip(_("Close")) self.tb_save.triggered.connect(self.callback_save_image) toolbar.addAction(self.tb_save) self.main_vbox.addWidget(toolbar) self.my_figure=Figure(figsize=(5,4), dpi=100) self.canvas = FigureCanvas(self.my_figure) self.canvas.mpl_connect('key_press_event', self.press) self.canvas.setFocusPolicy( Qt.ClickFocus ) self.canvas.setFocus() self.canvas.figure.patch.set_facecolor('white') #self.canvas.set_size_request(600, 400) self.canvas.show() self.main_vbox.addWidget(self.canvas) #self.canvas.connect('key_press_event', self.on_key_press_event) self.setLayout(self.main_vbox)
def __init__(self, vw, vwgui): self.vw = vw self.vwgui = vwgui QToolBar.__init__(self, parent=vwgui) self.addWidget( QLabel('Example Toolbar:', parent=self) ) self.addAction('ONE', self.doOne)
def createControls(self): self.toolBarMain = QToolBar(self) self.toolBarMain.addAction(self.actionChangeBackground) self.toolBarMain.addAction(self.actionResetBackground) self.toolBarMain.addAction(self.actionChangeLayout) self.toolBarMain.addAction(self.actionClose) self.toolBarMain.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) self.toolBarMain.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.toolBarLayout = QToolBar(self) self.toolBarLayout.addAction(self.actionSelectWidgets) self.toolBarLayout.addAction(self.actionResetDefaultLayout) self.toolBarLayout.addAction(self.actionChangeLayout) self.toolBarLayout.addAction(self.actionClose) self.toolBarLayout.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) self.toolBarLayout.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.canvas = Canvas(self) self.layoutEditor = LayoutEditor(self) self.lblTitle = QLabel(self) self.lblTitle.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) self.setLayout(QVBoxLayout()) self.layoutTop = QHBoxLayout() self.layoutTop.addWidget(self.lblTitle) self.layoutTop.addWidget(self.toolBarMain) self.layoutTop.addWidget(self.toolBarLayout) self.toolBarLayout.hide() self.layout().addLayout(self.layoutTop) self.layout().addWidget(self.canvas) self.layout().addWidget(self.layoutEditor) self.layoutEditor.hide()
def ToolBar(*action_list): toolbar = QToolBar() for action in action_list: if action is None: toolbar.addSeparator() else: toolbar.addWidget(ToolButton(action)) return toolbar
def __init__(self, parent, canvas): QToolBar.__init__(self, parent) self._canvas = canvas self.addAction(QApplication.style().standardIcon(QStyle.SP_DialogSaveButton), "Save", canvas.saveImg) self.addAction("Zoom +", canvas.zoomUp) self.addAction("Zoom -", canvas.zoomDown) self.addAction("Configure", canvas.configure)
def initUI(self): QToolTip.setFont(QFont('SansSerif', 10)) self.setToolTip('This is a <b>QWidget</b> widget.') #quitBtn = QPushButton('Quit', self) #quitBtn.clicked.connect(self.quitBtnEvent()) #quitBtn.clicked.connect(QCoreApplication.instance().quit) #quitBtn.setToolTip('This is a <b>QPushButton</b> widget.') #quitBtn.resize(quitBtn.sizeHint()) exitAction = QAction(QIcon('application-exit-4.png'), '&Exit', self) exitAction.setShortcut('Alt+F4') exitAction.setStatusTip('Exit Application') exitAction.triggered.connect(qApp.quit) menuBar = QMenuBar() fileMenu = menuBar.addMenu('&File') fileMenu.addAction(exitAction) fileMenu.resize(fileMenu.sizeHint()) toolBar = QToolBar(self) toolBar.addAction(exitAction) #toolBar.resize(toolBar.sizeHint()) toolBar.setFixedHeight(60) hozLine = QFrame() hozLine.setFrameStyle(QFrame.HLine) #hozLine.setSizePolicy(QSizePolicy.Minimum,QSizePolicy.Expanding) statusBar = QStatusBar(self) statusBar.showMessage('Ready') grid = QGridLayout() lbl_1 = QLabel('1,1') lbl_2 = QLabel('1,2') lbl_3 = QLabel('2,1') lbl_4 = QLabel('2,2') grid.addWidget(lbl_1, 1, 1) grid.addWidget(lbl_2, 1, 2) grid.addWidget(lbl_3, 2, 1) grid.addWidget(lbl_4, 2, 2) vbox = QVBoxLayout() vbox.addWidget(menuBar) vbox.addWidget(hozLine) vbox.addWidget(toolBar) # vbox.addWidget(hozLine) vbox.addLayout(grid) vbox.addStretch(1) vbox.addWidget(statusBar) self.setLayout(vbox) self.setGeometry(300, 300, 500, 500) self.setWindowTitle('Photos') self.setWindowIcon(QIcon('camera-photo-5.png')) self.center() self.show()
def paintEvent(self, event): if self.isMenuBar(): painter = QStylePainter(self) option = QStyleOptionToolBar() self.initStyleOption(option) style = self.style() style.drawControl(QStyle.CE_MenuBarEmptyArea, option, painter, self) else: QToolBar.paintEvent(self, event)
def paintEvent(self, event): if self._queuedWidget.pendingMessageCount() == 0: QToolBar.paintEvent(self, event) return brush = self._queuedWidget.currentMessageBackground() painter = QPainter(self) painter.setPen(brush.color().darker(150)) painter.setBrush(brush) painter.drawRect(self.contentsRect().adjusted(0, 0, -1, -1))
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): QWidget.__init__(self) self.win_list=windows() self.setFixedSize(900, 600) self.setWindowIcon(QIcon(os.path.join(get_image_file_path(),"doping.png"))) self.setWindowTitle(_("Doping profile editor (www.gpvdm.com)")) self.win_list.set_window(self,"doping") self.main_vbox=QVBoxLayout() toolbar=QToolBar() toolbar.setIconSize(QSize(48, 48)) self.save = QAction(QIcon(os.path.join(get_image_file_path(),"save.png")), _("Save"), self) self.save.triggered.connect(self.callback_save) toolbar.addAction(self.save) spacer = QWidget() spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) toolbar.addWidget(spacer) self.help = QAction(QIcon(os.path.join(get_image_file_path(),"help.png")), _("Help"), self) self.help.triggered.connect(self.callback_help) toolbar.addAction(self.help) self.main_vbox.addWidget(toolbar) self.fig = Figure(figsize=(5,4), dpi=100) self.ax1=None self.show_key=True canvas = FigureCanvas(self.fig) #canvas.set_background('white') #canvas.set_facecolor('white') canvas.figure.patch.set_facecolor('white') canvas.show() self.main_vbox.addWidget(canvas) self.tab = QTableWidget() self.tab.resizeColumnsToContents() self.tab.verticalHeader().setVisible(False) self.tab.clear() self.tab.setColumnCount(4) self.tab.setSelectionBehavior(QAbstractItemView.SelectRows) self.load() self.build_mesh() self.tab.cellChanged.connect(self.tab_changed) self.main_vbox.addWidget(self.tab) self.draw_graph() self.setLayout(self.main_vbox) return
def init_chrome(self): # Set up the browser window chrome: self.setWindowTitle("Quickbrowse") toolbar = QToolBar("Toolbar") self.addToolBar(toolbar) btn_act = QAction("Back", self) # for an icon: QAction(QIcon("bug.png"), "Your button", self) btn_act.setStatusTip("Go back") btn_act.triggered.connect(self.go_back) toolbar.addAction(btn_act) btn_act = QAction("Forward", self) btn_act.setStatusTip("Go forward") btn_act.triggered.connect(self.go_forward) toolbar.addAction(btn_act) btn_act = QAction("Reload", self) btn_act.setStatusTip("Reload") btn_act.triggered.connect(self.reload) toolbar.addAction(btn_act) self.urlbar = ReadlineEdit() self.urlbar.setPlaceholderText("URL goes here") self.urlbar.returnPressed.connect(self.urlbar_load) toolbar.addWidget(self.urlbar) self.tabwidget = QTabWidget() self.tabwidget.setTabBarAutoHide(True) self.setCentralWidget(self.tabwidget) self.tabwidget.tabBar().installEventFilter(self) self.prev_middle = -1 self.active_tab = 0 self.setStatusBar(QStatusBar(self)) self.progress = QProgressBar() self.statusBar().addPermanentWidget(self.progress) # Key bindings # For keys like function keys, use QtGui.QKeySequence("F12") QShortcut("Ctrl+Q", self, activated=self.close) QShortcut("Ctrl+L", self, activated=self.select_urlbar) QShortcut("Ctrl+T", self, activated=self.new_tab) QShortcut("Ctrl+R", self, activated=self.reload) QShortcut("Ctrl++", self, activated=self.zoom) QShortcut("Ctrl+=", self, activated=self.zoom) QShortcut("Ctrl+-", self, activated=self.unzoom) QShortcut("Alt+Left", self, activated=self.go_back) QShortcut("Alt+Right", self, activated=self.go_forward) QShortcut("Esc", self, activated=self.unfullscreen)
def __initToolBars(self): """ Private method to populate the toolbars with our actions. """ self.windowToolBar = QToolBar(self.tr("Window"), self) self.windowToolBar.setIconSize(UI.Config.ToolBarIconSize) self.windowToolBar.addAction(self.closeAct) self.graphicsToolBar = QToolBar(self.tr("Graphics"), self) self.graphicsToolBar.setIconSize(UI.Config.ToolBarIconSize) self.graphicsToolBar.addAction(self.printPreviewAct) self.graphicsToolBar.addAction(self.printAct) self.addToolBar(Qt.TopToolBarArea, self.windowToolBar) self.addToolBar(Qt.TopToolBarArea, self.graphicsToolBar)
def gui(self): self.systray = QSystemTrayIcon() self.icon = QIcon(':/sansimera.png') self.systray.setIcon(self.icon) self.systray.setToolTip('Σαν σήμερα...') self.menu = QMenu() self.exitAction = QAction('&Έξοδος', self) self.refreshAction = QAction('&Ανανέωση', self) self.aboutAction = QAction('&Σχετικά', self) self.notification_interval = QAction('Ει&δοποίηση εορταζόντων', self) self.menu.addAction(self.notification_interval) self.menu.addAction(self.refreshAction) self.menu.addAction(self.aboutAction) self.menu.addAction(self.exitAction) self.systray.setContextMenu(self.menu) self.notification_interval.triggered.connect(self.interval_namedays) self.exitAction.triggered.connect(exit) self.refreshAction.triggered.connect(self.refresh) self.aboutAction.triggered.connect(self.about) self.browser = QTextBrowser() self.browser.setOpenExternalLinks(True) self.setGeometry(600, 500, 400, 300) self.setWindowIcon(self.icon) self.setWindowTitle('Σαν σήμερα...') self.setCentralWidget(self.browser) self.systray.show() self.systray.activated.connect(self.activate) self.browser.append('Λήψη...') nicon = QIcon(':/next') picon = QIcon(':/previous') ricon = QIcon(':/refresh') iicon = QIcon(':/info') qicon = QIcon(':/exit') inicon = QIcon(':/notifications') self.nextAction = QAction('Επόμενο', self) self.nextAction.setIcon(nicon) self.previousAction = QAction('Προηγούμενο', self) self.refreshAction.triggered.connect(self.refresh) self.nextAction.triggered.connect(self.nextItem) self.previousAction.triggered.connect(self.previousItem) self.previousAction.setIcon(picon) self.refreshAction.setIcon(ricon) self.exitAction.setIcon(qicon) self.aboutAction.setIcon(iicon) self.notification_interval.setIcon(inicon) controls = QToolBar() self.addToolBar(Qt.BottomToolBarArea, controls) controls.setObjectName('Controls') controls.addAction(self.previousAction) controls.addAction(self.nextAction) controls.addAction(self.refreshAction) self.restoreState(self.settings.value("MainWindow/State", QByteArray())) self.refresh()
def __init__(self, parent): # QTabWidget.__init__(parent) super(QTabWidget, self).__init__(parent) # self.setParent(parent) self.setMovable(True) toolBar = QToolBar() locatorAct = toolBar.addAction('Locate') locatorAct.triggered.connect(lambda: self.openLoctor()) reloadAct = toolBar.addAction('Reload') reloadAct.triggered.connect(lambda: self.reloadPage()) self.setCornerWidget(toolBar, Qt.TopRightCorner) self.tabBar().setStyleSheet('QTabBar::tab { min-width: 8ex; padding: 2px; margin-right: 4px; }')
def __init__(self, parent=None): QListWidget.__init__(self, parent) self.setWindowTitle(tr("Saved Sessions")) self.setWindowFlags(Qt.Dialog) hideAction = QAction(self) hideAction.setShortcuts(["Esc", "Ctrl+W"]) hideAction.triggered.connect(self.hide) self.addAction(hideAction) self.sessionList = QListWidget(self) self.sessionList.itemActivated.connect(self.loadSession) self.setCentralWidget(self.sessionList) self.toolBar = QToolBar(self) self.toolBar.setMovable(False) self.toolBar.setContextMenuPolicy(Qt.CustomContextMenu) self.addToolBar(Qt.BottomToolBarArea, self.toolBar) self.loadButton = QPushButton(tr("&Load"), self) self.loadButton.clicked.connect(lambda: self.loadSession(self.sessionList.currentItem())) self.toolBar.addWidget(self.loadButton) self.saveButton = QPushButton(tr("&Save"), self) self.saveButton.clicked.connect(saveSessionManually) self.saveButton.clicked.connect(self.refresh) self.toolBar.addWidget(self.saveButton) deleteAction = QAction(self) deleteAction.setShortcut("Del") deleteAction.triggered.connect(self.delete) self.addAction(deleteAction)
def __init__(self, project, settings): QWidget.__init__(self) self.ui = Ui_ProjectWidget() self.ui.setupUi(self) self.project = project self.project.filesChanged.connect(self.refresh) self.toolbar = QToolBar() import_image = lambda: ImportImage.pick(lambda f: self.import_image.emit(f[0]), settings) self.toolbar.addAction(ImportImage.icon(), ImportImage.ACTION_TEXT, import_image) self.ui.import_image.clicked.connect(import_image) self.raw_spectra_model = QStandardItemModel() self.calibrated_spectra_model = QStandardItemModel() self.finished_spectra_model = QStandardItemModel() def button_action(button, signal, widget, model): button.clicked.connect(lambda: signal.emit(model.item(widget.selectionModel().selectedRows()[0].row()).data() ) ) widget.selectionModel().selectionChanged.connect(lambda sel, unsel: button.setEnabled(len(sel.indexes())>0)) for model, widget in [(self.raw_spectra_model, self.ui.raw_spectra), (self.calibrated_spectra_model, self.ui.calibrated_spectra), (self.finished_spectra_model, self.ui.finished_spectra)]: widget.setModel(model) widget.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents) button_action(self.ui.calibrate, self.calibrate, self.ui.raw_spectra, self.raw_spectra_model) button_action(self.ui.math, self.math, self.ui.calibrated_spectra, self.calibrated_spectra_model) button_action(self.ui.finish, self.finish, self.ui.calibrated_spectra, self.calibrated_spectra_model) button_action(self.ui.open_finished, self.finish, self.ui.finished_spectra, self.finished_spectra_model) open_finished_menu = QMenu() self.ui.open_finished_dirs.setMenu(open_finished_menu) open_finished_menu.addAction(QIcon(':/image_20'), 'Exported Images folder', lambda: QDesktopServices.openUrl(QUrl.fromLocalFile(project.directory_path(Project.EXPORTED_IMAGES)))) open_finished_menu.addAction(QIcon(':/done_20'), 'Finished Spectra folder', lambda: QDesktopServices.openUrl(QUrl.fromLocalFile(project.directory_path(Project.FINISHED_PROFILES)))) self.refresh()
def __init__(self, parent=None): super(ClearHistoryDialog, self).__init__(parent) self.setWindowFlags(Qt.Dialog) self.setWindowTitle(tr("Clear Data")) closeWindowAction = QAction(self) closeWindowAction.setShortcuts(["Esc", "Ctrl+W", "Ctrl+Shift+Del"]) closeWindowAction.triggered.connect(self.close) self.addAction(closeWindowAction) self.layout = QVBoxLayout() self.setLayout(self.layout) label = QLabel(tr("What to clear:"), self) self.layout.addWidget(label) self.dataType = QComboBox(self) self.dataType.addItem(tr("History")) self.dataType.addItem(tr("Cookies")) self.dataType.addItem(tr("Memory Caches")) self.dataType.addItem(tr("Persistent Storage")) self.dataType.addItem(tr("Everything")) self.layout.addWidget(self.dataType) self.toolBar = QToolBar(self) self.toolBar.setStyleSheet(common.blank_toolbar) self.toolBar.setMovable(False) self.toolBar.setContextMenuPolicy(Qt.CustomContextMenu) self.layout.addWidget(self.toolBar) self.clearHistoryButton = QPushButton(tr("Clear"), self) self.clearHistoryButton.clicked.connect(self.clearHistory) self.toolBar.addWidget(self.clearHistoryButton) self.closeButton = QPushButton(tr("Close"), self) self.closeButton.clicked.connect(self.close) self.toolBar.addWidget(self.closeButton)
def initToolBar(self): self.toolBar = QToolBar("Tools") self.toolBar.setMovable(False) self.addToolBar(Qt.LeftToolBarArea, self.toolBar) self.toolBar.setIconSize(QSize(20, 20)) self.techAnButton = QToolButton() self.techAnButton.setText("Technical analysis") self.techAnButton.setFixedSize(130, 25) self.pairTrButton = QToolButton() self.pairTrButton.setText("Pair Trading") self.pairTrButton.setFixedSize(130, 25) self.atoTrdButton = QToolButton() self.atoTrdButton.setText("Monitor") self.atoTrdButton.setFixedSize(130, 25) self.trdPnlButton = QToolButton() self.trdPnlButton.setText("PnL Report") self.trdPnlButton.setFixedSize(130, 25) self.trdHisButton = QToolButton() self.trdHisButton.setText("Trade History") self.trdHisButton.setFixedSize(130, 25) self.techAnButton.clicked.connect(self.techAnPage) self.pairTrButton.clicked.connect(self.pairTrPage) self.atoTrdButton.clicked.connect(self.atoTrdPage) self.trdPnlButton.clicked.connect(self.trdPnlPage) self.trdHisButton.clicked.connect(self.trdHisPage) self.toolBar.addWidget(self.techAnButton) self.toolBar.addWidget(self.pairTrButton) self.toolBar.addWidget(self.atoTrdButton) self.toolBar.addWidget(self.trdPnlButton) self.toolBar.addWidget(self.trdHisButton) self.toolButtons = [self.techAnButton, self.pairTrButton, self.atoTrdButton, self.trdPnlButton, self.trdHisButton]
def __init__(self, rows, cols, parent = None): super(SpreadSheet, self).__init__(parent) self.toolBar = QToolBar() self.addToolBar(self.toolBar) self.formulaInput = QLineEdit() self.cellLabel = QLabel(self.toolBar) self.cellLabel.setMinimumSize(80, 0) self.toolBar.addWidget(self.cellLabel) self.toolBar.addWidget(self.formulaInput) self.table = QTableWidget(rows, cols, self) for c in range(cols): character = chr(ord('A') + c) self.table.setHorizontalHeaderItem(c, QTableWidgetItem(character)) self.table.setItemPrototype(self.table.item(rows - 1, cols - 1)) self.table.setItemDelegate(SpreadSheetDelegate(self)) self.createActions() self.updateColor(0) self.setupMenuBar() self.setupContents() self.setupContextMenu() self.setCentralWidget(self.table) self.statusBar() self.table.currentItemChanged.connect(self.updateStatus) self.table.currentItemChanged.connect(self.updateColor) self.table.currentItemChanged.connect(self.updateLineEdit) self.table.itemChanged.connect(self.updateStatus) self.formulaInput.returnPressed.connect(self.returnPressed) self.table.itemChanged.connect(self.updateLineEdit) self.setWindowTitle("Spreadsheet")
def __init__(self): QWidgetSavePos.__init__(self, "doping") self.setMinimumSize(900, 600) self.setWindowIcon(icon_get("doping")) self.setWindowTitle( _("Doping/Mobilie ion profile editor") + " (https://www.gpvdm.com)") self.epi = get_epi() self.main_vbox = QVBoxLayout() toolbar = QToolBar() toolbar.setIconSize(QSize(48, 48)) self.save = QAction(icon_get("document-save-as"), _("Save"), self) self.save.triggered.connect(self.callback_save) toolbar.addAction(self.save) spacer = QWidget() spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) toolbar.addWidget(spacer) self.help = QAction(icon_get("help"), _("Help"), self) self.help.triggered.connect(self.callback_help) toolbar.addAction(self.help) self.main_vbox.addWidget(toolbar) self.fig = Figure(figsize=(5, 4), dpi=100) self.ax1 = None self.show_key = True canvas = FigureCanvas(self.fig) #canvas.set_background('white') #canvas.set_facecolor('white') canvas.figure.patch.set_facecolor('white') canvas.show() self.main_vbox.addWidget(canvas) self.tab = gpvdm_tab() self.tab.resizeColumnsToContents() self.tab.verticalHeader().setVisible(False) self.tab.clear() self.tab.setColumnCount(6) self.tab.setSelectionBehavior(QAbstractItemView.SelectRows) self.load() self.build_mesh() self.tab.cellChanged.connect(self.tab_changed) self.tab.setColumnWidth(2, 150) self.tab.setColumnWidth(3, 150) self.tab.setColumnWidth(4, 180) self.tab.setColumnWidth(5, 180) self.main_vbox.addWidget(self.tab) self.draw_graph() self.setLayout(self.main_vbox) layers = epitaxy_get_layers() for i in range(0, layers): dos_file = epitaxy_get_dos_file(i) + ".inp" if dos_file.startswith("dos") == True: get_watch().add_call_back(dos_file, self.load) return
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)
class InfoDialog(QDialog): def __init__(self, app: dict, icon_cache: MemoryCache, i18n: I18n, screen_size: QSize()): super(InfoDialog, self).__init__() self.setWindowTitle(str(app['__app__'])) self.screen_size = screen_size self.i18n = i18n layout = QVBoxLayout() self.setLayout(layout) self.toolbar_field = QToolBar() self.bt_back = QPushButton(i18n['back'].capitalize()) self.bt_back.clicked.connect(self.back_to_info) self.bt_back.setCursor(QCursor(Qt.PointingHandCursor)) self.toolbar_field.addWidget(self.bt_back) self.layout().addWidget(self.toolbar_field) self.toolbar_field.hide() # shows complete field string self.text_field = QPlainTextEdit() self.text_field.setReadOnly(True) self.layout().addWidget(self.text_field) self.text_field.hide() self.gbox_info = QGroupBox() self.gbox_info.setMaximumHeight(self.screen_size.height() - self.screen_size.height() * 0.1) self.gbox_info_layout = QGridLayout() self.gbox_info.setLayout(self.gbox_info_layout) layout.addWidget(self.gbox_info) # THERE ARE CRASHES WITH SOME RARE ICONS ( like insomnia ). IT CAN BE A QT BUG. IN THE MEANTIME, ONLY THE TYPE ICON WILL BE RENDERED # # icon_data = icon_cache.get(app['__app__'].model.icon_url) # # if icon_data and icon_data.get('icon'): # self.setWindowIcon(icon_data.get('icon')) self.setWindowIcon(QIcon(app['__app__'].model.get_type_icon_path())) for idx, attr in enumerate(sorted(app.keys())): if attr not in IGNORED_ATTRS and app[attr]: i18n_key = app['__app__'].model.gem_name + '.info.' + attr.lower() if isinstance(app[attr], list): val = ' '.join([str(e).strip() for e in app[attr] if e]) show_val = '\n'.join(['* ' + str(e).strip() for e in app[attr] if e]) else: val = str(app[attr]).strip() show_val = val i18n_val = i18n.get('{}.{}'.format(i18n_key, val.lower())) if i18n_val: val = i18n_val show_val = val text = QLineEdit() text.setToolTip(show_val) text.setText(val) text.setCursorPosition(0) text.setStyleSheet("width: 400px") text.setReadOnly(True) label = QLabel(i18n.get(i18n_key, i18n.get(attr.lower(), attr)).capitalize()) label.setStyleSheet("font-weight: bold") self.gbox_info_layout.addWidget(label, idx, 0) self.gbox_info_layout.addWidget(text, idx, 1) self._gen_show_button(idx, show_val) self.adjustSize() def _gen_show_button(self, idx: int, val): def show_full_field(): self.gbox_info.hide() self.toolbar_field.show() self.text_field.show() self.text_field.setPlainText(val) bt_full_field = QPushButton(self.i18n['show'].capitalize()) bt_full_field.setCursor(QCursor(Qt.PointingHandCursor)) bt_full_field.clicked.connect(show_full_field) self.gbox_info_layout.addWidget(bt_full_field, idx, 2) def back_to_info(self): self.text_field.setPlainText("") self.text_field.hide() self.toolbar_field.hide() self.gbox_info.show()
def __init__(self, parent=None): QMainWindow.__init__(self, parent) self.resize(950, 700) screenRect = QDesktopWidget().screenGeometry() if globalSettings.windowGeometry: self.restoreGeometry(globalSettings.windowGeometry) else: self.move((screenRect.width()-self.width())/2, (screenRect.height()-self.height())/2) if not screenRect.contains(self.geometry()): self.showMaximized() if sys.platform.startswith('darwin'): # https://github.com/retext-project/retext/issues/198 searchPaths = QIcon.themeSearchPaths() searchPaths.append('/opt/local/share/icons') searchPaths.append('/usr/local/share/icons') QIcon.setThemeSearchPaths(searchPaths) if globalSettings.iconTheme: QIcon.setThemeName(globalSettings.iconTheme) if QIcon.themeName() in ('hicolor', ''): if not QFile.exists(icon_path + 'document-new.png'): QIcon.setThemeName(get_icon_theme()) if QFile.exists(icon_path+'retext.png'): self.setWindowIcon(QIcon(icon_path+'retext.png')) elif QFile.exists('/usr/share/pixmaps/retext.png'): self.setWindowIcon(QIcon('/usr/share/pixmaps/retext.png')) else: self.setWindowIcon(QIcon.fromTheme('retext', QIcon.fromTheme('accessories-text-editor'))) self.tabWidget = QTabWidget(self) self.initTabWidget() self.setCentralWidget(self.tabWidget) self.tabWidget.currentChanged.connect(self.changeIndex) self.tabWidget.tabCloseRequested.connect(self.closeTab) toolBar = QToolBar(self.tr('File toolbar'), self) self.addToolBar(Qt.TopToolBarArea, toolBar) self.editBar = QToolBar(self.tr('Edit toolbar'), self) self.addToolBar(Qt.TopToolBarArea, self.editBar) self.searchBar = QToolBar(self.tr('Search toolbar'), self) self.addToolBar(Qt.BottomToolBarArea, self.searchBar) toolBar.setVisible(not globalSettings.hideToolBar) self.editBar.setVisible(not globalSettings.hideToolBar) self.actionNew = self.act(self.tr('New'), 'document-new', self.createNew, shct=QKeySequence.New) self.actionNew.setPriority(QAction.LowPriority) self.actionOpen = self.act(self.tr('Open'), 'document-open', self.openFile, shct=QKeySequence.Open) self.actionOpen.setPriority(QAction.LowPriority) self.actionSetEncoding = self.act(self.tr('Set encoding'), trig=self.showEncodingDialog) self.actionSetEncoding.setEnabled(False) self.actionReload = self.act(self.tr('Reload'), 'view-refresh', lambda: self.currentTab.readTextFromFile()) self.actionReload.setEnabled(False) self.actionSave = self.act(self.tr('Save'), 'document-save', self.saveFile, shct=QKeySequence.Save) self.actionSave.setEnabled(False) self.actionSave.setPriority(QAction.LowPriority) self.actionSaveAs = self.act(self.tr('Save as'), 'document-save-as', self.saveFileAs, shct=QKeySequence.SaveAs) self.actionNextTab = self.act(self.tr('Next tab'), 'go-next', lambda: self.switchTab(1), shct=Qt.CTRL+Qt.Key_PageDown) self.actionPrevTab = self.act(self.tr('Previous tab'), 'go-previous', lambda: self.switchTab(-1), shct=Qt.CTRL+Qt.Key_PageUp) self.actionPrint = self.act(self.tr('Print'), 'document-print', self.printFile, shct=QKeySequence.Print) self.actionPrint.setPriority(QAction.LowPriority) self.actionPrintPreview = self.act(self.tr('Print preview'), 'document-print-preview', self.printPreview) self.actionViewHtml = self.act(self.tr('View HTML code'), 'text-html', self.viewHtml) self.actionChangeEditorFont = self.act(self.tr('Change editor font'), trig=self.changeEditorFont) self.actionChangePreviewFont = self.act(self.tr('Change preview font'), trig=self.changePreviewFont) self.actionSearch = self.act(self.tr('Find text'), 'edit-find', shct=QKeySequence.Find) self.actionSearch.setCheckable(True) self.actionSearch.triggered[bool].connect(self.searchBar.setVisible) self.searchBar.visibilityChanged.connect(self.searchBarVisibilityChanged) self.actionPreview = self.act(self.tr('Preview'), shct=Qt.CTRL+Qt.Key_E, trigbool=self.preview) if QIcon.hasThemeIcon('document-preview'): self.actionPreview.setIcon(QIcon.fromTheme('document-preview')) elif QIcon.hasThemeIcon('preview-file'): self.actionPreview.setIcon(QIcon.fromTheme('preview-file')) elif QIcon.hasThemeIcon('x-office-document'): self.actionPreview.setIcon(QIcon.fromTheme('x-office-document')) else: self.actionPreview.setIcon(QIcon(icon_path+'document-preview.png')) self.actionLivePreview = self.act(self.tr('Live preview'), shct=Qt.CTRL+Qt.Key_L, trigbool=self.enableLivePreview) menuPreview = QMenu() menuPreview.addAction(self.actionLivePreview) self.actionPreview.setMenu(menuPreview) self.actionTableMode = self.act(self.tr('Table editing mode'), shct=Qt.CTRL+Qt.Key_T, trigbool=lambda x: self.currentTab.editBox.enableTableMode(x)) if ReTextFakeVimHandler: self.actionFakeVimMode = self.act(self.tr('FakeVim mode'), shct=Qt.CTRL+Qt.ALT+Qt.Key_V, trigbool=self.enableFakeVimMode) if globalSettings.useFakeVim: self.actionFakeVimMode.setChecked(True) self.enableFakeVimMode(True) self.actionFullScreen = self.act(self.tr('Fullscreen mode'), 'view-fullscreen', shct=Qt.Key_F11, trigbool=self.enableFullScreen) self.actionFullScreen.setPriority(QAction.LowPriority) self.actionConfig = self.act(self.tr('Preferences'), icon='preferences-system', trig=self.openConfigDialog) self.actionConfig.setMenuRole(QAction.PreferencesRole) self.actionSaveHtml = self.act('HTML', 'text-html', self.saveFileHtml) self.actionPdf = self.act('PDF', 'application-pdf', self.savePdf) self.actionOdf = self.act('ODT', 'x-office-document', self.saveOdf) self.getExportExtensionsList() self.actionQuit = self.act(self.tr('Quit'), 'application-exit', shct=QKeySequence.Quit) self.actionQuit.setMenuRole(QAction.QuitRole) self.actionQuit.triggered.connect(self.close) self.actionUndo = self.act(self.tr('Undo'), 'edit-undo', lambda: self.currentTab.editBox.undo(), shct=QKeySequence.Undo) self.actionRedo = self.act(self.tr('Redo'), 'edit-redo', lambda: self.currentTab.editBox.redo(), shct=QKeySequence.Redo) self.actionCopy = self.act(self.tr('Copy'), 'edit-copy', lambda: self.currentTab.editBox.copy(), shct=QKeySequence.Copy) self.actionCut = self.act(self.tr('Cut'), 'edit-cut', lambda: self.currentTab.editBox.cut(), shct=QKeySequence.Cut) self.actionPaste = self.act(self.tr('Paste'), 'edit-paste', lambda: self.currentTab.editBox.paste(), shct=QKeySequence.Paste) self.actionUndo.setEnabled(False) self.actionRedo.setEnabled(False) self.actionCopy.setEnabled(False) self.actionCut.setEnabled(False) qApp = QApplication.instance() qApp.clipboard().dataChanged.connect(self.clipboardDataChanged) self.clipboardDataChanged() if enchant is not None: self.actionEnableSC = self.act(self.tr('Enable'), trigbool=self.enableSpellCheck) self.actionSetLocale = self.act(self.tr('Set locale'), trig=self.changeLocale) self.actionWebKit = self.act(self.tr('Use WebKit renderer'), trigbool=self.enableWebKit) if ReTextWebPreview is None: globalSettings.useWebKit = False self.actionWebKit.setEnabled(False) self.actionWebKit.setChecked(globalSettings.useWebKit) self.actionShow = self.act(self.tr('Show directory'), 'system-file-manager', self.showInDir) self.actionFind = self.act(self.tr('Next'), 'go-next', self.find, shct=QKeySequence.FindNext) self.actionFindPrev = self.act(self.tr('Previous'), 'go-previous', lambda: self.find(back=True), shct=QKeySequence.FindPrevious) self.actionReplace = self.act(self.tr('Replace'), 'edit-find-replace', lambda: self.find(replace=True)) self.actionReplaceAll = self.act(self.tr('Replace all'), trig=self.replaceAll) menuReplace = QMenu() menuReplace.addAction(self.actionReplaceAll) self.actionReplace.setMenu(menuReplace) self.actionCloseSearch = self.act(self.tr('Close'), 'window-close', lambda: self.searchBar.setVisible(False)) self.actionCloseSearch.setPriority(QAction.LowPriority) self.actionHelp = self.act(self.tr('Get help online'), 'help-contents', self.openHelp) self.aboutWindowTitle = self.tr('About ReText') self.actionAbout = self.act(self.aboutWindowTitle, 'help-about', self.aboutDialog) self.actionAbout.setMenuRole(QAction.AboutRole) self.actionAboutQt = self.act(self.tr('About Qt')) self.actionAboutQt.setMenuRole(QAction.AboutQtRole) self.actionAboutQt.triggered.connect(qApp.aboutQt) availableMarkups = markups.get_available_markups() if not availableMarkups: print('Warning: no markups are available!') if len(availableMarkups) > 1: self.chooseGroup = QActionGroup(self) markupActions = [] for markup in availableMarkups: markupAction = self.act(markup.name, trigbool=self.markupFunction(markup)) if markup.name == globalSettings.defaultMarkup: markupAction.setChecked(True) self.chooseGroup.addAction(markupAction) markupActions.append(markupAction) self.actionBold = self.act(self.tr('Bold'), shct=QKeySequence.Bold, trig=lambda: self.insertFormatting('bold')) self.actionItalic = self.act(self.tr('Italic'), shct=QKeySequence.Italic, trig=lambda: self.insertFormatting('italic')) self.actionUnderline = self.act(self.tr('Underline'), shct=QKeySequence.Underline, trig=lambda: self.insertFormatting('underline')) self.usefulTags = ('header', 'italic', 'bold', 'underline', 'numbering', 'bullets', 'image', 'link', 'inline code', 'code block', 'blockquote') self.usefulChars = ('deg', 'divide', 'dollar', 'hellip', 'laquo', 'larr', 'lsquo', 'mdash', 'middot', 'minus', 'nbsp', 'ndash', 'raquo', 'rarr', 'rsquo', 'times') self.formattingBox = QComboBox(self.editBar) self.formattingBox.addItem(self.tr('Formatting')) self.formattingBox.addItems(self.usefulTags) self.formattingBox.activated[str].connect(self.insertFormatting) self.symbolBox = QComboBox(self.editBar) self.symbolBox.addItem(self.tr('Symbols')) self.symbolBox.addItems(self.usefulChars) self.symbolBox.activated.connect(self.insertSymbol) self.updateStyleSheet() menubar = self.menuBar() menuFile = menubar.addMenu(self.tr('File')) menuEdit = menubar.addMenu(self.tr('Edit')) menuHelp = menubar.addMenu(self.tr('Help')) menuFile.addAction(self.actionNew) menuFile.addAction(self.actionOpen) self.menuRecentFiles = menuFile.addMenu(self.tr('Open recent')) self.menuRecentFiles.aboutToShow.connect(self.updateRecentFiles) menuFile.addAction(self.actionShow) menuFile.addAction(self.actionSetEncoding) menuFile.addAction(self.actionReload) menuFile.addSeparator() menuFile.addAction(self.actionSave) menuFile.addAction(self.actionSaveAs) menuFile.addSeparator() menuFile.addAction(self.actionNextTab) menuFile.addAction(self.actionPrevTab) menuFile.addSeparator() menuExport = menuFile.addMenu(self.tr('Export')) menuExport.addAction(self.actionSaveHtml) menuExport.addAction(self.actionOdf) menuExport.addAction(self.actionPdf) if self.extensionActions: menuExport.addSeparator() for action, mimetype in self.extensionActions: menuExport.addAction(action) menuExport.aboutToShow.connect(self.updateExtensionsVisibility) menuFile.addAction(self.actionPrint) menuFile.addAction(self.actionPrintPreview) menuFile.addSeparator() menuFile.addAction(self.actionQuit) menuEdit.addAction(self.actionUndo) menuEdit.addAction(self.actionRedo) menuEdit.addSeparator() menuEdit.addAction(self.actionCut) menuEdit.addAction(self.actionCopy) menuEdit.addAction(self.actionPaste) menuEdit.addSeparator() if enchant is not None: menuSC = menuEdit.addMenu(self.tr('Spell check')) menuSC.addAction(self.actionEnableSC) menuSC.addAction(self.actionSetLocale) menuEdit.addAction(self.actionSearch) menuEdit.addAction(self.actionChangeEditorFont) menuEdit.addAction(self.actionChangePreviewFont) menuEdit.addSeparator() if len(availableMarkups) > 1: self.menuMode = menuEdit.addMenu(self.tr('Default markup')) for markupAction in markupActions: self.menuMode.addAction(markupAction) menuFormat = menuEdit.addMenu(self.tr('Formatting')) menuFormat.addAction(self.actionBold) menuFormat.addAction(self.actionItalic) menuFormat.addAction(self.actionUnderline) menuEdit.addAction(self.actionWebKit) menuEdit.addSeparator() menuEdit.addAction(self.actionViewHtml) menuEdit.addAction(self.actionPreview) menuEdit.addAction(self.actionTableMode) if ReTextFakeVimHandler: menuEdit.addAction(self.actionFakeVimMode) menuEdit.addSeparator() menuEdit.addAction(self.actionFullScreen) menuEdit.addAction(self.actionConfig) menuHelp.addAction(self.actionHelp) menuHelp.addSeparator() menuHelp.addAction(self.actionAbout) menuHelp.addAction(self.actionAboutQt) toolBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) toolBar.addAction(self.actionNew) toolBar.addSeparator() toolBar.addAction(self.actionOpen) toolBar.addAction(self.actionSave) toolBar.addAction(self.actionPrint) toolBar.addSeparator() toolBar.addAction(self.actionPreview) toolBar.addAction(self.actionFullScreen) self.editBar.addAction(self.actionUndo) self.editBar.addAction(self.actionRedo) self.editBar.addSeparator() self.editBar.addAction(self.actionCut) self.editBar.addAction(self.actionCopy) self.editBar.addAction(self.actionPaste) self.editBar.addSeparator() self.editBar.addWidget(self.formattingBox) self.editBar.addWidget(self.symbolBox) self.searchEdit = QLineEdit(self.searchBar) self.searchEdit.setPlaceholderText(self.tr('Search')) self.searchEdit.returnPressed.connect(self.find) self.replaceEdit = QLineEdit(self.searchBar) self.replaceEdit.setPlaceholderText(self.tr('Replace with')) self.replaceEdit.returnPressed.connect(self.find) self.csBox = QCheckBox(self.tr('Case sensitively'), self.searchBar) self.searchBar.addWidget(self.searchEdit) self.searchBar.addWidget(self.replaceEdit) self.searchBar.addSeparator() self.searchBar.addWidget(self.csBox) self.searchBar.addAction(self.actionFindPrev) self.searchBar.addAction(self.actionFind) self.searchBar.addAction(self.actionReplace) self.searchBar.addAction(self.actionCloseSearch) self.searchBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.searchBar.setVisible(False) self.autoSaveEnabled = globalSettings.autoSave if self.autoSaveEnabled: timer = QTimer(self) timer.start(60000) timer.timeout.connect(self.saveAll) self.ind = None if enchant is not None: self.sl = globalSettings.spellCheckLocale try: enchant.Dict(self.sl or None) except enchant.errors.Error as e: print(e, file=sys.stderr) globalSettings.spellCheck = False if globalSettings.spellCheck: self.actionEnableSC.setChecked(True) self.fileSystemWatcher = QFileSystemWatcher() self.fileSystemWatcher.fileChanged.connect(self.fileChanged)
def _init_ui(self): main_widget = QWidget(self) widget_box = QVBoxLayout(main_widget) graphics_tbr = QTabWidget(main_widget) copter_lbl = QLabel(main_widget) copter_lbl.setText(self.copter_name) copter_lbl.setObjectName("copter_lbl") name_font = QFont("Times", 20, QFont.Bold) copter_lbl.setFont(name_font) copter_lbl.setAlignment(Qt.AlignCenter) pg.setConfigOption('foreground', 'k') pg.setConfigOption('background', 'w') view3d_tab = Copter3DWidget(self) view3d_tab.setObjectName("view3d_tab") graphics_tbr.addTab(view3d_tab, "3D view") pos_tab = PlotWidget(graphics_tbr) pos_tab.setObjectName("pos_tab") pos_tab.plot_mode_changed.connect(self._change_pos_mode) name_lbl = pos_tab.findChild(QLabel, "name_lbl") name_lbl.setText("Position plot") name_lbl.show() plot_enabled_w = pos_tab.findChild(QWidget, "plot_enabled_w") plot_enabled_w.hide() self._init_plot(pos_tab) self.pos_curves = self._init_curves(pos_tab) graphics_tbr.addTab(pos_tab, "Position plots") rot_q_tab = PlotWidget(graphics_tbr) rot_q_tab.setObjectName("rot_q_tab") rot_q_tab.plot_mode_changed.connect(self._change_rot_mode) name_lbl = rot_q_tab.findChild(QLabel, "name_lbl") name_lbl.setText("Angular position plot") name_lbl.show() plot_enabled_w = rot_q_tab.findChild(QWidget, "plot_enabled_w") plot_enabled_w.hide() self._init_plot(rot_q_tab) self.rot_q_curves = self._init_curves(rot_q_tab) graphics_tbr.addTab(rot_q_tab, "Angular position plots") vel_tab = PlotWidget(graphics_tbr) vel_tab.setObjectName("vel_tab") name_lbl = vel_tab.findChild(QLabel, "name_lbl") name_lbl.setText("Velocity plot") name_lbl.show() plot_enabled_w = vel_tab.findChild(QWidget, "plot_enabled_w") plot_enabled_w.hide() plot_mode_w = vel_tab.findChild(QWidget, "plot_mode_w") plot_mode_w.hide() self._init_plot(vel_tab) self.vel_curves = self._init_curves(vel_tab) graphics_tbr.addTab(vel_tab, "Velocity plots") ang_vel_tab = PlotWidget(graphics_tbr) ang_vel_tab.setObjectName("ang_vel_tab") name_lbl = ang_vel_tab.findChild(QLabel, "name_lbl") name_lbl.setText("Angular velocity plot") name_lbl.show() plot_enabled_w = ang_vel_tab.findChild(QWidget, "plot_enabled_w") plot_enabled_w.hide() plot_mode_w = ang_vel_tab.findChild(QWidget, "plot_mode_w") plot_mode_w.hide() self._init_plot(ang_vel_tab) self.ang_vel_curves = self._init_curves(ang_vel_tab) graphics_tbr.addTab(ang_vel_tab, "Angular velocity plots") acel_tab = PlotWidget(graphics_tbr) acel_tab.setObjectName("acel_tab") name_lbl = acel_tab.findChild(QLabel, "name_lbl") name_lbl.setText("Acceleration plot") name_lbl.show() plot_enabled_w = acel_tab.findChild(QWidget, "plot_enabled_w") plot_enabled_w.hide() plot_mode_w = acel_tab.findChild(QWidget, "plot_mode_w") plot_mode_w.hide() self._init_plot(acel_tab) self.acel_curves = self._init_curves(acel_tab) graphics_tbr.addTab(acel_tab, "Acceleration plots") ang_acel_tab = PlotWidget(graphics_tbr) ang_acel_tab.setObjectName("ang_acel_tab") name_lbl = ang_acel_tab.findChild(QLabel, "name_lbl") name_lbl.setText("Angular acceleration plot") name_lbl.show() plot_enabled_w = ang_acel_tab.findChild(QWidget, "plot_enabled_w") plot_enabled_w.hide() plot_mode_w = ang_acel_tab.findChild(QWidget, "plot_mode_w") plot_mode_w.hide() self._init_plot(ang_acel_tab) self.ang_acel_curves = self._init_curves(ang_acel_tab) graphics_tbr.addTab(ang_acel_tab, "Angular acceleration plots") engine_pwm_tab = PlotWidget(graphics_tbr) engine_pwm_tab.setObjectName("engine_pwm_tab") name_lbl = engine_pwm_tab.findChild(QLabel, "name_lbl") name_lbl.setText("Engines PWM plot") name_lbl.show() plot_enabled_w = engine_pwm_tab.findChild(QWidget, "plot_enabled_w") plot_enabled_w.hide() plot_mode_w = engine_pwm_tab.findChild(QWidget, "plot_mode_w") plot_mode_w.hide() self._init_engines_plot(engine_pwm_tab) self.pwm_curves = self._init_curves(engine_pwm_tab) graphics_tbr.addTab(engine_pwm_tab, "Engines PWM plots") engine_pow_tab = PlotWidget(graphics_tbr) engine_pow_tab.setObjectName("engine_pow_tab") name_lbl = engine_pow_tab.findChild(QLabel, "name_lbl") name_lbl.setText("Engines power plot") name_lbl.show() plot_enabled_w = engine_pow_tab.findChild(QWidget, "plot_enabled_w") plot_enabled_w.hide() plot_mode_w = engine_pow_tab.findChild(QWidget, "plot_mode_w") plot_mode_w.hide() self._init_engines_plot(engine_pow_tab) self.pow_curves = self._init_curves(engine_pow_tab) graphics_tbr.addTab(engine_pow_tab, "Engines power plots") engine_ang_v_tab = PlotWidget(graphics_tbr) engine_ang_v_tab.setObjectName("engine_ang_v_tab") name_lbl = engine_ang_v_tab.findChild(QLabel, "name_lbl") name_lbl.setText("Engines angular velocity plot") name_lbl.show() plot_enabled_w = engine_ang_v_tab.findChild(QWidget, "plot_enabled_w") plot_enabled_w.hide() plot_mode_w = engine_ang_v_tab.findChild(QWidget, "plot_mode_w") plot_mode_w.hide() self._init_engines_plot(engine_ang_v_tab) self.eng_ang_v_curves = self._init_curves(engine_ang_v_tab) graphics_tbr.addTab(engine_ang_v_tab, "Engines angular velocity plots") left_spacer = QWidget() left_spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) right_spacer = QWidget() right_spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) control_tlbr = QToolBar(self) control_tlbr.setMovable(False) control_tlbr.addWidget(left_spacer) self.start_act = QAction(QIcon(__icon_dir__ + 'startIcon.png'), "Start simulation", self) self.start_act.setObjectName("start_act") self.start_act.setStatusTip("Start simulation") self.start_act.triggered.connect(self._start_video) control_tlbr.addAction(self.start_act) control_tlbr.addSeparator() self.pause_act = QAction(QIcon(__icon_dir__ + 'pauseIcon.png'), "Pause simulation", self) self.pause_act.setObjectName("pause_act") self.pause_act.setStatusTip("Pause simulation") self.pause_act.triggered.connect(self._pause_video) self.pause_act.setEnabled(False) control_tlbr.addAction(self.pause_act) control_tlbr.addSeparator() self.stop_act = QAction(QIcon(__icon_dir__ + 'stopIcon.png'), "Stop simulation", self) self.stop_act.setObjectName("stop_act") self.stop_act.setStatusTip("Stop simulation") self.stop_act.triggered.connect(self.stop_video) self.stop_act.setEnabled(False) control_tlbr.addAction(self.stop_act) control_tlbr.addWidget(right_spacer) tb_iconsize = QSize(50, 50) control_tlbr.setIconSize(tb_iconsize) slider = QRangeSlider() slider.setObjectName('slider') slider.setFixedHeight(25) slider.setMin(int(self.log_data[0, 0])) slider.setMax(int(self.log_data[0, -1]) + 1) slider.setEnd(int(self.log_data[0, -1]) + 1) slider.setStart(int(self.log_data[0, 0])) slider.setBackgroundStyle( 'background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #555, stop:1 #666);' ) slider.setSpanStyle( 'background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #282, stop:1 #393);' ) slider.setStyleSheet(""" QRangeSlider > QSplitter::handle { background: #000000; } QRangeSlider > QSplitter::handle:vertical { height: 4px; } QRangeSlider > QSplitter::handle:pressed { background: #7D7D7D; } """) slider.tail.setTextColor(210) slider.handle.setTextColor(0) slider.head.setTextColor(210) slider.startValueChanged.connect(self._change_start_index) slider.endValueChanged.connect(self._change_end_index) widget_box.addWidget(copter_lbl) widget_box.addWidget(graphics_tbr) widget_box.addWidget(slider) widget_box.addWidget(control_tlbr) main_widget.setLayout(widget_box) self.setCentralWidget(main_widget) return
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"))
def _createToolBars(self): penToolBar = QToolBar("Color", self) penToolBar.setIconSize(QSize(50, 50)) boardToolBar = QToolBar("Color", self) boardToolBar.setIconSize(QSize(50, 50)) actionBar = QToolBar("Action", self) actionBar.setIconSize(QSize(50, 50)) self.toolBars = [penToolBar, boardToolBar, actionBar] self.addToolBar(penToolBar) self.addToolBar(boardToolBar) self.addToolBar(Qt.LeftToolBarArea, actionBar) avail_colors = { 'red': Qt.red, 'green': Qt.green, 'blue': Qt.blue, 'cyan': Qt.cyan, 'magenta': Qt.magenta, 'yellow': Qt.yellow, 'black': Qt.black, 'white': Qt.white, 'orange': QColor('#ff8000'), 'gray': QColor('#808080'), } for acol in avail_colors: penToolBar.addAction( self.addAction(f'{acol}', self._getIcon('rect_filled', {'FILL': acol, 'STROKE': 'none'}), self.setColor(avail_colors[acol])) ) penToolBar.addAction(self.addAction(f'Color Picker', self._getIcon('color_picker'), self.colorPicker())) penToolBar.addAction(self.addAction(f'Eraser', self._getIcon('eraser'), self.setEraser())) actionBar.addAction(self.addAction("Path", self._getIcon('path'), self.setAction('drawPath'))) actionBar.addAction(self.addAction("Rect", self._getIcon('rect'), self.setAction('drawRect'))) actionBar.addAction(self.addAction("Line", self._getIcon('line'), self.setAction('drawLine'))) actionBar.addAction(self.addAction("Point", self._getIcon('dot'), self.setAction('drawDot'))) actionBar.addAction(self.addAction("Matplotlib chart", self._getIcon('mpl'), self.showChart())) lineTypeMenu = QMenu() lineTypeMenu.addAction(self.addAction('Solid', self._getIcon('line'), self.setStyle(Qt.SolidLine))) lineTypeMenu.addAction(self.addAction('Dashed', self._getIcon('line_dashed'), self.setStyle(Qt.DashLine))) lineTypeButton = QToolButton(self) lineTypeButton.setToolButtonStyle(Qt.ToolButtonIconOnly) lineTypeButton.setIcon(self._getIcon('line_type')) lineTypeButton.setPopupMode(QToolButton.InstantPopup) # MenuButtonPopup lineTypeButton.setMenu(lineTypeMenu) lineTypeButton.setToolTip('Line type') actionBar.addWidget(lineTypeButton) lineWidthMenu = QMenu() lineWidthMenu.addAction(self.addAction('Thin', self._getIcon('line_thin'), self.setWidth(width=3))) lineWidthMenu.addAction(self.addAction('Medium', self._getIcon('line_medium'), self.setWidth(width=15))) lineWidthMenu.addAction(self.addAction('Thick', self._getIcon('line_thick'), self.setWidth(width=25))) lineWidthButton = QToolButton(self) lineWidthButton.setToolButtonStyle(Qt.ToolButtonIconOnly) lineWidthButton.setIcon(self._getIcon('line_width')) lineWidthButton.setPopupMode(QToolButton.InstantPopup) lineWidthButton.setMenu(lineWidthMenu) lineWidthButton.setToolTip('Line width') actionBar.addWidget(lineWidthButton) boardToolBar.addAction(self.addAction("Whiteboard", self._getIcon('board', custom_colors_dict={'FILL': 'white'}), self.setupBoard(Qt.white))) boardToolBar.addAction(self.addAction("Blackboard", self._getIcon('board', custom_colors_dict={'FILL': 'black'}), self.setupBoard(Qt.black))) boardToolBar.addAction(self.addAction("Transparent", self._getIcon('board_transparent', custom_colors_dict={'FILL': 'black'}), self._clearBackground)) boardToolBar.addAction(self.addAction("Remove drawings", self._getIcon('remove'), self.removeDrawing())) actionBar.addAction(self.addAction("Save image", self._getIcon('save'), self.saveDrawing())) # self.style().standardIcon(QtWidgets.QStyle.SP_DialogSaveButton)
def __init__(self, myserver, status_bar, scan_root_dir, sim_name): QWidget.__init__(self) self.main_vbox = QVBoxLayout() self.tokens = tokens() self.sim_name = sim_name self.myserver = myserver self.status_bar = status_bar self.param_list = scan_items_get_list() #self.tab_label=tab_label self.sim_dir = os.path.join(scan_root_dir, sim_name) toolbar = QToolBar() toolbar.setIconSize(QSize(32, 32)) self.tb_add = QAction(icon_get("list-add"), _("Add parameter to scan"), self) self.tb_add.triggered.connect(self.callback_add_item) toolbar.addAction(self.tb_add) self.tb_minus = QAction(icon_get("list-remove"), _("Delete item"), self) self.tb_minus.triggered.connect(self.callback_delete_item) toolbar.addAction(self.tb_minus) self.tb_down = QAction(icon_get("go-down"), _("Move down"), self) self.tb_down.triggered.connect(self.callback_move_down) toolbar.addAction(self.tb_down) self.tb_up = QAction(icon_get("go-up"), _("Move up"), self) self.tb_up.triggered.connect(self.callback_move_up) toolbar.addAction(self.tb_up) #self.tb_notes = QAction(icon_get("go-down.png"), _("Notes"), self) #self.tb_notes.triggered.connect(self.callback_notes) #toolbar.addAction(self.tb_notes) #self.tb_notes = QAction(icon_get("select"), _("Select parameter to change"), self) #self.tb_notes.triggered.connect(self.callback_show_list) #toolbar.addAction(self.tb_notes) self.tb_command = QAction(icon_get("utilities-terminal"), _("Insert python command"), self) self.tb_command.triggered.connect(self.callback_insert_command) toolbar.addAction(self.tb_command) self.main_vbox.addWidget(toolbar) self.tab = QTableWidget() #self.tab.resizeColumnsToContents() self.tab.verticalHeader().setVisible(False) self.tab.setColumnCount(5) #if enable_betafeatures()==False: # self.tab.setColumnHidden(0, True) # self.tab.setColumnHidden(1, True) self.tab.setSelectionBehavior(QAbstractItemView.SelectRows) self.tab.setColumnWidth(2, 300) self.tab.setColumnWidth(3, 200) self.load() self.tab.cellChanged.connect(self.tab_changed) self.main_vbox.addWidget(self.tab) self.popMenu = QMenu(self) #self.mp_show_list=QAction(_("Select parameter to scan"), self) #self.mp_show_list.triggered.connect(self.callback_show_list) #self.popMenu.addAction(self.mp_show_list) self.popMenu.addSeparator() self.mp_delete = QAction(_("Delete item"), self) self.mp_delete.triggered.connect(self.callback_delete_item) self.popMenu.addAction(self.mp_delete) self.mp_copy = QAction(_("Copy"), self) self.mp_copy.triggered.connect(self.callback_copy_item) self.popMenu.addAction(self.mp_copy) self.mp_paste = QAction(_("Paste"), self) self.mp_paste.triggered.connect(self.callback_paste_item) self.popMenu.addAction(self.mp_paste) self.popMenu.addSeparator() self.mp_add = QAction(_("Add item"), self) self.mp_add.triggered.connect(self.callback_add_item) self.popMenu.addAction(self.mp_add) self.mp_down = QAction(_("Move down"), self) self.mp_down.triggered.connect(self.callback_move_down) self.popMenu.addAction(self.mp_down) self.mp_down = QAction(_("Move down"), self) self.mp_down.triggered.connect(self.callback_move_down) self.popMenu.addAction(self.mp_down) self.popMenu.addSeparator() self.setMinimumSize(700, 500) self.setLayout(self.main_vbox)
def __init__(self, context: ApplicationContext, manager: SoftwareManager, screen_size: QSize, i18n: I18n, manage_window: QWidget): super(PreparePanel, self).__init__() self.setWindowFlag(Qt.WindowCloseButtonHint, False) self.i18n = i18n self.context = context self.manage_window = manage_window self.setWindowTitle('{} ({})'.format( self.i18n['prepare_panel.title.start'].capitalize(), __app_name__)) self.setMinimumWidth(screen_size.width() * 0.5) self.setMinimumHeight(screen_size.height() * 0.35) self.setMaximumHeight(screen_size.height() * 0.95) self.setLayout(QVBoxLayout()) self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred) self.manager = manager self.tasks = {} self.ntasks = 0 self.ftasks = 0 self.self_close = False self.prepare_thread = Prepare(self.context, manager, self.i18n) self.prepare_thread.signal_register.connect(self.register_task) self.prepare_thread.signal_update.connect(self.update_progress) self.prepare_thread.signal_finished.connect(self.finish_task) self.prepare_thread.signal_started.connect(self.start) self.prepare_thread.signal_ask_password.connect(self.ask_root_password) self.signal_password_response.connect( self.prepare_thread.set_password_reply) self.check_thread = CheckFinished() self.signal_status.connect(self.check_thread.update) self.check_thread.signal_finished.connect(self.finish) self.skip_thread = EnableSkip() self.skip_thread.signal_timeout.connect(self._enable_skip_button) self.progress_thread = AnimateProgress() self.progress_thread.signal_change.connect(self._change_progress) self.label_top = QLabel() self.label_top.setText("{}...".format( self.i18n['prepare_panel.title.start'].capitalize())) self.label_top.setAlignment(Qt.AlignHCenter) self.label_top.setStyleSheet( "QLabel { font-size: 14px; font-weight: bold; }") self.layout().addWidget(self.label_top) self.layout().addWidget(QLabel()) self.table = QTableWidget() self.table.setStyleSheet( "QTableWidget { background-color: transparent; }") self.table.setFocusPolicy(Qt.NoFocus) self.table.setShowGrid(False) self.table.verticalHeader().setVisible(False) self.table.horizontalHeader().setVisible(False) self.table.horizontalHeader().setSizePolicy( QSizePolicy.MinimumExpanding, QSizePolicy.Preferred) self.table.setColumnCount(4) self.table.setHorizontalHeaderLabels(['' for _ in range(4)]) self.layout().addWidget(self.table) toolbar = QToolBar() self.bt_close = QPushButton(self.i18n['close'].capitalize()) self.bt_close.clicked.connect(self.close) self.bt_close.setVisible(False) self.ref_bt_close = toolbar.addWidget(self.bt_close) toolbar.addWidget(new_spacer()) self.progress_bar = QProgressBar() self.progress_bar.setMaximumHeight(10 if QApplication.instance().style( ).objectName().lower() == 'windows' else 4) self.progress_bar.setTextVisible(False) self.progress_bar.setVisible(False) self.ref_progress_bar = toolbar.addWidget(self.progress_bar) toolbar.addWidget(new_spacer()) self.bt_skip = QPushButton( self.i18n['prepare_panel.bt_skip.label'].capitalize()) self.bt_skip.clicked.connect(self.finish) self.bt_skip.setEnabled(False) toolbar.addWidget(self.bt_skip) self.layout().addWidget(toolbar)
def setupTextActions(self): tb = QToolBar(self) tb.setWindowTitle("Format Actions") self.addToolBar(tb) menu = QMenu("F&ormat", self) self.menuBar().addMenu(menu) self.actionTextBold = QAction(QIcon.fromTheme( 'format-text-bold', QIcon(rsrcPath + '/textbold.png')), "&Bold", self, priority=QAction.LowPriority, shortcut=Qt.CTRL + Qt.Key_B, triggered=self.textBold, checkable=True) bold = QFont() bold.setBold(True) self.actionTextBold.setFont(bold) tb.addAction(self.actionTextBold) menu.addAction(self.actionTextBold) self.actionTextItalic = QAction(QIcon.fromTheme( 'format-text-italic', QIcon(rsrcPath + '/textitalic.png')), "&Italic", self, priority=QAction.LowPriority, shortcut=Qt.CTRL + Qt.Key_I, triggered=self.textItalic, checkable=True) italic = QFont() italic.setItalic(True) self.actionTextItalic.setFont(italic) tb.addAction(self.actionTextItalic) menu.addAction(self.actionTextItalic) self.actionTextUnderline = QAction(QIcon.fromTheme( 'format-text-underline', QIcon(rsrcPath + '/textunder.png')), "&Underline", self, priority=QAction.LowPriority, shortcut=Qt.CTRL + Qt.Key_U, triggered=self.textUnderline, checkable=True) underline = QFont() underline.setUnderline(True) self.actionTextUnderline.setFont(underline) tb.addAction(self.actionTextUnderline) menu.addAction(self.actionTextUnderline) menu.addSeparator() grp = QActionGroup(self, triggered=self.textAlign) # Make sure the alignLeft is always left of the alignRight. if QApplication.isLeftToRight(): self.actionAlignLeft = QAction( QIcon.fromTheme('format-justify-left', QIcon(rsrcPath + '/textleft.png')), "&Left", grp) self.actionAlignCenter = QAction( QIcon.fromTheme('format-justify-center', QIcon(rsrcPath + '/textcenter.png')), "C&enter", grp) self.actionAlignRight = QAction( QIcon.fromTheme('format-justify-right', QIcon(rsrcPath + '/textright.png')), "&Right", grp) else: self.actionAlignRight = QAction( QIcon.fromTheme('format-justify-right', QIcon(rsrcPath + '/textright.png')), "&Right", grp) self.actionAlignCenter = QAction( QIcon.fromTheme('format-justify-center', QIcon(rsrcPath + '/textcenter.png')), "C&enter", grp) self.actionAlignLeft = QAction( QIcon.fromTheme('format-justify-left', QIcon(rsrcPath + '/textleft.png')), "&Left", grp) self.actionAlignJustify = QAction( QIcon.fromTheme('format-justify-fill', QIcon(rsrcPath + '/textjustify.png')), "&Justify", grp) self.actionAlignLeft.setShortcut(Qt.CTRL + Qt.Key_L) self.actionAlignLeft.setCheckable(True) self.actionAlignLeft.setPriority(QAction.LowPriority) self.actionAlignCenter.setShortcut(Qt.CTRL + Qt.Key_E) self.actionAlignCenter.setCheckable(True) self.actionAlignCenter.setPriority(QAction.LowPriority) self.actionAlignRight.setShortcut(Qt.CTRL + Qt.Key_R) self.actionAlignRight.setCheckable(True) self.actionAlignRight.setPriority(QAction.LowPriority) self.actionAlignJustify.setShortcut(Qt.CTRL + Qt.Key_J) self.actionAlignJustify.setCheckable(True) self.actionAlignJustify.setPriority(QAction.LowPriority) tb.addActions(grp.actions()) menu.addActions(grp.actions()) menu.addSeparator() pix = QPixmap(16, 16) pix.fill(Qt.black) self.actionTextColor = QAction(QIcon(pix), "&Color...", self, triggered=self.textColor) tb.addAction(self.actionTextColor) menu.addAction(self.actionTextColor) tb = QToolBar(self) tb.setAllowedAreas(Qt.TopToolBarArea | Qt.BottomToolBarArea) tb.setWindowTitle("Format Actions") self.addToolBarBreak(Qt.TopToolBarArea) self.addToolBar(tb) comboStyle = QComboBox(tb) tb.addWidget(comboStyle) comboStyle.addItem("Standard") comboStyle.addItem("Bullet List (Disc)") comboStyle.addItem("Bullet List (Circle)") comboStyle.addItem("Bullet List (Square)") comboStyle.addItem("Ordered List (Decimal)") comboStyle.addItem("Ordered List (Alpha lower)") comboStyle.addItem("Ordered List (Alpha upper)") comboStyle.addItem("Ordered List (Roman lower)") comboStyle.addItem("Ordered List (Roman upper)") comboStyle.activated.connect(self.textStyle) self.comboFont = QFontComboBox(tb) tb.addWidget(self.comboFont) self.comboFont.activated[str].connect(self.textFamily) self.comboSize = QComboBox(tb) self.comboSize.setObjectName("comboSize") tb.addWidget(self.comboSize) self.comboSize.setEditable(True) db = QFontDatabase() for size in db.standardSizes(): self.comboSize.addItem("%s" % (size)) self.comboSize.activated[str].connect(self.textSize) self.comboSize.setCurrentIndex( self.comboSize.findText("%s" % (QApplication.font().pointSize())))
def setupEditActions(self): tb = QToolBar(self) tb.setWindowTitle("Edit Actions") self.addToolBar(tb) menu = QMenu("&Edit", self) self.menuBar().addMenu(menu) self.actionUndo = QAction(QIcon.fromTheme( 'edit-undo', QIcon(rsrcPath + '/editundo.png')), "&Undo", self, shortcut=QKeySequence.Undo) tb.addAction(self.actionUndo) menu.addAction(self.actionUndo) self.actionRedo = QAction(QIcon.fromTheme( 'edit-redo', QIcon(rsrcPath + '/editredo.png')), "&Redo", self, priority=QAction.LowPriority, shortcut=QKeySequence.Redo) tb.addAction(self.actionRedo) menu.addAction(self.actionRedo) menu.addSeparator() self.actionCut = QAction(QIcon.fromTheme( 'edit-cut', QIcon(rsrcPath + '/editcut.png')), "Cu&t", self, priority=QAction.LowPriority, shortcut=QKeySequence.Cut) tb.addAction(self.actionCut) menu.addAction(self.actionCut) self.actionCopy = QAction(QIcon.fromTheme( 'edit-copy', QIcon(rsrcPath + '/editcopy.png')), "&Copy", self, priority=QAction.LowPriority, shortcut=QKeySequence.Copy) tb.addAction(self.actionCopy) menu.addAction(self.actionCopy) self.actionPaste = QAction( QIcon.fromTheme('edit-paste', QIcon(rsrcPath + '/editpaste.png')), "&Paste", self, priority=QAction.LowPriority, shortcut=QKeySequence.Paste, enabled=(len(QApplication.clipboard().text()) != 0)) tb.addAction(self.actionPaste) menu.addAction(self.actionPaste)
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)
class InfoTable(QTableWidget): def __init__(self, mainWindow): super().__init__() self.mainWindow = mainWindow self.isFree = True self.isConnected = True self.header = [] self.mThread = QThread() self.analyser = Analyser(self) self.analyser.moveToThread(self.mThread) self.analyser.startSignal.connect(self.analyser.analyse) self.analyser.progressSignal.connect( self.analyser.fileList.updateProgress) self.analyser.uploadSingal.connect(self.analyser.fileList.upload) # self.analyser.excelSignal.connect(self.analyser.infoTable.open) self.analyser.errorSignal.connect(self.analyser.fileList.error) self.analyser.closeSignal.connect(self.finishAnalyse) # self.mThread.started.connect(self.analyser.analyse) self.setColumnCount(0) self.setRowCount(0) self.setStyleSheet(uiConfig.INFOTABLE_S) self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) self.setVisible(True) self.createActions() self.createToolBar() self.itemSelectionChanged.connect(self.openImage) self.itemChanged.connect(self.updateValue) def updateValue(self, item): self.itemChanged.disconnect(self.updateValue) item.modify() self.changeItem(item.list_item.info_dict, item.row()) self.resizeCell() if self.isConnected: self.itemChanged.connect(self.updateValue) def openImage(self): row, col = self.currentRow(), self.currentColumn() if row >= 0: path = '' if col >= 2: if col == 4: col = 5 elif col == 5: col = 4 path = 'cache/img/' + str(row) + '_' + str(col - 2) + '.png' # else: # path = self.mainWindow.fileList.item(row).cpath if os.path.exists(path): self.mainWindow.imageArea.open(path) # TODO def open(self, fileName): if fileName: self.clear() df = pd.read_excel(fileName, header=0) # read file and set header row self.header = df.columns.ravel().tolist() for i in range(len(self.header)): self.header[i] = str(self.header[i]) self.setColumnCount(len(df.columns)) self.setRowCount(len(df.index)) self.setHorizontalHeaderLabels(self.header) for i in range(len(df.index)): for j in range(len(df.columns)): self.setItem(i, j, QTableWidgetItem(str(df.iat[i, j]))) self.resizeCell() def changeItem(self, info_dict, row): self.item(row, 0).setText(info_dict['name']) self.item(row, 1).setText(info_dict['type']) self.item(row, 2).setText(info_dict['left'] + ', ' + info_dict['up']) self.item(row, 3).setText(info_dict['right'] + ', ' + info_dict['up']) self.item(row, 4).setText(info_dict['left'] + ', ' + info_dict['down']) self.item(row, 5).setText(info_dict['right'] + ', ' + info_dict['down']) def insertRecord(self, info_dict): if self.header == [] or self.header == None: self.header = excelConfig.COL_TITLES self.setColumnCount(len(self.header)) self.setHorizontalHeaderLabels(self.header) row = self.rowCount() list_item = self.mainWindow.fileList.item(row) self.setRowCount(row + 1) try: self.itemChanged.disconnect(self.updateValue) except: pass self.setItem(row, 0, TableItem(info_dict['name'], list_item)) self.setItem(row, 1, TableItem(info_dict['type'], list_item)) self.setItem( row, 2, TableItem(info_dict['left'] + ', ' + info_dict['up'], list_item)) self.setItem( row, 3, TableItem(info_dict['right'] + ', ' + info_dict['up'], list_item)) self.setItem( row, 4, TableItem(info_dict['left'] + ', ' + info_dict['down'], list_item)) self.setItem( row, 5, TableItem(info_dict['right'] + ', ' + info_dict['down'], list_item)) self.resizeCell() if self.isConnected: self.itemChanged.connect(self.updateValue) def resizeCell(self): self.resizeColumnsToContents() self.resizeRowsToContents() # TODO def analyse(self): imagePath = [] self.clear() self.setRowCount(0) self.setColumnCount(0) self.header = [] for i in range(self.mainWindow.fileList.count()): self.mainWindow.fileList.item(i).updateProgress(-100) imagePath.append(self.mainWindow.fileList.item(i).cpath) # self.analyser.getImages(imagePath) self.mThread.start() self.analyser.getImages(imagePath) self.analyser.startSignal.emit() self.isFree = False self.updateActions() return def finishAnalyse(self): self.mThread.quit() self.isFree = True self.updateActions() def saveAsExcel(self): path = QFileDialog.getSaveFileName(self, '保存文件', '未命名', ".xls(*.xls)") try: filename = path[0] except: return wbk = xlwt.Workbook() self.sheet = wbk.add_sheet("sheet", cell_overwrite_ok=True) row = 0 col = 0 for i in range(self.columnCount()): self.sheet.write(0, i, self.header[i]) for i in range(self.columnCount()): for x in range(self.rowCount()): try: teext = str(self.item(row, col).text()) self.sheet.write(row + 1, col, teext) row += 1 except AttributeError: row += 1 row = 0 col += 1 wbk.save(filename) # TODO def saveAsWord(self): return def saveAsCSV(self): path = QFileDialog.getSaveFileName(self, '保存文件', '未命名', 'CSV(*.csv)') try: filename = path[0] except: return with open(filename, 'w', newline='') as stream: writer = csv.writer(stream) writer.writerow(self.header) for row in range(self.rowCount()): rowdata = [] for column in range(self.columnCount()): item = self.item(row, column) if item is not None: rowdata.append(item.text()) else: rowdata.append('') writer.writerow(rowdata) # TODO: Add Icon def createActions(self): # QIcon("images/control.png") self.analyseAct = self.formatAction("ui/images/run.jpg", "开始\n运行", enabled=False, triggered=self.analyse) self.saveAsExcelAct = self.formatAction("ui/images/save.jpg", "另存为\nExcel", enabled=False, triggered=self.saveAsExcel) self.saveAsWordAct = self.formatAction("ui/images/save.jpg", "另存为\nWord", enabled=False, triggered=self.saveAsWord) self.saveAsCSVAct = self.formatAction("ui/images/save.jpg", "另存为\nCSV", enabled=False, triggered=self.saveAsCSV) def formatAction(self, imagePath, text, shortcut=None, enabled=False, triggered=None): icon = QPixmap(imagePath) action = QAction(QIcon(icon), text, self, triggered=triggered) action.setEnabled(enabled) return action def createToolBar(self): self.toolBar = QToolBar() self.toolBar.addSeparator() self.toolBar.addAction(self.analyseAct) self.toolBar.addAction(self.saveAsExcelAct) self.toolBar.addAction(self.saveAsWordAct) self.toolBar.addAction(self.saveAsCSVAct) self.toolBar.setStyleSheet(uiConfig.TOOLBAR_S) self.mainWindow.addToolBar(Qt.TopToolBarArea, self.toolBar) def updateActions(self): self.analyseAct.setEnabled(self.mainWindow.fileList.count() and self.isFree) isSaveable = self.verticalHeader().count() self.saveAsExcelAct.setEnabled(isSaveable) self.saveAsWordAct.setEnabled(isSaveable) self.saveAsCSVAct.setEnabled(isSaveable) # TODO def changeContent(self): return
class CustomPlotWidget(PlotWidget): # pylint: disable=too-many-instance-attributes def __init__(self, parent=None, backend="matplotlib"): super().__init__(parent=parent, backend=backend) self.plotArea = self.getWidgetHandle() if sys.platform == "darwin": self.setIconSize(QSize(24, 24)) self.setActiveCurveHandling(False) self.setGraphGrid("both") self.addInteractiveToolBar() self.addMainToolBar() self.addProfileToolBar() self.addOutputToolBar() self.sigContentChanged.connect(self.setProfileToolBarVisibility) self.sigPlotSignal.connect(self.plotEvent) def plotEvent(self, event): if event["event"] == "mouseMoved": x, y = event["x"], event["y"] xPixel, yPixel = event["xpixel"], event["ypixel"] self.showPositionInfo(x, y, xPixel, yPixel) def showPositionInfo(self, x, y, xPixel, yPixel): # For images get also the data at the x and y coordinates. condition = lambda item: isinstance(item, items.ImageBase) data = None for picked in self.pickItems(xPixel, yPixel, condition): image = picked.getItem() indices = picked.getIndices(copy=False) if indices is not None: row, col = indices[0][0], indices[1][0] data = image.getData(copy=False)[row, col] for item in self.getItems(): if isinstance(item, items.Curve): message = "X: {:g} Y: {:g}".format(x, y) elif isinstance(item, items.ImageBase) and data is not None: message = "X: {:g} Y: {:g} Data: {:g}".format(x, y, data) else: message = None self.window().statusBar().showMessage(message) def contextMenuEvent(self, event): contextMenu = QMenu(self) zoomBackAction = ZoomBackAction(plot=self, parent=self) crosshairAction = CrosshairAction(plot=self, color="lime", parent=contextMenu) contextMenu.addAction(zoomBackAction) contextMenu.addAction(crosshairAction) contextMenu.exec_(event.globalPos()) def addInteractiveToolBar(self): self.interactiveToolBar = QToolBar("Interaction", parent=self) zoomModeAction = ZoomModeAction(plot=self, parent=self.interactiveToolBar) panModeAction = PanModeAction(plot=self, parent=self.interactiveToolBar) self.interactiveToolBar.addAction(zoomModeAction) self.interactiveToolBar.addAction(panModeAction) self.addToolBar(self.interactiveToolBar) def addMainToolBar(self): self.mainToolBar = QToolBar("Curve or Image", parent=self) self.resetZoomAction = ResetZoomAction(plot=self, parent=self.mainToolBar) self.xAxisAutoScaleAction = XAxisAutoScaleAction( plot=self, parent=self.mainToolBar) self.yAxisAutoScaleAction = YAxisAutoScaleAction( plot=self, parent=self.mainToolBar) self.curveStyleAction = CurveStyleAction(plot=self, parent=self.mainToolBar) self.colormapAction = ColormapAction(plot=self, parent=self.mainToolBar) self.keepAspectRatioAction = KeepAspectRatioAction( plot=self, parent=self.mainToolBar) self.gridAction = GridAction(plot=self, parent=self.mainToolBar) self.mainToolBar.addAction(self.resetZoomAction) self.mainToolBar.addAction(self.xAxisAutoScaleAction) self.mainToolBar.addAction(self.yAxisAutoScaleAction) self.mainToolBar.addAction(self.gridAction) self.mainToolBar.addAction(self.curveStyleAction) self.mainToolBar.addAction(self.colormapAction) self.mainToolBar.addAction(self.keepAspectRatioAction) self.addToolBar(self.mainToolBar) def addOutputToolBar(self): self.outputToolBar = QToolBar("IO", parent=self) self.copyAction = CopyAction(plot=self, parent=self.outputToolBar) self.saveAction = SaveAction(plot=self, parent=self.outputToolBar) self.outputToolBar.addAction(self.copyAction) self.outputToolBar.addAction(self.saveAction) self.addToolBar(self.outputToolBar) def addProfileToolBar(self): self.profileToolBar = QToolBar("Profile", parent=self) profileManager = ProfileManager(plot=self, parent=self.profileToolBar) profileManager.setProfileWindowClass(CustomProfileWindow) profileManager.setItemType(image=True) profileManager.setActiveItemTracking(True) roiManager = profileManager.getRoiManager() roiManager.sigInteractiveRoiCreated.connect(self.configureRois) horizontalLineAction = profileManager.createProfileAction( ProfileImageHorizontalLineROI, parent=self.profileToolBar) verticalLineAction = profileManager.createProfileAction( ProfileImageVerticalLineROI, parent=self.profileToolBar) crossLineAction = profileManager.createProfileAction( ProfileImageCrossROI, parent=self.profileToolBar) freeLineAction = profileManager.createProfileAction( ProfileImageLineROI, parent=self.profileToolBar) cleanAction = profileManager.createClearAction(self.profileToolBar) editorAction = profileManager.createEditorAction(self.profileToolBar) self.profileToolBar.addAction(horizontalLineAction) self.profileToolBar.addAction(verticalLineAction) self.profileToolBar.addAction(crossLineAction) self.profileToolBar.addAction(freeLineAction) self.profileToolBar.addAction(cleanAction) self.profileToolBar.addAction(editorAction) self.profileToolBar.setVisible(False) self.addToolBar(self.profileToolBar) def setProfileToolBarVisibility(self): imageBaseItems = [ item for item in self.getItems() if isinstance(item, items.ImageBase) ] if imageBaseItems: self.profileToolBar.setVisible(True) else: self.profileToolBar.setVisible(False) @staticmethod def configureRois(roi): roi.setName("") roi.setProfileMethod("sum") def reset(self): self.clear() self.setKeepDataAspectRatio(False) self.setGraphTitle() self.setGraphXLabel("X") self.setGraphXLimits(0, 100) self.setGraphYLabel("Y") self.setGraphYLimits(0, 100)
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 __init__(self, parent): super(VidCutter, self).__init__(parent) self.parent = parent self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.videoWidget = VideoWidget() self.videoService = VideoService(self) QFontDatabase.addApplicationFont( os.path.join(self.getAppPath(), 'fonts', 'DroidSansMono.ttf')) QFontDatabase.addApplicationFont( os.path.join(self.getAppPath(), 'fonts', 'HelveticaNeue.ttf')) qApp.setFont(QFont('Helvetica Neue', 10)) self.clipTimes = [] self.inCut = False self.movieFilename = '' self.movieLoaded = False self.timeformat = 'hh:mm:ss' self.finalFilename = '' self.totalRuntime = 0 self.initIcons() self.initActions() self.toolbar = QToolBar( floatable=False, movable=False, iconSize=QSize(28, 28), toolButtonStyle=Qt.ToolButtonTextUnderIcon, styleSheet= 'QToolBar QToolButton { min-width:82px; margin-left:10px; margin-right:10px; font-size:14px; }' ) self.initToolbar() self.aboutMenu, self.cliplistMenu = QMenu(), QMenu() self.initMenus() self.seekSlider = VideoSlider(parent=self, sliderMoved=self.setPosition) self.seekSlider.installEventFilter(self) self.initNoVideo() self.cliplist = QListWidget( sizePolicy=QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding), contextMenuPolicy=Qt.CustomContextMenu, uniformItemSizes=True, iconSize=QSize(100, 700), dragDropMode=QAbstractItemView.InternalMove, alternatingRowColors=True, customContextMenuRequested=self.itemMenu, styleSheet='QListView::item { margin:10px 5px; }') self.cliplist.setFixedWidth(185) self.cliplist.model().rowsMoved.connect(self.syncClipList) listHeader = QLabel(pixmap=QPixmap( os.path.join(self.getAppPath(), 'images', 'clipindex.png'), 'PNG'), alignment=Qt.AlignCenter) listHeader.setStyleSheet( '''padding:5px; padding-top:8px; border:1px solid #b9b9b9; border-bottom:none; background-color:qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFF, stop: 0.5 #EAEAEA, stop: 0.6 #EAEAEA stop:1 #FFF);''' ) self.runtimeLabel = QLabel('<div align="right">00:00:00</div>', textFormat=Qt.RichText) self.runtimeLabel.setStyleSheet( '''font-family:Droid Sans Mono; font-size:10pt; color:#FFF; background:rgb(106, 69, 114) url(:images/runtime.png) no-repeat left center; padding:2px; padding-right:8px; border:1px solid #b9b9b9; border-top:none;''' ) self.clipindexLayout = QVBoxLayout(spacing=0) self.clipindexLayout.setContentsMargins(0, 0, 0, 0) self.clipindexLayout.addWidget(listHeader) self.clipindexLayout.addWidget(self.cliplist) self.clipindexLayout.addWidget(self.runtimeLabel) self.videoLayout = QHBoxLayout() self.videoLayout.setContentsMargins(0, 0, 0, 0) self.videoLayout.addWidget(self.novideoWidget) self.videoLayout.addLayout(self.clipindexLayout) self.timeCounter = QLabel('00:00:00 / 00:00:00', autoFillBackground=True, alignment=Qt.AlignCenter, sizePolicy=QSizePolicy( QSizePolicy.Expanding, QSizePolicy.Fixed)) self.timeCounter.setStyleSheet( 'color:#FFF; background:#000; font-family:Droid Sans Mono; font-size:10.5pt; padding:4px;' ) videoplayerLayout = QVBoxLayout(spacing=0) videoplayerLayout.setContentsMargins(0, 0, 0, 0) videoplayerLayout.addWidget(self.videoWidget) videoplayerLayout.addWidget(self.timeCounter) self.videoplayerWidget = QWidget(self, visible=False) self.videoplayerWidget.setLayout(videoplayerLayout) self.menuButton = QPushButton(icon=self.aboutIcon, flat=True, toolTip='About', statusTip='About', iconSize=QSize(24, 24), cursor=Qt.PointingHandCursor) self.menuButton.setMenu(self.aboutMenu) self.muteButton = QPushButton(icon=self.unmuteIcon, flat=True, toolTip='Mute', statusTip='Toggle audio mute', cursor=Qt.PointingHandCursor, clicked=self.muteAudio) self.volumeSlider = QSlider(Qt.Horizontal, toolTip='Volume', statusTip='Adjust volume level', cursor=Qt.PointingHandCursor, value=50, sizePolicy=QSizePolicy( QSizePolicy.Fixed, QSizePolicy.Minimum), minimum=0, maximum=100, sliderMoved=self.setVolume) self.volumeSlider.setStyleSheet( '''QSlider::groove:horizontal { height:40px; } QSlider::sub-page:horizontal { border:1px outset #6A4572; background:#6A4572; margin:2px; } QSlider::handle:horizontal { image: url(:images/knob.png) no-repeat top left; width:20px; }''' ) self.saveAction = QPushButton( self.parent, icon=self.saveIcon, text='Save Video', flat=True, toolTip='Save Video', clicked=self.cutVideo, cursor=Qt.PointingHandCursor, iconSize=QSize(30, 30), statusTip='Save video clips merged as a new video file', enabled=False) self.saveAction.setStyleSheet( '''QPushButton { color:#FFF; padding:8px; font-size:12pt; border:1px inset #481953; border-radius:4px; background-color:rgb(106, 69, 114); } QPushButton:!enabled { background-color:rgba(0, 0, 0, 0.1); color:rgba(0, 0, 0, 0.3); border:1px inset #CDCDCD; } QPushButton:hover { background-color:rgba(255, 255, 255, 0.8); color:#444; } QPushButton:pressed { background-color:rgba(218, 218, 219, 0.8); color:#444; }''' ) controlsLayout = QHBoxLayout() controlsLayout.addStretch(1) controlsLayout.addWidget(self.toolbar) controlsLayout.addSpacerItem(QSpacerItem(20, 1)) controlsLayout.addWidget(self.saveAction) controlsLayout.addStretch(1) controlsLayout.addWidget(self.muteButton) controlsLayout.addWidget(self.volumeSlider) controlsLayout.addSpacing(1) controlsLayout.addWidget(self.menuButton) layout = QVBoxLayout() layout.setContentsMargins(10, 10, 10, 4) layout.addLayout(self.videoLayout) layout.addWidget(self.seekSlider) layout.addLayout(controlsLayout) self.setLayout(layout) self.mediaPlayer.setVideoOutput(self.videoWidget) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) self.mediaPlayer.error.connect(self.handleError)
def _set_col_actions(self, col: int, pkg: PackageView): item = QToolBar() item.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred) if pkg.model.installed: def run(): self.window.run_app(pkg) bt = IconButton(QIcon(resource.get_path('img/app_play.svg')), i18n=self.i18n, action=run, tooltip=self.i18n['action.run.tooltip']) bt.setEnabled(pkg.model.can_be_run()) item.addWidget(bt) def handle_click(): self.show_pkg_actions(pkg) settings = self.has_any_settings(pkg) if pkg.model.installed: bt = IconButton(QIcon(resource.get_path('img/app_actions.svg')), i18n=self.i18n, action=handle_click, tooltip=self.i18n['action.settings.tooltip']) bt.setEnabled(bool(settings)) item.addWidget(bt) if not pkg.model.installed: def get_screenshots(): self.window.get_screenshots(pkg) bt = IconButton(QIcon(resource.get_path('img/camera.svg')), i18n=self.i18n, action=get_screenshots, tooltip=self.i18n['action.screenshots.tooltip']) bt.setEnabled(bool(pkg.model.has_screenshots())) item.addWidget(bt) def get_info(): self.window.get_app_info(pkg) bt = IconButton(QIcon(resource.get_path('img/app_info.svg')), i18n=self.i18n, action=get_info, tooltip=self.i18n['action.info.tooltip']) bt.setEnabled(bool(pkg.model.has_info())) item.addWidget(bt) self.setCellWidget(pkg.table_index, col, item)
def measurement(self): toolbar = QToolBar() toolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) toolbar.setIconSize(QSize(42, 42)) self.tb_new = QAction(QIcon_load("document-new"), wrap_text(_("New measurement"), 2), self) toolbar.addAction(self.tb_new) self.tb_delete = QAction(QIcon_load("edit-delete"), wrap_text(_("Delete measurement"), 3), self) toolbar.addAction(self.tb_delete) self.tb_clone = QAction(QIcon_load("clone"), wrap_text(_("Clone measurement"), 3), self) toolbar.addAction(self.tb_clone) self.tb_rename = QAction(QIcon_load("rename"), wrap_text(_("Rename measurement"), 3), self) toolbar.addAction(self.tb_rename) spacer = QWidget() spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) toolbar.addWidget(spacer) self.home_help = QAction(QIcon_load("internet-web-browser"), _("Help"), self) toolbar.addAction(self.home_help) return toolbar
class PuttySessionM(QtWidgets.QWidget): def __init__(self): super(PuttySessionM, self).__init__() self.sessions = Sessions() self.init_ui() def init_ui(self): self.init_element() self.init_layout() self.init_slot() self.init_tray() self.setWindowTitle("PuttySessionPanel") self.setWindowIcon(QIcon(g_icon_name["software"])) self.setWindowFlags(Qt.WindowMinimizeButtonHint | Qt.WindowCloseButtonHint) self.sizeHint() self.setFixedSize(580, 160) self.close_confirm = False def init_tray(self): self.tray = QSystemTrayIcon() self.tray.setIcon(QIcon(g_icon_name["software"])) self.tray.activated.connect(self.tray_click) self.tray_restore = QAction("Restore", self, triggered=self.showNormal) self.tray_quit = QAction("Quit", self, triggered=self.close) self.tray_sessions = QMenu("Sessions", self) for session_name in self.session_names: session_name_action = QAction(session_name, self) session_name_action.triggered.connect( functools.partial(self.tray_session_open, session_name)) self.tray_sessions.addAction(session_name_action) self.tray_menu = QMenu(QApplication.desktop()) self.tray_menu.addAction(self.tray_restore) self.tray_menu.addAction(self.tray_quit) self.tray_menu.addMenu(self.tray_sessions) self.tray.setContextMenu(self.tray_menu) self.tray.show() def init_slot(self): self.open_btn.clicked.connect(self.putty_open) self.save_open_btn.clicked.connect(self.putty_save_and_open) self.session_list.itemClicked.connect(self.session_show) self.session_list.itemDoubleClicked.connect(self.session_show_and_open) self.session_remove.triggered.connect(self.session_del) self.session_add.triggered.connect(self.session_save) self.save_edit.returnPressed.connect(self.session_save) self.session_search.triggered.connect(self.session_search_slot) self.session_search_edit.returnPressed.connect( self.session_search_slot) def init_layout(self): self.session_grid = QGridLayout() self.session_grid.addWidget(self.ip_label, 0, 4, 1, 1) self.session_grid.addWidget(self.ip_edit, 0, 5, 1, 2) self.session_grid.addWidget(self.port_label, 0, 7, 1, 1) self.session_grid.addWidget(self.port_edit, 0, 8, 1, 1) self.session_grid.addWidget(self.user_label, 1, 4, 1, 1) self.session_grid.addWidget(self.user_edit, 1, 5, 1, 2) self.session_grid.addWidget(self.pwd_label, 2, 4, 1, 1) self.session_grid.addWidget(self.pwd_edit, 2, 5, 1, 2) self.session_grid.addWidget(self.save_label, 3, 4, 1, 1) self.session_grid.addWidget(self.save_edit, 3, 5, 1, 2) self.session_grid.addWidget(self.session_list, 0, 0, 4, 4) self.session_grid.addWidget(self.session_toolbar, 4, 0, 1, 4) self.session_grid.addWidget(self.open_btn, 4, 5, 1, 1) self.session_grid.addWidget(self.save_open_btn, 4, 6, 1, 1) self.setLayout(self.session_grid) def init_element(self): self.ip_label = QLabel("Host IP") self.ip_edit = QLineEdit() self.port_label = QLabel("Port") self.port_edit = QLineEdit() self.port_edit.setText("22") self.port_edit.setMaximumSize(QSize(40, 40)) self.user_label = QLabel("Username") self.user_edit = QLineEdit() self.pwd_label = QLabel("Password") self.pwd_edit = QLineEdit() self.pwd_edit.setEchoMode(QLineEdit.PasswordEchoOnEdit) self.save_label = QLabel("Saved as") self.save_edit = QLineEdit() self.save_open_btn = QPushButton("&Save and Open") self.save_open_btn.minimumSizeHint() self.open_btn = QPushButton("&Open") self.open_btn.minimumSizeHint() self.session_add = QAction(QIcon(g_icon_name["session_add"]), "Add", self) self.session_remove = QAction(QIcon(g_icon_name["session_remove"]), "Remove", self) self.session_search = QAction(QIcon(g_icon_name["session_search"]), "Search", self) self.session_search_edit = QLineEdit() self.session_toolbar = QToolBar("SesionTool") self.session_toolbar.addAction(self.session_add) self.session_toolbar.addAction(self.session_remove) self.session_toolbar.addAction(self.session_search) self.session_toolbar.addWidget(self.session_search_edit) self.session_list = QListWidget() self.session_names = self.sessions.get_session_names() self.session_list.addItems(self.session_names) def tray_session_open(self, session_name): session_attr = self.sessions.get_session_attr(session_name) host = session_attr.get("host", "") port = session_attr.get("port", "") user = session_attr.get("username", "") pawd = session_attr.get("passwd", "") self.shell_open_putty(host, port, user, pawd) def session_search_slot(self): self.session_list.clear() self.session_names = self.sessions.get_session_names() search_text = self.session_search_edit.text() if not search_text: self.session_list.addItems(self.session_names) return match_sesion_names = [] for session_name in self.session_names: if search_text in session_name: match_sesion_names.append(session_name) self.session_list.addItems(match_sesion_names) def session_save(self): if not self.check_input(): return host = self.ip_edit.text() port = self.port_edit.text() user = self.user_edit.text() pawd = self.pwd_edit.text() session_name = self.save_edit.text() if not session_name: session_name = "{0}@{1}".format(user, host) session_attr = { "host": host, "port": port, "username": user, "passwd": pawd } if self.sessions.is_new_session_name(session_name): self.session_list.addItem(session_name) session_name_action = QAction(session_name, self) session_name_action.triggered.connect( functools.partial(self.tray_session_open, session_name)) self.tray_sessions.addAction(session_name_action) self.sessions.save_session(session_name, session_attr) def session_del(self): current_item = self.session_list.currentItem() if current_item is None: QMessageBox.information(self, "Message", "Please select a session!") return session_name = current_item.text() reply = QMessageBox.question( self, "Message", "Are you sure to remove \"{0}\"?".format(session_name), QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) if reply == QMessageBox.No: return self.session_list.takeItem(self.session_list.currentRow()) for action in self.tray_sessions.actions(): if action.text() == session_name: self.tray_sessions.removeAction(action) break self.sessions.remove_session(session_name) def session_show_and_open(self): self.session_show() self.putty_open() def session_show(self): self.ip_edit.clear() self.port_edit.clear() self.user_edit.clear() self.pwd_edit.clear() self.save_edit.clear() session_name = self.session_list.currentItem().text() session_attr = self.sessions.get_session_attr(session_name) self.save_edit.setText(session_name) if "host" in session_attr: self.ip_edit.setText(session_attr["host"]) if "port" in session_attr: self.port_edit.setText(session_attr["port"]) if "username" in session_attr: self.user_edit.setText(session_attr["username"]) if "passwd" in session_attr: self.pwd_edit.setText(session_attr["passwd"]) def tray_click(self, click_way): if click_way == QSystemTrayIcon.DoubleClick: self.showNormal() self.setWindowState(Qt.WindowActive) def putty_save_and_open(self): if not self.putty_open(): return self.session_save() def putty_open(self): if not self.check_input(): return False host_ip = self.ip_edit.text() host_port = self.port_edit.text() user_name = self.user_edit.text() passwd = self.pwd_edit.text() self.shell_open_putty(host_ip, host_port, user_name, passwd) return True def check_input(self): ip_text = self.ip_edit.text() if not ip_text or not check_ip_validity(ip_text): QMessageBox.information(self, "Information", "Please input right Host IP") return False port_text = self.port_edit.text() if not port_text or not check_port_validity(port_text): QMessageBox.information(self, "Information", "Please input right Port") return False return True def shell_open_putty(self, host_ip, host_port, user_name, passwd): if not host_ip or not host_port: QMessageBox.information(self, "Information", "Please input Host IP and Port") return open_cmd = "putty -ssh -P {port}".format(port=host_port) if user_name and not has_special_chars(user_name): open_cmd = "{cmd} -l \"{user}\"".format(cmd=open_cmd, user=user_name) if passwd and not has_special_chars(passwd): open_cmd = "{cmd} -pw \"{pwd}\"".format(cmd=open_cmd, pwd=passwd) open_cmd = "{cmd} {ip}".format(cmd=open_cmd, ip=host_ip) # print("Open putty:", open_cmd) Popen(open_cmd) def keyPressEvent(self, event): if event.key() == Qt.Key_Escape: self.hide() def changeEvent(self, event): if self.isMinimized(): self.hide() def closeEvent(self, event): if not self.close_confirm: return reply = QMessageBox.question(self, "Message", "Are you sure to quit?", QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) if reply == QMessageBox.Yes: event.accept() else: event.ignore()
class VidCutter(QWidget): def __init__(self, parent): super(VidCutter, self).__init__(parent) self.parent = parent self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.videoWidget = VideoWidget() self.videoService = VideoService(self) QFontDatabase.addApplicationFont( os.path.join(self.getAppPath(), 'fonts', 'DroidSansMono.ttf')) QFontDatabase.addApplicationFont( os.path.join(self.getAppPath(), 'fonts', 'HelveticaNeue.ttf')) qApp.setFont(QFont('Helvetica Neue', 10)) self.clipTimes = [] self.inCut = False self.movieFilename = '' self.movieLoaded = False self.timeformat = 'hh:mm:ss' self.finalFilename = '' self.totalRuntime = 0 self.initIcons() self.initActions() self.toolbar = QToolBar( floatable=False, movable=False, iconSize=QSize(28, 28), toolButtonStyle=Qt.ToolButtonTextUnderIcon, styleSheet= 'QToolBar QToolButton { min-width:82px; margin-left:10px; margin-right:10px; font-size:14px; }' ) self.initToolbar() self.aboutMenu, self.cliplistMenu = QMenu(), QMenu() self.initMenus() self.seekSlider = VideoSlider(parent=self, sliderMoved=self.setPosition) self.seekSlider.installEventFilter(self) self.initNoVideo() self.cliplist = QListWidget( sizePolicy=QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding), contextMenuPolicy=Qt.CustomContextMenu, uniformItemSizes=True, iconSize=QSize(100, 700), dragDropMode=QAbstractItemView.InternalMove, alternatingRowColors=True, customContextMenuRequested=self.itemMenu, styleSheet='QListView::item { margin:10px 5px; }') self.cliplist.setFixedWidth(185) self.cliplist.model().rowsMoved.connect(self.syncClipList) listHeader = QLabel(pixmap=QPixmap( os.path.join(self.getAppPath(), 'images', 'clipindex.png'), 'PNG'), alignment=Qt.AlignCenter) listHeader.setStyleSheet( '''padding:5px; padding-top:8px; border:1px solid #b9b9b9; border-bottom:none; background-color:qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFF, stop: 0.5 #EAEAEA, stop: 0.6 #EAEAEA stop:1 #FFF);''' ) self.runtimeLabel = QLabel('<div align="right">00:00:00</div>', textFormat=Qt.RichText) self.runtimeLabel.setStyleSheet( '''font-family:Droid Sans Mono; font-size:10pt; color:#FFF; background:rgb(106, 69, 114) url(:images/runtime.png) no-repeat left center; padding:2px; padding-right:8px; border:1px solid #b9b9b9; border-top:none;''' ) self.clipindexLayout = QVBoxLayout(spacing=0) self.clipindexLayout.setContentsMargins(0, 0, 0, 0) self.clipindexLayout.addWidget(listHeader) self.clipindexLayout.addWidget(self.cliplist) self.clipindexLayout.addWidget(self.runtimeLabel) self.videoLayout = QHBoxLayout() self.videoLayout.setContentsMargins(0, 0, 0, 0) self.videoLayout.addWidget(self.novideoWidget) self.videoLayout.addLayout(self.clipindexLayout) self.timeCounter = QLabel('00:00:00 / 00:00:00', autoFillBackground=True, alignment=Qt.AlignCenter, sizePolicy=QSizePolicy( QSizePolicy.Expanding, QSizePolicy.Fixed)) self.timeCounter.setStyleSheet( 'color:#FFF; background:#000; font-family:Droid Sans Mono; font-size:10.5pt; padding:4px;' ) videoplayerLayout = QVBoxLayout(spacing=0) videoplayerLayout.setContentsMargins(0, 0, 0, 0) videoplayerLayout.addWidget(self.videoWidget) videoplayerLayout.addWidget(self.timeCounter) self.videoplayerWidget = QWidget(self, visible=False) self.videoplayerWidget.setLayout(videoplayerLayout) self.menuButton = QPushButton(icon=self.aboutIcon, flat=True, toolTip='About', statusTip='About', iconSize=QSize(24, 24), cursor=Qt.PointingHandCursor) self.menuButton.setMenu(self.aboutMenu) self.muteButton = QPushButton(icon=self.unmuteIcon, flat=True, toolTip='Mute', statusTip='Toggle audio mute', cursor=Qt.PointingHandCursor, clicked=self.muteAudio) self.volumeSlider = QSlider(Qt.Horizontal, toolTip='Volume', statusTip='Adjust volume level', cursor=Qt.PointingHandCursor, value=50, sizePolicy=QSizePolicy( QSizePolicy.Fixed, QSizePolicy.Minimum), minimum=0, maximum=100, sliderMoved=self.setVolume) self.volumeSlider.setStyleSheet( '''QSlider::groove:horizontal { height:40px; } QSlider::sub-page:horizontal { border:1px outset #6A4572; background:#6A4572; margin:2px; } QSlider::handle:horizontal { image: url(:images/knob.png) no-repeat top left; width:20px; }''' ) self.saveAction = QPushButton( self.parent, icon=self.saveIcon, text='Save Video', flat=True, toolTip='Save Video', clicked=self.cutVideo, cursor=Qt.PointingHandCursor, iconSize=QSize(30, 30), statusTip='Save video clips merged as a new video file', enabled=False) self.saveAction.setStyleSheet( '''QPushButton { color:#FFF; padding:8px; font-size:12pt; border:1px inset #481953; border-radius:4px; background-color:rgb(106, 69, 114); } QPushButton:!enabled { background-color:rgba(0, 0, 0, 0.1); color:rgba(0, 0, 0, 0.3); border:1px inset #CDCDCD; } QPushButton:hover { background-color:rgba(255, 255, 255, 0.8); color:#444; } QPushButton:pressed { background-color:rgba(218, 218, 219, 0.8); color:#444; }''' ) controlsLayout = QHBoxLayout() controlsLayout.addStretch(1) controlsLayout.addWidget(self.toolbar) controlsLayout.addSpacerItem(QSpacerItem(20, 1)) controlsLayout.addWidget(self.saveAction) controlsLayout.addStretch(1) controlsLayout.addWidget(self.muteButton) controlsLayout.addWidget(self.volumeSlider) controlsLayout.addSpacing(1) controlsLayout.addWidget(self.menuButton) layout = QVBoxLayout() layout.setContentsMargins(10, 10, 10, 4) layout.addLayout(self.videoLayout) layout.addWidget(self.seekSlider) layout.addLayout(controlsLayout) self.setLayout(layout) self.mediaPlayer.setVideoOutput(self.videoWidget) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) self.mediaPlayer.error.connect(self.handleError) def initNoVideo(self) -> None: novideoImage = QLabel(alignment=Qt.AlignCenter, autoFillBackground=False, pixmap=QPixmap( os.path.join(self.getAppPath(), 'images', 'novideo.png'), 'PNG'), sizePolicy=QSizePolicy( QSizePolicy.Expanding, QSizePolicy.MinimumExpanding)) novideoImage.setBackgroundRole(QPalette.Dark) novideoImage.setContentsMargins(0, 20, 0, 20) self.novideoLabel = QLabel(alignment=Qt.AlignCenter, autoFillBackground=True, sizePolicy=QSizePolicy( QSizePolicy.Expanding, QSizePolicy.Minimum)) self.novideoLabel.setBackgroundRole(QPalette.Dark) self.novideoLabel.setContentsMargins(0, 20, 15, 60) novideoLayout = QVBoxLayout(spacing=0) novideoLayout.addWidget(novideoImage) novideoLayout.addWidget(self.novideoLabel, alignment=Qt.AlignTop) self.novideoMovie = QMovie( os.path.join(self.getAppPath(), 'images', 'novideotext.gif')) self.novideoMovie.frameChanged.connect(self.setNoVideoText) self.novideoMovie.start() self.novideoWidget = QWidget(self, autoFillBackground=True) self.novideoWidget.setBackgroundRole(QPalette.Dark) self.novideoWidget.setLayout(novideoLayout) def initIcons(self) -> None: self.appIcon = QIcon( os.path.join(self.getAppPath(), 'images', 'vidcutter.png')) self.openIcon = QIcon( os.path.join(self.getAppPath(), 'images', 'addmedia.png')) self.playIcon = QIcon( os.path.join(self.getAppPath(), 'images', 'play.png')) self.pauseIcon = QIcon( os.path.join(self.getAppPath(), 'images', 'pause.png')) self.cutStartIcon = QIcon( os.path.join(self.getAppPath(), 'images', 'cut-start.png')) self.cutEndIcon = QIcon( os.path.join(self.getAppPath(), 'images', 'cut-end.png')) self.saveIcon = QIcon( os.path.join(self.getAppPath(), 'images', 'save.png')) self.muteIcon = QIcon( os.path.join(self.getAppPath(), 'images', 'muted.png')) self.unmuteIcon = QIcon( os.path.join(self.getAppPath(), 'images', 'unmuted.png')) self.upIcon = QIcon(os.path.join(self.getAppPath(), 'images', 'up.png')) self.downIcon = QIcon( os.path.join(self.getAppPath(), 'images', 'down.png')) self.removeIcon = QIcon( os.path.join(self.getAppPath(), 'images', 'remove.png')) self.removeAllIcon = QIcon( os.path.join(self.getAppPath(), 'images', 'remove-all.png')) self.successIcon = QIcon( os.path.join(self.getAppPath(), 'images', 'success.png')) self.aboutIcon = QIcon( os.path.join(self.getAppPath(), 'images', 'about.png')) self.completePlayIcon = QIcon( os.path.join(self.getAppPath(), 'images', 'complete-play.png')) self.completeOpenIcon = QIcon( os.path.join(self.getAppPath(), 'images', 'complete-open.png')) self.completeRestartIcon = QIcon( os.path.join(self.getAppPath(), 'images', 'complete-restart.png')) self.completeExitIcon = QIcon( os.path.join(self.getAppPath(), 'images', 'complete-exit.png')) def initActions(self) -> None: self.openAction = QAction(self.openIcon, 'Add Media', self, statusTip='Select media source', triggered=self.openFile) self.playAction = QAction(self.playIcon, 'Play Video', self, statusTip='Play selected media', triggered=self.playVideo, enabled=False) self.cutStartAction = QAction(self.cutStartIcon, 'Set Start', self, toolTip='Set Start', statusTip='Set start marker', triggered=self.cutStart, enabled=False) self.cutEndAction = QAction(self.cutEndIcon, 'Set End', self, statusTip='Set end marker', triggered=self.cutEnd, enabled=False) self.moveItemUpAction = QAction( self.upIcon, 'Move Up', self, statusTip='Move clip position up in list', triggered=self.moveItemUp, enabled=False) self.moveItemDownAction = QAction( self.downIcon, 'Move Down', self, statusTip='Move clip position down in list', triggered=self.moveItemDown, enabled=False) self.removeItemAction = QAction( self.removeIcon, 'Remove clip', self, statusTip='Remove selected clip from list', triggered=self.removeItem, enabled=False) self.removeAllAction = QAction(self.removeAllIcon, 'Clear list', self, statusTip='Clear all clips from list', triggered=self.clearList, enabled=False) self.aboutAction = QAction('About %s' % qApp.applicationName(), self, statusTip='Credits and acknowledgements', triggered=self.aboutInfo) self.aboutQtAction = QAction('About Qt', self, statusTip='About Qt', triggered=qApp.aboutQt) self.mediaInfoAction = QAction( 'Media Information', self, statusTip='Media information from loaded video file', triggered=self.mediaInfo, enabled=False) def initToolbar(self) -> None: self.toolbar.addAction(self.openAction) self.toolbar.addAction(self.playAction) self.toolbar.addSeparator() self.toolbar.addAction(self.cutStartAction) self.toolbar.addAction(self.cutEndAction) self.toolbar.addSeparator() def initMenus(self) -> None: self.aboutMenu.addAction(self.mediaInfoAction) self.aboutMenu.addSeparator() self.aboutMenu.addAction(self.aboutQtAction) self.aboutMenu.addAction(self.aboutAction) self.cliplistMenu.addAction(self.moveItemUpAction) self.cliplistMenu.addAction(self.moveItemDownAction) self.cliplistMenu.addSeparator() self.cliplistMenu.addAction(self.removeItemAction) self.cliplistMenu.addAction(self.removeAllAction) def setRunningTime(self, runtime: str) -> None: self.runtimeLabel.setText('<div align="right">%s</div>' % runtime) @pyqtSlot(int) def setNoVideoText(self, frame: int) -> None: self.novideoLabel.setPixmap(self.novideoMovie.currentPixmap()) def itemMenu(self, pos: QPoint) -> None: globalPos = self.cliplist.mapToGlobal(pos) self.moveItemUpAction.setEnabled(False) self.moveItemDownAction.setEnabled(False) self.removeItemAction.setEnabled(False) self.removeAllAction.setEnabled(False) index = self.cliplist.currentRow() if index != -1: if not self.inCut: if index > 0: self.moveItemUpAction.setEnabled(True) if index < self.cliplist.count() - 1: self.moveItemDownAction.setEnabled(True) if self.cliplist.count() > 0: self.removeItemAction.setEnabled(True) if self.cliplist.count() > 0: self.removeAllAction.setEnabled(True) self.cliplistMenu.exec_(globalPos) def moveItemUp(self) -> None: index = self.cliplist.currentRow() tmpItem = self.clipTimes[index] del self.clipTimes[index] self.clipTimes.insert(index - 1, tmpItem) self.renderTimes() def moveItemDown(self) -> None: index = self.cliplist.currentRow() tmpItem = self.clipTimes[index] del self.clipTimes[index] self.clipTimes.insert(index + 1, tmpItem) self.renderTimes() def removeItem(self) -> None: index = self.cliplist.currentRow() del self.clipTimes[index] if self.inCut and index == self.cliplist.count() - 1: self.inCut = False self.initMediaControls() self.renderTimes() def clearList(self) -> None: self.clipTimes.clear() self.cliplist.clear() self.inCut = False self.renderTimes() self.initMediaControls() def mediaInfo(self) -> None: if self.mediaPlayer.isMetaDataAvailable(): content = '<table cellpadding="4">' for key in self.mediaPlayer.availableMetaData(): val = self.mediaPlayer.metaData(key) if type(val) is QSize: val = '%s x %s' % (val.width(), val.height()) content += '<tr><td align="right"><b>%s:</b></td><td>%s</td></tr>\n' % ( key, val) content += '</table>' mbox = QMessageBox(windowTitle='Media Information', windowIcon=self.parent.windowIcon(), textFormat=Qt.RichText) mbox.setText('<b>%s</b>' % os.path.basename( self.mediaPlayer.currentMedia().canonicalUrl().toLocalFile())) mbox.setInformativeText(content) mbox.exec_() else: QMessageBox.critical( self.parent, 'Could not retrieve media information', '''There was a problem in tring to retrieve media information. This DOES NOT mean there is a problem with the file and you should be able to continue using it.''') def aboutInfo(self) -> None: about_html = '''<style> a { color:#441d4e; text-decoration:none; font-weight:bold; } a:hover { text-decoration:underline; } </style> <p style="font-size:26pt; font-weight:bold;">%s</p> <p> <span style="font-size:13pt;"><b>Version: %s</b></span> <span style="font-size:10pt;position:relative;left:5px;">( %s )</span> </p> <p style="font-size:13px;"> Copyright © 2016 <a href="mailto:[email protected]">Pete Alexandrou</a> <br/> Website: <a href="%s">%s</a> </p> <p style="font-size:13px;"> Thanks to the folks behind the <b>Qt</b>, <b>PyQt</b> and <b>FFmpeg</b> projects for all their hard and much appreciated work. </p> <p style="font-size:11px;"> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. </p> <p style="font-size:11px;"> This software uses libraries from the <a href="https://www.ffmpeg.org">FFmpeg</a> project under the <a href="https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html">LGPLv2.1</a> </p>''' % (qApp.applicationName(), qApp.applicationVersion(), platform.architecture()[0], qApp.organizationDomain(), qApp.organizationDomain()) QMessageBox.about(self.parent, 'About %s' % qApp.applicationName(), about_html) def openFile(self) -> None: filename, _ = QFileDialog.getOpenFileName(self.parent, caption='Select video', directory=QDir.homePath()) if filename != '': self.loadFile(filename) def loadFile(self, filename: str) -> None: self.movieFilename = filename if not os.path.exists(filename): return self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(filename))) self.initMediaControls(True) self.cliplist.clear() self.clipTimes = [] self.parent.setWindowTitle( '%s - %s' % (qApp.applicationName(), os.path.basename(filename))) if not self.movieLoaded: self.videoLayout.replaceWidget(self.novideoWidget, self.videoplayerWidget) self.novideoMovie.stop() self.novideoMovie.deleteLater() self.novideoWidget.deleteLater() self.videoplayerWidget.show() self.videoWidget.show() self.movieLoaded = True if self.mediaPlayer.isVideoAvailable(): self.mediaPlayer.setPosition(1) self.mediaPlayer.play() self.mediaPlayer.pause() def playVideo(self) -> None: if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() self.playAction.setText('Play Video') else: self.mediaPlayer.play() self.playAction.setText('Pause Video') def initMediaControls(self, flag: bool = True) -> None: self.playAction.setEnabled(flag) self.saveAction.setEnabled(False) self.cutStartAction.setEnabled(flag) self.cutEndAction.setEnabled(False) self.mediaInfoAction.setEnabled(flag) if flag: self.seekSlider.setRestrictValue(0) def setPosition(self, position: int) -> None: self.mediaPlayer.setPosition(position) def positionChanged(self, progress: int) -> None: self.seekSlider.setValue(progress) currentTime = self.deltaToQTime(progress) totalTime = self.deltaToQTime(self.mediaPlayer.duration()) self.timeCounter.setText('%s / %s' % (currentTime.toString( self.timeformat), totalTime.toString(self.timeformat))) @pyqtSlot() def mediaStateChanged(self) -> None: if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playAction.setIcon(self.pauseIcon) else: self.playAction.setIcon(self.playIcon) def durationChanged(self, duration: int) -> None: self.seekSlider.setRange(0, duration) def muteAudio(self, muted: bool) -> None: if self.mediaPlayer.isMuted(): self.mediaPlayer.setMuted(not self.mediaPlayer.isMuted()) self.muteButton.setIcon(self.unmuteIcon) self.muteButton.setToolTip('Mute') else: self.mediaPlayer.setMuted(not self.mediaPlayer.isMuted()) self.muteButton.setIcon(self.muteIcon) self.muteButton.setToolTip('Unmute') def setVolume(self, volume: int) -> None: self.mediaPlayer.setVolume(volume) def toggleFullscreen(self) -> None: self.videoWidget.setFullScreen(not self.videoWidget.isFullScreen()) def cutStart(self) -> None: self.clipTimes.append([ self.deltaToQTime(self.mediaPlayer.position()), '', self.captureImage() ]) self.cutStartAction.setDisabled(True) self.cutEndAction.setEnabled(True) self.seekSlider.setRestrictValue(self.seekSlider.value() + 1000) self.mediaPlayer.setPosition(self.seekSlider.restrictValue) self.inCut = True self.renderTimes() def cutEnd(self) -> None: item = self.clipTimes[len(self.clipTimes) - 1] selected = self.deltaToQTime(self.mediaPlayer.position()) if selected.__lt__(item[0]): QMessageBox.critical( self.parent, 'Invalid END Time', 'The clip end time must come AFTER it\'s start time. Please try again.' ) return item[1] = selected self.cutStartAction.setEnabled(True) self.cutEndAction.setDisabled(True) self.seekSlider.setRestrictValue(0) self.inCut = False self.renderTimes() @pyqtSlot(QModelIndex, int, int, QModelIndex, int) def syncClipList(self, parent: QModelIndex, start: int, end: int, destination: QModelIndex, row: int) -> None: if start < row: index = row - 1 else: index = row clip = self.clipTimes.pop(start) self.clipTimes.insert(index, clip) def renderTimes(self) -> None: self.cliplist.clear() self.seekSlider.setCutMode(self.inCut) if len(self.clipTimes) > 4: self.cliplist.setFixedWidth(200) else: self.cliplist.setFixedWidth(185) self.totalRuntime = 0 for item in self.clipTimes: endItem = '' if type(item[1]) is QTime: endItem = item[1].toString(self.timeformat) self.totalRuntime += item[0].msecsTo(item[1]) listitem = QListWidgetItem() listitem.setTextAlignment(Qt.AlignVCenter) if type(item[2]) is QPixmap: listitem.setIcon(QIcon(item[2])) self.cliplist.addItem(listitem) marker = QLabel( '''<style>b { font-size:8pt; } p { margin:5px; }</style> <p><b>START</b><br/>%s</p><p><b>END</b><br/>%s</p>''' % (item[0].toString(self.timeformat), endItem)) self.cliplist.setItemWidget(listitem, marker) listitem.setFlags(Qt.ItemIsSelectable | Qt.ItemIsDragEnabled | Qt.ItemIsEnabled) if len(self.clipTimes) and not self.inCut: self.saveAction.setEnabled(True) if self.inCut or len(self.clipTimes) == 0 or not type( self.clipTimes[0][1]) is QTime: self.saveAction.setEnabled(False) self.setRunningTime( self.deltaToQTime(self.totalRuntime).toString(self.timeformat)) @staticmethod def deltaToQTime(millisecs: int) -> QTime: secs = millisecs / 1000 return QTime((secs / 3600) % 60, (secs / 60) % 60, secs % 60, (secs * 1000) % 1000) def captureImage(self) -> None: frametime = self.deltaToQTime( self.mediaPlayer.position()).addSecs(1).toString(self.timeformat) inputfile = self.mediaPlayer.currentMedia().canonicalUrl().toLocalFile( ) imagecap = self.videoService.capture(inputfile, frametime) if type(imagecap) is QPixmap: return imagecap def cutVideo(self) -> bool: self.setCursor(Qt.BusyCursor) clips = len(self.clipTimes) filename, filelist = '', [] source = self.mediaPlayer.currentMedia().canonicalUrl().toLocalFile() _, sourceext = os.path.splitext(source) if clips > 0: self.finalFilename, _ = QFileDialog.getSaveFileName( self.parent, 'Save video', source, 'Video files (*%s)' % sourceext) if self.finalFilename != '': self.saveAction.setDisabled(True) self.showProgress(clips) file, ext = os.path.splitext(self.finalFilename) index = 1 self.progress.setLabelText('Cutting video clips...') qApp.processEvents() for clip in self.clipTimes: duration = self.deltaToQTime(clip[0].msecsTo( clip[1])).toString(self.timeformat) filename = '%s_%s%s' % (file, '{0:0>2}'.format(index), ext) filelist.append(filename) self.videoService.cut(source, filename, clip[0].toString(self.timeformat), duration) index += 1 if len(filelist) > 1: self.joinVideos(filelist, self.finalFilename) else: QFile.remove(self.finalFilename) QFile.rename(filename, self.finalFilename) self.unsetCursor() self.progress.setLabelText('Complete...') qApp.processEvents() self.saveAction.setEnabled(True) self.progress.close() self.progress.deleteLater() self.complete() self.saveAction.setEnabled(True) self.unsetCursor() self.saveAction.setDisabled(True) return True self.unsetCursor() self.saveAction.setDisabled(True) return False def joinVideos(self, joinlist: list, filename: str) -> None: listfile = os.path.normpath( os.path.join(os.path.dirname(joinlist[0]), '.vidcutter.list')) fobj = open(listfile, 'w') for file in joinlist: fobj.write('file \'%s\'\n' % file.replace("'", "\\'")) fobj.close() self.videoService.join(listfile, filename) try: QFile.remove(listfile) for file in joinlist: if os.path.isfile(file): QFile.remove(file) except: pass def showProgress(self, steps: int, label: str = 'Processing video...') -> None: self.progress = QProgressDialog(label, None, 0, steps, self.parent, windowModality=Qt.ApplicationModal, windowIcon=self.parent.windowIcon(), minimumDuration=0, minimumWidth=500) self.progress.show() for i in range(steps): self.progress.setValue(i) qApp.processEvents() time.sleep(1) def complete(self) -> None: info = QFileInfo(self.finalFilename) mbox = QMessageBox(windowTitle='Success', windowIcon=self.parent.windowIcon(), minimumWidth=500, iconPixmap=self.successIcon.pixmap(48, 49), textFormat=Qt.RichText) mbox.setText( ''' <style> table.info { margin:8px; padding:4px 15px; } td.label { font-weight:bold; font-size:9pt; text-align:right; background-color:#444; color:#FFF; } td.value { background-color:#FFF !important; font-size:10pt; } </style> <p>Your video was successfully created.</p> <p align="center"> <table class="info" cellpadding="6" cellspacing="0"> <tr> <td class="label"><b>Filename</b></td> <td class="value" nowrap>%s</td> </tr> <tr> <td class="label"><b>Size</b></td> <td class="value">%s</td> </tr> <tr> <td class="label"><b>Runtime</b></td> <td class="value">%s</td> </tr> </table> </p> <p>How would you like to proceed?</p>''' % (QDir.toNativeSeparators( self.finalFilename), self.sizeof_fmt(int(info.size())), self.deltaToQTime(self.totalRuntime).toString(self.timeformat))) play = mbox.addButton('Play', QMessageBox.AcceptRole) play.setIcon(self.completePlayIcon) play.clicked.connect(self.openResult) fileman = mbox.addButton('Open', QMessageBox.AcceptRole) fileman.setIcon(self.completeOpenIcon) fileman.clicked.connect(self.openFolder) end = mbox.addButton('Exit', QMessageBox.AcceptRole) end.setIcon(self.completeExitIcon) end.clicked.connect(self.close) new = mbox.addButton('Restart', QMessageBox.AcceptRole) new.setIcon(self.completeRestartIcon) new.clicked.connect(self.startNew) mbox.setDefaultButton(new) mbox.setEscapeButton(new) mbox.exec_() def sizeof_fmt(self, num: float, suffix: chr = 'B') -> str: for unit in ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z']: if abs(num) < 1024.0: return "%3.1f%s%s" % (num, unit, suffix) num /= 1024.0 return "%.1f%s%s" % (num, 'Y', suffix) @pyqtSlot() def openFolder(self) -> None: self.openResult(pathonly=True) @pyqtSlot(bool) def openResult(self, pathonly: bool = False) -> None: self.startNew() if len(self.finalFilename) and os.path.exists(self.finalFilename): target = self.finalFilename if not pathonly else os.path.dirname( self.finalFilename) QDesktopServices.openUrl(QUrl.fromLocalFile(target)) @pyqtSlot() def startNew(self) -> None: self.unsetCursor() self.clearList() self.seekSlider.setValue(0) self.seekSlider.setRange(0, 0) self.mediaPlayer.setMedia(QMediaContent()) self.initNoVideo() self.videoLayout.replaceWidget(self.videoplayerWidget, self.novideoWidget) self.initMediaControls(False) self.parent.setWindowTitle('%s' % qApp.applicationName()) def wheelEvent(self, event: QWheelEvent) -> None: if self.mediaPlayer.isVideoAvailable( ) or self.mediaPlayer.isAudioAvailable(): if event.angleDelta().y() > 0: newval = self.seekSlider.value() - 1000 else: newval = self.seekSlider.value() + 1000 self.seekSlider.setValue(newval) self.seekSlider.setSliderPosition(newval) self.mediaPlayer.setPosition(newval) event.accept() def keyPressEvent(self, event: QKeyEvent) -> None: if self.mediaPlayer.isVideoAvailable( ) or self.mediaPlayer.isAudioAvailable(): addtime = 0 if event.key() == Qt.Key_Left: addtime = -1000 elif event.key() == Qt.Key_PageUp or event.key() == Qt.Key_Up: addtime = -10000 elif event.key() == Qt.Key_Right: addtime = 1000 elif event.key() == Qt.Key_PageDown or event.key() == Qt.Key_Down: addtime = 10000 elif event.key() == Qt.Key_Enter: self.toggleFullscreen() elif event.key( ) == Qt.Key_Escape and self.videoWidget.isFullScreen(): self.videoWidget.setFullScreen(False) if addtime != 0: newval = self.seekSlider.value() + addtime self.seekSlider.setValue(newval) self.seekSlider.setSliderPosition(newval) self.mediaPlayer.setPosition(newval) event.accept() def mousePressEvent(self, event: QMouseEvent) -> None: if event.button() == Qt.BackButton and self.cutStartAction.isEnabled(): self.cutStart() event.accept() elif event.button( ) == Qt.ForwardButton and self.cutEndAction.isEnabled(): self.cutEnd() event.accept() else: super(VidCutter, self).mousePressEvent(event) def eventFilter(self, obj: QObject, event: QEvent) -> bool: if event.type() == QEvent.MouseButtonRelease and isinstance( obj, VideoSlider): if obj.objectName() == 'VideoSlider' and ( self.mediaPlayer.isVideoAvailable() or self.mediaPlayer.isAudioAvailable()): obj.setValue( QStyle.sliderValueFromPosition(obj.minimum(), obj.maximum(), event.x(), obj.width())) self.mediaPlayer.setPosition(obj.sliderPosition()) return QWidget.eventFilter(self, obj, event) @pyqtSlot(QMediaPlayer.Error) def handleError(self, error: QMediaPlayer.Error) -> None: self.unsetCursor() self.startNew() if error == QMediaPlayer.ResourceError: QMessageBox.critical( self.parent, 'Error', 'Invalid media file detected at:<br/><br/><b>%s</b><br/><br/>%s' % (self.movieFilename, self.mediaPlayer.errorString())) else: QMessageBox.critical(self.parent, 'Error', self.mediaPlayer.errorString()) def getAppPath(self) -> str: return ':' def closeEvent(self, event: QCloseEvent) -> None: self.parent.closeEvent(event)
def __init__(self, parent=None): QMainWindow.__init__(self, parent) self.interface_lng_val = 'Russian' if self.interface_lng_val == 'Russian': self.setWindowTitle("Графический интерфейс программы OpenFOAM") elif self.interface_lng_val == 'English': self.setWindowTitle("OpenFOAM_decompose_GUI") # Базовые переменные self.full_dir = '' self.prj_name = '' self.con = '' self.lock_bool = False self.application = '' self.object_edit_txt = '' # ---------------------------Панель управления подготовкой задачи МСС----------------------------- # self.proj_open = QAction(self) self.proj_open.setEnabled(True) proj_ico = self.style().standardIcon(QStyle.SP_ArrowUp) self.proj_open.setIcon(proj_ico) if self.interface_lng_val == 'Russian': self.proj_open.setToolTip('Открыть проект') elif self.interface_lng_val == 'English': self.proj_open.setToolTip('Open the project') self.lng_chs = QAction(self) self.lng_chs.setEnabled(True) lng_chs_ico = self.style().standardIcon( QStyle.SP_FileDialogDetailedView) self.lng_chs.setIcon(lng_chs_ico) if self.interface_lng_val == 'Russian': self.lng_chs.setToolTip('Выбрать язык интерфейса программы') elif self.interface_lng_val == 'English': self.lng_chs.setToolTip('Select the interface language') self.file_open = QAction(self) self.file_open.setEnabled(False) file_open_ico = self.style().standardIcon(QStyle.SP_FileIcon) self.file_open.setIcon(file_open_ico) if self.interface_lng_val == 'Russian': self.file_open.setToolTip( 'Открыть форму создания служебного файла для директории 0') elif self.interface_lng_val == 'English': self.file_open.setToolTip( 'Open the form for creating the service file for the directory 0' ) self.toolBar_1 = QToolBar("MyToolBar") self.toolBar_1.addAction(self.proj_open) self.toolBar_1.addAction(self.lng_chs) self.toolBar_1.addAction(self.file_open) self.proj_open.triggered.connect( lambda: first_toolbar_functions_class.on_proj_open(self)) self.lng_chs.triggered.connect( lambda: first_toolbar_functions_class.on_lng_chs(self)) self.file_open.triggered.connect( lambda: first_toolbar_functions_class.on_0_files_window_chs(self)) self.addToolBar(self.toolBar_1) ###----------------------Панель управления подготовкой РС--------------------------### self.msh_open = QAction(self) self.msh_open.setEnabled(False) msh_ico = self.style().standardIcon(QStyle.SP_FileDialogNewFolder) self.msh_open.setIcon(msh_ico) if self.interface_lng_val == 'Russian': self.msh_open.setToolTip('Открыть форму выбора расчетной сетки') elif self.interface_lng_val == 'English': self.msh_open.setToolTip('Open the mesh selection form') self.msh_run = QAction(self) self.msh_run.setEnabled(False) msh_ico = self.style().standardIcon(QStyle.SP_ArrowRight) self.msh_run.setIcon(msh_ico) if self.interface_lng_val == 'Russian': self.msh_run.setToolTip('Выполнить генерацию расчетной сетки') elif self.interface_lng_val == 'English': self.msh_run.setToolTip('Make the mesh generation') self.msh_visual = QAction(self) self.msh_visual.setEnabled(False) msh_visual_ico = self.style().standardIcon(QStyle.SP_MediaSeekForward) self.msh_visual.setIcon(msh_visual_ico) if self.interface_lng_val == 'Russian': self.msh_visual.setToolTip( 'Выполнить визуализацию расчетной сетки') elif self.interface_lng_val == 'English': self.msh_visual.setToolTip('Make the mesh visualization') self.toolBar_2 = QToolBar() self.toolBar_2.addAction(self.msh_open) self.toolBar_2.addAction(self.msh_run) self.toolBar_2.addAction(self.msh_visual) self.msh_open.triggered.connect( lambda: second_toolbar_functions_class.on_msh_open(self)) self.msh_run.triggered.connect( lambda: second_toolbar_functions_class.on_msh_run( prj_path_val, mesh_name_txt_val, pp_dir, self, self. interface_lng_val, msh_type)) self.msh_visual.triggered.connect( lambda: second_toolbar_functions_class.on_visual_msh_run( prj_path_val, mesh_name_txt_val, pp_dir, self, self. interface_lng_val, msh_type)) self.addToolBar(self.toolBar_2) self.insertToolBarBreak(self.toolBar_2) ###----------------------Панель управления решением задачи МСС--------------------------### self.solv_run = QAction(self) self.solv_run.setEnabled(False) solv_run_ico = self.style().standardIcon(QStyle.SP_DialogNoButton) self.solv_run.setIcon(solv_run_ico) if self.interface_lng_val == 'Russian': self.solv_run.setToolTip('Выполнить решение') elif self.interface_lng_val == 'English': self.solv_run.setToolTip('Run solution') self.solv_stop = QAction(self) self.solv_stop.setEnabled(False) close_ico = self.style().standardIcon(QStyle.SP_DockWidgetCloseButton) self.solv_stop.setIcon(close_ico) if self.interface_lng_val == 'Russian': self.solv_stop.setToolTip('Остановить процесс решения') elif self.interface_lng_val == 'English': self.solv_stop.setToolTip('Stop the solution process') self.solv_run_vis = QAction(self) self.solv_run_vis.setEnabled(False) solv_run_vis_ico = self.style().standardIcon(QStyle.SP_CommandLink) self.solv_run_vis.setIcon(solv_run_vis_ico) if self.interface_lng_val == 'Russian': self.solv_run_vis.setToolTip( 'Выполнить визуализацию результатов решения') elif self.interface_lng_val == 'English': self.solv_run_vis.setToolTip('Visualize the solution results') self.toolBar_3 = QToolBar() self.toolBar_3.addAction(self.solv_run) self.toolBar_3.addAction(self.solv_stop) self.toolBar_3.addAction(self.solv_run_vis) self.solv_run.triggered.connect( lambda: second_toolbar_functions_class.on_solv_run( prj_path_val, mesh_name_txt_val, pp_dir, self, self. interface_lng_val, msh_type)) self.solv_stop.triggered.connect( lambda: second_toolbar_functions_class.on_solv_stop( prj_path_val, mesh_name_txt_val, pp_dir, self, self. interface_lng_val, msh_type)) self.solv_run_vis.triggered.connect( lambda: second_toolbar_functions_class.on_solv_vis( prj_path_val, mesh_name_txt_val, pp_dir, self, self. interface_lng_val, msh_type)) self.addToolBar(self.toolBar_3) self.insertToolBarBreak(self.toolBar_3) ###----------------Верхний виджет с полным путем до файла сетки----------------### self.tdw = QDockWidget() self.tdw.setFixedSize(1400, 65) self.tdw.setFeatures(self.tdw.NoDockWidgetFeatures) self.tdw_grid = QGridLayout() self.tdw_grid.setColumnStretch(2, 1) self.tdw_frame = QFrame() self.tdw_frame.setStyleSheet("background-color: ghostwhite;" "border-width: 0.5px;" "border-style: solid;" "border-color: silver;") self.tdw_frame.setLayout(self.tdw_grid) self.tdw.setWidget(self.tdw_frame) self.addDockWidget(QtCore.Qt.TopDockWidgetArea, self.tdw) ###-----------------Левый виджет с файловой системой проекта---------------------### self.fsw = QDockWidget() self.fsw.setFeatures(self.fsw.NoDockWidgetFeatures) self.fsw_label = QLabel() self.fsw_label.setAlignment(QtCore.Qt.AlignCenter) self.fsw_grid = QGridLayout() self.fsw_grid.addWidget(self.fsw_label, 0, 0) self.fsw_frame = QFrame() self.fsw_frame.setFixedSize(200, 35) self.fsw_frame.setStyleSheet("background-color: honeydew;" "border-width: 1px;" "border-style: solid;" "border-color: dimgray;" "border-radius: 4px;") self.fsw_frame.setLayout(self.fsw_grid) if self.interface_lng_val == 'Russian': fs_lbl = "Файловая Cтруктура Проекта" elif self.interface_lng_val == 'English': fs_lbl = "File Structure of the Project" self.fsw_label.setText("<font color='SeaGreen'>" + fs_lbl + "</font>") self.fsw_label.setStyleSheet("border-style: none;" "font-size: 10pt;") self.fsw.setTitleBarWidget(self.fsw_frame) self.treeview = QTreeView() self.treeview.setFixedSize(200, 520) self.treeview.model = QtGui.QStandardItemModel() self.treeview.setModel(self.treeview.model) self.treeview.setColumnWidth(0, 100) self.treeview.setColumnHidden(1, True) self.treeview.setColumnHidden(2, True) self.treeview.setColumnHidden(3, True) self.treeview.header().hide() self.treeview.setItemsExpandable(False) self.treeview.clicked.connect(self.on_treeview_clicked) self.fsw.setWidget(self.treeview) ###-----------Правый виджет с формой вывода результатов генерации файлов-----------### self.cdw = QDockWidget() self.cdw.setFeatures(self.cdw.NoDockWidgetFeatures) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.cdw) self.cdw_grid = QGridLayout() self.cdw_frame = QFrame() self.cdw_frame.setFixedSize(495, 35) self.cdw_frame.setStyleSheet("border-width: 1px;" "border-style: solid;" "border-color: dimgray;" "border-radius: 4px;" "background-color: honeydew;") self.cdw_frame.setLayout(self.cdw_grid) self.outf_lbl = QLabel() self.outf_lbl.setAlignment(QtCore.Qt.AlignCenter) self.outf_lbl.setStyleSheet("border-style: none;" "font-size: 9pt;") self.cdw_grid.addWidget(self.outf_lbl, 0, 0) self.outf_edit = QTextEdit() self.outf_scroll = QScrollArea() self.outf_scroll.setWidgetResizable(True) self.outf_scroll.setWidget(self.outf_edit) self.outf_scroll.setFixedSize(495, 520) ###-----------------Центральный виджет с формой параметров---------------------### self.ffw = QDockWidget() self.ffw.setFeatures(self.ffw.NoDockWidgetFeatures) self.ffw_label = QLabel() self.ffw_label.setAlignment(QtCore.Qt.AlignCenter) self.ffw_grid = QGridLayout() self.ffw_grid.addWidget(self.ffw_label, 0, 0) self.ffw_frame = QFrame() self.ffw_frame.setFixedSize(693, 44) self.ffw_frame.setStyleSheet("border-width: 1px;" "border-style: solid;" "border-color: dimgray;" "border-radius: 4px;" "background-color: honeydew;") self.ffw_frame.setLayout(self.ffw_grid) ###------------------Нижний виджет со служебными сообщениями------------------### if self.interface_lng_val == 'Russian': self.serv_mes = QDockWidget("Служебные сообщения") elif self.interface_lng_val == 'English': self.serv_mes = QDockWidget("Service messages") self.serv_mes.setFixedSize(1400, 160) self.serv_mes.setFeatures(self.serv_mes.NoDockWidgetFeatures) self.listWidget = QListWidget() self.serv_mes.setWidget(self.listWidget)
class MainWindowClass(QMainWindow): def __init__(self, parent=None): QMainWindow.__init__(self, parent) self.interface_lng_val = 'Russian' if self.interface_lng_val == 'Russian': self.setWindowTitle("Графический интерфейс программы OpenFOAM") elif self.interface_lng_val == 'English': self.setWindowTitle("OpenFOAM_decompose_GUI") # Базовые переменные self.full_dir = '' self.prj_name = '' self.con = '' self.lock_bool = False self.application = '' self.object_edit_txt = '' # ---------------------------Панель управления подготовкой задачи МСС----------------------------- # self.proj_open = QAction(self) self.proj_open.setEnabled(True) proj_ico = self.style().standardIcon(QStyle.SP_ArrowUp) self.proj_open.setIcon(proj_ico) if self.interface_lng_val == 'Russian': self.proj_open.setToolTip('Открыть проект') elif self.interface_lng_val == 'English': self.proj_open.setToolTip('Open the project') self.lng_chs = QAction(self) self.lng_chs.setEnabled(True) lng_chs_ico = self.style().standardIcon( QStyle.SP_FileDialogDetailedView) self.lng_chs.setIcon(lng_chs_ico) if self.interface_lng_val == 'Russian': self.lng_chs.setToolTip('Выбрать язык интерфейса программы') elif self.interface_lng_val == 'English': self.lng_chs.setToolTip('Select the interface language') self.file_open = QAction(self) self.file_open.setEnabled(False) file_open_ico = self.style().standardIcon(QStyle.SP_FileIcon) self.file_open.setIcon(file_open_ico) if self.interface_lng_val == 'Russian': self.file_open.setToolTip( 'Открыть форму создания служебного файла для директории 0') elif self.interface_lng_val == 'English': self.file_open.setToolTip( 'Open the form for creating the service file for the directory 0' ) self.toolBar_1 = QToolBar("MyToolBar") self.toolBar_1.addAction(self.proj_open) self.toolBar_1.addAction(self.lng_chs) self.toolBar_1.addAction(self.file_open) self.proj_open.triggered.connect( lambda: first_toolbar_functions_class.on_proj_open(self)) self.lng_chs.triggered.connect( lambda: first_toolbar_functions_class.on_lng_chs(self)) self.file_open.triggered.connect( lambda: first_toolbar_functions_class.on_0_files_window_chs(self)) self.addToolBar(self.toolBar_1) ###----------------------Панель управления подготовкой РС--------------------------### self.msh_open = QAction(self) self.msh_open.setEnabled(False) msh_ico = self.style().standardIcon(QStyle.SP_FileDialogNewFolder) self.msh_open.setIcon(msh_ico) if self.interface_lng_val == 'Russian': self.msh_open.setToolTip('Открыть форму выбора расчетной сетки') elif self.interface_lng_val == 'English': self.msh_open.setToolTip('Open the mesh selection form') self.msh_run = QAction(self) self.msh_run.setEnabled(False) msh_ico = self.style().standardIcon(QStyle.SP_ArrowRight) self.msh_run.setIcon(msh_ico) if self.interface_lng_val == 'Russian': self.msh_run.setToolTip('Выполнить генерацию расчетной сетки') elif self.interface_lng_val == 'English': self.msh_run.setToolTip('Make the mesh generation') self.msh_visual = QAction(self) self.msh_visual.setEnabled(False) msh_visual_ico = self.style().standardIcon(QStyle.SP_MediaSeekForward) self.msh_visual.setIcon(msh_visual_ico) if self.interface_lng_val == 'Russian': self.msh_visual.setToolTip( 'Выполнить визуализацию расчетной сетки') elif self.interface_lng_val == 'English': self.msh_visual.setToolTip('Make the mesh visualization') self.toolBar_2 = QToolBar() self.toolBar_2.addAction(self.msh_open) self.toolBar_2.addAction(self.msh_run) self.toolBar_2.addAction(self.msh_visual) self.msh_open.triggered.connect( lambda: second_toolbar_functions_class.on_msh_open(self)) self.msh_run.triggered.connect( lambda: second_toolbar_functions_class.on_msh_run( prj_path_val, mesh_name_txt_val, pp_dir, self, self. interface_lng_val, msh_type)) self.msh_visual.triggered.connect( lambda: second_toolbar_functions_class.on_visual_msh_run( prj_path_val, mesh_name_txt_val, pp_dir, self, self. interface_lng_val, msh_type)) self.addToolBar(self.toolBar_2) self.insertToolBarBreak(self.toolBar_2) ###----------------------Панель управления решением задачи МСС--------------------------### self.solv_run = QAction(self) self.solv_run.setEnabled(False) solv_run_ico = self.style().standardIcon(QStyle.SP_DialogNoButton) self.solv_run.setIcon(solv_run_ico) if self.interface_lng_val == 'Russian': self.solv_run.setToolTip('Выполнить решение') elif self.interface_lng_val == 'English': self.solv_run.setToolTip('Run solution') self.solv_stop = QAction(self) self.solv_stop.setEnabled(False) close_ico = self.style().standardIcon(QStyle.SP_DockWidgetCloseButton) self.solv_stop.setIcon(close_ico) if self.interface_lng_val == 'Russian': self.solv_stop.setToolTip('Остановить процесс решения') elif self.interface_lng_val == 'English': self.solv_stop.setToolTip('Stop the solution process') self.solv_run_vis = QAction(self) self.solv_run_vis.setEnabled(False) solv_run_vis_ico = self.style().standardIcon(QStyle.SP_CommandLink) self.solv_run_vis.setIcon(solv_run_vis_ico) if self.interface_lng_val == 'Russian': self.solv_run_vis.setToolTip( 'Выполнить визуализацию результатов решения') elif self.interface_lng_val == 'English': self.solv_run_vis.setToolTip('Visualize the solution results') self.toolBar_3 = QToolBar() self.toolBar_3.addAction(self.solv_run) self.toolBar_3.addAction(self.solv_stop) self.toolBar_3.addAction(self.solv_run_vis) self.solv_run.triggered.connect( lambda: second_toolbar_functions_class.on_solv_run( prj_path_val, mesh_name_txt_val, pp_dir, self, self. interface_lng_val, msh_type)) self.solv_stop.triggered.connect( lambda: second_toolbar_functions_class.on_solv_stop( prj_path_val, mesh_name_txt_val, pp_dir, self, self. interface_lng_val, msh_type)) self.solv_run_vis.triggered.connect( lambda: second_toolbar_functions_class.on_solv_vis( prj_path_val, mesh_name_txt_val, pp_dir, self, self. interface_lng_val, msh_type)) self.addToolBar(self.toolBar_3) self.insertToolBarBreak(self.toolBar_3) ###----------------Верхний виджет с полным путем до файла сетки----------------### self.tdw = QDockWidget() self.tdw.setFixedSize(1400, 65) self.tdw.setFeatures(self.tdw.NoDockWidgetFeatures) self.tdw_grid = QGridLayout() self.tdw_grid.setColumnStretch(2, 1) self.tdw_frame = QFrame() self.tdw_frame.setStyleSheet("background-color: ghostwhite;" "border-width: 0.5px;" "border-style: solid;" "border-color: silver;") self.tdw_frame.setLayout(self.tdw_grid) self.tdw.setWidget(self.tdw_frame) self.addDockWidget(QtCore.Qt.TopDockWidgetArea, self.tdw) ###-----------------Левый виджет с файловой системой проекта---------------------### self.fsw = QDockWidget() self.fsw.setFeatures(self.fsw.NoDockWidgetFeatures) self.fsw_label = QLabel() self.fsw_label.setAlignment(QtCore.Qt.AlignCenter) self.fsw_grid = QGridLayout() self.fsw_grid.addWidget(self.fsw_label, 0, 0) self.fsw_frame = QFrame() self.fsw_frame.setFixedSize(200, 35) self.fsw_frame.setStyleSheet("background-color: honeydew;" "border-width: 1px;" "border-style: solid;" "border-color: dimgray;" "border-radius: 4px;") self.fsw_frame.setLayout(self.fsw_grid) if self.interface_lng_val == 'Russian': fs_lbl = "Файловая Cтруктура Проекта" elif self.interface_lng_val == 'English': fs_lbl = "File Structure of the Project" self.fsw_label.setText("<font color='SeaGreen'>" + fs_lbl + "</font>") self.fsw_label.setStyleSheet("border-style: none;" "font-size: 10pt;") self.fsw.setTitleBarWidget(self.fsw_frame) self.treeview = QTreeView() self.treeview.setFixedSize(200, 520) self.treeview.model = QtGui.QStandardItemModel() self.treeview.setModel(self.treeview.model) self.treeview.setColumnWidth(0, 100) self.treeview.setColumnHidden(1, True) self.treeview.setColumnHidden(2, True) self.treeview.setColumnHidden(3, True) self.treeview.header().hide() self.treeview.setItemsExpandable(False) self.treeview.clicked.connect(self.on_treeview_clicked) self.fsw.setWidget(self.treeview) ###-----------Правый виджет с формой вывода результатов генерации файлов-----------### self.cdw = QDockWidget() self.cdw.setFeatures(self.cdw.NoDockWidgetFeatures) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.cdw) self.cdw_grid = QGridLayout() self.cdw_frame = QFrame() self.cdw_frame.setFixedSize(495, 35) self.cdw_frame.setStyleSheet("border-width: 1px;" "border-style: solid;" "border-color: dimgray;" "border-radius: 4px;" "background-color: honeydew;") self.cdw_frame.setLayout(self.cdw_grid) self.outf_lbl = QLabel() self.outf_lbl.setAlignment(QtCore.Qt.AlignCenter) self.outf_lbl.setStyleSheet("border-style: none;" "font-size: 9pt;") self.cdw_grid.addWidget(self.outf_lbl, 0, 0) self.outf_edit = QTextEdit() self.outf_scroll = QScrollArea() self.outf_scroll.setWidgetResizable(True) self.outf_scroll.setWidget(self.outf_edit) self.outf_scroll.setFixedSize(495, 520) ###-----------------Центральный виджет с формой параметров---------------------### self.ffw = QDockWidget() self.ffw.setFeatures(self.ffw.NoDockWidgetFeatures) self.ffw_label = QLabel() self.ffw_label.setAlignment(QtCore.Qt.AlignCenter) self.ffw_grid = QGridLayout() self.ffw_grid.addWidget(self.ffw_label, 0, 0) self.ffw_frame = QFrame() self.ffw_frame.setFixedSize(693, 44) self.ffw_frame.setStyleSheet("border-width: 1px;" "border-style: solid;" "border-color: dimgray;" "border-radius: 4px;" "background-color: honeydew;") self.ffw_frame.setLayout(self.ffw_grid) ###------------------Нижний виджет со служебными сообщениями------------------### if self.interface_lng_val == 'Russian': self.serv_mes = QDockWidget("Служебные сообщения") elif self.interface_lng_val == 'English': self.serv_mes = QDockWidget("Service messages") self.serv_mes.setFixedSize(1400, 160) self.serv_mes.setFeatures(self.serv_mes.NoDockWidgetFeatures) self.listWidget = QListWidget() self.serv_mes.setWidget(self.listWidget) ###---------------------Функции, связанные с работой главного окна------------------------### # ...........................Функция клика по файлу из дерева......................... ###........................Функция открытия окна выбора интерфейса программы...................### # ...........................Функция клика по файлу из дерева......................... def on_treeview_clicked(self, index): global fileName indexItem = self.treeview.model.index(index.row(), 0, index.parent()) self.lock_bool = True self.file_name = self.treeview.model.itemFromIndex(indexItem).text() file_form_class.inp_file_form_func(self, self.file_name, self.con) file_name_title = file_form_class.out_file_name_func() self.clear_label = QLabel() if file_name_title != None: if file_name_title != 'md': #self.cdw.setWidget(self.clear_label) #self.cdw.setTitleBarWidget if os.path.exists(self.full_dir + '/system/' + file_name_title): outf = open(self.full_dir + '/system/' + file_name_title) data = outf.read() self.outf_edit.setText(data) outf.close() elif os.path.exists(self.full_dir + '/constant/' + file_name_title): outf = open(self.full_dir + '/constant/' + file_name_title) data = outf.read() self.outf_edit.setText(data) outf.close() elif os.path.exists(self.full_dir + '/0/' + file_name_title): outf = open(self.full_dir + '/0/' + file_name_title) data = outf.read() self.outf_edit.setText(data) outf.close() self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.cdw) self.cdw.setWidget(self.outf_scroll) #data = outf.read() if self.interface_lng_val == 'Russian': self.outf_lbl.setText("Файл " + "<font color='peru'>" + file_name_title + "</font>") elif self.interface_lng_val == 'English': self.outf_lbl.setText("<font color='peru'>" + file_name_title + "</font>" + " file") #self.outf_edit.setText(data) self.cdw.setTitleBarWidget(self.cdw_frame) #outf.close() self.setCentralWidget(self.ffw) file_form = file_form_class.out_file_form_func() self.ffw.setWidget(file_form) self.ffw.setTitleBarWidget(self.ffw_frame) if self.interface_lng_val == 'Russian': self.ffw_label.setText("Форма параметров файла: " + "<font color='peru'>" + file_name_title + "</font>") elif self.interface_lng_val == 'English': self.ffw_label.setText("<font color='peru'>" + file_name_title + "</font>" + " file parameters form") self.ffw_label.setStyleSheet("border-style: none;" "font-size: 9pt;") elif file_name_title == 'md': if self.interface_lng_val == 'Russian': msg_lbl = QLabel( '<span style="color:blue">Для создания расчетной сетки воспользуйтесь панелью инструментов</span>' ) elif self.interface_lng_val == 'English': msg_lbl = QLabel( '<span style="color:blue">To create a mesh use the toolbar.</span>' ) self.listWidget.clear() self.item = QListWidgetItem() self.listWidget.addItem(self.item) self.listWidget.setItemWidget(self.item, msg_lbl) else: self.ffw.setTitleBarWidget(self.clear_label) self.ffw.setWidget(self.clear_label) self.cdw.setWidget(self.clear_label) self.cdw.setTitleBarWidget(self.clear_label) # .........................Функция получения языка интерфейса.......................... def on_lng_get(self, interface_lng): global interface_lng_val self.interface_lng_val = interface_lng if self.interface_lng_val == 'Russian': self.setWindowTitle("Графический интерфейс программы OpenFOAM") self.proj_open.setToolTip('Открыть проект') self.msh_run.setToolTip('Выполнить генерацию расчетной сетки') self.msh_visual.setToolTip( 'Выполнить визуализацию расчетной сетки') self.lng_chs.setToolTip('Выбрать язык интерфейса программы') self.file_open.setToolTip( 'Открыть форму создания служебного файла для директории 0') self.msh_open.setToolTip('Открыть форму выбора расчетной сетки') self.solv_run.setToolTip('Выполнить решение') self.solv_stop.setToolTip('Остановить процесс решения') self.solv_run_vis.setToolTip( 'Выполнить визуализацию результатов решения') elif self.interface_lng_val == 'English': self.setWindowTitle("OpenFOAM_decompose_GUI") self.proj_open.setToolTip('Open the project') self.msh_run.setToolTip('Run mesh generation') self.msh_visual.setToolTip('Run mesh visualization') self.lng_chs.setToolTip( 'Select the interface language for the program') self.file_open.setToolTip( 'Open the form for creating the service file for the directory 0' ) self.msh_open.setToolTip('Open the mesh selection form') self.solv_run.setToolTip('Run solution') self.solv_stop.setToolTip('Stop the solution process') self.solv_run_vis.setToolTip('Visualize the solution results') # .........................Функция получения пути до директории.......................... def on_prj_path_get(self, prj_path, mesh_name_txt): global prj_path_val global mesh_name_txt_val global pp_dir prj_path_val = prj_path mesh_name_txt_val = mesh_name_txt pp_dir, pp_sys = os.path.split(prj_path_val) # .............................Функция получения типа сетки.............................. def on_mesh_type_get(self, pd_2): global msh_type msh_type = pd_2
class MainWindowUi(QMainWindow): def __init__(self, parent=None): super().__init__(parent) self.setWindowTitle("FastLogger") self._central_widget = QWidget(self) self.setCentralWidget(self._central_widget) self.layout = QGridLayout() self._central_widget.setLayout(self.layout) self._create_actions() self._create_menubar() self._create_toolbar() self._create_statusbar() self._create_log_area() self._bind_actions() def _create_actions(self): self.action_new = QAction(QIcon("assets/icons/document-new.png"), "&New Log") self.action_new.setShortcut("Ctrl+N") self.action_open = QAction(QIcon("assets/icons/document-open.png"), "&Open Log") self.action_open.setShortcut("Ctrl+O") self.action_save = QAction(QIcon("assets/icons/document-save.png"), "&Save Log") self.action_save.setShortcut("Ctrl+S") self.action_save_as = QAction( QIcon("assets/icons/document-save-as.png"), "Save Log &as") self.action_save_as.setShortcut("Ctrl+Shift+S") def _bind_actions(self): self.action_new.triggered.connect(self.log_editor.onNewFile) self.action_open.triggered.connect(self.log_editor.onOpenFile) self.action_save.triggered.connect(self.log_editor.onSaveFile) self.action_save_as.triggered.connect(self.log_editor.onSaveAsFile) def _create_log_area(self): self.log_area = QSplitter(self) self.log_area.setChildrenCollapsible(False) self.log_viewer = LogViewer() self.log_editor = LogEditor(self.log_viewer, self.statusbar) self.log_area.addWidget(self.log_editor) self.log_area.addWidget(self.log_viewer) self.layout.addWidget(self.log_area, 0, 0, 1, 1) def _create_menubar(self): self.menubar = QMenuBar(self) self.menu_file = QMenu("&File", self.menubar) self.menubar.addAction(self.menu_file.menuAction()) self.menu_file.addAction(self.action_new) self.menu_file.addAction(self.action_open) self.menu_file.addAction(self.action_save) self.menu_file.addAction(self.action_save_as) self.menu_edit = QMenu("&Edit", self.menubar) self.setMenuBar(self.menubar) def _create_toolbar(self): self.toolbar = QToolBar(self) self.toolbar.setMovable(False) self.toolbar.setToolButtonStyle(Qt.ToolButtonIconOnly) self.toolbar.addAction(self.action_new) self.toolbar.addAction(self.action_open) self.toolbar.addAction(self.action_save) self.toolbar.addAction(self.action_save_as) self.addToolBar(Qt.TopToolBarArea, self.toolbar) def _create_statusbar(self): self.statusbar = StatusBar(self) self.setStatusBar(self.statusbar)
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 = MyQDateTimeEdit(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 = MyQDateTimeEdit(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 column of GID and column of link. 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 folder'), self, statusTip=QCoreApplication.translate( "mainwindow_ui_tr", 'move selected download files to another folder'), 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>"))
def __init__(self): super().__init__() # self.setWindowTitle("ToolBar") self.setWindowTitle("My App") label = QLabel("Hello!") label.setAlignment(Qt.AlignCenter) self.setCentralWidget(label) toolbar = QToolBar("My main toolbar") toolbar.setIconSize(QSize(20, 20)) self.addToolBar(toolbar) button_action = QAction("Your Button", self) button_action.setIcon(QIcon("bug.png")) button_action.setStatusTip("This is your action") button_action.triggered.connect(self.onMyToolBarButtonClick) button_action.setCheckable(True) toolbar.addAction(button_action) # -------Separator toolbar.addSeparator() # action2 button_action2 = QAction(QIcon("bug.png"), "your button2", self) button_action2.setStatusTip("This is your button2") button_action2.setCheckable(True) button_action2.triggered.connect(self.onMyToolBarButtonClick) toolbar.addAction(button_action2) toolbar.addWidget(QLabel("Hello")) toolbar.addWidget(QCheckBox()) self.setStatusBar(QStatusBar(self))
class SvgDiagram(E5MainWindow): """ Class implementing a dialog showing a SVG graphic. """ ZoomLevels = [ 1, 3, 5, 7, 9, 10, 20, 30, 50, 67, 80, 90, 100, 110, 120, 133, 150, 170, 200, 240, 300, 400, 500, 600, 700, 800, 900, 1000, ] ZoomLevelDefault = 100 def __init__(self, svgFile, parent=None, name=None): """ Constructor @param svgFile filename of a SVG graphics file to show (string) @param parent parent widget of the view (QWidget) @param name name of the view widget (string) """ super(SvgDiagram, self).__init__(parent) if name: self.setObjectName(name) else: self.setObjectName("SvgDiagram") self.setWindowTitle(self.tr("SVG-Viewer")) self.svgWidget = QSvgWidget() self.svgWidget.setObjectName("svgWidget") self.svgWidget.setBackgroundRole(QPalette.Base) self.svgWidget.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) self.svgView = QScrollArea() self.svgView.setObjectName("svgView") self.svgView.setBackgroundRole(QPalette.Dark) self.svgView.setWidget(self.svgWidget) self.setCentralWidget(self.svgView) self.__zoomWidget = E5ZoomWidget( UI.PixmapCache.getPixmap("zoomOut.png"), UI.PixmapCache.getPixmap("zoomIn.png"), UI.PixmapCache.getPixmap("zoomReset.png"), self) self.statusBar().addPermanentWidget(self.__zoomWidget) self.__zoomWidget.setMapping(SvgDiagram.ZoomLevels, SvgDiagram.ZoomLevelDefault) self.__zoomWidget.valueChanged.connect(self.__doZoom) # polish up the dialog self.resize(QSize(800, 600).expandedTo(self.minimumSizeHint())) self.zoom = 1.0 self.svgFile = svgFile self.svgWidget.load(self.svgFile) self.svgWidget.resize(self.svgWidget.renderer().defaultSize()) self.__initActions() self.__initContextMenu() self.__initToolBars() self.grabGesture(Qt.PinchGesture) def __initActions(self): """ Private method to initialize the view actions. """ self.closeAct = \ QAction(UI.PixmapCache.getIcon("close.png"), self.tr("Close"), self) self.closeAct.triggered.connect(self.close) self.printAct = \ QAction(UI.PixmapCache.getIcon("print.png"), self.tr("Print"), self) self.printAct.triggered.connect(self.__printDiagram) self.printPreviewAct = \ QAction(UI.PixmapCache.getIcon("printPreview.png"), self.tr("Print Preview"), self) self.printPreviewAct.triggered.connect(self.__printPreviewDiagram) def __initContextMenu(self): """ Private method to initialize the context menu. """ self.__menu = QMenu(self) self.__menu.addAction(self.closeAct) self.__menu.addSeparator() self.__menu.addAction(self.printPreviewAct) self.__menu.addAction(self.printAct) self.setContextMenuPolicy(Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.__showContextMenu) def __showContextMenu(self, coord): """ Private slot to show the context menu of the listview. @param coord the position of the mouse pointer (QPoint) """ self.__menu.popup(self.mapToGlobal(coord)) def __initToolBars(self): """ Private method to populate the toolbars with our actions. """ self.windowToolBar = QToolBar(self.tr("Window"), self) self.windowToolBar.setIconSize(UI.Config.ToolBarIconSize) self.windowToolBar.addAction(self.closeAct) self.graphicsToolBar = QToolBar(self.tr("Graphics"), self) self.graphicsToolBar.setIconSize(UI.Config.ToolBarIconSize) self.graphicsToolBar.addAction(self.printPreviewAct) self.graphicsToolBar.addAction(self.printAct) self.addToolBar(Qt.TopToolBarArea, self.windowToolBar) self.addToolBar(Qt.TopToolBarArea, self.graphicsToolBar) def getDiagramName(self): """ Public method to retrieve a name for the diagram. @return name for the diagram """ return self.svgFile def wheelEvent(self, evt): """ Protected method to handle wheel events. @param evt reference to the wheel event (QWheelEvent) """ if evt.modifiers() & Qt.ControlModifier: if qVersion() >= "5.0.0": delta = evt.angleDelta().y() else: delta = evt.delta() if delta < 0: self.__zoomOut() else: self.__zoomIn() evt.accept() return super(SvgDiagram, self).wheelEvent(evt) def event(self, evt): """ Public method handling events. @param evt reference to the event (QEvent) @return flag indicating, if the event was handled (boolean) """ if evt.type() == QEvent.Gesture: self.gestureEvent(evt) return True return super(SvgDiagram, self).event(evt) def gestureEvent(self, evt): """ Protected method handling gesture events. @param evt reference to the gesture event (QGestureEvent """ pinch = evt.gesture(Qt.PinchGesture) if pinch: if pinch.state() == Qt.GestureStarted: pinch.setScaleFactor(self.__zoom() / 100) else: self.__doZoom(int(pinch.scaleFactor() * 100)) evt.accept() ########################################################################### ## Private menu handling methods below. ########################################################################### def __adjustScrollBar(self, scrollBar, factor): """ Private method to adjust a scrollbar by a certain factor. @param scrollBar reference to the scrollbar object (QScrollBar) @param factor factor to adjust by (float) """ scrollBar.setValue( int(factor * scrollBar.value() + ((factor - 1) * scrollBar.pageStep() / 2))) def __levelForZoom(self, zoom): """ Private method determining the zoom level index given a zoom factor. @param zoom zoom factor (integer) @return index of zoom factor (integer) """ try: index = SvgDiagram.ZoomLevels.index(zoom) except ValueError: for index in range(len(SvgDiagram.ZoomLevels)): if zoom <= SvgDiagram.ZoomLevels[index]: break return index def __doZoom(self, value): """ Private method to set the zoom value in percent. @param value zoom value in percent (integer) """ oldValue = self.__zoom() if value != oldValue: self.svgWidget.resize(value / 100 * self.svgWidget.sizeHint()) factor = value / oldValue self.__adjustScrollBar(self.svgView.horizontalScrollBar(), factor) self.__adjustScrollBar(self.svgView.verticalScrollBar(), factor) self.__zoomWidget.setValue(value) def __zoomIn(self): """ Private method to zoom into the SVG. """ index = self.__levelForZoom(self.__zoom()) if index < len(SvgDiagram.ZoomLevels) - 1: self.__doZoom(SvgDiagram.ZoomLevels[index + 1]) def __zoomOut(self): """ Private method to zoom out of the SVG. """ index = self.__levelForZoom(self.__zoom()) if index > 0: self.__doZoom(SvgDiagram.ZoomLevels[index - 1]) def __zoomReset(self): """ Private method to reset the zoom value. """ self.__doZoom(SvgDiagram.ZoomLevels[SvgDiagram.ZoomLevelDefault]) def __zoom(self): """ Private method to get the current zoom factor in percent. @return current zoom factor in percent (integer) """ return int(self.svgWidget.width() / self.svgWidget.sizeHint().width() * 100.0) def __printDiagram(self): """ Private slot called to print the diagram. """ printer = QPrinter(mode=QPrinter.ScreenResolution) printer.setFullPage(True) if Preferences.getPrinter("ColorMode"): printer.setColorMode(QPrinter.Color) else: printer.setColorMode(QPrinter.GrayScale) if Preferences.getPrinter("FirstPageFirst"): printer.setPageOrder(QPrinter.FirstPageFirst) else: printer.setPageOrder(QPrinter.LastPageFirst) printerName = Preferences.getPrinter("PrinterName") if printerName: printer.setPrinterName(printerName) printDialog = QPrintDialog(printer, self) if printDialog.exec_(): self.__print(printer) def __printPreviewDiagram(self): """ Private slot called to show a print preview of the diagram. """ from PyQt5.QtPrintSupport import QPrintPreviewDialog printer = QPrinter(mode=QPrinter.ScreenResolution) printer.setFullPage(True) if Preferences.getPrinter("ColorMode"): printer.setColorMode(QPrinter.Color) else: printer.setColorMode(QPrinter.GrayScale) if Preferences.getPrinter("FirstPageFirst"): printer.setPageOrder(QPrinter.FirstPageFirst) else: printer.setPageOrder(QPrinter.LastPageFirst) printer.setPageMargins( Preferences.getPrinter("LeftMargin") * 10, Preferences.getPrinter("TopMargin") * 10, Preferences.getPrinter("RightMargin") * 10, Preferences.getPrinter("BottomMargin") * 10, QPrinter.Millimeter) printerName = Preferences.getPrinter("PrinterName") if printerName: printer.setPrinterName(printerName) preview = QPrintPreviewDialog(printer, self) preview.paintRequested[QPrinter].connect(self.__print) preview.exec_() def __print(self, printer): """ Private slot to the actual printing. @param printer reference to the printer object (QPrinter) """ painter = QPainter() painter.begin(printer) # calculate margin and width of printout font = QFont("times", 10) painter.setFont(font) fm = painter.fontMetrics() fontHeight = fm.lineSpacing() marginX = printer.pageRect().x() - printer.paperRect().x() marginX = Preferences.getPrinter("LeftMargin") * \ int(printer.resolution() / 2.54) - marginX marginY = printer.pageRect().y() - printer.paperRect().y() marginY = Preferences.getPrinter("TopMargin") * \ int(printer.resolution() / 2.54) - marginY width = printer.width() - marginX - \ Preferences.getPrinter("RightMargin") * \ int(printer.resolution() / 2.54) height = printer.height() - fontHeight - 4 - marginY - \ Preferences.getPrinter("BottomMargin") * \ int(printer.resolution() / 2.54) # write a foot note s = self.tr("Diagram: {0}").format(self.getDiagramName()) tc = QColor(50, 50, 50) painter.setPen(tc) painter.drawRect(marginX, marginY, width, height) painter.drawLine(marginX, marginY + height + 2, marginX + width, marginY + height + 2) painter.setFont(font) painter.drawText(marginX, marginY + height + 4, width, fontHeight, Qt.AlignRight, s) # render the diagram painter.setViewport(marginX, marginY, width, height) self.svgWidget.renderer().render(painter) painter.end()
def __init__(self, *args, **kwargs): super(MainWindow, self).__init__(*args, **kwargs) self.setWindowTitle("My Awesome App") label = QLabel("This is a PyQt5 window!") # The `Qt` namespace has a lot of attributes to customise # widgets. See: http://doc.qt.io/qt-5/qt.html label.setAlignment(Qt.AlignCenter) # Set the central widget of the Window. Widget will expand # to take up all the space in the window by default. self.setCentralWidget(label) menu = self.menuBar() file_menu = menu.addMenu("&File") toolbar = QToolBar("My main toolbar") self.addToolBar(toolbar) action_name = "File" icon_name ="app.png" status_tooltip = "File" self.add_an_action(action_name, icon_name, status_tooltip, toolbar, file_menu) action_name = "Edit" icon_name ="edit.png" status_tooltip = "Edit" self.add_an_action(action_name, icon_name, status_tooltip, toolbar, file_menu) action_name = "Copy" icon_name ="copy.png" status_tooltip = "Copy" self.add_an_action(action_name, icon_name, status_tooltip, toolbar, file_menu) action_name = "Delete" icon_name ="delete.png" status_tooltip = "Delete" self.add_an_action(action_name, icon_name, status_tooltip, toolbar, file_menu) file_menu.addMenu("&SubItem") toolbar.addWidget(QLabel("Hello")) checkbox = QCheckBox() checkbox.setText("Select") toolbar.addWidget(checkbox) combobox = QComboBox() combobox.addItem("Banane") combobox.addItem("Mango") combobox.addItem("Orange") combobox.addItem("Clementine") combobox.addItem("Banane") toolbar.addWidget(combobox) button_sub = QAction("Open", self) button_sub.setStatusTip("This is your button") button_sub.triggered.connect(self.onMyToolBarButtonClick) #button_action.addAction(button_sub) self.setWindowIcon(QIcon("app.png")) self.setStatusBar(QStatusBar(self))
class ProfileDockWidget(QDockWidget): """ Dockable window that is a combined profile and ruler """ # signals profileClosed = pyqtSignal(QDockWidget, name='profileClosed') def __init__(self, parent, viewwidget): QDockWidget.__init__(self, "Profile", parent) self.viewwidget = viewwidget # create a new widget that lives in the dock window self.dockWidget = QWidget() self.mainLayout = QVBoxLayout() self.toolBar = QToolBar(self.dockWidget) self.setupActions() self.setupToolbar() self.mainLayout.addWidget(self.toolBar) self.plotWidget = plotwidget.PlotLineWidget(self) self.mainLayout.addWidget(self.plotWidget) self.whitePen = QPen(Qt.white) self.whitePen.setWidth(1) self.redPen = QPen(Qt.red) self.redPen.setWidth(1) self.greenPen = QPen(Qt.green) self.greenPen.setWidth(1) self.bluePen = QPen(Qt.blue) self.bluePen.setWidth(1) self.distanceLabel = QLabel() self.mainLayout.addWidget(self.distanceLabel) self.dockWidget.setLayout(self.mainLayout) # tell the dock window this is the widget to display self.setWidget(self.dockWidget) self.resize(400, 200) # allow plot scaling to be changed by user # Min, Max. None means 'auto'. self.plotScaling = (None, None) # store the range of the data so we can init plot scale dlg self.dataRange = None # last polyLine so we can quickly resraw if plot scale changes self.lastPolyLine = None def setupActions(self): """ Create the actions to be shown on the toolbar """ self.followAction = QAction(self) self.followAction.setText("&Follow Query Tool") self.followAction.setStatusTip("Follow Query Tool") self.followAction.setIcon(QIcon(":/viewer/images/profileruler.png")) self.followAction.setCheckable(True) self.followAction.setChecked(True) self.savePlotAction = QAction(self, triggered=self.savePlot) self.savePlotAction.setText("&Save Plot") self.savePlotAction.setStatusTip("Save Plot") self.savePlotAction.setIcon(QIcon(":/viewer/images/saveplot.png")) self.plotScalingAction = QAction(self, triggered=self.onPlotScaling) self.plotScalingAction.setText("Set Plot Scaling") self.plotScalingAction.setStatusTip("Set Plot Scaling") icon = QIcon(":/viewer/images/setplotscale.png") self.plotScalingAction.setIcon(icon) def setupToolbar(self): """ Add the actions to the toolbar """ self.toolBar.addAction(self.followAction) self.toolBar.addAction(self.savePlotAction) self.toolBar.addAction(self.plotScalingAction) def savePlot(self): """ Save the plot as a file. Either .pdf or .ps QPrinter chooses format based on extension. """ from PyQt5.QtPrintSupport import QPrinter from PyQt5.QtWidgets import QFileDialog from PyQt5.QtGui import QPainter fname, filter = QFileDialog.getSaveFileName(self, "Plot File", filter="PDF (*.pdf);;Postscript (*.ps)") if fname != '': printer = QPrinter() printer.setOrientation(QPrinter.Landscape) printer.setColorMode(QPrinter.Color) printer.setOutputFileName(fname) printer.setResolution(96) painter = QPainter() painter.begin(printer) self.plotWidget.render(painter) painter.end() def plotProfile(self, xdata, ydata, mask, pen): """ Plot the xdata vs ydata. Use the mask to split the plot up so values only plotted where mask = True """ # get all the indices where the mask # changes from True to False and vice versa changeidx = numpy.diff(mask).nonzero()[0] # because diff() starts from the second element # we actually want the indices relative to the start changeidx = changeidx + 1 # go all the way to the end changeidx = numpy.append(changeidx, mask.size) lastidx = 0 # start at the beginning of the array for idx in changeidx: if mask[lastidx]: # we are in a run of True's xdatasub = xdata[lastidx:idx] ydatasub = ydata[lastidx:idx] curve = plotwidget.PlotCurve(xdatasub, ydatasub, pen) self.plotWidget.addCurve(curve) lastidx = idx def newLine(self, polyLine): """ Widget has collected a new line """ if not self.followAction.isChecked(): return title = "Profile: %s" % polyLine.layer.title self.setWindowTitle(title) # get the info we need out of the PolylineToolInfo profiledata, profilemask, distance = polyLine.getProfile() # set the distance text with commas etc as defined # by the system locale txt = QLocale.system().toString(distance[-1]) fmt = "Total Distance: %s" % txt self.distanceLabel.setText(fmt) # get rid of curves from last time self.plotWidget.removeCurves() if isinstance(profiledata, list): # RGB penList = [self.redPen, self.greenPen, self.bluePen] minValue = None maxValue = None for data, pen in zip(profiledata, penList): # record the range of the data for scaling masked = numpy.compress(profilemask, data) if masked.size == 0: # can't do anything if no valid data continue bandMinValue = masked.min() bandMaxValue = masked.max() self.plotProfile(distance, data, profilemask, pen) if minValue is None or bandMinValue < bandMinValue: minValue = bandMinValue if maxValue is None or bandMaxValue > maxValue: maxValue = bandMaxValue else: # greyscale # find range of data for scaling masked = numpy.compress(profilemask, profiledata) if masked.size == 0: # can't do anything if no valid data return minValue = masked.min() maxValue = masked.max() pen = self.whitePen self.plotProfile(distance, profiledata, profilemask, pen) self.dataRange = (minValue, maxValue) # include total distance in case start or end off image self.plotWidget.setXRange(0, distance[-1]) # set scaling if needed minScale, maxScale = self.plotScaling if minScale is None and maxScale is None: # set back to auto self.plotWidget.setYRange() else: # we need to provide both min and max so # derive from data if needed if minScale is None: minScale = minValue if maxScale is None: maxScale = maxValue self.plotWidget.setYRange(minScale, maxScale) self.lastPolyLine = polyLine def onPlotScaling(self): """ Allows the user to change the Y axis scaling of the plot """ from .plotscalingdialog import PlotScalingDialog if self.dataRange is not None: minValue, maxValue = self.dataRange # should inherit type of minValue etc # which should be the same as the data array data = numpy.array([minValue, maxValue]) else: # uint8 default if no data data = numpy.array([0, 1], dtype=numpy.uint8) dlg = PlotScalingDialog(self, self.plotScaling, data) if dlg.exec_() == PlotScalingDialog.Accepted: self.plotScaling = dlg.getScale() if self.lastPolyLine is not None: self.newLine(self.lastPolyLine) def closeEvent(self, event): """ Window is being closed - inform parent window """ self.profileClosed.emit(self)
def setupFileActions(self): tb = QToolBar(self) tb.setWindowTitle("File Actions") self.addToolBar(tb) menu = QMenu("&File", self) self.menuBar().addMenu(menu) self.actionNew = QAction(QIcon.fromTheme( 'document-new', QIcon(rsrcPath + '/filenew.png')), "&New", self, priority=QAction.LowPriority, shortcut=QKeySequence.New, triggered=self.fileNew) tb.addAction(self.actionNew) menu.addAction(self.actionNew) self.actionOpen = QAction(QIcon.fromTheme( 'document-open', QIcon(rsrcPath + '/fileopen.png')), "&Open...", self, shortcut=QKeySequence.Open, triggered=self.fileOpen) tb.addAction(self.actionOpen) menu.addAction(self.actionOpen) menu.addSeparator() self.actionSave = QAction(QIcon.fromTheme( 'document-save', QIcon(rsrcPath + '/filesave.png')), "&Save", self, shortcut=QKeySequence.Save, triggered=self.fileSave, enabled=False) tb.addAction(self.actionSave) menu.addAction(self.actionSave) self.actionSaveAs = QAction("Save &As...", self, priority=QAction.LowPriority, shortcut=Qt.CTRL + Qt.SHIFT + Qt.Key_S, triggered=self.fileSaveAs) menu.addAction(self.actionSaveAs) menu.addSeparator() self.actionPrint = QAction(QIcon.fromTheme( 'document-print', QIcon(rsrcPath + '/fileprint.png')), "&Print...", self, priority=QAction.LowPriority, shortcut=QKeySequence.Print, triggered=self.filePrint) tb.addAction(self.actionPrint) menu.addAction(self.actionPrint) self.actionPrintPreview = QAction( QIcon.fromTheme('fileprint', QIcon(rsrcPath + '/fileprint.png')), "Print Preview...", self, shortcut=Qt.CTRL + Qt.SHIFT + Qt.Key_P, triggered=self.filePrintPreview) menu.addAction(self.actionPrintPreview) self.actionPrintPdf = QAction(QIcon.fromTheme( 'exportpdf', QIcon(rsrcPath + '/exportpdf.png')), "&Export PDF...", self, priority=QAction.LowPriority, shortcut=Qt.CTRL + Qt.Key_D, triggered=self.filePrintPdf) tb.addAction(self.actionPrintPdf) menu.addAction(self.actionPrintPdf) menu.addSeparator() self.actionQuit = QAction("&Quit", self, shortcut=QKeySequence.Quit, triggered=self.close) menu.addAction(self.actionQuit)
class ReTextWindow(QMainWindow): def __init__(self, parent=None): QMainWindow.__init__(self, parent) self.resize(950, 700) screenRect = QDesktopWidget().screenGeometry() if globalSettings.windowGeometry: self.restoreGeometry(globalSettings.windowGeometry) else: self.move((screenRect.width()-self.width())/2, (screenRect.height()-self.height())/2) if not screenRect.contains(self.geometry()): self.showMaximized() if sys.platform.startswith('darwin'): # https://github.com/retext-project/retext/issues/198 searchPaths = QIcon.themeSearchPaths() searchPaths.append('/opt/local/share/icons') searchPaths.append('/usr/local/share/icons') QIcon.setThemeSearchPaths(searchPaths) if globalSettings.iconTheme: QIcon.setThemeName(globalSettings.iconTheme) if QIcon.themeName() in ('hicolor', ''): if not QFile.exists(icon_path + 'document-new.png'): QIcon.setThemeName(get_icon_theme()) if QFile.exists(icon_path+'retext.png'): self.setWindowIcon(QIcon(icon_path+'retext.png')) elif QFile.exists('/usr/share/pixmaps/retext.png'): self.setWindowIcon(QIcon('/usr/share/pixmaps/retext.png')) else: self.setWindowIcon(QIcon.fromTheme('retext', QIcon.fromTheme('accessories-text-editor'))) self.tabWidget = QTabWidget(self) self.initTabWidget() self.setCentralWidget(self.tabWidget) self.tabWidget.currentChanged.connect(self.changeIndex) self.tabWidget.tabCloseRequested.connect(self.closeTab) toolBar = QToolBar(self.tr('File toolbar'), self) self.addToolBar(Qt.TopToolBarArea, toolBar) self.editBar = QToolBar(self.tr('Edit toolbar'), self) self.addToolBar(Qt.TopToolBarArea, self.editBar) self.searchBar = QToolBar(self.tr('Search toolbar'), self) self.addToolBar(Qt.BottomToolBarArea, self.searchBar) toolBar.setVisible(not globalSettings.hideToolBar) self.editBar.setVisible(not globalSettings.hideToolBar) self.actionNew = self.act(self.tr('New'), 'document-new', self.createNew, shct=QKeySequence.New) self.actionNew.setPriority(QAction.LowPriority) self.actionOpen = self.act(self.tr('Open'), 'document-open', self.openFile, shct=QKeySequence.Open) self.actionOpen.setPriority(QAction.LowPriority) self.actionSetEncoding = self.act(self.tr('Set encoding'), trig=self.showEncodingDialog) self.actionSetEncoding.setEnabled(False) self.actionReload = self.act(self.tr('Reload'), 'view-refresh', lambda: self.currentTab.readTextFromFile()) self.actionReload.setEnabled(False) self.actionSave = self.act(self.tr('Save'), 'document-save', self.saveFile, shct=QKeySequence.Save) self.actionSave.setEnabled(False) self.actionSave.setPriority(QAction.LowPriority) self.actionSaveAs = self.act(self.tr('Save as'), 'document-save-as', self.saveFileAs, shct=QKeySequence.SaveAs) self.actionNextTab = self.act(self.tr('Next tab'), 'go-next', lambda: self.switchTab(1), shct=Qt.CTRL+Qt.Key_PageDown) self.actionPrevTab = self.act(self.tr('Previous tab'), 'go-previous', lambda: self.switchTab(-1), shct=Qt.CTRL+Qt.Key_PageUp) self.actionPrint = self.act(self.tr('Print'), 'document-print', self.printFile, shct=QKeySequence.Print) self.actionPrint.setPriority(QAction.LowPriority) self.actionPrintPreview = self.act(self.tr('Print preview'), 'document-print-preview', self.printPreview) self.actionViewHtml = self.act(self.tr('View HTML code'), 'text-html', self.viewHtml) self.actionChangeEditorFont = self.act(self.tr('Change editor font'), trig=self.changeEditorFont) self.actionChangePreviewFont = self.act(self.tr('Change preview font'), trig=self.changePreviewFont) self.actionSearch = self.act(self.tr('Find text'), 'edit-find', shct=QKeySequence.Find) self.actionSearch.setCheckable(True) self.actionSearch.triggered[bool].connect(self.searchBar.setVisible) self.searchBar.visibilityChanged.connect(self.searchBarVisibilityChanged) self.actionPreview = self.act(self.tr('Preview'), shct=Qt.CTRL+Qt.Key_E, trigbool=self.preview) if QIcon.hasThemeIcon('document-preview'): self.actionPreview.setIcon(QIcon.fromTheme('document-preview')) elif QIcon.hasThemeIcon('preview-file'): self.actionPreview.setIcon(QIcon.fromTheme('preview-file')) elif QIcon.hasThemeIcon('x-office-document'): self.actionPreview.setIcon(QIcon.fromTheme('x-office-document')) else: self.actionPreview.setIcon(QIcon(icon_path+'document-preview.png')) self.actionLivePreview = self.act(self.tr('Live preview'), shct=Qt.CTRL+Qt.Key_L, trigbool=self.enableLivePreview) menuPreview = QMenu() menuPreview.addAction(self.actionLivePreview) self.actionPreview.setMenu(menuPreview) self.actionTableMode = self.act(self.tr('Table editing mode'), shct=Qt.CTRL+Qt.Key_T, trigbool=lambda x: self.currentTab.editBox.enableTableMode(x)) if ReTextFakeVimHandler: self.actionFakeVimMode = self.act(self.tr('FakeVim mode'), shct=Qt.CTRL+Qt.ALT+Qt.Key_V, trigbool=self.enableFakeVimMode) if globalSettings.useFakeVim: self.actionFakeVimMode.setChecked(True) self.enableFakeVimMode(True) self.actionFullScreen = self.act(self.tr('Fullscreen mode'), 'view-fullscreen', shct=Qt.Key_F11, trigbool=self.enableFullScreen) self.actionFullScreen.setPriority(QAction.LowPriority) self.actionConfig = self.act(self.tr('Preferences'), icon='preferences-system', trig=self.openConfigDialog) self.actionConfig.setMenuRole(QAction.PreferencesRole) self.actionSaveHtml = self.act('HTML', 'text-html', self.saveFileHtml) self.actionPdf = self.act('PDF', 'application-pdf', self.savePdf) self.actionOdf = self.act('ODT', 'x-office-document', self.saveOdf) self.getExportExtensionsList() self.actionQuit = self.act(self.tr('Quit'), 'application-exit', shct=QKeySequence.Quit) self.actionQuit.setMenuRole(QAction.QuitRole) self.actionQuit.triggered.connect(self.close) self.actionUndo = self.act(self.tr('Undo'), 'edit-undo', lambda: self.currentTab.editBox.undo(), shct=QKeySequence.Undo) self.actionRedo = self.act(self.tr('Redo'), 'edit-redo', lambda: self.currentTab.editBox.redo(), shct=QKeySequence.Redo) self.actionCopy = self.act(self.tr('Copy'), 'edit-copy', lambda: self.currentTab.editBox.copy(), shct=QKeySequence.Copy) self.actionCut = self.act(self.tr('Cut'), 'edit-cut', lambda: self.currentTab.editBox.cut(), shct=QKeySequence.Cut) self.actionPaste = self.act(self.tr('Paste'), 'edit-paste', lambda: self.currentTab.editBox.paste(), shct=QKeySequence.Paste) self.actionUndo.setEnabled(False) self.actionRedo.setEnabled(False) self.actionCopy.setEnabled(False) self.actionCut.setEnabled(False) qApp = QApplication.instance() qApp.clipboard().dataChanged.connect(self.clipboardDataChanged) self.clipboardDataChanged() if enchant is not None: self.actionEnableSC = self.act(self.tr('Enable'), trigbool=self.enableSpellCheck) self.actionSetLocale = self.act(self.tr('Set locale'), trig=self.changeLocale) self.actionWebKit = self.act(self.tr('Use WebKit renderer'), trigbool=self.enableWebKit) if ReTextWebPreview is None: globalSettings.useWebKit = False self.actionWebKit.setEnabled(False) self.actionWebKit.setChecked(globalSettings.useWebKit) self.actionShow = self.act(self.tr('Show directory'), 'system-file-manager', self.showInDir) self.actionFind = self.act(self.tr('Next'), 'go-next', self.find, shct=QKeySequence.FindNext) self.actionFindPrev = self.act(self.tr('Previous'), 'go-previous', lambda: self.find(back=True), shct=QKeySequence.FindPrevious) self.actionReplace = self.act(self.tr('Replace'), 'edit-find-replace', lambda: self.find(replace=True)) self.actionReplaceAll = self.act(self.tr('Replace all'), trig=self.replaceAll) menuReplace = QMenu() menuReplace.addAction(self.actionReplaceAll) self.actionReplace.setMenu(menuReplace) self.actionCloseSearch = self.act(self.tr('Close'), 'window-close', lambda: self.searchBar.setVisible(False)) self.actionCloseSearch.setPriority(QAction.LowPriority) self.actionHelp = self.act(self.tr('Get help online'), 'help-contents', self.openHelp) self.aboutWindowTitle = self.tr('About ReText') self.actionAbout = self.act(self.aboutWindowTitle, 'help-about', self.aboutDialog) self.actionAbout.setMenuRole(QAction.AboutRole) self.actionAboutQt = self.act(self.tr('About Qt')) self.actionAboutQt.setMenuRole(QAction.AboutQtRole) self.actionAboutQt.triggered.connect(qApp.aboutQt) availableMarkups = markups.get_available_markups() if not availableMarkups: print('Warning: no markups are available!') if len(availableMarkups) > 1: self.chooseGroup = QActionGroup(self) markupActions = [] for markup in availableMarkups: markupAction = self.act(markup.name, trigbool=self.markupFunction(markup)) if markup.name == globalSettings.defaultMarkup: markupAction.setChecked(True) self.chooseGroup.addAction(markupAction) markupActions.append(markupAction) self.actionBold = self.act(self.tr('Bold'), shct=QKeySequence.Bold, trig=lambda: self.insertFormatting('bold')) self.actionItalic = self.act(self.tr('Italic'), shct=QKeySequence.Italic, trig=lambda: self.insertFormatting('italic')) self.actionUnderline = self.act(self.tr('Underline'), shct=QKeySequence.Underline, trig=lambda: self.insertFormatting('underline')) self.usefulTags = ('header', 'italic', 'bold', 'underline', 'numbering', 'bullets', 'image', 'link', 'inline code', 'code block', 'blockquote') self.usefulChars = ('deg', 'divide', 'dollar', 'hellip', 'laquo', 'larr', 'lsquo', 'mdash', 'middot', 'minus', 'nbsp', 'ndash', 'raquo', 'rarr', 'rsquo', 'times') self.formattingBox = QComboBox(self.editBar) self.formattingBox.addItem(self.tr('Formatting')) self.formattingBox.addItems(self.usefulTags) self.formattingBox.activated[str].connect(self.insertFormatting) self.symbolBox = QComboBox(self.editBar) self.symbolBox.addItem(self.tr('Symbols')) self.symbolBox.addItems(self.usefulChars) self.symbolBox.activated.connect(self.insertSymbol) self.updateStyleSheet() menubar = self.menuBar() menuFile = menubar.addMenu(self.tr('File')) menuEdit = menubar.addMenu(self.tr('Edit')) menuHelp = menubar.addMenu(self.tr('Help')) menuFile.addAction(self.actionNew) menuFile.addAction(self.actionOpen) self.menuRecentFiles = menuFile.addMenu(self.tr('Open recent')) self.menuRecentFiles.aboutToShow.connect(self.updateRecentFiles) menuFile.addAction(self.actionShow) menuFile.addAction(self.actionSetEncoding) menuFile.addAction(self.actionReload) menuFile.addSeparator() menuFile.addAction(self.actionSave) menuFile.addAction(self.actionSaveAs) menuFile.addSeparator() menuFile.addAction(self.actionNextTab) menuFile.addAction(self.actionPrevTab) menuFile.addSeparator() menuExport = menuFile.addMenu(self.tr('Export')) menuExport.addAction(self.actionSaveHtml) menuExport.addAction(self.actionOdf) menuExport.addAction(self.actionPdf) if self.extensionActions: menuExport.addSeparator() for action, mimetype in self.extensionActions: menuExport.addAction(action) menuExport.aboutToShow.connect(self.updateExtensionsVisibility) menuFile.addAction(self.actionPrint) menuFile.addAction(self.actionPrintPreview) menuFile.addSeparator() menuFile.addAction(self.actionQuit) menuEdit.addAction(self.actionUndo) menuEdit.addAction(self.actionRedo) menuEdit.addSeparator() menuEdit.addAction(self.actionCut) menuEdit.addAction(self.actionCopy) menuEdit.addAction(self.actionPaste) menuEdit.addSeparator() if enchant is not None: menuSC = menuEdit.addMenu(self.tr('Spell check')) menuSC.addAction(self.actionEnableSC) menuSC.addAction(self.actionSetLocale) menuEdit.addAction(self.actionSearch) menuEdit.addAction(self.actionChangeEditorFont) menuEdit.addAction(self.actionChangePreviewFont) menuEdit.addSeparator() if len(availableMarkups) > 1: self.menuMode = menuEdit.addMenu(self.tr('Default markup')) for markupAction in markupActions: self.menuMode.addAction(markupAction) menuFormat = menuEdit.addMenu(self.tr('Formatting')) menuFormat.addAction(self.actionBold) menuFormat.addAction(self.actionItalic) menuFormat.addAction(self.actionUnderline) menuEdit.addAction(self.actionWebKit) menuEdit.addSeparator() menuEdit.addAction(self.actionViewHtml) menuEdit.addAction(self.actionPreview) menuEdit.addAction(self.actionTableMode) if ReTextFakeVimHandler: menuEdit.addAction(self.actionFakeVimMode) menuEdit.addSeparator() menuEdit.addAction(self.actionFullScreen) menuEdit.addAction(self.actionConfig) menuHelp.addAction(self.actionHelp) menuHelp.addSeparator() menuHelp.addAction(self.actionAbout) menuHelp.addAction(self.actionAboutQt) toolBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) toolBar.addAction(self.actionNew) toolBar.addSeparator() toolBar.addAction(self.actionOpen) toolBar.addAction(self.actionSave) toolBar.addAction(self.actionPrint) toolBar.addSeparator() toolBar.addAction(self.actionPreview) toolBar.addAction(self.actionFullScreen) self.editBar.addAction(self.actionUndo) self.editBar.addAction(self.actionRedo) self.editBar.addSeparator() self.editBar.addAction(self.actionCut) self.editBar.addAction(self.actionCopy) self.editBar.addAction(self.actionPaste) self.editBar.addSeparator() self.editBar.addWidget(self.formattingBox) self.editBar.addWidget(self.symbolBox) self.searchEdit = QLineEdit(self.searchBar) self.searchEdit.setPlaceholderText(self.tr('Search')) self.searchEdit.returnPressed.connect(self.find) self.replaceEdit = QLineEdit(self.searchBar) self.replaceEdit.setPlaceholderText(self.tr('Replace with')) self.replaceEdit.returnPressed.connect(self.find) self.csBox = QCheckBox(self.tr('Case sensitively'), self.searchBar) self.searchBar.addWidget(self.searchEdit) self.searchBar.addWidget(self.replaceEdit) self.searchBar.addSeparator() self.searchBar.addWidget(self.csBox) self.searchBar.addAction(self.actionFindPrev) self.searchBar.addAction(self.actionFind) self.searchBar.addAction(self.actionReplace) self.searchBar.addAction(self.actionCloseSearch) self.searchBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.searchBar.setVisible(False) self.autoSaveEnabled = globalSettings.autoSave if self.autoSaveEnabled: timer = QTimer(self) timer.start(60000) timer.timeout.connect(self.saveAll) self.ind = None if enchant is not None: self.sl = globalSettings.spellCheckLocale try: enchant.Dict(self.sl or None) except enchant.errors.Error as e: print(e, file=sys.stderr) globalSettings.spellCheck = False if globalSettings.spellCheck: self.actionEnableSC.setChecked(True) self.fileSystemWatcher = QFileSystemWatcher() self.fileSystemWatcher.fileChanged.connect(self.fileChanged) def restoreLastOpenedFiles(self): for file in readListFromSettings("lastFileList"): self.openFileWrapper(file) # Show the tab of last opened file lastTabIndex = globalSettings.lastTabIndex if lastTabIndex >= 0 and lastTabIndex < self.tabWidget.count(): self.tabWidget.setCurrentIndex(lastTabIndex) def iterateTabs(self): for i in range(self.tabWidget.count()): yield self.tabWidget.widget(i) def updateStyleSheet(self): if globalSettings.styleSheet: sheetfile = QFile(globalSettings.styleSheet) sheetfile.open(QIODevice.ReadOnly) self.ss = QTextStream(sheetfile).readAll() sheetfile.close() else: palette = QApplication.palette() self.ss = 'html { color: %s; }\n' % palette.color(QPalette.WindowText).name() self.ss += 'td, th { border: 1px solid #c3c3c3; padding: 0 3px 0 3px; }\n' self.ss += 'table { border-collapse: collapse; }\n' def initTabWidget(self): def dragEnterEvent(e): e.acceptProposedAction() def dropEvent(e): fn = bytes(e.mimeData().data('text/plain')).decode().rstrip() if fn.startswith('file:'): fn = QUrl(fn).toLocalFile() self.openFileWrapper(fn) self.tabWidget.setTabsClosable(True) self.tabWidget.setAcceptDrops(True) self.tabWidget.setMovable(True) self.tabWidget.dragEnterEvent = dragEnterEvent self.tabWidget.dropEvent = dropEvent if hasattr(self.tabWidget, 'setTabBarAutoHide'): self.tabWidget.setTabBarAutoHide(globalSettings.tabBarAutoHide) def act(self, name, icon=None, trig=None, trigbool=None, shct=None): if not isinstance(shct, QKeySequence): shct = QKeySequence(shct) if icon: action = QAction(self.actIcon(icon), name, self) else: action = QAction(name, self) if trig: action.triggered.connect(trig) elif trigbool: action.setCheckable(True) action.triggered[bool].connect(trigbool) if shct: action.setShortcut(shct) return action def actIcon(self, name): return QIcon.fromTheme(name, QIcon(icon_path+name+'.png')) def printError(self): import traceback print('Exception occurred while parsing document:', file=sys.stderr) traceback.print_exc() def tabFileNameChanged(self, tab): ''' Perform all UI state changes that need to be done when the filename of the current tab has changed. ''' if tab == self.currentTab: if tab.fileName: self.setWindowTitle("") self.setWindowFilePath(tab.fileName) self.tabWidget.setTabText(self.ind, tab.getBaseName()) self.tabWidget.setTabToolTip(self.ind, tab.fileName) QDir.setCurrent(QFileInfo(tab.fileName).dir().path()) else: self.setWindowFilePath('') self.setWindowTitle(self.tr('New document') + '[*]') canReload = bool(tab.fileName) and not self.autoSaveActive(tab) self.actionSetEncoding.setEnabled(canReload) self.actionReload.setEnabled(canReload) def tabActiveMarkupChanged(self, tab): ''' Perform all UI state changes that need to be done when the active markup class of the current tab has changed. ''' if tab == self.currentTab: markupClass = tab.getActiveMarkupClass() dtMarkdown = (markupClass == markups.MarkdownMarkup) dtMkdOrReST = dtMarkdown or (markupClass == markups.ReStructuredTextMarkup) self.formattingBox.setEnabled(dtMarkdown) self.symbolBox.setEnabled(dtMarkdown) self.actionUnderline.setEnabled(dtMarkdown) self.actionBold.setEnabled(dtMkdOrReST) self.actionItalic.setEnabled(dtMkdOrReST) def tabModificationStateChanged(self, tab): ''' Perform all UI state changes that need to be done when the modification state of the current tab has changed. ''' if tab == self.currentTab: changed = tab.editBox.document().isModified() if self.autoSaveActive(tab): changed = False self.actionSave.setEnabled(changed) self.setWindowModified(changed) def createTab(self, fileName): self.currentTab = ReTextTab(self, fileName, previewState=int(globalSettings.livePreviewByDefault)) self.currentTab.fileNameChanged.connect(lambda: self.tabFileNameChanged(self.currentTab)) self.currentTab.modificationStateChanged.connect(lambda: self.tabModificationStateChanged(self.currentTab)) self.currentTab.activeMarkupChanged.connect(lambda: self.tabActiveMarkupChanged(self.currentTab)) self.tabWidget.addTab(self.currentTab, self.tr("New document")) self.currentTab.updateBoxesVisibility() def closeTab(self, ind): if self.maybeSave(ind): if self.tabWidget.count() == 1: self.createTab("") closedTab = self.tabWidget.widget(ind) if closedTab.fileName: self.fileSystemWatcher.removePath(closedTab.fileName) self.tabWidget.removeTab(ind) closedTab.deleteLater() def changeIndex(self, ind): ''' This function is called when a different tab is selected. It changes the state of the window to mirror the current state of the newly selected tab. Future changes to this state will be done in response to signals emitted by the tab, to which the window was subscribed when the tab was created. The window is subscribed to all tabs like this, but only the active tab will logically generate these signals. Aside from the above this function also calls the handlers for the other changes that are implied by a tab switch: filename change, modification state change and active markup change. ''' self.currentTab = self.tabWidget.currentWidget() editBox = self.currentTab.editBox previewState = self.currentTab.previewState self.actionUndo.setEnabled(editBox.document().isUndoAvailable()) self.actionRedo.setEnabled(editBox.document().isRedoAvailable()) self.actionCopy.setEnabled(editBox.textCursor().hasSelection()) self.actionCut.setEnabled(editBox.textCursor().hasSelection()) self.actionPreview.setChecked(previewState >= PreviewLive) self.actionLivePreview.setChecked(previewState == PreviewLive) self.actionTableMode.setChecked(editBox.tableModeEnabled) self.editBar.setEnabled(previewState < PreviewNormal) self.ind = ind editBox.setFocus(Qt.OtherFocusReason) self.tabFileNameChanged(self.currentTab) self.tabModificationStateChanged(self.currentTab) self.tabActiveMarkupChanged(self.currentTab) def changeEditorFont(self): font, ok = QFontDialog.getFont(globalSettings.editorFont, self) if ok: globalSettings.editorFont = font for tab in self.iterateTabs(): tab.editBox.updateFont() def changePreviewFont(self): font, ok = QFontDialog.getFont(globalSettings.font, self) if ok: globalSettings.font = font for tab in self.iterateTabs(): tab.triggerPreviewUpdate() def preview(self, viewmode): self.currentTab.previewState = viewmode * 2 self.actionLivePreview.setChecked(False) self.editBar.setDisabled(viewmode) self.currentTab.updateBoxesVisibility() def enableLivePreview(self, livemode): self.currentTab.previewState = int(livemode) self.actionPreview.setChecked(livemode) self.editBar.setEnabled(True) self.currentTab.updateBoxesVisibility() def enableWebKit(self, enable): globalSettings.useWebKit = enable for tab in self.iterateTabs(): tab.previewBox.disconnectExternalSignals() tab.previewBox.setParent(None) tab.previewBox.deleteLater() tab.previewBox = tab.createPreviewBox(tab.editBox) tab.previewBox.setMinimumWidth(125) tab.addWidget(tab.previewBox) tab.setSizes((50, 50)) tab.triggerPreviewUpdate() tab.updateBoxesVisibility() def enableCopy(self, copymode): self.actionCopy.setEnabled(copymode) self.actionCut.setEnabled(copymode) def enableFullScreen(self, yes): if yes: self.showFullScreen() else: self.showNormal() def openConfigDialog(self): dlg = ConfigDialog(self) dlg.setWindowTitle(self.tr('Preferences')) dlg.show() def enableFakeVimMode(self, yes): globalSettings.useFakeVim = yes if yes: FakeVimMode.init(self) for tab in self.iterateTabs(): tab.editBox.installFakeVimHandler() else: FakeVimMode.exit(self) def enableSpellCheck(self, yes): try: dict = enchant.Dict(self.sl or None) except enchant.errors.Error as e: QMessageBox.warning(self, '', str(e)) self.actionEnableSC.setChecked(False) yes = False self.setAllDictionaries(dict if yes else None) globalSettings.spellCheck = yes def setAllDictionaries(self, dictionary): for tab in self.iterateTabs(): hl = tab.highlighter hl.dictionary = dictionary hl.rehighlight() def changeLocale(self): localedlg = LocaleDialog(self, defaultText=self.sl) if localedlg.exec() != QDialog.Accepted: return sl = localedlg.localeEdit.text() try: enchant.Dict(sl or None) except enchant.errors.Error as e: QMessageBox.warning(self, '', str(e)) else: self.sl = sl or None self.enableSpellCheck(self.actionEnableSC.isChecked()) if localedlg.checkBox.isChecked(): globalSettings.spellCheckLocale = sl def searchBarVisibilityChanged(self, visible): self.actionSearch.setChecked(visible) if visible: self.searchEdit.setFocus(Qt.ShortcutFocusReason) def find(self, back=False, replace=False): flags = QTextDocument.FindFlags() if back: flags |= QTextDocument.FindBackward if self.csBox.isChecked(): flags |= QTextDocument.FindCaseSensitively text = self.searchEdit.text() replaceText = self.replaceEdit.text() if replace else None found = self.currentTab.find(text, flags, replaceText=replaceText) self.setSearchEditColor(found) def replaceAll(self): text = self.searchEdit.text() replaceText = self.replaceEdit.text() found = self.currentTab.replaceAll(text, replaceText) self.setSearchEditColor(found) def setSearchEditColor(self, found): palette = self.searchEdit.palette() palette.setColor(QPalette.Active, QPalette.Base, Qt.white if found else QColor(255, 102, 102)) self.searchEdit.setPalette(palette) def showInDir(self): if self.currentTab.fileName: path = QFileInfo(self.currentTab.fileName).path() QDesktopServices.openUrl(QUrl.fromLocalFile(path)) else: QMessageBox.warning(self, '', self.tr("Please, save the file somewhere.")) def moveToTopOfRecentFileList(self, fileName): if fileName: files = readListFromSettings("recentFileList") if fileName in files: files.remove(fileName) files.insert(0, fileName) if len(files) > 10: del files[10:] writeListToSettings("recentFileList", files) def createNew(self, text=None): self.createTab("") self.ind = self.tabWidget.count()-1 self.tabWidget.setCurrentIndex(self.ind) if text: self.currentTab.editBox.textCursor().insertText(text) def switchTab(self, shift=1): self.tabWidget.setCurrentIndex((self.ind + shift) % self.tabWidget.count()) def updateRecentFiles(self): self.menuRecentFiles.clear() self.recentFilesActions = [] filesOld = readListFromSettings("recentFileList") files = [] for f in filesOld: if QFile.exists(f): files.append(f) self.recentFilesActions.append(self.act(f, trig=self.openFunction(f))) writeListToSettings("recentFileList", files) for action in self.recentFilesActions: self.menuRecentFiles.addAction(action) def markupFunction(self, markup): return lambda: self.setDefaultMarkup(markup) def openFunction(self, fileName): return lambda: self.openFileWrapper(fileName) def extensionFunction(self, data): return lambda: \ self.runExtensionCommand(data['Exec'], data['FileFilter'], data['DefaultExtension']) def getExportExtensionsList(self): extensions = [] for extsprefix in datadirs: extsdir = QDir(extsprefix+'/export-extensions/') if extsdir.exists(): for fileInfo in extsdir.entryInfoList(['*.desktop', '*.ini'], QDir.Files | QDir.Readable): extensions.append(self.readExtension(fileInfo.filePath())) locale = QLocale.system().name() self.extensionActions = [] for extension in extensions: try: if ('Name[%s]' % locale) in extension: name = extension['Name[%s]' % locale] elif ('Name[%s]' % locale.split('_')[0]) in extension: name = extension['Name[%s]' % locale.split('_')[0]] else: name = extension['Name'] data = {} for prop in ('FileFilter', 'DefaultExtension', 'Exec'): if 'X-ReText-'+prop in extension: data[prop] = extension['X-ReText-'+prop] elif prop in extension: data[prop] = extension[prop] else: data[prop] = '' action = self.act(name, trig=self.extensionFunction(data)) if 'Icon' in extension: action.setIcon(self.actIcon(extension['Icon'])) mimetype = extension['MimeType'] if 'MimeType' in extension else None except KeyError: print('Failed to parse extension: Name is required', file=sys.stderr) else: self.extensionActions.append((action, mimetype)) def updateExtensionsVisibility(self): markupClass = self.currentTab.getActiveMarkupClass() for action in self.extensionActions: if markupClass is None: action[0].setEnabled(False) continue mimetype = action[1] if mimetype is None: enabled = True elif markupClass == markups.MarkdownMarkup: enabled = (mimetype in ("text/x-retext-markdown", "text/x-markdown", "text/markdown")) elif markupClass == markups.ReStructuredTextMarkup: enabled = (mimetype in ("text/x-retext-rst", "text/x-rst")) else: enabled = False action[0].setEnabled(enabled) def readExtension(self, fileName): extFile = QFile(fileName) extFile.open(QIODevice.ReadOnly) extension = {} stream = QTextStream(extFile) while not stream.atEnd(): line = stream.readLine() if '=' in line: index = line.index('=') extension[line[:index].rstrip()] = line[index+1:].lstrip() extFile.close() return extension def openFile(self): supportedExtensions = ['.txt'] for markup in markups.get_all_markups(): supportedExtensions += markup.file_extensions fileFilter = ' (' + str.join(' ', ['*'+ext for ext in supportedExtensions]) + ');;' fileNames = QFileDialog.getOpenFileNames(self, self.tr("Select one or several files to open"), "", self.tr("Supported files") + fileFilter + self.tr("All files (*)")) for fileName in fileNames[0]: self.openFileWrapper(fileName) def openFileWrapper(self, fileName): if not fileName: return fileName = QFileInfo(fileName).canonicalFilePath() exists = False for i, tab in enumerate(self.iterateTabs()): if tab.fileName == fileName: exists = True ex = i if exists: self.tabWidget.setCurrentIndex(ex) elif QFile.exists(fileName): noEmptyTab = ( (self.ind is None) or self.currentTab.fileName or self.currentTab.editBox.toPlainText() or self.currentTab.editBox.document().isModified() ) if noEmptyTab: self.createTab(fileName) self.ind = self.tabWidget.count()-1 self.tabWidget.setCurrentIndex(self.ind) if fileName: self.fileSystemWatcher.addPath(fileName) self.currentTab.readTextFromFile(fileName) self.moveToTopOfRecentFileList(self.currentTab.fileName) def showEncodingDialog(self): if not self.maybeSave(self.ind): return codecsSet = set(bytes(QTextCodec.codecForName(alias).name()) for alias in QTextCodec.availableCodecs()) encoding, ok = QInputDialog.getItem(self, '', self.tr('Select file encoding from the list:'), [bytes(b).decode() for b in sorted(codecsSet)], 0, False) if ok: self.currentTab.readTextFromFile(None, encoding) def saveFileAs(self): self.saveFile(dlg=True) def saveAll(self): for tab in self.iterateTabs(): if tab.fileName and QFileInfo(tab.fileName).isWritable(): tab.saveTextToFile() def saveFile(self, dlg=False): fileNameToSave = self.currentTab.fileName if (not fileNameToSave) or dlg: markupClass = self.currentTab.getActiveMarkupClass() if (markupClass is None) or not hasattr(markupClass, 'default_extension'): defaultExt = self.tr("Plain text (*.txt)") ext = ".txt" else: defaultExt = self.tr('%s files', 'Example of final string: Markdown files') \ % markupClass.name + ' (' + str.join(' ', ('*'+extension for extension in markupClass.file_extensions)) + ')' if markupClass == markups.MarkdownMarkup: ext = globalSettings.markdownDefaultFileExtension elif markupClass == markups.ReStructuredTextMarkup: ext = globalSettings.restDefaultFileExtension else: ext = markupClass.default_extension fileNameToSave = QFileDialog.getSaveFileName(self, self.tr("Save file"), "", defaultExt)[0] if fileNameToSave: if not QFileInfo(fileNameToSave).suffix(): fileNameToSave += ext # Make sure we don't overwrite a file opened in other tab for tab in self.iterateTabs(): if tab is not self.currentTab and tab.fileName == fileNameToSave: QMessageBox.warning(self, "", self.tr("Cannot save to file which is open in another tab!")) return False self.actionSetEncoding.setDisabled(self.autoSaveActive()) if fileNameToSave: if self.currentTab.saveTextToFile(fileNameToSave): self.moveToTopOfRecentFileList(self.currentTab.fileName) return True else: QMessageBox.warning(self, '', self.tr("Cannot save to file because it is read-only!")) return False def saveHtml(self, fileName): if not QFileInfo(fileName).suffix(): fileName += ".html" try: _, htmltext, _ = self.currentTab.getDocumentForExport(includeStyleSheet=False, webenv=True) except Exception: return self.printError() htmlFile = QFile(fileName) htmlFile.open(QIODevice.WriteOnly) html = QTextStream(htmlFile) if globalSettings.defaultCodec: html.setCodec(globalSettings.defaultCodec) html << htmltext htmlFile.close() def textDocument(self, title, htmltext): td = QTextDocument() td.setMetaInformation(QTextDocument.DocumentTitle, title) if self.ss: td.setDefaultStyleSheet(self.ss) td.setHtml(htmltext) td.setDefaultFont(globalSettings.font) return td def saveOdf(self): title, htmltext, _ = self.currentTab.getDocumentForExport(includeStyleSheet=True, webenv=False) try: document = self.textDocument(title, htmltext) except Exception: return self.printError() fileName = QFileDialog.getSaveFileName(self, self.tr("Export document to ODT"), "", self.tr("OpenDocument text files (*.odt)"))[0] if not QFileInfo(fileName).suffix(): fileName += ".odt" writer = QTextDocumentWriter(fileName) writer.setFormat(b"odf") writer.write(document) def saveFileHtml(self): fileName = QFileDialog.getSaveFileName(self, self.tr("Save file"), "", self.tr("HTML files (*.html *.htm)"))[0] if fileName: self.saveHtml(fileName) def getDocumentForPrint(self, title, htmltext, preview): if globalSettings.useWebKit: return preview try: return self.textDocument(title, htmltext) except Exception: self.printError() def standardPrinter(self, title): printer = QPrinter(QPrinter.HighResolution) printer.setDocName(title) printer.setCreator('ReText %s' % app_version) return printer def savePdf(self): fileName = QFileDialog.getSaveFileName(self, self.tr("Export document to PDF"), "", self.tr("PDF files (*.pdf)"))[0] if fileName: if not QFileInfo(fileName).suffix(): fileName += ".pdf" title, htmltext, preview = self.currentTab.getDocumentForExport(includeStyleSheet=True, webenv=False) printer = self.standardPrinter(title) printer.setOutputFormat(QPrinter.PdfFormat) printer.setOutputFileName(fileName) document = self.getDocumentForPrint(title, htmltext, preview) if document != None: document.print(printer) def printFile(self): title, htmltext, preview = self.currentTab.getDocumentForExport(includeStyleSheet=True, webenv=False) printer = self.standardPrinter(title) dlg = QPrintDialog(printer, self) dlg.setWindowTitle(self.tr("Print document")) if (dlg.exec() == QDialog.Accepted): document = self.getDocumentForPrint(title, htmltext, preview) if document != None: document.print(printer) def printPreview(self): title, htmltext, preview = self.currentTab.getDocumentForExport(includeStyleSheet=True, webenv=False) document = self.getDocumentForPrint(title, htmltext, preview) if document is None: return printer = self.standardPrinter(title) preview = QPrintPreviewDialog(printer, self) preview.paintRequested.connect(document.print) preview.exec() def runExtensionCommand(self, command, filefilter, defaultext): import shlex of = ('%of' in command) html = ('%html' in command) if of: if defaultext and not filefilter: filefilter = '*'+defaultext fileName = QFileDialog.getSaveFileName(self, self.tr('Export document'), '', filefilter)[0] if not fileName: return if defaultext and not QFileInfo(fileName).suffix(): fileName += defaultext else: fileName = 'out' + defaultext basename = '.%s.retext-temp' % self.currentTab.getBaseName() if html: tmpname = basename+'.html' self.saveHtml(tmpname) else: tmpname = basename + self.currentTab.getActiveMarkupClass().default_extension self.currentTab.writeTextToFile(tmpname) command = command.replace('%of', shlex.quote(fileName)) command = command.replace('%html' if html else '%if', shlex.quote(tmpname)) try: Popen(str(command), shell=True).wait() except Exception as error: errorstr = str(error) QMessageBox.warning(self, '', self.tr('Failed to execute the command:') + '\n' + errorstr) QFile(tmpname).remove() def autoSaveActive(self, tab=None): tab = tab if tab else self.currentTab return bool(self.autoSaveEnabled and tab.fileName and QFileInfo(tab.fileName).isWritable()) def clipboardDataChanged(self): mimeData = QApplication.instance().clipboard().mimeData() if mimeData is not None: self.actionPaste.setEnabled(mimeData.hasText() or mimeData.hasImage()) def insertFormatting(self, formatting): cursor = self.currentTab.editBox.textCursor() text = cursor.selectedText() moveCursorTo = None def c(cursor): nonlocal moveCursorTo moveCursorTo = cursor.position() def ensurenl(cursor): if not cursor.atBlockStart(): cursor.insertText('\n\n') toinsert = { 'header': (ensurenl, '# ', text), 'italic': ('*', text, c, '*'), 'bold': ('**', text, c, '**'), 'underline': ('<u>', text, c, '</u>'), 'numbering': (ensurenl, ' 1. ', text), 'bullets': (ensurenl, ' * ', text), 'image': ('![', text or self.tr('Alt text'), c, '](', self.tr('URL'), ')'), 'link': ('[', text or self.tr('Link text'), c, '](', self.tr('URL'), ')'), 'inline code': ('`', text, c, '`'), 'code block': (ensurenl, ' ', text), 'blockquote': (ensurenl, '> ', text), } if formatting not in toinsert: return cursor.beginEditBlock() for token in toinsert[formatting]: if callable(token): token(cursor) else: cursor.insertText(token) cursor.endEditBlock() self.formattingBox.setCurrentIndex(0) # Bring back the focus on the editor self.currentTab.editBox.setFocus(Qt.OtherFocusReason) if moveCursorTo: cursor.setPosition(moveCursorTo) self.currentTab.editBox.setTextCursor(cursor) def insertSymbol(self, num): if num: self.currentTab.editBox.insertPlainText('&'+self.usefulChars[num-1]+';') self.symbolBox.setCurrentIndex(0) def fileChanged(self, fileName): ind = None for testind, tab in enumerate(self.iterateTabs()): if tab.fileName == fileName: ind = testind if ind is None: self.fileSystemWatcher.removePath(fileName) self.tabWidget.setCurrentIndex(ind) if not QFile.exists(fileName): self.currentTab.editBox.document().setModified(True) QMessageBox.warning(self, '', self.tr( 'This file has been deleted by other application.\n' 'Please make sure you save the file before exit.')) elif not self.currentTab.editBox.document().isModified(): # File was not modified in ReText, reload silently self.currentTab.readTextFromFile() else: text = self.tr( 'This document has been modified by other application.\n' 'Do you want to reload the file (this will discard all ' 'your changes)?\n') if self.autoSaveEnabled: text += self.tr( 'If you choose to not reload the file, auto save mode will ' 'be disabled for this session to prevent data loss.') messageBox = QMessageBox(QMessageBox.Warning, '', text) reloadButton = messageBox.addButton(self.tr('Reload'), QMessageBox.YesRole) messageBox.addButton(QMessageBox.Cancel) messageBox.exec() if messageBox.clickedButton() is reloadButton: self.currentTab.readTextFromFile() else: self.autoSaveEnabled = False self.currentTab.editBox.document().setModified(True) if fileName not in self.fileSystemWatcher.files(): # https://github.com/retext-project/retext/issues/137 self.fileSystemWatcher.addPath(fileName) def maybeSave(self, ind): tab = self.tabWidget.widget(ind) if self.autoSaveActive(tab): tab.saveTextToFile() return True if not tab.editBox.document().isModified(): return True self.tabWidget.setCurrentIndex(ind) ret = QMessageBox.warning(self, '', self.tr("The document has been modified.\nDo you want to save your changes?"), QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel) if ret == QMessageBox.Save: return self.saveFile(False) elif ret == QMessageBox.Cancel: return False return True def closeEvent(self, closeevent): for ind in range(self.tabWidget.count()): if not self.maybeSave(ind): return closeevent.ignore() if globalSettings.saveWindowGeometry and not self.isMaximized(): globalSettings.windowGeometry = self.saveGeometry() if globalSettings.openLastFilesOnStartup: files = [tab.fileName for tab in self.iterateTabs()] writeListToSettings("lastFileList", files) globalSettings.lastTabIndex = self.tabWidget.currentIndex() closeevent.accept() def viewHtml(self): htmlDlg = HtmlDialog(self) try: _, htmltext, _ = self.currentTab.getDocumentForExport(includeStyleSheet=False, webenv=False) except Exception: return self.printError() winTitle = self.currentTab.getBaseName() htmlDlg.setWindowTitle(winTitle+" ("+self.tr("HTML code")+")") htmlDlg.textEdit.setPlainText(htmltext.rstrip()) htmlDlg.hl.rehighlight() htmlDlg.show() htmlDlg.raise_() htmlDlg.activateWindow() def openHelp(self): QDesktopServices.openUrl(QUrl('https://github.com/retext-project/retext/wiki')) def aboutDialog(self): QMessageBox.about(self, self.aboutWindowTitle, '<p><b>' + (self.tr('ReText %s (using PyMarkups %s)') % (app_version, markups.__version__)) +'</b></p>' + self.tr('Simple but powerful editor' ' for Markdown and reStructuredText') +'</p><p>'+self.tr('Author: Dmitry Shachnev, 2011').replace('2011', '2011–2016') +'<br><a href="https://github.com/retext-project/retext">'+self.tr('Website') +'</a> | <a href="http://daringfireball.net/projects/markdown/syntax">' +self.tr('Markdown syntax') +'</a> | <a href="http://docutils.sourceforge.net/docs/user/rst/quickref.html">' +self.tr('reStructuredText syntax')+'</a></p>') def setDefaultMarkup(self, markupClass): globalSettings.defaultMarkup = markupClass.name for tab in self.iterateTabs(): if not tab.fileName: tab.updateActiveMarkupClass()