def open_context_menu(self, event): ## Make life easier get_icon = Icons().get_icon ## Is this a system install? sysInstall = (os.path.expanduser('~') in sys.argv[0]) menu = QMenu(self) ## Edit item editAction = QAction(QIcon(get_icon("edit-entry", sysInstall)), "Edit entry", self) editAction.setStatusTip("Edit entry") editAction.triggered.connect(self.parent.edit_item) ## The remove item removeAction = QAction(QIcon(get_icon("list-remove", sysInstall)), "Remove item", self) removeAction.setStatusTip("Remove item") removeAction.triggered.connect(self.parent.remove_item) ## Add the actions to the menu menu.addAction(editAction) menu.addAction(removeAction) ## Execute the menu menu.exec(event.globalPos())
def initUI(self): # 添加打开菜单 openFile = QAction(QIcon('open.png'), 'Open', self) openFile.setShortcut('Ctrl+O') openFile.setStatusTip('Open new File') openFile.triggered.connect(self.openFile) openFile.setIcon(QIcon('import.ico')) menubar = self.menuBar() fileMenu = menubar.addMenu('&File') fileMenu.addAction(openFile) toolBar = self.addToolBar("File") toolBar.addAction(openFile) # 设置PlotWidget self.dataPlot.plotItem.showGrid(True, True, 0.5) pen = pyqtgraph.mkPen(color='b') self.dataPlotRange.setMouseEnabled(x=False, y=False) # dataPlotRange 不能移动 self.dataPlot.setAutoVisible(y=True) # 设置treeWidget的相关 self.treeWidget.setColumnCount(4) self.treeWidget.setHeaderLabels( ['#', 'File Name', 'Corrective Name', 'Unit']) self.treeWidget.setColumnWidth(0, 30) self.treeWidget.setColumnWidth(1, 100) self.treeWidget.setColumnWidth(2, 200)
def init_menu(window): exitAction = QAction('&Exit', window) exitAction.setShortcut('Ctrl+Q') exitAction.setStatusTip('Exit application') exitAction.triggered.connect(window.close) menu = window.menuBar() menuitem = menu.addMenu('&File') menuitem.addAction(exitAction)
def clone_action(ac, parent): if ac.isSeparator(): ans = QAction(parent) ans.setSeparator(True) return ans sc = ac.shortcut() sc = '' if sc.isEmpty() else sc.toString(sc.NativeText) ans = QAction(ac.icon(), ac.text() + '\t' + sc, parent) ans.triggered.connect(ac.trigger) ans.setEnabled(ac.isEnabled()) ans.setStatusTip(ac.statusTip()) ans.setVisible(ac.isVisible()) return ans
def __init__(self, asterstudy): """Constructor. Create test actions.""" self._asterstudy = asterstudy self._actions = {} # action = QAction("Create sample study", asterstudy) action.setStatusTip("Create a sample study for testing") action.triggered.connect(self._create_sample_study) self._actions[self.DefaultStudy] = action # action = QAction("Dump study", asterstudy) action.setStatusTip("Dump study contents to the file") action.triggered.connect(self._dump_study) self._actions[self.DumpStudy] = action self._dump_file_name = None
def _createAction(self, actionid, icon, text, tooltip, slot, toggled=False): """ Creates the new internal action with given identifier. """ action = QAction(icon, text, self) action.setToolTip(text) action.setStatusTip(tooltip) action.setCheckable(toggled) if slot is not None: if action.isCheckable(): action.toggled.connect(slot) else: action.triggered.connect(slot) self._actions[actionid] = action return action
def initUI(self): # Title title = QLabel(self) title.setFont(self.titleFont) title.setText("TEXT TO THREAD") title.setMinimumWidth(int(self.width / 2)) title.move(5, 22) # Text box self.text = QTextEdit(self) self.text.setMinimumWidth(self.width - 10) self.text.setMinimumHeight(self.height - 110) self.text.move(5, 50) # Publish button self.send = QPushButton(self) self.send.setText("Publish") self.send.setMinimumWidth(self.width - 10) self.send.move(5, self.height - 35) self.send.clicked.connect(self.convertToThread) # Add images checkbox self.images = QCheckBox(self) self.images.setText("Add images") self.images.move(10, self.height - 62) # Create the menu bar menu = self.menuBar() actions = menu.addMenu("&Actions") # Clear the text box new = QAction("&New", self) new.setShortcut("Ctrl+N") new.setStatusTip("Clear the window") new.triggered.connect(self.text.clear) actions.addAction(new) # Send the tweets send = QAction("&Send", self) send.setShortcut("Ctrl+Return") send.setStatusTip("Send the tweets") send.triggered.connect(self.convertToThread) actions.addAction(send) # Rewrite the access credentials credentials = QAction("&Change credentials", self) credentials.setShortcut("Ctrl+R") credentials.setStatusTip("Change the credentials, restart required") credentials.triggered.connect(self.changeKeys) actions.addAction(credentials) # Exit from the app exit = QAction("&Exit", self) exit.setShortcut("Ctrl+Q") exit.setStatusTip("Exit from the app") exit.triggered.connect(sys.exit) actions.addAction(exit)
def load_recents_menu(self): self.recentsMenu.clear() recents = Recents().load_recents() if len(recents) == 0: self.recentsMenu.setEnabled(False) else: recents.reverse() self.recentsMenu.setEnabled(True) for path in recents: rAction = QAction(os.path.basename(path), self) rAction.setStatusTip("Path: %s" % path) rAction.triggered.connect(partial(self.load_file, path)) self.recentsMenu.addAction(rAction)
def clone_action(ac, parent): if ac.isSeparator(): ans = QAction(parent) ans.setSeparator(True) return ans sc = ac.shortcut() sc = '' if sc.isEmpty() else sc.toString( QKeySequence.SequenceFormat.NativeText) text = ac.text() if '\t' not in text: text += '\t' + sc ans = QAction(ac.icon(), text, parent) ans.triggered.connect(ac.trigger) ans.setEnabled(ac.isEnabled()) ans.setStatusTip(ac.statusTip()) ans.setVisible(ac.isVisible()) return ans
def initUI(self): # 添加打开菜单 openFile = QAction(QIcon('open.png'), 'Open', self) openFile.setShortcut('Ctrl+O') openFile.setStatusTip('Open new File') openFile.triggered.connect(self.openFile) openFile.setIcon(QIcon('import.ico')) menubar = self.menuBar() fileMenu = menubar.addMenu('&File') fileMenu.addAction(openFile) toolBar = self.addToolBar("File") toolBar.addAction(openFile) # 设置PlotWidget self.dataPlot.plotItem.showGrid(True, True, 0.5) self.dataPlotRange.setMouseEnabled(x=False, y=False) # dataPlotRange 不能移动 self.dataPlot.setAutoVisible(y=True) # 设置treeWidget的相关 self.treeWidget.setContextMenuPolicy(Qt.CustomContextMenu) self.treeWidget.customContextMenuRequested.connect( self.showContextMenu) self.treeWidget.treeContextMenu = QMenu(self) self.actionA = self.treeWidget.treeContextMenu.addAction(u'Plot') self.actionA.triggered.connect(lambda: self.chartPlot( self.treeWidget.currentItem(), self.treeWidget.selectedItems())) self.treeWidget.setColumnCount(4) self.treeWidget.setHeaderLabels( ['#', 'File Name', 'Corrective Name', 'Unit']) self.treeWidget.setColumnWidth(0, 30) self.treeWidget.setColumnWidth(1, 100) self.treeWidget.setColumnWidth(2, 200)
class GUI(QtWidgets.QMainWindow): def __init__(self): '''Asetetaan muuttujille alkuarvoja ohjelman suorittamiseksi''' super().__init__() self.title = "Lujuusanalysaattori" self.left = 200 self.top = 200 self.width = 1300 self.height = 700 self.palkin_default_pituus = 5 self.square_size = 10 self.ikkuna() self.button_height = 75 self.button_width = 150 self.button_separation = 25 self.x = 0 self.y = 0 self.palkin_leveys = 700 self.palkin_korkeus = 75 self.palkin_keskipiste = 650 self.palkin_paatypiste = 1000 self.yksikko_arvo = 0 self.voima = 20 self.maks_jannitys = "-" self.asteikko_teksti = QGraphicsSimpleTextItem() '''Lisää QGraphicsScenen ruudukon piirtämistä varten''' self.scene = QtWidgets.QGraphicsScene() self.scene.setSceneRect(0, -20, self.width - 200, self.height - 100) '''Suoritetaan lukuisia metodeja, jolla ohjelma "alustetaan"''' self.aloita_simulaatio() self.simulaatioikkuna() self.simulaatio_nappi() self.materiaali_valikko() self.uusi_palkki_nappi() self.lisaa_tuki_nappi() self.lisaa_ulkoinen_voima_nappi() self.poista_ulkoinen_voima_nappi() self.vaihda_tuki_nappi() Ominaisuudet.alkuarvot(self) self.lisaa_palkki() self.palkin_pituus_valikko() self.yksikko_pituus() self.asteikko() self.lisaa_asteikko_arvo() self.asteikko_teksti.hide() self.tulos_teksti() self.lisaa_seina_tuki() self.lisaa_tuki_alhaalta() self.ulkoinen_voima_valikko() self.ulkoinen_voima_nuoli_alatuki() self.ulkoinen_voima_nuoli_seinatuki() Ominaisuudet.alkuarvot(self) '''Asetetaan tietyille napeille tietty näkyvyys''' self.lisaa_tuki.setEnabled(False) self.simuloi.setEnabled(False) self.show() def ikkuna(self): '''Tekee ohjelman pääikkunan''' self.setGeometry(self.left, self.top, self.width, self.height) self.setWindowTitle('Lujuusanalysaattori') self.horizontal = QtWidgets.QHBoxLayout() '''Luo menubarin''' self.uusiAction = QAction("Uusi simulaatio", self) self.uusiAction.setStatusTip("Luo uusi rakenne") self.uusiAction.triggered.connect(self.uusi_rakenne) self.uusiAction.setEnabled(True) self.uusiAction.setShortcut("Ctrl+N") self.tallennaAction = QAction("Tallenna simulaatio", self) self.tallennaAction.setStatusTip("Tallenna simulaatio") self.tallennaAction.triggered.connect(self.tallenna_rakenne) self.tallennaAction.setEnabled(False) self.tallennaAction.setShortcut("Ctrl+S") self.avaaAction = QAction("Lataa simulaatio", self) self.avaaAction.setStatusTip("Lataa simulaatio tiedostosta") self.avaaAction.triggered.connect(self.lataa_tallennettu_rakenne) self.avaaAction.setShortcut("Ctrl+O") self.exitAction = QAction("Exit", self) self.exitAction.setToolTip("Lopeta ohjelma") self.exitAction.triggered.connect(self.close_application) self.exitAction.setShortcut("Ctrl+E") self.statusBar() mainMenu = self.menuBar() fileMenu = mainMenu.addMenu('&File') aboutMenu = mainMenu.addMenu('&About') fileMenu.addAction(self.uusiAction) fileMenu.addAction(self.avaaAction) fileMenu.addAction(self.tallennaAction) fileMenu.addAction(self.exitAction) def tallenna_rakenne(self): '''Hoitaa rakenteen tallentamisen''' tallennus = Tallennin.tallenin(self) if tallennus == True: '''Kerrotaan käyttäjälle, että tallennus onnistui''' msgBox = QMessageBox() msgBox.setText("Tallennus onnistui!") msgBox.setWindowTitle("Onnistunut Tallennus") msgBox.setMinimumWidth(50) msgBox.addButton(QPushButton('OK'), QMessageBox.NoRole) msgBox.exec_() def lataa_tallennettu_rakenne(self): '''Metodi avaa QFileDialog ikkunan, josta käyttäjä valitsee tiedoston, jossa aiemmin tallennettu rakenne sijaitsee. Vain .txt -tiedostot ovat ladattavissa ''' options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog tiedosto, _ = QFileDialog.getOpenFileName(self, "Valitse tiedosto", "", "txt Files (*.txt)", options=options) lataus = Lataaja.lataaja(self, tiedosto) if lataus == False: return if lataus == True: self.uusi_rakenne() Lataaja.lataaja(self, tiedosto) tuen_tyyppi = Ominaisuudet.palauta_tuen_tyyppi(self) '''Jos tuki on seinästä, piirretään sitä vastaava grafiikka''' if tuen_tyyppi == 0: self.nayta_seina_tuki() self.gradient_seina_tuki() '''Jos tuki on alhaalta, piirretään sitä vastaava grafiikka''' if tuen_tyyppi == 1: self.nayta_tuki_alhaalta() self.gradient_alatuki() if tuen_tyyppi != 2: self.vaihda_tuki.show() self.lisaa_tuki.hide() '''Jos ulkoinen voima on asetettu, piirretään se''' ulkoinen_voima = int( Ominaisuudet.onko_ulkoinen_voima_asetettu(self)) if ulkoinen_voima == 1: self.nayta_ulkoinen_voima() self.nayta_palkki() Laskin.laskin(self) self.paivita_tulos_teksti() self.tulos.show() self.sp.setValue(float(Ominaisuudet.palauta_palkin_pituus(self))) self.uusiAction.setEnabled(True) self.simuloi.setEnabled(True) '''Kerrotaan käyttäjälle, että kaikki onnistui''' msgBox = QMessageBox() msgBox.setText("Lataus onnistui!") msgBox.setWindowTitle("Onnistunut lataus") msgBox.addButton(QPushButton('OK'), QMessageBox.NoRole) msgBox.exec_() def aloita_simulaatio(self): '''Aloittaa simulaation''' self.setCentralWidget(QtWidgets.QWidget()) self.horizontal = QtWidgets.QHBoxLayout() self.centralWidget().setLayout(self.horizontal) def simulaatioikkuna(self): '''lisää view näyttämistä varten''' self.view = QtWidgets.QGraphicsView(self.scene, self) self.view.adjustSize() self.view.show() self.horizontal.addWidget(self.view) def uusi_palkki_nappi(self): '''Luo Uusi palkki -napin''' self.uusi_palkki = QPushButton('Uusi palkki') self.uusi_palkki.setToolTip("Lisää uusi palkki") self.uusi_palkki.move(0, 0) self.uusi_palkki.resize(self.button_width, self.button_height) self.uusi_palkki.font = QtGui.QFont() self.uusi_palkki.font.setPointSize(12) self.uusi_palkki.setFont(self.uusi_palkki.font) self.uusi_palkki.setEnabled(True) self.scene.addWidget(self.uusi_palkki) self.uusi_palkki.clicked.connect(self.nayta_palkki) def nayta_palkki(self): '''Näyttää kaikki palkkiin liittyvät komponentit sekä asettaa uusi palkki -napin toimimattomaksi''' self.rect.show() self.palkin_pituus.show() self.sp.show() self.yksikko.show() self.asteikko_teksti.show() self.line.show() self.nuoli_1.show() self.nuoli_2.show() self.uusi_palkki.setEnabled(False) self.lisaa_tuki.setEnabled(True) self.materiaali_valinta.setEnabled(True) def lisaa_palkki(self): '''lisää palkin''' self.rect = QGraphicsRectItem(300, 200, self.palkin_leveys, self.palkin_korkeus) self.rect.setBrush(QBrush(4)) self.scene.addItem(self.rect) self.rect.hide() self.lisaa_tuki.setEnabled(True) '''Aina kun on uusi palkki luotu, voidaan aloittaa simulaatio alusta''' self.uusiAction.setEnabled(True) def lisaa_tuki_nappi(self): '''Luo Lisää tuki -napin''' self.lisaa_tuki = QPushButton("Lisää tuki") self.lisaa_tuki.setToolTip("Lisää tuki") self.lisaa_tuki.move(0, self.button_height + self.button_separation) self.lisaa_tuki.resize(self.button_width, self.button_height) self.lisaa_tuki.font = QtGui.QFont() self.lisaa_tuki.font.setPointSize(12) self.lisaa_tuki.setFont(self.lisaa_tuki.font) self.lisaa_tuki.setEnabled(False) self.lisaa_tuki.clicked.connect(self.valitse_tuki) self.scene.addWidget(self.lisaa_tuki) def vaihda_tuki_nappi(self): '''Luo vaihda tuki -napin''' self.vaihda_tuki = QPushButton("Vaihda tuki") self.vaihda_tuki.setToolTip("Vaihda tuki") self.vaihda_tuki.move(0, self.button_height + self.button_separation) self.vaihda_tuki.resize(self.button_width, self.button_height) self.vaihda_tuki.setFont(self.lisaa_tuki.font) self.vaihda_tuki.clicked.connect(self.valitse_tuki) self.scene.addWidget(self.vaihda_tuki) self.vaihda_tuki.hide() def valitse_tuki(self): '''Tuen valinta. Jos tuki on seinästä (tyyppi = 0), kysytään halutaanko vaihtaa. Jos haluaa muutetaan tuen grafiikka ja arvo''' if Ominaisuudet.palauta_tuen_tyyppi(self) == 0: msgBox = QMessageBox() msgBox.setText("Haluatko vaihtaa tuen tyyppiä?") msgBox.addButton(QPushButton('En'), QMessageBox.NoRole) msgBox.addButton(QPushButton('Kyllä'), QMessageBox.YesRole) vastaus = msgBox.exec_() self.rect.setBrush(QBrush(4)) if vastaus == 1: self.viiva_1.hide() self.viiva_2.hide() self.viiva_3.hide() self.viiva_4.hide() self.nayta_tuki_alhaalta() if int(Ominaisuudet.onko_ulkoinen_voima_asetettu(self)) == 1: self.viiva.hide() self.nuoli_3.hide() self.viiva_5.show() self.nuoli_6.show() Ominaisuudet.tuki(self, 1) return '''Jos tuki on alhaalta (tyyppi = 1), kysytään halutaanko vaihtaa. Jos haluaa muutetaan tuen grafiikka ja arvo''' if Ominaisuudet.palauta_tuen_tyyppi(self) == 1: msgBox = QMessageBox() msgBox.setText("Haluatko vaihtaa tuen tyyppiä?") msgBox.addButton(QPushButton('Kyllä'), QMessageBox.YesRole) msgBox.addButton(QPushButton('En'), QMessageBox.NoRole) vastaus = msgBox.exec_() self.rect.setBrush(QBrush(4)) if vastaus == 0: Ominaisuudet.tuki(self, 0) self.nuoli_4.hide() self.nuoli_5.hide() self.nayta_seina_tuki() if int(Ominaisuudet.onko_ulkoinen_voima_asetettu(self)) == 1: self.viiva.show() self.nuoli_3.show() self.viiva_5.hide() self.nuoli_6.hide() if vastaus == 1: pass '''Jos tukea ei ole (tyyppi = 2). Tuen tyypin valinta''' if Ominaisuudet.palauta_tuen_tyyppi(self) == 2: msgBox = QMessageBox() msgBox.setText("Valitse tuen tyyppi") msgBox.addButton(QPushButton('Seinätuki'), QMessageBox.YesRole) msgBox.addButton(QPushButton('Tuki alhaalta'), QMessageBox.NoRole) vastaus = msgBox.exec_() self.vaihda_tuki.show() self.lisaa_tuki.hide() if vastaus == 0: self.nayta_seina_tuki() Ominaisuudet.tuki(self, 0) if vastaus == 1: self.nayta_tuki_alhaalta() Ominaisuudet.tuki(self, 1) '''Joka tapauksessa asetetaan ulkoisen voiman lisääminen mahdolliseksi sekä maalataan palkki normaaliksi''' self.lisaa_ulkoinen_voima.setEnabled(True) self.simuloi.setEnabled(True) def nayta_seina_tuki(self): '''Näytetään seinätukea kuvaavat grafiikat''' self.viiva_1.show() self.viiva_2.show() self.viiva_3.show() self.viiva_4.show() def nayta_tuki_alhaalta(self): '''Näytetään alatukea kuvaavat grafiikat''' self.nuoli_4.show() self.nuoli_5.show() def paivita_tuen_tyyppi(self, tyyppi): '''Päivittää tuen tyypin arvon Ominaisuudet luokassa''' Ominaisuudet.tuki(self, tyyppi) def lisaa_seina_tuki(self): '''Piirtää seinätukea kuvaavat viivat sekä asettaa self.tuen_tyyppi arvoksi Asettaa SIMULOI-napin painettavaksi''' viiva = QtGui.QPen(QtCore.Qt.black, 2) viiva.setStyle(QtCore.Qt.SolidLine) self.viiva_1 = QGraphicsLineItem(QtCore.QLineF(300, 202, 275, 225)) self.viiva_2 = QGraphicsLineItem(QtCore.QLineF(300, 222, 275, 245)) self.viiva_3 = QGraphicsLineItem(QtCore.QLineF(300, 242, 275, 265)) self.viiva_4 = QGraphicsLineItem(QtCore.QLineF(300, 262, 275, 285)) self.scene.addItem(self.viiva_1) self.scene.addItem(self.viiva_2) self.scene.addItem(self.viiva_3) self.scene.addItem(self.viiva_4) self.viiva_1.hide() self.viiva_2.hide() self.viiva_3.hide() self.viiva_4.hide() tyyppi = 0 Ominaisuudet.tuki(self, tyyppi) self.simuloi.setEnabled(True) def lisaa_tuki_alhaalta(self): '''Piirtää alhaalta tukemista kuvaavat grafiikat sekä asettaa self.tuen_tyyppi arvoksi 1''' leveys = 15 #nuolen leveus pikseleissä korkeus = 30 #nuuolen korkeus pikseleissä '''Nuolen kärkien koordinaatit''' nuoli_piste_1 = QtCore.QPointF(305, 275) nuoli_piste_2 = QtCore.QPointF(305 - leveys, 275 + korkeus) nuoli_piste_3 = QtCore.QPointF(305 + leveys, 275 + korkeus) nuoli_piste_4 = QtCore.QPointF(995, 275) nuoli_piste_5 = QtCore.QPointF(995 - leveys, 275 + korkeus) nuoli_piste_6 = QtCore.QPointF(995 + leveys, 275 + korkeus) '''Luodaan nuolia kuvaavat QPolygonF oliot''' self.nuoli_4 = QGraphicsPolygonItem( QtGui.QPolygonF([nuoli_piste_1, nuoli_piste_2, nuoli_piste_3])) self.nuoli_5 = QGraphicsPolygonItem( QtGui.QPolygonF([nuoli_piste_4, nuoli_piste_5, nuoli_piste_6])) self.nuoli_brush = QtGui.QBrush(1) self.nuoli_pencil = QtGui.QPen(QtCore.Qt.black, 2) self.nuoli_pencil.setStyle(QtCore.Qt.SolidLine) '''Lisätään nuolet sceneen''' self.scene.addItem(self.nuoli_4) self.scene.addItem(self.nuoli_5) self.nuoli_4.hide() self.nuoli_5.hide() tyyppi = 1 Ominaisuudet.tuki(self, tyyppi) self.simuloi.setEnabled(True) def lisaa_ulkoinen_voima_nappi(self): '''Luo Lisää ulkoinen voima -napin''' self.lisaa_ulkoinen_voima = QPushButton("Lisää ulkoinen voima") self.lisaa_ulkoinen_voima.setToolTip("Lisää ulkoinen voima") self.lisaa_ulkoinen_voima.move( 0, 2 * self.button_height + 2 * self.button_separation) self.lisaa_ulkoinen_voima.resize(self.button_width, self.button_height) self.lisaa_ulkoinen_voima.font = QtGui.QFont() self.lisaa_ulkoinen_voima.font.setPointSize(8) self.lisaa_ulkoinen_voima.setFont(self.lisaa_ulkoinen_voima.font) self.lisaa_ulkoinen_voima.clicked.connect(self.nayta_ulkoinen_voima) self.lisaa_ulkoinen_voima.clicked.connect(self.nollaa_gradientti) self.lisaa_ulkoinen_voima.setEnabled(False) self.scene.addWidget(self.lisaa_ulkoinen_voima) def poista_ulkoinen_voima_nappi(self): '''Luo poista ulkoinen voima -napin''' self.poista_ulkoinen_voima = QPushButton("Poista ulkoinen voima") self.poista_ulkoinen_voima.setToolTip("Poista ulkoinen voima") self.poista_ulkoinen_voima.move( 0, 2 * self.button_height + 2 * self.button_separation) self.poista_ulkoinen_voima.resize(self.button_width, self.button_height) self.poista_ulkoinen_voima.setFont(self.lisaa_ulkoinen_voima.font) self.poista_ulkoinen_voima.clicked.connect(self.piilota_ulkoinen_voima) self.poista_ulkoinen_voima.clicked.connect(self.nollaa_gradientti) self.scene.addWidget(self.poista_ulkoinen_voima) self.poista_ulkoinen_voima.hide() def piilota_ulkoinen_voima(self): '''Piilotaa kaiken ulkoiseen voimaan liittyvän''' self.sp_voima.hide() self.yksikko_voima.hide() self.ulkoinen_voima.hide() self.lisaa_ulkoinen_voima.show() self.lisaa_ulkoinen_voima.setEnabled(True) self.viiva.hide() self.nuoli_3.hide() self.viiva_5.hide() self.nuoli_6.hide() self.poista_ulkoinen_voima.hide() self.lisaa_ulkoinen_voima.show() self.tulos.hide() Ominaisuudet.ulkoinen_voima(self, 0) def nayta_ulkoinen_voima(self): '''Näytetään ulkoinen voima riippuen tuen tyypistä''' self.sp_voima.show() self.yksikko_voima.show() self.ulkoinen_voima.show() self.lisaa_ulkoinen_voima.hide() self.poista_ulkoinen_voima.show() if int(Ominaisuudet.palauta_tuen_tyyppi(self)) == 0: self.viiva.show() self.nuoli_3.show() if int(Ominaisuudet.palauta_tuen_tyyppi(self)) == 1: self.viiva_5.show() self.nuoli_6.show() Ominaisuudet.ulkoinen_voima(self, 1) def ulkoinen_voima_valikko(self): '''Luo voiman suuruus -tekstin''' self.ulkoinen_voima = QGraphicsSimpleTextItem("Voiman suuruus") self.ulkoinen_voima.setPos(600, 5) self.ulkoinen_voima.font = QtGui.QFont() self.ulkoinen_voima.font.setPointSize(12) self.ulkoinen_voima.setFont(self.ulkoinen_voima.font) self.lisaa_ulkoinen_voima.setEnabled(False) self.scene.addItem(self.ulkoinen_voima) self.ulkoinen_voima.hide() '''Luo voiman arvon QSpinBoxin''' self.sp_voima = QSpinBox() self.sp_voima.move(750, 5) self.sp_voima.setRange(0, 10000) self.sp_voima.setSingleStep(1) self.sp_voima.setMinimumHeight(30) self.sp_voima.setValue(int(Ominaisuudet.palauta_voima(self))) self.sp_voima.valueChanged.connect(self.paivita_voima) self.scene.addWidget(self.sp_voima) self.sp_voima.hide() '''Luo yksikönvalinta QComboBOxin''' self.yksikko_voima = QComboBox() self.yksikko_voima.addItem("kN", 0) self.yksikko_voima.addItem("N", 1) self.yksikko_voima.move(820, 5) self.yksikko_voima.setMinimumHeight(30) self.yksikko_voima.setCurrentIndex( int(Ominaisuudet.palauta_voiman_yksikko(self))) self.yksikko_voima.setEditable(True) self.yksikko_voima.lineEdit().setAlignment(QtCore.Qt.AlignCenter) self.scene.addWidget(self.yksikko_voima) self.yksikko_voima.currentIndexChanged.connect( self.paivita_yksikko_voima) self.yksikko_voima.hide() def ulkoinen_voima_nuoli_seinatuki(self): '''Luo nuolen osoittamaan ulkoisen voiman paikkaa''' voima_viiva = QtGui.QPen(QtCore.Qt.black, 2) voima_viiva.setStyle(QtCore.Qt.SolidLine) '''Nuolen kärkien koordinaatit seinätuelle''' nuoli_piste_1 = QtCore.QPointF(self.palkin_paatypiste - 7, 185) nuoli_piste_2 = QtCore.QPointF(self.palkin_paatypiste, 200) nuoli_piste_3 = QtCore.QPointF(self.palkin_paatypiste + 7, 185) viiva_x = self.palkin_paatypiste self.viiva = QGraphicsLineItem( QtCore.QLineF(viiva_x, 100, viiva_x, 200)) '''Luodaan nuoli QPolygonItem olio''' self.nuoli_3 = QGraphicsPolygonItem( QtGui.QPolygonF([nuoli_piste_1, nuoli_piste_2, nuoli_piste_3])) self.nuoli_brush = QtGui.QBrush(1) self.nuoli_pencil = QtGui.QPen(QtCore.Qt.black, 2) self.nuoli_pencil.setStyle(QtCore.Qt.SolidLine) '''Lisätään viiva sekä päiden nuolet sceneen''' self.scene.addItem(self.viiva) self.scene.addItem(self.nuoli_3) self.viiva.hide() self.nuoli_3.hide() '''Lisätään tieto, että voima on asetettu''' Ominaisuudet.ulkoinen_voima(self, 1) def ulkoinen_voima_nuoli_alatuki(self): '''Nuolen kärkien koordinaatit alhaalta tuetulle palkille''' nuoli_piste_1 = QtCore.QPointF(self.palkin_keskipiste - 7, 185) nuoli_piste_2 = QtCore.QPointF(self.palkin_keskipiste, 200) nuoli_piste_3 = QtCore.QPointF(self.palkin_keskipiste + 7, 185) viiva_x = self.palkin_keskipiste '''Luodaan nuoli QPolygonItem olio''' self.nuoli_6 = QGraphicsPolygonItem( QtGui.QPolygonF([nuoli_piste_1, nuoli_piste_2, nuoli_piste_3])) self.nuoli_brush = QtGui.QBrush(1) self.nuoli_pencil = QtGui.QPen(QtCore.Qt.black, 2) self.nuoli_pencil.setStyle(QtCore.Qt.SolidLine) self.viiva_5 = QGraphicsLineItem( QtCore.QLineF(viiva_x, 100, viiva_x, 200)) '''Lisätään viiva sekä päiden nuolet sceneen''' self.scene.addItem(self.viiva_5) self.scene.addItem(self.nuoli_6) self.viiva_5.hide() self.nuoli_6.hide() '''Lisätään tieto, että voima on asetettu''' Ominaisuudet.ulkoinen_voima(self, 1) def paivita_voima(self): '''Lukee voiman arvon ja kutsuu Ominaisuudet luoka metodia voima''' voima = self.sp_voima.value() Ominaisuudet.voima(self, voima) def paivita_yksikko_voima(self): '''Lukee ykiskön arvon ja kutsuu Ominaisuudet-luokan metodia yksikko_voima''' self.yksikko_voima_arvo = self.yksikko_voima.currentData() Ominaisuudet.yksikko_voima(self, self.yksikko_voima_arvo) def materiaali_valikko(self): ''' Luo Materiaali-otsikon''' self.materiaali = QGraphicsSimpleTextItem("Materiaali") self.materiaali.setPos( 0, 3 * self.button_height + 3 * self.button_separation) self.materiaali.font = QtGui.QFont() self.materiaali.font.setPointSize(12) self.materiaali.setFont(self.materiaali.font) self.scene.addItem(self.materiaali) '''Luo drop down valikon materiaalivalinnalle''' self.materiaali_valinta = QComboBox() self.materiaali_valinta.addItem("Teräs", 0) self.materiaali_valinta.addItem("Alumiini", 1) self.materiaali_valinta.addItem("Muovi", 2) self.materiaali_valinta.move( 0, 3 * self.button_height + 3 * self.button_separation + 25) self.materiaali_valinta.resize(self.button_width, self.button_height - 25) self.materiaali_valinta.setEditable(True) self.materiaali_valinta.lineEdit().setAlignment(QtCore.Qt.AlignCenter) self.materiaali_valinta.setCurrentIndex(0) self.scene.addWidget(self.materiaali_valinta) self.materiaali_valinta.setEnabled(False) self.materiaali_valinta.currentIndexChanged.connect( self.paivita_materiaali) def paivita_materiaali(self): '''Lukee materiaalin arvon ja kutsuu Ominaisuudet-luokan metodia materiaali''' materiaali = self.materiaali_valinta.currentData() Ominaisuudet.materiaali(self, materiaali) def simulaatio_nappi(self): '''Luo SIMULOI-napin''' self.simuloi = QPushButton('SIMULOI') self.simuloi.setToolTip('Simuloi valittu rakenne') self.simuloi.move(0, 4 * self.button_height + 4 * self.button_separation) self.simuloi.setStyleSheet("background-color:rgb(122, 201, 255)") self.simuloi.resize(self.button_width, self.button_height) self.simuloi.font = QtGui.QFont() self.simuloi.font.setPointSize(12) self.simuloi.setFont(self.simuloi.font) self.simuloi.setEnabled(False) self.simuloi.clicked.connect(self.simulaatio) self.scene.addWidget(self.simuloi) def simulaatio(self): '''Kutsuu laskentaa suorittavaa metodia ja tallentaa tuloksen. Tämän jälkeen kutsuu lopputuloksen esittävän tekstin päivittävää metodia sekä palkin visualisoivaa gradient-metodia''' Laskin.laskin(self) Ominaisuudet.palauta_tulos(self) self.paivita_tulos_teksti() self.tallennaAction.setEnabled(True) if Ominaisuudet.palauta_tuen_tyyppi(self) == 0: if Ominaisuudet.onko_ulkoinen_voima_asetettu(self) == 1: self.gradient_seina_tuki() if Ominaisuudet.onko_ulkoinen_voima_asetettu(self) == 0: self.gradient_seina_tuki_ei_voimaa() if Ominaisuudet.palauta_tuen_tyyppi(self) == 1: self.gradient_alatuki() def tulos_teksti(self): '''Lisää tekstin, joka kertoo maksimijänintyksen arvon''' teksti = "Maksimijännitys " + str(self.maks_jannitys) + " MPa" self.tulos = QGraphicsSimpleTextItem(teksti) self.tulos.setPos(550, 500) self.tulos.font = QtGui.QFont() self.tulos.font.setPointSize(12) self.tulos.setFont(self.tulos.font) self.scene.addItem(self.tulos) self.tulos.hide() def paivita_tulos_teksti(self): '''Päivittää maksimijännityksen arvoa kuvaavan tekstin''' maks_jannitys = Ominaisuudet.palauta_tulos(self) self.tulos.setText("Maksimijännitys " + str(maks_jannitys) + " MPa") self.tulos.show() def palkin_pituus_valikko(self): '''Luo palkin pituus tekstin sekä spinbox-valitsimen pituuden asettamista varten Päivittää palkin pituuden Ominaisuudet luokan avulla''' self.palkin_pituus = QGraphicsSimpleTextItem("Palkin pituus") self.palkin_pituus.setPos(300, 5) self.palkin_pituus.font = QtGui.QFont() self.palkin_pituus.font.setPointSize(12) self.palkin_pituus.setFont(self.palkin_pituus.font) self.scene.addItem(self.palkin_pituus) self.palkin_pituus.hide() self.sp = QSpinBox() self.scene.addWidget(self.sp) self.sp.hide() self.sp.move(450, 5) self.sp.setRange(0, 100) self.sp.setSingleStep(1) self.sp.setMinimumHeight(30) self.sp.setValue(int(Ominaisuudet.palauta_palkin_pituus(self))) self.paivita_pituus() self.sp.valueChanged.connect(self.paivita_pituus) def paivita_pituus(self): '''Lukee palkin pituuden ja aktivoi Ominaisuudet luokan meodin palkin pituus''' self.palkin_pituus_arvo = self.sp.value() Ominaisuudet.palkin_pituus(self, self.palkin_pituus_arvo) self.paivita_asteikon_arvot() def yksikko_pituus(self): '''Luo yksikönvalinta dropdown-menun ja arvon muuttuessa päivittää yksikön Ominaisuudet-luokassa''' self.yksikko = QComboBox() self.yksikko.addItem("m", 0) self.yksikko.addItem("cm", 1) self.yksikko.addItem("mm", 2) self.yksikko.move(500, 5) self.yksikko.setMinimumHeight(30) self.yksikko.setEditable(True) self.yksikko.lineEdit().setAlignment(QtCore.Qt.AlignCenter) self.yksikko.setCurrentIndex( Ominaisuudet.palauta_pituuden_yksikko(self)) self.scene.addWidget(self.yksikko) self.yksikko.hide() self.yksikko_arvo = self.yksikko.currentData() self.yksikko.currentIndexChanged.connect(self.paivita_yksikko) def paivita_yksikko(self): '''Lukee yksikön arvon ja kutsuu Ominaisuudet-luokan metodia yksikko''' self.yksikko_arvo = self.yksikko.currentData() Ominaisuudet.yksikko(self, self.yksikko_arvo) self.paivita_asteikon_arvot() def asteikko(self): ''''Luodaan viivaa kuvaava olio''' viiva = QtGui.QPen(QtCore.Qt.black, 2) viiva.setStyle(QtCore.Qt.SolidLine) '''Oikean puoleisen nuolen kärkien koordinaatit''' nuoli_1_piste_1 = QtCore.QPointF(990, 390) nuoli_1_piste_2 = QtCore.QPointF(1000, 400) nuoli_1_piste_3 = QtCore.QPointF(990, 410) '''Vasemman puoleisen nuolen kärkien koordinaatit''' nuoli_2_piste_1 = QtCore.QPointF(310, 390) nuoli_2_piste_2 = QtCore.QPointF(300, 400) nuoli_2_piste_3 = QtCore.QPointF(310, 410) '''Luodaan nuoli QPolygonF oliot''' self.nuoli_1 = QGraphicsPolygonItem( QtGui.QPolygonF( [nuoli_1_piste_1, nuoli_1_piste_2, nuoli_1_piste_3])) self.nuoli_2 = QGraphicsPolygonItem( QtGui.QPolygonF( [nuoli_2_piste_1, nuoli_2_piste_2, nuoli_2_piste_3])) self.nuoli_brush = QtGui.QBrush(1) self.nuoli_pencil = QtGui.QPen(QtCore.Qt.black, 2) self.nuoli_pencil.setStyle(QtCore.Qt.SolidLine) self.line = QGraphicsLineItem(QtCore.QLineF(300, 400, 1000, 400)) '''Lisätään viiva sekä päiden nuolet sceneen''' self.scene.addItem(self.line) self.scene.addItem(self.nuoli_1) self.scene.addItem(self.nuoli_2) self.line.hide() self.nuoli_1.hide() self.nuoli_2.hide() def lisaa_asteikko_arvo(self): '''Lisää tekstikentän pituuden arvolle sekä yksikölle''' teksti = (str(Ominaisuudet.palauta_palkin_pituus(self)) + " " + "m") self.asteikko_teksti = QGraphicsSimpleTextItem() self.asteikko_teksti.setText(teksti) self.asteikko_teksti.setPos(650, 425) self.asteikko_teksti.font = QtGui.QFont() self.asteikko_teksti.font.setPointSize(12) self.asteikko_teksti.setFont(self.asteikko_teksti.font) self.scene.addItem(self.asteikko_teksti) self.asteikko_teksti.hide() def paivita_asteikon_arvot(self): '''Päivittää palkin pituutta kuvaavan asteikon''' yksikko = Ominaisuudet.palauta_pituuden_yksikko(self) if yksikko == 0: self.yksikko_merkki = "m" if yksikko == 1: self.yksikko_merkki = "cm" if yksikko == 2: self.yksikko_merkki = "mm" pituus = float(Ominaisuudet.palauta_palkin_pituus(self)) teksti = str(str(pituus) + " " + self.yksikko_merkki) self.asteikko_teksti.setText(teksti) self.asteikko_teksti.show() def gradient_seina_tuki(self): '''Luo seinästä tuetun palkin rasitusta kuvaavan gradientin''' gradient = QLinearGradient(300, 200, 300 + self.palkin_leveys, 200) gradient.setColorAt(0, QColor(244, 72, 66)) gradient.setColorAt(1, QColor(65, 244, 83)) self.rect.setBrush(gradient) def gradient_seina_tuki_ei_voimaa(self): '''Luo ilman ulkoista voimaa olevan gradientin''' gradient = QLinearGradient(300, 200, 300 + (self.palkin_leveys / 2), 200) gradient.setColorAt(0, QColor(244, 72, 66)) gradient.setColorAt(1, QColor(65, 244, 83)) self.rect.setBrush(gradient) def gradient_alatuki(self): '''Luo kahdella alatuella olevan palkin rasitusta kuvaavan gradientin''' gradient = QLinearGradient(300, 200, 300 + self.palkin_leveys, 200) gradient.setColorAt(0, QColor(65, 244, 83)) gradient.setColorAt(0.5, QColor(244, 72, 66)) gradient.setColorAt(1, QColor(65, 244, 83)) self.rect.setBrush(gradient) def nollaa_gradientti(self): '''Asettaa palkin "normaaliksi"''' self.rect.setBrush(QBrush(4)) def uusi_rakenne(self): '''Muokkaa ikkunaa uuden simulaation luomista varten''' self.rect.hide() self.ulkoinen_voima.hide() self.sp_voima.hide() self.yksikko_voima.hide() self.nuoli_1.hide() self.nuoli_2.hide() self.nuoli_3.hide() self.nuoli_4.hide() self.nuoli_5.hide() self.nuoli_6.hide() self.viiva_1.hide() self.viiva_2.hide() self.viiva_3.hide() self.viiva_4.hide() self.viiva_5.hide() self.viiva.hide() self.palkin_pituus.hide() self.sp.hide() self.yksikko.hide() self.line.hide() self.asteikko_teksti.hide() self.tulos.hide() self.nollaa_gradientti() self.lisaa_tuki.show() self.vaihda_tuki.hide() self.poista_ulkoinen_voima.hide() self.lisaa_ulkoinen_voima.show() Ominaisuudet.alkuarvot(self) '''Asettaa napit''' self.uusi_palkki.setEnabled(True) self.lisaa_ulkoinen_voima.setEnabled(False) self.lisaa_tuki.setEnabled(False) self.simuloi.setEnabled(False) self.tallennaAction.setEnabled(False) '''Päivittää tuen tyypiksi arvon, joka vastaa, ettei tukea ole''' self.tuen_tyyppi = 2 def close_application(self): '''sulkee ohjelman''' sys.exit()
class UFDebugToolUI(object): def __init__(self, window=None): self.window = window if window is not None else QWidget super(UFDebugToolUI, self).__init__() self.lang = 'en' self.set_ui() def set_ui(self): self._set_window() self._set_menubar() self._set_tab() def _set_window(self): self.window.setWindowTitle(self.window.tr('UF-Debug-Tool')) self.window.setMinimumHeight(800) self.window.setMinimumWidth(1080) self.main_layout = QVBoxLayout(self.window) def _set_menubar(self): self.menuBar = QMenuBar() self.main_layout.setMenuBar(self.menuBar) fileMenu = self.menuBar.addMenu('File') self.newFileAction = QAction(self.window.tr('New'), self.window) self.newFileAction.setShortcut('Ctrl+N') self.newFileAction.setStatusTip('New File') fileMenu.addAction(self.newFileAction) self.openFileAction = QAction(self.window.tr('Open'), self.window) self.openFileAction.setShortcut('Ctrl+O') self.openFileAction.setToolTip('Open File') fileMenu.addAction(self.openFileAction) self.saveFileAction = QAction(self.window.tr('Save'), self.window) self.saveFileAction.setShortcut('Ctrl+S') self.saveFileAction.setStatusTip('Save File') fileMenu.addAction(self.saveFileAction) self.closeFileAction = QAction(self.window.tr('Close'), self.window) self.closeFileAction.setShortcut('Ctrl+W') self.closeFileAction.setStatusTip('Close File') fileMenu.addAction(self.closeFileAction) self.newFileAction.triggered.connect(self.new_dialog) self.openFileAction.triggered.connect(self.open_dialog) self.saveFileAction.triggered.connect(self.save_dialog) self.closeFileAction.triggered.connect(self.close_dialog) debugMenu = self.menuBar.addMenu('Debug') self.logAction = QAction(self.window.tr('Log'), self.window) self.logAction.setShortcut('Ctrl+D') self.logAction.setStatusTip('Open-Log') self.logAction.triggered.connect(self.control_log_window) debugMenu.addAction(self.logAction) def control_log_window(self): if self.window.log_window.isHidden(): self.window.log_window.show() self.logAction.setText('Close-Log') else: self.window.log_window.hide() self.logAction.setText('Open-Log') def switch_tab(self, index): pass # if index == 2: # self.menuBar.setHidden(False) # else: # self.menuBar.setHidden(True) def _set_tab(self): self.tab_widget = QTabWidget() # self.tab_widget.currentChanged.connect(self.switch_tab) # tab_widget.setMaximumHeight(self.window.geometry().height() // 2) self.main_layout.addWidget(self.tab_widget) toolbox1 = QToolBox() toolbox2 = QToolBox() toolbox3 = QToolBox() toolbox4 = QToolBox() toolbox5 = QToolBox() groupbox1 = QGroupBox() groupbox2 = QGroupBox() groupbox3 = QGroupBox() groupbox4 = QGroupBox() groupbox5 = QGroupBox() toolbox1.addItem(groupbox1, "") toolbox2.addItem(groupbox2, "") toolbox3.addItem(groupbox3, "") toolbox4.addItem(groupbox4, "") toolbox5.addItem(groupbox5, "") self.tab_widget.addTab(toolbox1, "uArm") self.tab_widget.addTab(toolbox2, "xArm") self.tab_widget.addTab(toolbox3, "OpenMV") self.tab_widget.addTab(toolbox4, "Gcode") self.tab_widget.addTab(toolbox5, "WebView") uarm_layout = QVBoxLayout(groupbox1) xarm_layout = QVBoxLayout(groupbox2) openmv_layout = QHBoxLayout(groupbox3) gcode_layout = QVBoxLayout(groupbox4) webview_layout = QVBoxLayout(groupbox5) self.uarm_ui = UArmUI(self, uarm_layout) self.xarm_ui = XArmUI(self, xarm_layout) self.openmv_ui = OpenMV_UI(self, openmv_layout) self.gcode_ui = GcodeUI(self, gcode_layout) self.webview_ui = WebViewUI(self, webview_layout) self.tab_widget.setCurrentIndex(0) def new_dialog(self): self.openmv_ui.textEdit.setText('') self.openmv_ui.textEdit.filename = None self.openmv_ui.label_title.setText('untitled') self.tab_widget.setCurrentIndex(2) self.openmv_ui.textEdit.setDisabled(False) def open_dialog(self): fname = QFileDialog.getOpenFileName(self.window, 'Open file', '') if fname and fname[0]: with open(fname[0], "r") as f: self.openmv_ui.textEdit.setText(f.read()) self.openmv_ui.label_title.setText(fname[0]) self.openmv_ui.textEdit.filename = fname[0] self.tab_widget.setCurrentIndex(2) self.openmv_ui.textEdit.setDisabled(False) def save_dialog(self): widget = self.window.focusWidget() if widget: if not self.openmv_ui.textEdit.filename: fname = QFileDialog.getSaveFileName(self.window, 'Save File', '') if fname and fname[0]: self.openmv_ui.textEdit.filename = fname[0] if self.openmv_ui.textEdit.filename: data = widget.toPlainText() with open(self.openmv_ui.textEdit.filename, "w") as f: f.write(data) def close_dialog(self): self.openmv_ui.textEdit.clear() self.openmv_ui.textEdit.filename = None self.openmv_ui.label_title.setText('') self.openmv_ui.textEdit.setDisabled(True)
class MainWindow(QMainWindow): opts = read_config() profiles = read_profiles() urls = [] def __init__(self, debug=False): super().__init__() self.debug = debug self.icon_paths() self.init_UI() def icon_paths(self): self.defaultIconTheme = QIcon.themeName() iconPaths = QIcon.themeSearchPaths() iconPaths.append(icon_path()) QIcon.setThemeSearchPaths(iconPaths) QIcon.setFallbackSearchPaths([icon_path("default")]) QIcon.setFallbackThemeName("default") #QIcon.setThemeName( "default" ) def init_UI(self): ## Set the theme self.set_stylesheet(self.opts["theme"]) self.profiles = read_profiles() self.mainWidget = MainWidget(self) self.statusBar() self.build_menu_bar() self.setCentralWidget(self.mainWidget) self.resize(WINDOW_WIDTH, WINDOW_HEIGHT) self.center_window() self.setWindowTitle("qYoutube-DL") self.show() def center_window(self): f = self.frameGeometry() center = QDesktopWidget().availableGeometry().center() f.moveCenter(center) self.move(f.topLeft()) def build_menu_bar(self): get_icon = Icons().get_icon ## Is this a system install? sysInstall = (os.path.expanduser('~') in sys.argv[0]) ######## Actions ## Save saveAction = QAction( QIcon(get_icon("document-save-symbolic", sysInstall)), "&Save Settings", self) saveAction.setShortcut("Ctrl+S") saveAction.setStatusTip("Save current settings") saveAction.triggered.connect(self.save_settings) ## Import playlist importAction = QAction( QIcon(get_icon("document-open-symbolic", sysInstall)), "&Import URLs", self) importAction.setShortcut("Ctrl+I") importAction.setStatusTip("Import a saved list of URLs") importAction.triggered.connect(self.import_urls) ## Export playlist exportAction = QAction( QIcon(get_icon("document-save-symbolic", sysInstall)), "&Export URLs", self) exportAction.setShortcut("Ctrl+E") exportAction.setStatusTip("Export URLs to a text file") exportAction.triggered.connect(self.export_urls) ## Exit exitAction = QAction( QIcon(get_icon("application-exit-symbolic", sysInstall)), "&Exit", self) exitAction.setShortcut("Ctrl+Q") exitAction.setStatusTip("Exit the application") exitAction.triggered.connect(qApp.quit) ## Go goAction = QAction(QIcon(get_icon("go-next-symbolic", sysInstall)), "Download URLs", self) goAction.setShortcut("Return") goAction.setStatusTip("Download current URL list") goAction.triggered.connect(self.mainWidget.start_download) ## Paste pasteAction = QAction( QIcon(get_icon("edit-paste-symbolic", sysInstall)), "&Paste", self) pasteAction.setShortcut("Ctrl+V") pasteAction.setStatusTip("Add URL from clipboard") pasteAction.triggered.connect(self.mainWidget.quick_add_item) ## Set destination setDestAction = QAction( QIcon(get_icon("document-open-symbolic", sysInstall)), "Set &Download directory", self) setDestAction.setShortcut("Ctrl+D") setDestAction.setStatusTip("Choose your download directory") setDestAction.triggered.connect(self.mainWidget.set_destination) ## Allow duplicates self.dupeAction = QAction("Allow duplicates", self) self.dupeAction.setStatusTip("Allow duplicate URLs in queue") self.dupeAction.setCheckable(True) if self.opts["duplicates"] == "true": self.dupeAction.setChecked(True) self.dupeAction.triggered.connect(self.check_dupe_box) ## New folder for playlists self.playlistFolderAction = QAction("New folder for playlists", self) self.playlistFolderAction.setStatusTip( "Create a new folder for every playlist downloaded") self.playlistFolderAction.setCheckable(True) if self.opts["playlistFolder"] == "true": self.playlistFolderAction.setChecked(True) self.playlistFolderAction.triggered.connect( self.check_playlist_dir_box) ## About action aboutAction = QAction( QIcon(get_icon("help-about-symbolic", sysInstall)), "&About", self) aboutAction.setStatusTip("Information about the program") aboutAction.triggered.connect(self.about) ## ====== Theme actions ## System default theme defaultThemeAction = QAction("Default", self) defaultThemeAction.setStatusTip("Set theme to system default") defaultThemeAction.triggered.connect(self.toggle_theme_default) ## Light theme lightThemeAction = QAction("Light theme", self) lightThemeAction.setStatusTip("Use a light theme") lightThemeAction.triggered.connect(self.toggle_theme_light) ## Dark theme darkThemeAction = QAction("Dark theme", self) darkThemeAction.setStatusTip("Use a dark theme") darkThemeAction.triggered.connect(self.toggle_theme_dark) ## Create the menubar menuBar = self.menuBar() ## Create file menu fileMenu = menuBar.addMenu("&File") fileMenu.addAction(saveAction) fileMenu.addAction(exportAction) fileMenu.addSeparator() fileMenu.addAction(importAction) fileMenu.addSeparator() fileMenu.addAction(goAction) fileMenu.addSeparator() fileMenu.addAction(exitAction) ## Edit Menu editMenu = menuBar.addMenu("&Edit") editMenu.addAction(pasteAction) ## Settins Menu settingsMenu = menuBar.addMenu("&Settings") themesMenu = settingsMenu.addMenu("Theme") settingsMenu.addSeparator() settingsMenu.addAction(setDestAction) settingsMenu.addSeparator() settingsMenu.addAction(self.dupeAction) settingsMenu.addAction(self.playlistFolderAction) ## Themes submenu themesMenu.addAction(defaultThemeAction) themesMenu.addAction(lightThemeAction) themesMenu.addAction(darkThemeAction) ## Help menu helpMenu = menuBar.addMenu("&Help") helpMenu.addAction(aboutAction) def import_urls(self): dDir = self.mainWidget.destEdit.text() filename, blank = QFileDialog.getOpenFileName(self, "Import URLs", dDir) if filename != "": try: fin = open(filename, "r") rawUrls = fin.readlines() fin.close() urls = [] for r in rawUrls: urls.append(r.strip()) self.load_urls(urls) self.statusBar().showMessage("URLs imported", 2000) except (OSError, PermissionError, FileNotFoundError): print("ERROR: Cannot read from '%s'! Unable to load URLs" % filename) def export_urls(self): dDir = self.mainWidget.destEdit.text() filename, blank = QFileDialog.getSaveFileName(self, "Export URLs", dDir) if filename != "": try: urls = self.mainWidget.get_urls() fout = open(filename, "w") fout.writelines(urls) fout.close() self.statusBar().showMessage("URLs exported", 2000) except (OSError, PermissionError, FileNotFoundError): print("ERROR: Cannot write to '%s'! Unable to export URLs" % filename) def load_urls(self, urls): self.mainWidget.load_urls(urls) def write_config(self): self.opts["downloadPath"] = self.mainWidget.destEdit.text() self.opts["duplicates"] = str(self.dupeAction.isChecked()).lower() boolStr = str(self.playlistFolderAction.isChecked()).lower() self.opts["playlistFolder"] = boolStr write_config(self.opts) def save_settings(self): self.write_config() self.statusBar().showMessage("Settings saved", 2000) def check_dupe_box(self): self.opts["duplicates"] = str(self.dupeAction.isChecked()).lower() self.save_settings() def check_playlist_dir_box(self): boolStr = str(self.playlistFolderAction.isChecked()).lower() self.opts["playlistFolder"] = boolStr self.save_settings() def about(self): aboutStr = """ qYoutube-DL is a basic PyQt5 frontend to Youtube-DL. Version: %s License: GPLv3 - https://www.gnu.org/licenses/gpl-3.0.txt Author: James Hendrie - [email protected] Git: https://github.com/jahendrie/qytdl """ % qytdl_version() msg = QMessageBox.about(self, "About qYoutube-DL", aboutStr) def toggle_theme_default(self): self.set_stylesheet() self.opts["theme"] = "default" self.write_config() def toggle_theme_light(self): self.set_stylesheet("light") self.opts["theme"] = "light" self.write_config() def toggle_theme_dark(self): self.set_stylesheet("dark") self.opts["theme"] = "dark" self.write_config() def set_stylesheet(self, ssStr=""): if ssStr == "dark" or ssStr == "light": ssFile = open(stylesheets_path("%s.qss" % ssStr), "r") self.setStyleSheet(ssFile.read()) ssFile.close() QIcon.setThemeName(ssStr) else: self.setStyleSheet("") QIcon.setThemeName(self.defaultIconTheme)
def build_menu_bar(self): get_icon = Icons().get_icon ######## Actions ## Save saveAction = QAction(QIcon(get_icon("document-save-as")), "&Save", self) saveAction.setShortcut("Ctrl+S") saveAction.setStatusTip("Save file") saveAction.triggered.connect(self.save_file) ## Save As saveAsAction = QAction(QIcon(get_icon("document-save")), "&Save As", self) saveAsAction.setStatusTip("Save file as...") saveAsAction.triggered.connect(self.save_file_as) ## Open openAction = QAction(QIcon(get_icon("document-open")), "&Open", self) openAction.setShortcut("Ctrl+O") openAction.setStatusTip("Open file") openAction.triggered.connect(self.open_file) ## Import template importAction = QAction(QIcon(get_icon("document-open")), "&Import template", self) importAction.setStatusTip("Import a template file") importAction.triggered.connect(self.import_template) ## Export exportAction = QAction(QIcon(get_icon("document-save")), "&Export PDF", self) exportAction.setShortcut("Ctrl+E") exportAction.setStatusTip("Export each character's profile as a PDF") exportAction.triggered.connect(self.export_file) if not canExportPDF: exportAction.setDisabled(True) ## Exit exitAction = QAction(QIcon(get_icon("application-exit")), "&Exit", self) exitAction.setShortcut("Ctrl+Q") exitAction.setStatusTip("Exit the application") exitAction.triggered.connect(qApp.quit) ## About action aboutAction = QAction(QIcon(get_icon("help-about")), "&About", self) aboutAction.setStatusTip("Information about the program") aboutAction.triggered.connect(self.about) ## Create the menubar menuBar = self.menuBar() ## Create file menu fileMenu = menuBar.addMenu("&File") fileMenu.addAction(openAction) ## Recents menu self.recentsMenu = fileMenu.addMenu("Recent") fileMenu.addSeparator() fileMenu.addAction(saveAction) fileMenu.addAction(saveAsAction) fileMenu.addSeparator() fileMenu.addAction(exportAction) fileMenu.addSeparator() fileMenu.addAction(exitAction) ## Create edit menu editMenu = menuBar.addMenu("&Edit") editMenu.addAction(importAction) helpMenu = menuBar.addMenu("&Help") helpMenu.addAction(aboutAction) self.load_recents_menu()
def __init__(self, astergui, parent=None): """ Create panel. Arguments: astergui (AsterGui): AsterGui instance. parent (Optional[QWidget]): Parent widget. """ super(ParameterPanel, self).__init__(parent=parent, name=translate("ParameterPanel", "Edit command"), astergui=astergui) self.setPixmap(load_pixmap("as_pic_edit_command.png")) self._files_model = astergui.study().dataFilesModel() self._unit_model = None self._command = None self.title = ParameterTitle(self) self.title.installEventFilter(self) self._name = QLineEdit(self) self.views = QStackedWidget(self) v_layout = QVBoxLayout(self) v_layout.setContentsMargins(0, 0, 0, 0) v_layout.setSpacing(5) v_layout.addWidget(self.title) v_layout.addWidget(HLine(self)) n_layout = QHBoxLayout() v_layout.addLayout(n_layout) n_layout.addWidget(QLabel(translate("ParameterPanel", "Name"), self)) n_layout.addWidget(self._name) # force to be a valid identifier + length <= 8 self._name.setValidator(QRegExpValidator(QRegExp(r"[a-zA-Z]\w{1,7}"))) # create toolbar tbar = QToolBar(self) tbar.setToolButtonStyle(Qt.ToolButtonIconOnly) # - Edit comment edit_comment = QAction(translate("AsterStudy", "Edit &Comment"), self) edit_comment.setToolTip(translate("AsterStudy", "Edit comment")) edit_comment.setStatusTip( translate("AsterStudy", "Edit comment for the " "selected object")) edit_comment.setIcon(load_icon("as_pic_edit_comment.png")) connect(edit_comment.triggered, self._editComment) tbar.addAction(edit_comment) # - Switch on/off business-translations title = translate("AsterStudy", "Use Business-Oriented Translations") self.use_translations = QAction(title, self) title = translate("AsterStudy", "Use business-oriented translations") self.use_translations.setToolTip(title) self.use_translations.setStatusTip(title) self.use_translations.setIcon(load_icon("as_pic_use_translations.png")) self.use_translations.setCheckable(True) if behavior().forced_native_names: force = behavior().force_native_names self.use_translations.setDisabled(True) is_on = not force else: is_on = behavior().use_business_translations Options.use_translations = is_on self.use_translations.setChecked(is_on) connect(self.use_translations.toggled, self.updateTranslations) tbar.addAction(self.use_translations) # - Hide unused hide_unused = astergui.action(ActionType.HideUnused) connect(hide_unused.toggled, self._unusedVisibility) tbar.addAction(hide_unused) # - What's this whats_this = QWhatsThis.createAction(tbar) whats_this.setToolTip(translate("AsterStudy", "What's this?")) whats_this.setStatusTip( translate("AsterStudy", "Show element's description")) whats_this.setIcon(load_icon("as_pic_whats_this.png")) tbar.addAction(whats_this) # - Link to doc tbar.addAction(astergui.action(ActionType.LinkToDoc)) n_layout.addWidget(tbar) v_layout.addWidget(self.views) self._updateState()
class ParameterPanel(EditionWidget, WidgetController): """Edition Panel implementation.""" def __init__(self, astergui, parent=None): """ Create panel. Arguments: astergui (AsterGui): AsterGui instance. parent (Optional[QWidget]): Parent widget. """ super(ParameterPanel, self).__init__(parent=parent, name=translate("ParameterPanel", "Edit command"), astergui=astergui) self.setPixmap(load_pixmap("as_pic_edit_command.png")) self._files_model = astergui.study().dataFilesModel() self._unit_model = None self._command = None self.title = ParameterTitle(self) self.title.installEventFilter(self) self._name = QLineEdit(self) self.views = QStackedWidget(self) v_layout = QVBoxLayout(self) v_layout.setContentsMargins(0, 0, 0, 0) v_layout.setSpacing(5) v_layout.addWidget(self.title) v_layout.addWidget(HLine(self)) n_layout = QHBoxLayout() v_layout.addLayout(n_layout) n_layout.addWidget(QLabel(translate("ParameterPanel", "Name"), self)) n_layout.addWidget(self._name) # force to be a valid identifier + length <= 8 self._name.setValidator(QRegExpValidator(QRegExp(r"[a-zA-Z]\w{1,7}"))) # create toolbar tbar = QToolBar(self) tbar.setToolButtonStyle(Qt.ToolButtonIconOnly) # - Edit comment edit_comment = QAction(translate("AsterStudy", "Edit &Comment"), self) edit_comment.setToolTip(translate("AsterStudy", "Edit comment")) edit_comment.setStatusTip( translate("AsterStudy", "Edit comment for the " "selected object")) edit_comment.setIcon(load_icon("as_pic_edit_comment.png")) connect(edit_comment.triggered, self._editComment) tbar.addAction(edit_comment) # - Switch on/off business-translations title = translate("AsterStudy", "Use Business-Oriented Translations") self.use_translations = QAction(title, self) title = translate("AsterStudy", "Use business-oriented translations") self.use_translations.setToolTip(title) self.use_translations.setStatusTip(title) self.use_translations.setIcon(load_icon("as_pic_use_translations.png")) self.use_translations.setCheckable(True) if behavior().forced_native_names: force = behavior().force_native_names self.use_translations.setDisabled(True) is_on = not force else: is_on = behavior().use_business_translations Options.use_translations = is_on self.use_translations.setChecked(is_on) connect(self.use_translations.toggled, self.updateTranslations) tbar.addAction(self.use_translations) # - Hide unused hide_unused = astergui.action(ActionType.HideUnused) connect(hide_unused.toggled, self._unusedVisibility) tbar.addAction(hide_unused) # - What's this whats_this = QWhatsThis.createAction(tbar) whats_this.setToolTip(translate("AsterStudy", "What's this?")) whats_this.setStatusTip( translate("AsterStudy", "Show element's description")) whats_this.setIcon(load_icon("as_pic_whats_this.png")) tbar.addAction(whats_this) # - Link to doc tbar.addAction(astergui.action(ActionType.LinkToDoc)) n_layout.addWidget(tbar) v_layout.addWidget(self.views) self._updateState() def unitModel(self): """ Method that get unit model. Returns: UnitModel: Unit model. """ return self._unit_model def command(self): """ Get command being edited. Returns: Command: Command being edited. """ return self._command def setCommand(self, command): """ Set command to edit. Arguments: command (Command): Command to edit. """ self.clear() self._command = command if self._command is None: self._name.setText("") else: self._name.setText(self._command.name) self._unit_model = UnitModel(command.stage) pview = self._createParameterView(ParameterPath(self._command), '') pview.view().setItemValue(command.storage) hide_unused = self.astergui().action(ActionType.HideUnused) pview.setUnusedVisibile(not hide_unused.isChecked()) self.views.setCurrentWidget(pview) self._updateState() def currentPath(self): """ Get currently edited parameter path. Returns: str: currently edited parameter path. """ path = "" wid = self.currentParameterView() if wid is not None: path = wid.path() return path def isCurrentCommand(self): """ Get true if the currently edited view contains command. Returns: bool: Current edited command flag """ curpath = self.currentPath() return ParameterPath(self.command()).isEqual(curpath) def currentParameterView(self): """ Get current parameter view. Returns: ParameterView: current view. """ return self.views.currentWidget() def clear(self): """Remove all parameter views.""" while self.views.count() > 0: wid = self.views.widget(0) if wid is not None: self.views.removeWidget(wid) wid.deleteLater() def store(self): """ Save data from all parameter views. """ cmd = self.command() if cmd is not None: with auto_dupl_on(self.astergui().study().activeCase): cmd.rename(self._name.text()) wid = self._viewByPath(ParameterPath(cmd)) if wid is not None: cmd.init(wid.view().itemValue()) def requiredButtons(self): """ Return the combination of standard button flags required for this widget. Returns: int: button flags for buttons required for this widget (combination of QDialogButtonBox.StandardButton flags). """ if self.isCurrentCommand(): return QDialogButtonBox.Ok | QDialogButtonBox.Apply | \ QDialogButtonBox.Close else: return QDialogButtonBox.Ok | QDialogButtonBox.Cancel | \ QDialogButtonBox.Abort def isButtonEnabled(self, button): """ Return True if a particular button is enabled. Arguments: button (QDialogButtonBox.StandardButton): button flag. Returns: True: that means that all buttons should be enabled. """ return True def perform(self, button): """ Perform action on button click. Redefined method from the base class. Arguments: button (QDialogButtonBox.StandardButton): clicked button flag. """ if button == QDialogButtonBox.Ok: self.performOk() elif button == QDialogButtonBox.Apply: self.performApply() elif button == QDialogButtonBox.Abort: self.performAbort() elif button == QDialogButtonBox.Close or \ button == QDialogButtonBox.Cancel: self.performClose() def performOk(self): """Called when `Ok` button is clicked in Edition panel.""" self.performChanges(True) def performApply(self): """Called when `Apply` button is clicked in Edition panel.""" self.performChanges(False) def performAbort(self): """Called when `Abort` button is clicked in Edition panel.""" pref_mgr = self.astergui().preferencesMgr() msg = translate( "ParameterPanel", "Command edition will be aborted and " "all made changes will be lost. " "Do you want to continue?") noshow = "parampanel_abort" ask = MessageBox.question(self.astergui().mainWindow(), translate("ParameterPanel", "Abort"), msg, QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes, noshow=noshow, prefmgr=pref_mgr) if ask == QMessageBox.Yes: self.close() self.astergui().study().revert() def performClose(self): """Called when `Cancel` button is clicked in Edition panel.""" has_modif = self._hasModifications() if has_modif: pref_mgr = self.astergui().preferencesMgr() msg = translate( "ParameterPanel", "There are some unsaved modifications will be " "lost. Do you want to continue?") noshow = "parampanel_close" ask = MessageBox.question(self.astergui().mainWindow(), translate("ParameterPanel", "Close"), msg, QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes, noshow=noshow, prefmgr=pref_mgr) has_modif = ask != QMessageBox.Yes if not has_modif: self.performDissmis(True) def performChanges(self, close=True): """ Validate and store the command into data model. """ wid = self.currentParameterView() if wid is not None: view = wid.view() if view.validate(): cur_path = self.currentPath() if self.isCurrentCommand(): self.store() self._files_model.update() if self.astergui() is not None: opname = translate("ParameterPanel", "Edit command") self.astergui().study().commit(opname) self.astergui().update() if close: self.performDissmis(False) msg = translate("ParameterPanel", "Command '{}' successfully stored") msg = msg.format(self._name.text()) self.astergui().showMessage(msg) else: child_val = view.itemValue() self._removeCurrentView() curview = self.currentParameterView() subitem = curview.view().findItemByPath(cur_path) if subitem is not None: subitem.setItemValue(child_val) self._updateState() self.updateButtonStatus() def performDissmis(self, revert=True): """ Cancel changes and revert the command changes. """ if self.isCurrentCommand(): self.close() if revert: self.astergui().study().revert() else: self._removeCurrentView() self._updateState() self.updateButtonStatus() def showEvent(self, event): """ Reimplemented for internal reason: updates the title depending on read only state, etc. """ title = translate("ParameterPanel", "View command") \ if self.isReadOnly() else \ translate("ParameterPanel", "Edit command") self.setWindowTitle(title) hide_unused = self.astergui().action(ActionType.HideUnused) hide_unused.setVisible(True) hide_unused.setChecked(self.isReadOnly()) # update meshview meshes = avail_meshes_in_cmd(self.command()) for i, mesh in enumerate(meshes): filename, meshname = get_cmd_mesh(mesh) if filename: if i > 0: self.meshview().displayMEDFileName(filename, meshname, 1.0, False) else: self.meshview().displayMEDFileName(filename, meshname, 1.0, True) super(ParameterPanel, self).showEvent(event) def hideEvent(self, event): """ Reimplemented for internal reason: hides "Hide unused" action. """ hide_unused = self.astergui().action(ActionType.HideUnused) hide_unused.setVisible(False) super(ParameterPanel, self).hideEvent(event) def updateTranslations(self): """ Update translations in GUI elements. """ Options.use_translations = self.use_translations.isChecked() self._updateState() for i in xrange(self.views.count()): view = self.views.widget(i) view.updateTranslations() def eventFilter(self, receiver, event): """ Event filter; processes clicking ln links in What's This window. """ if receiver == self.title and event.type() == QEvent.WhatsThisClicked: QDesktopServices.openUrl(QUrl(event.href())) return super(ParameterPanel, self).eventFilter(receiver, event) def _hasModifications(self): curview = self.currentParameterView().view() \ if self.currentParameterView() is not None else None return curview.hasModifications() \ if curview is not None else False def _updateState(self): """Update state and current title label.""" disabled = self.command() is None self.setDisabled(disabled) if not disabled: disabled = self.command().gettype(ConversionLevel.NoFail) is None self._name.setDisabled(disabled) txt = [] pview = self.currentParameterView() if pview is not None: txt = pview.path().names() ppath = None txt_list = [] tooltip = "" whats_this = "" while len(txt) > 0: name = txt.pop(0) if ppath is None: ppath = ParameterPath(self.command(), name=name) else: ppath = ppath.absolutePath(name) if ppath.isInSequence(): txt_list.append("[" + name + "]") elif get_cata_typeid(ppath.keyword()) in (IDS.simp, IDS.fact): # translate keyword kwtext = Options.translate_command(ppath.command().title, name) txt_list.append(kwtext) elif get_cata_typeid(ppath.keyword()) == IDS.command: # translate command translation = Options.translate_command(name) txt_list.append(translation) if translation != name: wttext = italic(translation) + " ({})".format(bold(name)) else: wttext = bold(name) tooltip = preformat(wttext) url = self.astergui().doc_url(name) if url: wttext += " " wttext += href( image(CFG.rcfile("as_pic_help.png"), width=20, height=20), url) wttext = preformat(wttext) docs = CATA.get_command_docstring(name) if docs: wttext += "<hr>" wttext += docs whats_this = wttext self.title.setTitle(txt_list) self.title.setToolTip(tooltip) self.title.setWhatsThis(whats_this) def _removeCurrentView(self): """ Remove the parameter view for given object. Arguments: obj (Parameter): Command's parameter. """ curview = self.currentParameterView() if curview is not None: master = curview.view().masterItem() if master is not None and master.slaveItem() == curview.view(): master.setSlaveItem(None) curview.view().setMasterItem(None) view = self._parentView(curview) if view is not None: self.views.setCurrentWidget(view) hide_unused = self.astergui().action(ActionType.HideUnused) view.setUnusedVisibile(not hide_unused.isChecked()) self.views.removeWidget(curview) curview.deleteLater() self._updateState() def _viewByPath(self, path): view = None for i in xrange(self.views.count()): the_view = self.views.widget(i) if the_view.path().isEqual(path): view = the_view break return view def _parentView(self, curview): view = None path = curview.path() while path is not None and view is None: path = path.parentPath() view = self._viewByPath(path) return view def _gotoParameter(self, path, link): """ Activate the parameter view for object with given id. Arguments: uid (int): Object's UID. """ curview = self.currentParameterView() act_item = curview.view().findItemByPath(path) child_val = None wid = self._createParameterView(path, link) if act_item is not None: child_val = act_item.itemValue() act_item.setSlaveItem(wid.view()) wid.view().setMasterItem(act_item) hide_unused = self.astergui().action(ActionType.HideUnused) wid.setUnusedVisibile(not hide_unused.isChecked()) self.views.setCurrentWidget(wid) wid.view().setItemValue(child_val) self._updateState() self.updateButtonStatus() def _createParameterView(self, path, link): """ Create parameter view for given object. Arguments: path (ParameterPath): Path of parameter to edit. Returns: ParameterWindow: Parameter view for parameter path. """ # pragma pylint: disable=redefined-variable-type pview = None if link == EditorLink.Table: pview = ParameterTableWindow(path, self, self.views) elif link == EditorLink.List: pview = ParameterListWindow(path, self, self.views) elif link == EditorLink.GrMa: pview = ParameterMeshGroupWindow(path, self, self.views) else: pview = ParameterFactWindow(path, self, self.views) connect(pview.gotoParameter, self._gotoParameter) self.views.addWidget(pview) return pview def _unusedVisibility(self, ison): """ Invoked when 'Hide unused' button toggled """ curview = self.currentParameterView() curview.setUnusedVisibile(not ison) def meshview(self): """ Returns the central *MeshView* object """ return self.astergui().workSpace().panels[Panel.View] def _editComment(self): """ Invoked when 'Edit comment' button is clicked """ panel = CommentPanel(self.astergui(), owner=self) panel.node = self.command() self.astergui().workSpace().panel(Panel.Edit).setEditor(panel) def pendingStorage(self): """ Dictionnary being filled as this command is edited. """ wid = self._viewByPath(ParameterPath(self.command())) if wid is not None: return wid.view().itemValue() return None
def initUI(self): # 添加打开菜单 selFileAction = QAction('&Open', self) # QAction(QIcon('open.png'), '&Open', self) selFileAction.setShortcut('Ctrl+O') selFileAction.setStatusTip('Open new File') selFileAction.triggered.connect(self.openFile) # open data file selFileAction.setIcon(QIcon(self.resource_path('import.png'))) exitAction = QAction('&Exit', self) #QtGui.QAction(QIcon('exit.png'), '&Exit', self) exitAction.setShortcut('Ctrl+Q') exitAction.setStatusTip('Exit the application') #exitAction.triggered.connect(QtGui.qApp.quit) exitAction.triggered.connect(self.exitAPP) # exit the application exitAction.setIcon(QIcon(self.resource_path('exit.png'))) clearAction = QAction('Clear', self) # QtGui.QAction(QIcon('Clear.png'), 'Clear', self) clearAction.triggered.connect(self.clearPlotArea) clearAction.setIcon(QIcon(self.resource_path('clear.png'))) addPlotAction = QAction( 'Add a Plot', self) #QtGui.QAction(QIcon('Addplot.png'), 'Add a Plot', self) addPlotAction.triggered.connect(self.addPlotAera) addPlotAction.setIcon(QIcon(self.resource_path('addplot.png'))) removePlotAction = QAction('Remove the Plot', self) # QtGui.QAction(QIcon('Addplot.png'), 'Remove a Plot', self) removePlotAction.triggered.connect(self.removeDataPlotWin) removePlotAction.setIcon(QIcon(self.resource_path('remvplot.png'))) viewAllAction = QAction("View All", self) viewAllAction.triggered.connect(self.autoRangeAllWins) viewAllAction.setIcon(QIcon(self.resource_path('viewall.png'))) menubar = self.menuBar() fileMenu = menubar.addMenu('&File') # add menu File fileMenu.addAction(selFileAction) # link menu bar to openfile action with a menu item fileMenu.addAction(exitAction) # add menu item exit plotMenu = menubar.addMenu("Plot") # add menu Plot plotMenu.addAction(clearAction) # add menu item of 'Clear' plot plotMenu.addAction(addPlotAction) # add menu item of 'Add a Plot' plotMenu.addAction(removePlotAction) # add menu item of 'Add a Plot' helpMenu = menubar.addMenu("Help") # add menu help helpAction = QAction('?', helpMenu) helpAction.triggered.connect(self.helpme) helpMenu.addAction(helpAction) toolBar = self.addToolBar("Open") toolBar.addAction(selFileAction) # link tool bar to openfile action toolBar.addAction(clearAction) toolBar.addAction(addPlotAction) toolBar.addAction(removePlotAction) toolBar.addAction(viewAllAction) # toolBar = self.addToolBar('Exit') # toolBar.addAction(selExitAction) # link menu bar to openfile action # 设置dataPlot class: PlotWidget self.dataPlot.plotItem.showGrid(True, True, 0.5) #self.dataPlot.plotItem.addLegend() self.dataPlot.setAutoVisible(y=True) # 设置treeWidget的相关 class: QTreeWidget self.treeWidget.setContextMenuPolicy(Qt.CustomContextMenu) self.treeWidget.customContextMenuRequested.connect(self.showContextMenu) self.treeWidget.treeContextMenu = QMenu(self) self.actionA = self.treeWidget.treeContextMenu.addAction(u'Plot') self.actionA.triggered.connect( lambda: self.plotData(self.currSelctPlotWgt, self.treeWidget.selectedItems())) self.treeWidget.setColumnCount(4) self.treeWidget.setHeaderLabels(['#', 'Parameter', 'Parameter Name', 'Unit']) self.treeWidget.setColumnWidth(0, 10) self.treeWidget.setColumnWidth(1, 50) self.treeWidget.setColumnWidth(2, 100) ### drag and drop self.treeWidget.setDragDropMode(self.treeWidget.DragOnly) # set up context menu of list widget self.listWidget.setContextMenuPolicy(Qt.CustomContextMenu) self.listWidget.customContextMenuRequested.connect(self.showListContextMenu) self.listWidget.listContextMenu = QMenu(self) self.actionB = self.listWidget.listContextMenu.addAction(u'Remove') self.actionB.triggered.connect( lambda: self.removeItemInPlot(self.listWidget.selectedItems())) #################### get the test data from the import window self.winImpData = clsImportData(self.dataparam, self.lTestDATA) # instance of the ImportData window # # x axis for time # xAxis = self.TimeAxisItem("bottom") xAxis = self.dataPlot.plotItem.axes['bottom']['item'] # plotitem and viewbox ## at least one plotitem is used whioch holds its own viewbox and left axis viewBox = self.dataPlot.plotItem.vb # reference to viewbox of the plotitem viewBox.scaleBy(y=None) # # link x axis to view box xAxis.linkToView(viewBox) self.dataPlot.plotItem.scene().sigMouseMoved.connect(self.mouseMove) #self.dataPlot.plotItem.scene().sigMouseClicked.connect(self.mouseClick) # self.dataPlot.HoverEnterEvent = self.hoverEnterEvent ## drag and drop # self.dataPlot.dragEnterEvent = self.dragEnterEvent # self.dataPlot.plotItem.setAcceptDrops(True) # self.dataPlot.plotItem.dropEvent = self.dropEvent vLine = InfiniteLine(angle=90, movable=False, name='vline') hLine = InfiniteLine(angle=0, movable=False, name='hline') self.dataPlot.addItem(vLine, ignoreBounds=True) self.dataPlot.addItem(hLine, ignoreBounds=True) # set the default plot range self.dataPlot.setXRange(self.minTimestamp,self.maxTimestamp,padding=20) self.dataPlot.setYRange(-10, 10, padding=20) self.dataPlot.plotItem.getViewBox().setLimits() self.dataPlot.plotItem.getAxis('left').setWidth(w=30) self.dataPlot.plotItem.hideButtons() #self.dataPlot.plotItem.scene().sigMouseLeave.connect(self.mouseLeave) # ##TODO: cleaning house job self.dataPlot.installEventFilter(self) txtY_value = TextItem("", fill=(0, 0, 255, 80), anchor=(0,1),color='w') txtY_value.setParentItem(viewBox) self.curLabelofYvalue = txtY_value # #self.dataPlot.addItem(self.lableY_value) # labelY_value.setPos(self.minTimestamp,100.0) self.configPlotArea(self.dataPlot) # set current selection plot window background self.currSelctPlotWgt = self.dataPlot self.currSelctPlotWgt.setBackground(0.95)
def __initUI(self): self.resize(850, 650) self.center() self.setWindowTitle('Application de tracking vidéo') self.statusBar() # status bar at the bottom of the window # QTabWidget of the application showing the 5 tabs self.tabs = QTabWidget() # tab1: display video images & video metadata self.imageTab = ImageDisplay(self) # tab2: plot (y(t), x(t)) self.onePlot = OnePlot(self) # tab3: plot curves x(t) and y(t) self.twoPlots_xy = TwoPlots(self, "position") # tab4: plot curves Vx(t) and Vy(t) self.twoPlots_VxVy = TwoPlots(self, "velocity") # tab5: plot of f(t)=f(x(t), y(t), t) self.functionOfXY = FunctionPlot(self) # tab6: IPython shell self.pythonConsole = PythonConsole(self) self.tabs.addTab(self.imageTab,"Visualisation images") self.tabs.addTab(self.onePlot,"Trajectoire") self.tabs.addTab(self.twoPlots_xy,"Positions") self.tabs.addTab(self.twoPlots_VxVy,"Vitesses") self.tabs.addTab(self.functionOfXY,"Outil de tracé") self.tabs.addTab(self.pythonConsole,"IPython") self.setCentralWidget(self.tabs) # Menu(s) self.menubar = self.menuBar() if platform.uname().system.startswith('Darw') : # Mac OS specificity: self.menubar.setNativeMenuBar(False) ###### Menu 'Files' fileMenu = self.menubar.addMenu('&Fichier') ### Open images directory: qa = QAction(QIcon(VideoTracker.icone_dir+'/open.png'), 'Ouvrir dossier images', self) qa.setShortcut('Ctrl+D') qa.setStatusTip("Ouvre un dossier contenant déjà "+\ "les images d'une vidéo") # connexion avec la méthode 'load_images_from_directory' qui est # définie dans l'objet 'imageTab' : qa.triggered.connect(self.imageTab.load_images_from_directory) fileMenu.addAction(qa) ### Load a video file : qa = QAction(QIcon(VideoTracker.icone_dir+'/open.png'), "Charger un fichier vidéo", self) qa.setShortcut('Ctrl+O') qa.setStatusTip('Ouvre un fihier vidéo et le '+\ 'découpe en images successives...') # connexion avec la méthode 'open_video' qui est définie dans # l'objet 'imageTab' : qa.triggered.connect(self.imageTab.open_video) fileMenu.addAction(qa) ### Export CSV: qa = QAction(QIcon(VideoTracker.icone_dir+'/exportCSV.png'),\ 'Export CSV', self) qa.setStatusTip("Exporte les positions extraites de la vidéo dans un"+\ "fichier CSV.") qa.triggered.connect(self.ExportCSV) fileMenu.addAction(qa) ### Import CSV: qa = QAction(QIcon(VideoTracker.icone_dir+'/importCSV.png'),\ 'Import CSV', self) qa.setStatusTip("Importe les données depuis un fichier CSV forgé par VideoTracker.") qa.triggered.connect(self.ImportCSV) fileMenu.addAction(qa) ### Quit : qa = QAction(QIcon(VideoTracker.icone_dir+'/exit.png'),\ 'Quitter', self) qa.setShortcut('Ctrl+Q') qa.setStatusTip("Quitter l'application") qa.triggered.connect(self.close) fileMenu.addAction(qa) ###### Le menu 'Options' optionMenu = self.menubar.addMenu('&Options') ### Display info box windows: qa = QAction('Afficher boîtes info', self, checkable=True) text = 'Afficher ou non les boîtes de dialogue d\'information' qa.setStatusTip(text)# message in the status bar qa.setChecked(True) qa.triggered.connect(lambda e: self.set_flag("displayInfo",e)) optionMenu.addAction(qa) ### Verbose mode : qa = QAction('Mode verbeux', self, checkable=True) text = 'Afficher ou non des informations dans le shell Python' qa.setStatusTip(text) # message in the status bar qa.setChecked(True) qa.triggered.connect(lambda e: self.set_flag("debug", e)) optionMenu.addAction(qa) ### Clear trajectory plots before a new plot: qa = QAction('Effacement trajectoire avant tracé', self, checkable=True) text = 'Effacer automatiquement le tracé des onglets <Trajectoires> et ' text += '<X(t) et Y(t)> un nouveau tracé ?' qa.setStatusTip(text) # message in the status bar qa.setChecked(True) qa.triggered.connect(lambda e: self.set_flag("autoClearTraj", e) ) optionMenu.addAction(qa) ### draw/not draw the selected color area qa = QAction('Dessiner la sélection couleur de la cible', self, checkable=True) text = 'Dessine la zone sélectionnée pour la couleur de la cible' qa.setStatusTip(text) # message in the status bar qa.setChecked(True) qa.triggered.connect(lambda e: self.set_flag("drawTargetSelection", e)) optionMenu.addAction(qa)
class MainWidget(QWidget): """Main window class that provides logic of the program. Allows to search concept and to show information about concepts and relations """ def __init__(self, parent=None, application=None): super().__init__(parent) self.parent = parent self.application = application self.db = self.openDatabase() self.initUI() def initActions(self): """initalization of actions for main windows""" self.help_action = QAction("&Help", self) self.help_action.setShortcut("F1") self.help_action.setStatusTip('Help') self.help_action.triggered.connect(lambda: HelpDialog(self)) self.about_action = QAction("&About", self) self.about_action.setStatusTip('About') self.about_action.triggered.connect(self.showAboutMessage) self.new_db_action = QAction("New DB", self) self.new_db_action.setShortcut("Ctrl+N") self.new_db_action.triggered.connect(self.openNewDB) self.delete_сoncept_action = QAction("&Delete", self) self.delete_сoncept_action.setShortcut("DEL") self.delete_сoncept_action.setStatusTip("Delete") self.delete_сoncept_action.triggered.connect(lambda: self.delete(Concept)) self.delete_subcategory_action = QAction("&Delete subcategory", self) self.delete_subcategory_action.triggered.connect(lambda: self.delete(Subcategory)) self.edit_concept_action = QAction("&Edit", self) self.edit_concept_action.setShortcut("F2") self.edit_concept_action.triggered.connect(self.editConcept) self.edit_relation_action = QAction("&Edit", self) self.edit_relation_action.setShortcut("Ctrl+F2") self.edit_relation_action.triggered.connect(self.editRelation) self.exit_action = QAction("&Exit", self) self.exit_action.setShortcut("ESC") self.exit_action.triggered.connect(self.close) self.select_relation_action = QAction("&Select relation", self) self.select_relation_action.triggered.connect(self.setRelationDescription) self.delete_relation_action = QAction("&Delete", self) self.delete_relation_action.setShortcut("Ctrl+DEL") self.delete_relation_action.triggered.connect(lambda: self.delete(Relation)) def showAboutMessage(self): try: with open("about.txt") as f: text = f.read() QMessageBox.about(self.parent, "About application", text) except: pass def openNewDB(self): """This method deletes setting.py file and closes current application session. This uses for creating a new instance of Main Window. """ if os.path.exists("setting.py"): os.remove("setting.py") self.parent.close() self.application.exit(1) def initUI(self): self.initActions() self.add_data_button = QPushButton("Add data", self) self.export_button = QPushButton("Export references", self) self.search_box = QGroupBox() self.concept_list = QListWidget(self) self.relation_list = QListWidget(self) self.result_table = QTextEdit(self) self.concept_list.selectionModel().selectionChanged.connect(self.searchRelations) self.concept_list.setSelectionMode(QAbstractItemView.ContiguousSelection) self.concept_list.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.concept_list.setContextMenuPolicy(Qt.CustomContextMenu) self.concept_list.customContextMenuRequested.connect(self.showConceptContextMenu) self.relation_list.setContextMenuPolicy(Qt.CustomContextMenu) self.relation_list.customContextMenuRequested.connect(self.showRelationContextMenu) self.relation_list.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.relation_list.selectionModel().selectionChanged.connect(self.setRelationDescription) self.initSearchFrame(self.search_box) self.grid = QGridLayout() self.result_table.setReadOnly(True) self.search() self.configWidgets() self.bindWidgets() self.show() def showConceptContextMenu(self, pos): if not len(self.concept_list.selectedItems()) == 1: return global_position = self.concept_list.mapToGlobal(pos) my_menu = QMenu() my_menu.addAction(self.edit_concept_action) my_menu.addAction(self.delete_сoncept_action) my_menu.addAction(self.delete_subcategory_action) my_menu.addSeparator() my_menu.addAction(self.help_action) my_menu.addAction(self.exit_action) my_menu.exec(global_position) def initSearchFrame(self, frame): self.search_line = QLineEdit(frame) checkboxes = QGroupBox() checkboxes.setStyleSheet("border:0;") self.concept_checkbox = QCheckBox("Concept", checkboxes) self.description_checkbox = QCheckBox("Description", checkboxes) self.study_checkbox = QCheckBox("Study", checkboxes) self.reference_checkbox = QCheckBox("Reference", checkboxes) self.in_selected_checkbox = QCheckBox("Search in selected concepts", checkboxes) self.search_button = QPushButton("Search", checkboxes) checkboxes_layout = QGridLayout(checkboxes) checkboxes_layout.addWidget(self.concept_checkbox, 0, 0) checkboxes_layout.addWidget(self.description_checkbox, 0, 1) checkboxes_layout.addWidget(self.study_checkbox, 0, 2) checkboxes_layout.addWidget(self.reference_checkbox, 0, 3) checkboxes_layout.addWidget(self.in_selected_checkbox, 0, 4) checkboxes_layout.setContentsMargins(0, 0, 0, 0) self.concept_checkbox.setChecked(True) self.in_selected_checkbox.setChecked(True) grid = QGridLayout(frame) grid.addWidget(self.search_line, 1, 0) grid.addWidget(self.search_button, 1, 1) grid.addWidget(checkboxes, 2, 0, Qt.AlignLeft) frame.setLayout(grid) def getSearchData(self): """This method reads parameters of search line and checkboxes, and returns "Subcategory" class. None and [] uses for showing checkboxes that have been checked. """ concept = self.search_line.text() if self.concept_checkbox.isChecked() else None if self.reference_checkbox.isChecked(): reference = [ #RelationReference(text=self.search_line.text()), ConceptReference(text=self.search_line.text()) ] else: reference = [] if self.description_checkbox.isChecked(): description = [Description(text=self.search_line.text(), reference=reference)] else: description = [Description(reference=reference)] study = self.search_line.text() if self.study_checkbox.isChecked() else None if self.in_selected_checkbox.isChecked and len(self.concept_list.selectedItems()) > 1: selected_items_raw = self.concept_list.selectedItems() selected_items = [item.data(Qt.UserRole)[1] for item in selected_items_raw] else: selected_items = [] return Subcategory(subcategory=concept, description=description, study=study), selected_items # todo: doesn't work, becouse need html + bib --> rendered bib def searchRelations(self): """This method triggers when the user clicked on the concept. This method selected ID of a subcategory from selected item in conceptions list and then searches and setting all information about this selected concept. """ if not self.concept_list.selectedItems(): self.setConceptDescription() self.setResult([], self.relation_list) return subcategory_id = self.concept_list.selectedItems()[0].data(Qt.UserRole)[1].id self.setConceptDescription() result = self.db.search_relation(subcategory_id) self.setResult(result, self.relation_list) def showRelationContextMenu(self, pos): global_position = self.relation_list.mapToGlobal(pos) my_menu = QMenu() my_menu.addAction(self.edit_relation_action) my_menu.addAction(self.delete_relation_action) my_menu.addSeparator() my_menu.exec(global_position) def editRelation(self): """This method opens dialog for editing Relation""" if hasSlelectedItems(self.relation_list): relation = self.relation_list.selectedItems()[0].data(Qt.UserRole)[2] dlg = EditRelationDialog(self, relation) if dlg.exec_(): relation = dlg.getValue() self.db.update_relation(relation) self.select_relation_action.trigger() def editConcept(self): """This method opens dialog for editing Concept""" if hasSlelectedItems(self.concept_list): concept = self.concept_list.selectedItems()[0].data(Qt.UserRole)[0] subcategory = self.concept_list.selectedItems()[0].data(Qt.UserRole)[1] dlg = EditConceptDialog(self, concept, subcategory) if dlg.exec_(): concept, subcategory = dlg.getValue() self.db.update_concept(concept) self.db.update_subcategory(subcategory) self.search() def delete(self, something): """This universal method for deleting something from the list and database. "something" parameter needs to be any of this types: Concept, Subcategory, Relation """ if something == Concept: number = 0 target_list = self.concept_list elif something == Subcategory: number = 1 target_list = self.concept_list elif something == Relation: number = 2 target_list = self.relation_list if hasSlelectedItems(target_list): something = target_list.selectedItems()[0].data(Qt.UserRole)[number] self.db.delete(something) self.search() # need refactoring def setRelationDescription(self): """This method retrieves information about relation, formats and sets it in description field. """ if hasSlelectedItems(self.relation_list): relation = self.relation_list.selectedItems()[0].data(Qt.UserRole)[2] concept1 = "{}{}".format(relation.node1.concept.name, ", {}".format(relation.node1.subcategory) if relation.node1.subcategory else "") concept2 = "{}{}".format(relation.node2.concept.name, ", {}".format(relation.node2.subcategory) if relation.node2.subcategory else "") description = relation.description study = relation.study references = relation.reference # HTML is used for a better information formating text = "<b>Relation between </b> \"{}\" <b>and</b> \"{}\"<p>".format(concept1, concept2) text += r"<b>Description:</b>" + "<br> {} <p>".format(description) text += r"<b>Study:</b> {} <p>".format(study) text += r"<b>References:</b><ol>" for ref in references: text += " <li> {} </li>".format(getBibRenderFromHTML(ref.text)) text += "</ol><br>" self.result_table.setHtml(text) else: self.result_table.clear() # need refactoring def setConceptDescription(self): """This method retrieves information about concept, formats and sets it in description field. """ if not self.concept_list.selectedItems(): self.result_table.setHtml("") return concept = self.concept_list.selectedItems()[0].data(Qt.UserRole)[0] subcategory = self.concept_list.selectedItems()[0].data(Qt.UserRole)[1] description = subcategory.description # HTML is used for a better information formating text = "<b>Concept:</b> {}<p>".format(concept.name) text += "<b>Subcategory:</b> {}<p>".format(subcategory.subcategory) text += "<b>Synonyms:</b> {}<p>".format(concept.synonyms) text += "<ol>" for des in description: text += "<li> {}".format("<b>Description:</b> <br>") text += " {} <p>".format(des.text) text += "<ol>" text += "<b>References: </b>" for ref in des.reference: text += "<li>" text += "{}".format(getBibRenderFromHTML(ref.text)) text += "</li>" text += "</ol>" text += "</li>" text += "</ol>" self.result_table.setHtml(text) def setResult(self, result, list): """This is a universal method for showing information in a relation field or in a concept field. """ list.clear() for concept, subcategory, *other in result: item = QListWidgetItem() item.setData(Qt.UserRole, (concept, subcategory, *other)) item.setText("{}{} {}".format(concept.name, "" if subcategory.subcategory == "" else ", ", subcategory.subcategory)) list.insertItem(0, item) def search(self): subcategory, selected_items = self.getSearchData() result = self.db.search_nodes(subcategory, selected_items) self.setResult([], self.relation_list) self.setResult(result, self.concept_list) self.setResult([], self.relation_list) self.setRelationDescription() def configWidgets(self): self.grid.setAlignment(Qt.AlignTop) self.grid.setSpacing(5) self.menu_bar = QMenuBar(self) self.database_menu = self.menu_bar.addMenu("Database") self.database_menu.addAction(self.new_db_action) self.database_menu.addSeparator() self.database_menu.addAction(self.exit_action) self.concept_menu = self.menu_bar.addMenu("Concept") self.concept_menu.addAction(self.edit_concept_action) self.concept_menu.addAction(self.delete_сoncept_action) self.concept_menu.addAction(self.delete_subcategory_action) self.relation_menu = self.menu_bar.addMenu("Relation") self.relation_menu.addAction(self.edit_relation_action) self.relation_menu.addAction(self.delete_relation_action) self.help_menu = self.menu_bar.addMenu("Help") self.help_menu.addAction(self.help_action) self.help_menu.addAction(self.about_action) self.grid.setMenuBar(self.menu_bar) self.concept_box = QGroupBox("Concepts") self.concept_grid = QGridLayout() self.concept_grid.setContentsMargins(0, 10, 0, 0) self.concept_grid.addWidget(self.concept_list) self.concept_box.setLayout(self.concept_grid) self.relation_box = QGroupBox("Relations") self.relation_grid = QGridLayout() self.relation_grid.setContentsMargins(0, 10, 0, 0) self.relation_grid.addWidget(self.relation_list) self.relation_box.setLayout(self.relation_grid) self.description_box = QGroupBox("Description") self.description_grid = QGridLayout() self.description_grid.setContentsMargins(0, 10, 0, 0) self.description_grid.addWidget(self.result_table) self.description_box.setLayout(self.description_grid) self.concept_splitter = QSplitter(self) self.concept_splitter.addWidget(self.concept_box) self.concept_splitter.addWidget(self.relation_box) self.description_splitter = QSplitter(self) self.description_splitter.setOrientation(Qt.Vertical) self.description_splitter.addWidget(self.concept_splitter) self.description_splitter.addWidget(self.description_box) self.grid.addWidget(self.add_data_button, 1, 0, Qt.AlignLeft) self.grid.addWidget(self.export_button, 1, 1, Qt.AlignRight) self.grid.addWidget(self.search_box, 2, 0, 1, 2) self.grid.addWidget(self.description_splitter, 5, 0, 1, 2) self.setLayout(self.grid) def bindWidgets(self): self.add_data_button.clicked.connect(self.addData) self.search_button.clicked.connect(self.search) self.export_button.clicked.connect(self.exportReferences) self.search_line.returnPressed.connect(self.search) def exportReferences(self): references = self.db.get_all_references() references = [getPlainText(ref.text) for ref in references] references = list(set(references)) references = [prepareBibStr(ref) for ref in references] final_text = ",\n\n".join(references) dlg = QFileDialog() file_path = dlg.getSaveFileName(self, "Save bibtex file")[0] if not (file_path == ""): # todo: check readBibsFromFile try: with open(file_path, 'w') as f: f.write(final_text) except Exception as error: showError(error) def addData(self): dlg = NewDataDialog(self.db) dlg.exec_() self.search() def getPath(self): dialog = NewDBDialog() if dialog.exec_(): path = dialog.path with open("setting.py", "w") as f: f.write("{{ 'last': r'{0}' }}".format(path)) return path else: self.close() def openDatabase(self): if os.path.exists("setting.py"): with open("setting.py") as f: setting = eval(f.read()) if "last" in setting: if os.path.exists(setting["last"]): path = setting["last"] else: path = self.getPath() else: path = self.getPath() else: path = self.getPath() if path is None: self.close() exit(0) else: return Graph(path) def closeEvent(self, event): event.ignore()
class MainWindow(QWidget): """Main window class that provides logic of the program. Allows to search concept and to show information about concepts and relations """ def __init__(self, application): super().__init__() self.application = application self.db = self.openDatabase() self._initUI() def initActions(self): """initalization of actions for main windows""" self.help_action = QAction("&Help", self) self.help_action.setShortcut("F1") self.help_action.setStatusTip('Help') self.help_action.triggered.connect(lambda: HelpDialog(self)) self.new_db_action = QAction("New DB", self) self.new_db_action.setShortcut("Ctrl+N") self.new_db_action.triggered.connect(self.openNewDB) self.delete_сoncept_action = QAction("&Delete", self) self.delete_сoncept_action.setShortcut("DEL") self.delete_сoncept_action.setStatusTip("Delete") self.delete_сoncept_action.triggered.connect(lambda: self.delete(Concept)) self.delete_subcategory_action = QAction("&Delete subcategory", self) self.delete_subcategory_action.triggered.connect(lambda: self.delete(Subcategory)) self.edit_concept_action = QAction("&Edit", self) self.edit_concept_action.setShortcut("F2") self.edit_concept_action.triggered.connect(self.editConcept) self.edit_relation_action = QAction("&Edit", self) self.edit_relation_action.setShortcut("Ctrl+F2") self.edit_relation_action.triggered.connect(self.editRelation) self.exit_action = QAction("&Exit", self) self.exit_action.setShortcut("ESC") self.exit_action.triggered.connect(self.close) self.select_relation_action = QAction("&Select relation", self) self.select_relation_action.triggered.connect(self.setRelationDescription) self.delete_relation_action = QAction("&Delete", self) self.delete_relation_action.setShortcut("Ctrl+DEL") self.delete_relation_action.triggered.connect(lambda: self.delete(Relation)) def openNewDB(self): """This method deletes setting.py file and closes current application session. This uses for creating a new instance of Main Window. """ if os.path.exists("setting.py"): os.remove("setting.py") self.application.exit(1) def _initUI(self): self.setWindowIcon(QIcon("logo.png")) self.setWindowTitle('GraphNotes') self.resize(1000, 700) self.initActions() self.add_data_button = QPushButton("Add data", self) self.search_box = QGroupBox() self._initSearchFrame(self.search_box) self.concept_list = QListWidget(self) self.relation_list = QListWidget(self) self.result_table = QTextEdit(self) self.concept_list.itemClicked.connect(self.searchRelations) self.concept_list.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.concept_list.setContextMenuPolicy(Qt.CustomContextMenu) self.concept_list.customContextMenuRequested.connect(self._showConceptContextMenu) self.relation_list.setContextMenuPolicy(Qt.CustomContextMenu) self.relation_list.customContextMenuRequested.connect(self._showRelationContextMenu) self.relation_list.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.relation_list.itemClicked.connect(self.setRelationDescription) self.grid = QGridLayout() self.result_table.setReadOnly(True) self.search() self._configWidgets() self._bindWidgets() self.show() def _showConceptContextMenu(self, pos): global_position = self.concept_list.mapToGlobal(pos) my_menu = QMenu() my_menu.addAction(self.edit_concept_action) my_menu.addAction(self.delete_сoncept_action) my_menu.addAction(self.delete_subcategory_action) my_menu.addSeparator() my_menu.addAction(self.help_action) my_menu.addAction(self.exit_action) my_menu.exec(global_position) def _initSearchFrame(self, frame): self.search_line = QLineEdit(frame) checkboxes = QGroupBox() checkboxes.setStyleSheet("border:0;") self.concept_checkbox = QCheckBox("Concept", checkboxes) self.description_checkbox = QCheckBox("Description", checkboxes) self.study_checkbox = QCheckBox("Study", checkboxes) self.search_button = QPushButton("Search", checkboxes) checkboxes_layout = QGridLayout(checkboxes) checkboxes_layout.addWidget(self.concept_checkbox, 0, 0) checkboxes_layout.addWidget(self.description_checkbox, 0, 1) checkboxes_layout.addWidget(self.study_checkbox, 0, 2) checkboxes_layout.setContentsMargins(0, 0, 0, 0) self.concept_checkbox.setChecked(True) grid = QGridLayout(frame) grid.addWidget(self.search_line, 1, 0) grid.addWidget(self.search_button, 1, 1) grid.addWidget(checkboxes, 2, 0, Qt.AlignLeft) frame.setLayout(grid) def getSearchData(self): """This method reads parameters of search line and checkboxes, and returns "Subcategory" class. None and [] uses for showing checkboxes that have been checked. """ concept = self.search_line.text() if self.concept_checkbox.isChecked() else None description = [Description(text=self.search_line.text())] if self.description_checkbox.isChecked() else [] study = self.search_line.text() if self.study_checkbox.isChecked() else None return Subcategory(subcategory=concept, description=description, study=study) def searchRelations(self): """This method triggers when the user clicked on the concept. This method selected ID of a subcategory from selected item in conceptions list and then searches and setting all information about this selected concept. """ subcategory_id = self.concept_list.selectedItems()[0].data(Qt.UserRole)[1].id self.setConceptDescription() result = self.db.search_relation(subcategory_id) self.setResult(result, self.relation_list) def _showRelationContextMenu(self, pos): global_position = self.relation_list.mapToGlobal(pos) my_menu = QMenu() my_menu.addAction(self.edit_relation_action) my_menu.addAction(self.delete_relation_action) my_menu.addSeparator() my_menu.exec(global_position) def editRelation(self): """This method opens dialog for editing Relation""" if self.relation_list.currentIndex().isValid(): relation = self.relation_list.selectedItems()[0].data(Qt.UserRole)[2] dlg = EditRelationDialog(self, relation) if dlg.exec_(): relation = dlg.getValue() self.db.update_relation(relation) self.select_relation_action.trigger() def editConcept(self): """This method opens dialog for editing Concept""" if self.concept_list.currentIndex().isValid(): concept = self.concept_list.selectedItems()[0].data(Qt.UserRole)[0] subcategory = self.concept_list.selectedItems()[0].data(Qt.UserRole)[1] dlg = EditConceptDialog(self, concept, subcategory) if dlg.exec_(): concept, subcategory = dlg.getValue() self.db.update_concept(concept) self.db.update_subcategory(subcategory) self.search() def delete(self, something): """This universal method for deleting something from the list and database. "something" parameter needs to be any of this types: Concept, Subcategory, Relation """ if something == Concept: number = 0 target_list = self.concept_list elif something == Subcategory: number = 1 target_list = self.concept_list elif something == Relation: number = 2 target_list = self.relation_list if target_list.currentIndex().isValid(): something = target_list.selectedItems()[0].data(Qt.UserRole)[number] self.db.delete(something) self.search() def setRelationDescription(self): """This method retrieves information about relation, formats and sets it in description field. """ if self.relation_list.currentIndex().isValid(): relation = self.relation_list.selectedItems()[0].data(Qt.UserRole)[2] concept1 = "{}{}".format(relation.node1.concept.name, ", {}".format(relation.node1.subcategory) if relation.node1.subcategory else "") concept2 = "{}{}".format(relation.node2.concept.name, ", {}".format(relation.node2.subcategory) if relation.node2.subcategory else "") description = relation.description study = relation.study references = relation.reference # HTML is used for a better information formating text = "<b>Relation between </b> \"{}\" <b>and</b> \"{}\"<p>".format(concept1, concept2) text += r"<b>Description:</b>" + "<br> {} <p>".format(description) text += r"<b>Study:</b> {} <p>".format(study) text += r"<b>References:</b><ol>" for ref in references: text += " <li> {} </li>".format(ref.text) text += "</ol><br>" self.result_table.setText(text) else: self.result_table.clear() def setConceptDescription(self): """This method retrieves information about concept, formats and sets it in description field. """ concept = self.concept_list.selectedItems()[0].data(Qt.UserRole)[0] subcategory = self.concept_list.selectedItems()[0].data(Qt.UserRole)[1] description = subcategory.description # HTML is used for a better information formating text = "<b>Concept:</b> {}<p>".format(concept.name) text += "<b>Subcategory:</b> {}<p>".format(subcategory.subcategory) text += "<b>Synonyms:</b> {}<p>".format(concept.synonyms) text += "<ol>" for des in description: text += "<li> {}".format("<b>Description:</b> <br>") text += " {} <p>".format(des.text) text += "<ol>" text += "<b>References: </b>" for ref in des.reference: text += "<li>" text += "{}".format(ref.text) text += "</li>" text += "</ol>" text += "</li>" text += "</ol>" self.result_table.setText(text) def setResult(self, result, list): """This is a universal method for showing information in a relation field or in a concept field. """ list.clear() for concept, subcategory, *other in result: item = QListWidgetItem() item.setData(Qt.UserRole, (concept, subcategory, *other)) item.setText("{}{} {}".format(concept.name, "" if subcategory.subcategory == "" else ", ", subcategory.subcategory)) list.insertItem(0, item) def search(self): parameters = self.getSearchData() result = self.db.search_nodes(parameters) self.setResult([], self.relation_list) self.setResult(result, self.concept_list) self.setResult([], self.relation_list) self.setRelationDescription() def _configWidgets(self): self.grid.setAlignment(Qt.AlignTop) self.grid.setSpacing(5) self.menu_bar = QMenuBar(self) self.database_menu = self.menu_bar.addMenu("Database") self.database_menu.addAction(self.new_db_action) self.database_menu.addSeparator() self.database_menu.addAction(self.exit_action) self.concept_menu = self.menu_bar.addMenu("Concept") self.concept_menu.addAction(self.edit_concept_action) self.concept_menu.addAction(self.delete_сoncept_action) self.concept_menu.addAction(self.delete_subcategory_action) self.relation_menu = self.menu_bar.addMenu("Relation") self.relation_menu.addAction(self.edit_relation_action) self.relation_menu.addAction(self.delete_relation_action) self.help_menu = self.menu_bar.addMenu("Help") self.help_menu.addAction(self.help_action) self.grid.setMenuBar(self.menu_bar) self.concept_box = QGroupBox("Concepts") self.concept_grid = QGridLayout() self.concept_grid.setContentsMargins(0, 10, 0, 0) self.concept_grid.addWidget(self.concept_list) self.concept_box.setLayout(self.concept_grid) self.relation_box = QGroupBox("Relations") self.relation_grid = QGridLayout() self.relation_grid.setContentsMargins(0, 10, 0, 0) self.relation_grid.addWidget(self.relation_list) self.relation_box.setLayout(self.relation_grid) self.description_box = QGroupBox("Description") self.description_grid = QGridLayout() self.description_grid.setContentsMargins(0, 10, 0, 0) self.description_grid.addWidget(self.result_table) self.description_box.setLayout(self.description_grid) self.concept_splitter = QSplitter(self) self.concept_splitter.addWidget(self.concept_box) self.concept_splitter.addWidget(self.relation_box) self.description_splitter = QSplitter(self) self.description_splitter.setOrientation(Qt.Vertical) self.description_splitter.addWidget(self.concept_splitter) self.description_splitter.addWidget(self.description_box) self.grid.addWidget(self.add_data_button, 1, 0, Qt.AlignLeft) self.grid.addWidget(self.search_box, 2, 0, 1, 2) self.grid.addWidget(self.description_splitter, 5, 0, 1, 2) self.setLayout(self.grid) def _bindWidgets(self): self.add_data_button.clicked.connect(self.addData) self.search_button.clicked.connect(self.search) self.search_line.returnPressed.connect(self.search) def addData(self): dlg = NewDataDialog(self.db) dlg.exec_() self.search() def getPath(self): dialog = NewDBDialog() if dialog.exec_(): print("EXEc") path = dialog.path with open("setting.py", "w") as f: f.write("{{ 'last': r'{0}' }}".format(path)) return path else: self.close() def openDatabase(self): if os.path.exists("setting.py"): with open("setting.py") as f: setting = eval(f.read()) if "last" in setting: if os.path.exists(setting["last"]): path = setting["last"] else: path = self.getPath() else: path = self.getPath() else: path = self.getPath() if path is None: self.close() exit(0) else: return Graph(path)
def build_menu_bar(self): get_icon = Icons().get_icon ## Is this a system install? sysInstall = (os.path.expanduser('~') in sys.argv[0]) ######## Actions ## Save saveAction = QAction( QIcon(get_icon("document-save-symbolic", sysInstall)), "&Save Settings", self) saveAction.setShortcut("Ctrl+S") saveAction.setStatusTip("Save current settings") saveAction.triggered.connect(self.save_settings) ## Import playlist importAction = QAction( QIcon(get_icon("document-open-symbolic", sysInstall)), "&Import URLs", self) importAction.setShortcut("Ctrl+I") importAction.setStatusTip("Import a saved list of URLs") importAction.triggered.connect(self.import_urls) ## Export playlist exportAction = QAction( QIcon(get_icon("document-save-symbolic", sysInstall)), "&Export URLs", self) exportAction.setShortcut("Ctrl+E") exportAction.setStatusTip("Export URLs to a text file") exportAction.triggered.connect(self.export_urls) ## Exit exitAction = QAction( QIcon(get_icon("application-exit-symbolic", sysInstall)), "&Exit", self) exitAction.setShortcut("Ctrl+Q") exitAction.setStatusTip("Exit the application") exitAction.triggered.connect(qApp.quit) ## Go goAction = QAction(QIcon(get_icon("go-next-symbolic", sysInstall)), "Download URLs", self) goAction.setShortcut("Return") goAction.setStatusTip("Download current URL list") goAction.triggered.connect(self.mainWidget.start_download) ## Paste pasteAction = QAction( QIcon(get_icon("edit-paste-symbolic", sysInstall)), "&Paste", self) pasteAction.setShortcut("Ctrl+V") pasteAction.setStatusTip("Add URL from clipboard") pasteAction.triggered.connect(self.mainWidget.quick_add_item) ## Set destination setDestAction = QAction( QIcon(get_icon("document-open-symbolic", sysInstall)), "Set &Download directory", self) setDestAction.setShortcut("Ctrl+D") setDestAction.setStatusTip("Choose your download directory") setDestAction.triggered.connect(self.mainWidget.set_destination) ## Allow duplicates self.dupeAction = QAction("Allow duplicates", self) self.dupeAction.setStatusTip("Allow duplicate URLs in queue") self.dupeAction.setCheckable(True) if self.opts["duplicates"] == "true": self.dupeAction.setChecked(True) self.dupeAction.triggered.connect(self.check_dupe_box) ## New folder for playlists self.playlistFolderAction = QAction("New folder for playlists", self) self.playlistFolderAction.setStatusTip( "Create a new folder for every playlist downloaded") self.playlistFolderAction.setCheckable(True) if self.opts["playlistFolder"] == "true": self.playlistFolderAction.setChecked(True) self.playlistFolderAction.triggered.connect( self.check_playlist_dir_box) ## About action aboutAction = QAction( QIcon(get_icon("help-about-symbolic", sysInstall)), "&About", self) aboutAction.setStatusTip("Information about the program") aboutAction.triggered.connect(self.about) ## ====== Theme actions ## System default theme defaultThemeAction = QAction("Default", self) defaultThemeAction.setStatusTip("Set theme to system default") defaultThemeAction.triggered.connect(self.toggle_theme_default) ## Light theme lightThemeAction = QAction("Light theme", self) lightThemeAction.setStatusTip("Use a light theme") lightThemeAction.triggered.connect(self.toggle_theme_light) ## Dark theme darkThemeAction = QAction("Dark theme", self) darkThemeAction.setStatusTip("Use a dark theme") darkThemeAction.triggered.connect(self.toggle_theme_dark) ## Create the menubar menuBar = self.menuBar() ## Create file menu fileMenu = menuBar.addMenu("&File") fileMenu.addAction(saveAction) fileMenu.addAction(exportAction) fileMenu.addSeparator() fileMenu.addAction(importAction) fileMenu.addSeparator() fileMenu.addAction(goAction) fileMenu.addSeparator() fileMenu.addAction(exitAction) ## Edit Menu editMenu = menuBar.addMenu("&Edit") editMenu.addAction(pasteAction) ## Settins Menu settingsMenu = menuBar.addMenu("&Settings") themesMenu = settingsMenu.addMenu("Theme") settingsMenu.addSeparator() settingsMenu.addAction(setDestAction) settingsMenu.addSeparator() settingsMenu.addAction(self.dupeAction) settingsMenu.addAction(self.playlistFolderAction) ## Themes submenu themesMenu.addAction(defaultThemeAction) themesMenu.addAction(lightThemeAction) themesMenu.addAction(darkThemeAction) ## Help menu helpMenu = menuBar.addMenu("&Help") helpMenu.addAction(aboutAction)