def dialogExtract2csv(self): d = QDialog(self) d.setFixedWidth(450) d.setWindowTitle("Extract data to Csv") d.setVisible(True) vbox = QVBoxLayout() tabWidget = QTabWidget() for name, mod in list(self.moduleDict.items()): wid = QWidget() grid = QGridLayout() grid.setSpacing(20) wid.dateStart = QLineEdit('%s00:00' % dt.datetime.now().strftime("%Y-%m-%dT")) wid.dateEnd = QLineEdit("Now") grid.addWidget(QLabel("From"), 0, 0) grid.addWidget(wid.dateStart, 0, 1) grid.addWidget(QLabel("To"), 0, 2) grid.addWidget(wid.dateEnd, 0, 3) for i, device in enumerate(mod.devices): checkbox = QCheckBox(device.deviceLabel) checkbox.stateChanged.connect(partial(self.csvUpdateTab, name, checkbox, device)) checkbox.setCheckState(2) grid.addWidget(checkbox, 1 + i, 0, 1, 3) wid.setLayout(grid) tabWidget.addTab(wid, name) buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) buttonBox.button(QDialogButtonBox.Ok).clicked.connect(partial(self.extract2csv, tabWidget, d)) buttonBox.button(QDialogButtonBox.Cancel).clicked.connect(d.close) vbox.addWidget(tabWidget) vbox.addWidget(buttonBox) d.setLayout(vbox)
class PluginErrorDialog(QDialog): """ Dialog with tabs each tab is a python traceback """ def __init__(self): super(PluginErrorDialog, self).__init__() self.setWindowTitle(translations.TR_PLUGIN_ERROR_REPORT) self.resize(600, 400) vbox = QVBoxLayout(self) label = QLabel(translations.TR_SOME_PLUGINS_REMOVED) vbox.addWidget(label) self._tabs = QTabWidget() vbox.addWidget(self._tabs) hbox = QHBoxLayout() btnAccept = QPushButton(translations.TR_ACCEPT) btnAccept.setMaximumWidth(100) hbox.addWidget(btnAccept) vbox.addLayout(hbox) #signals btnAccept.clicked['bool'].connect(self.close) def add_traceback(self, plugin_name, traceback_msg): """Add a Traceback to the widget on a new tab""" traceback_widget = TracebackWidget(traceback_msg) self._tabs.addTab(traceback_widget, plugin_name)
class ViewSourceDialogTabber(QMainWindow): def __init__(self, parent=None, title="Source"): super(ViewSourceDialogTabber, self).__init__(parent) self.setWindowTitle(title) self.tabs = QTabWidget(self) self.tabs.setElideMode(Qt.ElideRight) self.tabs.setTabsClosable(True) self.tabs.tabCloseRequested.connect(self.removeTab) self.setCentralWidget(self.tabs) self.tabs.currentChanged.connect(self.updateWindowTitle) def sizeHint(self): return QSize(640, 480) def removeTab(self): self.tabs.removeTab(self.tabs.currentIndex()) def addTab(self, title="New Tab", data=""): vsd = ViewSourceDialog(self, str(title)) vsd.setPlainText(data) self.tabs.addTab(vsd, tr("Source of %s") % (title,)) self.tabs.setCurrentIndex(self.tabs.count()-1) self.raise_() self.activateWindow() def updateWindowTitle(self): try: self.setWindowTitle(tr("Source of %s") % (self.tabs.currentWidget().windowTitle(),)) except: pass if self.tabs.count() == 0: self.hide()
class MyTabWidget(QWidget): def __init__(self): super().__init__() # Initialize tab screen self.tabs = QTabWidget() self.tabs.resize(300, 200) tab1 = QWidget() tab2 = QWidget() # Add tabs self.tabs.addTab(tab1, "Tab 1") self.tabs.addTab(tab2, "Tab 2") # Populate the first tab button1 = QPushButton("PyQt5 button") tab1_layout = QVBoxLayout() tab1_layout.addWidget(button1) tab1.setLayout(tab1_layout) # Set the layout layout = QVBoxLayout() layout.addWidget(self.tabs) self.setLayout(layout)
class TabDialog(QDialog): def __init__(self, parent=None): super(TabDialog, self).__init__(parent) self.ctx = zmq.Context() self.socket = self.ctx.socket(zmq.REQ) self.showFullScreen() self.tabW = QTabWidget() self.Locator = SelectLocator(self) self.Session = SelectSession(self) self.View = ViewData(self) self.tabW.addTab(self.Locator, "Select Locator") self.tabW.addTab(self.Session, "Select Session") self.tabW.addTab(self.View, "View Data") self.tabW.setTabEnabled(1, False) self.tabW.setTabEnabled(2, False) mainLayout = QVBoxLayout() mainLayout.addWidget(self.tabW) self.setLayout(mainLayout) self.setWindowTitle("Tab Dialog")
class dailyTab(QWidget): def __init__(self): super().__init__() # Виджет для дейлков # Содержит содержит главный таб виджет для дейликов self.tab = QTabWidget() self.vbox = QVBoxLayout() self.vbox.addWidget(self.tab) self.setLayout(self.vbox) self.threads = [] # При ините создаём тред для получения дейликов self.loadDataThread = loadDataThread(r'https://api.guildwars2.com/v2/achievements/daily') self.loadDataThread.signal.connect(self.getEvent, Qt.QueuedConnection) self.loadDataThread.start() def getEvent(self, signal): signal = json.loads(signal) for metaEvent in signal.keys(): setattr(self,metaEvent,frame()) self.tab.addTab(getattr(self,metaEvent),metaEvent) for event in signal[metaEvent]: if (event['level']['max'] == 80 and metaEvent == 'pve') or metaEvent != 'pve': getattr(self,metaEvent).getEvent(event) def addTab(self, event, metaEvent): getattr(self,'{}Tab'.format(metaEvent)).addEvent(event) self.resize(self.grid.sizeHint())
class T_window(QWidget): def __init__(self): super().__init__() self.tabs = QTabWidget() self.com = T_communication() self.pbar = QProgressBar() self.pbar.setFormat("Battery : %p%") self.grid = QGridLayout() self.setLayout(self.grid) self.grid.addWidget(self.pbar) self.grid.addWidget(self.tabs) self.dpi = T_dpi() self.com.getDpi(self.dpi) self.dpi.dataHasBeenSent() self.t = [] for i in range(0, 4): self.t.append(T_tab(i, self.dpi, self.com)) self.tabs.addTab(self.t[i], "Mode " + str(i + 1)) self.data = T_data(self.pbar, self.tabs, self.dpi, self.com) for i in range(0, 4): self.t[i].sendButton.clicked.connect(self.data.sendDpi) self.t[i].resetButton.clicked.connect(self.com.resetDpi) self.timer = QBasicTimer() self.timer.start(100, self.data) self.tabs.currentChanged.connect(self.com.sendMode)
class MyTableWidget(QWidget): def __init__(self, parent): super(QWidget, self).__init__(parent) self.layout = QVBoxLayout(self) # Initialize tab screen self.tabs = QTabWidget() # self.tabs.tabBar().hide() self.tabs.setTabPosition(QTabWidget.West) self.tab1 = QWidget() self.tab2 = QWidget() self.tabs.resize(300,200) # Add tabs self.tabs.addTab(self.tab1, QIcon('./liveSEC/icones/app.jpg'), "Tab 1") self.tabs.addTab(self.tab2,"Tab 2") # Create first tab self.tab1.layout = QVBoxLayout(self) self.pushButton1 = QPushButton("PyQt5 button") self.tab1.layout.addWidget(self.pushButton1) self.tab1.setLayout(self.tab1.layout) # Add tabs to widget self.layout.addWidget(self.tabs) self.setLayout(self.layout) @pyqtSlot() def on_click(self): print("\n") for currentQTableWidgetItem in self.tableWidget.selectedItems(): print(currentQTableWidgetItem.row(), currentQTableWidgetItem.column(), currentQTableWidgetItem.text())
class TabWidgets(QTabWidget): def __init__(self, parent): super(TabWidgets, self).__init__(parent) self.wdg1 = QWidget(self) self.lay_wdg1 = QVBoxLayout(self.wdg1) self.wdg2 = QWidget(self) self.lay_wdg2 = QVBoxLayout(self.wdg2) #self.wdg1.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) #self.wdg2.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) self.wdg1.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) self.wdg2.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) self._construct_UI() #------------------------------------------------------------------------------ def _construct_UI(self): """ Initialize UI with tabbed subplots """ self.tabWidget = QTabWidget(self) self.tabWidget.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.tabWidget.addTab(self.wdg1, 'Wdg 1') self.tabWidget.addTab(self.wdg2, 'Wdg 2') layVMain = QVBoxLayout() layVMain.addWidget(self.tabWidget) self.setLayout(layVMain) # When user has switched the tab, call self.current_tab_redraw print('size wdg1: {0}'.format(self.wdg1.size())) print('size wdg2: {0}'.format(self.wdg2.size())) self.tabWidget.currentChanged.connect(self.current_tab_redraw) #------------------------------------------------------------------------------ def current_tab_redraw(self): pass
def initialize(self): tab_widget = QTabWidget() tab1 = QWidget() tab2 = QWidget() juggle_button = QPushButton("Juggle") juggle_button.clicked.connect(self.start_simulation) hbox = QHBoxLayout() hbox.addStretch(1) hbox.addWidget(juggle_button) vbox = QVBoxLayout(tab1) vbox.addStretch(1) vbox.addLayout(hbox) hbox2 = QHBoxLayout(tab2) tab_widget.addTab(tab1, "Main") tab_widget.addTab(tab2, "Other") self.setCentralWidget(tab_widget) menubar = self.menuBar() file_menu = menubar.addMenu('&File') help_menu = menubar.addMenu('&Help') about = help_menu.addMenu('&About') exit_action = QAction(QIcon('exit.png'), '&Exit', self) exit_action.triggered.connect(qApp.quit) file_menu.addAction(exit_action) self.setGeometry(300, 300, 350, 300) self.setWindowTitle('Juggling Simulator') self.show()
class RosConfigDialog(QDialog): configChanged = pyqtSignal() # use this for editable filtering of message types http://www.qtcentre.org/threads/23143-Combobox-entries-filter-as-I-type def __init__(self, name): super(QDialog, self).__init__() self.setWindowTitle(name) self.tabWidget = None self.config = None self.packageTab = None self.topicsTab = None self.tabWidget = QTabWidget() mainLayout = QFormLayout() mainLayout.addWidget(self.tabWidget) self.packageTab = PackageTab() self.packageTab.configChanged.connect(self.configChangedHandler) self.tabWidget.addTab(self.packageTab, 'Package') self.topicsTab = TopicsTab() self.topicsTab.configChanged.connect(self.configChangedHandler) self.tabWidget.addTab(self.topicsTab, 'Topics') self.resize(700, 100) self.setLayout(mainLayout) def setConfig(self, config): self.config = config self.packageTab.setConfig(self.config) self.topicsTab.setConfig(self.config) def configChangedHandler(self): self.configChanged.emit()
def __init__(self, title, text, image, contributors, parent=None): super(AboutDialog, self).__init__(parent) layout = QVBoxLayout() titleLayout = QHBoxLayout() name_versionLabel = QLabel(title) contentsLayout = QHBoxLayout() aboutBrowser = QTextBrowser() aboutBrowser.append(text) aboutBrowser.setOpenExternalLinks(True) creditsBrowser = QTextBrowser() creditsBrowser.append(contributors) creditsBrowser.setOpenExternalLinks(True) TabWidget = QTabWidget() TabWidget.addTab(aboutBrowser, self.tr('About')) TabWidget.addTab(creditsBrowser, self.tr('Contributors')) aboutBrowser.moveCursor(QTextCursor.Start) creditsBrowser.moveCursor(QTextCursor.Start) imageLabel = QLabel() imageLabel.setPixmap(QPixmap(image)) titleLayout.addWidget(imageLabel) titleLayout.addWidget(name_versionLabel) titleLayout.addStretch() contentsLayout.addWidget(TabWidget) buttonLayout = QHBoxLayout() buttonBox = QDialogButtonBox(QDialogButtonBox.Ok) buttonLayout.addWidget(buttonBox) layout.addLayout(titleLayout) layout.addLayout(contentsLayout) layout.addLayout(buttonLayout) self.setLayout(layout) buttonBox.clicked.connect(self.accept) self.setMinimumSize(QSize(380, 400)) self.setWindowTitle(self.tr('About Onkyo QT'))
class GUI(QDialog): def __init__(self, settings): super(QDialog, self).__init__() self.setWindowTitle("Settings") self.setWindowIcon(QIcon('ui/icon.png')) self.setModal(True) self.setWindowFlags(Qt.WindowStaysOnTopHint) self._button_box = QDialogButtonBox( QDialogButtonBox.Ok ) self._button_box.button(QDialogButtonBox.Ok).clicked.connect(self.accept) self._tabs = QTabWidget() self._layout = QBoxLayout(QBoxLayout.TopToBottom) self._layout.addWidget(self._tabs) self._layout.addWidget(self._button_box) self.setLayout(self._layout) # setup tabs self.tab_list = {} self.widgets = {} # general tab general_tab = GeneralTab(settings) self._tabs.addTab(general_tab, general_tab.get_title()) characters_tab = CharactersTab(settings) self._tabs.addTab(characters_tab, characters_tab.get_title()) def set_show_tab(self, tab): if tab == "characters": self._tabs.setCurrentIndex(1)
class class_config_window(QWidget): def init(self): self.setFixedSize(900, 600) self.setWindowIcon(QIcon(os.path.join(get_image_file_path(),"cog.png"))) self.setWindowTitle(_("Configure (www.gpvdm.com)")) self.main_vbox = QVBoxLayout() toolbar=QToolBar() toolbar.setIconSize(QSize(48, 48)) spacer = QWidget() spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) toolbar.addWidget(spacer) self.undo = QAction(QIcon(os.path.join(get_image_file_path(),"help.png")), 'Hide', self) self.undo.setStatusTip(_("Close")) self.undo.triggered.connect(self.callback_help) toolbar.addAction(self.undo) self.main_vbox.addWidget(toolbar) self.notebook = QTabWidget() self.notebook.setMovable(True) self.main_vbox.addWidget(self.notebook) files=["math.inp","dump.inp","thermal.inp","led.inp","config.inp"] description=["Math","Dump","Thermal","LED","GUI config"] for i in range(0,len(files)): tab=tab_class() tab.init(files[i],description[i]) self.notebook.addTab(tab,description[i]) self.setLayout(self.main_vbox) self.win_list=windows() self.win_list.load() self.win_list.set_window(self,"config_window") #self.connect("delete-event", self.callback_close_window) #self.hide() def callback_help(self,widget): webbrowser.open('http://www.gpvdm.com/man/index.html') def closeEvent(self, event): self.win_list.update(self,"config_window")
class AboutDialog(QDialog): def __init__(self, parent=None): super(AboutDialog, self).__init__(parent) self.create() title = QLabel() title.setText('Pulppy Software\nLinear Programming Software') title.setAlignment(Qt.AlignLeft) title.setStyleSheet("font-weight: bold") icon = QLabel() imagen = QPixmap('pulppy.ico') icon.setPixmap(imagen) topLayout = QHBoxLayout() topLayout.addWidget(icon) topLayout.addWidget(title) mainLayout = QVBoxLayout() mainLayout.addLayout(topLayout) mainLayout.addWidget(self.tabWidget) self.setLayout(mainLayout) self.setGeometry(500, 200, 350, 250) self.setWindowTitle('About') self.setWindowIcon(QIcon('pulppy.ico')) def create(self): self.tabWidget = QTabWidget() tab1 = QWidget() labelDescription = QLabel() labelDescription.setText("Linear Programming Software for optimizing\n" "various practical problems of Operations Research.\n" "\n" "Repository:\n" "https://github.com/bruino/pulppy\n") tab1hbox = QHBoxLayout() tab1hbox.addWidget(labelDescription) tab1.setLayout(tab1hbox) tab2 = QWidget() labelAutors = QLabel() labelAutors.setText("+ Danert, Maldonado Jessica\n" "+ Gutierrez, Mariano\n" "+ Moreno, Victor Ricardo\n" "+ Sarverry, Bruno Alejandro\n") tab2hbox = QHBoxLayout() tab2hbox.setContentsMargins(5, 5, 5, 5) tab2hbox.addWidget(labelAutors) tab2.setLayout(tab2hbox) self.tabWidget.addTab(tab1, "&About") self.tabWidget.addTab(tab2, "&Autors")
async def search_and_show_pubkey(cls, parent, app, pubkey): dialog = QDialog(parent) dialog.setWindowTitle("Informations") layout = QVBoxLayout(dialog) tabwidget = QTabWidget(dialog) layout.addWidget(tabwidget) identities = await app.identities_service.lookup(pubkey) for i in identities: user_info = cls.create(parent, app, i) user_info.refresh() tabwidget.addTab(user_info.view, i.uid) return await dialog_async_exec(dialog)
def __init__(self, parent=None): super(FenetreCentrale, self).__init__(parent) tabWidget = QTabWidget() tabWidget.addTab(ModaliteEvaluation(),"Modalite d'evaluation") tabWidget.addTab(GestionEleve(),"Gestion des eleves") #tabWidget.addTab(Essai(),"Lolilol") layout = QVBoxLayout() layout.addWidget(tabWidget) self.setLayout(layout)
class CueSettings(QDialog): on_apply = QtCore.pyqtSignal(dict) def __init__(self, widgets=[], cue=None, check=False, **kwargs): super().__init__(**kwargs) conf = {} if(cue is not None): conf = deepcopy(cue.properties()) self.setWindowTitle(conf['name']) self.setWindowModality(QtCore.Qt.ApplicationModal) self.setMaximumSize(635, 530) self.setMinimumSize(635, 530) self.resize(635, 530) self.sections = QTabWidget(self) self.sections.setGeometry(QtCore.QRect(5, 10, 625, 470)) wsize = QtCore.QSize(625, 470 - self.sections.tabBar().height()) for widget in widgets: widget = widget(wsize, cue) widget.set_configuration(conf) widget.enable_check(check) self.sections.addTab(widget, widget.Name) self.dialogButtons = QDialogButtonBox(self) self.dialogButtons.setGeometry(10, 490, 615, 30) self.dialogButtons.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok | QDialogButtonBox.Apply) self.dialogButtons.rejected.connect(self.reject) self.dialogButtons.accepted.connect(self.accept) apply = self.dialogButtons.button(QDialogButtonBox.Apply) apply.clicked.connect(self.apply) def accept(self): self.apply() super().accept() def apply(self): new_conf = {} for n in range(self.sections.count()): deep_update(new_conf, self.sections.widget(n).get_configuration()) self.on_apply.emit(new_conf)
class mainWindow(QWidget): def __init__(self): super().__init__() # Виджет для главного таб виджета # Содержит вкладки для дейликов и т.д. self.vbox = QVBoxLayout() self.dailyTab = dailyTab() self.tab = QTabWidget() self.tab.addTab(self.dailyTab,'Daily events') self.vbox.addWidget(self.tab) self.setLayout(self.vbox)
def __init__(self): super(Window, self).__init__() self.setWindowTitle("Ledger visualizer") # Create a layout Object, attached to the window. layout = QVBoxLayout(self) self.options = Options(self) layout.addWidget(self.options) tabs = QTabWidget() layout.addWidget(tabs) graph = GraphTab(self.options) tabs.addTab(graph, "Time series") graph = AccountTab(self.options) tabs.addTab(graph, "Account breakdown") graph = BarTab(self.options) tabs.addTab(graph, "Timed breakdown") text = PieTab(self.options) tabs.addTab(text, "Pie charts") button = QPushButton("Quit", self) layout.addWidget(button) button.clicked.connect(app.quit)
def show_about_referentials(self, referentials): dialog = QDialog(self) layout = QVBoxLayout(dialog) tabwidget = QTabWidget(dialog) layout.addWidget(tabwidget) for ref in referentials: widget = QWidget() layout = QVBoxLayout(widget) label = QLabel() label.setText(self.text_referential(ref)) layout.addWidget(label) tabwidget.addTab(widget, ref.translated_name()) dialog.setWindowTitle(self.tr("Referentials")) dialog.exec()
class WritePanel(SubWindow, WindowSystemController): ''' 'Write' main panel. Detachable ''' def __init__(self, parent=None, parent_window_system_controller=None): ''' ''' super(WritePanel, self).__init__( parent=parent, parent_window_system_controller=parent_window_system_controller) self.setWindowTitle(_("Write")) self.setObjectName("write_sub_window") self.dock_system = DockSystem( self, self, DockSystem.DockTypes.WritePanelDock) # connect core signal to open sheets : cfg.core.tree_sheet_manager.sheet_is_opening.connect( self.open_write_tab) # Project tree view dock : self.dock_system.add_dock("write-tree-dock", Qt.LeftDockWidgetArea) # set TabWidget: self.tab_widget = QTabWidget(self) self.setCentralWidget(self.tab_widget) # subscribe cfg.core.subscriber.subscribe_update_func_to_domain( self._clear_project, "core.project.close") def open_write_tab(self, tree_sheet): new_write_tab = WriteTab(self, self) new_write_tab.tree_sheet = tree_sheet self.tab_widget.addTab(new_write_tab, new_write_tab.tab_title) # temp for test: new_write_tab.dock_system.add_dock("properties-dock") def _clear_project(self): # TODO: make that cleaner for i in range(0, self.tab_widget.count()): widget = self.tab_widget.widget(i) widget.close() widget.deleteLater() self.tab_widget.clear()
class pl_main(QWidget,tab_base): lines=[] edit_list=[] file_name="" line_number=[] save_file_name="" name="Luminescence" def __init__(self): QWidget.__init__(self) self.main_vbox = QVBoxLayout() self.notebook = QTabWidget() self.main_vbox.addWidget(self.notebook) self.setLayout(self.main_vbox) self.notebook.setTabsClosable(True) self.notebook.setMovable(True) bar=QHTabBar() bar.setStyleSheet("QTabBar::tab { height: 35px; width: 200px; }") self.notebook.setTabBar(bar) self.notebook.setTabPosition(QTabWidget.West) def update(self): self.notebook.clear() files=epitaxy_get_dos_files() for i in range(0,epitaxy_get_layers()): pl_file=epitaxy_get_pl_file(i) if pl_file.startswith("pl")==True: widget = QWidget() name="Luminescence of "+epitaxy_get_name(i) print(pl_file,files) widget=tab_class() widget.init(pl_file+".inp",name) self.notebook.addTab(widget,name) def help(self): help_window().help_set_help(["tab.png","<big><b>Luminescence</b></big>\nIf you set 'Turn on luminescence' to true, the simulation will assume recombination is a raditave process and intergrate it to produce Voltage-Light intensity curves (lv.dat). Each number in the tab tells the model how efficient each recombination mechanism is at producing photons."])
def __init__(self, parent): super(QWidget, self).__init__(parent) tabs = QTabWidget() tab1 = QWidget() tab2 = QWidget() tabs.addTab(tab1, 'Tab 1') tabs.addTab(tab2, 'Tab 2') tab1_layout = QVBoxLayout() button = QPushButton('Button') tab1_layout.addWidget(button) tab1.setLayout(tab1_layout) main_layout = QVBoxLayout() main_layout.addWidget(tabs) self.setLayout(main_layout)
def __init__(self, mainwindow): """Creates the about dialog. You can simply exec_() it.""" super(AboutDialog, self).__init__(mainwindow) self.setWindowTitle(_("About {appname}").format(appname = appinfo.appname)) layout = QVBoxLayout() self.setLayout(layout) tabw = QTabWidget() layout.addWidget(tabw) tabw.addTab(About(self), _("About")) tabw.addTab(Credits(self), _("Credits")) tabw.addTab(Version(self), _("Version")) button = QDialogButtonBox(QDialogButtonBox.Ok) button.setCenterButtons(True) button.accepted.connect(self.accept) layout.addWidget(button) layout.setSizeConstraint(QLayout.SetFixedSize)
def __init__(self, file=None, parent=None): """Initialize QTabWidget with tabs for each metadata page.""" super(InformationDialog, self).__init__(parent) self.setWindowTitle('Media Information') info_icon = utilities.resource_filename('mosaic.images', 'md_info.png') self.setWindowIcon(QIcon(info_icon)) self.setFixedSize(600, 600) media_information = GeneralInformation(file) metadata_information = FullInformation(file) page = QTabWidget() page.addTab(media_information, 'General') page.addTab(metadata_information, 'Metadata') dialog_layout = QHBoxLayout() dialog_layout.addWidget(page) self.setLayout(dialog_layout)
def __init__(self, repo, parent=None): super().__init__(parent) fileInfo = QFileInfo(repo.fileName) tabWidget = QTabWidget() tabWidget.addTab(repoTab(repo), _("Repo")) tabWidget.addTab(ApplicationsTab(repo), _("Files")) tabWidget.addTab(GeneralTab(fileInfo), _("File")) buttonBox = QDialogButtonBox(QDialogButtonBox.Ok) buttonBox.accepted.connect(self.accept) buttonBox.rejected.connect(self.reject) mainLayout = QVBoxLayout() mainLayout.addWidget(tabWidget) ''' key=RepoAttributes.URL.value if (key in repo.items): self.url=repo.items[key] self.urlbtn = QCommandLinkButton( self.url) self.urlbtn.clicked.connect(self.OnUrlMessage) #mainLayout.addWidget(self.urlbtn) ''' mainLayout.addWidget(buttonBox) self.setLayout(mainLayout) self.setWindowTitle(repo.name)
def previewWidget(self): t = QTabWidget() t.setDocumentMode(True) t.setStyleSheet(""" QTabBar::tab{ background-color: #BBB; padding: 3px 25px; border: none; } QTabBar::tab:selected, QTabBar::tab:hover{ background-color:skyblue; } """) w0 = QPlainTextEdit() w0.setFrameShape(QFrame.NoFrame) w0.setReadOnly(True) w1 = QPlainTextEdit() w1.setFrameShape(QFrame.NoFrame) w1.setReadOnly(True) t.addTab(w0, qApp.translate("Export", "Markdown source")) t.addTab(w1, qApp.translate("Export", "HTML Source")) if webView: w2 = webView() t.addTab(w2, qApp.translate("Export", "HTML Output")) t.setCurrentIndex(2) return t
def __init__(self, parent, window=False): if window: super().__init__(None, Qt.Window) else: super().__init__(parent) self.setAttribute(Qt.WA_DeleteOnClose) self.parent_widget = parent main_layout = QVBoxLayout(self) tabbar = QTabWidget(self) main_layout.addWidget(tabbar) # Tags tree self.tags_tree = TagsTreeView(parent=self, app_window=self.parent_widget) self.tags_tree.setHeaderHidden(True) tabbar.addTab(self.tags_tree, 'Namespace && Tags') self.tags_layout = QVBoxLayout(self.tags_tree) if parent.manga_list_view.gallery_model.db_emitter._finished: self.setup_tags() else: parent.manga_list_view.gallery_model.db_emitter.DONE.connect(self.setup_tags) # Tags stats self.tags_stats = QListWidget(self) tabbar.addTab(self.tags_stats, 'Statistics') tabbar.setTabEnabled(1, False) # About AD self.about_db = QWidget(self) tabbar.addTab(self.about_db, 'DB Info') tabbar.setTabEnabled(2, False) self.resize(300, 600) self.setWindowTitle('DB Overview') self.setWindowIcon(QIcon(app_constants.APP_ICO_PATH))
def setupUI(self): """Create User Interface. """ mainWidget = QWidget() mainLayout = QHBoxLayout() tabs = QTabWidget() self.classes_tree_view = ClassesTreeView(self) tabs.addTab(self.widgetDataset(), self.tr("Dataset")) tabs.addTab(self.widgetTraining(), self.tr("Training")) tabs.addTab(self.widgetRecognition(), self.tr("Recognition")) leftLayout, rightLayout = QHBoxLayout(), QHBoxLayout() leftLayout.addWidget(self.classes_tree_view) rightLayout.addWidget(tabs) left, right = QWidget(), QWidget() left.setLayout(leftLayout) right.setLayout(rightLayout) self.hsplitter = QSplitter(QtCore.Qt.Horizontal) self.hsplitter.addWidget(left) self.hsplitter.addWidget(right) self.hsplitter.setStretchFactor(1, 3) mainLayout.addWidget(self.hsplitter) mainWidget.setLayout(mainLayout) self.setCentralWidget(mainWidget)
class AppWindow(QMainWindow): onRestart = pyqtSignal(name='onRestart') def __init__(self, dwarf_args, flags=None): super(AppWindow, self).__init__(flags) self.dwarf_args = dwarf_args self.session_manager = SessionManager(self) self.session_manager.sessionCreated.connect(self.session_created) self.session_manager.sessionStopped.connect(self.session_stopped) self.session_manager.sessionClosed.connect(self.session_closed) self._tab_order = [ 'memory', 'modules', 'ranges', 'jvm-inspector', 'jvm-debugger' ] self.menu = self.menuBar() self._is_newer_dwarf = False self.view_menu = None #dockwidgets self.watchers_dwidget = None self.hooks_dwiget = None self.bookmarks_dwiget = None self.registers_dock = None self.console_dock = None self.backtrace_dock = None self.threads_dock = None #panels self.asm_panel = None self.console_panel = None self.context_panel = None self.backtrace_panel = None self.contexts_list_panel = None self.data_panel = None self.emulator_panel = None self.ftrace_panel = None self.hooks_panel = None self.bookmarks_panel = None self.smali_panel = None self.java_inspector_panel = None self.java_explorer_panel = None self.java_trace_panel = None self.memory_panel = None self.modules_panel = None self.ranges_panel = None self.search_panel = None self.trace_panel = None self.watchers_panel = None self.welcome_window = None self._ui_elems = [] self.setWindowTitle( 'Dwarf - A debugger for reverse engineers, crackers and security analyst' ) # load external assets _app = QApplication.instance() self.remove_tmp_dir() # themes self.prefs = Prefs() self.set_theme(self.prefs.get('dwarf_ui_theme', 'black')) # load font if os.path.exists(utils.resource_path('assets/Anton.ttf')): QFontDatabase.addApplicationFont( utils.resource_path('assets/Anton.ttf')) if os.path.exists(utils.resource_path('assets/OpenSans-Regular.ttf')): QFontDatabase.addApplicationFont( utils.resource_path('assets/OpenSans-Regular.ttf')) _app.setFont(QFont("OpenSans", 9, QFont.Normal)) if os.path.exists(utils.resource_path('assets/OpenSans-Bold.ttf')): QFontDatabase.addApplicationFont( utils.resource_path('assets/OpenSans-Bold.ttf')) # mainwindow statusbar self.progressbar = QProgressBar() self.progressbar.setRange(0, 0) self.progressbar.setVisible(False) self.progressbar.setFixedHeight(15) self.progressbar.setFixedWidth(100) self.progressbar.setTextVisible(False) self.progressbar.setValue(30) self.statusbar = QStatusBar(self) self.statusbar.setAutoFillBackground(False) self.statusbar.addPermanentWidget(self.progressbar) self.statusbar.setObjectName("statusbar") self.setStatusBar(self.statusbar) self.main_tabs = QTabWidget(self) self.main_tabs.setMovable(False) self.main_tabs.setTabsClosable(True) self.main_tabs.setAutoFillBackground(True) self.main_tabs.tabCloseRequested.connect(self._on_close_tab) self.setCentralWidget(self.main_tabs) if self.dwarf_args.package is None: self.welcome_window = WelcomeDialog(self) self.welcome_window.setModal(True) self.welcome_window.onIsNewerVersion.connect( self._enable_update_menu) self.welcome_window.onUpdateComplete.connect( self._on_dwarf_updated) self.welcome_window.setWindowTitle( 'Welcome to Dwarf - A debugger for reverse engineers, crackers and security analyst' ) self.welcome_window.onSessionSelected.connect(self._start_session) self.welcome_window.onSessionRestore.connect(self._restore_session) # wait for welcome screen self.hide() self.welcome_window.show() else: if dwarf_args.package is not None: if dwarf_args.type is None: # no device given check if package is local path if os.path.exists(dwarf_args.package): print('* Starting new LocalSession') self._start_session('local') else: print('use -t to set sessiontype') exit(0) else: print('* Starting new Session') self._start_session(dwarf_args.type) def _setup_main_menu(self): self.menu = self.menuBar() dwarf_menu = QMenu('Dwarf', self) theme = QMenu('Theme', dwarf_menu) theme.addAction('Black') theme.addAction('Dark') theme.addAction('Light') theme.triggered.connect(self._set_theme) dwarf_menu.addMenu(theme) dwarf_menu.addSeparator() if self._is_newer_dwarf: dwarf_menu.addAction('Update', self._update_dwarf) dwarf_menu.addAction('Close', self.session_manager.session.stop) self.menu.addMenu(dwarf_menu) session = self.session_manager.session if session is not None: session_menu = session.main_menu if isinstance(session_menu, list): for menu in session_menu: self.menu.addMenu(menu) else: self.menu.addMenu(session_menu) self.view_menu = QMenu('View', self) subview_menu = QMenu('Subview', self.view_menu) subview_menu.addAction('Search', lambda: self.show_main_tab('search'), shortcut=QKeySequence(Qt.CTRL + Qt.Key_F3)) subview_menu.addAction('Emulator', lambda: self.show_main_tab('emulator'), shortcut=QKeySequence(Qt.CTRL + Qt.Key_F2)) subview_menu.addAction('Disassembly', lambda: self.show_main_tab('disassembly'), shortcut=QKeySequence(Qt.CTRL + Qt.Key_F5)) self.view_menu.addMenu(subview_menu) self.view_menu.addSeparator() self.menu.addMenu(self.view_menu) if self.dwarf_args.debug_script: debug_menu = QMenu('Debug', self) debug_menu.addAction('Reload core', self._menu_reload_core) debug_menu.addAction('Debug dwarf js core', self._menu_debug_dwarf_js) self.menu.addMenu(debug_menu) about_menu = QMenu('About', self) about_menu.addAction('Dwarf on GitHub', self._menu_github) about_menu.addAction('Documention', self._menu_documentation) about_menu.addAction('Api', self._menu_api) about_menu.addAction('Slack', self._menu_slack) about_menu.addSeparator() about_menu.addAction('Info', self._show_about_dlg) self.menu.addMenu(about_menu) def _enable_update_menu(self): self._is_newer_dwarf = True def _update_dwarf(self): if self.welcome_window: self.welcome_window._update_dwarf() def _on_close_tab(self, index): tab_text = self.main_tabs.tabText(index) if tab_text: if tab_text.lower() in self.session_manager.session.non_closable: return try: self._ui_elems.remove(tab_text.lower()) except ValueError: # recheck ValueError: list.remove(x): x not in list pass self.main_tabs.removeTab(index) def _handle_tab_change(self): for index in range(self.main_tabs.count()): tab_name = self.main_tabs.tabText(index).lower().replace(' ', '-') if tab_name in self.session_manager.session.non_closable: self.main_tabs.tabBar().setTabButton(index, QTabBar.RightSide, None) if tab_name in self._tab_order: should_index = self._tab_order.index(tab_name) if index != should_index: self.main_tabs.tabBar().moveTab(index, should_index) def _on_dwarf_updated(self): self.onRestart.emit() def remove_tmp_dir(self): if os.path.exists('.tmp'): shutil.rmtree('.tmp', ignore_errors=True) def _set_theme(self, qaction): if qaction: self.set_theme(qaction.text()) def _menu_reload_core(self): self.dwarf.load_script() def _menu_debug_dwarf_js(self): you_know_what_to_do = json.loads( self.dwarf._script.exports.debugdwarfjs()) return you_know_what_to_do def show_main_tab(self, name): # elem doesnt exists? create it if name not in self._ui_elems: self._create_ui_elem(name) index = 0 name = name.join(name.split()).lower() if name == 'memory': index = self.main_tabs.indexOf(self.memory_panel) elif name == 'ranges': index = self.main_tabs.indexOf(self.ranges_panel) elif name == 'search': index = self.main_tabs.indexOf(self.search_panel) elif name == 'modules': index = self.main_tabs.indexOf(self.modules_panel) elif name == 'disassembly': index = self.main_tabs.indexOf(self.asm_panel) elif name == 'trace': index = self.main_tabs.indexOf(self.trace_panel) elif name == 'data': index = self.main_tabs.indexOf(self.data_panel) elif name == 'emulator': index = self.main_tabs.indexOf(self.emulator_panel) elif name == 'java-trace': index = self.main_tabs.indexOf(self.java_trace_panel) elif name == 'jvm-inspector': index = self.main_tabs.indexOf(self.java_inspector_panel) elif name == 'jvm-debugger': index = self.main_tabs.indexOf(self.java_explorer_panel) elif name == 'smali': index = self.main_tabs.indexOf(self.smali_panel) self.main_tabs.setCurrentIndex(index) def jump_to_address(self, ptr, show_panel=True): if self.memory_panel is not None: if show_panel: self.show_main_tab('memory') self.memory_panel.read_memory(ptr) @pyqtSlot(name='mainMenuGitHub') def _menu_github(self): QDesktopServices.openUrl(QUrl('https://github.com/iGio90/Dwarf')) @pyqtSlot(name='mainMenuDocumentation') def _menu_api(self): QDesktopServices.openUrl(QUrl('https://igio90.github.io/Dwarf/')) @pyqtSlot(name='mainMenuApi') def _menu_documentation(self): QDesktopServices.openUrl(QUrl('https://igio90.github.io/Dwarf/api')) @pyqtSlot(name='mainMenuSlack') def _menu_slack(self): QDesktopServices.openUrl( QUrl('https://join.slack.com/t/resecret/shared_invite' '/enQtMzc1NTg4MzE3NjA1LTlkNzYxNTIwYTc2ZTYyOWY1MT' 'Q1NzBiN2ZhYjQwYmY0ZmRhODQ0NDE3NmRmZjFiMmE1MDYwN' 'WJlNDVjZDcwNGE')) def _show_about_dlg(self): about_dlg = AboutDialog(self) about_dlg.show() def _create_ui_elem(self, elem): if not isinstance(elem, str): return if elem not in self._ui_elems: self._ui_elems.append(elem) if elem == 'watchers': from ui.panel_watchers import WatchersPanel self.watchers_dwidget = QDockWidget('Watchers', self) self.watchers_panel = WatchersPanel(self) # dont respond to dblclick mem cant be shown # self.watchers_panel.onItemDoubleClicked.connect( # self._on_watcher_clicked) self.watchers_panel.onItemRemoved.connect( self._on_watcher_removeditem) self.watchers_panel.onItemAdded.connect(self._on_watcher_added) self.watchers_dwidget.setWidget(self.watchers_panel) self.watchers_dwidget.setObjectName('WatchersPanel') self.addDockWidget(Qt.LeftDockWidgetArea, self.watchers_dwidget) self.view_menu.addAction(self.watchers_dwidget.toggleViewAction()) elif elem == 'hooks': from ui.panel_hooks import HooksPanel self.hooks_dwiget = QDockWidget('Breakpoints', self) self.hooks_panel = HooksPanel(self) self.hooks_panel.onShowMemoryRequest.connect( self._on_watcher_clicked) self.hooks_panel.onHookRemoved.connect(self._on_hook_removed) self.hooks_dwiget.setWidget(self.hooks_panel) self.hooks_dwiget.setObjectName('HooksPanel') self.addDockWidget(Qt.LeftDockWidgetArea, self.hooks_dwiget) self.view_menu.addAction(self.hooks_dwiget.toggleViewAction()) elif elem == 'bookmarks': from ui.panel_bookmarks import BookmarksPanel self.bookmarks_dwiget = QDockWidget('Boomarks', self) self.bookmarks_panel = BookmarksPanel(self) self.bookmarks_panel.onShowMemoryRequest.connect( self._on_watcher_clicked) self.bookmarks_dwiget.setWidget(self.bookmarks_panel) self.bookmarks_dwiget.setObjectName('BookmarksPanel') self.addDockWidget(Qt.LeftDockWidgetArea, self.bookmarks_dwiget) self.view_menu.addAction(self.bookmarks_dwiget.toggleViewAction()) elif elem == 'registers': from ui.panel_context import ContextPanel self.registers_dock = QDockWidget('Context', self) self.context_panel = ContextPanel(self) self.registers_dock.setWidget(self.context_panel) self.registers_dock.setObjectName('ContextsPanel') self.addDockWidget(Qt.RightDockWidgetArea, self.registers_dock) self.view_menu.addAction(self.registers_dock.toggleViewAction()) elif elem == 'memory': from ui.panel_memory import MemoryPanel self.memory_panel = MemoryPanel(self) self.memory_panel.onShowDisassembly.connect( self._disassemble_range) self.memory_panel.dataChanged.connect(self._on_memory_modified) self.memory_panel.statusChanged.connect(self.set_status_text) self.main_tabs.addTab(self.memory_panel, 'Memory') elif elem == 'jvm-debugger': from ui.panel_java_explorer import JavaExplorerPanel self.java_explorer_panel = JavaExplorerPanel(self) self.main_tabs.addTab(self.java_explorer_panel, 'JVM debugger') self.main_tabs.tabBar().moveTab( self.main_tabs.indexOf(self.java_explorer_panel), 1) elif elem == 'jvm-inspector': from ui.panel_java_inspector import JavaInspector self.java_inspector_panel = JavaInspector(self) self.main_tabs.addTab(self.java_inspector_panel, 'JVM inspector') elif elem == 'console': from ui.panel_console import ConsolePanel self.console_dock = QDockWidget('Console', self) self.console_panel = ConsolePanel(self) self.dwarf.onLogToConsole.connect(self._log_js_output) self.console_dock.setWidget(self.console_panel) self.console_dock.setObjectName('ConsolePanel') self.addDockWidget(Qt.BottomDockWidgetArea, self.console_dock) self.view_menu.addAction(self.console_dock.toggleViewAction()) elif elem == 'backtrace': from ui.panel_backtrace import BacktracePanel self.backtrace_dock = QDockWidget('Backtrace', self) self.backtrace_panel = BacktracePanel(self) self.backtrace_dock.setWidget(self.backtrace_panel) self.backtrace_dock.setObjectName('BacktracePanel') self.backtrace_panel.onShowMemoryRequest.connect( self._on_watcher_clicked) self.addDockWidget(Qt.RightDockWidgetArea, self.backtrace_dock) self.view_menu.addAction(self.backtrace_dock.toggleViewAction()) elif elem == 'threads': from ui.panel_contexts_list import ContextsListPanel self.threads_dock = QDockWidget('Threads', self) self.contexts_list_panel = ContextsListPanel(self) self.dwarf.onThreadResumed.connect( self.contexts_list_panel.resume_tid) self.contexts_list_panel.onItemDoubleClicked.connect( self._manually_apply_context) self.threads_dock.setWidget(self.contexts_list_panel) self.threads_dock.setObjectName('ThreadPanel') self.addDockWidget(Qt.RightDockWidgetArea, self.threads_dock) self.view_menu.addAction(self.threads_dock.toggleViewAction()) elif elem == 'modules': from ui.panel_modules import ModulesPanel self.modules_panel = ModulesPanel(self) self.modules_panel.onModuleSelected.connect( self._on_module_dblclicked) self.modules_panel.onModuleFuncSelected.connect( self._on_modulefunc_dblclicked) self.modules_panel.onAddHook.connect(self._on_addmodule_hook) self.modules_panel.onDumpBinary.connect(self._on_dumpmodule) self.main_tabs.addTab(self.modules_panel, 'Modules') elif elem == 'ranges': from ui.panel_ranges import RangesPanel self.ranges_panel = RangesPanel(self) self.ranges_panel.onItemDoubleClicked.connect( self._range_dblclicked) self.ranges_panel.onDumpBinary.connect(self._on_dumpmodule) # connect to watcherpanel func self.ranges_panel.onAddWatcher.connect( self.watchers_panel.do_addwatcher_dlg) self.main_tabs.addTab(self.ranges_panel, 'Ranges') elif elem == 'search': from ui.panel_search import SearchPanel self.search_panel = SearchPanel(self) self.search_panel.onShowMemoryRequest.connect( self._on_watcher_clicked) self.main_tabs.addTab(self.search_panel, 'Search') elif elem == 'data': from ui.panel_data import DataPanel self.data_panel = DataPanel(self) self.main_tabs.addTab(self.data_panel, 'Data') elif elem == 'trace': from ui.panel_trace import TracePanel self.trace_panel = TracePanel(self) self.main_tabs.addTab(self.trace_panel, 'Trace') elif elem == 'disassembly': from ui.widgets.disasm_view import DisassemblyView self.asm_panel = DisassemblyView(self) self.asm_panel.onShowMemoryRequest.connect(self._on_disasm_showmem) self.main_tabs.addTab(self.asm_panel, 'Disassembly') elif elem == 'emulator': from ui.panel_emulator import EmulatorPanel self.emulator_panel = EmulatorPanel(self) self.main_tabs.addTab(self.emulator_panel, 'Emulator') elif elem == 'java-trace': from ui.panel_java_trace import JavaTracePanel self.java_trace_panel = JavaTracePanel(self) self.main_tabs.addTab(self.java_trace_panel, 'JVM tracer') elif elem == 'smali': from ui.panel_smali import SmaliPanel self.smali_panel = SmaliPanel() self.main_tabs.addTab(self.smali_panel, 'Smali') else: print('no handler for elem: ' + elem) # make tabs unclosable and sort self._handle_tab_change() # TODO: remove add @2x for item in self.findChildren(QDockWidget): if item: if 'darwin' in sys.platform: item.setStyleSheet( 'QDockWidget::title { padding-left:-30px; } QDockWidget::close-button, QDockWidget::float-button { width: 10px; height:10px }' ) def set_theme(self, theme): if theme: theme = theme.replace(os.pardir, '').replace('.', '') theme = theme.join(theme.split()).lower() theme_style = 'assets/' + theme + '_style.qss' if not os.path.exists(utils.resource_path(theme_style)): return self.prefs.put('dwarf_ui_theme', theme) try: _app = QApplication.instance() with open(theme_style) as stylesheet: _app.setStyleSheet(_app.styleSheet() + '\n' + stylesheet.read()) except Exception as e: pass # err = self.dwarf.spawn(dwarf_args.package, dwarf_args.script) def set_status_text(self, txt): self.statusbar.showMessage(txt) # ************************************************************************ # **************************** Properties ******************************** # ************************************************************************ @property def disassembly(self): return self.asm_panel @property def backtrace(self): return self.backtrace_panel @property def console(self): return self.console_panel @property def context(self): return self.context_panel @property def threads(self): return self.contexts_list_panel @property def emulator(self): return self.emulator_panel @property def ftrace(self): return self.ftrace_panel @property def hooks(self): return self.hooks_panel @property def java_inspector(self): return self.java_inspector_panel @property def java_explorer(self): return self.java_explorer_panel @property def memory(self): return self.memory_panel @property def modules(self): return self.memory_panel @property def ranges(self): return self.ranges_panel @property def trace(self): return self.trace_panel @property def watchers(self): return self.watchers_panel @property def dwarf(self): if self.session_manager.session is not None: return self.session_manager.session.dwarf else: return None # ************************************************************************ # **************************** Handlers ********************************** # ************************************************************************ # session handlers def _start_session(self, session_type, session_data=None): if self.welcome_window is not None: self.welcome_window.close() self.session_manager.create_session(session_type, session_data=session_data) def _restore_session(self, session_data): if 'session' in session_data: session_type = session_data['session'] self._start_session(session_type, session_data=session_data) def session_created(self): # session init done create ui for it session = self.session_manager.session self._setup_main_menu() for ui_elem in session.session_ui_sections: ui_elem = ui_elem.join(ui_elem.split()).lower() self._create_ui_elem(ui_elem) self.dwarf.onAttached.connect(self._on_attached) self.dwarf.onScriptLoaded.connect(self._on_script_loaded) # hookup self.dwarf.onSetRanges.connect(self._on_setranges) self.dwarf.onSetModules.connect(self._on_setmodules) self.dwarf.onAddNativeHook.connect(self._on_add_hook) self.dwarf.onApplyContext.connect(self._apply_context) self.dwarf.onThreadResumed.connect(self.on_tid_resumed) self.dwarf.onTraceData.connect(self._on_tracer_data) self.dwarf.onSetData.connect(self._on_set_data) self.session_manager.start_session(self.dwarf_args) q_settings = QSettings("dwarf_window_pos.ini", QSettings.IniFormat) ui_state = q_settings.value('dwarf_ui_state') if ui_state: self.restoreGeometry(ui_state) window_state = q_settings.value('dwarf_ui_window', self.saveState()) if window_state: self.restoreState(window_state) self.showMaximized() def session_stopped(self): self.remove_tmp_dir() self.menu.clear() self.main_tabs.clear() # actually we need to kill this. needs a refactor if self.java_trace_panel is not None: self.java_trace_panel = None for elem in self._ui_elems: if elem == 'watchers': self.watchers_panel.clear_list() self.watchers_panel.close() self.watchers_panel = None self.removeDockWidget(self.watchers_dwidget) self.watchers_dwidget = None elif elem == 'hooks': self.hooks_panel.close() self.hooks_panel = None self.removeDockWidget(self.hooks_dwiget) self.hooks_dwiget = None elif elem == 'registers': self.context_panel.close() self.context_panel = None self.removeDockWidget(self.registers_dock) self.registers_dock = None elif elem == 'memory': self.memory_panel.close() self.memory_panel = None self.main_tabs.removeTab(0) # self.main_tabs elif elem == 'jvm-debugger': self.java_explorer_panel.close() self.java_explorer_panel = None self.removeDockWidget(self.watchers_dwidget) elif elem == 'console': self.console_panel.close() self.console_panel = None self.removeDockWidget(self.console_dock) self.console_dock = None elif elem == 'backtrace': self.backtrace_panel.close() self.backtrace_panel = None self.removeDockWidget(self.backtrace_dock) elif elem == 'threads': self.contexts_list_panel.close() self.contexts_list_panel = None self.removeDockWidget(self.threads_dock) self.threads_dock = None elif elem == 'bookmarks': self.bookmarks_panel.close() self.bookmarks_panel = None self.removeDockWidget(self.bookmarks_dwiget) self.bookmarks_dwiget = None def session_closed(self): self._ui_elems = [] self.hide() if self.welcome_window is not None: self.welcome_window.exec() # close if it was a commandline session if self.welcome_window is None: if self.dwarf_args.package: self.close() # ui handler def closeEvent(self, event): """ Window closed save stuff or whatever at exit detaches dwarf """ # save windowstuff q_settings = QSettings("dwarf_window_pos.ini", QSettings.IniFormat) q_settings.setValue('dwarf_ui_state', self.saveGeometry()) q_settings.setValue('dwarf_ui_window', self.saveState()) if self.dwarf: self.dwarf.detach() super().closeEvent(event) def _on_watcher_clicked(self, ptr): """ Address in Watcher/Hookpanel was clicked show Memory """ if '.' in ptr: # java_hook file_path = ptr.replace('.', os.path.sep) if os.path.exists('.tmp/smali/' + file_path + '.smali'): if self.smali_panel is None: self._create_ui_elem('smali') self.smali_panel.set_file('.tmp/smali/' + file_path + '.smali') self.show_main_tab('smali') else: self.memory_panel.read_memory(ptr=ptr) self.show_main_tab('memory') def _on_disasm_showmem(self, ptr, length): """ Address in Disasm was clicked adds temphighlight for bytes from current instruction """ self.memory_panel.read_memory(ptr) self.memory_panel.add_highlight( HighLight('attention', utils.parse_ptr(ptr), length)) self.show_main_tab('memory') def _on_watcher_added(self, ptr): """ Watcher Entry was added """ try: # set highlight self.memory_panel.add_highlight( HighLight('watcher', ptr, self.dwarf.pointer_size)) except HighlightExistsError: pass def _on_watcher_removeditem(self, ptr): """ Watcher Entry was removed remove highlight too """ self.memory_panel.remove_highlight(ptr) def _on_module_dblclicked(self, data): """ Module in ModulePanel was doubleclicked """ addr, size = data addr = utils.parse_ptr(addr) size = int(size, 10) self.memory_panel.read_memory(ptr=addr, length=size) self.show_main_tab('Memory') def _on_modulefunc_dblclicked(self, ptr): """ Function in ModulePanel was doubleclicked """ ptr = utils.parse_ptr(ptr) self.memory_panel.read_memory(ptr=ptr) self.show_main_tab('Memory') def _on_dumpmodule(self, data): """ DumpBinary MenuItem in ModulePanel was selected """ ptr, size = data ptr = utils.parse_ptr(ptr) size = int(size, 10) self.dwarf.dump_memory(ptr=ptr, length=size) def _disassemble_range(self, mem_range): """ Disassemble MenuItem in Hexview was selected """ if mem_range: if self.asm_panel is None: self._create_ui_elem('disassembly') if mem_range: self.asm_panel.disassemble(mem_range) self.show_main_tab('disassembly') def _range_dblclicked(self, ptr): """ Range in RangesPanel was doubleclicked """ ptr = utils.parse_ptr(ptr) self.memory_panel.read_memory(ptr=ptr) self.show_main_tab('Memory') # dwarf handlers def _log_js_output(self, output): if self.console_panel is not None: self.console_panel.get_js_console().log(output) def _on_setranges(self, ranges): """ Dwarf wants to set Ranges only hooked up to switch tab or create ui its connected in panel after creation """ if self.ranges_panel is None: self.show_main_tab('ranges') # forward only now to panel it connects after creation self.ranges_panel.set_ranges(ranges) def _on_setmodules(self, modules): """ Dwarf wants to set Modules only hooked up to switch tab or create ui its connected in panel after creation """ if self.modules_panel is None: self._create_ui_elem('modules') self.modules_panel.set_modules(modules) if self.modules_panel is not None: self.show_main_tab('modules') def _manually_apply_context(self, context): """ perform additional operation if the context has been manually applied from the context list """ self._apply_context(context, manual=True) def _apply_context(self, context, manual=False): # update current context tid # this should be on top as any further api from js needs to be executed on that thread is_initial_hook = context['reason'] >= 0 if manual or (self.dwarf.context_tid and not is_initial_hook): self.dwarf.context_tid = context['tid'] if 'context' in context: if not manual: self.threads.add_context(context) is_java = context['is_java'] if is_java: if self.java_explorer_panel is None: self._create_ui_elem('jvm-debugger') self.context_panel.set_context(context['ptr'], 1, context['context']) self.java_explorer_panel._set_handle_arg(-1) self.show_main_tab('jvm-debugger') else: self.context_panel.set_context(context['ptr'], 0, context['context']) if 'pc' in context['context']: if not 'disassembly' in self._ui_elems: from lib.range import Range _range = Range(Range.SOURCE_TARGET, self.dwarf) _range.init_with_address( int(context['context']['pc']['value'], 16)) self._disassemble_range(_range) if 'backtrace' in context: self.backtrace_panel.set_backtrace(context['backtrace']) def _on_add_hook(self, hook): try: # set highlight ptr = hook.get_ptr() ptr = utils.parse_ptr(ptr) self.memory_panel.add_highlight( HighLight('hook', ptr, self.dwarf.pointer_size)) except HighlightExistsError: pass def _on_hook_removed(self, ptr): ptr = utils.parse_ptr(ptr) self.memory_panel.remove_highlight(ptr) def _on_addmodule_hook(self, data): ptr, name = data self.dwarf.hook_native(ptr, own_input=name) def on_tid_resumed(self, tid): if self.dwarf: if self.dwarf.context_tid == tid: # clear backtrace if 'backtrace' in self._ui_elems: if self.backtrace_panel is not None: self.backtrace_panel.clear() # remove thread if 'threads' in self._ui_elems: if self.contexts_list_panel is not None: self.contexts_list_panel.resume_tid(tid) # clear registers if 'registers' in self._ui_elems: if self.context_panel is not None: self.context_panel.clear() # clear jvm explorer if 'jvm-debugger' in self._ui_elems: if self.java_explorer_panel is not None: self.java_explorer_panel.clear_panel() # invalidate dwarf context tid self.dwarf.context_tid = 0 def _on_tracer_data(self, data): if not data: return if self.trace_panel is None: self._create_ui_elem('trace') if self.trace_panel is not None: self.show_main_tab('Trace') self.trace_panel.start() trace_events_parts = data[1].split(',') while trace_events_parts: trace_event = TraceEvent(trace_events_parts.pop(0), trace_events_parts.pop(0), trace_events_parts.pop(0), trace_events_parts.pop(0)) self.trace_panel.event_queue.append(trace_event) def _on_set_data(self, data): if not isinstance(data, list): return if self.data_panel is None: self._create_ui_elem('data') if self.data_panel is not None: self.show_main_tab('Data') self.data_panel.append_data(data[0], data[1], data[2]) def show_progress(self, text): self.progressbar.setVisible(True) self.set_status_text(text) def hide_progress(self): self.progressbar.setVisible(False) self.set_status_text('') def _on_attached(self, data): self.setWindowTitle('Dwarf - Attached to %s (%s)' % (data[1], data[0])) def _on_script_loaded(self): # restore the loaded session if any self.session_manager.restore_session() def _on_memory_modified(self, pos, length): data_pos = self.memory_panel.base + pos data = self.memory_panel.data[pos:pos + length] data = [data[0]] # todo: strange js part if self.dwarf.dwarf_api('writeBytes', [data_pos, data]): pass else: utils.show_message_box('Failed to write Memory') def on_add_bookmark(self, ptr): """ provide ptr as int """ if self.bookmarks_panel is not None: self.bookmarks_panel._create_bookmark(ptr=hex(ptr))
class mainWindow(QMainWindow): """ Main window of openlavaMonitor. """ def __init__(self): super().__init__() self.myDrawCurve = bmonitor.drawCurve() self.freshMark = False self.initUI() def initUI(self): """ Main process, draw the main graphic frame. """ self.queueList = openlava_common.getQueueList() self.hostList = openlava_common.getHostList() # Add menubar. if not self.freshMark: self.genMenubar() # Define main Tab widget self.mainTab = QTabWidget(self) self.setCentralWidget(self.mainTab) # Define four sub-tabs (JOB/JOBS/HOSTS/QUEUES) self.jobTab = QWidget() self.jobsTab = QWidget() self.hostsTab = QWidget() self.queuesTab = QWidget() # Add the sub-tabs into main Tab widget self.mainTab.addTab(self.jobTab, 'JOB') self.mainTab.addTab(self.jobsTab, 'JOBS') self.mainTab.addTab(self.hostsTab, 'HOSTS') self.mainTab.addTab(self.queuesTab, 'QUEUES') # Generate the sub-tabs self.genJobTab() self.genJobsTab() self.genHostsTab() self.genQueuesTab() # Show main window self.resize(1111, 620) pyqt5_common.centerWindow(self) self.setWindowTitle('openlavaMonitor') def genMenubar(self): """ Generate menubar. """ menubar = self.menuBar() # File exitAction = QAction('Quit', self) exitAction.triggered.connect(qApp.quit) fileMenu = menubar.addMenu('File') fileMenu.addAction(exitAction) # Setup freshAction = QAction('Fresh', self) freshAction.triggered.connect(self.fresh) setupMenu = menubar.addMenu('Setup') setupMenu.addAction(freshAction) def fresh(self): print('* Re-Loading openlava status, please wait a moment ...') self.freshMark = True self.initUI() ## Common sub-functions (begin) ## def guiWarning(self, warningMessage): """ Show the specified warning message on both of command line and GUI window. """ common.printWarning(warningMessage) QMessageBox.warning(self, 'openlavaMonitor Warning', warningMessage) ## Common sub-functions (end) ## ## For job TAB (begin) ## def genJobTab(self): """ Generate the job tab on openlavaMonitor GUI, show job informations. """ # Init var self.currentJob = '' self.jobInfoDic = {} # self.jobTab self.jobTabFrame0 = QFrame(self.jobTab) self.jobTabFrame1 = QFrame(self.jobTab) self.jobTabFrame2 = QFrame(self.jobTab) self.jobTabFrame3 = QFrame(self.jobTab) self.jobTabFrame0.setFrameShadow(QFrame.Raised) self.jobTabFrame0.setFrameShape(QFrame.Box) self.jobTabFrame1.setFrameShadow(QFrame.Raised) self.jobTabFrame1.setFrameShape(QFrame.Box) self.jobTabFrame2.setFrameShadow(QFrame.Raised) self.jobTabFrame2.setFrameShape(QFrame.Box) self.jobTabFrame3.setFrameShadow(QFrame.Raised) self.jobTabFrame3.setFrameShape(QFrame.Box) # self.jobTab - Grid jobTabGrid = QGridLayout() jobTabGrid.addWidget(self.jobTabFrame0, 0, 0) jobTabGrid.addWidget(self.jobTabFrame1, 1, 0) jobTabGrid.addWidget(self.jobTabFrame2, 2, 0, 1, 2) jobTabGrid.addWidget(self.jobTabFrame3, 0, 1, 2, 1) jobTabGrid.setRowStretch(0, 1) jobTabGrid.setRowStretch(1, 1) jobTabGrid.setRowStretch(2, 10) jobTabGrid.setColumnStretch(0, 1) jobTabGrid.setColumnStretch(1, 10) jobTabGrid.setColumnMinimumWidth(0, 250) jobTabGrid.setColumnMinimumWidth(1, 500) self.jobTab.setLayout(jobTabGrid) # Generate sub-frames self.genJobTabFrame0() self.genJobTabFrame1() self.genJobTabFrame2() self.genJobTabFrame3() def genJobTabFrame0(self): # self.jobTabFrame0 jobTabJobLabel = QLabel(self.jobTabFrame0) jobTabJobLabel.setText('Job') self.jobTabJobLine = QLineEdit() jobTabCheckButton = QPushButton('Check', self.jobTabFrame0) jobTabCheckButton.clicked.connect(self.checkJob) # self.jobTabFrame0 - Grid jobTabFrame0Grid = QGridLayout() jobTabFrame0Grid.addWidget(jobTabJobLabel, 0, 0) jobTabFrame0Grid.addWidget(self.jobTabJobLine, 0, 1) jobTabFrame0Grid.addWidget(jobTabCheckButton, 0, 2) self.jobTabFrame0.setLayout(jobTabFrame0Grid) def genJobTabFrame1(self): # self.jobTabFrame1 jobTabUserLabel = QLabel('User', self.jobTabFrame1) self.jobTabUserLine = QLineEdit() jobTabStatusLabel = QLabel('Status', self.jobTabFrame1) self.jobTabStatusLine = QLineEdit() jobTabQueueLabel = QLabel('Queue', self.jobTabFrame1) self.jobTabQueueLine = QLineEdit() jobTabStartedOnLabel = QLabel('Host', self.jobTabFrame1) self.jobTabStartedOnLine = QLineEdit() jobTabProjectLabel = QLabel('Project', self.jobTabFrame1) self.jobTabProjectLine = QLineEdit() jobTabProcessorsRequestedLabel = QLabel('Processors', self.jobTabFrame1) self.jobTabProcessorsRequestedLine = QLineEdit() jobTabCpuTimeLabel = QLabel('Cpu Time', self.jobTabFrame1) self.jobTabCpuTimeLine = QLineEdit() jobTabRusageMemLabel = QLabel('Rusage', self.jobTabFrame1) self.jobTabRusageMemLine = QLineEdit() jobTabMemLabel = QLabel('Mem', self.jobTabFrame1) self.jobTabMemLine = QLineEdit() # self.jobTabFrame1 - Grid jobTabFrame1Grid = QGridLayout() jobTabFrame1Grid.addWidget(jobTabUserLabel, 0, 0) jobTabFrame1Grid.addWidget(self.jobTabUserLine, 0, 1) jobTabFrame1Grid.addWidget(jobTabStatusLabel, 1, 0) jobTabFrame1Grid.addWidget(self.jobTabStatusLine, 1, 1) jobTabFrame1Grid.addWidget(jobTabQueueLabel, 2, 0) jobTabFrame1Grid.addWidget(self.jobTabQueueLine, 2, 1) jobTabFrame1Grid.addWidget(jobTabStartedOnLabel, 3, 0) jobTabFrame1Grid.addWidget(self.jobTabStartedOnLine, 3, 1) jobTabFrame1Grid.addWidget(jobTabProjectLabel, 4, 0) jobTabFrame1Grid.addWidget(self.jobTabProjectLine, 4, 1) jobTabFrame1Grid.addWidget(jobTabProcessorsRequestedLabel, 5, 0) jobTabFrame1Grid.addWidget(self.jobTabProcessorsRequestedLine, 5, 1) jobTabFrame1Grid.addWidget(jobTabCpuTimeLabel, 6, 0) jobTabFrame1Grid.addWidget(self.jobTabCpuTimeLine, 6, 1) jobTabFrame1Grid.addWidget(jobTabRusageMemLabel, 7, 0) jobTabFrame1Grid.addWidget(self.jobTabRusageMemLine, 7, 1) jobTabFrame1Grid.addWidget(jobTabMemLabel, 8, 0) jobTabFrame1Grid.addWidget(self.jobTabMemLine, 8, 1) self.jobTabFrame1.setLayout(jobTabFrame1Grid) def genJobTabFrame2(self): # self.jobTabFrame2 self.jobTabJobInfoText = QTextEdit(self.jobTabFrame2) # self.jobTabFrame2 - Grid jobTabFrame2Grid = QGridLayout() jobTabFrame2Grid.addWidget(self.jobTabJobInfoText, 0, 0) self.jobTabFrame2.setLayout(jobTabFrame2Grid) def genJobTabFrame3(self): # self.jobTabFram3 self.jobTabMemCurveLabel = QLabel('Job memory curve', self.jobTabFrame3) self.jobTabMemCurveLabel.setAlignment(Qt.AlignCenter) # self.jobTabFram3 - Grid jobTabFrame3Grid = QGridLayout() jobTabFrame3Grid.addWidget(self.jobTabMemCurveLabel, 0, 0) self.jobTabFrame3.setLayout(jobTabFrame3Grid) def checkJob(self): """ Get job information with "bjobs -UF <jobId>", save the infomation into dict self.jobInfoDic. Update self.jobTabFrame1 and self.jobTabFrame3. """ self.currentJob = self.jobTabJobLine.text().strip() print('* Checking job "' + str(self.currentJob) + '".') # Initicalization self.updateJobTabFrame1(init=True) self.updateJobTabFrame2(init=True) self.updateJobTabFrame3(init=True) # Job name must be a string of numbers. if not re.match('^[0-9]+$', self.currentJob): warningMessage = '*Warning*: No valid job is specified!' self.guiWarning(warningMessage) return # Get job info print('Getting job information for job "' + str(self.currentJob) + '".') self.jobInfoDic = openlava_common.getBjobsUfInfo(command='bjobs -UF ' + str(self.currentJob)) # Update the related frames with the job info. self.updateJobTabFrame1() self.updateJobTabFrame2() self.updateJobTabFrame3() def updateJobTabFrame1(self, init=False): """ Update self.jobTabFrame1 with job infos. """ # For "User" item. if init: self.jobTabUserLine.setText('') else: self.jobTabUserLine.setText(self.jobInfoDic[self.currentJob]['user']) self.jobTabUserLine.setCursorPosition(0) # For "Status" item. if init: self.jobTabStatusLine.setText('') else: self.jobTabStatusLine.setText(self.jobInfoDic[self.currentJob]['status']) self.jobTabStatusLine.setCursorPosition(0) # For "Queue" item. if init: self.jobTabQueueLine.setText('') else: self.jobTabQueueLine.setText(self.jobInfoDic[self.currentJob]['queue']) self.jobTabQueueLine.setCursorPosition(0) # For "Host" item. if init: self.jobTabStartedOnLine.setText('') else: self.jobTabStartedOnLine.setText(self.jobInfoDic[self.currentJob]['startedOn']) self.jobTabStartedOnLine.setCursorPosition(0) # For "Processors" item. if init: self.jobTabProcessorsRequestedLine.setText('') else: self.jobTabProcessorsRequestedLine.setText(self.jobInfoDic[self.currentJob]['processorsRequested']) self.jobTabProcessorsRequestedLine.setCursorPosition(0) # For "Cpu Time" item. if init: self.jobTabCpuTimeLine.setText('') else: if self.jobInfoDic[self.currentJob]['cpuTime'] != '': self.jobTabCpuTimeLine.setText(self.jobInfoDic[self.currentJob]['cpuTime'] + ' s') self.jobTabCpuTimeLine.setCursorPosition(0) # For "Project" item. if init: self.jobTabProjectLine.setText('') else: self.jobTabProjectLine.setText(self.jobInfoDic[self.currentJob]['project']) self.jobTabProjectLine.setCursorPosition(0) # For "Rusage" item. if init: self.jobTabRusageMemLine.setText('') else: if self.jobInfoDic[self.currentJob]['rusageMem'] != '': self.jobTabRusageMemLine.setText(self.jobInfoDic[self.currentJob]['rusageMem'] + ' M') self.jobTabRusageMemLine.setCursorPosition(0) # For "Mem" item. if init: self.jobTabMemLine.setText('') else: if self.jobInfoDic[self.currentJob]['mem'] != '': self.jobTabMemLine.setText(self.jobInfoDic[self.currentJob]['mem'] + ' M') self.jobTabMemLine.setCursorPosition(0) def updateJobTabFrame2(self, init=False): """ Show job detailed description info on self.jobTabFrame2/self.jobTabJobInfoText. """ self.jobTabJobInfoText.clear() if not init: self.jobTabJobInfoText.insertPlainText(self.jobInfoDic[self.currentJob]['jobInfo']) pyqt5_common.textEditVisiblePosition(self.jobTabJobInfoText, 'Start') def updateJobTabFrame3(self, init=False): """ Draw memory curve for current job, save the png picture and show it on self.jobTabFrame3. """ self.jobTabMemCurveLabel.setText('Job memory curve') if not init: if self.jobInfoDic[self.currentJob]['status'] == 'PEND': warningMessage = '*Warning*: "' + str(self.currentJob) + '" is PEND job, cannot draw memory curve for it.' self.guiWarning(warningMessage) else: # Generate memory curve with the specified job id self.myDrawCurve.drawJobMemCurve(self.currentJob) memCurveFig = str(config.tmpPath) + '/' + str(user) + '_' + str(self.currentJob) + '.png' if os.path.exists(memCurveFig): pixMap = QPixmap(memCurveFig).scaled(self.jobTabMemCurveLabel.width(), self.jobTabMemCurveLabel.height()) self.jobTabMemCurveLabel.setPixmap(pixMap) else: warningMessage = '*Warning*: Not find memory curve fig "' + str(memCurveFig) + '".' self.guiWarning(warningMessage) ## For job TAB (end) ## ## For jobs TAB (start) ## def genJobsTab(self): """ Generate the jobs tab on openlavaMonitor GUI, show jobs informations. """ # self.jobsTab self.jobsTabFrame0 = QFrame(self.jobsTab) self.jobsTabFrame0.setFrameShadow(QFrame.Raised) self.jobsTabFrame0.setFrameShape(QFrame.Box) self.jobsTabTable = QTableWidget(self.jobsTab) self.jobsTabTable.itemClicked.connect(self.jobsTabCheckClick) # self.jobsTab - Grid jobsTabGrid = QGridLayout() jobsTabGrid.addWidget(self.jobsTabFrame0, 0, 0) jobsTabGrid.addWidget(self.jobsTabTable, 1, 0) jobsTabGrid.setRowStretch(0, 1) jobsTabGrid.setRowStretch(1, 10) self.jobsTab.setLayout(jobsTabGrid) # Generate sub-frame self.genJobsTabFrame0() self.genJobsTabTable() def setJobsTabStatusCombo(self, statusList=['RUN', 'PEND', 'ALL']): """ Set (initialize) self.jobsTabStatusCombo. """ self.jobsTabStatusCombo.clear() for status in statusList: self.jobsTabStatusCombo.addItem(status) def setJobsTabQueueCombo(self, queueList=[]): """ Set (initialize) self.jobsTabQueueCombo. """ self.jobsTabQueueCombo.clear() if len(queueList) == 0: queueList = copy.deepcopy(self.queueList) queueList.insert(0, 'ALL') for queue in queueList: self.jobsTabQueueCombo.addItem(queue) def setJobsTabStartedOnCombo(self, hostList=[]): """ Set (initialize) self.jobsTabStartedOnCombo. """ self.jobsTabStartedOnCombo.clear() if len(hostList) == 0: hostList = copy.deepcopy(self.hostList) hostList.insert(0, 'ALL') for host in hostList: self.jobsTabStartedOnCombo.addItem(host) def genJobsTabFrame0(self): # self.jobsTabFrame0 jobsTabUserLabel = QLabel('User', self.jobsTabFrame0) jobsTabUserLabel.setStyleSheet("font-weight: bold;") self.jobsTabUserLine = QLineEdit() jobsTabStatusLabel = QLabel(' Status', self.jobsTabFrame0) jobsTabStatusLabel.setStyleSheet("font-weight: bold;") self.jobsTabStatusCombo = QComboBox(self.jobsTabFrame0) self.setJobsTabStatusCombo() jobsTabQueueLabel = QLabel(' Queue', self.jobsTabFrame0) jobsTabQueueLabel.setStyleSheet("font-weight: bold;") self.jobsTabQueueCombo = QComboBox(self.jobsTabFrame0) self.setJobsTabQueueCombo() jobsTabStartedOnLabel = QLabel(' Host', self.jobsTabFrame0) jobsTabStartedOnLabel.setStyleSheet("font-weight: bold;") self.jobsTabStartedOnCombo = QComboBox(self.jobsTabFrame0) self.setJobsTabStartedOnCombo() self.jobsTabStatusCombo.currentIndexChanged.connect(self.genJobsTabTable) self.jobsTabQueueCombo.currentIndexChanged.connect(self.genJobsTabTable) self.jobsTabStartedOnCombo.currentIndexChanged.connect(self.genJobsTabTable) jobsTabCheckButton = QPushButton('Check', self.jobsTabFrame0) jobsTabCheckButton.clicked.connect(self.genJobsTabTable) # self.jobsTabFrame0 - Grid jobsTabFrame0Grid = QGridLayout() jobsTabFrame0Grid.addWidget(jobsTabUserLabel, 0, 0) jobsTabFrame0Grid.addWidget(self.jobsTabUserLine, 0, 1) jobsTabFrame0Grid.addWidget(jobsTabStatusLabel, 0, 2) jobsTabFrame0Grid.addWidget(self.jobsTabStatusCombo, 0, 3) jobsTabFrame0Grid.addWidget(jobsTabQueueLabel, 0, 4) jobsTabFrame0Grid.addWidget(self.jobsTabQueueCombo, 0, 5) jobsTabFrame0Grid.addWidget(jobsTabStartedOnLabel, 0, 6) jobsTabFrame0Grid.addWidget(self.jobsTabStartedOnCombo, 0, 7) jobsTabFrame0Grid.addWidget(jobsTabCheckButton, 0, 8) jobsTabFrame0Grid.setColumnStretch(1, 1) jobsTabFrame0Grid.setColumnStretch(3, 1) jobsTabFrame0Grid.setColumnStretch(5, 1) jobsTabFrame0Grid.setColumnStretch(7, 1) self.jobsTabFrame0.setLayout(jobsTabFrame0Grid) def genJobsTabTable(self): self.jobsTabTable.setShowGrid(True) self.jobsTabTable.setSortingEnabled(True) self.jobsTabTable.setColumnCount(12) self.jobsTabTable.setHorizontalHeaderLabels(['Job', 'User', 'Status', 'Queue', 'Host', 'Started', 'Project', 'Processers', 'cpuTime', 'Rusage (G)', 'Mem (G)', 'Command']) command = 'bjobs -UF ' user = self.jobsTabUserLine.text().strip() if re.match('^\s*$', user): command = str(command) + ' -u all' else: command = str(command) + ' -u ' + str(user) queue = self.jobsTabQueueCombo.currentText().strip() if queue != 'ALL': command = str(command) + ' -q ' + str(queue) status = self.jobsTabStatusCombo.currentText().strip() if status == 'RUN': command = str(command) + ' -r' elif status == 'PEND': command = str(command) + ' -p' elif status == 'ALL': command = str(command) + ' -a' startedOn = self.jobsTabStartedOnCombo.currentText().strip() if startedOn != 'ALL': command = str(command) + ' -m ' + str(startedOn) jobDic = openlava_common.getBjobsUfInfo(command) self.jobsTabTable.setRowCount(len(jobDic.keys())) jobs = list(jobDic.keys()) for i in range(len(jobs)): job = jobs[i] j = 0 self.jobsTabTable.setItem(i, j, QTableWidgetItem(job)) j = j+1 item = QTableWidgetItem() item.setText(jobDic[job]['user']) self.jobsTabTable.setItem(i, j, item) j = j+1 item = QTableWidgetItem() item.setText(jobDic[job]['status']) self.jobsTabTable.setItem(i, j, item) j = j+1 item = QTableWidgetItem() item.setText(jobDic[job]['queue']) self.jobsTabTable.setItem(i, j, item) j = j+1 item = QTableWidgetItem() item.setText(jobDic[job]['startedOn']) self.jobsTabTable.setItem(i, j, item) j = j+1 item = QTableWidgetItem() item.setText(jobDic[job]['startedTime']) self.jobsTabTable.setItem(i, j, item) j = j+1 if str(jobDic[job]['project']) != '': item = QTableWidgetItem() item.setData(Qt.DisplayRole, jobDic[job]['project']) self.jobsTabTable.setItem(i, j, item) j = j+1 if str(jobDic[job]['processorsRequested']) != '': item = QTableWidgetItem() item.setData(Qt.DisplayRole, int(jobDic[job]['processorsRequested'])) self.jobsTabTable.setItem(i, j, item) j = j+1 if str(jobDic[job]['cpuTime']) != '': item = QTableWidgetItem() item.setData(Qt.DisplayRole, int(jobDic[job]['cpuTime'])) self.jobsTabTable.setItem(i, j, item) j = j+1 if str(jobDic[job]['rusageMem']) != '': item = QTableWidgetItem() rusageMemValue = int(jobDic[job]['rusageMem'])/1024 item.setData(Qt.DisplayRole, int(rusageMemValue)) self.jobsTabTable.setItem(i, j, item) j = j+1 if str(jobDic[job]['mem']) != '': item = QTableWidgetItem() memValue = int(jobDic[job]['mem'])/1024 item.setData(Qt.DisplayRole, int(memValue)) self.jobsTabTable.setItem(i, j, item) j = j+1 item = QTableWidgetItem() item.setText(jobDic[job]['command']) self.jobsTabTable.setItem(i, j, item) def jobsTabCheckClick(self, item=None): """ With the clicked job, jump the the job Tab, show the job related infos. """ if item != None: if item.column() == 0: currentRow = self.jobsTabTable.currentRow() job = self.jobsTabTable.item(currentRow, 0).text().strip() if job != '': self.jobTabJobLine.setText(job) self.checkJob() self.mainTab.setCurrentWidget(self.jobTab) ## For jobs TAB (end) ## ## For hosts TAB (start) ## def genHostsTab(self): """ Generate the hosts tab on openlavaMonitor GUI, show hosts informations. """ # self.hostsTabTable self.hostsTabFrame0 = QFrame(self.hostsTab) self.hostsTabFrame0.setFrameShadow(QFrame.Raised) self.hostsTabFrame0.setFrameShape(QFrame.Box) self.hostsTabTable = QTableWidget(self.hostsTab) self.hostsTabTable.itemClicked.connect(self.hostsTabCheckClick) # self.hostsTabTable - Grid hostsTabGrid = QGridLayout() hostsTabGrid.addWidget(self.hostsTabFrame0, 0, 0) hostsTabGrid.addWidget(self.hostsTabTable, 1, 0) hostsTabGrid.setRowStretch(0, 1) hostsTabGrid.setRowStretch(1, 10) self.hostsTab.setLayout(hostsTabGrid) # Generate sub-fram self.genHostsTabFrame0() self.genHostsTabTable() def setHostsTabQueueCombo(self, queueList=[]): """ Set (initialize) self.hostsTabQueueCombo. """ self.hostsTabQueueCombo.clear() if len(queueList) == 0: queueList = copy.deepcopy(self.queueList) queueList.insert(0, 'ALL') for queue in queueList: self.hostsTabQueueCombo.addItem(queue) def genHostsTabFrame0(self): # self.hostsTabFrame0 hostsTabQueueLabel = QLabel(' Queue', self.hostsTabFrame0) hostsTabQueueLabel.setStyleSheet("font-weight: bold;") self.hostsTabQueueCombo = QComboBox(self.hostsTabFrame0) self.setHostsTabQueueCombo() self.hostsTabQueueCombo.currentIndexChanged.connect(self.genHostsTabTable) hostsTabEmptyLabel = QLabel('') # self.hostsTabFrame0 - Grid hostsTabFrame0Grid = QGridLayout() hostsTabFrame0Grid.addWidget(hostsTabQueueLabel, 0, 1) hostsTabFrame0Grid.addWidget(self.hostsTabQueueCombo, 0, 2) hostsTabFrame0Grid.addWidget(hostsTabEmptyLabel, 0, 3) hostsTabFrame0Grid.setColumnStretch(1, 1) hostsTabFrame0Grid.setColumnStretch(2, 1) hostsTabFrame0Grid.setColumnStretch(3, 8) self.hostsTabFrame0.setLayout(hostsTabFrame0Grid) def genHostsTabTable(self): print('* Updating hosts information, please wait a moment ...') self.hostsTabTable.setShowGrid(True) self.hostsTabTable.setSortingEnabled(True) self.hostsTabTable.setColumnCount(10) self.hostsTabTable.setHorizontalHeaderLabels(['Host', 'Status', 'Queue', 'Njobs', 'Ncpus', 'Ut (%)', 'Mem (G)', 'Maxmem (G)', 'swp (G)', 'maxswp (G)']) queue = self.hostsTabQueueCombo.currentText().strip() bhostsDic = openlava_common.getBhostsInfo() lshostsDic = openlava_common.getLshostsInfo() lsloadDic = openlava_common.getLsloadInfo() hostQueueDic = openlava_common.getHostQueueInfo() # Get expected host list self.queueHostList = [] if queue == 'ALL': self.queueHostList = self.hostList else: for host in self.hostList: if queue in hostQueueDic[host]: self.queueHostList.append(host) self.hostsTabTable.setRowCount(len(self.queueHostList)) for i in range(len(self.queueHostList)): host = self.queueHostList[i] j = 0 self.hostsTabTable.setItem(i, j, QTableWidgetItem(host)) j = j+1 index = bhostsDic['HOST_NAME'].index(host) status = bhostsDic['STATUS'][index] item = QTableWidgetItem(status) if str(status) == 'closed': item.setFont(QFont('song', 10, QFont.Bold)) item.setForeground(QBrush(Qt.red)) self.hostsTabTable.setItem(i, j, item) j = j+1 if host in hostQueueDic.keys(): queues = ' '.join(hostQueueDic[host]) item = QTableWidgetItem(queues) self.hostsTabTable.setItem(i, j, item) j = j+1 index = bhostsDic['HOST_NAME'].index(host) njobs = bhostsDic['NJOBS'][index] if not re.match('^[0-9]+$', njobs): common.printWarning('*Warning*: host(' + str(host) + ') NJOBS info "' + str(njobs) + '": invalid value, reset it to "0".') njobs = 0 item = QTableWidgetItem() item.setData(Qt.DisplayRole, int(njobs)) self.hostsTabTable.setItem(i, j, item) j = j+1 index = lshostsDic['HOST_NAME'].index(host) ncpus = lshostsDic['ncpus'][index] if not re.match('^[0-9]+$', ncpus): common.printWarning('*Warning*: host(' + str(host) + ') ncpus info "' + str(ncpus) + '": invalid value, reset it to "0".') ncpus = 0 item = QTableWidgetItem() item.setData(Qt.DisplayRole, int(ncpus)) self.hostsTabTable.setItem(i, j, item) j = j+1 index = lsloadDic['HOST_NAME'].index(host) ut = lsloadDic['ut'][index] ut = re.sub('%', '', ut) if not re.match('^[0-9]+$', ut): common.printWarning('*Warning*: host(' + str(host) + ') ut info "' + str(ut) + '": invalid value, reset it to "0".') ut = 0 item = QTableWidgetItem() item.setData(Qt.DisplayRole, int(ut)) self.hostsTabTable.setItem(i, j, item) j = j+1 index = lsloadDic['HOST_NAME'].index(host) mem = lsloadDic['mem'][index] if re.search('M', mem): mem = re.sub('M', '', mem) mem = int(mem)/1024 elif re.search('G', mem): mem = re.sub('G', '', mem) else: common.printWarning('*Warning*: host(' + str(host) + ') mem info "' + str(mem) + '": unrecognized unit, reset it to "0".') mem = 0 item = QTableWidgetItem() item.setData(Qt.DisplayRole, int(mem)) self.hostsTabTable.setItem(i, j, item) j = j+1 index = lshostsDic['HOST_NAME'].index(host) maxmem = lshostsDic['maxmem'][index] if re.search('M', maxmem): maxmem = re.sub('M', '', maxmem) maxmem = int(maxmem)/1024 elif re.search('G', maxmem): maxmem = re.sub('G', '', maxmem) else: common.printWarning('*Warning*: host(' + str(host) + ') maxmem info "' + str(maxmem) + '": unrecognized unit, reset it to "0".') maxmem = 0 item = QTableWidgetItem() item.setData(Qt.DisplayRole, int(maxmem)) self.hostsTabTable.setItem(i, j, item) j = j+1 index = lsloadDic['HOST_NAME'].index(host) swp = lsloadDic['swp'][index] if re.search('M', swp): swp = re.sub('M', '', swp) swp = int(swp)/1024 elif re.search('G', swp): swp = re.sub('G', '', swp) else: common.printWarning('*Warning*: host(' + str(host) + ') swp info "' + str(swp) + '": unrecognized unit, reset it to "0".') swp = 0 item = QTableWidgetItem() item.setData(Qt.DisplayRole, int(swp)) self.hostsTabTable.setItem(i, j, item) j = j+1 index = lshostsDic['HOST_NAME'].index(host) maxswp = lshostsDic['maxswp'][index] if re.search('M', maxswp): maxswp = re.sub('M', '', maxswp) maxswp = int(maxswp)/1024 elif re.search('G', maxswp): maxswp = re.sub('G', '', maxswp) else: common.printWarning('*Warning*: host(' + str(host) + ') maxswp info "' + str(maxswp) + '": unrecognized unit, reset it to "0".') maxswp = 0 item = QTableWidgetItem() item.setData(Qt.DisplayRole, int(maxswp)) self.hostsTabTable.setItem(i, j, item) def hostsTabCheckClick(self, item=None): """ If click the host name (or Njobs number), jump to the jobs Tab and show the host related jobs. """ if item != None: currentRow = self.hostsTabTable.currentRow() host = self.hostsTabTable.item(currentRow, 0).text().strip() njobsNum = self.hostsTabTable.item(currentRow, 3).text().strip() if (item.column() == 0) or (item.column() == 3): if int(njobsNum) > 0: self.jobsTabUserLine.setText('') self.setJobsTabStatusCombo() self.setJobsTabQueueCombo() hostList = copy.deepcopy(self.queueHostList) hostList.remove(host) hostList.insert(0, host) hostList.insert(1, 'ALL') self.setJobsTabStartedOnCombo(hostList) self.genJobsTabTable() self.mainTab.setCurrentWidget(self.jobsTab) self.mainTab.setCurrentWidget(self.jobsTab) ## For hosts TAB (end) ## ## For queues TAB (start) ## def genQueuesTab(self): """ Generate the queues tab on openlavaMonitor GUI, show queues informations. """ # Init var self.bqueuesFilesDic = {} # self.queuesTab self.queuesTabTable = QTableWidget(self.queuesTab) self.queuesTabTable.itemClicked.connect(self.queuesTabCheckClick) self.queuesTabFrame0 = QFrame(self.queuesTab) self.queuesTabFrame0.setFrameShadow(QFrame.Raised) self.queuesTabFrame0.setFrameShape(QFrame.Box) self.queuesTabFrame1 = QFrame(self.queuesTab) self.queuesTabFrame1.setFrameShadow(QFrame.Raised) self.queuesTabFrame1.setFrameShape(QFrame.Box) # self.queuesTab - Grid queuesTabGrid = QGridLayout() queuesTabGrid.addWidget(self.queuesTabTable, 0, 0) queuesTabGrid.addWidget(self.queuesTabFrame0, 0, 1) queuesTabGrid.addWidget(self.queuesTabFrame1, 1, 0, 1, 2) queuesTabGrid.setRowStretch(0, 1) queuesTabGrid.setRowStretch(1, 10) queuesTabGrid.setColumnStretch(0, 1) queuesTabGrid.setColumnStretch(1, 10) queuesTabGrid.setRowMinimumHeight(0, 350) queuesTabGrid.setRowMinimumHeight(1, 150) queuesTabGrid.setColumnMinimumWidth(0, 328) queuesTabGrid.setColumnMinimumWidth(1, 500) self.queuesTab.setLayout(queuesTabGrid) # Generate sub-frame self.genQueuesTabTable() self.genQueuesTabFrame0() self.genQueuesTabFrame1() def genQueuesTabTable(self): self.queuesTabTable.setShowGrid(True) self.queuesTabTable.setColumnCount(3) self.queuesTabTable.setHorizontalHeaderLabels(['QUEUE', 'PEND', 'RUN']) # Hide the vertical header self.queuesTabTable.verticalHeader().setVisible(False) queuesDic = openlava_common.getBqueuesInfo() self.queuesTabTable.setRowCount(len(self.queueList)) for i in range(len(self.queueList)): queue = self.queueList[i] index = queuesDic['QUEUE_NAME'].index(queue) j = 0 item = QTableWidgetItem(queue) self.queuesTabTable.setItem(i, j, item) j = j+1 pend = queuesDic['PEND'][index] item = QTableWidgetItem(pend) if int(pend) > 0: item.setFont(QFont('song', 10, QFont.Bold)) item.setForeground(QBrush(Qt.red)) self.queuesTabTable.setItem(i, j, item) j = j+1 run = queuesDic['RUN'][index] item = QTableWidgetItem(run) self.queuesTabTable.setItem(i, j, item) def genQueuesTabFrame0(self): # self.queuesTabFrame0 self.queuesTabJobNumCurveLabel = QLabel('queue (PEND/RUN) job number curve', self.queuesTabFrame0) self.queuesTabJobNumCurveLabel.setAlignment(Qt.AlignCenter) # self.queuesTabFrame0 - Grid queuesTabFrame0Grid = QGridLayout() queuesTabFrame0Grid.addWidget(self.queuesTabJobNumCurveLabel, 0, 0) self.queuesTabFrame0.setLayout(queuesTabFrame0Grid) def genQueuesTabFrame1(self): # self.queuesTabFrame1 self.queuesTabText = QTextEdit(self.queuesTabFrame1) # self.queuesTabFrame1 - Grid queuesTabFrame1Grid = QGridLayout() queuesTabFrame1Grid.addWidget(self.queuesTabText, 0, 0) self.queuesTabFrame1.setLayout(queuesTabFrame1Grid) def queuesTabCheckClick(self, item=None): """ If click the queue name, jump to the jobs Tab and show the queue related jobs. If click the PEND number, jump the jobs Tab and show the queue PEND related jobs. If click the RUN number, jump the jobs Tab and show the queue RUN related jobs. """ if item != None: currentRow = self.queuesTabTable.currentRow() queue = self.queuesTabTable.item(currentRow, 0).text().strip() pendNum = self.queuesTabTable.item(currentRow, 1).text().strip() runNum = self.queuesTabTable.item(currentRow, 2).text().strip() if item.column() == 0: print('* Checking queue "' + str(queue) + '".') self.updateQueueTabFrame0(queue) self.updateQueueTabFrame1(queue) elif item.column() == 1: if (pendNum != '') and (int(pendNum) > 0): self.jobsTabUserLine.setText('') statusList = ['PEND', 'RUN', 'ALL'] self.setJobsTabStatusCombo(statusList) queueList = copy.deepcopy(self.queueList) queueList.remove(queue) queueList.insert(0, queue) queueList.insert(1, 'ALL') self.setJobsTabQueueCombo(queueList) self.setJobsTabStartedOnCombo() self.genJobsTabTable() self.mainTab.setCurrentWidget(self.jobsTab) elif item.column() == 2: if (runNum != '') and (int(runNum) > 0): self.jobsTabUserLine.setText('') statusList = ['RUN', 'PEND', 'ALL'] self.setJobsTabStatusCombo(statusList) queueList = copy.deepcopy(self.queueList) queueList.remove(queue) queueList.insert(0, queue) queueList.insert(1, 'ALL') self.setJobsTabQueueCombo(queueList) self.setJobsTabStartedOnCombo() self.genJobsTabTable() self.mainTab.setCurrentWidget(self.jobsTab) def updateQueueTabFrame0(self, queue): """ Draw queue (PEND/RUN) job number current job, save the png picture and show it on self.queuesTabFrame0. """ self.queuesTabJobNumCurveLabel.setText('queue (PEND/RUN) job number curve') # Generate queue job number curve with the specified job id self.myDrawCurve.drawQueueJobNumCurve(queue) queueJobNumCurveFig = str(config.tmpPath) + '/' + str(user) + '_' + str(queue) + '_jobNum.png' if os.path.exists(queueJobNumCurveFig): pixMap = QPixmap(queueJobNumCurveFig).scaled(self.queuesTabJobNumCurveLabel.width(), self.queuesTabJobNumCurveLabel.height()) self.queuesTabJobNumCurveLabel.setPixmap(pixMap) else: warningMessage = '*Warning*: Not find queue job number curve fig "' + str(queueJobNumCurveFig) + '".' self.guiWarning(warningMessage) def updateQueueTabFrame1(self, queue): """ Show queue detailed informations on self.queuesTabText. """ self.queuesTabText.clear() command = 'bqueues -l ' + str(queue) lines = os.popen(command).readlines() for line in lines: self.queuesTabText.insertPlainText(line) pyqt5_common.textEditVisiblePosition(self.queuesTabText, 'Start') ## For queues TAB (end) ## def closeEvent(self, QCloseEvent): """ When window close, post-process. """ print('Bye')
class Channels(QWidget): """Widget with information about channel groups. Attributes ---------- parent : QMainWindow the main window config : ConfigChannels preferences for this widget filename : path to file file with the channel groups groups : list of dict each dict contains information about one channel group tabs : QTabWidget Widget that contains the tabs with channel groups """ def __init__(self, parent): super().__init__() self.parent = parent self.config = ConfigChannels(lambda: None) self.filename = None self.groups = [] self.tabs = None self.create() self.create_action() def create(self): """Create Channels Widget""" add_button = QPushButton('New') add_button.clicked.connect(self.new_group) color_button = QPushButton('Color') color_button.clicked.connect(self.color_group) del_button = QPushButton('Delete') del_button.clicked.connect(self.del_group) apply_button = QPushButton('Apply') apply_button.clicked.connect(self.apply) self.button_add = add_button self.button_color = color_button self.button_del = del_button self.button_apply = apply_button buttons = QGridLayout() buttons.addWidget(add_button, 0, 0) buttons.addWidget(color_button, 1, 0) buttons.addWidget(del_button, 0, 1) buttons.addWidget(apply_button, 1, 1) self.tabs = QTabWidget() layout = QVBoxLayout() layout.addLayout(buttons) layout.addWidget(self.tabs) self.setLayout(layout) self.setEnabled(False) self.button_color.setEnabled(False) self.button_del.setEnabled(False) self.button_apply.setEnabled(False) def create_action(self): """Create actions related to channel selection.""" actions = {} act = QAction('Load Montage...', self) act.triggered.connect(self.load_channels) act.setEnabled(False) actions['load_channels'] = act act = QAction('Save Montage...', self) act.triggered.connect(self.save_channels) act.setEnabled(False) actions['save_channels'] = act self.action = actions def update(self): self.setEnabled(True) self.action['load_channels'].setEnabled(True) self.action['save_channels'].setEnabled(True) def new_group(self, checked=False, test_name=None): """Create a new channel group. Parameters ---------- checked : bool comes from QAbstractButton.clicked test_name : str used for testing purposes to avoid modal window Notes ----- Don't call self.apply() just yet, only if the user wants it. """ chan_name = self.parent.labels.chan_name if chan_name is None: msg = 'No dataset loaded' self.parent.statusBar().showMessage(msg) lg.debug(msg) else: if test_name is None: new_name = QInputDialog.getText(self, 'New Channel Group', 'Enter Name') else: new_name = [test_name, True] # like output of getText if new_name[1]: s_freq = self.parent.info.dataset.header['s_freq'] group = ChannelsGroup(chan_name, new_name[0], self.config.value, s_freq) self.tabs.addTab(group, new_name[0]) self.tabs.setCurrentIndex(self.tabs.currentIndex() + 1) # activate buttons self.button_color.setEnabled(True) self.button_del.setEnabled(True) self.button_apply.setEnabled(True) def color_group(self, checked=False, test_color=None): """Change the color of the group.""" group = self.tabs.currentWidget() if test_color is None: newcolor = QColorDialog.getColor(group.idx_color) else: newcolor = test_color group.idx_color = newcolor self.apply() def del_group(self): """Delete current group.""" idx = self.tabs.currentIndex() self.tabs.removeTab(idx) self.apply() def apply(self): """Apply changes to the plots.""" self.read_group_info() if self.tabs.count() == 0: # disactivate buttons self.button_color.setEnabled(False) self.button_del.setEnabled(False) self.button_apply.setEnabled(False) else: # activate buttons self.button_color.setEnabled(True) self.button_del.setEnabled(True) self.button_apply.setEnabled(True) if self.groups: self.parent.overview.update_position() self.parent.spectrum.update() self.parent.notes.enable_events() else: self.parent.traces.reset() self.parent.spectrum.reset() self.parent.notes.enable_events() def read_group_info(self): """Get information about groups directly from the widget.""" self.groups = [] for i in range(self.tabs.count()): one_group = self.tabs.widget(i).get_info() # one_group['name'] = self.tabs.tabText(i) self.groups.append(one_group) def load_channels(self, checked=False, test_name=None): """Load channel groups from file. Parameters ---------- test_name : path to file when debugging the function, you can open a channels file from the command line """ chan_name = self.parent.labels.chan_name if self.filename is not None: filename = self.filename elif self.parent.info.filename is not None: filename = (splitext(self.parent.info.filename)[0] + '_channels.json') else: filename = None if test_name is None: filename, _ = QFileDialog.getOpenFileName( self, 'Open Channels Montage', filename, 'Channels File (*.json)') else: filename = test_name if filename == '': return self.filename = filename with open(filename, 'r') as outfile: groups = load(outfile) s_freq = self.parent.info.dataset.header['s_freq'] no_in_dataset = [] for one_grp in groups: no_in_dataset.extend(set(one_grp['chan_to_plot']) - set(chan_name)) chan_to_plot = set(chan_name) & set(one_grp['chan_to_plot']) ref_chan = set(chan_name) & set(one_grp['ref_chan']) group = ChannelsGroup(chan_name, one_grp['name'], one_grp, s_freq) group.highlight_channels(group.idx_l0, chan_to_plot) group.highlight_channels(group.idx_l1, ref_chan) self.tabs.addTab(group, one_grp['name']) if no_in_dataset: msg = 'Channels not present in the dataset: ' + ', '.join( no_in_dataset) self.parent.statusBar().showMessage(msg) lg.debug(msg) self.apply() def save_channels(self, checked=False, test_name=None): """Save channel groups to file.""" self.read_group_info() if self.filename is not None: filename = self.filename elif self.parent.info.filename is not None: filename = (splitext(self.parent.info.filename)[0] + '_channels.json') else: filename = None if test_name is None: filename, _ = QFileDialog.getSaveFileName( self, 'Save Channels Montage', filename, 'Channels File (*.json)') else: filename = test_name if filename == '': return self.filename = filename groups = deepcopy(self.groups) for one_grp in groups: one_grp['color'] = one_grp['color'].rgba() with open(filename, 'w') as outfile: dump(groups, outfile, indent=' ') def reset(self): """Reset all the information of this widget.""" self.filename = None self.groups = [] self.tabs.clear() self.setEnabled(False) self.button_color.setEnabled(False) self.button_del.setEnabled(False) self.button_apply.setEnabled(False) self.action['load_channels'].setEnabled(False) self.action['save_channels'].setEnabled(False)
class central(QWidget): #Cria widget para colocar na janela central onde as duas def __init__(self): super().__init__() self.setWindowIcon(QIcon("icons/icone_TCC.png")) self.UI() def UI(self): main = QVBoxLayout() #Widget principal, onde serão colocadas todas as abas self.unit_y = "Ângulo de deflexão (° graus)" self.unit_x = "Segundos (s)" self.lines = [] #Lista das linhas do listwidget reinicia self.tabela_param = 830 self.passw = "lembrei" # Cria os principais layouts que serão inseridos nas 4 abas do software self.main_tab = QHBoxLayout() #Layout para a aba principal db_tab = QVBoxLayout() #Layout para a aba dos dados rep_tab = QVBoxLayout() #Aba dos relatórios info_tab = QVBoxLayout() #Aba das informações """ Widgets da primeira aba """ fonte = QFont() #Cria a fonte em negrito fonte.setBold(True) #Cria o formulário dos parâmetros, controle e barra de progresso self.formulario = QVBoxLayout() #Cria o form das principais atividades self.lbl_void = QLabel() #Label vazio para espaçar os dados self.lbl_imp = QLabel("Dir. do Sistema",self) #Label da importação do benchmark self.lbl_imp.setFont(fonte) #self.lbl_icon.setAlignment(Qt.AlignCenter) self.btn_bch = QPushButton("Benchmark") self.btn_bch.clicked.connect(self.bench) self.lbl_param = QLabel("Parametrização",self) self.lbl_param.setFont(fonte) self.lbl_font = QLabel("Fonte da OFC: ") self.cmb_font = QComboBox(self) #Cria o combobox do primeiro parâmetro self.cmb_font.addItems(font) #Carrega lista das fontes de perturbação self.cmb_font.currentTextChanged.connect(self.pdate_ampl) self.hbox_font = QHBoxLayout() self.hbox_font.addWidget(self.lbl_font) self.hbox_font.addWidget(self.cmb_font) self.lbl_type = QLabel("Tipo da OFC: ") self.cmb_type = QComboBox(self) #Cria o combobox do primeiro parâmetro self.cmb_type.addItems(type_ofc) #Carrega lista das fontes de perturbação self.hbox_type = QHBoxLayout() self.hbox_type.addWidget(self.lbl_type) self.hbox_type.addWidget(self.cmb_type) self.lbl_turb = QLabel("Turbulência: ") self.cmb_turb = QComboBox(self) #Cria o combobox do segundo parâmetro self.cmb_turb.addItems(turb) self.hbox_turb = QHBoxLayout() self.hbox_turb.addWidget(self.lbl_turb) self.hbox_turb.addWidget(self.cmb_turb) self.lbl_ctrl1 = QLabel("Tipo Controle: ") self.cmb_ctrl1 = QComboBox(self)#Cria o combobox do terceiro parâmetro self.cmb_ctrl1.addItems(ctrl) self.hbox_ctrl1 = QHBoxLayout() self.hbox_ctrl1.addWidget(self.lbl_ctrl1) self.hbox_ctrl1.addWidget(self.cmb_ctrl1) self.lbl_ampl = QLabel("Ampl(mm)/Bias(mm)/Freq(rad/s):") self.cmb_ampl = QComboBox(self) #Cria o combobox das unidades do eixo das abscissas self.cmb_ampl.addItems(ampl) self.cmb_bias = QComboBox(self) #Cria o combobox das unidades do eixo das abscissas self.cmb_bias.addItems(bias) self.cmb_freq = QComboBox(self) #Cria o combobox das unidades do eixo das oordenadas self.cmb_freq.addItems(freq) self.amp_bias_freq = QHBoxLayout() self.amp_bias_freq.addWidget(self.cmb_ampl,30) self.amp_bias_freq.addWidget(self.cmb_bias,30) self.amp_bias_freq.addWidget(self.cmb_freq,40) self.lbl_ctrl = QLabel("Painel de Controle",self) self.lbl_ctrl.setFont(fonte) self.lbl_bench = QLabel("Modelo .lsx Benchmark: ") self.cmb_bench = QComboBox(self) #Cria o combobox das unidades do eixo das oordenadas self.lbl_treino = QLabel("Modo de Treinamento: ") self.cmb_treino = QComboBox(self) #Cria o combobox das unidades do eixo das oordenadas self.cmb_treino.addItems(treino) self.lbl_time = QLabel("Tempo de Simulação: ") self.line_time = QLineEdit() self.line_time.setPlaceholderText("Segundos") self.hbox_time = QHBoxLayout() self.hbox_time.addWidget(self.lbl_time) self.hbox_time.addWidget(self.line_time) self.list_status = QListWidget() self.list_status.doubleClicked.connect(self.exp_rep) self.btn_start = QPushButton("Iniciar") self.btn_start.clicked.connect(self.start) self.btn_start.setDisabled(True) self.pbar = QProgressBar() self.pbar.setFont(fonte) #Insere no formulário os widgets: self.formulario.addStretch() cp = QDesktopWidget().availableGeometry().center() if cp.y()*2 >= 1030: #Se a resolução for alta, coloca o ícone da pontifícia self.tabela_param = 1385 self.lbl_icon = QLabel() #Label que armazena o icone #Icone da pontifícia: icone_tcc = QPixmap("icons/TCC_Icon.png")#.scaled(50, 61, Qt.KeepAspectRatio, Qt.FastTransformation) self.lbl_icon.setPixmap(icone_tcc) self.lbl_icon.setAlignment(Qt.AlignCenter) self.formulario.addWidget(self.lbl_icon) self.passw = "" #self.benchmark_path = r"D:/PUCPR/TRABALHO DE CONCLUSAO DO CURSO - TCC/SOFT SENSORS" self.formulario.addWidget(self.lbl_imp) self.formulario.addWidget(self.btn_bch) self.formulario.addWidget(QHLine())#)#self.lbl_void) #Espaçamento self.formulario.addWidget(self.lbl_param) self.formulario.addLayout(self.hbox_font) self.formulario.addLayout(self.hbox_type) self.formulario.addLayout(self.hbox_turb) self.formulario.addLayout(self.hbox_ctrl1) self.formulario.addWidget(self.lbl_ampl) self.formulario.addLayout(self.amp_bias_freq) self.formulario.addWidget(QHLine())#self.lbl_void) #Espaçamento self.formulario.addWidget(self.lbl_ctrl) self.formulario.addWidget(self.lbl_bench) self.formulario.addWidget(self.cmb_bench) self.formulario.addWidget(self.lbl_treino) self.formulario.addWidget(self.cmb_treino) self.formulario.addLayout(self.hbox_time) self.formulario.addWidget(self.btn_start) self.formulario.addWidget(self.list_status) self.formulario.addWidget(self.pbar) self.formulario.setAlignment(Qt.AlignCenter) self.formulario.addStretch() #cria o gráfico self.grafico = PlotWidget() self.grafico.setBackground('#323232') #Coloca a cor de fundo igual a do restante da interface # Coloca título no gráfico self.grafico.setTitle("Simulação do Benchmark OFC: AirBus", color="#56fceb", size="20pt") self.styles = {"color": "#56fceb", "font-size": "16px"} #Cria os estilos de fonte do gráfico self.grafico.setLabel("left", self.unit_y, **self.styles) #Insere a unidade do eixo Oordenado self.grafico.setLabel("bottom", self.unit_x, **self.styles) #Insere a unidade do eixo das Abscissas self.grafico.addLegend() #Coloca legenda no gráfico self.grafico.showGrid(x=True, y=True) #Coloca as grids no gráfico #Cria as três curvas que serão periodicamente atualizadas #self.dx_falhas = ScatterPlotItem(name="Falhas: OFC", symbolSize=10,symbol='x',symbolBrush=("#fc031c"), # pen=mkPen(color="#fc031c", width=1)) #self.grafico.addItem(self.dx_falhas) self.dx_comm = self.grafico.plot(name="Comando de Controle", symbolSize=5,symbolBrush=("#15bf48"), pen=mkPen(color="#15bf48", width=2)) self.dx_meas = self.grafico.plot(name="Deflexão Mensurada", symbolSize=5,symbolBrush=("#56fceb"), pen=mkPen(color="#56fceb", width=2)) self.dx_falhas = self.grafico.plot(name="Falhas: OFC", symbolSize=20,symbol='x',symbolBrush=("#fc031c"), pen=mkPen(color="#323232", width=0.001)) self.formulario.addStretch() #Insere os widgets na widget da aba self.main_tab.addLayout(self.formulario,13.5) #Adiciona a aba os parâmetros self.main_tab.addWidget(self.grafico,86.5) #Adiciona o gráfico a aba principal """ Cria os widgets da segunda tab """ self.db_table = QTableView() #Cria tabela do banco de dados #Itens abaixo da tabela self.btn_consulta = QPushButton("Consultar o Número de itens mais Atuais") self.btn_consulta.clicked.connect(self.update_tb) self.n_itens = QLineEdit() self.n_itens.setPlaceholderText("N° Itens") self.status_itens = QLineEdit() self.status_itens.setPlaceholderText("Status do software:") self.status_itens.setDisabled(True) self.btn_pdate = QPushButton("Atualiza para os 1000 últimos dados registrados") self.btn_pdate.clicked.connect(self.update_tb_1000) self.btn_exp = QPushButton("Exportar tabela para Excel") self.btn_exp.clicked.connect(self.exp_dados_excel) self.pbar_db = QProgressBar() self.pbar_db.setFont(fonte) self.db_func = QHBoxLayout() #Layout dos botões abaixo da tabela self.db_func.addWidget(self.btn_consulta,28) self.db_func.addWidget(self.n_itens,4.5) self.db_func.addWidget(self.status_itens,8.5) self.db_func.addWidget(self.pbar_db,25) self.db_func.addWidget(self.btn_pdate,21) self.db_func.addWidget(self.btn_exp,12) #Insere abaixo da tabela os itens: db_tab.addWidget(self.db_table,93) db_tab.addLayout(self.db_func,7) db_tab.addStretch() """ Cria os widgets da terceira aba """ self.rep_table = QTableView() #Cria tabela do relatório #Itens abaixo da tabela self.btn_pdate_rep = QPushButton("Atualiza para todos os dados registrados") self.btn_pdate_rep.clicked.connect(self.update_rep) self.btn_rep = QPushButton("Atualiza para todos últimos 'N' dados registrados") self.btn_rep.clicked.connect(self.update_rep_n) self.btn_exp_rep = QPushButton("Exportar relatório para Excel") self.btn_exp_rep.clicked.connect(self.exp_rep_excel) self.n_itens_rep = QLineEdit() self.n_itens_rep.setPlaceholderText("N° Itens") self.status_itens = QLineEdit() self.pbar_rep = QProgressBar() self.pbar_rep.setFont(fonte) self.rep_func = QHBoxLayout() #Layout dos botões abaixo da tabela self.rep_func.addWidget(self.btn_pdate_rep,20) self.rep_func.addWidget(self.btn_rep,22) self.rep_func.addWidget(self.n_itens_rep,4.5) self.rep_func.addWidget(self.pbar_rep,38) self.rep_func.addWidget(self.btn_exp_rep,15.5) #Insere abaixo da tabela os itens: rep_tab.addStretch() rep_tab.addWidget(self.rep_table,90) rep_tab.addLayout(self.rep_func,10) rep_tab.addStretch() """ Cria os widgets da aba informativa """ #Cria a aba informativa do final self.mapa = QLabel() # self.mapa.setPixmap(QPixmap("icons/MAPA_MENTAL.png")) info_tab.addWidget(self.mapa) info_tab.setAlignment(Qt.AlignHCenter) ############################Criando abas############################## self.tabs = QTabWidget() #Widget das tabs que reune as 4 self.tab1 = QWidget() #Tab de emulação do benchmark self.tab2 = QWidget() #Tab do banco de dados self.tab3 = QWidget() #Relatório de Falhas self.tab4 = QWidget() #Informações complementares self.tabs.addTab(self.tab1,"Simulação do Sistema") self.tabs.addTab(self.tab2,"Consulta Geral ao Banco de Dados") self.tabs.addTab(self.tab3,"Consultar Tabela do Relatório de Falhas") self.tabs.addTab(self.tab4,"Informações sobre o TCC: Mapa Mental") self.tab1.setLayout(self.main_tab) # Adicionando a aba de simulação self.tab2.setLayout(db_tab) # Adicionando adicionando aba do db self.tab3.setLayout(rep_tab) # Adicionando adcionando aba self.tab4.setLayout(info_tab) # Adicionando para a tab1 #Adiciona ao box principal a estrutura de tabs main.addWidget(self.tabs) #Coloca a estrutura de tabs no layout principal self.setLayout(main) def plot(self, x, y, plotname, color): pen = mkPen(color=color) self.grafico.plot(x, y, name=plotname, pen=pen, symbolSize=5, symbolBrush=(color)) def maria_conn(self): try: self.conn = mariadb.connect( user="******", password=self.passw, host="127.0.0.1", port=3306, database="db_ofc_tcc") self.cur = self.conn.cursor() except mariadb.Error as e: QMessageBox.warning(self,"Aviso",f"Sem conexão com o Banco de dados, devido ao erro: {e}") self.list_status.addItem("Conectado ao db_tcc") if "Conectado ao db_tcc" not in self.lines: #Se não estiver coloca self.lines.append("Conectado ao db_tcc") def bench(self): ask_dir = "Escolha o diretório onde o Benchmark se encontra" self.benchmark = str(QFileDialog.getExistingDirectory(None,ask_dir)) self.list_status.clear() #Limpa a lista toda vez que o botão de benchmark é pressionado if self.benchmark != '': #Se não for vazio, continua arqs = os.listdir(self.benchmark) bench = [] #Reiniciado quando escolhida outra pasta self.lines = [] #Lista das linhas do listwidget reinicia for arq in arqs: if '.slx' in arq: #Se a extenção do arquivo for a mesma do simulink bench.append(arq) if not(bench): #Se o vetor estiver vazio not_bench = f"Não foi encontrado arquivo do simulink no diretório selecionado {self.benchmark}!" QMessageBox.warning(self,"Aviso!",not_bench) else: self.list_status.addItem(f"Diretório: {self.benchmark}") self.lines.append("\n-------------------------------------------------------------\n") self.lines.append(f"Diretório: {self.benchmark}") self.cmb_bench.addItems(bench) self.maria_conn() #Inicia conexão com o banco de dados self.btn_start.setDisabled(False) #Habilita o botão para iniciar os testes self.pbar.setValue(10)#Coloca 10% na barra de progresso def get_param(self): print(self.line_time.text()) #Valida o que o usuário digitou try: if float(self.line_time.text()) < 0: QMessageBox.warning(None,"Erro!","Insira um valor numérico real não negativo no Tempo de Simulação!") return else: simu_time = float(self.line_time.text()) except: QMessageBox.warning(None,"Erro!","Insira um valor numérico real não negativo no Tempo de Simulação!") return #Define a função de turbulência da classe aircraft turb = self.cmb_turb.currentText() if turb == 'None': func_turb = "setNoTurbulence()" elif turb == 'Light': func_turb = "setLightTurbulence()" elif turb == 'Moderate': func_turb = "setModerateTurbulence()" elif turb == 'Severe': func_turb = "setSevereTurbulence()" param = [self.cmb_font.currentText(),self.cmb_type.currentText(),self.cmb_ampl.currentText(), self.cmb_bias.currentText(),self.cmb_freq.currentText().replace("π","*pi"),func_turb, self.cmb_ctrl1.currentIndex()+1,simu_time] print(param) return param def start(self): global Relatorio_TXT_Etapas, time, time_fail, delta_comm, delta_meas, ofc_falhas #Limpa variáveis globais time = [] time_fail = [] delta_comm = [] delta_meas = [] ofc_falhas = [] #Treina os parâmetros simu = self.cmb_bench.currentText() self.system = self.benchmark+"/"+self.cmb_bench.currentText() #Caminho do sistema #monitora(system) #chama o simulink para emular o sistema quest = f"O sistema para emulação no Simulink é {self.system}?" if QMessageBox.question(self,"Tem certeza?",quest,QMessageBox.Yes|QMessageBox.No, QMessageBox.No) == QMessageBox.Yes: self.metodo = self.cmb_treino.currentText() #Pega do combo o texto do modelo a treinar self.benchmark_simu = self.cmb_bench.currentText() self.parametros = self.get_param() #Recebe os parâmetros informados pelo usuário if not self.parametros: self.line_time.setFocus() return self.list_status.addItem(f"Treinando o modelo {simu} pelo método {self.metodo}") self.lines.append(f"Treinando o modelo {simu} pelo método {self.metodo}") self.pbar.setValue(15) #Chama a classe do treino tic_mdl = datetime.now() #Dá ao usuário a possibilidade de treinar ou carregar modelo quest2 = "Deseja treinar os dados? O não implica em carregar módulo default de treino" if QMessageBox.question(self,"Treinar ou não?",quest2,QMessageBox.Yes|QMessageBox.No, QMessageBox.No) == QMessageBox.Yes and self.metodo != 'Support Vector Machine': self.modelo = treina_modelo(self.metodo,True) method = "Treinado" else: #Se for SVM, carrega o modelo pronto ao invez de treinar self.modelo = treina_modelo(self.metodo,False) method = "Carregado" self.list_status.addItem(f"Modelo {simu} foi {method} pelo método {self.metodo} em {datetime.now()-tic_mdl}") self.lines.append(f"Modelo {simu} foi {method} pelo método {self.metodo} em {datetime.now()-tic_mdl}") self.pbar.setValue(25) self.list_status.addItem(f"Iniciando {self.system} no Simulink") self.lines.append(f"Iniciando {self.system} no Simulink") #monitora(system) #Associa o monitoramento self.list_status.addItem("Iniciando o MatLab (estimado: 13.6s)") self.lines.append("Iniciando o MatLab (estimado: 13.6s)") self.pbar.setValue(30) tic_matlab = datetime.now() self.eng = matlab.engine.start_matlab() #Background true para receber os valores self.list_status.addItem(f"O MatLab foi iniciado em {datetime.now()-tic_matlab}") self.lines.append(f"O MatLab foi iniciado em {datetime.now()-tic_matlab}") print(self.benchmark) self.eng.addpath(self.benchmark,nargout=0) #Função que carrega todas as variáveis necessárias pra se iniciar o simulink self.SimulinkPlant(self.parametros) self.list_status.addItem("Carregando modelo no SimuLink (estimado: 6.35s)") self.lines.append("Carregando modelo no SimuLink (estimado: 6.35s)") self.pbar.setValue(32.5) self.eng.eval(f"model = '{self.system}'",nargout=0) self.eng.eval(f"simulation.setSimulinkModel('{self.benchmark_simu}');",nargout=0) self.pbar.setValue(35) self.list_status.addItem("Carregando prâmetros ao modelo Simulink") self.lines.append("Carregando prâmetros ao modelo Simulink") tic_m = datetime.now() self.eng.eval("SimOut = sim(simulation.simulink_model, 'SrcWorkspace', 'current');",nargout=0) self.processo = self.eng.eval("""[SimOut.dx_comm SimOut.dx_meas SimOut.time];""") self.list_status.addItem(f"O Modelo {simu} foi treinado pelo método {self.metodo} em {datetime.now()-tic_m}") self.lines.append(f"O Modelo {simu} foi treinado pelo método {self.metodo} em {datetime.now()-tic_m}") self.pbar.setValue(40) self.list_status.addItem(f"Emulando {self.system} no Simulink") self.lines.append(f"Emulando {self.system} no Simulink") Relatorio_TXT_Etapas = self.lines #Emulação do sistema self.delta_comm = [] #Zera a lista de declara self.delta_meas = [] self.ofc_fail = [] #Armazena dados das falhas encontradas self.time_fail = [] self.time = [] self.barra = 40 self.janela = 40 #Tamanho da janela de dados a ser colatada self.i = 0 #Número da iteração self.total_itter = self.parametros[-1]*40 + 1 #Numero total de iterações #Loop do timar para plotar o gráfico self.timer = QTimer() self.timer.setInterval(10) self.timer.timeout.connect(self.update_graph) QMessageBox.information(self,"Aviso",f"O {self.system} será emulado") self.timer.start() else: pass def update_graph(self): global time, delta_comm, delta_meas, simulado, ofc_falhas, time_fail self.barra += (self.i/(self.total_itter) - 0.4*(self.i/self.total_itter))/(self.total_itter/200.4) #Recebe apenas os valores desejados, comando, medida e tempo self.delta_comm.append(self.processo[self.i][0]) self.delta_meas.append(self.processo[self.i][1]) self.time.append(self.processo[self.i][2]) dat = [self.processo[self.i][0],self.processo[self.i][1],self.processo[self.i][2]] win = [] for i in range(self.janela): if self.i < self.total_itter-self.janela: win.append(float(self.processo[i+self.i][0])) #Recebe o valor das janelas respectivas else: win.append(float(self.processo[randint(0,self.total_itter-1)][0])) #Revebe valor de indice aleatório w = array(win) result = int(self.modelo.predict(w.reshape(1,-1)).astype(int16)[0]) #Recebe 0 se não há falha e 1 se houver if result == 1: #Se é uma falha, acrescenta ao vetor o dado da falha self.ofc_fail.append(self.processo[self.i][1]) self.time_fail.append(self.processo[self.i][2]) reg = [dat[0],dat[1],dat[2],result,win] #Cria vetor com os dados e a classificação dos sinais self.update_db(reg,self.parametros) #Atualiza o banco de dados com a informação mais recente self.dx_comm.setData(self.time, self.delta_comm) self.dx_meas.setData(self.time, self.delta_meas) if self.ofc_fail: #Se houver dados nesse objeto self.dx_falhas.setData(self.time_fail, self.ofc_fail) else: self.dx_falhas.setData([0],[0]) self.pbar.setValue(self.barra)#Coloca % na barra de progresso self.i += 1 if self.i >= self.total_itter-1: print(self.barra) self.timer.stop() self.conn.commit() self.pbar.setValue(100) time = self.time delta_comm = self.delta_comm delta_meas = self.delta_meas ofc_falhas = self.ofc_fail time_fail = self.time_fail simulado = True #Variável que habilita impressão do gráfico QMessageBox.information(self,"Sucesso!",f"O processo {self.system} foi emulado com sucesso!") return def SimulinkPlant(self,param): """ Essa função objetiva declarar as variáveis necessárias para desenvolvimento da simulação Parameter ---------- param: array Array com todos os parâmetros fornecidos pelo usuário Returns ------- None. Mas realiza inúmeros comandos para simular a planta e declarar as variáveis """ #Iniciando o benchmark e carrega as principais variáveis ao console da API self.eng.eval("ofc_benchmark_init;",nargout=0) self.eng.eval("simulation.setSimulinkModel('ofc_benchmark_acquire');",nargout=0) #Carrega as variáveis: aircraft, ofc, servoModel, servoReal e simulation! self.eng.eval("servoReal.randomiseServoParameters()",nargout=0) #Faz o objeto servo real ficar aleatório self.eng.eval(f"ofc.setLocation('{param[0]}')",nargout=0) self.eng.eval(f"ofc.setType('{param[1]}')",nargout=0) self.eng.eval(f"ofc.setAmplitude({param[2]})",nargout=0) self.eng.eval(f"ofc.setBias({param[3]})",nargout=0) self.eng.eval(f"ofc.setFrequency({param[4]})",nargout=0) self.eng.eval("ofc.setPhase(0)",nargout=0) self.eng.eval("ofc.setStartTime(0)",nargout=0) self.eng.eval(f"aircraft.{param[5]}",nargout=0) #Cria sinal aleatório de controle self.eng.eval("""controls = {@(x)aircraft.setControlInput('FPA_control'), ... @(x)aircraft.setControlInput('NZ_step', x(1), x(2), x(3)), ... @(x)aircraft.setControlInput('NZ_sine', x(1), x(2), x(3), x(4)), ... @(x)aircraft.setControlInput('NZ_chirp', x(1))};""",nargout=0) self.eng.eval("controls{"+str(param[6])+"}([10^randi([-1 1]),randi([10 25]),randi([35, 50]),randi([0, 10])])", nargout=0) self.eng.eval(f"simulation.setStopTime({param[7]})",nargout=0) #Seta o tempo final de simulação def update_tb(self): global df self.pbar_db.setValue(0) #Zera a barra de progresso limite = self.n_itens.text() self.pbar_db.setValue(10) try: int(limite) except: QMessageBox.warning(self,"Atenção!","Insira um número inteiro!") return if int(limite) <= 0: QMessageBox.warning(self,"Atenção!","Insira um número positivo maior que zero!") return try: self.cur.execute(f"SELECT * FROM tb_ofc_dt ORDER BY id DESC LIMIT {limite};") except: self.maria_conn() self.cur.execute(f"SELECT * FROM tb_ofc_dt ORDER BY id DESC LIMIT {limite};") self.pbar_db.setValue(20) dados = self.cur.fetchall() #Convertendo os dados provenientes do banco de dados para um dataframe e então envia para tabela self.df = DataFrame(dados, columns = ["id","data","Deflexão comando","Deflexão medida", "Tempo (s)","Falha","Parâmetros"]) df = self.df self.pbar_db.setValue(30) self.db_table.setModel(pandasModel(self.df)) #Coloca os dados consultados na tabela self.db_table.setColumnWidth(0,45) self.db_table.setColumnWidth(1,120) self.db_table.setColumnWidth(2,105) self.db_table.setColumnWidth(3,105) self.db_table.setColumnWidth(4,65) self.db_table.setColumnWidth(5,42) self.db_table.setColumnWidth(6,self.tabela_param) self.pbar_db.setValue(100) def update_tb_1000(self): global Relatorio_TXT_Etapas, df try: self.cur.execute("SELECT * FROM tb_ofc_dt ORDER BY id DESC LIMIT 1000;") except: self.maria_conn() self.cur.execute("SELECT * FROM tb_ofc_dt ORDER BY id DESC LIMIT 1000;") falhas = self.cur.fetchall() self.list_status.addItem("O relatório de falhas foi gerado!") self.lines.append("O relatório de falhas foi gerado!") Relatorio_TXT_Etapas = self.lines self.df = DataFrame(falhas, columns = ["id","data","Deflexão comando","Deflexão medida", "Tempo (s)","Falha","Parâmetros"]) df = self.df self.db_table.setModel(pandasModel(self.df)) self.db_table.setColumnWidth(0,45) self.db_table.setColumnWidth(1,120) self.db_table.setColumnWidth(2,105) self.db_table.setColumnWidth(3,105) self.db_table.setColumnWidth(4,65) self.db_table.setColumnWidth(5,42) self.db_table.setColumnWidth(6,self.tabela_param) self.pbar_db.setValue(100) def update_db(self,dt,p): """ Essa função cadastra um item no banco de dados Parameters ---------- dt : tuple Linha proveniente do objeto de dados do matlab com três linhas (tempo, comando, medida e falha). p : list Lista dos parâmetros selecionados pelo usuário. Returns ------- None. """ global freq, ctrl, ampl fe = p[4].replace('*pi','π') pa = f"Metodo: {self.metodo}; F_OFC: {p[0]}; T_OFC: {p[1]}; Ampli.: {p[2]}; Bias: {p[3]}; Freq: {fe};" pa += f"Turb: {p[5].replace('()','')}; T_Ctrl: {ctrl[p[6]]}; t_simu: {p[7]}s; window: {dt[4]}" nw = datetime.now().strftime("%Y-%m-%d %H:%M:%S")#datetime.strftime(datetime.now(),"%d/%b/%Y - %H:%M") self.cur.execute("""INSERT INTO tb_ofc_dt (data,dx_comm,dx_meas,dt,falha,parametros) VALUES (?,?,?,?,?,?);""",[nw,dt[0],dt[1],dt[2],dt[3],pa]) def exp_graph(self): """ Essa função exporta o gráfico como está na tela em forma de imagem Returns ------- None. """ global time, delta_comm, delta_meas, simulado if simulado: ask_dir = "Escolha o diretório onde o deseja salvar o gráfico" #string que pergunta o diretório save = str(QFileDialog.getExistingDirectory(None,ask_dir)) #Pede ao usuário o diretório onde ele quer salvar self.grafico.plot(time,delta_comm, symbolSize=5,symbolBrush=("#15bf48"), pen=mkPen(color="#15bf48", width=2)) self.grafico.plot(time,delta_meas, symbolSize=5,symbolBrush=("#56fceb"), pen=mkPen(color="#56fceb", width=2)) self.grafico.plot(time_fail,ofc_falhas, symbolSize=15,symbol='x',symbolBrush=("#fc031c"), pen=mkPen(color="#323232", width=0.001)) exporter = exporters.ImageExporter(self.grafico.plotItem) #Exporta o objeto do gráfico exporter.export(save+f'/graph_{int(datetime.timestamp(datetime.now()))}.png') #Salva como png o gráfico QMessageBox.information(self,"Concluído!",f"Gráfico salvo com sucesso em: {save}") else: QMessageBox.warning(self,"Atenção!","O sistema ainda não foi emulado!") def exp_excel_all(self,aq): """ Essa função exporta os dados adquiridos para uma planilha do excel Returns ------- Não retorna parâmetros, apenas executa a ação de exportar para uma planilha """ global df, dff if not(df.empty) or not(dff.empty): #Se um dos dois não for vazio salve = str(QFileDialog.getExistingDirectory(None, "Escolha o diretório onde quer salvar o relatório")) save = salve+"/Relatório_OFC_MFF.xlsx" if aq==0 and not(df.empty): #Se os dados foram coletados, gera dos dados df.to_excel(save,sheet_name="Relatório_OFC_MFF",index=False) info_save_excel = f"O relatório geral foi salvo em {save}!" elif aq==1 and not(dff.empty): #Se as falhas foram coletadas, gera as falhas dff.to_excel(save.replace("MFF","FALHAS_MFF"),sheet_name="Relatório_Falhas_OFC_MFF",index=False) info_save_excel = f"O relatório final das falhas de caráter oscilatória foi salvo em {save}!" elif aq==2 and (not(df.empty) or not(dff.empty)): #Salva ambos if not(df.empty): df.to_excel(save,sheet_name="Relatório_OFC_MFF",index=False) info_save_excel = f"O relatório geral foi salvo em {save}!" if not(dff.empty): dff.to_excel(save.replace("MFF","FALHAS_MFF"),sheet_name="Relatório_Falhas_OFC_MFF",index=False) info_save_excel = f"O relatório final das falhas de caráter oscilatória foi salvo em {save}!" if not(df.empty) and not(dff.empty): info_save_excel = f"Os dois relatórios foram salvos em {save}!" QMessageBox.information(self,"Sucesso!",info_save_excel) else: info_not_save = "Nenhum dos dois relatórios foram gerados ainda!" QMessageBox.warning(self,"Atenção!",info_not_save) def exp_rep_excel(self): """ Essa função exporta os dados adquiridos para uma planilha do excel Returns ------- Não retorna parâmetros, apenas executa a ação de exportar para uma planilha """ self.exp_excel_all(1) def exp_dados_excel(self): """ Essa função exporta os dados adquiridos para uma planilha do excel Returns ------- Não retorna parâmetros, apenas executa a ação de exportar para uma planilha """ self.exp_excel_all(0) def exp_rep(self): """ Exporta um relatório em txt com os dados de falhas é acionado ao clickar duas vezes na caixa com logs duplo click em Returns ------- None. """ global Relatorio_TXT_Etapas #Insere na função a variável compartilhada entre classes if Relatorio_TXT_Etapas: dire = str(QFileDialog.getExistingDirectory(None, "Escolha o diretório para salvar o relatório em TXT!")) with open(dire+"/Relatorio_TXT_Etapas.txt",'w') as txt: txt.write("Relatório das etapas realizadas pelo software:\n") for line in Relatorio_TXT_Etapas: #Para cada linha, escreve no TXT txt.write("\n"+str(line)) QMessageBox.information(None,"Feito!","O relatório com as etapas realizadas foi salvo com sucesso!") else: QMessageBox.warning(None,"Atenção!","O relatório com as etapas ainda não foi gerado!") def update_rep_n(self): #Essa função irá popular a tabela de dados global dff limit = self.n_itens_rep.text() self.pbar_rep.setValue(10) #Reseta o valor da barra de progresso para 10% try: int(limit) except: QMessageBox.warning(self,"Atenção!","Insira um número inteiro!") return try: self.cur.execute(f"SELECT * FROM tb_ofc_dt WHERE falha = 1 ORDER BY id DESC LIMIT {limit}") except: self.maria_conn() self.cur.execute(f"SELECT * FROM tb_ofc_dt WHERE falha = 1 ORDER BY id DESC LIMIT {limit}") falhas = self.cur.fetchall() self.dff = DataFrame(falhas, columns = ["id","data","Deflexão comando","Deflexão medida", "Tempo (s)","Falha","Parâmetros"]) dff = self.dff self.rep_table.setModel(pandasModel(self.dff)) self.rep_table.setColumnWidth(0,45) self.rep_table.setColumnWidth(1,120) self.rep_table.setColumnWidth(2,110) self.rep_table.setColumnWidth(3,100) self.rep_table.setColumnWidth(4,65) self.rep_table.setColumnWidth(5,42) self.rep_table.setColumnWidth(6,self.tabela_param) self.pbar_rep.setValue(100) def update_rep(self): #Essa função irá popular a tabela de dados global dff try: self.cur.execute("SELECT * FROM tb_ofc_dt WHERE falha = 1 ORDER BY id DESC") except: self.maria_conn() self.cur.execute("SELECT * FROM tb_ofc_dt WHERE falha = 1 ORDER BY id DESC") falhas = self.cur.fetchall() self.dff = DataFrame(falhas, columns = ["id","data","Deflexão comando","Deflexão medida", "Tempo (s)","Falha","Parâmetros"]) dff = self.dff self.rep_table.setModel(pandasModel(self.dff)) self.rep_table.setColumnWidth(0,45) self.rep_table.setColumnWidth(1,120) self.rep_table.setColumnWidth(2,110) self.rep_table.setColumnWidth(3,100) self.rep_table.setColumnWidth(4,65) self.rep_table.setColumnWidth(5,42) self.rep_table.setColumnWidth(6,self.tabela_param) self.pbar_rep.setValue(100) def pdate_ampl(self): if self.cmb_font.currentText() in ['sensor','cs_sensor']: self.lbl_ampl.setText("Ampl(mm)/Bias(mm)/Freq(rad/s):") else: self.lbl_ampl.setText("Ampl(mA)/Bias(mA)/Freq(rad/s):") def filed(self): #Abre o arquivo em forma de dicionário e retorna o caminho completo (posição 0) path = QFileDialog.getOpenFileName(self,"Abre um arquivo do excel","","All Files(*);;*xlsx *xls") if (".xls" in path[0]): #Se for um arquivo do excel modelo = ExcelFile(path[0]).parse(0,skiprows=1)# Carrega o template em um Excel e a planilha self.relatorio.setModel(pandasModel(modelo)) self.tab2.setDisabled(False) self.tab2.update() self.update() else: #Se não for... QMessageBox.warning(self,"Arquivo incorreto","Escolha um arquivo do Excel (.xlsx ou .xls)!") def salva(self): #Salva o dataset do relatório em um arquivo excel global df, dff, Relatorio_TXT_Etapas, simulado if not(df.empty) or not(dff.empty) or Relatorio_TXT_Etapas or simulado: #Se tem algo para salvar, procede r1 = ""; r2 = ""; r3 = "" salve = str(QFileDialog.getExistingDirectory(None, "Escolha o diretório onde quer salvar o relatório")) save_total = salve+"/Relatório_OFC_MFF.xlsx" save_falhas = salve+"/Relatório_OFC_Falhas_MFF.xlsx" save_txt = salve+"/Relatorio_TXT_Etapas.txt" if not(df.empty): #Se o dataframe com os dados contar com mais de 0 codigos df.to_excel(save_total,sheet_name="Relatório_OFC_MFF",index=False) r1 = "Relatório_OFC_MFF," if not(dff.empty): #Se as falhas foram coletadas, gera as falhas dff.to_excel(save_falhas,sheet_name="Relatório_Falhas_OFC_MFF",index=False) r2 = "Relatório_Falhas_OFC_MFF," if len(Relatorio_TXT_Etapas) > 0: #Se o relatório txt não está vazio with open(save_txt,'w') as txt: txt.write("Relatório das etapas realizadas pelo software:\n") for line in Relatorio_TXT_Etapas: #Para cada linha, escreve no TXT txt.write("\n"+str(line)) r3 = "Relatorio_TXT_Etapas" duplas = (r1 or r2) or (r1 or r3) or (r2 or r3) #Uma dupla todos = (r1 and r2 and r3) #Todos solo = (r1 or r2 or r3) and not (duplas) #Apenas um if duplas: #Plural QMessageBox.information(self,"Sucesso!",f"Os relatórios: {r1}{r2}{r3} foram salvos!".replace(","," e ")) elif todos: QMessageBox.information(self,"Sucesso!",f"Os relatórios: {r1}{r2}{r3} foram salvos!") elif solo: #Singular QMessageBox.information(self,"Sucesso!",f"O relatório: {r1}{r2}{r3} foi salvo!") if simulado:#Se foi simulado, exporta o gráfico if (QMessageBox.warning(self,"Aviso","Você gostaria de salvar o gráfico?", QMessageBox.Yes|QMessageBox.No,QMessageBox.No) == QMessageBox.Yes): self.exp_graph() else: QMessageBox.warning(self,"Atenção!","Nenhum relatório foi gerado, portanto não há o que salvar!")
class AdminDialog(QDialog): """ Displays administrative related information and settings (logs, environment variables, third party packages etc...). """ def __init__(self, parent=None): super().__init__(parent) self.microbit_widget = None self.package_widget = None self.envar_widget = None def setup(self, log, settings, packages, mode, device_list): self.setMinimumSize(600, 400) self.setWindowTitle(_("Mu Administration")) widget_layout = QVBoxLayout() self.setLayout(widget_layout) self.tabs = QTabWidget() widget_layout.addWidget(self.tabs) button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) button_box.accepted.connect(self.accept) button_box.rejected.connect(self.reject) widget_layout.addWidget(button_box) # Tabs self.log_widget = LogWidget(self) self.log_widget.setup(log) self.tabs.addTab(self.log_widget, _("Current Log")) if mode.short_name in ["python", "web", "pygamezero"]: self.envar_widget = EnvironmentVariablesWidget(self) self.envar_widget.setup(settings.get("envars", "")) self.tabs.addTab(self.envar_widget, _("Python3 Environment")) if mode.short_name == "microbit": self.microbit_widget = MicrobitSettingsWidget(self) self.microbit_widget.setup( settings.get("minify", False), settings.get("microbit_runtime", ""), ) self.tabs.addTab(self.microbit_widget, _("BBC micro:bit Settings")) if mode.short_name in ["python", "web", "pygamezero"]: self.package_widget = PackagesWidget(self) self.package_widget.setup(packages) self.tabs.addTab(self.package_widget, _("Third Party Packages")) if mode.short_name == "esp": self.esp_widget = ESPFirmwareFlasherWidget(self) self.esp_widget.setup(mode, device_list) self.tabs.addTab(self.esp_widget, _("ESP Firmware flasher")) # Configure local. self.locale_widget = LocaleWidget(self) self.locale_widget.setup(settings.get("locale")) self.tabs.addTab(self.locale_widget, load_icon("language.svg"), _("Select Language")) self.log_widget.log_text_area.setFocus() def settings(self): """ Return a dictionary representation of the raw settings information generated by this dialog. Such settings will need to be processed / checked in the "logic" layer of Mu. """ settings = {} if self.envar_widget: settings["envars"] = self.envar_widget.text_area.toPlainText() if self.microbit_widget: settings["minify"] = self.microbit_widget.minify.isChecked() settings[ "microbit_runtime"] = self.microbit_widget.runtime_path.text() if self.package_widget: settings["packages"] = self.package_widget.text_area.toPlainText() settings["locale"] = self.locale_widget.get_locale() return settings
class JoggerDialog(QDialog): """Robot jogger dialog allows user to connect/disconnect to/from robot, modify its settings (axes, linear speed, angular speed, blend radius, tcp and coordinate frame), and control its pose and joint angles. """ class TabIndex: SETTINGS = 0 POSE = 1 JOINTS = 2 ROBOTS = ("abb", "ur", "franka") def __init__(self, parent=None): super().__init__(parent) self.robot = None QApplication.setStyle(QStyleFactory.create("Fusion")) QToolTip.setFont(QFont("SansSerif", 10)) self.setFixedSize(800, 450) self.setWindowTitle("Robot Jogger") self.setWindowIcon( QIcon(os.path.join(os.path.dirname(__file__), "robot.png"))) self.setToolTip("Robot jogger based on Common Robot Interface") self.robotLabel = QLabel("robot:") self.robotLabel.setFixedWidth(50) self.robotLabel.setFixedHeight(20) self.robotLabel.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.robotComboBox = QComboBox() self.robotComboBox.addItems(self.ROBOTS) self.robotComboBox.setCurrentText("abb") self.robotComboBox.setFixedWidth(70) self.robotComboBox.setFixedHeight(20) self.robotComboBox.setEnabled(True) self.ipLabel = QLabel("ip:") self.ipLabel.setFixedWidth(20) self.ipLabel.setFixedHeight(20) self.ipLabel.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.ipEditBox = LineEdit() self.ipEditBox.setFixedHeight(20) self.ipEditBox.setEnabled(True) self.portLabel = QLabel("port:") self.portLabel.setFixedWidth(40) self.portLabel.setFixedHeight(20) self.portLabel.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.portEditBox = LineEdit() self.portEditBox.setFixedWidth(60) self.portEditBox.setFixedHeight(20) self.portEditBox.setEnabled(True) self.connectPushButton = QPushButton("&Connect") self.connectPushButton.setFixedHeight(20) self.connectPushButton.setDefault(False) self.connectPushButton.setAutoDefault(True) self.connectPushButton.setEnabled(True) self.disconnectPushButton = QPushButton("&Disconnect") self.disconnectPushButton.setFixedHeight(20) self.disconnectPushButton.setDefault(False) self.disconnectPushButton.setAutoDefault(False) self.disconnectPushButton.setEnabled(False) topLayout = QGridLayout() topLayout.setHorizontalSpacing(20) topLayout.setVerticalSpacing(20) topLayout.setContentsMargins(10, 10, 10, 10) topLayout.addWidget(self.robotLabel, 0, 0) topLayout.addWidget(self.robotComboBox, 0, 1) topLayout.addWidget(self.ipLabel, 0, 2) topLayout.addWidget(self.ipEditBox, 0, 3) topLayout.addWidget(self.portLabel, 0, 4) topLayout.addWidget(self.portEditBox, 0, 5) topLayout.addWidget(self.connectPushButton, 0, 6) topLayout.addWidget(self.disconnectPushButton, 1, 6) robot = self.robotComboBox.currentText() self.createTabWidget(robot) self.tabWidget.setEnabled(False) mainLayout = QVBoxLayout() mainLayout.addLayout(topLayout) mainLayout.addWidget(self.tabWidget) self.setLayout(mainLayout) self.robotComboBox.currentIndexChanged[str].connect( self.onRobotChanged) self.ipEditBox.textEditingFinished.connect(self.onIPAddressChanged) self.portEditBox.textEditingFinished.connect(self.onPortChanged) self.connectPushButton.clicked.connect(self.onConnect) self.disconnectPushButton.clicked.connect(self.onDisconnect) self.axesComboBox.currentIndexChanged.connect(self.onAxesChanged) self.linearSpeedEditBox.textEditingFinished.connect( self.onLinearSpeedChanged) self.angularSpeedEditBox.textEditingFinished.connect( self.onAngularSpeedChanged) self.blendRadiusEditBox.textEditingFinished.connect( self.onBlendRadiusChanged) self.tcpEditWidget.editingFinished.connect(self.onTCPChanged) self.coordFrameEditWidget.editingFinished.connect( self.onCoordFrameChanged) self.poseControlWidget.valueChanged.connect(self.onPoseChanged) self.tabWidget.currentChanged.connect(self.onTabChanged) def createTabWidget(self, robot): self.tabWidget = QTabWidget() self.tabWidget.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Ignored) settingsTab = QWidget() self.createControlSettingsWidget() settingsTabLayout = QHBoxLayout() settingsTabLayout.setContentsMargins(5, 5, 5, 5) settingsTabLayout.addWidget(self.controlSettings) settingsTab.setLayout(settingsTabLayout) poseTab = QWidget() self.poseControlWidget = MultiSliderControlWidget( names=("x", "y", "z", "alpha", "beta", "gamma"), units=("mm", ) * 3 + ("°", ) * 3, ranges=((-1000, 1000), ) * 3 + ((-360, 360), ) * 3, values=(0, ) * 6, ) poseTabLayout = QHBoxLayout() poseTabLayout.setContentsMargins(5, 5, 5, 5) poseTabLayout.addWidget(self.poseControlWidget) poseTab.setLayout(poseTabLayout) jointsTab = QWidget() # widget content depends on robot type self.tabWidget.addTab(settingsTab, "&Settings") self.tabWidget.addTab(poseTab, "&Pose") self.tabWidget.addTab(jointsTab, "&Joints") def createControlSettingsWidget(self): self.controlSettings = QWidget() self.minLinearSpeed = 0.001 self.maxLinearSpeed = 1000 self.minAngularSpeed = 0.001 self.maxAngularSpeed = 1000 self.minBlendRadius = 0 self.maxBlendRadius = 1000 miscSettingsGroupBox = QGroupBox(title="Misc:") self.axesLabel = QLabel("axes:") self.axesLabel.setFixedWidth(50) self.axesLabel.setFixedHeight(20) self.axesComboBox = QComboBox() self.axesComboBox.addItems(SyncRobot.EULER_AXES) self.axesComboBox.setCurrentText("rxyz") self.axesComboBox.setFixedHeight(20) self.axisUnitsLabel = QLabel() self.axisUnitsLabel.setFixedWidth(40) self.axisUnitsLabel.setFixedHeight(20) self.linearSpeedLabel = QLabel("linear\nspeed:") self.linearSpeedLabel.setFixedWidth(50) self.linearSpeedLabel.setFixedHeight(40) self.linearSpeedEditBox = LineEdit() self.linearSpeedEditBox.setText("{:.1f}".format(0)) self.linearSpeedEditBox.setFixedHeight(20) self.linearSpeedEditBox.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.linearSpeedUnitsLabel = QLabel("mm/s") self.linearSpeedUnitsLabel.setFixedWidth(40) self.linearSpeedUnitsLabel.setFixedHeight(20) self.angularSpeedLabel = QLabel("angular\nspeed:") self.angularSpeedLabel.setFixedWidth(50) self.angularSpeedLabel.setFixedHeight(40) self.angularSpeedEditBox = LineEdit() self.angularSpeedEditBox.setText("{:.1f}".format(0)) self.angularSpeedEditBox.setFixedHeight(20) self.angularSpeedEditBox.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.angularSpeedUnitsLabel = QLabel("°/s") self.angularSpeedUnitsLabel.setFixedWidth(40) self.angularSpeedUnitsLabel.setFixedHeight(20) self.blendRadiusLabel = QLabel("blend\nradius:") self.blendRadiusLabel.setFixedWidth(50) self.blendRadiusLabel.setFixedHeight(40) self.blendRadiusEditBox = LineEdit() self.blendRadiusEditBox.setText("{:.1f}".format(0)) self.blendRadiusEditBox.setFixedHeight(20) self.blendRadiusEditBox.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.blendRadiusEditBox.setEnabled(False) self.blendRadiusUnitsLabel = QLabel("mm") self.blendRadiusUnitsLabel.setFixedWidth(40) self.blendRadiusUnitsLabel.setFixedHeight(20) miscSettingsLayout = QGridLayout() miscSettingsLayout.setHorizontalSpacing(15) miscSettingsLayout.setVerticalSpacing(5) miscSettingsLayout.addWidget(self.axesLabel, 0, 0) miscSettingsLayout.addWidget(self.axesComboBox, 0, 1) miscSettingsLayout.addWidget(self.linearSpeedLabel, 1, 0) miscSettingsLayout.addWidget(self.linearSpeedEditBox, 1, 1) miscSettingsLayout.addWidget(self.linearSpeedUnitsLabel, 1, 2) miscSettingsLayout.addWidget(self.angularSpeedLabel, 2, 0) miscSettingsLayout.addWidget(self.angularSpeedEditBox, 2, 1) miscSettingsLayout.addWidget(self.angularSpeedUnitsLabel, 2, 2) miscSettingsLayout.addWidget(self.blendRadiusLabel, 3, 0) miscSettingsLayout.addWidget(self.blendRadiusEditBox, 3, 1) miscSettingsLayout.addWidget(self.blendRadiusUnitsLabel, 3, 2) miscSettingsGroupBox.setLayout(miscSettingsLayout) self.tcpEditWidget = MultiNumberEditWidget( names=("x", "y", "z", "alpha", "beta", "gamma"), units=("mm", ) * 3 + ("°", ) * 3, ranges=((-1000, 1000), ) * 3 + ((-360, 360), ) * 3, values=(0, ) * 6, ) tcpGroupBox = QGroupBox(title="TCP:") tcpLayout = QVBoxLayout() tcpLayout.addWidget(self.tcpEditWidget) tcpGroupBox.setLayout(tcpLayout) self.coordFrameEditWidget = MultiNumberEditWidget( names=("x", "y", "z", "alpha", "beta", "gamma"), units=("mm", ) * 3 + ("°", ) * 3, ranges=((-1000, 1000), ) * 3 + ((-360, 360), ) * 3, values=(0, ) * 6, ) coordFrameGroupBox = QGroupBox(title="Coordinate Frame:") coordFrameLayout = QVBoxLayout() coordFrameLayout.addWidget(self.coordFrameEditWidget) coordFrameGroupBox.setLayout(coordFrameLayout) controlSettingsLayout = QGridLayout() controlSettingsLayout.setHorizontalSpacing(15) controlSettingsLayout.setVerticalSpacing(5) controlSettingsLayout.addWidget(miscSettingsGroupBox, 0, 0) controlSettingsLayout.addWidget(tcpGroupBox, 0, 1) controlSettingsLayout.addWidget(coordFrameGroupBox, 0, 2) self.controlSettings.setLayout(controlSettingsLayout) def closeEvent(self, event): reply = QMessageBox.question(self, "Message", "Are you sure you want to quit?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: if self.robot is not None: self.robot.close() event.accept() else: event.ignore() def onRobotChanged(self, value): logger.debug("JoggerDialog.onRobotChanged(value={})".format(value)) if value == "franka": # No need to specify port for Franka arm self.portEditBox.setText("") self.portEditBox.setEnabled(False) elif value == "ur": # UR controller always listens on port 30004 self.portEditBox.setText(str(30004)) self.portEditBox.setEnabled(False) else: self.portEditBox.setEnabled(True) def onIPAddressChanged(self): ip = self.sender().text() logger.debug("JoggerDialog.onIPAddressChanged(text={})".format(ip)) if not isValidIPAddress(ip): msg = QErrorMessage(self) msg.showMessage("Invalid IP address") msg.exec_() self.sender().setFocus() def onPortChanged(self): port = self.sender().text() logger.debug("JoggerDialog.onPortChanged(text={})".format(port)) if not isValidPortNumber(port): msg = QErrorMessage(self) msg.showMessage("Invalid port number") msg.exec_() self.sender().setFocus() def onConnect(self): robot = self.robotComboBox.currentText() ip = self.ipEditBox.text() port = self.portEditBox.text() logger.debug("JoggerDialog.onConnect(robot={}, ip={}, port={})".format( robot, ip, port)) if robot in ("abb", 'ur') and (not isValidIPAddress(ip) or not isValidPortNumber(port)): msg = QErrorMessage(self) msg.showMessage("Please specify valid IP address and port number") msg.exec_() self.sender().setFocus() return if robot == "franka" and not isValidIPAddress( ip): # no need to specify port for Franka arm msg = QErrorMessage(self) msg.showMessage("Please specify valid IP address") msg.exec_() self.sender().setFocus() return try: if robot == "abb": port = int(port) self.robot = SyncRobot(ABBController(ip, port)) elif robot == "ur": self.robot = SyncRobot(RTDEController(ip)) elif robot == "franka": self.robot = SyncRobot(PyfrankaController(ip)) except: msg = QErrorMessage(self) msg.showMessage("Failed to connect to server") msg.exec_() else: self.robotComboBox.setEnabled(False) self.ipEditBox.setEnabled(False) self.portEditBox.setEnabled(False) self.connectPushButton.setEnabled(False) self.disconnectPushButton.setEnabled(True) self.axesComboBox.setCurrentText(self.robot.axes) if robot == "franka": # Disable settings that don't apply to Franka arm self.linearSpeedEditBox.setText("n/a") self.angularSpeedEditBox.setText("n/a") self.blendRadiusEditBox.setText("n/a") self.linearSpeedEditBox.setEnabled(False) self.blendRadiusEditBox.setEnabled(False) self.angularSpeedEditBox.setEnabled(False) else: self.linearSpeedEditBox.setText("{:.1f}".format( self.robot.linear_speed)) self.angularSpeedEditBox.setText("{:.1f}".format( self.robot.angular_speed)) self.blendRadiusEditBox.setText("{:.1f}".format( self.robot.blend_radius)) self.linearSpeedEditBox.setEnabled(True) self.blendRadiusEditBox.setEnabled(True) self.angularSpeedEditBox.setEnabled(True) self.tcpEditWidget.value = self.robot.tcp self.coordFrameEditWidget.value = self.robot.coord_frame # Set up joint angles tab - need to do this dynamically now because layout depends on # whether ABB/UR5 robot is selected (6 joints), or Franka robot is selected (7 joints) jointsTab = QWidget() n_joints = 7 if robot == "franka" else 6 self.jointControlWidget = MultiSliderControlWidget( names=["joint {}".format(i + 1) for i in range(n_joints)], units=("°", ) * n_joints, ranges=((-360, 360), ) * n_joints, values=(0, ) * n_joints, ) self.jointControlWidget.valueChanged.connect( self.onJointAnglesChanged) jointsTabLayout = QHBoxLayout() jointsTabLayout.setContentsMargins(5, 5, 5, 5) jointsTabLayout.addWidget(self.jointControlWidget) jointsTab.setLayout(jointsTabLayout) self.tabWidget.removeTab(2) self.tabWidget.addTab(jointsTab, "&Joints") self.tabWidget.setCurrentIndex(self.TabIndex.SETTINGS) self.tabWidget.setEnabled(True) def onDisconnect(self): logger.debug("JoggerDialog.onDisconnect") self.robotComboBox.setEnabled(True) self.ipEditBox.setEnabled(True) robot = self.robotComboBox.currentText() if robot == "abb": self.portEditBox.setEnabled(True) elif robot in ("ur", "franka"): self.portEditBox.setEnabled(False) self.connectPushButton.setEnabled(True) self.disconnectPushButton.setEnabled(False) self.tabWidget.setCurrentIndex(self.TabIndex.SETTINGS) self.tabWidget.setEnabled(False) self.robot.close() self.robot = None def onAxesChanged(self): axes = self.sender().currentText() logger.debug("JoggerDialog.onAxesChanged(axes={})".format(axes)) self.robot.axes = axes self.tcpEditWidget.value = self.robot.tcp self.coordFrameEditWidget.value = self.robot.coord_frame def onLinearSpeedChanged(self): linearSpeed = self.sender().text() logger.debug( "JoggerDialog.onLinearSpeedChanged(speed={})".format(linearSpeed)) if isValidNumber(linearSpeed, self.minLinearSpeed, self.maxLinearSpeed): linearSpeed = float(linearSpeed) self.sender().setText("{:.1f}".format(linearSpeed)) self.robot.linear_speed = linearSpeed else: msg = QErrorMessage(self) msg.showMessage("Invalid or out of range [{}, {}] number".format( self.minLinearSpeed, self.maxLinearSpeed)) msg.exec_() self.sender().setText("{:.1f}".format(0)) self.sender().setFocus() def onAngularSpeedChanged(self): angularSpeed = self.sender().text() logger.debug("JoggerDialog.onAngularSpeedChanged(speed={})".format( angularSpeed)) if isValidNumber(angularSpeed, self.minAngularSpeed, self.maxAngularSpeed): angularSpeed = float(angularSpeed) self.sender().setText("{:.1f}".format(angularSpeed)) self.robot.angular_speed = angularSpeed else: msg = QErrorMessage(self) msg.showMessage("Invalid or out of range [{}, {}] number".format( self.minAngularSpeed, self.maxAngularSpeed)) msg.exec_() self.sender().setText("{:.1f}".format(0)) self.sender().setFocus() def onBlendRadiusChanged(self): blendRadius = self.blendRadiusEditBox.text() logger.debug( "JoggerDialog.onBlendRadiusChanged(radius={})".format(blendRadius)) if isValidNumber(blendRadius, self.minBlendRadius, self.maxBlendRadius): blendRadius = float(blendRadius) self.sender().setText("{:.1f}".format(blendRadius)) self.robot.blend_radius = blendRadius else: msg = QErrorMessage(self) msg.showMessage("Invalid or out of range [{}, {}] number".format( self.minBlendRadius, self.maxBlendRadius)) msg.exec_() self.sender().setText("{:.1f}".format(0)) self.sender().setFocus() def onTCPChanged(self): logger.debug("JoggerDialog.onTCPChanged(tcp={})".format( self.tcpEditWidget.value)) self.robot.tcp = self.tcpEditWidget.value def onCoordFrameChanged(self): logger.debug("JoggerDialog.onCoordFrameChanged(frame={})".format( self.coordFrameEditWidget.value)) self.robot.coord_frame = self.coordFrameEditWidget.value def onPoseChanged(self): logger.debug("JoggerDialog.onPoseChanged(pose={})".format( self.poseControlWidget.value)) self.robot.move_linear(self.poseControlWidget.value) def onJointAnglesChanged(self): logger.debug("JoggerDialog.onJointAnglesChanged(angles={})".format( self.jointControlWidget.value)) self.robot.move_joints(self.jointControlWidget.value) def onTabChanged(self, index): logger.debug("JoggerDialog.onTabChanged(index={}, text={})".format( index, self.tabWidget.tabText(index))) if index == self.TabIndex.POSE: self.poseControlWidget.value = self.robot.pose elif index == self.TabIndex.JOINTS: self.jointControlWidget.value = self.robot.joint_angles
class ScoreWizardDialog(QDialog): pitchLanguageChanged = pyqtSignal(str) def __init__(self, mainwindow): super(ScoreWizardDialog, self).__init__(mainwindow) self.addAction(mainwindow.actionCollection.help_whatsthis) self._pitchLanguage = None layout = QVBoxLayout() self.setLayout(layout) self.tabs = QTabWidget() b = self.dialogButtons = QDialogButtonBox() b.setStandardButtons(QDialogButtonBox.Reset | QDialogButtonBox.Ok | QDialogButtonBox.Cancel) b.accepted.connect(self.accept) b.rejected.connect(self.reject) userguide.addButton(b, "scorewiz") b.button(QDialogButtonBox.Reset).clicked.connect(self.reset) self.previewButton = b.addButton('', QDialogButtonBox.ActionRole) self.previewButton.clicked.connect(self.showPreview) layout.addWidget(self.tabs) layout.addWidget(b) self.header = Header(self) self.tabs.addTab(self.header, '') self.parts = Parts(self) self.tabs.addTab(self.parts, '') self.settings = Settings(self) self.tabs.addTab(self.settings, '') self.tabs.setCurrentIndex(0) self.tabs.widget(0).widget() # activate it self.tabs.currentChanged.connect(self.slotCurrentChanged) qutil.saveDialogSize(self, "scorewiz/dialog/size") app.translateUI(self) self.accepted.connect(self.slotAccepted) def translateUI(self): self.setWindowTitle(app.caption(_("Score Setup Wizard"))) for i in range(self.tabs.count()): self.tabs.setTabText(i, self.tabs.widget(i).title()) self.dialogButtons.button(QDialogButtonBox.Reset).setText(_("Clear")) self.dialogButtons.button(QDialogButtonBox.Reset).setToolTip( _("Clears the current page of the Score Wizard.")) self.previewButton.setText(_("Preview")) def slotCurrentChanged(self, i): """Lazy-loads the tab's page if shown for the first time.""" self.tabs.widget(i).widget() def reset(self): self.tabs.currentWidget().widget().clear() def setPitchLanguage(self, language): if language != self._pitchLanguage: self._pitchLanguage = language self.pitchLanguageChanged.emit(language) def pitchLanguage(self): if self._pitchLanguage is None: # load setting; saving occurs in .settings.py lang = QSettings().value('scorewiz/lilypond/pitch_language', '', str) from .scoreproperties import keyNames if lang not in keyNames: lang = '' self._pitchLanguage = lang return self._pitchLanguage def slotAccepted(self): """Makes the score and puts it in the editor.""" from . import build builder = build.Builder(self) # get the builder text = builder.text() # get the source text lydoc = ly.document.Document(text) # temporarily store it in a lydoc cursor = ly.document.Cursor(lydoc) # make a cursor selecting it indent.indenter().indent(cursor) # indent it according to user prefs doc = app.openUrl(QUrl()) # get a new Frescobaldi document doc.setPlainText(lydoc.plaintext()) # write the text in it doc.setModified(False) # make it "not modified" self.parent().setCurrentDocument(doc) def showPreview(self): """Shows a preview.""" # get the document and fill in some example music from . import preview, build builder = build.Builder(self) doc = builder.document() preview.examplify(doc) # preview it import musicpreview dlg = musicpreview.MusicPreviewDialog(self) dlg.preview(builder.text(doc), _("Score Preview")) dlg.exec_() dlg.cleanup()
class SelectFileDataWidget(QWidget): def __init__(self, outer_fk): super().__init__() self.outer_fk = outer_fk self.tabWidget = QTabWidget() self.vbox = QVBoxLayout() self.__files_tab = QWidget() self.__files_tab.setLayout(self.__create_files_tab_layout()) self.tabWidget.addTab(self.__files_tab, 'Files List') self.__opened_files = {} self.vbox.addWidget(self.tabWidget) self.setLayout(self.vbox) def __create_files_tab_layout(self): self.hor_layout = QVBoxLayout() self.label = QLabel("SEISMOGRAM FILES") self.__open_folder_btn = QToolButton(self) __open_folder_btn_size_policy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) self.__open_folder_btn.setSizePolicy(__open_folder_btn_size_policy) self.__open_folder_btn.setDefaultAction( OpenFilesAction(self, self._load_data)) self.hor_layout.addWidget(self.label) self.hor_layout.addWidget(self.__open_folder_btn) self.table = QTableWidget(self) self.table.setColumnCount(3) self.table.setHorizontalHeaderLabels(["File", "Type", "Fix"]) self.table.cellClicked.connect(self.__cell_click) self.table_header = self.table.horizontalHeader() self.table_header.setSectionResizeMode(0, QHeaderView.Stretch) self.table_header.setSectionResizeMode(1, QHeaderView.ResizeToContents) self.table_header.setSectionResizeMode(2, QHeaderView.ResizeToContents) self.hor_layout.addWidget(self.table) return self.hor_layout def _load_data(self, path): for i in path[0]: _, name = os.path.split(i) if (not name in self.__opened_files.keys()): self.__opened_files[name] = i self.add_row(name) def get_open_file_dialog_load_data_func(self): return self._load_data def add_row(self, filename): row = self.table.rowCount() self.table.setRowCount(row + 1) cell = QTableWidgetItem(str(filename)) qc = QComboBox() qchb = QHBoxLayout() qchb.addWidget(QCheckBox()) qchb.setAlignment(Qt.AlignCenter) chkBoxItem = QTableWidgetItem() chkBoxItem.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) chkBoxItem.setCheckState(Qt.Unchecked) qc.addItem("Null") qc.addItem("None") self.table.setItem(row, 0, cell) self.table.setCellWidget(row, 1, qc) self.table.setCellWidget(row, 2, WidgetWrapper.WidgetWrapper(qchb)) # self.table.setItem(row, 2, chkBoxItem) def __cell_click(self, *args, **kwargs): if args[1] == 0: self.outer_fk(self.__opened_files[self.table.item( args[0], args[1]).text()])
class AddLinkWindow_Ui(QWidget): def __init__(self, persepolis_setting): super().__init__() self.persepolis_setting = persepolis_setting # get icons name icons = ':/' + \ str(self.persepolis_setting.value('settings/icons')) + '/' self.setMinimumSize(QtCore.QSize(520, 425)) self.setWindowIcon( QIcon.fromTheme('persepolis', QIcon(':/persepolis.svg'))) window_verticalLayout = QVBoxLayout() # add link tab widget self.add_link_tabWidget = QTabWidget(self) window_verticalLayout.addWidget(self.add_link_tabWidget) # link tab self.link_tab = QWidget() link_tab_verticalLayout = QVBoxLayout(self.link_tab) link_tab_verticalLayout.setContentsMargins(21, 21, 21, 81) self.link_frame = QFrame(self.link_tab) self.link_frame.setFrameShape(QFrame.StyledPanel) self.link_frame.setFrameShadow(QFrame.Raised) horizontalLayout_2 = QHBoxLayout(self.link_frame) self.link_verticalLayout = QVBoxLayout() # link -> self.link_horizontalLayout = QHBoxLayout() self.link_label = QLabel(self.link_frame) self.link_horizontalLayout.addWidget(self.link_label) self.link_lineEdit = QLineEdit(self.link_frame) self.link_horizontalLayout.addWidget(self.link_lineEdit) self.link_verticalLayout.addLayout(self.link_horizontalLayout) horizontalLayout_2.addLayout(self.link_verticalLayout) link_tab_verticalLayout.addWidget(self.link_frame) # add change_name field -> change_name_horizontalLayout = QHBoxLayout() self.change_name_checkBox = QCheckBox(self.link_frame) change_name_horizontalLayout.addWidget(self.change_name_checkBox) self.change_name_lineEdit = QLineEdit(self.link_frame) change_name_horizontalLayout.addWidget(self.change_name_lineEdit) self.link_verticalLayout.addLayout(change_name_horizontalLayout) # add_category -> queue_horizontalLayout = QHBoxLayout() self.queue_frame = QFrame(self) self.queue_frame.setFrameShape(QFrame.StyledPanel) self.queue_frame.setFrameShadow(QFrame.Raised) add_queue_horizontalLayout = QHBoxLayout(self.queue_frame) self.add_queue_label = QLabel(self.queue_frame) add_queue_horizontalLayout.addWidget(self.add_queue_label) self.add_queue_comboBox = QComboBox(self.queue_frame) add_queue_horizontalLayout.addWidget(self.add_queue_comboBox) queue_horizontalLayout.addWidget(self.queue_frame) queue_horizontalLayout.addStretch(1) self.size_label = QLabel(self) queue_horizontalLayout.addWidget(self.size_label) link_tab_verticalLayout.addLayout(queue_horizontalLayout) self.add_link_tabWidget.addTab(self.link_tab, '') # proxy tab self.proxy_tab = QWidget(self) proxy_verticalLayout = QVBoxLayout(self.proxy_tab) proxy_verticalLayout.setContentsMargins(21, 21, 21, 171) proxy_horizontalLayout = QHBoxLayout() self.proxy_checkBox = QCheckBox(self.proxy_tab) self.detect_proxy_pushButton = QPushButton(self.proxy_tab) self.detect_proxy_label = QLabel(self.proxy_tab) proxy_horizontalLayout.addWidget(self.proxy_checkBox) proxy_horizontalLayout.addWidget(self.detect_proxy_label) proxy_horizontalLayout.addWidget(self.detect_proxy_pushButton) proxy_verticalLayout.addLayout(proxy_horizontalLayout) self.proxy_frame = QFrame(self.proxy_tab) self.proxy_frame.setFrameShape(QFrame.StyledPanel) self.proxy_frame.setFrameShadow(QFrame.Raised) gridLayout = QGridLayout(self.proxy_frame) self.ip_label = QLabel(self.proxy_frame) gridLayout.addWidget(self.ip_label, 0, 0, 1, 1) self.ip_lineEdit = QLineEdit(self.proxy_frame) self.ip_lineEdit.setInputMethodHints(QtCore.Qt.ImhNone) gridLayout.addWidget(self.ip_lineEdit, 0, 1, 1, 1) self.port_label = QLabel(self.proxy_frame) gridLayout.addWidget(self.port_label, 0, 2, 1, 1) self.port_spinBox = QSpinBox(self.proxy_frame) self.port_spinBox.setMaximum(65535) self.port_spinBox.setSingleStep(1) gridLayout.addWidget(self.port_spinBox, 0, 3, 1, 1) self.proxy_user_label = QLabel(self.proxy_frame) gridLayout.addWidget(self.proxy_user_label, 2, 0, 1, 1) self.proxy_user_lineEdit = QLineEdit(self.proxy_frame) gridLayout.addWidget(self.proxy_user_lineEdit, 2, 1, 1, 1) self.proxy_pass_label = QLabel(self.proxy_frame) gridLayout.addWidget(self.proxy_pass_label, 2, 2, 1, 1) self.proxy_pass_lineEdit = QLineEdit(self.proxy_frame) self.proxy_pass_lineEdit.setEchoMode(QLineEdit.Password) gridLayout.addWidget(self.proxy_pass_lineEdit, 2, 3, 1, 1) proxy_verticalLayout.addWidget(self.proxy_frame) self.add_link_tabWidget.addTab(self.proxy_tab, '') # more options tab self.more_options_tab = QWidget(self) more_options_tab_verticalLayout = QVBoxLayout(self.more_options_tab) # download UserName & Password -> download_horizontalLayout = QHBoxLayout() download_horizontalLayout.setContentsMargins(-1, 10, -1, -1) download_verticalLayout = QVBoxLayout() self.download_checkBox = QCheckBox(self.more_options_tab) download_verticalLayout.addWidget(self.download_checkBox) self.download_frame = QFrame(self.more_options_tab) self.download_frame.setFrameShape(QFrame.StyledPanel) self.download_frame.setFrameShadow(QFrame.Raised) gridLayout_2 = QGridLayout(self.download_frame) self.download_user_lineEdit = QLineEdit(self.download_frame) gridLayout_2.addWidget(self.download_user_lineEdit, 0, 1, 1, 1) self.download_user_label = QLabel(self.download_frame) gridLayout_2.addWidget(self.download_user_label, 0, 0, 1, 1) self.download_pass_label = QLabel(self.download_frame) gridLayout_2.addWidget(self.download_pass_label, 1, 0, 1, 1) self.download_pass_lineEdit = QLineEdit(self.download_frame) self.download_pass_lineEdit.setEchoMode(QLineEdit.Password) gridLayout_2.addWidget(self.download_pass_lineEdit, 1, 1, 1, 1) download_verticalLayout.addWidget(self.download_frame) download_horizontalLayout.addLayout(download_verticalLayout) # select folder -> self.folder_frame = QFrame(self.more_options_tab) self.folder_frame.setFrameShape(QFrame.StyledPanel) self.folder_frame.setFrameShadow(QFrame.Raised) gridLayout_3 = QGridLayout(self.folder_frame) self.download_folder_lineEdit = QLineEdit(self.folder_frame) gridLayout_3.addWidget(self.download_folder_lineEdit, 2, 0, 1, 1) self.folder_pushButton = QPushButton(self.folder_frame) gridLayout_3.addWidget(self.folder_pushButton, 3, 0, 1, 1) self.folder_pushButton.setIcon(QIcon(icons + 'folder')) self.folder_label = QLabel(self.folder_frame) self.folder_label.setAlignment(QtCore.Qt.AlignCenter) gridLayout_3.addWidget(self.folder_label, 1, 0, 1, 1) download_horizontalLayout.addWidget(self.folder_frame) more_options_tab_verticalLayout.addLayout(download_horizontalLayout) # start time -> time_limit_horizontalLayout = QHBoxLayout() time_limit_horizontalLayout.setContentsMargins(-1, 10, -1, -1) start_verticalLayout = QVBoxLayout() self.start_checkBox = QCheckBox(self.more_options_tab) start_verticalLayout.addWidget(self.start_checkBox) self.start_frame = QFrame(self.more_options_tab) self.start_frame.setFrameShape(QFrame.StyledPanel) self.start_frame.setFrameShadow(QFrame.Raised) horizontalLayout_5 = QHBoxLayout(self.start_frame) self.start_time_qDataTimeEdit = QDateTimeEdit(self.start_frame) self.start_time_qDataTimeEdit.setDisplayFormat('H:mm') horizontalLayout_5.addWidget(self.start_time_qDataTimeEdit) start_verticalLayout.addWidget(self.start_frame) time_limit_horizontalLayout.addLayout(start_verticalLayout) # end time -> end_verticalLayout = QVBoxLayout() self.end_checkBox = QCheckBox(self.more_options_tab) end_verticalLayout.addWidget(self.end_checkBox) self.end_frame = QFrame(self.more_options_tab) self.end_frame.setFrameShape(QFrame.StyledPanel) self.end_frame.setFrameShadow(QFrame.Raised) horizontalLayout_6 = QHBoxLayout(self.end_frame) self.end_time_qDateTimeEdit = QDateTimeEdit(self.end_frame) self.end_time_qDateTimeEdit.setDisplayFormat('H:mm') horizontalLayout_6.addWidget(self.end_time_qDateTimeEdit) end_verticalLayout.addWidget(self.end_frame) time_limit_horizontalLayout.addLayout(end_verticalLayout) # limit Speed -> limit_verticalLayout = QVBoxLayout() self.limit_checkBox = QCheckBox(self.more_options_tab) limit_verticalLayout.addWidget(self.limit_checkBox) self.limit_frame = QFrame(self.more_options_tab) self.limit_frame.setFrameShape(QFrame.StyledPanel) self.limit_frame.setFrameShadow(QFrame.Raised) horizontalLayout_4 = QHBoxLayout(self.limit_frame) self.limit_spinBox = QDoubleSpinBox(self.limit_frame) self.limit_spinBox.setMinimum(1) self.limit_spinBox.setMaximum(1023) horizontalLayout_4.addWidget(self.limit_spinBox) self.limit_comboBox = QComboBox(self.limit_frame) self.limit_comboBox.addItem("") self.limit_comboBox.addItem("") horizontalLayout_4.addWidget(self.limit_comboBox) limit_verticalLayout.addWidget(self.limit_frame) time_limit_horizontalLayout.addLayout(limit_verticalLayout) more_options_tab_verticalLayout.addLayout(time_limit_horizontalLayout) # number of connections -> connections_horizontalLayout = QHBoxLayout() connections_horizontalLayout.setContentsMargins(-1, 10, -1, -1) self.connections_frame = QFrame(self.more_options_tab) self.connections_frame.setFrameShape(QFrame.StyledPanel) self.connections_frame.setFrameShadow(QFrame.Raised) horizontalLayout_3 = QHBoxLayout(self.connections_frame) self.connections_label = QLabel(self.connections_frame) horizontalLayout_3.addWidget(self.connections_label) self.connections_spinBox = QSpinBox(self.connections_frame) self.connections_spinBox.setMinimum(1) self.connections_spinBox.setMaximum(16) self.connections_spinBox.setProperty("value", 16) horizontalLayout_3.addWidget(self.connections_spinBox) connections_horizontalLayout.addWidget(self.connections_frame) connections_horizontalLayout.addStretch(1) more_options_tab_verticalLayout.addLayout(connections_horizontalLayout) self.add_link_tabWidget.addTab(self.more_options_tab, '') # ok cancel download_later buttons -> buttons_horizontalLayout = QHBoxLayout() buttons_horizontalLayout.addStretch(1) self.download_later_pushButton = QPushButton(self) self.download_later_pushButton.setIcon(QIcon(icons + 'stop')) self.cancel_pushButton = QPushButton(self) self.cancel_pushButton.setIcon(QIcon(icons + 'remove')) self.ok_pushButton = QPushButton(self) self.ok_pushButton.setIcon(QIcon(icons + 'ok')) buttons_horizontalLayout.addWidget(self.download_later_pushButton) buttons_horizontalLayout.addWidget(self.cancel_pushButton) buttons_horizontalLayout.addWidget(self.ok_pushButton) window_verticalLayout.addLayout(buttons_horizontalLayout) self.setLayout(window_verticalLayout) # labels -> self.setWindowTitle("Enter Your Link") self.link_label.setText("Download Link : ") self.add_queue_label.setText("Add to category : ") self.change_name_checkBox.setText("Change File Name : ") self.detect_proxy_pushButton.setText("Detect system proxy setting") self.proxy_checkBox.setText("Proxy") self.proxy_pass_label.setText("Proxy PassWord : "******"IP : ") self.proxy_user_label.setText("Proxy UserName : "******"Port:") self.download_checkBox.setText("Download UserName and PassWord") self.download_user_label.setText("Download UserName : "******"Download PassWord : "******"Change Download Folder") self.folder_label.setText("Download Folder : ") self.start_checkBox.setText("Start Time") self.end_checkBox.setText("End Time") self.limit_checkBox.setText("Limit Speed") self.limit_comboBox.setItemText(0, "KB/S") self.limit_comboBox.setItemText(1, "MB/S") self.connections_label.setText("Number Of Connections :") self.cancel_pushButton.setText("Cancel") self.ok_pushButton.setText("OK") self.download_later_pushButton.setText("Download later") self.add_link_tabWidget.setTabText( self.add_link_tabWidget.indexOf(self.link_tab), "Link") self.add_link_tabWidget.setTabText( self.add_link_tabWidget.indexOf(self.proxy_tab), "Proxy") self.add_link_tabWidget.setTabText( self.add_link_tabWidget.indexOf(self.more_options_tab), "More Options") def changeIcon(self, icons): icons = ':/' + str(icons) + '/' self.folder_pushButton.setIcon(QIcon(icons + 'folder')) self.download_later_pushButton.setIcon(QIcon(icons + 'stop')) self.cancel_pushButton.setIcon(QIcon(icons + 'remove')) self.ok_pushButton.setIcon(QIcon(icons + 'ok'))
def initGUI(self): self.setWindowTitle('БиоРАСКАН-24') self.setWindowIcon(QIcon('Рисунок1.png')) self.settingsWidget = SettingsWidget(self) mainLayout = QGridLayout() self.setLayout(mainLayout) leftLayout = QVBoxLayout() leftLayout.setSpacing(20) mainLayout.addLayout(leftLayout, 1, 1, Qt.AlignCenter) tabWidget = QTabWidget() mainLayout.addWidget(tabWidget, 1, 3, Qt.AlignCenter) mainLayout.setRowStretch(0, 2) # empty space above ui mainLayout.setRowStretch(1, 1) # ui mainLayout.setRowStretch(2, 2) # console mainLayout.setRowStretch(3, 2) # empty space below ui mainLayout.setColumnStretch(0, 2) # empty space to the right from ui mainLayout.setColumnStretch( 2, 1) # empty space between left layout and right layout mainLayout.setColumnStretch(4, 2) # empty space to the left from ui # console output self.console = ConsoleWidget(self) self.console.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.console.setReadOnly(True) mainLayout.addWidget(self.console, 2, 1, 1, 3) # settings layout settingsLayout = QGridLayout() leftLayout.addLayout(settingsLayout) lengthSettingsText = QLabel('Длительность эксперимента') self.lengthSettingsEdit = QLineEdit('1') self.lengthSettingsEdit.setValidator(MyIntValidator(1, 30)) lmin = QLabel('мин') lmin.setObjectName("secondary") settingsLayout.addWidget(lengthSettingsText, 0, 0) settingsLayout.addWidget(self.lengthSettingsEdit, 0, 2) settingsLayout.addWidget(lmin, 0, 3) settingsLayout.setColumnMinimumWidth( 1, 30) # middle column to add some sapace intervalLayoutText = QLabel('Интервал расчета') self.intervalLayoutEdit = QLineEdit('10') self.intervalLayoutEdit.setValidator(MyIntValidator(10, 300)) imin = QLabel('сек') imin.setObjectName("secondary") settingsLayout.addWidget(intervalLayoutText, 1, 0) settingsLayout.addWidget(self.intervalLayoutEdit, 1, 2) settingsLayout.addWidget(imin, 1, 3) self.comBox = QComboBox(self) COMLayoutText = QLabel('Выбор COM-порта') COM_list = serial_ports() self.comBox.addItems(COM_list) settingsLayout.addWidget(COMLayoutText, 2, 0) settingsLayout.addWidget(self.comBox, 2, 2) # back to main layout settingsLayout.setRowMinimumHeight(3, 20) # add some space vertically self.soundCheckBox = QCheckBox('Звуковое оповещение') settingsLayout.addWidget(self.soundCheckBox, 4, 0) self.settingsButton = QPushButton('ДОПОЛНИТЕЛЬНО') self.settingsButton.setObjectName('secondary') settingsLayout.addWidget(self.settingsButton, 4, 2, 1, 2, Qt.AlignLeft) self.settingsButton.clicked.connect(lambda: self.settingsWidget.open()) self.timeLabel = QLabel('00:00:00') self.timeLabel.setObjectName('timeLabel') leftLayout.addWidget(self.timeLabel) leftLayout.setAlignment(self.timeLabel, Qt.AlignHCenter) infoLayout = QHBoxLayout() infoLayout.setSpacing(20) leftLayout.addLayout(infoLayout) infoLayout.addStretch() chss = QLabel('ЧСС') chss.setObjectName('leftBar') infoLayout.addWidget(chss) self.heartRateText = QLabel('0') self.heartRateText.setObjectName('primary') self.heartRateText.setAlignment(Qt.AlignRight) infoLayout.addWidget(self.heartRateText) udm = QLabel('уд/мин') udm.setObjectName('secondary') infoLayout.addWidget(udm) infoLayout.addSpacing(40) chd = QLabel('ЧД') chd.setObjectName('leftBar') infoLayout.addWidget(chd) self.breathRateText = QLabel('0') self.breathRateText.setObjectName('primary') self.breathRateText.setAlignment(Qt.AlignRight) infoLayout.addWidget(self.breathRateText) vdm = QLabel('вдох/мин') vdm.setObjectName('secondary') infoLayout.addWidget(vdm) infoLayout.addStretch() buttonLayout = QHBoxLayout() leftLayout.addLayout(buttonLayout) self.startStopButton = QPushButton('ЗАПУСК') self.startStopButton.setCheckable(True) self.saveButton = QPushButton('ЗАПИСЬ') self.saveButton.setCheckable(True) buttonLayout.addWidget(self.startStopButton) buttonLayout.addSpacing(20) buttonLayout.addWidget(self.saveButton) self.saveButton.toggled.connect(self.onSaveButtonClicked) self.startStopButton.toggled.connect(self.onButtonClick) # firs tab tabOneWidget = QWidget() tabOneLayout = QVBoxLayout() tabOneWidget.setLayout(tabOneLayout) tabWidget.addTab(tabOneWidget, "Сигнал локатора") self.locatorPlotWidget = PlotWidget(300, 20, 2) tabOneLayout.addWidget(self.locatorPlotWidget) tabOneButtonsLayout = QGridLayout() tabOneLayout.addLayout(tabOneButtonsLayout) locatorLeftCheckBox = QCheckBox('1-ая квадратура') tabOneButtonsLayout.addWidget(locatorLeftCheckBox, 0, 3) locatorRightCheckBox = QCheckBox('2-ая квадратура') tabOneButtonsLayout.addWidget(locatorRightCheckBox, 1, 3) locatorLeftCheckBox.setChecked(True) locatorRightCheckBox.setChecked(True) locatorLeftCheckBox.stateChanged.connect( lambda state: self.locatorPlotWidget.hideCurve( 0, False if state == 1 or state == 2 else True)) locatorRightCheckBox.stateChanged.connect( lambda state: self.locatorPlotWidget.hideCurve( 1, False if state == 1 or state == 2 else True)) # second tab tabTwoWidget = QWidget() tabTwoLayout = QVBoxLayout() tabTwoLayout.setContentsMargins(0, 0, 0, 0) tabTwoWidget.setLayout(tabTwoLayout) tabWidget.addTab(tabTwoWidget, "ЧСС/ЧД") self.heartRatePlotWidget = PlotWidget(30, 10000, 1) self.breathRatePlotWidget = PlotWidget(30, 10000, 1) tabTwoLayout.addWidget(self.heartRatePlotWidget) tabTwoLayout.addWidget(self.breathRatePlotWidget) # third tab tabThreeWidget = QWidget() tabThreeLayout = QVBoxLayout() tabThreeWidget.setLayout(tabThreeLayout) tabWidget.addTab(tabThreeWidget, "Отфильтрованный сигнал") self.heartFilteredPlotWidget = PlotWidget(300, 100, 2) self.breathFilteredPlotWidget = PlotWidget(300, 100, 2) tabThreeLayout.addWidget(self.heartFilteredPlotWidget) tabThreeLayout.addWidget(self.breathFilteredPlotWidget)
class ResultsGUI(QWidget): def __init__(self, key_value, column_headers, method, parent=None): super(ResultsGUI, self).__init__(parent) # set window dimension and center it screen = QApplication.desktop().screenGeometry() width = int(screen.width() * 0.5) height = int(screen.height() * 0.5) xpos = screen.width() // 2 - width // 2 ypos = screen.height() // 2 - height // 2 self.setGeometry(xpos, ypos, width, height) # Initialize tabs self.tabs = QTabWidget(self) self.tab1 = QWidget(self) self.tab2 = QWidget(self) self.tab3 = QWidget(self) self.tab1.layoutVertical = QVBoxLayout(self.tab1) self.tab2.layoutVertical = QVBoxLayout(self.tab2) self.tab3.layoutVertical = QVBoxLayout(self.tab3) self.tab1.setLayout(self.tab1.layoutVertical) self.tab2.setLayout(self.tab2.layoutVertical) self.tab3.setLayout(self.tab3.layoutVertical) self.tabs.addTab(self.tab1, 'Alg 1') self.tabs.addTab(self.tab2, 'Alg 2') self.tabs.addTab(self.tab3, 'Alg 3') # table view 1 self.tab1.tableView = table_view_factory(self.tab1) self.tab1.model = QStandardItemModel(self.tab1) self.tab1.tableView.setModel(self.tab1.model) self.tab1.layoutVertical.addWidget(self.tab1.tableView) # table view 2 self.tab2.tableView = table_view_factory(self.tab2) self.tab2.model = self.tab1.model self.tab2.tableView.setModel(self.tab2.model) self.tab2.layoutVertical.addWidget(self.tab2.tableView) # table view 3 self.tab3.tableView = table_view_factory(self.tab3) self.tab3.model = self.tab1.model self.tab3.tableView.setModel(self.tab3.model) self.tab3.layoutVertical.addWidget(self.tab3.tableView) self.tab1.model.setHorizontalHeaderLabels(column_headers) if method == "cb": data = get_recommendation_content_based(key_value) else: data = get_recommendation_collaborative_based(key_value) for rank, row in enumerate(data, start=1): items = [ QStandardItem(str(field)) for field in row ] items.insert(0, QStandardItem(str(rank))) self.tab1.model.appendRow(items) self.layout = QVBoxLayout(self) self.layout.addWidget(self.tabs) self.setLayout(self.layout)
class Example(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.radius = 10 self.color = 'r' self.circles = Circles() # Initialize tab screen self.tabs = QTabWidget() self.tab1 = QWidget() self.tab2 = QWidget() self.tabs.resize(3000, 2000) # Add tabs self.tabs.addTab(self.tab1, "Edit") self.tabs.addTab(self.tab2, "Model") #self.setMouseTracking(True) self.figure = plt.figure() self.figureEarth = plt.figure() self.canvas = FigureCanvas(self.figure) self.canvasEarth = FigureCanvas(self.figureEarth) self.canvas.mpl_connect('motion_notify_event', self.mouseMoveEvent) self.canvas.mpl_connect('button_press_event', self.mousePrintEvent) self.button_group = QtWidgets.QButtonGroup() # Number group self.r0 = QtWidgets.QRadioButton("verlet") self.button_group.addButton(self.r0) self.r1 = QtWidgets.QRadioButton("scipy") self.button_group.addButton(self.r1) self.r2 = QtWidgets.QRadioButton("threading") self.button_group.addButton(self.r2) self.r3 = QtWidgets.QRadioButton("multiprocessing") self.button_group.addButton(self.r3) self.r4 = QtWidgets.QRadioButton("compare all") self.button_group.addButton(self.r4) self.button_group.buttonClicked.connect(self.RadioButtonClicked) self.ax = self.figure.add_subplot(111) # create an axis self.ax.set_xlim([-100, 100]) self.ax.set_ylim([-100, 100]) self.axEarth = self.figureEarth.add_subplot(111) # create an axis self.axEarth.set_xlim([-2.0 * (10**11), 2.0 * (10**11)]) self.axEarth.set_ylim([-2.0 * (10**11), 2.0 * (10**11)]) # Just some button connected to method self.buttonPlus = QPushButton('+') self.buttonPlus.clicked.connect(self.IncreaseAxes) self.buttonPlus.resize(self.buttonPlus.sizeHint()) self.buttonPlus.move(50, 50) self.buttonMinus = QPushButton('-') self.buttonMinus.clicked.connect(self.DecreaseAxes) self.buttonMinus.resize(self.buttonMinus.sizeHint()) self.buttonMinus.move(70, 70) self.buttonSave = QPushButton('Save to xml file', self) self.buttonSave.move(10, 10) self.buttonSave.clicked.connect(self.saveFileDialog) self.buttonOpen = QPushButton('Load from xml file', self) self.buttonOpen.clicked.connect(self.openFileDialog) self.buttonOpen.resize(self.buttonMinus.sizeHint()) self.buttonOpen.move(70, 70) self.buttonColor = QPushButton('Open color dialog', self) self.buttonColor.setToolTip('Opens color dialog') self.buttonColor.move(10, 10) self.buttonColor.clicked.connect(self.openColorDialog) self.textboxX = QLineEdit(self) self.textboxX.move(20, 20) self.textboxX.resize(120, 40) #self.textboxX.setText('0') self.textboxY = QLineEdit(self) self.textboxY.move(220, 20) self.textboxY.resize(120, 40) #self.textboxY.setText('0') self.sld = QSlider(Qt.Horizontal, self) self.sld.setFocusPolicy(Qt.NoFocus) self.sld.setGeometry(30, 40, 100, 30) self.sld.setRange(1.0, 100.0) self.sld.setValue(10.0) self.sld.valueChanged.connect(self.changeSliderRadius) self.textboxSld = QLineEdit(self) self.textboxSld.move(420, 20) self.textboxSld.resize(120, 40) self.textboxSld.setText("10") self.textboxSld.textChanged.connect(self.changeTextRadius) # set the layout self.layout = QVBoxLayout(self) self.tab1.layout = QVBoxLayout(self) self.tab1.layout.addWidget(self.textboxX) self.tab1.layout.addWidget(self.textboxY) self.tab1.layout.addWidget(self.buttonColor) self.tab1.layout.addWidget(self.sld) self.tab1.layout.addWidget(self.textboxSld) self.tab1.layout.addWidget(self.canvas) self.tab1.layout.addWidget(self.buttonPlus) self.tab1.layout.addWidget(self.buttonMinus) self.tab1.layout.addWidget(self.buttonOpen) self.tab1.layout.addWidget(self.buttonSave) self.tab1.setLayout(self.tab1.layout) self.tab2.layout = QVBoxLayout(self) self.tab2.layout.addWidget(self.r0) self.tab2.layout.addWidget(self.r1) self.tab2.layout.addWidget(self.r2) self.tab2.layout.addWidget(self.r3) self.tab2.layout.addWidget(self.r4) self.tab2.layout.addWidget(self.canvasEarth) self.tab2.setLayout(self.tab2.layout) self.layout.addWidget(self.tabs) self.setLayout(self.layout) #self.setLayout(layout) self.canvas.draw() self.canvasEarth.draw() #btn = QPushButton('Button', self) #btn.setToolTip('This is a <b>QuitButton</b> widget') #btn.clicked.connect(self.changeButtonName) #btn.resize(btn.sizeHint()) #btn.move(50, 50) self.setGeometry(300, 300, 1000, 1000) self.setWindowTitle('Circles') self.show() def changeSliderRadius(self, value): self.radius = value print(value) self.textboxSld.setText(str(self.radius)) def changeTextRadius(self, value): if value != '' and self.IsFloat(value): radius = float(value) self.radius = radius print(value) if radius < self.sld.minimum(): self.textboxSld.setText(str(self.sld.minimum())) self.radius = self.sld.minimum() elif radius > self.sld.maximum(): self.textboxSld.setText(str(self.sld.maximum())) self.radius = self.sld.maximum() self.sld.setValue(int(radius)) def openColorDialog(self): color = QColorDialog.getColor() self.color = color.name() if color.isValid(): print(color.name()) def mouseMoveEvent(self, e): print('mouseEvent') #print(e) if (e.inaxes): x = e.xdata y = e.ydata self.textboxX.setText("{0}".format(x)) self.textboxY.setText("{0}".format(y)) def changeButtonName(self): self.setWindowTitle(Circle.CircleName()) def IncreaseAxes(self): xlim = self.ax.get_xlim() self.ax.set_xlim(np.multiply(xlim, 1.5)) ylim = self.ax.get_ylim() self.ax.set_ylim(np.multiply(ylim, 1.5)) self.canvas.draw() self.sld.setMaximum(self.sld.maximum() * 1.5) self.sld.setMinimum(self.sld.minimum() * 1.5) def DecreaseAxes(self): xlim = self.ax.get_xlim() self.ax.set_xlim(np.divide(xlim, 1.5)) ylim = self.ax.get_ylim() self.ax.set_ylim(np.divide(ylim, 1.5)) self.canvas.draw() self.sld.setMaximum(self.sld.maximum() / 1.5) self.sld.setMinimum(self.sld.minimum() / 1.5) def mousePrintEvent(self, event): #if event.button() == QtCore.Qt.LeftButton: # print("Press!") #super(GraphicsView, self).mousePressEvent(event) print('circle') #Circle.Draw(0, 0, self.radius, self.color, self.figure) circle1 = MyCircle(event.xdata, event.ydata, self.radius, self.color) self.ax.add_artist(circle1) self.canvas.draw() self.circles.Add(circle1) def CreateXMLRoot(self): root = ET.Element("root") doc = ET.SubElement(root, "doc") fig = ET.SubElement(doc, "figure") ET.SubElement(fig, "X").text = str(self.ax.get_xlim()[1]) ET.SubElement(fig, "Y").text = str(self.ax.get_ylim()[1]) ET.SubElement(fig, "Color").text = self.color slider = ET.SubElement(doc, "slider") ET.SubElement(slider, "Max").text = str(self.sld.maximum()) ET.SubElement(slider, "Min").text = str(self.sld.minimum()) ET.SubElement(slider, "Radius").text = str(self.radius) circles = ET.SubElement(doc, "circles") i = 0 for element in self.circles.elements: el = ET.SubElement(circles, "circle{0}".format(i)) ET.SubElement(el, "X").text = str(element.x) ET.SubElement(el, "Y").text = str(element.y) ET.SubElement(el, "radius").text = str(element.radius) ET.SubElement(el, "color").text = str(element.color) i += 1 return root def saveFileDialog(self): tree = ET.ElementTree(self.CreateXMLRoot()) options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog fileName, _ = QFileDialog.getSaveFileName( self, "Save File as", "", "All Files (*);;Python Files (*.py)", options=options) if fileName: print(fileName) tree.write(fileName) def ParseXMLFile(self, filename): tree = ET.ElementTree(file=filename) for elem in tree.iter(tag="figure"): x = float(elem.find("X").text) y = float(elem.find("Y").text) self.color = elem.find("Color").text self.ax.set_xlim([-x, x]) self.ax.set_ylim([-y, y]) for elem in tree.iter(tag="slider"): max = float(elem.find("Max").text) min = float(elem.find("Min").text) self.sld.setRange(min, max) self.radius = int(float(elem.find("Radius").text)) self.sld.setValue(self.radius) self.textboxSld.setText(str(self.radius)) self.ax.clear() for elem in tree.iter(tag="circles"): for el in elem: x1 = float(el.find("X").text) y1 = float(el.find("Y").text) r = float(el.find("radius").text) col = el.find("color").text print('circle') circle1 = MyCircle(x1, y1, r, col) self.ax.add_artist(circle1) self.canvas.draw() self.circles.Add(circle1) def openFileDialog(self): options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog fileName, _ = QFileDialog.getOpenFileName( self, "Open File", "", "All Files (*);;Text Files (*.txt)", options=options) if fileName: print(fileName) self.ParseXMLFile(fileName) def RadioButtonClicked(self, button): #self.axEarth.set_xlim([-2.0* (10**11), 2.0* (10**11)]) #self.axEarth.set_ylim([-2.0* (10**11), 2.0* (10**11)]) MEarth = 5.9724 * (10**24) MMoon = 7.34767309 * (10**22) MSun = 1988500 * (10**24) if (self.r0.isChecked()): N = 40000 dt = 1200 #Tn = np.linspace(0, 40*1200, 40) Earth = Cosmic(N, MEarth, 0, -1.496 * (10**11), 29.783 * (10**3), 0, 0, 0, []) Moon = Cosmic(N, MMoon, 0, -1.496 * (10**11) - 384.467 * (10**6), 29.783 * (10**3) + 1022, 0, 0, 0, []) Sun = Cosmic(N, MSun, 0, 0, 0, 0, 0, 0, []) cosmics = [Sun, Earth, Moon] for obj in cosmics: for interactionObj in cosmics: if (not interactionObj is obj): obj.Interactions.append( (interactionObj.M, interactionObj.R)) #verlet = Verlet(N, dt, cosmics) #verlet.VerletMain() verlet = VerletOpenCL(N, dt, cosmics) verlet.VerletMain() print("Verlet calculated") self.axEarth.clear() Tn = np.linspace(0, 4, 40001) ani = SubplotAnimation(self.figureEarth, self.axEarth, Tn, Sun.R[0, :], Sun.R[1, :], Earth.R[0, :], Earth.R[1, :], Moon.R[0, :], Moon.R[1, :]) self.canvasEarth.draw() if (self.r1.isChecked()): p = [ 6.67408 * (10**(-11)), 1988500 * (10**24), 5.9724 * (10**24), 7.34767309 * (10**22) ] w0 = [ 0, 0, 0, 0, 0, 0, 0, 29.783 * (10**3), -1.496 * (10**11), 0, 0, 0, 0, 29.783 * (10**3) + 1022, -1.496 * (10**11) - 384.467 * (10**6), 0, 0, 0 ] t = [1200 * float(i) for i in range(40000)] wsol = odeint(vectorfield, w0, t, args=(p, )) xSun = wsol[:, 0] ySun = wsol[:, 2] xEarth = wsol[:, 6] yEarth = wsol[:, 8] xMoon = wsol[:, 12] yMoon = wsol[:, 14] print(5) self.axEarth.clear() Tn = np.linspace(0, 4, 40000) ani = SubplotAnimation(self.figureEarth, self.axEarth, Tn, xSun, ySun, xEarth, yEarth, xMoon, yMoon) self.canvasEarth.draw() if (self.r2.isChecked()): N = 40000 dt = 1200 Earth = Cosmic(N, MEarth, 0, -1.496 * (10**11), 29.783 * (10**3), 0, 0, 0, []) Moon = Cosmic(N, MMoon, 0, -1.496 * (10**11) - 384.467 * (10**6), 29.783 * (10**3) + 1022, 0, 0, 0, []) Sun = Cosmic(N, MSun, 0, 0, 0, 0, 0, 0, []) cosmics = [Sun, Earth, Moon] for obj in cosmics: for interactionObj in cosmics: if (not interactionObj is obj): obj.Interactions.append( (interactionObj.M, interactionObj.R)) verlet = VerletThreads(N, dt, cosmics) verlet.VerletMain() self.figureEarth.clear() Tn = np.linspace(0, 4, 40001) ani = SubplotAnimation(self.figureEarth, self.axEarth, Tn, Sun.R[0, :], Sun.R[1, :], Earth.R[0, :], Earth.R[1, :], Moon.R[0, :], Moon.R[1, :]) self.canvasEarth.draw() if (self.r3.isChecked()): N = 40000 dt = 1200 Earth = CosmicMulti(N, MEarth, 0, -1.496 * (10**11), 29.783 * (10**3), 0, 0, 0, []) Moon = CosmicMulti(N, MMoon, 0, -1.496 * (10**11) - 384.467 * (10**6), 29.783 * (10**3) + 1022, 0, 0, 0, []) Sun = CosmicMulti(N, MSun, 0, 0, 0, 0, 0, 0, []) cosmics = [Sun, Earth, Moon] for obj in cosmics: for interactionObj in cosmics: if (not interactionObj is obj): obj.Interactions.append( (interactionObj.M, interactionObj.R)) verlet = VerletMultiProcessing(N, dt, cosmics) verlet.VerletMain() print("Verlet calculated") self.figureEarth.clear() Tn = np.linspace(0, 4, 40001) ani = SubplotAnimation(self.figureEarth, self.axEarth, Tn, Sun.bR[0, :], Sun.bR[1, :], Earth.bR[0, :], Earth.bR[1, :], Moon.bR[0, :], Moon.bR[1, :]) self.canvasEarth.draw() if (self.r4.isChecked()): #TimesAll() TimesAllKBodies(50) #verlet = VerletThreads(400000,120) #verlet.REarth[0,0] = 0 #verlet.REarth[1,0] = -1.496*(10**11) #verlet.VEarth[0,0] = 29.783*(10**3) #verlet.RMoon[1,0] = -1.496*(10**11) - 384.467*(10**6) #verlet.VMoon[0,0] = 29.783*(10**3) + 1022 #verlet.VerletMain() #print(5) #self.axEarth.plot(verlet.REarth[0,:], verlet.REarth[1, :], color = 'blue') #self.axEarth.plot(verlet.RMoon[0,:], verlet.RMoon[1, :], color = 'gray') #print(6) #self.canvasEarth.draw() def IsFloat(self, value): try: float(value) return True except: return False
class App(QWidget): def __init__(self): super().__init__() self.title = 'Algoritmos evolutivos' self.left = 50 self.top = 50 self.width = 720 self.height = 540 self.initUI() def initUI(self): self.layout = QVBoxLayout(self) self.tabs = QTabWidget() self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) self.tabs.resize(300, 200) self.tabs.addTab(UIEvolutionary(), 'Evolutionary') self.tabs.addTab(UIImmune(), 'Immune') self.tabs.addTab(UIPhysical(), 'Physical') self.tabs.addTab(UIProbabilistic(), 'Probabilistic') self.tabs.addTab(UIStochastic(), 'Stochastic') self.tabs.addTab(UISwarm(), 'Swarm') self.tabs.addTab(UIParallel(), 'Parallel') self.layout.addWidget(self.tabs) self.setLayout(self.layout)
class AboutWindow_Ui(QWidget): def __init__(self,persepolis_setting): super().__init__() self.persepolis_setting = persepolis_setting # add support for other languages locale = str(self.persepolis_setting.value('settings/locale')) QLocale.setDefault(QLocale(locale)) self.translator = QTranslator() if self.translator.load(':/translations/locales/ui_' + locale, 'ts'): QCoreApplication.installTranslator(self.translator) # set ui direction ui_direction = self.persepolis_setting.value('ui_direction') if ui_direction == 'rtl': self.setLayoutDirection(Qt.RightToLeft) elif ui_direction in 'ltr': self.setLayoutDirection(Qt.LeftToRight) icons = ':/' + \ str(self.persepolis_setting.value('settings/icons')) + '/' self.setMinimumSize(QSize(545, 375)) self.setWindowIcon(QIcon.fromTheme('persepolis', QIcon(':/persepolis.svg'))) verticalLayout = QVBoxLayout(self) self.about_tabWidget = QTabWidget(self) # about tab self.about_tab = QWidget(self) about_tab_horizontalLayout = QHBoxLayout(self.about_tab) about_tab_verticalLayout = QVBoxLayout() # persepolis icon if qtsvg_available: persepolis_icon_verticalLayout = QVBoxLayout() self.persepolis_icon = QtSvg.QSvgWidget(':/persepolis.svg') self.persepolis_icon.setFixedSize(QSize(64, 64)) persepolis_icon_verticalLayout.addWidget(self.persepolis_icon) persepolis_icon_verticalLayout.addStretch(1) about_tab_horizontalLayout.addLayout(persepolis_icon_verticalLayout) self.title_label = QLabel(self.about_tab) font = QFont() font.setBold(True) font.setWeight(75) self.title_label.setFont(font) self.title_label.setAlignment(Qt.AlignCenter) about_tab_verticalLayout.addWidget(self.title_label) self.version_label = QLabel(self.about_tab) self.version_label.setAlignment(Qt.AlignCenter) about_tab_verticalLayout.addWidget(self.version_label) self.site2_label = QLabel(self.about_tab) self.site2_label.setTextFormat(Qt.RichText) self.site2_label.setAlignment(Qt.AlignCenter) self.site2_label.setOpenExternalLinks(True) self.site2_label.setTextInteractionFlags( Qt.TextBrowserInteraction) about_tab_verticalLayout.addWidget(self.site2_label) self.telegram_label = QLabel(self.about_tab) self.telegram_label.setTextFormat(Qt.RichText) self.telegram_label.setAlignment(Qt.AlignCenter) self.telegram_label.setOpenExternalLinks(True) self.telegram_label.setTextInteractionFlags( Qt.TextBrowserInteraction) about_tab_verticalLayout.addWidget(self.telegram_label) self.twitter_label = QLabel(self.about_tab) self.twitter_label.setTextFormat(Qt.RichText) self.twitter_label.setAlignment(Qt.AlignCenter) self.twitter_label.setOpenExternalLinks(True) self.twitter_label.setTextInteractionFlags( Qt.TextBrowserInteraction) about_tab_verticalLayout.addWidget(self.twitter_label) about_tab_verticalLayout.addStretch(1) about_tab_horizontalLayout.addLayout(about_tab_verticalLayout) # developers_tab self.developers_tab = QWidget(self) developers_verticalLayout = QVBoxLayout(self.developers_tab) self.developers_title_label = QLabel(self.developers_tab) font.setBold(True) font.setWeight(75) self.developers_title_label.setFont(font) self.developers_title_label.setAlignment(Qt.AlignCenter) developers_verticalLayout.addWidget(self.developers_title_label) self.name_label = QLabel(self.developers_tab) self.name_label.setAlignment(Qt.AlignCenter) developers_verticalLayout.addWidget(self.name_label) developers_verticalLayout.addStretch(1) # translators tab self.translators_tab = QWidget(self) translators_tab_verticalLayout = QVBoxLayout(self.translators_tab) # chinese translators self.chinese_translators_label = QLabel(self.translators_tab) self.chinese_translators_label.setFont(font) self.chinese_translators_label.setAlignment(Qt.AlignCenter) translators_tab_verticalLayout.addWidget(self.chinese_translators_label) self.chinese_translatos_name_label = QLabel(self.translators_tab) self.chinese_translatos_name_label.setAlignment(Qt.AlignCenter) translators_tab_verticalLayout.addWidget(self.chinese_translatos_name_label) # persian translators self.persian_translators_label = QLabel(self.translators_tab) self.persian_translators_label.setFont(font) self.persian_translators_label.setAlignment(Qt.AlignCenter) translators_tab_verticalLayout.addWidget(self.persian_translators_label) self.persian_translatos_name_label = QLabel(self.translators_tab) self.persian_translatos_name_label.setAlignment(Qt.AlignCenter) translators_tab_verticalLayout.addWidget(self.persian_translatos_name_label) translators_tab_verticalLayout.addStretch(1) # License tab self.license_tab = QWidget(self) license_tab_verticalLayout = QVBoxLayout(self.license_tab) self.license_text = QTextEdit(self.license_tab) self.license_text.setReadOnly(True) license_tab_verticalLayout.addWidget(self.license_text) verticalLayout.addWidget(self.about_tabWidget) # buttons button_horizontalLayout = QHBoxLayout() button_horizontalLayout.addStretch(1) self.pushButton = QPushButton(self) self.pushButton.setIcon(QIcon(icons + 'ok')) self.pushButton.clicked.connect(self.close) button_horizontalLayout.addWidget(self.pushButton) verticalLayout.addLayout(button_horizontalLayout) self.setWindowTitle(QCoreApplication.translate("about_ui_tr", "About Persepolis")) # about_tab self.title_label.setText(QCoreApplication.translate("about_ui_tr", "Persepolis Download Manager")) self.version_label.setText(QCoreApplication.translate("about_ui_tr", "Version 3.0.1")) self.site2_label.setText(QCoreApplication.translate("about_ui_tr", "<a href=https://persepolisdm.github.io>https://persepolisdm.github.io</a>", "TRANSLATORS NOTE: YOU REALLY DON'T NEED TO TRANSLATE THIS PART!")) self.telegram_label.setText(QCoreApplication.translate("about_ui_tr", "<a href=https://telegram.me/persepolisdm>https://telegram.me/persepolisdm</a>", "TRANSLATORS NOTE: YOU REALLY DON'T NEED TO TRANSLATE THIS PART!")) self.twitter_label.setText(QCoreApplication.translate("about_ui_tr", "<a href=https://twitter.com/persepolisdm>https://twitter.com/persepolisdm</a>", "TRANSLATORS NOTE: YOU REALLY DON'T NEED TO TRANSLATE THIS PART!")) #developers_tab self.developers_title_label.setText(QCoreApplication.translate('about_ui_tr', 'Developers:')) self.name_label.setText(QCoreApplication.translate("about_ui_tr", "\nAliReza AmirSamimi\nMohammadreza Abdollahzadeh\nSadegh Alirezaie\nMostafa Asadi\nMohammadAmin Vahedinia\nJafar Akhondali\nH.Rostami", "TRANSLATORS NOTE: YOU REALLY DON'T NEED TO TRANSLATE THIS PART!")) # translators_tab self.persian_translators_label.setText(QCoreApplication.translate("about_ui_tr", "Persian translators:")) self.persian_translatos_name_label.setText(QCoreApplication.translate("about_ui_tr", "H.Rostami\nMostafa Asadi")) self.chinese_translators_label.setText(QCoreApplication.translate("about_ui_tr", "Chinese translators:")) self.chinese_translatos_name_label.setText(QCoreApplication.translate("about_ui_tr", "Davinma\n210hcl\nleoxxx")) # License self.license_text.setPlainText(""" This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/. """) # tabs self.about_tabWidget.addTab(self.about_tab, QCoreApplication.translate("about_ui_tr", "About Persepolis")) self.about_tabWidget.addTab(self.developers_tab, QCoreApplication.translate("about_ui_tr", "Developers")) self.about_tabWidget.addTab(self.translators_tab, QCoreApplication.translate("about_ui_tr", "Translators")) self.about_tabWidget.addTab(self.license_tab, QCoreApplication.translate("about_ui_tr", "License")) # button self.pushButton.setText(QCoreApplication.translate("about_ui_tr", "OK"))
class WeatherDataGapfiller(QMainWindow): ConsoleSignal = QSignal(str) def __init__(self, parent=None): super().__init__(parent) self._workdir = None self._corrcoeff_update_inprogress = False self._pending_corrcoeff_update = None self._loading_data_inprogress = False self.__initUI__() # Setup the DataGapfillManager. self.gapfill_manager = DataGapfillManager() self.gapfill_manager.sig_task_progress.connect( self.progressbar.setValue) self.gapfill_manager.sig_status_message.connect( self.set_statusbar_text) def __initUI__(self): self.setWindowIcon(get_icon('master')) # Setup the toolbar at the bottom. self.btn_fill = QPushButton('Gapfill Data') self.btn_fill.setIcon(get_icon('fill_data')) self.btn_fill.setIconSize(get_iconsize('small')) self.btn_fill.setToolTip( "Fill the gaps in the daily weather data of the selected " "weather station.") self.btn_fill.clicked.connect(self._handle_gapfill_btn_clicked) widget_toolbar = QFrame() grid_toolbar = QGridLayout(widget_toolbar) grid_toolbar.addWidget(self.btn_fill, 0, 0) grid_toolbar.setContentsMargins(0, 0, 0, 0) grid_toolbar.setColumnStretch(0, 100) # ---- Target Station groupbox self.target_station = QComboBox() self.target_station.currentIndexChanged.connect( self._handle_target_station_changed) self.target_station_info = QTextEdit() self.target_station_info.setReadOnly(True) self.target_station_info.setMaximumHeight(110) self.btn_refresh_staList = QToolButton() self.btn_refresh_staList.setIcon(get_icon('refresh')) self.btn_refresh_staList.setToolTip( 'Force the reloading of the weather data files') self.btn_refresh_staList.setIconSize(get_iconsize('small')) self.btn_refresh_staList.setAutoRaise(True) self.btn_refresh_staList.clicked.connect( lambda: self.load_data_dir_content(force_reload=True)) self.btn_delete_data = QToolButton() self.btn_delete_data.setIcon(get_icon('delete_data')) self.btn_delete_data.setEnabled(False) self.btn_delete_data.setAutoRaise(True) self.btn_delete_data.setToolTip( 'Remove the currently selected dataset and delete the input ' 'datafile. However, raw datafiles will be kept.') self.btn_delete_data.clicked.connect(self.delete_current_dataset) # Generate the layout for the target station group widget. self.target_widget = QWidget() target_station_layout = QGridLayout(self.target_widget) target_station_layout.setHorizontalSpacing(1) target_station_layout.setColumnStretch(0, 1) target_station_layout.setContentsMargins(0, 0, 0, 0) widgets = [self.target_station, self.btn_refresh_staList, self.btn_delete_data] target_station_layout.addWidget(self.target_station, 1, 0) for col, widget in enumerate(widgets): target_station_layout.addWidget(widget, 1, col) # Setup the gapfill dates. label_From = QLabel('From : ') self.date_start_widget = QDateEdit() self.date_start_widget.setDisplayFormat('dd / MM / yyyy') self.date_start_widget.setEnabled(False) self.date_start_widget.dateChanged.connect( self._update_corrcoeff_table) label_To = QLabel('To : ') self.date_end_widget = QDateEdit() self.date_end_widget.setEnabled(False) self.date_end_widget.setDisplayFormat('dd / MM / yyyy') self.date_end_widget.dateChanged.connect( self._update_corrcoeff_table) self.fillDates_widg = QWidget() gapfilldates_layout = QGridLayout(self.fillDates_widg) gapfilldates_layout.addWidget(label_From, 0, 0) gapfilldates_layout.addWidget(self.date_start_widget, 0, 1) gapfilldates_layout.addWidget(label_To, 1, 0) gapfilldates_layout.addWidget(self.date_end_widget, 1, 1) gapfilldates_layout.setColumnStretch(2, 1) gapfilldates_layout.setContentsMargins(0, 0, 0, 0) # Create the gapfill target station groupbox. target_groupbox = QGroupBox("Fill data for weather station") target_layout = QGridLayout(target_groupbox) target_layout.addWidget(self.target_widget, 0, 0) target_layout.addWidget(self.target_station_info, 1, 0) target_layout.addWidget(self.fillDates_widg, 2, 0) # Setup the left panel. self._regression_model_groupbox = ( self._create_regression_model_settings()) self._station_selection_groupbox = ( self._create_station_selection_criteria()) self.left_panel = QFrame() left_panel_layout = QGridLayout(self.left_panel) left_panel_layout.addWidget(target_groupbox, 0, 0) left_panel_layout.addWidget(self._station_selection_groupbox, 3, 0) left_panel_layout.addWidget(self._regression_model_groupbox, 4, 0) left_panel_layout.addWidget(widget_toolbar, 5, 0) left_panel_layout.setRowStretch(6, 1) left_panel_layout.setContentsMargins(0, 0, 0, 0) # Setup the right panel. self.corrcoeff_textedit = QTextEdit() self.corrcoeff_textedit.setReadOnly(True) self.corrcoeff_textedit.setMinimumWidth(700) self.corrcoeff_textedit.setFrameStyle(0) self.corrcoeff_textedit.document().setDocumentMargin(10) self.sta_display_summary = QTextEdit() self.sta_display_summary.setReadOnly(True) self.sta_display_summary.setFrameStyle(0) self.sta_display_summary.document().setDocumentMargin(10) self.right_panel = QTabWidget() self.right_panel.addTab( self.corrcoeff_textedit, 'Correlation Coefficients') self.right_panel.addTab( self.sta_display_summary, 'Data Overview') # Setup the progressbar. self.progressbar = QProgressBar() self.progressbar.setValue(0) self.progressbar.hide() self.statustext = QLabel() self.statustext.setStyleSheet( "QLabel {background-color: transparent; padding: 0 0 0 3px;}") self.statustext.setMinimumHeight(self.progressbar.minimumHeight()) # Setup the main widget. main_widget = QWidget() main_grid = QGridLayout(main_widget) main_grid.addWidget(self.left_panel, 0, 0) main_grid.addWidget(self.right_panel, 0, 1) main_grid.addWidget(self.progressbar, 1, 0, 1, 2) main_grid.addWidget(self.statustext, 1, 0, 1, 2) main_grid.setColumnStretch(1, 500) main_grid.setRowStretch(0, 500) self.setCentralWidget(main_widget) def _create_station_selection_criteria(self): Nmax_label = QLabel('Nbr. of stations :') self.Nmax = QSpinBox() self.Nmax.setRange(0, 99) self.Nmax.setMinimum(1) self.Nmax.setValue(CONF.get('gapfill_data', 'nbr_of_station', 4)) self.Nmax.setAlignment(Qt.AlignCenter) ttip = ('<p>Distance limit beyond which neighboring stations' ' are excluded from the gapfilling procedure.</p>' '<p>This condition is ignored if set to -1.</p>') distlimit_label = QLabel('Max. Distance :') distlimit_label.setToolTip(ttip) self.distlimit = QSpinBox() self.distlimit.setRange(-1, 9999) self.distlimit.setSingleStep(1) self.distlimit.setValue( CONF.get('gapfill_data', 'max_horiz_dist', 100)) self.distlimit.setToolTip(ttip) self.distlimit.setSuffix(' km') self.distlimit.setAlignment(Qt.AlignCenter) self.distlimit.valueChanged.connect(self._update_corrcoeff_table) ttip = ('<p>Altitude difference limit over which neighboring ' ' stations are excluded from the gapfilling procedure.</p>' '<p>This condition is ignored if set to -1.</p>') altlimit_label = QLabel('Max. Elevation Diff. :') altlimit_label.setToolTip(ttip) self.altlimit = QSpinBox() self.altlimit.setRange(-1, 9999) self.altlimit.setSingleStep(1) self.altlimit.setValue( CONF.get('gapfill_data', 'max_vert_dist', 350)) self.altlimit.setToolTip(ttip) self.altlimit.setSuffix(' m') self.altlimit.setAlignment(Qt.AlignCenter) self.altlimit.valueChanged.connect(self._update_corrcoeff_table) # Setup the main widget. widget = QGroupBox('Stations Selection Criteria') layout = QGridLayout(widget) layout.addWidget(Nmax_label, 0, 0) layout.addWidget(self.Nmax, 0, 1) layout.addWidget(distlimit_label, 1, 0) layout.addWidget(self.distlimit, 1, 1) layout.addWidget(altlimit_label, 2, 0) layout.addWidget(self.altlimit, 2, 1) layout.setColumnStretch(0, 1) return widget def _create_advanced_settings(self): self.full_error_analysis = QCheckBox('Full Error Analysis.') self.full_error_analysis.setChecked(True) fig_opt_layout = QGridLayout() fig_opt_layout.addWidget(QLabel("Figure output format : "), 0, 0) fig_opt_layout.addWidget(self.fig_format, 0, 2) fig_opt_layout.addWidget(QLabel("Figure labels language : "), 1, 0) fig_opt_layout.addWidget(self.fig_language, 1, 2) fig_opt_layout.setContentsMargins(0, 0, 0, 0) fig_opt_layout.setColumnStretch(1, 100) # Setup the main layout. widget = QFrame() layout = QGridLayout(widget) layout.addWidget(self.full_error_analysis, 0, 0) layout.addLayout(fig_opt_layout, 2, 0) layout.setRowStretch(layout.rowCount(), 100) layout.setContentsMargins(10, 0, 10, 0) return widget def _create_regression_model_settings(self): self.RMSE_regression = QRadioButton('Ordinary Least Squares') self.RMSE_regression.setChecked( CONF.get('gapfill_data', 'regression_model', 'OLS') == 'OLS') self.ABS_regression = QRadioButton('Least Absolute Deviations') self.ABS_regression.setChecked( CONF.get('gapfill_data', 'regression_model', 'OLS') == 'LAD') widget = QGroupBox('Regression Model') layout = QGridLayout(widget) layout.addWidget(self.RMSE_regression, 0, 0) layout.addWidget(self.ABS_regression, 1, 0) return widget def set_statusbar_text(self, text): self.statustext.setText(text) @property def workdir(self): return self._workdir def set_workdir(self, dirname): """ Set the working directory to dirname. """ self._workdir = dirname self.gapfill_manager.set_workdir(dirname) self.load_data_dir_content() def delete_current_dataset(self): """ Delete the current dataset source file and force a reload of the input daily weather datafiles. """ current_index = self.target_station.currentIndex() if current_index != -1: basename = self.gapfill_manager.worker().wxdatasets.fnames[ current_index] filename = os.path.join(self.workdir, basename) delete_file(filename) self.load_data_dir_content() def _handle_target_station_changed(self): """Handle when the target station is changed by the user.""" self.btn_delete_data.setEnabled( self.target_station.currentIndex() != -1) self.update_corrcoeff() def get_dataset_names(self): """ Return a list of the names of the dataset that are loaded in memory and listed in the target station dropdown menu. """ return [self.target_station.itemText(i) for i in range(self.target_station.count())] # ---- Correlation coefficients def update_corrcoeff(self): """ Calculate the correlation coefficients and display the results in the GUI. """ if self.target_station.currentIndex() != -1: station_id = self.target_station.currentData() if self._corrcoeff_update_inprogress is True: self._pending_corrcoeff_update = station_id else: self._corrcoeff_update_inprogress = True self.corrcoeff_textedit.setText('') self.gapfill_manager.set_target_station( station_id, callback=self._handle_corrcoeff_updated) def _handle_corrcoeff_updated(self): self._corrcoeff_update_inprogress = False if self._pending_corrcoeff_update is None: self._update_corrcoeff_table() else: self._pending_corrcoeff_update = None self.update_corrcoeff() def _update_corrcoeff_table(self): """ This method plot the correlation coefficient table in the display area. It is separated from the method "update_corrcoeff" because red numbers and statistics regarding missing data for the selected time period can be updated in the table when the user changes the values without having to recalculate the correlation coefficient each time. """ if self.target_station.currentIndex() != -1: table, target_info = ( self.gapfill_manager.worker().generate_correlation_html_table( self.get_gapfill_parameters())) self.corrcoeff_textedit.setText(table) self.target_station_info.setText(target_info) # ---- Load Data def load_data_dir_content(self, force_reload=False): """ Load weater data from valid files contained in the working directory. """ self._pending_corrcoeff_update = None self._loading_data_inprogress = True self.left_panel.setEnabled(False) self.right_panel.setEnabled(False) self.corrcoeff_textedit.setText('') self.target_station_info.setText('') self.target_station.clear() self.gapfill_manager.load_data( force_reload=force_reload, callback=self._handle_data_dir_content_loaded) def _handle_data_dir_content_loaded(self): """ Handle when data finished loaded from valid files contained in the working directory. """ self.left_panel.setEnabled(True) self.right_panel.setEnabled(True) self.target_station.blockSignals(True) station_names = self.gapfill_manager.get_station_names() station_ids = self.gapfill_manager.get_station_ids() for station_name, station_id in zip(station_names, station_ids): self.target_station.addItem( '{} ({})'.format(station_name, station_id), userData=station_id) self.target_station.blockSignals(False) self.sta_display_summary.setHtml( self.gapfill_manager.worker().generate_html_summary_table()) if len(station_names) > 0: self._setup_fill_and_save_dates() self.target_station.blockSignals(True) self.target_station.setCurrentIndex(0) self.target_station.blockSignals(False) self._handle_target_station_changed() self._loading_data_inprogress = False def _setup_fill_and_save_dates(self): """ Set first and last dates of the 'Fill data for weather station'. """ if self.gapfill_manager.count(): self.date_start_widget.setEnabled(True) self.date_end_widget.setEnabled(True) mindate = ( self.gapfill_manager.worker() .wxdatasets.metadata['first_date'].min()) maxdate = ( self.gapfill_manager.worker() .wxdatasets.metadata['last_date'].max()) qdatemin = QDate(mindate.year, mindate.month, mindate.day) qdatemax = QDate(maxdate.year, maxdate.month, maxdate.day) self.date_start_widget.blockSignals(True) self.date_start_widget.setDate(qdatemin) self.date_start_widget.setMinimumDate(qdatemin) self.date_start_widget.setMaximumDate(qdatemax) self.date_start_widget.blockSignals(False) self.date_end_widget.blockSignals(True) self.date_end_widget.setDate(qdatemax) self.date_end_widget.setMinimumDate(qdatemin) self.date_end_widget.setMaximumDate(qdatemax) self.date_end_widget.blockSignals(False) # ---- Gapfill Data def get_gapfill_parameters(self): """ Return a dictionary containing the parameters that are set in the GUI for gapfilling weather data. """ return { 'limitDist': self.distlimit.value(), 'limitAlt': self.altlimit.value(), 'date_start': self.date_start_widget.date().toString('dd/MM/yyyy'), 'date_end': self.date_end_widget.date().toString('dd/MM/yyyy') } def _handle_gapfill_btn_clicked(self): """ Handle when the user clicked on the gapfill button. """ if self.gapfill_manager.count() == 0: QMessageBox.warning( self, 'Warning', "There is no data to fill.", QMessageBox.Ok) return # Check for dates errors. datetime_start = datetime_from_qdatedit(self.date_start_widget) datetime_end = datetime_from_qdatedit(self.date_end_widget) if datetime_start > datetime_end: QMessageBox.warning( self, 'Warning', ("<i>From</i> date is set to a later time than " "the <i>To</i> date."), QMessageBox.Ok) return if self.target_station.currentIndex() == -1: QMessageBox.warning( self, 'Warning', "No weather station is currently selected", QMessageBox.Ok) return self.start_gapfill_target() def _handle_gapfill_target_finished(self): """ Method initiated from an automatic return from the gapfilling process in batch mode. Iterate over the station list and continue process normally. """ self.btn_fill.setIcon(get_icon('fill_data')) self.btn_fill.setEnabled(True) self.target_widget.setEnabled(True) self.fillDates_widg.setEnabled(True) self._regression_model_groupbox.setEnabled(True) self._station_selection_groupbox.setEnabled(True) self.progressbar.setValue(0) QApplication.processEvents() self.progressbar.hide() def start_gapfill_target(self): # Update the gui. self.btn_fill.setEnabled(False) self.fillDates_widg.setEnabled(False) self.target_widget.setEnabled(False) self._regression_model_groupbox.setEnabled(False) self._station_selection_groupbox.setEnabled(False) self.progressbar.show() # Start the gapfill thread. self.gapfill_manager.gapfill_data( time_start=datetime_from_qdatedit(self.date_start_widget), time_end=datetime_from_qdatedit(self.date_end_widget), max_neighbors=self.Nmax.value(), hdist_limit=self.distlimit.value(), vdist_limit=self.altlimit.value(), regression_mode=self.RMSE_regression.isChecked(), callback=self._handle_gapfill_target_finished ) def close(self): CONF.set('gapfill_data', 'nbr_of_station', self.Nmax.value()) CONF.set('gapfill_data', 'max_horiz_dist', self.distlimit.value()) CONF.set('gapfill_data', 'max_vert_dist', self.altlimit.value()) CONF.set('gapfill_data', 'regression_model', 'OLS' if self.RMSE_regression.isChecked() else 'LAD') super().close()
class Zstopwatch(QWidget): """Zstopwatch class""" def __init__(self): super().__init__() self.create_widgets() def create_widgets(self): """create_widgets""" self.seconds = 0 self.current_seconds = 0 #vbox_main self.vbox_main = QVBoxLayout() self.vbox_main.setContentsMargins(2, 2, 2, 2) self.setLayout(self.vbox_main) #hbox_tools self.hbox_tools = QHBoxLayout() self.vbox_main.addLayout(self.hbox_tools) #button_start self.button_start = QPushButton('Start') self.button_start.setIcon(QIcon(':/start_icon.png')) self.button_start.setFixedSize(80, 30) self.button_start.setCursor(Qt.PointingHandCursor) self.button_start.setStyleSheet(styles.get_button_style()) self.button_start.clicked.connect(self.press_start_button) self.hbox_tools.addWidget(self.button_start) # self.hbox_tools.addStretch() #button_stop self.button_stop = QPushButton('Stop') self.button_stop.setIcon(QIcon(':/stop_icon.png')) self.button_stop.setFixedSize(80, 30) self.button_stop.setCursor(Qt.PointingHandCursor) self.button_stop.setStyleSheet(styles.get_button_style()) self.button_stop.clicked.connect(self.press_stop_button) self.hbox_tools.addWidget(self.button_stop) #frame_labels self.frame_labels = QFrame() self.frame_labels.setStyleSheet("QFrame{border:1px solid silver;}") self.vbox_main.addWidget(self.frame_labels) #vbox_labels self.vbox_labels = QVBoxLayout() self.frame_labels.setLayout(self.vbox_labels) #label_timer self.label_timer = QLabel() self.label_timer.setAlignment(Qt.AlignCenter) self.label_timer.setStyleSheet( "QLabel{font-size:48px; border:1px solid transparent;}") self.vbox_labels.addWidget(self.label_timer) #label_current_time self.label_current_time = QLabel() self.label_current_time.setAlignment(Qt.AlignCenter) self.label_current_time.setStyleSheet("""QLabel{ font-size:24px; color:#609dff; border:1px solid transparent; }""") self.vbox_labels.addWidget(self.label_current_time) #tabber self.tabber = QTabWidget() self.tabber.setIconSize(QSize(35, 35)) self.vbox_main.addWidget(self.tabber) #add tabs #clock self.clock_tab = clock_tab.Clock_tab() self.tabber.addTab(self.clock_tab, QIcon(':/clock_icon.png'), '') #plan self.plan_tab = plan_tab.Plan_tab() self.tabber.addTab(self.plan_tab, QIcon(':/plan_icon.png'), '') #config self.config_tab = config_tab.Config_tab() self.tabber.addTab(self.config_tab, QIcon(':/config_icon.png'), '') #about self.about_tab = about.About() self.tabber.addTab(self.about_tab, QIcon(':/about_icon.png'), '') #main_timer self.main_timer = QTimer() self.main_timer.setInterval(1000) self.main_timer.timeout.connect(self.timer_out) #current_timer self.current_timer = QTimer() self.current_timer.setInterval(1000) self.current_timer.timeout.connect(self.current_timer_out) ### self.setWindowTitle('ZVVStopWatch') self.setWindowIcon(QIcon(':/app_icon.png')) self.setFixedSize(400, 550) self.show() #AUTORUN self.set_default_time() ####################################################################### def set_default_time(self): """Set default time""" #main_timer self.seconds = 0 self.set_time(self.seconds) #current_timer self.current_seconds = 0 self.set_current_time(self.current_seconds) def press_start_button(self): """Press start button""" if self.clock_tab.table_widget.rowCount() > 0: self.clock_tab.table_widget.setRowCount(0) self.main_timer.start() self.check_plan_task() QSound.play('./sounds/click.wav') def press_stop_button(self): """Press start button""" self.main_timer.stop() self.current_timer.stop() self.set_default_time() def timer_out(self): """Timer out""" self.seconds += 1 self.set_time(self.seconds) self.play_main_seconds_sound(self.seconds) def set_time(self, seconds): """Set seconds""" time_info = datetime.timedelta(seconds=seconds) self.label_timer.setText(str(time_info)) def check_plan_task(self): """Check plan task""" if self.plan_tab.table_widget.rowCount() > 0: self.current_seconds = int( self.plan_tab.table_widget.item(0, 1).TASK_TIME) self.set_current_time(self.current_seconds) self.current_timer.start() else: if self.config_tab.checkbox_end_all_tasks.isChecked(): if self.clock_tab.table_widget.rowCount() > 0: self.press_stop_button() def current_timer_out(self): """Current time out""" self.current_seconds -= 1 self.set_current_time(self.current_seconds) if self.current_seconds <= 0: #delete plan row, get new task and start task if self.plan_tab.table_widget.rowCount() > 0: name = self.plan_tab.table_widget.item(0, 0).TASK_NAME time_text = self.plan_tab.table_widget.item(0, 1).TASK_TIME self.clock_tab.add_one_row(name, time_text) QSound.play('./sounds/finish.wav') self.current_timer.stop() self.plan_tab.remove_row(0) self.check_plan_task() def set_current_time(self, current_seconds): """Set current_seconds""" time_info = datetime.timedelta(seconds=current_seconds) self.label_current_time.setText(str(time_info)[2:]) def play_main_seconds_sound(self, seconds): """Play main seconds sounds""" time_min = self.config_tab.spinbox_min_task.value() time_sec = self.config_tab.spinbox_sec_task.value() if time_min > 0 or time_sec > 0: full_time = (time_min * 60) + time_sec if seconds % full_time == 0: QSound.play('./sounds/normal.wav')
class Setting_Ui(QWidget): def __init__(self, persepolis_setting): super().__init__() icon = QtGui.QIcon() # add support for other languages locale = str(persepolis_setting.value('settings/locale')) QLocale.setDefault(QLocale(locale)) self.translator = QTranslator() if self.translator.load(':/translations/locales/ui_' + locale, 'ts'): QCoreApplication.installTranslator(self.translator) self.setWindowIcon( QIcon.fromTheme('persepolis', QIcon(':/persepolis.svg'))) self.setWindowTitle( QCoreApplication.translate("setting_ui_tr", 'Preferences')) # set ui direction ui_direction = persepolis_setting.value('ui_direction') if ui_direction == 'rtl': self.setLayoutDirection(Qt.RightToLeft) elif ui_direction in 'ltr': self.setLayoutDirection(Qt.LeftToRight) global icons icons = ':/' + str(persepolis_setting.value('settings/icons')) + '/' self.verticalLayout_2 = QVBoxLayout(self) self.setting_tabWidget = QTabWidget(self) # download_options_tab self.download_options_tab = QWidget() self.layoutWidget = QWidget(self.download_options_tab) self.download_options_verticalLayout = QVBoxLayout(self.layoutWidget) self.download_options_verticalLayout.setContentsMargins(21, 21, 0, 0) self.download_options_verticalLayout.setObjectName( "download_options_verticalLayout") self.horizontalLayout_5 = QHBoxLayout() # tries_label self.tries_label = QLabel(self.layoutWidget) self.horizontalLayout_5.addWidget(self.tries_label) # tries_spinBox self.tries_spinBox = QSpinBox(self.layoutWidget) self.tries_spinBox.setMinimum(1) self.horizontalLayout_5.addWidget(self.tries_spinBox) self.download_options_verticalLayout.addLayout(self.horizontalLayout_5) self.horizontalLayout_4 = QHBoxLayout() # wait_label self.wait_label = QLabel(self.layoutWidget) self.horizontalLayout_4.addWidget(self.wait_label) # wait_spinBox self.wait_spinBox = QSpinBox(self.layoutWidget) self.horizontalLayout_4.addWidget(self.wait_spinBox) self.download_options_verticalLayout.addLayout(self.horizontalLayout_4) self.horizontalLayout_3 = QHBoxLayout() # time_out_label self.time_out_label = QLabel(self.layoutWidget) self.horizontalLayout_3.addWidget(self.time_out_label) # time_out_spinBox self.time_out_spinBox = QSpinBox(self.layoutWidget) self.horizontalLayout_3.addWidget(self.time_out_spinBox) self.download_options_verticalLayout.addLayout(self.horizontalLayout_3) self.horizontalLayout_2 = QHBoxLayout() # connections_label self.connections_label = QLabel(self.layoutWidget) self.horizontalLayout_2.addWidget(self.connections_label) # connections_spinBox self.connections_spinBox = QSpinBox(self.layoutWidget) self.connections_spinBox.setMinimum(1) self.connections_spinBox.setMaximum(16) self.horizontalLayout_2.addWidget(self.connections_spinBox) self.download_options_verticalLayout.addLayout(self.horizontalLayout_2) # rpc_port_label self.rpc_port_label = QLabel(self.layoutWidget) self.rpc_horizontalLayout = QHBoxLayout() self.rpc_horizontalLayout.addWidget(self.rpc_port_label) # rpc_port_spinbox self.rpc_port_spinbox = QSpinBox(self.layoutWidget) self.rpc_port_spinbox.setMinimum(1024) self.rpc_port_spinbox.setMaximum(65535) self.rpc_horizontalLayout.addWidget(self.rpc_port_spinbox) self.download_options_verticalLayout.addLayout( self.rpc_horizontalLayout) # wait_queue wait_queue_horizontalLayout = QHBoxLayout() self.wait_queue_label = QLabel(self.layoutWidget) wait_queue_horizontalLayout.addWidget(self.wait_queue_label) self.wait_queue_time = QDateTimeEdit(self.layoutWidget) self.wait_queue_time.setDisplayFormat('H:mm') wait_queue_horizontalLayout.addWidget(self.wait_queue_time) self.download_options_verticalLayout.addLayout( wait_queue_horizontalLayout) # change aria2 path aria2_path_verticalLayout = QVBoxLayout() self.aria2_path_checkBox = QCheckBox(self.layoutWidget) aria2_path_verticalLayout.addWidget(self.aria2_path_checkBox) aria2_path_horizontalLayout = QHBoxLayout() self.aria2_path_lineEdit = QLineEdit(self.layoutWidget) aria2_path_horizontalLayout.addWidget(self.aria2_path_lineEdit) self.aria2_path_pushButton = QPushButton(self.layoutWidget) aria2_path_horizontalLayout.addWidget(self.aria2_path_pushButton) aria2_path_verticalLayout.addLayout(aria2_path_horizontalLayout) self.download_options_verticalLayout.addLayout( aria2_path_verticalLayout) self.setting_tabWidget.addTab(self.download_options_tab, "") # save_as_tab self.save_as_tab = QWidget() self.layoutWidget1 = QWidget(self.save_as_tab) self.save_as_verticalLayout = QVBoxLayout(self.layoutWidget1) self.save_as_verticalLayout.setContentsMargins(20, 30, 0, 0) self.download_folder_horizontalLayout = QHBoxLayout() # download_folder_label self.download_folder_label = QLabel(self.layoutWidget1) self.download_folder_horizontalLayout.addWidget( self.download_folder_label) # download_folder_lineEdit self.download_folder_lineEdit = QLineEdit(self.layoutWidget1) self.download_folder_horizontalLayout.addWidget( self.download_folder_lineEdit) # download_folder_pushButton self.download_folder_pushButton = QPushButton(self.layoutWidget1) self.download_folder_horizontalLayout.addWidget( self.download_folder_pushButton) self.save_as_verticalLayout.addLayout( self.download_folder_horizontalLayout) self.temp_horizontalLayout = QHBoxLayout() # temp_download_label self.temp_download_label = QLabel(self.layoutWidget1) self.temp_horizontalLayout.addWidget(self.temp_download_label) # temp_download_lineEdit self.temp_download_lineEdit = QLineEdit(self.layoutWidget1) self.temp_horizontalLayout.addWidget(self.temp_download_lineEdit) # temp_download_pushButton self.temp_download_pushButton = QPushButton(self.layoutWidget1) self.temp_horizontalLayout.addWidget(self.temp_download_pushButton) self.save_as_verticalLayout.addLayout(self.temp_horizontalLayout) # create subfolder checkBox self.subfolder_checkBox = QCheckBox(self.layoutWidget1) self.save_as_verticalLayout.addWidget(self.subfolder_checkBox) self.setting_tabWidget.addTab(self.save_as_tab, "") # notifications_tab self.notifications_tab = QWidget() self.layoutWidget2 = QWidget(self.notifications_tab) self.verticalLayout_4 = QVBoxLayout(self.layoutWidget2) self.verticalLayout_4.setContentsMargins(21, 21, 0, 0) # enable_notifications_checkBox self.enable_notifications_checkBox = QCheckBox(self.layoutWidget2) self.verticalLayout_4.addWidget(self.enable_notifications_checkBox) # sound_frame self.sound_frame = QFrame(self.layoutWidget2) self.sound_frame.setFrameShape(QFrame.StyledPanel) self.sound_frame.setFrameShadow(QFrame.Raised) self.verticalLayout = QVBoxLayout(self.sound_frame) # volume_label self.volume_label = QLabel(self.sound_frame) self.verticalLayout.addWidget(self.volume_label) # volume_dial self.volume_dial = QDial(self.sound_frame) self.volume_dial.setProperty("value", 100) self.verticalLayout.addWidget(self.volume_dial) self.verticalLayout_4.addWidget(self.sound_frame) self.setting_tabWidget.addTab(self.notifications_tab, "") # style_tab self.style_tab = QWidget() self.layoutWidget3 = QWidget(self.style_tab) self.verticalLayout_3 = QVBoxLayout(self.layoutWidget3) self.verticalLayout_3.setContentsMargins(21, 21, 0, 0) self.horizontalLayout_8 = QHBoxLayout() # style_label self.style_label = QLabel(self.layoutWidget3) self.horizontalLayout_8.addWidget(self.style_label) # style_comboBox self.style_comboBox = QComboBox(self.layoutWidget3) self.horizontalLayout_8.addWidget(self.style_comboBox) self.verticalLayout_3.addLayout(self.horizontalLayout_8) self.horizontalLayout_7 = QHBoxLayout() # language_combox self.lang_label = QLabel(self.layoutWidget3) self.horizontalLayout_7.addWidget(self.lang_label) self.lang_comboBox = QComboBox(self.layoutWidget3) self.horizontalLayout_7.addWidget(self.lang_comboBox) # language_label self.verticalLayout_3.addLayout(self.horizontalLayout_7) self.horizontalLayout_7 = QHBoxLayout() self.lang_label.setText( QCoreApplication.translate("setting_ui_tr", "language :")) # color_label self.color_label = QLabel(self.layoutWidget3) self.horizontalLayout_7.addWidget(self.color_label) # color_comboBox self.color_comboBox = QComboBox(self.layoutWidget3) self.horizontalLayout_7.addWidget(self.color_comboBox) self.verticalLayout_3.addLayout(self.horizontalLayout_7) # icon_label self.horizontalLayout_12 = QHBoxLayout() self.icon_label = QLabel(self.layoutWidget3) self.horizontalLayout_12.addWidget(self.icon_label) # icon_comboBox self.icon_comboBox = QComboBox(self.layoutWidget3) self.horizontalLayout_12.addWidget(self.icon_comboBox) self.verticalLayout_3.addLayout(self.horizontalLayout_12) # icons_size_comboBox self.icons_size_horizontalLayout = QHBoxLayout() self.icons_size_label = QLabel(self.layoutWidget3) self.icons_size_horizontalLayout.addWidget(self.icons_size_label) self.icons_size_comboBox = QComboBox(self.layoutWidget3) self.icons_size_horizontalLayout.addWidget(self.icons_size_comboBox) self.verticalLayout_3.addLayout(self.icons_size_horizontalLayout) self.horizontalLayout_6 = QHBoxLayout() # notification_label self.horizontalLayout_13 = QHBoxLayout() self.notification_label = QLabel(self.layoutWidget3) self.horizontalLayout_13.addWidget(self.notification_label) # notification_comboBox self.notification_comboBox = QComboBox(self.layoutWidget3) self.horizontalLayout_13.addWidget(self.notification_comboBox) self.verticalLayout_3.addLayout(self.horizontalLayout_13) # font_checkBox self.font_checkBox = QCheckBox(self.layoutWidget3) self.horizontalLayout_6.addWidget(self.font_checkBox) # fontComboBox self.fontComboBox = QFontComboBox(self.layoutWidget3) self.horizontalLayout_6.addWidget(self.fontComboBox) # font_size_label self.font_size_label = QLabel(self.layoutWidget3) self.horizontalLayout_6.addWidget(self.font_size_label) # font_size_spinBox self.font_size_spinBox = QSpinBox(self.layoutWidget3) self.font_size_spinBox.setMinimum(1) self.horizontalLayout_6.addWidget(self.font_size_spinBox) self.verticalLayout_3.addLayout(self.horizontalLayout_6) self.setting_tabWidget.addTab(self.style_tab, "") self.verticalLayout_2.addWidget(self.setting_tabWidget) self.horizontalLayout = QHBoxLayout() spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem) # Enable system tray icon self.enable_system_tray_checkBox = QCheckBox(self.layoutWidget3) self.verticalLayout_3.addWidget(self.enable_system_tray_checkBox) # after_download dialog self.after_download_checkBox = QCheckBox() self.verticalLayout_3.addWidget(self.after_download_checkBox) # show_menubar_checkbox self.show_menubar_checkbox = QCheckBox() self.verticalLayout_3.addWidget(self.show_menubar_checkbox) # show_sidepanel_checkbox self.show_sidepanel_checkbox = QCheckBox() self.verticalLayout_3.addWidget(self.show_sidepanel_checkbox) # hide progress window self.show_progress_window_checkbox = QCheckBox() self.verticalLayout_3.addWidget(self.show_progress_window_checkbox) # add persepolis to startup self.startup_checkbox = QCheckBox() self.verticalLayout_3.addWidget(self.startup_checkbox) # keep system awake self.keep_awake_checkBox = QCheckBox() self.verticalLayout_3.addWidget(self.keep_awake_checkBox) # columns_tab self.columns_tab = QWidget() layoutWidget4 = QWidget(self.columns_tab) column_verticalLayout = QVBoxLayout(layoutWidget4) column_verticalLayout.setContentsMargins(21, 21, 0, 0) # creating checkBox for columns self.show_column_label = QLabel() self.column0_checkBox = QCheckBox() self.column1_checkBox = QCheckBox() self.column2_checkBox = QCheckBox() self.column3_checkBox = QCheckBox() self.column4_checkBox = QCheckBox() self.column5_checkBox = QCheckBox() self.column6_checkBox = QCheckBox() self.column7_checkBox = QCheckBox() self.column10_checkBox = QCheckBox() self.column11_checkBox = QCheckBox() self.column12_checkBox = QCheckBox() column_verticalLayout.addWidget(self.show_column_label) column_verticalLayout.addWidget(self.column0_checkBox) column_verticalLayout.addWidget(self.column1_checkBox) column_verticalLayout.addWidget(self.column2_checkBox) column_verticalLayout.addWidget(self.column3_checkBox) column_verticalLayout.addWidget(self.column4_checkBox) column_verticalLayout.addWidget(self.column5_checkBox) column_verticalLayout.addWidget(self.column6_checkBox) column_verticalLayout.addWidget(self.column7_checkBox) column_verticalLayout.addWidget(self.column10_checkBox) column_verticalLayout.addWidget(self.column11_checkBox) column_verticalLayout.addWidget(self.column12_checkBox) self.setting_tabWidget.addTab(self.columns_tab, '') # youtube_tab self.youtube_tab = QWidget() self.layoutWidgetYTD = QWidget(self.youtube_tab) self.youtube_layout = QVBoxLayout(self.layoutWidgetYTD) self.youtube_layout.setContentsMargins(20, 30, 0, 0) self.youtube_verticalLayout = QVBoxLayout() # Whether to enable video link capturing. self.enable_ytd_checkbox = QCheckBox(self.layoutWidgetYTD) self.youtube_layout.addWidget(self.enable_ytd_checkbox) # If we should hide videos with no audio self.hide_no_audio_checkbox = QCheckBox(self.layoutWidgetYTD) self.youtube_verticalLayout.addWidget(self.hide_no_audio_checkbox) # If we should hide audios without video self.hide_no_video_checkbox = QCheckBox(self.layoutWidgetYTD) self.youtube_verticalLayout.addWidget(self.hide_no_video_checkbox) self.max_links_horizontalLayout = QHBoxLayout() # max_links_label self.max_links_label = QLabel(self.layoutWidgetYTD) self.max_links_horizontalLayout.addWidget(self.max_links_label) # max_links_spinBox self.max_links_spinBox = QSpinBox(self.layoutWidgetYTD) self.max_links_spinBox.setMinimum(1) self.max_links_spinBox.setMaximum(16) self.max_links_horizontalLayout.addWidget(self.max_links_spinBox) self.youtube_verticalLayout.addLayout(self.max_links_horizontalLayout) self.youtube_dl_path_horizontalLayout = QHBoxLayout() self.youtube_frame = QFrame(self.youtube_tab) self.youtube_frame.setLayout(self.youtube_verticalLayout) self.youtube_layout.addWidget(self.youtube_frame) self.setting_tabWidget.addTab(self.youtube_tab, "") # defaults_pushButton self.defaults_pushButton = QPushButton(self) self.horizontalLayout.addWidget(self.defaults_pushButton) # cancel_pushButton self.cancel_pushButton = QPushButton(self) self.cancel_pushButton.setIcon(QIcon(icons + 'remove')) self.horizontalLayout.addWidget(self.cancel_pushButton) # ok_pushButton self.ok_pushButton = QPushButton(self) self.ok_pushButton.setIcon(QIcon(icons + 'ok')) self.horizontalLayout.addWidget(self.ok_pushButton) self.verticalLayout_2.addLayout(self.horizontalLayout) self.setting_tabWidget.setCurrentIndex(3) self.setWindowTitle( QCoreApplication.translate("setting_ui_tr", "Preferences")) self.tries_label.setToolTip( QCoreApplication.translate( "setting_ui_tr", "<html><head/><body><p>Set number of tries if download failed.</p></body></html>" )) self.tries_label.setText( QCoreApplication.translate("setting_ui_tr", "Number of tries : ")) self.tries_spinBox.setToolTip( QCoreApplication.translate( "setting_ui_tr", "<html><head/><body><p>Set number of tries if download failed.</p></body></html>" )) self.wait_label.setToolTip( QCoreApplication.translate( "setting_ui_tr", "<html><head/><body><p>Set the seconds to wait between retries. Download manager will retry downloads when the HTTP server returns a 503 response.</p></body></html>" )) self.wait_label.setText( QCoreApplication.translate("setting_ui_tr", "Wait between retries (seconds) : ")) self.wait_spinBox.setToolTip( QCoreApplication.translate( "setting_ui_tr", "<html><head/><body><p>Set the seconds to wait between retries. Download manager will retry downloads when the HTTP server returns a 503 response.</p></body></html>" )) self.time_out_label.setToolTip( QCoreApplication.translate( "setting_ui_tr", "<html><head/><body><p>Set timeout in seconds. </p></body></html>" )) self.time_out_label.setText( QCoreApplication.translate("setting_ui_tr", "Time out (seconds) : ")) self.time_out_spinBox.setToolTip( QCoreApplication.translate( "setting_ui_tr", "<html><head/><body><p>Set timeout in seconds. </p></body></html>" )) self.connections_label.setToolTip( QCoreApplication.translate( "setting_ui_tr", "<html><head/><body><p>Using multiple connections can help speed up your download.</p></body></html>" )) self.connections_label.setText( QCoreApplication.translate("setting_ui_tr", "Number of connections : ")) self.connections_spinBox.setToolTip( QCoreApplication.translate( "setting_ui_tr", "<html><head/><body><p>Using multiple connections can help speed up your download.</p></body></html>" )) self.rpc_port_label.setText( QCoreApplication.translate("setting_ui_tr", "RPC port number : ")) self.rpc_port_spinbox.setToolTip( QCoreApplication.translate( "setting_ui_tr", "<html><head/><body><p> Specify a port number for JSON-RPC/XML-RPC server to listen to. Possible Values: 1024 - 65535 Default: 6801 </p></body></html>" )) self.wait_queue_label.setText( QCoreApplication.translate( "setting_ui_tr", 'Wait between every downloads in queue:')) self.aria2_path_checkBox.setText( QCoreApplication.translate("setting_ui_tr", 'Change aria2 default path')) self.aria2_path_pushButton.setText( QCoreApplication.translate("setting_ui_tr", 'Change')) aria2_path_tooltip = QCoreApplication.translate( "setting_ui_tr", "<html><head/><body><p>Attention: Wrong path may have caused problem! Do it carefully or don't change default setting!</p></body></html>" ) self.aria2_path_checkBox.setToolTip(aria2_path_tooltip) self.aria2_path_lineEdit.setToolTip(aria2_path_tooltip) self.aria2_path_pushButton.setToolTip(aria2_path_tooltip) self.setting_tabWidget.setTabText( self.setting_tabWidget.indexOf(self.download_options_tab), QCoreApplication.translate("setting_ui_tr", "Download Options")) self.download_folder_label.setText( QCoreApplication.translate("setting_ui_tr", "Download Folder : ")) self.download_folder_pushButton.setText( QCoreApplication.translate("setting_ui_tr", "Change")) self.temp_download_label.setText( QCoreApplication.translate("setting_ui_tr", "Temporary Download Folder : ")) self.temp_download_pushButton.setText( QCoreApplication.translate("setting_ui_tr", "Change")) self.subfolder_checkBox.setText( QCoreApplication.translate( "setting_ui_tr", "Create subfolders for Music,Videos,... in default download folder" )) self.setting_tabWidget.setTabText( self.setting_tabWidget.indexOf(self.save_as_tab), QCoreApplication.translate("setting_ui_tr", "Save as")) self.enable_notifications_checkBox.setText( QCoreApplication.translate("setting_ui_tr", "Enable notification sounds")) self.volume_label.setText( QCoreApplication.translate("setting_ui_tr", "Volume : ")) self.setting_tabWidget.setTabText( self.setting_tabWidget.indexOf(self.notifications_tab), QCoreApplication.translate("setting_ui_tr", "Notifications")) self.style_label.setText( QCoreApplication.translate("setting_ui_tr", "Style : ")) self.color_label.setText( QCoreApplication.translate("setting_ui_tr", "Color scheme : ")) self.icon_label.setText( QCoreApplication.translate("setting_ui_tr", "Icons : ")) self.icons_size_label.setText( QCoreApplication.translate("setting_ui_tr", "ToolBar's icons size : ")) self.notification_label.setText( QCoreApplication.translate("setting_ui_tr", "Notification type : ")) self.font_checkBox.setText( QCoreApplication.translate("setting_ui_tr", "Font : ")) self.font_size_label.setText( QCoreApplication.translate("setting_ui_tr", "Size : ")) self.enable_system_tray_checkBox.setText( QCoreApplication.translate("setting_ui_tr", "Enable system tray icon.")) self.after_download_checkBox.setText( QCoreApplication.translate( "setting_ui_tr", "Show download complete dialog,when download has finished.")) self.show_menubar_checkbox.setText( QCoreApplication.translate("setting_ui_tr", "Show menubar.")) self.show_sidepanel_checkbox.setText( QCoreApplication.translate("setting_ui_tr", "Show side panel.")) self.show_progress_window_checkbox.setText( QCoreApplication.translate("setting_ui_tr", "Show download's progress window")) self.startup_checkbox.setText( QCoreApplication.translate("setting_ui_tr", "Run Persepolis at startup")) self.keep_awake_checkBox.setText( QCoreApplication.translate("setting_ui_tr", "Keep system awake!")) self.keep_awake_checkBox.setToolTip( QCoreApplication.translate( "setting_ui_tr", "<html><head/><body><p>This option is preventing system from going to sleep.\ This is necessary if your power manager is suspending system automatically. </p></body></html>" )) self.wait_queue_time.setToolTip( QCoreApplication.translate( "setting_ui_tr", "<html><head/><body><p>Format HH:MM</p></body></html>")) self.setting_tabWidget.setTabText( self.setting_tabWidget.indexOf(self.style_tab), QCoreApplication.translate("setting_ui_tr", "Preferences")) # columns_tab self.show_column_label.setText( QCoreApplication.translate("setting_ui_tr", 'Show this columns:')) self.column0_checkBox.setText( QCoreApplication.translate("setting_ui_tr", 'File Name')) self.column1_checkBox.setText( QCoreApplication.translate("setting_ui_tr", 'Status')) self.column2_checkBox.setText( QCoreApplication.translate("setting_ui_tr", 'Size')) self.column3_checkBox.setText( QCoreApplication.translate("setting_ui_tr", 'Downloaded')) self.column4_checkBox.setText( QCoreApplication.translate("setting_ui_tr", 'Percentage')) self.column5_checkBox.setText( QCoreApplication.translate("setting_ui_tr", 'Connections')) self.column6_checkBox.setText( QCoreApplication.translate("setting_ui_tr", 'Transfer rate')) self.column7_checkBox.setText( QCoreApplication.translate("setting_ui_tr", 'Estimated time left')) self.column10_checkBox.setText( QCoreApplication.translate("setting_ui_tr", 'First try date')) self.column11_checkBox.setText( QCoreApplication.translate("setting_ui_tr", 'Last try date')) self.column12_checkBox.setText( QCoreApplication.translate("setting_ui_tr", 'Category')) self.setting_tabWidget.setTabText( self.setting_tabWidget.indexOf(self.columns_tab), QCoreApplication.translate("setting_ui_tr", "Columns customization")) # Video Finder options tab self.setting_tabWidget.setTabText( self.setting_tabWidget.indexOf(self.youtube_tab), QCoreApplication.translate("setting_ui_tr", "Video Finder Options")) self.enable_ytd_checkbox.setText( QCoreApplication.translate("setting_ui_tr", 'Enable Video Finder')) self.hide_no_audio_checkbox.setText( QCoreApplication.translate("setting_ui_tr", 'Hide videos with no audio')) self.hide_no_video_checkbox.setText( QCoreApplication.translate("setting_ui_tr", 'Hide audios with no video')) self.max_links_label.setText( QCoreApplication.translate( "setting_ui_tr", 'Maximum number of links to capture :<br/>' '<small>(If browser sends multiple video links at a time)</small>' )) # window buttons self.defaults_pushButton.setText( QCoreApplication.translate("setting_ui_tr", "Defaults")) self.cancel_pushButton.setText( QCoreApplication.translate("setting_ui_tr", "Cancel")) self.ok_pushButton.setText( QCoreApplication.translate("setting_ui_tr", "OK"))
class solar_main(QWidget): update = pyqtSignal() def __init__(self, path): self.path = path self.export_file_name = os.path.join(self.path, "spectra.inp") super().__init__() self.resize(1200, 600) self.setWindowIcon(icon_get("weather-few-clouds")) self.vbox = QVBoxLayout() self.ribbon = ribbon_solar() self.vbox.addWidget(self.ribbon) self.ribbon.run.triggered.connect(self.callback_run) self.ribbon.export.triggered.connect(self.callback_export) self.setWindowTitle( _("Solar Spectrum Generator") + " (https://www.gpvdm.com)") self.center() self.notebook = QTabWidget() self.vbox.addWidget(self.notebook) earth = planet(self.export_file_name) earth.set_earth(True) earth.init() self.notebook.addTab(earth, "Earth") #mercury = planet(self.export_file_name) #mercury.set_mercury(True) #mercury.set_orbitalpoint(True) #mercury.init() #self.notebook.addTab(mercury,"Mercury") #venus = planet(self.export_file_name) #venus.set_venus(True) #venus.set_orbitalpoint(True) #venus.init() #self.notebook.addTab(venus,"Venus") #mars = planet(self.export_file_name) #mars.set_mars(True) #mars.set_orbitalpoint(True) #mars.init() #self.notebook.addTab(mars,"Mars") #ceres = planet(self.export_file_name) #ceres.set_ceres(True) #ceres.set_orbitalpoint(True) #ceres.init() #self.notebook.addTab(ceres, "Ceres (Dwarf Planet)") #europa = planet(self.export_file_name) #europa.set_europa(True) #europa.set_orbitalpoint(True) #europa.init() #self.notebook.addTab(europa, "Europa (moon of Jupiter)") #halley = planet(self.export_file_name) #halley.set_halley(True) #halley.set_orbitalpoint(True) #halley.init() #self.notebook.addTab(halley, "Halley's Comet") #pluto = planet(self.export_file_name) #pluto.set_pluto(True) #pluto.set_orbitalpoint(True) #pluto.init() #self.notebook.addTab(pluto, "Pluto") self.setLayout(self.vbox) def callback_run(self): tab = self.notebook.currentWidget() tab.update() def callback_export(self): tab = self.notebook.currentWidget() tab.export() self.update.emit() def save(self): self.notebook.currentWidget().save() def copy(self): self.notebook.currentWidget().copy2clip() def center(self): qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft())
def __init__(self): super().__init__() self.setLayout(QVBoxLayout()) self.setWindowTitle(i18n("Export settings")) buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) buttons.accepted.connect(self.accept) buttons.rejected.connect(self.reject) mainWidget = QTabWidget() self.layout().addWidget(mainWidget) self.layout().addWidget(buttons) # Set basic crop settings # Set which layers to remove before export. mainExportSettings = QWidget() mainExportSettings.setLayout(QVBoxLayout()) groupExportCrop = QGroupBox(i18n("Crop settings")) formCrop = QFormLayout() groupExportCrop.setLayout(formCrop) self.chk_toOutmostGuides = QCheckBox(i18n("Crop to outmost guides")) self.chk_toOutmostGuides.setChecked(True) self.chk_toOutmostGuides.setToolTip( i18n( "This will crop to the outmost guides if possible and otherwise use the underlying crop settings." )) formCrop.addRow("", self.chk_toOutmostGuides) btn_fromSelection = QPushButton( i18n("Set margins from active selection")) btn_fromSelection.clicked.connect(self.slot_set_margin_from_selection) # This doesn't work. formCrop.addRow("", btn_fromSelection) self.spn_marginLeft = QSpinBox() self.spn_marginLeft.setMaximum(99999) self.spn_marginLeft.setSuffix(" px") formCrop.addRow(i18n("Left:"), self.spn_marginLeft) self.spn_marginTop = QSpinBox() self.spn_marginTop.setMaximum(99999) self.spn_marginTop.setSuffix(" px") formCrop.addRow(i18n("Top:"), self.spn_marginTop) self.spn_marginRight = QSpinBox() self.spn_marginRight.setMaximum(99999) self.spn_marginRight.setSuffix(" px") formCrop.addRow(i18n("Right:"), self.spn_marginRight) self.spn_marginBottom = QSpinBox() self.spn_marginBottom.setMaximum(99999) self.spn_marginBottom.setSuffix(" px") formCrop.addRow(i18n("Bottom:"), self.spn_marginBottom) groupExportLayers = QGroupBox(i18n("Layers")) formLayers = QFormLayout() groupExportLayers.setLayout(formLayers) self.cmbLabelsRemove = labelSelector() formLayers.addRow(i18n("Label for removal:"), self.cmbLabelsRemove) self.ln_text_layer_name = QLineEdit() self.ln_text_layer_name.setToolTip( i18n( "These are keywords that can be used to identify text layers. A layer only needs to contain the keyword to be recognised. Keywords should be comma seperated." )) self.ln_panel_layer_name = QLineEdit() self.ln_panel_layer_name.setToolTip( i18n( "These are keywords that can be used to identify panel layers. A layer only needs to contain the keyword to be recognised. Keywords should be comma seperated." )) formLayers.addRow(i18n("Text Layer Key:"), self.ln_text_layer_name) formLayers.addRow(i18n("Panel Layer Key:"), self.ln_panel_layer_name) mainExportSettings.layout().addWidget(groupExportCrop) mainExportSettings.layout().addWidget(groupExportLayers) mainWidget.addTab(mainExportSettings, i18n("General")) # CBZ, crop, resize, which metadata to add. CBZexportSettings = QWidget() CBZexportSettings.setLayout(QVBoxLayout()) self.CBZactive = QCheckBox(i18n("Export to CBZ")) CBZexportSettings.layout().addWidget(self.CBZactive) self.CBZgroupResize = comic_export_resize_widget("CBZ") CBZexportSettings.layout().addWidget(self.CBZgroupResize) self.CBZactive.clicked.connect(self.CBZgroupResize.setEnabled) CBZgroupMeta = QGroupBox(i18n("Metadata to add")) # CBZexportSettings.layout().addWidget(CBZgroupMeta) CBZgroupMeta.setLayout(QFormLayout()) mainWidget.addTab(CBZexportSettings, "CBZ") # ACBF, crop, resize, creator name, version history, panel layer, text layers. ACBFExportSettings = QWidget() ACBFform = QFormLayout() ACBFExportSettings.setLayout(QVBoxLayout()) ACBFdocInfo = QGroupBox() ACBFdocInfo.setTitle(i18n("ACBF Document Info")) ACBFdocInfo.setLayout(ACBFform) self.lnACBFSource = QLineEdit() self.lnACBFSource.setToolTip( i18n( "Whether the acbf file is an adaption of an existing source, and if so, how to find information about that source. So for example, for an adapted webcomic, the official website url should go here." )) self.lnACBFID = QLabel() self.lnACBFID.setToolTip( i18n( "By default this will be filled with a generated universal unique identifier. The ID by itself is merely so that comic book library management programs can figure out if this particular comic is already in their database and whether it has been rated. Of course, the UUID can be changed into something else by manually changing the json, but this is advanced usage." )) self.spnACBFVersion = QSpinBox() self.ACBFhistoryModel = QStandardItemModel() acbfHistoryList = QListView() acbfHistoryList.setModel(self.ACBFhistoryModel) btn_add_history = QPushButton(i18n("Add history entry")) btn_add_history.clicked.connect(self.slot_add_history_item) self.chkIncludeTranslatorComments = QCheckBox() self.chkIncludeTranslatorComments.setText( i18n("Include Translator's Comments")) self.chkIncludeTranslatorComments.setToolTip( i18n( "A PO file can contain translator's comments. If this is checked, the translations comments will be added as references into the ACBF file." )) self.lnTranslatorHeader = QLineEdit() ACBFform.addRow(i18n("Source:"), self.lnACBFSource) ACBFform.addRow(i18n("ACBF UID:"), self.lnACBFID) ACBFform.addRow(i18n("Version:"), self.spnACBFVersion) ACBFform.addRow(i18n("Version History:"), acbfHistoryList) ACBFform.addRow("", btn_add_history) ACBFform.addRow("", self.chkIncludeTranslatorComments) ACBFform.addRow(i18n("Translator Header:"), self.lnTranslatorHeader) ACBFAuthorInfo = QWidget() acbfAVbox = QVBoxLayout(ACBFAuthorInfo) infoLabel = QLabel( i18n( "The people responsible for the generation of the CBZ/ACBF files." )) infoLabel.setWordWrap(True) ACBFAuthorInfo.layout().addWidget(infoLabel) self.ACBFauthorModel = QStandardItemModel(0, 6) labels = [ i18n("Nick Name"), i18n("Given Name"), i18n("Middle Name"), i18n("Family Name"), i18n("Email"), i18n("Homepage") ] self.ACBFauthorModel.setHorizontalHeaderLabels(labels) self.ACBFauthorTable = QTableView() acbfAVbox.addWidget(self.ACBFauthorTable) self.ACBFauthorTable.setModel(self.ACBFauthorModel) self.ACBFauthorTable.verticalHeader().setDragEnabled(True) self.ACBFauthorTable.verticalHeader().setDropIndicatorShown(True) self.ACBFauthorTable.verticalHeader().setSectionsMovable(True) self.ACBFauthorTable.verticalHeader().sectionMoved.connect( self.slot_reset_author_row_visual) AuthorButtons = QHBoxLayout() btn_add_author = QPushButton(i18n("Add author")) btn_add_author.clicked.connect(self.slot_add_author) AuthorButtons.addWidget(btn_add_author) btn_remove_author = QPushButton(i18n("Remove author")) btn_remove_author.clicked.connect(self.slot_remove_author) AuthorButtons.addWidget(btn_remove_author) acbfAVbox.addLayout(AuthorButtons) ACBFStyle = QWidget() ACBFStyle.setLayout(QHBoxLayout()) self.ACBFStylesModel = QStandardItemModel() self.ACBFStyleClass = QListView() self.ACBFStyleClass.setModel(self.ACBFStylesModel) ACBFStyle.layout().addWidget(self.ACBFStyleClass) ACBFStyleEdit = QWidget() ACBFStyleEditVB = QVBoxLayout(ACBFStyleEdit) self.ACBFfontCombo = QFontComboBox() self.ACBFdefaultFont = QComboBox() self.ACBFdefaultFont.addItems( ["sans-serif", "serif", "monospace", "cursive", "fantasy"]) self.ACBFBold = QCheckBox(i18n("Bold")) self.ACBFItal = QCheckBox(i18n("Italic")) self.ACBFStyleClass.clicked.connect(self.slot_set_style) self.ACBFStyleClass.selectionModel().selectionChanged.connect( self.slot_set_style) self.ACBFStylesModel.itemChanged.connect(self.slot_set_style) self.ACBFfontCombo.currentFontChanged.connect( self.slot_font_current_style) self.ACBFfontCombo.setEditable(False) self.ACBFBold.toggled.connect(self.slot_font_current_style) self.ACBFItal.toggled.connect(self.slot_font_current_style) colorWidget = QGroupBox(self) colorWidget.setTitle(i18n("Text Colors")) colorWidget.setLayout(QVBoxLayout()) self.regularColor = QColorDialog() self.invertedColor = QColorDialog() self.btn_acbfRegColor = QPushButton(i18n("Regular Text"), self) self.btn_acbfRegColor.clicked.connect(self.slot_change_regular_color) self.btn_acbfInvColor = QPushButton(i18n("Inverted Text"), self) self.btn_acbfInvColor.clicked.connect(self.slot_change_inverted_color) colorWidget.layout().addWidget(self.btn_acbfRegColor) colorWidget.layout().addWidget(self.btn_acbfInvColor) ACBFStyleEditVB.addWidget(colorWidget) ACBFStyleEditVB.addWidget(self.ACBFfontCombo) ACBFStyleEditVB.addWidget(self.ACBFdefaultFont) ACBFStyleEditVB.addWidget(self.ACBFBold) ACBFStyleEditVB.addWidget(self.ACBFItal) ACBFStyleEditVB.addStretch() ACBFStyle.layout().addWidget(ACBFStyleEdit) ACBFTabwidget = QTabWidget() ACBFTabwidget.addTab(ACBFdocInfo, i18n("Document Info")) ACBFTabwidget.addTab(ACBFAuthorInfo, i18n("Author Info")) ACBFTabwidget.addTab(ACBFStyle, i18n("Style Sheet")) ACBFExportSettings.layout().addWidget(ACBFTabwidget) mainWidget.addTab(ACBFExportSettings, i18n("ACBF")) # Epub export, crop, resize, other questions. EPUBexportSettings = QWidget() EPUBexportSettings.setLayout(QVBoxLayout()) self.EPUBactive = QCheckBox(i18n("Export to EPUB")) EPUBexportSettings.layout().addWidget(self.EPUBactive) self.EPUBgroupResize = comic_export_resize_widget("EPUB") EPUBexportSettings.layout().addWidget(self.EPUBgroupResize) self.EPUBactive.clicked.connect(self.EPUBgroupResize.setEnabled) mainWidget.addTab(EPUBexportSettings, "EPUB") # For Print. Crop, no resize. TIFFExportSettings = QWidget() TIFFExportSettings.setLayout(QVBoxLayout()) self.TIFFactive = QCheckBox(i18n("Export to TIFF")) TIFFExportSettings.layout().addWidget(self.TIFFactive) self.TIFFgroupResize = comic_export_resize_widget("TIFF") TIFFExportSettings.layout().addWidget(self.TIFFgroupResize) self.TIFFactive.clicked.connect(self.TIFFgroupResize.setEnabled) mainWidget.addTab(TIFFExportSettings, "TIFF")
def getUi(self): self.font = QFont('微软雅黑', 16) self.setFont(self.font) self.setWindowTitle("CTA交易系统") self.setWindowIcon(QIcon('material\\icon.png')) self.setGeometry(200, 50, 1500, 1000) # 内部框架 vbox0 = QVBoxLayout() gbox1 = QGroupBox('频段') gbox2 = QGroupBox('基本日志记录') vbox0.addWidget(gbox1, stretch=2) vbox0.addWidget(gbox2, stretch=1) # 频段 tab = QTabWidget() self.TableFreqDuo = {} self.TableFreqKong = {} self.TableFreqPosition = {} self.TableFreqOrder = {} self.TableFreqTrade = {} for eachFreq in listFreq: tabSub = QTabWidget() #region 做多与做空 tabSub1 = QWidget() tableDuo = QTableWidget(0, len(listDuoKong), self) self.TableFreqDuo[eachFreq] = tableDuo tableDuo.setHorizontalHeaderLabels(listDuoKong) tableDuo.verticalHeader().setVisible(False) tableDuo.setFont(self.font) tableDuo.resizeColumnsToContents() tableKong = QTableWidget(0, len(listDuoKong), self) self.TableFreqKong[eachFreq] = tableKong tableKong.setHorizontalHeaderLabels(listDuoKong) tableKong.verticalHeader().setVisible(False) tableKong.setFont(self.font) tableKong.resizeColumnsToContents() vbox = QVBoxLayout() vbox.addWidget(QLabel('做多', self)) vbox.addWidget(tableDuo) vbox.addWidget(QLabel('做空', self)) vbox.addWidget(tableKong) tabSub1.setLayout(vbox) #endregion #region 频段的持仓 tabSub2 = QWidget() tablePosition = QTableWidget(0, len(listFreqPosition), self) tablePosition.setHorizontalHeaderLabels(listFreqPosition) for num in range(len(listFreqPosition)): tablePosition.horizontalHeaderItem(num).setFont(self.font) tablePosition.setFont(self.font) tablePosition.resizeColumnsToContents() tablePosition.verticalHeader().setVisible(False) self.TableFreqPosition[eachFreq] = tablePosition hbox = QHBoxLayout() hbox.addWidget(tablePosition) tabSub2.setLayout(hbox) #endregion #region 频段的成交 tabSub3 = QWidget() tableTrade = QTableWidget(0, len(listTrade), self) tableTrade.setHorizontalHeaderLabels(listTrade) for num in range(len(listTrade)): tableTrade.horizontalHeaderItem(num).setFont(self.font) tableTrade.setFont(self.font) tableTrade.resizeColumnsToContents() tableTrade.verticalHeader().setVisible(False) self.TableFreqTrade[eachFreq] = tableTrade hbox = QHBoxLayout() hbox.addWidget(tableTrade) tabSub3.setLayout(hbox) #endregion #region 频段的委托 tabSub4 = QWidget() tableOrder = QTableWidget(0, len(listOrder), self) tableOrder.setHorizontalHeaderLabels(listOrder) for num in range(len(listOrder)): tableOrder.horizontalHeaderItem(num).setFont(self.font) tableOrder.setFont(self.font) tableOrder.resizeColumnsToContents() tableOrder.verticalHeader().setVisible(False) self.TableFreqOrder[eachFreq] = tableOrder hbox = QHBoxLayout() hbox.addWidget(tableOrder) tabSub4.setLayout(hbox) #endregion tabSub.addTab(tabSub1, '做多与做空') tabSub.addTab(tabSub2, '频段持仓') tabSub.addTab(tabSub3, '频段成交') tabSub.addTab(tabSub4, '频段委托') tab.addTab(tabSub, 'CTA' + str(eachFreq)) hbox = QHBoxLayout() hbox.addWidget(tab) gbox1.setLayout(hbox) # 日志输出与总持仓显示 self.txtLog = QTextEdit(self) self.txtLog.setEnabled(True) hbox = QHBoxLayout() tab2 = QTabWidget() self.txtLog = QTextEdit(self) self.txtLog.setEnabled(True) tab2.addTab(self.txtLog, '程序日志') self.tabPosition = QWidget() self.tabPosition.setLayout(self.tabPositionUi()) tab2.addTab(self.tabPosition, '账户持仓') self.tabAccount = QWidget() self.tabAccount.setLayout(self.tabAccountUi()) tab2.addTab(self.tabAccount, '账户资金') tab2.currentChanged.connect(self.switchTab2) hbox.addWidget(tab2) gbox2.setLayout(hbox) #region 菜单栏 menu_root = self.menuBar() menu_root.setFont(self.font) orderhandle = menu_root.addMenu('手动下单操作') ordering = QAction('下单', self) ordering.setFont(self.font) ordering.triggered.connect(self.orderShow) orderhandle.addAction(ordering) orderingCancel = QAction('撤单', self) orderingCancel.setFont(self.font) orderingCancel.triggered.connect(self.orderCancelShow) orderhandle.addAction(orderingCancel) orderingPark = QAction('预下单', self) orderingPark.setFont(self.font) orderingPark.triggered.connect(self.orderParkShow) orderhandle.addAction(orderingPark) init = menu_root.addMenu('初始化操作') self.initItem = QAction('初始化开始', self) self.initItem.setFont(self.font) self.initItem.triggered.connect(self.getInit) init.addAction(self.initItem) start = menu_root.addMenu('交易中操作') self.startItem = QAction('交易开始', self) self.startItem.setFont(self.font) self.startItem.triggered.connect(self.getTrade) start.addAction(self.startItem) deleteDb = menu_root.addMenu('删除数据') self.dltItem = QAction('删除本交易日数据(含夜盘)', self) self.dltItem.setFont(self.font) self.dltItem.triggered.connect(self.theDlt) self.dltItem1 = QAction('删除本交易日数据(不含夜盘)', self) self.dltItem1.setFont(self.font) self.dltItem1.triggered.connect(self.theDlt1) self.dltItem2 = QAction('删除指定时间数据', self) self.dltItem2.setFont(self.font) self.dltItem2.triggered.connect(self.theDlt2) deleteDb.addAction(self.dltItem) deleteDb.addAction(self.dltItem1) deleteDb.addAction(self.dltItem2) #endregion # 总布局 widget = QWidget() widget.setLayout(vbox0) self.setCentralWidget(widget)
class EditStructure(ToolInstance): help = "https://github.com/QChASM/SEQCROW/wiki/Structure-Modification-Tool" SESSION_ENDURING = True SESSION_SAVE = True def __init__(self, session, name): super().__init__(session, name) self.settings = _EditStructureSettings(session, "Structure Modification") self.tool_window = MainToolWindow(self) self.close_previous_bool = self.settings.modify self._build_ui() def _build_ui(self): layout = QGridLayout() self.alchemy_tabs = QTabWidget() #substitute substitute_tab = QWidget() substitute_layout = QGridLayout(substitute_tab) sublabel = QLabel("substituent name:") substitute_layout.addWidget(sublabel, 0, 0, Qt.AlignVCenter) self.subname = QLineEdit() # self.subname.setText("Et") sub_completer = NameCompleter(Substituent.list(), self.subname) self.subname.setCompleter(sub_completer) self.subname.setToolTip("name of substituent in the AaronTools library or your personal library\nseparate names with commas and uncheck 'modify selected structure' to create several structures") substitute_layout.addWidget(self.subname, 0, 1, Qt.AlignVCenter) open_sub_lib = QPushButton("from library...") open_sub_lib.clicked.connect(self.open_sub_selector) substitute_layout.addWidget(open_sub_lib, 0, 2, Qt.AlignTop) substitute_layout.addWidget(QLabel("modify selected structure:"), 1, 0, 1, 1, Qt.AlignVCenter) self.close_previous_sub = QCheckBox() self.close_previous_sub.setToolTip("checked: selected structure will be modified\nunchecked: new model will be created for the modified structure") self.close_previous_sub.setChecked(self.settings.modify) self.close_previous_sub.stateChanged.connect(self.close_previous_change) substitute_layout.addWidget(self.close_previous_sub, 1, 1, 1, 2, Qt.AlignTop) substitute_layout.addWidget(QLabel("relax substituent:"), 2, 0, 1, 1, Qt.AlignVCenter) self.minimize = QCheckBox() self.minimize.setToolTip("spin the added substituents to try to minimize the LJ potential energy") self.minimize.setChecked(self.settings.minimize) substitute_layout.addWidget(self.minimize, 2, 1, 1, 1, Qt.AlignTop) substitute_layout.addWidget(QLabel("guess previous substituent:"), 3, 0, 1, 1, Qt.AlignVCenter) self.guess_old = QCheckBox() self.guess_old.setToolTip("checked: leave the longest connected fragment in the residue\nunchecked: previous substituent must be selected") self.guess_old.setChecked(self.settings.guess) self.guess_old.stateChanged.connect(lambda state, settings=self.settings: settings.__setattr__("guess", True if state == Qt.Checked else False)) substitute_layout.addWidget(self.guess_old, 3, 1, 1, 2, Qt.AlignTop) substitute_layout.addWidget(QLabel("new residue:"), 5, 0, 1, 1, Qt.AlignVCenter) self.new_residue = QCheckBox() self.new_residue.setToolTip("put the new substituent in its own residue instead\nof adding it to the residue of the old substituent") self.new_residue.setChecked(self.settings.new_residue) self.new_residue.stateChanged.connect(lambda state, settings=self.settings: settings.__setattr__("new_residue", True if state == Qt.Checked else False)) substitute_layout.addWidget(self.new_residue, 5, 1, 1, 2, Qt.AlignTop) substitute_layout.addWidget(QLabel("use distance names:"), 4, 0, 1, 1, Qt.AlignVCenter) self.use_greek = QCheckBox() self.use_greek.setChecked(self.settings.use_greek) self.use_greek.setToolTip("indicate distance from point of attachment with atom name") substitute_layout.addWidget(self.use_greek, 4, 1, 1, 1, Qt.AlignTop) substitute_layout.addWidget(QLabel("change residue name:"), 6, 0, 1, 1, Qt.AlignVCenter) self.new_sub_name = QLineEdit() self.new_sub_name.setToolTip("change name of modified residues") self.new_sub_name.setPlaceholderText("leave blank to keep current") substitute_layout.addWidget(self.new_sub_name, 6, 1, 1, 2, Qt.AlignTop) substitute_button = QPushButton("substitute current selection") substitute_button.clicked.connect(self.do_substitute) substitute_layout.addWidget(substitute_button, 7, 0, 1, 3, Qt.AlignTop) self.substitute_button = substitute_button substitute_layout.setRowStretch(0, 0) substitute_layout.setRowStretch(1, 0) substitute_layout.setRowStretch(2, 0) substitute_layout.setRowStretch(3, 0) substitute_layout.setRowStretch(4, 0) substitute_layout.setRowStretch(5, 0) substitute_layout.setRowStretch(6, 0) substitute_layout.setRowStretch(7, 1) #map ligand maplig_tab = QWidget() maplig_layout = QGridLayout(maplig_tab) liglabel = QLabel("ligand name:") maplig_layout.addWidget(liglabel, 0, 0, Qt.AlignVCenter) self.ligname = QLineEdit() lig_completer = NameCompleter(Component.list(), self.ligname) self.ligname.setCompleter(lig_completer) self.ligname.setToolTip("name of ligand in the AaronTools library or your personal library\nseparate names with commas and uncheck 'modify selected structure' to create several structures") maplig_layout.addWidget(self.ligname, 0, 1, Qt.AlignVCenter) open_lig_lib = QPushButton("from library...") open_lig_lib.clicked.connect(self.open_lig_selector) maplig_layout.addWidget(open_lig_lib, 0, 2, Qt.AlignTop) maplig_layout.addWidget(QLabel("modify selected structure:"), 1, 0, 1, 1, Qt.AlignVCenter) self.close_previous_lig = QCheckBox() self.close_previous_lig.setToolTip("checked: selected structure will be modified\nunchecked: new model will be created for the modified structure") self.close_previous_lig.setChecked(self.settings.modify) self.close_previous_lig.stateChanged.connect(self.close_previous_change) maplig_layout.addWidget(self.close_previous_lig, 1, 1, 1, 2, Qt.AlignTop) maplig_button = QPushButton("swap ligand with selected coordinating atoms") maplig_button.clicked.connect(self.do_maplig) maplig_layout.addWidget(maplig_button, 2, 0, 1, 3, Qt.AlignTop) self.maplig_button = maplig_button start_structure_button = QPushButton("place in:") self.lig_model_selector = ModelComboBox(self.session, addNew=True) start_structure_button.clicked.connect(self.do_new_lig) maplig_layout.addWidget(start_structure_button, 3, 0, 1, 1, Qt.AlignTop) maplig_layout.addWidget(self.lig_model_selector, 3, 1, 1, 2, Qt.AlignTop) maplig_layout.setRowStretch(0, 0) maplig_layout.setRowStretch(1, 0) maplig_layout.setRowStretch(2, 0) maplig_layout.setRowStretch(3, 1) #close ring closering_tab = QWidget() closering_layout = QGridLayout(closering_tab) ringlabel = QLabel("ring name:") closering_layout.addWidget(ringlabel, 0, 0, Qt.AlignVCenter) self.ringname = QLineEdit() ring_completer = NameCompleter(Ring.list(), self.ringname) self.ringname.setCompleter(ring_completer) self.ringname.setToolTip("name of ring in the AaronTools library or your personal library\nseparate names with commas and uncheck 'modify selected structure' to create several structures") closering_layout.addWidget(self.ringname, 0, 1, Qt.AlignVCenter) open_ring_lib = QPushButton("from library...") open_ring_lib.clicked.connect(self.open_ring_selector) closering_layout.addWidget(open_ring_lib, 0, 2, Qt.AlignTop) closering_layout.addWidget(QLabel("modify selected structure:"), 1, 0, 1, 1, Qt.AlignVCenter) self.close_previous_ring = QCheckBox() self.close_previous_ring.setToolTip("checked: selected structure will be modified\nunchecked: new model will be created for the modified structure") self.close_previous_ring.setChecked(self.settings.modify) self.close_previous_ring.stateChanged.connect(self.close_previous_change) closering_layout.addWidget(self.close_previous_ring, 1, 1, 1, 2, Qt.AlignTop) closering_layout.addWidget(QLabel("try multiple:"), 2, 0, 1, 1, Qt.AlignVCenter) self.minimize_ring = QCheckBox() self.minimize_ring.setToolTip("try to use other versions of this ring in the library to find the one that fits best") self.minimize_ring.setChecked(self.settings.minimize_ring) closering_layout.addWidget(self.minimize_ring, 2, 1, 1, 2, Qt.AlignTop) closering_layout.addWidget(QLabel("new residue name:"), 3, 0, 1, 1, Qt.AlignVCenter) self.new_ring_name = QLineEdit() self.new_ring_name.setToolTip("change name of modified residues") self.new_ring_name.setPlaceholderText("leave blank to keep current") closering_layout.addWidget(self.new_ring_name, 3, 1, 1, 2, Qt.AlignTop) closering_button = QPushButton("put a ring on current selection") closering_button.clicked.connect(self.do_fusering) closering_layout.addWidget(closering_button, 4, 0, 1, 3, Qt.AlignTop) self.closering_button = closering_button start_structure_button = QPushButton("place in:") self.ring_model_selector = ModelComboBox(self.session, addNew=True) start_structure_button.clicked.connect(self.do_new_ring) closering_layout.addWidget(start_structure_button, 5, 0, 1, 1, Qt.AlignTop) closering_layout.addWidget(self.ring_model_selector, 5, 1, 1, 2, Qt.AlignTop) closering_layout.setRowStretch(0, 0) closering_layout.setRowStretch(1, 0) closering_layout.setRowStretch(2, 0) closering_layout.setRowStretch(3, 0) closering_layout.setRowStretch(4, 0) closering_layout.setRowStretch(5, 1) #change element changeelement_tab = QWidget() changeelement_layout = QFormLayout(changeelement_tab) self.element = QPushButton("C") self.element.setMinimumWidth(int(1.3*self.element.fontMetrics().boundingRect("QQ").width())) self.element.setMaximumWidth(int(1.3*self.element.fontMetrics().boundingRect("QQ").width())) self.element.setMinimumHeight(int(1.5*self.element.fontMetrics().boundingRect("QQ").height())) self.element.setMaximumHeight(int(1.5*self.element.fontMetrics().boundingRect("QQ").height())) ele_color = tuple(list(element_color(ELEMENTS.index("C")))[:-1]) self.element.setStyleSheet( "QPushButton { background: rgb(%i, %i, %i); color: %s; font-weight: bold; }" % ( *ele_color, 'white' if sum( int(x < 130) - int(x > 225) for x in ele_color ) - int(ele_color[1] > 225) + int(ele_color[2] > 200) >= 2 else 'black' ) ) self.element.clicked.connect(self.open_ptable) changeelement_layout.addRow("element:", self.element) self.vsepr = QComboBox() self.vsepr.addItems([ "do not change", # 0 "linear (1 bond)", # 1 "linear (2 bonds)", # 2 "trigonal planar (2 bonds)", # 3 "tetrahedral (2 bonds)", # 4 "trigonal planar", # 5 "tetrahedral (3 bonds)", # 6 "T-shaped", # 7 "trigonal pyramidal", # 8 "tetrahedral", # 9 "sawhorse", #10 "seesaw", #11 "square planar", #12 "trigonal bipyramidal", #13 "square pyramidal", #14 "pentagonal", #15 "octahedral", #16 "hexagonal", #17 "trigonal prismatic", #18 "pentagonal pyramidal", #19 "capped octahedral", #20 "capped trigonal prismatic", #21 "heptagonal", #22 "hexagonal pyramidal", #23 "pentagonal bipyramidal", #24 "biaugmented trigonal prismatic", #25 "cubic", #26 "elongated trigonal bipyramidal", #27 "hexagonal bipyramidal", #28 "heptagonal pyramidal", #29 "octagonal", #30 "square antiprismatic", #31 "trigonal dodecahedral", #32 "capped cube", #33 "capped square antiprismatic", #34 "enneagonal", #35 "heptagonal bipyramidal", #36 "hula-hoop", #37 "triangular cupola", #38 "tridiminished icosahedral", #39 "muffin", #40 "octagonal pyramidal", #41 "tricapped trigonal prismatic", #42 ]) self.vsepr.setCurrentIndex(9) self.vsepr.insertSeparator(33) self.vsepr.insertSeparator(25) self.vsepr.insertSeparator(20) self.vsepr.insertSeparator(16) self.vsepr.insertSeparator(13) self.vsepr.insertSeparator(8) self.vsepr.insertSeparator(5) self.vsepr.insertSeparator(2) self.vsepr.insertSeparator(1) self.vsepr.insertSeparator(0) changeelement_layout.addRow("geometry:", self.vsepr) self.change_bonds = QCheckBox() self.change_bonds.setChecked(self.settings.change_bonds) changeelement_layout.addRow("adjust bond lengths:", self.change_bonds) change_element_button = QPushButton("change selected elements") change_element_button.clicked.connect(self.do_change_element) changeelement_layout.addRow(change_element_button) self.change_element_button = change_element_button start_structure_button = QPushButton("place in:") self.model_selector = ModelComboBox(self.session, addNew=True) start_structure_button.clicked.connect(self.do_new_atom) changeelement_layout.addRow(start_structure_button, self.model_selector) delete_atoms_button = QPushButton("delete selected atoms") delete_atoms_button.clicked.connect(self.delete_atoms) changeelement_layout.addRow(delete_atoms_button) self.alchemy_tabs.addTab(substitute_tab, "substitute") self.alchemy_tabs.addTab(maplig_tab, "swap ligand") self.alchemy_tabs.addTab(closering_tab, "fuse ring") self.alchemy_tabs.addTab(changeelement_tab, "change element") layout.addWidget(self.alchemy_tabs) self.tool_window.ui_area.setLayout(layout) self.tool_window.manage(None) def close_previous_change(self, state): if state == Qt.Checked: self.settings.modify = True for checkbox in [self.close_previous_lig, self.close_previous_sub, self.close_previous_ring]: checkbox.setChecked(True) self.close_previous_bool = True else: self.settings.modify = False for checkbox in [self.close_previous_lig, self.close_previous_sub, self.close_previous_ring]: checkbox.setChecked(False) self.close_previous_bool = False def do_substitute(self): subnames = self.subname.text() new_name = self.new_sub_name.text() use_attached = not self.guess_old.isChecked() minimize = self.minimize.isChecked() new_residue = self.new_residue.isChecked() use_greek = self.use_greek.isChecked() self.settings.minimize = minimize self.settings.use_greek = use_greek if len(new_name.strip()) > 0: run( self.session, "substitute sel substituents %s newName %s guessAttachment %s modify %s minimize %s useRemoteness %s newResidue %s" % ( subnames, new_name, not use_attached, self.close_previous_bool, minimize, use_greek, new_residue, ) ) else: run( self.session, "substitute sel substituents %s guessAttachment %s modify %s minimize %s useRemoteness %s newResidue %s" % ( subnames, not use_attached, self.close_previous_bool, minimize, use_greek, new_residue, ) ) def open_sub_selector(self): self.tool_window.create_child_window("select substituents", window_class=SubstituentSelection, textBox=self.subname) def do_maplig(self): lignames = self.ligname.text() selection = selected_atoms(self.session) if len(selection) < 1: raise RuntimeWarning("nothing selected") models = {} for atom in selection: if atom.structure not in models: models[atom.structure] = [AtomSpec(atom.atomspec)] else: models[atom.structure].append(AtomSpec(atom.atomspec)) first_pass = True new_structures = [] for ligname in lignames.split(','): ligname = ligname.strip() lig = Component(ligname) for model in models: if self.close_previous_bool and first_pass: rescol = ResidueCollection(model) elif self.close_previous_bool and not first_pass: raise RuntimeError("only the first model can be replaced") else: model_copy = model.copy() rescol = ResidueCollection(model_copy) for i, atom in enumerate(model.atoms): rescol.atoms[i].atomspec = atom.atomspec rescol.atoms[i].add_tag(atom.atomspec) rescol.atoms[i].chix_atom = atom target = rescol.find(models[model]) if len(target) % len(lig.key_atoms) == 0: k = 0 ligands = [] while k != len(target): res_lig = ResidueCollection(lig.copy(), comment=lig.comment) res_lig.parse_comment() res_lig = Component(res_lig, key_atoms = ",".join([str(k + 1) for k in res_lig.other["key_atoms"]])) ligands.append(res_lig) k += len(lig.key_atoms) else: raise RuntimeError("number of key atoms no not match: %i now, new ligand has %i" % (len(target), len(lig.key_atoms))) rescol.map_ligand(ligands, target) for center_atom in rescol.center: center_atom.connected = set([]) for atom in rescol.atoms: if atom not in rescol.center: if center_atom.is_connected(atom): atom.connected.add(center_atom) center_atom.connected.add(atom) if self.close_previous_bool: rescol.update_chix(model) else: struc = rescol.get_chimera(self.session) new_structures.append(struc) first_pass = False if not self.close_previous_bool: self.session.models.add(new_structures) def open_lig_selector(self): self.tool_window.create_child_window("select ligands", window_class=LigandSelection, textBox=self.ligname) def do_fusering(self): ring_names = self.ringname.text() new_name = self.new_ring_name.text() minimize_ring = self.minimize_ring.isChecked() self.settings.minimize_ring = minimize_ring if len(new_name.strip()) > 0: run( self.session, "fuseRing sel rings %s newName %s modify %s minimize %s" % ( ring_names, new_name, self.close_previous_bool, minimize_ring, ) ) else: run( self.session, "fuseRing sel rings %s modify %s minimize %s" % ( ring_names, self.close_previous_bool, minimize_ring, ) ) def open_ring_selector(self): self.tool_window.create_child_window("select rings", window_class=RingSelection, textBox=self.ringname) def open_ptable(self): self.tool_window.create_child_window("select element", window_class=_PTable, button=self.element) def display_help(self): """Show the help for this tool in the help viewer.""" from chimerax.core.commands import run run(self.session, 'open %s' % self.help if self.help is not None else "") def do_change_element(self): element = self.element.text() adjust_bonds = self.change_bonds.isChecked() self.settings.change_bonds = adjust_bonds vsepr = self.vsepr.currentText() if vsepr == "do not change": vsepr = False elif vsepr == "linear (1 bond)": vsepr = "linear 1" goal = 1 elif vsepr == "linear (2 bonds)": vsepr = "linear 2" goal = 2 elif vsepr == "trigonal planar (2 bonds)": vsepr = "bent 2 planar" goal = 2 elif vsepr == "tetrahedral (2 bonds)": vsepr = "bent 2 tetrahedral" goal = 2 elif vsepr == "trigonal planar": goal = 3 elif vsepr == "tetrahedral (3 bonds)": vsepr = "bent 3 tetrahedral" goal = 3 else: goal = len(Atom.get_shape(vsepr)) - 1 sel = selected_atoms(self.session) models, _ = guessAttachmentTargets(sel, self.session, allow_adjacent=False) for model in models: conv_res = list(models[model].keys()) for res in models[model]: for target in models[model][res]: for neighbor in target.neighbors: if neighbor.residue not in conv_res: conv_res.append(neighbor.residue) for pbg in self.session.models.list(type=PseudobondGroup): for pbond in pbg.pseudobonds: if target in pbond.atoms and all(atom.structure is model for atom in pbond.atoms): other_atom = pbond.other_atom(target) if other_atom.residue not in conv_res: conv_res.append(other_atom.residue) rescol = ResidueCollection(model, convert_residues=conv_res) for res in models[model]: residue = [resi for resi in rescol.residues if resi.chix_residue is res][0] for target in models[model][res]: targ = rescol.find_exact(AtomSpec(target.atomspec))[0] adjust_hydrogens = vsepr if vsepr is not False: cur_bonds = len(targ.connected) change_Hs = goal - cur_bonds adjust_hydrogens = (change_Hs, vsepr) residue.change_element(targ, element, adjust_bonds=adjust_bonds, adjust_hydrogens=adjust_hydrogens, ) residue.update_chix(res) def do_new_ring(self): rings = self.ringname.text() for ring in rings.split(","): ring = ring.strip() rescol = ResidueCollection(Ring(ring)) model = self.ring_model_selector.currentData() if model is None: chix = rescol.get_chimera(self.session) self.session.models.add([chix]) apply_seqcrow_preset(chix, fallback="Ball-Stick-Endcap") self.ring_model_selector.setCurrentIndex(self.ring_model_selector.count()-1) else: res = model.new_residue("new", "a", len(model.residues)+1) rescol.residues[0].update_chix(res) run(self.session, "select add %s" % " ".join([atom.atomspec for atom in res.atoms])) def do_new_lig(self): ligands = self.ligname.text() for lig in ligands.split(","): lig = lig.strip() rescol = ResidueCollection(Component(lig)) model = self.lig_model_selector.currentData() if model is None: chix = rescol.get_chimera(self.session) self.session.models.add([chix]) apply_seqcrow_preset(chix, fallback="Ball-Stick-Endcap") self.lig_model_selector.setCurrentIndex(self.lig_model_selector.count()-1) else: res = model.new_residue("new", "a", len(model.residues)+1) rescol.residues[0].update_chix(res) run(self.session, "select add %s" % " ".join([atom.atomspec for atom in res.atoms])) def do_new_atom(self): element = self.element.text() adjust_bonds = self.change_bonds.isChecked() self.settings.change_bonds = adjust_bonds vsepr = self.vsepr.currentText() if vsepr == "do not change": vsepr = False elif vsepr == "linear (1 bond)": vsepr = "linear 1" elif vsepr == "linear (2 bonds)": vsepr = "linear 2" elif vsepr == "trigonal planar (2 bonds)": vsepr = "bent 2 planar" elif vsepr == "tetrahedral (2 bonds)": vsepr = "bent 2 tetrahedral" elif vsepr == "tetrahedral (3 bonds)": vsepr = "bent 3 tetrahedral" if vsepr: atoms = Atom.get_shape(vsepr) atoms[0].element = element for atom in atoms[1:]: atom.element = "H" if adjust_bonds: # this works b/c all atoms are 1 angstrom from the center # just multiply by the distance we want expected_dist = RADII[element] + RADII["H"] for atom in atoms[1:]: atom.coords *= expected_dist for atom in atoms[1:]: atoms[0].connected.add(atom) atom.connected.add(atoms[0]) else: atoms = [Atom(element=element, coords=np.zeros(3))] rescol = ResidueCollection(atoms, name="new", refresh_connected=False) model = self.model_selector.currentData() if model is None: chix = rescol.get_chimera(self.session) self.session.models.add([chix]) apply_seqcrow_preset(chix, fallback="Ball-Stick-Endcap") self.model_selector.setCurrentIndex(self.model_selector.count()-1) else: res = model.new_residue("new", "a", len(model.residues)+1) rescol.residues[0].update_chix(res) run(self.session, "select add %s" % " ".join([atom.atomspec for atom in res.atoms])) def delete_atoms(self, *args): atoms = selected_atoms(self.session) for atom in atoms: atom.delete() def delete(self): self.ring_model_selector.deleteLater() self.lig_model_selector.deleteLater() self.model_selector.deleteLater() return super().delete() def close(self): self.ring_model_selector.deleteLater() self.lig_model_selector.deleteLater() self.model_selector.deleteLater() return super().close()
class Window(QWidget): def __init__(self, statusBar, menubar): super().__init__() self.statusbar = statusBar self.menubar = menubar self.url_without_schema = "" self.url = "" self.login_form = None self.threadpool = QThreadPool() self.init_ui() def init_ui(self): self.hbox = QHBoxLayout(self) self.set_frames() self.set_input_and_buttons() self.set_combobox() self.start_resource_monitor() self.set_menu() self.show() def start_on_click(self): if self.is_url_valid: self.clear_result_list() self.clear_infobox() self.disable_enable_options(True) self.start_action() pass else: self.print_error("[×] URL format is not correct") def stop_on_click(self): self.disable_enable_options(False) def print_error(self, message): self.information_list.addItem(message) def print_info(self, message): self.information_list.addItem(message) def print_result(self, message): self.result_list.addItem(message) def clear_infobox(self): self.information_list.clear() def clear_result_list(self): self.result_list.clear() def finish_control(self): self.disable_enable_options(False) def start_action(self): option_value = self.options_combobox.currentText() option_list = { 'Information Gather': self.start_information_gathering, 'Crawler': self.start_crawler, 'Port Scanner': self.start_port_scanner, 'Directory Scanner': self.start_directory_scanner, 'Subdomain Scanner': self.start_subdomain_scanner, 'Header Analysis': self.start_header_scanner, 'Xss Scanner': self.start_xss_scanner, 'SQLi Scanner': self.start_sqli_scanner, 'LFi/RFi Scanner': self.start_lfi_scanner, 'File Upload Scanner': self.start_fileupload_scanner, } option_list[option_value]() def start_information_gathering(self): self.print_info("[✔] Information Gathering started!") self.information_scanner = InfoCollector(self.url) self.information_scanner.signals.result_list.connect(self.print_result) self.information_scanner.signals.finish_control.connect( self.finish_control) self.information_scanner.signals.info_box.connect(self.print_info) self.threadpool.start(self.information_scanner) def start_crawler(self): self.print_info("[✔] Crawler started!") self.crawler = Crawler(self.url, self.login_form) self.crawler.signals.result_list.connect(self.print_result) self.crawler.signals.finish_control.connect(self.finish_control) self.crawler.signals.info_box.connect(self.print_info) self.threadpool.start(self.crawler) def start_port_scanner(self): self.print_info("[✔] Port Scanner started!") self.port_scanner = PortScanner(self.url_without_schema) self.port_scanner.signals.finish_control.connect(self.finish_control) self.port_scanner.signals.info_box.connect(self.print_info) self.port_scanner.signals.result_list.connect(self.print_result) self.threadpool.start(self.port_scanner) def start_directory_scanner(self): self.print_info("[✔] Directory Scanner started!") self.dir_scanner = DirScanner(self.url) self.dir_scanner.signals.finish_control.connect(self.finish_control) self.dir_scanner.signals.info_box.connect(self.print_info) self.dir_scanner.signals.result_list.connect(self.print_result) self.threadpool.start(self.dir_scanner) def start_subdomain_scanner(self): self.print_info("[✔] Subdomain Scanner started!") self.subdomain_scanner = SubdomainScanner(self.url_without_schema) self.subdomain_scanner.signals.finish_control.connect( self.finish_control) self.subdomain_scanner.signals.info_box.connect(self.print_info) self.subdomain_scanner.signals.result_list.connect(self.print_result) self.threadpool.start(self.subdomain_scanner) def start_header_scanner(self): self.print_info("[✔] Header Scanner started!") self.header_analysis = HeaderAnalyzer(self.url) self.header_analysis.signals.result_list.connect(self.print_result) self.header_analysis.signals.finish_control.connect( self.finish_control) self.header_analysis.signals.info_box.connect(self.print_info) self.threadpool.start(self.header_analysis) def start_xss_scanner(self): self.print_info("[✔] XSS Scanner started!") self.xss_scanner = XssScanner(self.url, self.login_form) self.xss_scanner.signals.info_box.connect(self.print_info) self.xss_scanner.signals.result_list.connect(self.print_result) self.xss_scanner.signals.finish_control.connect(self.finish_control) self.threadpool.start(self.xss_scanner) def start_sqli_scanner(self): self.print_info("[✔] SQLi Scanner started!") self.sqli_scanner = SqliScanner(self.url, self.login_form) self.sqli_scanner.signals.result_list.connect(self.print_result) self.sqli_scanner.signals.info_box.connect(self.print_info) self.sqli_scanner.signals.finish_control.connect(self.finish_control) self.threadpool.start(self.sqli_scanner) def start_lfi_scanner(self): self.print_info("[✔] File Inclusion Scanner started!") self.file_inclusion_Scanner = FileInclusionScanner( self.url, self.login_form) self.file_inclusion_Scanner.signals.result_list.connect( self.print_result) self.file_inclusion_Scanner.signals.info_box.connect(self.print_info) self.file_inclusion_Scanner.signals.finish_control.connect( self.finish_control) self.threadpool.start(self.file_inclusion_Scanner) def start_fileupload_scanner(self): self.print_info("[✔] File Upload Scanner started!") def start_resource_monitor(self): pid = os.getpid() self.resource_monitor = ResourceMonitor(pid) self.resource_monitor.signals.status.connect(self.set_statusbar) self.threadpool.start(self.resource_monitor) def set_statusbar(self, cpu_value, mem_value): text = "CPU Usage: %{} - Memory Usage: %{}".format( cpu_value, mem_value) self.statusbar.showMessage(text) def set_menu(self): settingsmenu = self.menubar.addMenu('Settings') settingsAct = QAction('Settings', self) settingsAct.setShortcut("Ctrl+S") settingsAct.setStatusTip('Set Scanner Settings') settingsAct.triggered.connect(self.show_settings_window) settingsmenu.addAction(settingsAct) exitmenu = self.menubar.addMenu('Exit') exitAct = QAction('Exit', self) exitmenu.addAction(exitAct) def set_login_settings(self): user_input_name = self.form_input_name_user.text() user_input_value = self.form_input_value_user.text() password_input_name = self.form_input_name_password.text() password_input_value = self.form_input_value_password.text() form_address = self.form_url_address_line.text() form_action = self.form_action_url_line.text() self.login_form = {} self.login_form['user_name_field'] = user_input_name self.login_form['user_value_field'] = user_input_value self.login_form['password_name_field'] = password_input_name self.login_form['password_value_field'] = password_input_value self.login_form['url'] = form_address self.login_form['action'] = form_action def show_settings_window(self): self.dlg = QDialog(self) self.dlg.setFixedSize(400, 250) self.dlg.setWindowTitle("Settings") # Initialize tab screen self.tabs = QTabWidget(self.dlg) self.general_settings_tab = QWidget() self.login_tab = QWidget() self.tabs.resize(400, 270) # Add tabs self.tabs.addTab(self.general_settings_tab, "General Settings") self.tabs.addTab(self.login_tab, "Login Settings") # Create first tab self.general_settings_tab.layout = QVBoxLayout(self.dlg) self.pushButton1 = QPushButton("PyQt5 button", self.general_settings_tab) self.label_login_information = QLabel(self.login_tab) self.label_login_information.setText('Login Form Informations') self.label_login_information.move(10, 10) self.label_input_name_user = QLabel(self.login_tab) self.label_input_name_user.setText('Input Name: ') self.label_input_name_user.move(20, 50) self.label_input_name_password = QLabel(self.login_tab) self.label_input_name_password.setText('Input Name: ') self.label_input_name_password.move(20, 80) self.label_input_value_user = QLabel(self.login_tab) self.label_input_value_user.setText('Input Value: ') self.label_input_value_user.move(210, 50) self.label_input_value_password = QLabel(self.login_tab) self.label_input_value_password.setText('Input Value: ') self.label_input_value_password.move(210, 80) self.form_input_name_user = QLineEdit(self.login_tab) self.form_input_name_user.resize(100, 18) self.form_input_name_user.move(100, 50) self.form_input_name_password = QLineEdit(self.login_tab) self.form_input_name_password.resize(100, 18) self.form_input_name_password.move(100, 80) self.form_input_value_user = QLineEdit(self.login_tab) self.form_input_value_user.resize(100, 18) self.form_input_value_user.move(285, 50) self.form_input_value_password = QLineEdit(self.login_tab) self.form_input_value_password.resize(100, 18) self.form_input_value_password.move(285, 80) self.form_url_address_label = QLabel(self.login_tab) self.form_url_address_label.setText("Form URL address : ") self.form_url_address_label.move(20, 120) self.form_url_address_line = QLineEdit(self.login_tab) self.form_url_address_line.resize(200, 18) self.form_url_address_line.move(138, 120) self.form_action_url_label = QLabel(self.login_tab) self.form_action_url_label.setText("Form Action URL : ") self.form_action_url_label.move(20, 150) self.form_action_url_line = QLineEdit(self.login_tab) self.form_action_url_line.resize(200, 18) self.form_action_url_line.move(138, 150) self.save_button = QPushButton('Save', self.login_tab) self.save_button.move(280, 180) self.save_button.clicked.connect(self.set_login_settings) self.dlg.exec_() @property def is_url_valid(self): # Get user input url = self.address_text.text() # Validation check result = validators.url(url) # Get url without schema if result: self.url = url parser = urlparse(url) self.url_without_schema = parser.netloc return result def disable_enable_options(self, is_disabled): self.address_text.setDisabled(is_disabled) self.start_button.setDisabled(is_disabled) self.options_combobox.setDisabled(is_disabled) self.stop_button.setDisabled(not is_disabled) def set_input_and_buttons(self): self.address_text = QLineEdit(self.top_frame) self.address_text.setPlaceholderText("https://example.com") self.address_text.move(20, 20) self.address_text.resize(300, 40) self.start_button = QPushButton('Start Scan', self.top_frame) self.start_button.clicked.connect(self.start_on_click) self.start_button.move(177, 70) self.start_button.resize(70, 23) self.stop_button = QPushButton('Stop Scan', self.top_frame) self.stop_button.clicked.connect(self.stop_on_click) self.stop_button.move(250, 70) self.stop_button.resize(70, 23) self.stop_button.setDisabled(True) self.information_label = QLabel("Information Box ", self.top_frame) self.information_label.setGeometry(400, 3, 100, 10) self.information_list = QListWidget(self.info_frame) self.information_list.setMinimumSize(20, 20) self.result_list = QListWidget(self.bottom_frame) self.result_list.setMinimumSize(580, 375) def set_frames(self): self.top_frame = QFrame(self) self.top_frame.resize(50, 150) self.info_frame = QFrame(self.top_frame) self.info_frame.setFrameShape(QFrame.StyledPanel) self.info_frame.setGeometry(340, 18, 220, 80) self.bottom_frame = QFrame(self) self.bottom_frame.resize(500, 550) self.top_frame.setFrameShape(QFrame.StyledPanel) self.bottom_frame.setFrameShape(QFrame.StyledPanel) self.splitter1 = QSplitter(Qt.Vertical, frameShape=QFrame.StyledPanel) self.splitter1.addWidget(self.top_frame) self.splitter1.addWidget(self.bottom_frame) self.hbox.addWidget(self.splitter1) def set_combobox(self): self.options_combobox = QComboBox(self.top_frame) option_list = [ 'Information Gather', 'Crawler', 'Port Scanner', 'Directory Scanner', 'Subdomain Scanner', 'Header Analysis', 'Xss Scanner', 'SQLi Scanner', 'LFi/RFi Scanner', 'File Upload Scanner', ] self.options_combobox.addItems(option_list) self.options_combobox.move(20, 70)
class SubwindowMisc(QWidget): """Show subwindow with miscellaneous settings.""" current_tab = -1 def createWindow(self, mainWindow, tab=''): """Create subwindow with miscellaneous settings.""" try: parent = None super().__init__(parent) # self.setWindowFlags(Qt.WindowStaysOnTopHint) self.setWindowIcon( QIcon(scctool.settings.getResFile('settings.png'))) self.setWindowModality(Qt.ApplicationModal) self.mainWindow = mainWindow self.passEvent = False self.controller = mainWindow.controller self.__dataChanged = False self.createButtonGroup() self.createTabs(tab) mainLayout = QVBoxLayout() mainLayout.addWidget(self.tabs) mainLayout.addLayout(self.buttonGroup) self.setLayout(mainLayout) self.resize( QSize(mainWindow.size().width() * 0.9, self.sizeHint().height())) relativeChange = QPoint(mainWindow.size().width() / 2, mainWindow.size().height() / 3)\ - QPoint(self.size().width() / 2, self.size().height() / 3) self.move(mainWindow.pos() + relativeChange) self.setWindowTitle(_("Miscellaneous Settings")) except Exception: module_logger.exception("message") def createTabs(self, tab=''): """Create tabs.""" self.tabs = QTabWidget() self.createMapsBox() self.createFavBox() self.createAliasBox() self.createOcrBox() self.createAlphaBox() self.createSC2ClientAPIBox() self.createAligulacTab() self.createCounterTab() # Add tabs self.tabs.addTab(self.mapsBox, _("Map Manager")) self.tabs.addTab(self.favBox, _("Favorites")) self.tabs.addTab(self.aliasBox, _("Alias")) self.tabs.addTab(self.ocrBox, _("OCR")) self.tabs.addTab(self.alphaBox, _("AlphaTL && Ingame Score")) self.tabs.addTab(self.clientapiBox, _("SC2 Client API")) self.tabs.addTab(self.aligulacTab, _("Aligulac")) self.tabs.addTab(self.counterTab, _("Countdown")) table = dict() table['mapmanager'] = 0 table['favorites'] = 1 table['alias'] = 2 table['ocr'] = 3 table['alphatl'] = 4 table['sc2clientapi'] = 5 table['aligulac'] = 6 table['counter'] = 7 self.tabs.setCurrentIndex(table.get(tab, SubwindowMisc.current_tab)) self.tabs.currentChanged.connect(self.tabChanged) @classmethod def tabChanged(cls, idx): """Save the current tab index.""" SubwindowMisc.current_tab = idx def changed(self): """Handle changes.""" self.__dataChanged = True def createAlphaBox(self): """Create Alpha QWidget.""" self.alphaBox = QWidget() mainLayout = QVBoxLayout() box = QGroupBox(_("AlphaTL")) layout = QHBoxLayout() self.cb_trans_banner = QCheckBox( " " + _("Download transparent Banner of the Match")) self.cb_trans_banner.setChecked( scctool.settings.config.parser.getboolean( "SCT", "transparent_match_banner")) self.cb_trans_banner.stateChanged.connect(self.changed) layout.addWidget(self.cb_trans_banner) box.setLayout(layout) mainLayout.addWidget(box) box = QGroupBox(_("Set Ingame Score Task")) layout = QVBoxLayout() self.cb_ctrlx = QCheckBox(" " + _('Automatically press Ctrl+X to apply the' ' correct player order ingame')) self.cb_ctrlx.setToolTip( _("This will ensure that the player of the first team is always" " on the left/top in the ingame Observer UI.")) self.cb_ctrlx.setChecked( scctool.settings.config.parser.getboolean("SCT", "CtrlX")) self.cb_ctrlx.stateChanged.connect(self.changed) layout.addWidget(self.cb_ctrlx) self.cb_ctrln = QCheckBox(" " + _('Automatically press Ctrl+N before' ' OCR to display player names')) self.cb_ctrln.setToolTip( _("This is recommended for Standard and Gawliq Observer UI.")) self.cb_ctrln.setChecked( scctool.settings.config.parser.getboolean("SCT", "CtrlN")) self.cb_ctrln.stateChanged.connect(self.changed) layout.addWidget(self.cb_ctrln) self.cb_ctrlshifts = QCheckBox( " " + _('Automatically press Ctrl+Shift+S to display' ' the ingame score')) self.cb_ctrlshifts.setToolTip( _("Ctrl+Shift+S is needed for the WCS-Gameheart Oberserver" " Overlay, but disables the sound for other overlays.")) self.cb_ctrlshifts.setChecked( scctool.settings.config.parser.getboolean("SCT", "CtrlShiftS")) self.cb_ctrlshifts.stateChanged.connect(self.changed) layout.addWidget(self.cb_ctrlshifts) self.cb_ctrlshiftc = QCheckBox( " " + _('Automatically press Ctrl+Shift+C to toogle the clan tag')) self.cb_ctrlshiftc.setChecked( scctool.settings.config.parser.getboolean("SCT", "CtrlShiftC")) self.cb_ctrlshiftc.stateChanged.connect(self.changed) layout.addWidget(self.cb_ctrlshiftc) container = QHBoxLayout() self.cb_ctrlshiftr = QComboBox() self.cb_ctrlshiftr.addItem("0") self.cb_ctrlshiftr.addItem("1") self.cb_ctrlshiftr.addItem("2") try: self.cb_ctrlshiftr.setCurrentIndex( scctool.settings.config.parser.getint("SCT", "CtrlShiftR")) except Exception: self.cb_ctrlshiftr.setCurrentIndex(0) self.cb_ctrlshiftr.setMaximumWidth(40) self.cb_ctrlshiftr.currentIndexChanged.connect(self.changed) container.addWidget( QLabel( _('Automatically press Ctrl+Shift+R to toogle the race icon ')) ) container.addWidget(self.cb_ctrlshiftr) container.addWidget(QLabel(_(' time(s)'))) layout.addLayout(container) self.cb_blacklist = QCheckBox(" " + _('Activate Blacklist for' ' Ingame Score')) self.cb_blacklist.setChecked( scctool.settings.config.parser.getboolean("SCT", "blacklist_on")) self.cb_blacklist.stateChanged.connect(self.changed) layout.addWidget(self.cb_blacklist) box.setLayout(layout) mainLayout.addWidget(box) box = QGroupBox(_("Blacklist for Ingame Score")) layout = QVBoxLayout() blacklistDesc = _("Enter your SC2 client usernames to deactivate" " automatically setting the ingame score and" " toogling the production tab when you are playing" " yourself. Replays are exempt.") label = QLabel(blacklistDesc) label.setAlignment(Qt.AlignJustify) label.setWordWrap(True) layout.addWidget(label) self.list_blacklist = ListTable(4, scctool.settings.config.getBlacklist()) self.list_blacklist.dataModified.connect(self.changed) self.list_blacklist.setFixedHeight(50) layout.addWidget(self.list_blacklist) box.setLayout(layout) mainLayout.addWidget(box) mainLayout.addItem( QSpacerItem(0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)) self.alphaBox.setLayout(mainLayout) def createFavBox(self): """Create favorites box.""" self.favBox = QWidget() mainLayout = QVBoxLayout() box = QGroupBox(_("Players")) layout = QHBoxLayout() self.list_favPlayers = ListTable( 4, scctool.settings.config.getMyPlayers()) self.list_favPlayers.dataModified.connect(self.changed) self.list_favPlayers.setFixedHeight(150) layout.addWidget(self.list_favPlayers) box.setLayout(layout) mainLayout.addWidget(box) box = QGroupBox(_("Teams")) layout = QVBoxLayout() self.list_favTeams = ListTable(3, scctool.settings.config.getMyTeams()) self.list_favTeams.dataModified.connect(self.changed) self.list_favTeams.setFixedHeight(100) layout.addWidget(self.list_favTeams) self.cb_swapTeams = QCheckBox( _('Swap my favorite team always to the left')) self.cb_swapTeams.setChecked( scctool.settings.config.parser.getboolean("SCT", "swap_myteam")) self.cb_swapTeams.stateChanged.connect(self.changed) layout.addWidget(self.cb_swapTeams) box.setLayout(layout) mainLayout.addWidget(box) mainLayout.addItem( QSpacerItem(0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)) self.favBox.setLayout(mainLayout) def createAliasBox(self): """Create favorites box.""" self.aliasBox = QWidget() mainLayout = QGridLayout() aliasDesc = _( 'Player and team aliases are replaced by the actual name when' + ' encountered by the match grabber. Additionally, SC2 player' + ' names listed as aliases are replaced in the intros' + ' and used to identify players by the automatic' + ' background tasks "Auto Score Update" and "Set Ingame Score".') label = QLabel(aliasDesc) label.setAlignment(Qt.AlignJustify) label.setWordWrap(True) mainLayout.addWidget(label, 1, 0, 1, 2) box = QGroupBox(_("Player Aliases")) layout = QVBoxLayout() self.list_aliasPlayers = AliasTreeView(self) self.list_aliasPlayers.aliasRemoved.connect( self.controller.aliasManager.removePlayerAlias) layout.addWidget(self.list_aliasPlayers) addButton = QPushButton(_("Add Alias")) addButton.clicked.connect( lambda: self.addAlias(self.list_aliasPlayers, _('Player Name'))) layout.addWidget(addButton) box.setLayout(layout) mainLayout.addWidget(box, 0, 0) box = QGroupBox(_("Team Aliases")) layout = QVBoxLayout() self.list_aliasTeams = AliasTreeView(self) self.list_aliasTeams.aliasRemoved.connect( self.controller.aliasManager.removeTeamAlias) layout.addWidget(self.list_aliasTeams) addButton = QPushButton(_("Add Alias")) addButton.clicked.connect( lambda: self.addAlias(self.list_aliasTeams, _('Team Name'))) layout.addWidget(addButton) box.setLayout(layout) mainLayout.addWidget(box, 0, 1) alias_list = self.controller.aliasManager.playerAliasList() for player, aliases in alias_list.items(): self.list_aliasPlayers.insertAliasList(player, aliases) alias_list = self.controller.aliasManager.teamAliasList() for team, aliases in alias_list.items(): self.list_aliasTeams.insertAliasList(team, aliases) self.aliasBox.setLayout(mainLayout) def addAlias(self, widget, scope, name=""): """Add an alias.""" name, ok = QInputDialog.getText(self, scope, scope + ':', text=name) if not ok: return name = name.strip() alias, ok = QInputDialog.getText(self, _('Alias'), _('Alias of {}').format(name) + ':', text="") alias = alias.strip() if not ok: return try: if widget == self.list_aliasPlayers: self.controller.aliasManager.addPlayerAlias(name, alias) elif widget == self.list_aliasTeams: self.controller.aliasManager.addTeamAlias(name, alias) widget.insertAlias(name, alias, True) except Exception as e: module_logger.exception("message") QMessageBox.critical(self, _("Error"), str(e)) def createSC2ClientAPIBox(self): """Create form for SC2 Client API config.""" self.clientapiBox = QWidget() mainLayout = QVBoxLayout() box = QGroupBox(_("SC2 Client API Address")) layout = QGridLayout() self.cb_usesc2listener = QCheckBox( " " + _("Listen to SC2 Client API running" " on a different PC in the network.")) self.cb_usesc2listener.setChecked( scctool.settings.config.parser.getboolean( "SCT", "sc2_network_listener_enabled")) self.cb_usesc2listener.stateChanged.connect(self.changed) self.listener_address = MonitoredLineEdit() self.listener_address.setAlignment(Qt.AlignCenter) self.listener_address.setText( scctool.settings.config.parser.get("SCT", "sc2_network_listener_address")) self.listener_address.textModified.connect(self.changed) # self.tesseract.setAlignment(Qt.AlignCenter) self.listener_address.setPlaceholderText("[Your SC2 PC IP]:6119") self.listener_address.setToolTip( _('IP address and port of machine running SC2.')) ip_port = ( r"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.)" + r"{3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]):[0-9]+$") self.listener_address.setValidator(QRegExpValidator(QRegExp(ip_port))) self.test_listener = QPushButton(" " + _("Test SC2 Client API Connection") + " ") self.test_listener.clicked.connect(self.testClientAPI) text = _("Activate this option if you are using a two computer " "setup with StarCraft Casting Tool running on a different" " PC than your SC2 client. Open the Battle.net launcher " "on the latter PC, click 'Options', 'Game Settings', and " "under SC2, check 'Additional Command Line Arguments', and " "enter '-clientapi 6119'. Finally set as network" " address below: '[Your SC2 PC IP]:6119'.") label = QLabel(text) label.setAlignment(Qt.AlignJustify) label.setOpenExternalLinks(True) label.setWordWrap(True) label.setMargin(5) layout.addWidget(label, 1, 0, 1, 3) layout.addWidget(self.cb_usesc2listener, 0, 0, 1, 3) layout.addWidget(QLabel(_("Network Address") + ": "), 3, 0) layout.addWidget(self.listener_address, 3, 1) layout.addWidget(self.test_listener, 3, 2) box.setLayout(layout) mainLayout.addWidget(box) mainLayout.addItem( QSpacerItem(0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)) self.clientapiBox.setLayout(mainLayout) def testClientAPI(self): """Test for connection to sc2 client api.""" QApplication.setOverrideCursor(Qt.WaitCursor) address = self.listener_address.text().strip() url = "http://{}/ui".format(address) try: r = requests.get(url, timeout=10) r.raise_for_status() successfull = True except Exception: successfull = False module_logger.error("message") finally: QApplication.restoreOverrideCursor() title = _("Connection Test") if successfull: QMessageBox.information( self, title, _('Connection to SC2 client API established!')) else: QMessageBox.warning( self, title, _('Unable to connect to SC2 client API.' ' Please make sure that SC2 is currently' ' running on that machine.')) def createOcrBox(self): """Create forms for OCR.""" self.ocrBox = QWidget() mainLayout = QVBoxLayout() box = QGroupBox( _("Optical Character Recognition for" " Automatic Setting of Ingame Score")) layout = QGridLayout() self.cb_useocr = QCheckBox(" " + _("Activate Optical Character Recognition")) self.cb_useocr.setChecked( scctool.settings.config.parser.getboolean("SCT", "use_ocr")) self.cb_useocr.stateChanged.connect(self.changed) self.tesseract = MonitoredLineEdit() self.tesseract.setText( scctool.settings.config.parser.get("SCT", "tesseract")) self.tesseract.textModified.connect(self.changed) # self.tesseract.setAlignment(Qt.AlignCenter) self.tesseract.setPlaceholderText( "C:\\Program Files (x86)\\Tesseract-OCR\\tesseract") self.tesseract.setReadOnly(True) self.tesseract.setToolTip(_('Tesseract-OCR Executable')) self.browse = QPushButton(_("Browse...")) self.browse.clicked.connect(self.selectTesseract) text = _( "Sometimes the order of players given by the SC2-Client-API" " differs from the order in the Observer-UI resulting in a" " swapped match score. To correct this via Optical Character" " Recognition you have to download {} and install and select the" " exectuable below, if it is not detected automatically.") url = 'https://github.com/UB-Mannheim/tesseract' + \ '/wiki#tesseract-at-ub-mannheim' href = "<a href='{}'>" + "Tesseract-OCR" + "</a>" href = href.format(url) label = QLabel(text.format(href)) label.setAlignment(Qt.AlignJustify) label.setOpenExternalLinks(True) label.setWordWrap(True) label.setMargin(5) layout.addWidget(label, 1, 0, 1, 2) layout.addWidget(self.cb_useocr, 0, 0, 1, 2) layout.addWidget(QLabel(_("Tesseract-OCR Executable") + ":"), 2, 0) layout.addWidget(self.tesseract, 3, 0) layout.addWidget(self.browse, 3, 1) box.setLayout(layout) mainLayout.addWidget(box) mainLayout.addItem( QSpacerItem(0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)) self.ocrBox.setLayout(mainLayout) if (not scctool.settings.windows): self.cb_useocr.setEnabled(False) self.cb_useocr.setAttribute(Qt.WA_AlwaysShowToolTips) self.cb_useocr.setToolTip( _("This feature is only available in Windows.")) self.tesseract.setEnabled(False) self.tesseract.setAttribute(Qt.WA_AlwaysShowToolTips) self.tesseract.setToolTip( _("This feature is only available in Windows.")) self.browse.setEnabled(False) self.browse.setAttribute(Qt.WA_AlwaysShowToolTips) self.browse.setToolTip( _("This feature is only available in Windows.")) def selectTesseract(self): """Create forms for tesseract.""" old_exe = self.tesseract.text() default = scctool.settings.config.findTesserAct(old_exe) exe, ok = QFileDialog.getOpenFileName( self, _("Select Tesseract-OCR Executable"), default, _("Tesseract-OCR Executable") + " (tesseract.exe);; " + _("Executable") + " (*.exe);; " + _("All files") + " (*)") if (ok and exe != old_exe): self.tesseract.setText(exe) self.changed() def createAligulacTab(self): """Create the aligulac tab.""" self.aligulacTab = QWidget() layout = QGridLayout() self.aligulacTreeview = AligulacTreeView( self, self.controller.aligulacManager) layout.addWidget(self.aligulacTreeview, 0, 0, 3, 1) self.pb_addAligulacID = QPushButton(_("Add Aligluac ID")) self.pb_addAligulacID.clicked.connect( lambda x, self=self: self.addAligulacID()) layout.addWidget(self.pb_addAligulacID, 1, 1) self.pb_removeAligulacID = QPushButton(_("Remove Aligulac ID")) self.pb_removeAligulacID.clicked.connect(self.removeAligulacID) layout.addWidget(self.pb_removeAligulacID, 2, 1) layout.addItem( QSpacerItem(0, 0, QSizePolicy.Minimum, QSizePolicy.Minimum), 0, 1) self.aligulacTab.setLayout(layout) def addAligulacID(self, name='', aligulac_id=1): """Add an aligulac ID.""" text, ok = QInputDialog.getText(self, _('Player Name'), _('Player Name') + ':', text=name) text = text.strip() if not ok or not text: return aligulac_id, ok = QInputDialog.getInt(self, _('Aligulac ID'), _('Aligulac ID') + ':', value=aligulac_id, min=1) if not ok: return self.aligulacTreeview.insertItem(text, aligulac_id) def removeAligulacID(self): """Remove an selected aligulac ID.""" self.aligulacTreeview.removeSelected() def createCounterTab(self): """Create the aligulac tab.""" self.counterTab = QWidget() layout = QFormLayout() self.le_countdown_replacement = QLineEdit() self.le_countdown_replacement.setText( scctool.settings.config.parser.get("Countdown", "replacement")) self.le_countdown_replacement.textChanged.connect(self.changed) layout.addRow(QLabel(_('Replacement Text')), self.le_countdown_replacement) self.cb_counter_matchgrabber_update = QCheckBox('') self.cb_counter_matchgrabber_update.setChecked( scctool.settings.config.parser.getboolean("Countdown", "matchgrabber_update")) self.cb_counter_matchgrabber_update.stateChanged.connect(self.changed) layout.addRow(QLabel(_('Update Static Countdown via MatchGrabber')), self.cb_counter_matchgrabber_update) self.counter_pretext = QPlainTextEdit() self.counter_pretext.setPlainText( scctool.settings.config.parser.get("Countdown", "pre_txt")) self.counter_pretext.textChanged.connect(self.changed) self.counter_posttext = QPlainTextEdit() self.counter_posttext.setPlainText( scctool.settings.config.parser.get("Countdown", "post_txt")) self.counter_posttext.textChanged.connect(self.changed) layout.addRow(QLabel('Pre-Text (in countdown.txt)'), self.counter_pretext) layout.addRow(QLabel('Post-Text (in countdown.txt)'), self.counter_posttext) self.counterTab.setLayout(layout) def createMapsBox(self): """Create box for map manager.""" self.mapsize = 300 self.mapsBox = QWidget() layout = QGridLayout() self.maplist = QListWidget() self.maplist.setSortingEnabled(True) for sc2map in scctool.settings.maps: self.maplist.addItem(QListWidgetItem(sc2map)) self.maplist.setCurrentItem(self.maplist.item(0)) self.maplist.currentItemChanged.connect(self.changePreview) # self.maplist.setFixedHeight(self.mapsize) self.maplist.setMinimumWidth(150) layout.addWidget(self.maplist, 0, 1, 2, 1) self.mapPreview = QLabel() self.mapPreview.setFixedWidth(self.mapsize) self.mapPreview.setFixedHeight(self.mapsize) self.mapPreview.setAlignment(Qt.AlignCenter) layout.addWidget(self.mapPreview, 0, 0) self.mapInfo = QLabel() self.mapInfo.setIndent(10) layout.addWidget(self.mapInfo, 1, 0) self.pb_addMapLiquipedia = QPushButton(_("Add from Liquipedia")) self.pb_addMapLiquipedia.clicked.connect(self.addFromLquipedia) self.pb_addMap = QPushButton(_("Add from File")) self.pb_addMap.clicked.connect(self.addMap) self.pb_renameMap = QPushButton(_("Rename")) self.pb_renameMap.clicked.connect(self.renameMap) self.pb_changeMap = QPushButton(_("Change Image")) self.pb_changeMap.clicked.connect(self.changeMap) self.pb_removeMap = QPushButton(_("Remove")) self.pb_removeMap.clicked.connect(self.deleteMap) self.sc_removeMap = QShortcut(QKeySequence("Del"), self.maplist) self.sc_removeMap.setAutoRepeat(False) self.sc_removeMap.setContext(Qt.WidgetWithChildrenShortcut) self.sc_removeMap.activated.connect(self.deleteMap) box = QWidget() container = QHBoxLayout() container.addWidget(self.pb_addMapLiquipedia, 0) container.addWidget(self.pb_addMap, 0) container.addWidget(QLabel(), 4) container.addWidget(self.pb_renameMap, 0) container.addWidget(self.pb_changeMap, 0) container.addWidget(self.pb_removeMap, 0) box.setLayout(container) layout.addWidget(box, 2, 0, 1, 2) layout.addItem( QSpacerItem(0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding), 3, 0, 1, 2) self.changePreview() self.mapsBox.setLayout(layout) def renameMap(self): """Rename maps.""" item = self.maplist.currentItem() mapname = item.text() text, ok = QInputDialog.getText(self, _('Map Name'), _('Map Name') + ':', text=mapname) if not ok: return text = text.strip() if (text == mapname): return if text.lower() == 'tbd': QMessageBox.critical( self, _("Error"), _('"{}" is not a valid map name.').format(text)) return if (text in scctool.settings.maps): buttonReply = QMessageBox.warning( self, _("Duplicate Entry"), _("Map is already in list! Overwrite?"), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if buttonReply == QMessageBox.No: return self.controller.addMap(self.controller.getMapImg(mapname, True), text) self.controller.deleteMap(mapname) item.setText(text) def changeMap(self): """Change a map.""" current_map = self.maplist.currentItem().text() fileName, ok = QFileDialog.getOpenFileName( self, _("Select Map Image (> 500x500px recommended)"), "", _("Supported Images") + " (*.png *.jpg *.jpeg)") if ok: base = os.path.basename(fileName) name, __ = os.path.splitext(base) name = name.replace("_", " ") self.controller.deleteMap(current_map) self.controller.addMap(fileName, current_map) self.changePreview() def addMap(self): """Add a map.""" fileName, ok = QFileDialog.getOpenFileName( self, _("Select Map Image (> 500x500px recommended)"), "", _("Supported Images") + " (*.png *.jpg *.jpeg)") if ok: base = os.path.basename(fileName) name, __ = os.path.splitext(base) name = name.replace("_", " ") map_name, ok = QInputDialog.getText(self, _('Map Name'), _('Map Name') + ':', text=name) map_name = map_name.strip() if ok: if map_name.lower() == 'tbd': QMessageBox.critical( self, _("Error"), _('"{}" is not a valid map name.').format(map_name)) return if (map_name in scctool.settings.maps): buttonReply = QMessageBox.warning( self, _("Duplicate Entry"), _("Map is already in list! Overwrite?"), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if buttonReply == QMessageBox.No: return else: self.controller.deleteMap(map_name) self.controller.addMap(fileName, map_name) items = self.maplist.findItems(map_name, Qt.MatchExactly) if len(items) == 0: item = QListWidgetItem(map_name) self.maplist.addItem(item) self.maplist.setCurrentItem(item) else: self.maplist.setCurrentItem(items[0]) self.changePreview() def addFromLquipedia(self): """Add a map from Liquipedia.""" grabber = LiquipediaGrabber() search_str = '' while True: search_str, ok = QInputDialog.getText(self, _('Map Name'), _('Map Name') + ':', text=search_str) search_str.strip() try: if ok and search_str: if search_str.lower() == 'tbd': QMessageBox.critical( self, _("Error"), _('"{}" is not a valid map name.').format( search_str)) continue try: QApplication.setOverrideCursor(Qt.WaitCursor) sc2map = grabber.get_map(search_str) except MapNotFound: QMessageBox.critical( self, _("Map not found"), _('"{}" was not found on Liquipedia.').format( search_str)) continue finally: QApplication.restoreOverrideCursor() map_name = sc2map.get_name() if (map_name in scctool.settings.maps): buttonReply = QMessageBox.warning( self, _("Duplicate Entry"), _("Map {} is already in list! Overwrite?".format( map_name)), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if buttonReply == QMessageBox.No: break else: self.controller.deleteMap(map_name) try: QApplication.setOverrideCursor(Qt.WaitCursor) images = grabber.get_images(sc2map.get_map_images()) image = "" for size in sorted(images): if not image or size <= 2500 * 2500: image = images[size] url = grabber._base_url + image downloader = MapDownloader(self, map_name, url) downloader.download() if map_name not in scctool.settings.maps: scctool.settings.maps.append(map_name) items = self.maplist.findItems(map_name, Qt.MatchExactly) if len(items) == 0: item = QListWidgetItem(map_name) self.maplist.addItem(item) self.maplist.setCurrentItem(item) else: self.maplist.setCurrentItem(items[0]) self.changePreview() except Exception: raise finally: QApplication.restoreOverrideCursor() except Exception as e: module_logger.exception("message") QMessageBox.critical(self, _("Error"), str(e)) break def deleteMap(self): """Delete a map.""" item = self.maplist.currentItem() mapname = item.text() buttonReply = QMessageBox.question( self, _('Delete map?'), _("Delete '{}' permanently?").format(mapname), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if buttonReply == QMessageBox.Yes: self.controller.deleteMap(mapname) self.maplist.takeItem(self.maplist.currentRow()) def changePreview(self): """Change the map preview.""" if self.maplist.count() < 1: return mapname = self.maplist.currentItem().text() if (mapname == "TBD"): self.pb_renameMap.setEnabled(False) self.pb_removeMap.setEnabled(False) self.sc_removeMap.setEnabled(False) else: self.pb_removeMap.setEnabled(True) self.pb_renameMap.setEnabled(True) self.sc_removeMap.setEnabled(True) file = self.controller.getMapImg(mapname, True) pixmap = QPixmap(file) height = pixmap.height() width = pixmap.width() ext = os.path.splitext(file)[1].replace(".", "").upper() size = humanize.naturalsize(os.path.getsize(file)) pixmap = QPixmap(file).scaled(self.mapsize, self.mapsize, Qt.KeepAspectRatio) self.mapPreview.setPixmap(pixmap) text = f"{width}x{height}px, {size}, {ext}" self.mapInfo.setText(text) def createButtonGroup(self): """Create buttons.""" try: layout = QHBoxLayout() layout.addWidget(QLabel("")) buttonCancel = QPushButton(_('Cancel')) buttonCancel.clicked.connect(self.closeWindow) layout.addWidget(buttonCancel) buttonSave = QPushButton(_('&Save && Close')) buttonSave.setToolTip(_("Shortcut: {}").format("Ctrl+S")) self.shortcut = QShortcut(QKeySequence("Ctrl+S"), self) self.shortcut.setAutoRepeat(False) self.shortcut.activated.connect(self.saveCloseWindow) buttonSave.clicked.connect(self.saveCloseWindow) layout.addWidget(buttonSave) self.buttonGroup = layout except Exception: module_logger.exception("message") def saveData(self): """Save the data.""" if (self.__dataChanged): scctool.settings.config.parser.set( "SCT", "myteams", ", ".join(self.list_favTeams.getData())) scctool.settings.config.parser.set( "SCT", "commonplayers", ", ".join(self.list_favPlayers.getData())) scctool.settings.config.parser.set("SCT", "tesseract", self.tesseract.text().strip()) scctool.settings.config.parser.set("SCT", "use_ocr", str(self.cb_useocr.isChecked())) scctool.settings.config.parser.set( "SCT", "transparent_match_banner", str(self.cb_trans_banner.isChecked())) scctool.settings.config.parser.set( "SCT", "CtrlShiftS", str(self.cb_ctrlshifts.isChecked())) scctool.settings.config.parser.set( "SCT", "CtrlShiftC", str(self.cb_ctrlshiftc.isChecked())) scctool.settings.config.parser.set( "SCT", "swap_myteam", str(self.cb_swapTeams.isChecked())) scctool.settings.config.parser.set("SCT", "CtrlN", str(self.cb_ctrln.isChecked())) scctool.settings.config.parser.set("SCT", "CtrlX", str(self.cb_ctrlx.isChecked())) scctool.settings.config.parser.set( "SCT", "CtrlShiftR", str(self.cb_ctrlshiftr.currentText())) scctool.settings.config.parser.set( "SCT", "blacklist_on", str(self.cb_blacklist.isChecked())) scctool.settings.config.parser.set( "SCT", "blacklist", ", ".join(self.list_blacklist.getData())) scctool.settings.config.parser.set( "SCT", "sc2_network_listener_address", self.listener_address.text().strip()) scctool.settings.config.parser.set( "SCT", "sc2_network_listener_enabled", str(self.cb_usesc2listener.isChecked())) scctool.settings.config.parser.set( "Countdown", "matchgrabber_update", str(self.cb_counter_matchgrabber_update.isChecked())) scctool.settings.config.parser.set( "Countdown", "replacement", self.le_countdown_replacement.text()) scctool.settings.config.parser.set( "Countdown", "pre_txt", self.counter_pretext.toPlainText()) scctool.settings.config.parser.set( "Countdown", "post_txt", self.counter_posttext.toPlainText()) self.controller.refreshButtonStatus() # self.controller.setCBS() self.__dataChanged = False def saveCloseWindow(self): """Save and close window.""" self.saveData() self.passEvent = True self.close() def closeWindow(self): """Close window.""" self.passEvent = True self.close() def closeEvent(self, event): """Handle close event.""" try: self.mainWindow.updateAllMapCompleters() if (not self.__dataChanged): event.accept() return if (not self.passEvent): if (self.isMinimized()): self.showNormal() buttonReply = QMessageBox.question( self, _('Save data?'), _("Save data?"), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if buttonReply == QMessageBox.Yes: self.saveData() event.accept() except Exception: module_logger.exception("message")
def __init__(self, window, plugin, keystore, device_id): title = _("{} Settings").format(plugin.device) super(SettingsDialog, self).__init__(window, title) self.setMaximumWidth(540) devmgr = plugin.device_manager() config = devmgr.config handler = keystore.handler thread = keystore.thread def invoke_client(method, *args, **kw_args): unpair_after = kw_args.pop('unpair_after', False) def task(): client = devmgr.client_by_id(device_id) if not client: raise RuntimeError("Device not connected") if method: getattr(client, method)(*args, **kw_args) if unpair_after: devmgr.unpair_id(device_id) return client.features thread.add(task, on_success=update) def update(features): self.features = features set_label_enabled() bl_hash = bh2u(features.bootloader_hash) bl_hash = "\n".join([bl_hash[:32], bl_hash[32:]]) noyes = [_("No"), _("Yes")] endis = [_("Enable Passphrases"), _("Disable Passphrases")] disen = [_("Disabled"), _("Enabled")] setchange = [_("Set a PIN"), _("Change PIN")] version = "%d.%d.%d" % (features.major_version, features.minor_version, features.patch_version) coins = ", ".join(coin.coin_name for coin in features.coins) device_label.setText(features.label) pin_set_label.setText(noyes[features.pin_protection]) passphrases_label.setText(disen[features.passphrase_protection]) bl_hash_label.setText(bl_hash) label_edit.setText(features.label) device_id_label.setText(features.device_id) initialized_label.setText(noyes[features.initialized]) version_label.setText(version) coins_label.setText(coins) clear_pin_button.setVisible(features.pin_protection) clear_pin_warning.setVisible(features.pin_protection) pin_button.setText(setchange[features.pin_protection]) pin_msg.setVisible(not features.pin_protection) passphrase_button.setText(endis[features.passphrase_protection]) language_label.setText(features.language) def set_label_enabled(): label_apply.setEnabled(label_edit.text() != self.features.label) def rename(): invoke_client('change_label', label_edit.text()) def toggle_passphrase(): title = _("Confirm Toggle Passphrase Protection") currently_enabled = self.features.passphrase_protection if currently_enabled: msg = _("After disabling passphrases, you can only pair this " "Electrum wallet if it had an empty passphrase. " "If its passphrase was not empty, you will need to " "create a new wallet with the install wizard. You " "can use this wallet again at any time by re-enabling " "passphrases and entering its passphrase.") else: msg = _("Your current Electrum wallet can only be used with " "an empty passphrase. You must create a separate " "wallet with the install wizard for other passphrases " "as each one generates a new set of addresses.") msg += "\n\n" + _("Are you sure you want to proceed?") if not self.question(msg, title=title): return invoke_client('toggle_passphrase', unpair_after=currently_enabled) def set_pin(): invoke_client('set_pin', remove=False) def clear_pin(): invoke_client('set_pin', remove=True) def wipe_device(): wallet = window.wallet if wallet and sum(wallet.get_balance()): title = _("Confirm Device Wipe") msg = _("Are you SURE you want to wipe the device?\n" "Your wallet still has viacoins in it!") if not self.question( msg, title=title, icon=QMessageBox.Critical): return invoke_client('wipe_device', unpair_after=True) def slider_moved(): mins = timeout_slider.sliderPosition() timeout_minutes.setText(_("{:2d} minutes").format(mins)) def slider_released(): config.set_session_timeout(timeout_slider.sliderPosition() * 60) # Information tab info_tab = QWidget() info_layout = QVBoxLayout(info_tab) info_glayout = QGridLayout() info_glayout.setColumnStretch(2, 1) device_label = QLabel() pin_set_label = QLabel() passphrases_label = QLabel() version_label = QLabel() device_id_label = QLabel() bl_hash_label = QLabel() bl_hash_label.setWordWrap(True) coins_label = QLabel() coins_label.setWordWrap(True) language_label = QLabel() initialized_label = QLabel() rows = [ (_("Device Label"), device_label), (_("PIN set"), pin_set_label), (_("Passphrases"), passphrases_label), (_("Firmware Version"), version_label), (_("Device ID"), device_id_label), (_("Bootloader Hash"), bl_hash_label), (_("Supported Coins"), coins_label), (_("Language"), language_label), (_("Initialized"), initialized_label), ] for row_num, (label, widget) in enumerate(rows): info_glayout.addWidget(QLabel(label), row_num, 0) info_glayout.addWidget(widget, row_num, 1) info_layout.addLayout(info_glayout) # Settings tab settings_tab = QWidget() settings_layout = QVBoxLayout(settings_tab) settings_glayout = QGridLayout() # Settings tab - Label label_msg = QLabel( _("Name this {}. If you have multiple devices " "their labels help distinguish them.").format(plugin.device)) label_msg.setWordWrap(True) label_label = QLabel(_("Device Label")) label_edit = QLineEdit() label_edit.setMinimumWidth(150) label_edit.setMaxLength(plugin.MAX_LABEL_LEN) label_apply = QPushButton(_("Apply")) label_apply.clicked.connect(rename) label_edit.textChanged.connect(set_label_enabled) settings_glayout.addWidget(label_label, 0, 0) settings_glayout.addWidget(label_edit, 0, 1, 1, 2) settings_glayout.addWidget(label_apply, 0, 3) settings_glayout.addWidget(label_msg, 1, 1, 1, -1) # Settings tab - PIN pin_label = QLabel(_("PIN Protection")) pin_button = QPushButton() pin_button.clicked.connect(set_pin) settings_glayout.addWidget(pin_label, 2, 0) settings_glayout.addWidget(pin_button, 2, 1) pin_msg = QLabel( _("PIN protection is strongly recommended. " "A PIN is your only protection against someone " "stealing your viacoins if they obtain physical " "access to your {}.").format(plugin.device)) pin_msg.setWordWrap(True) pin_msg.setStyleSheet("color: red") settings_glayout.addWidget(pin_msg, 3, 1, 1, -1) # Settings tab - Session Timeout timeout_label = QLabel(_("Session Timeout")) timeout_minutes = QLabel() timeout_slider = QSlider(Qt.Horizontal) timeout_slider.setRange(1, 60) timeout_slider.setSingleStep(1) timeout_slider.setTickInterval(5) timeout_slider.setTickPosition(QSlider.TicksBelow) timeout_slider.setTracking(True) timeout_msg = QLabel( _("Clear the session after the specified period " "of inactivity. Once a session has timed out, " "your PIN and passphrase (if enabled) must be " "re-entered to use the device.")) timeout_msg.setWordWrap(True) timeout_slider.setSliderPosition(config.get_session_timeout() // 60) slider_moved() timeout_slider.valueChanged.connect(slider_moved) timeout_slider.sliderReleased.connect(slider_released) settings_glayout.addWidget(timeout_label, 6, 0) settings_glayout.addWidget(timeout_slider, 6, 1, 1, 3) settings_glayout.addWidget(timeout_minutes, 6, 4) settings_glayout.addWidget(timeout_msg, 7, 1, 1, -1) settings_layout.addLayout(settings_glayout) settings_layout.addStretch(1) # Advanced tab advanced_tab = QWidget() advanced_layout = QVBoxLayout(advanced_tab) advanced_glayout = QGridLayout() # Advanced tab - clear PIN clear_pin_button = QPushButton(_("Disable PIN")) clear_pin_button.clicked.connect(clear_pin) clear_pin_warning = QLabel( _("If you disable your PIN, anyone with physical access to your " "{} device can spend your viacoins.").format(plugin.device)) clear_pin_warning.setWordWrap(True) clear_pin_warning.setStyleSheet("color: red") advanced_glayout.addWidget(clear_pin_button, 0, 2) advanced_glayout.addWidget(clear_pin_warning, 1, 0, 1, 5) # Advanced tab - toggle passphrase protection passphrase_button = QPushButton() passphrase_button.clicked.connect(toggle_passphrase) passphrase_msg = WWLabel(PASSPHRASE_HELP) passphrase_warning = WWLabel(PASSPHRASE_NOT_PIN) passphrase_warning.setStyleSheet("color: red") advanced_glayout.addWidget(passphrase_button, 3, 2) advanced_glayout.addWidget(passphrase_msg, 4, 0, 1, 5) advanced_glayout.addWidget(passphrase_warning, 5, 0, 1, 5) # Advanced tab - wipe device wipe_device_button = QPushButton(_("Wipe Device")) wipe_device_button.clicked.connect(wipe_device) wipe_device_msg = QLabel( _("Wipe the device, removing all data from it. The firmware " "is left unchanged.")) wipe_device_msg.setWordWrap(True) wipe_device_warning = QLabel( _("Only wipe a device if you have the recovery seed written down " "and the device wallet(s) are empty, otherwise the viacoins " "will be lost forever.")) wipe_device_warning.setWordWrap(True) wipe_device_warning.setStyleSheet("color: red") advanced_glayout.addWidget(wipe_device_button, 6, 2) advanced_glayout.addWidget(wipe_device_msg, 7, 0, 1, 5) advanced_glayout.addWidget(wipe_device_warning, 8, 0, 1, 5) advanced_layout.addLayout(advanced_glayout) advanced_layout.addStretch(1) tabs = QTabWidget(self) tabs.addTab(info_tab, _("Information")) tabs.addTab(settings_tab, _("Settings")) tabs.addTab(advanced_tab, _("Advanced")) dialog_vbox = QVBoxLayout(self) dialog_vbox.addWidget(tabs) dialog_vbox.addLayout(Buttons(CloseButton(self))) # Update information invoke_client(None)
class LibGeneratorUI(QDialog): num_of_funcs = 0 def __init__(self, parent=None): super(LibGeneratorUI, self).__init__(parent) self.layout = QGridLayout(self) self.workspace = os.path.dirname(os.path.realpath(__file__)) # current working folder self.tabs = QTabWidget() self.tab1 = QWidget() self.tab2 = QWidget() self.tabs.resize(1000, 200) # Add tabs self.tabs.addTab(self.tab1, 'Function') self.tabs.addTab(self.tab2, 'Defines and variables') self.tab1_layout = QVBoxLayout() self.tab1_layout.setSpacing(10) # Create first tab self.functions_list = [] self.create_functions_tab() #self.createDefinesTab() # Add tabs to widget self.tab1.setLayout(self.tab1_layout) self.layout.addWidget(self.tabs) self.addGenerateButton() self.setLayout(self.layout) self.setGeometry(700, 400, 400, 50) self.setWindowTitle('MCU Library Generator v1.0.0') self.setStyle('Fusion') def setStyle(self, styleName): QApplication.setStyle(QStyleFactory.create(styleName)) QApplication.setPalette(QApplication.palette()) def create_functions_tab(self): self.conf_box = QGroupBox('Configurations') self.confs_layout = QGridLayout() self.createConfBox() self.functions_box = QGroupBox('Functions') self.functions_layout = QGridLayout() add_func_button = QPushButton('Add function') add_func_button.setIcon(QtGui.QIcon('img/add.jpg')) add_func_button.clicked.connect(self.addFunction) self.functions_layout.addWidget(add_func_button, 0, 0) self.addFunction() self.tab1_layout.addWidget(self.conf_box) self.tab1_layout.addWidget(self.functions_box) def createConfBox(self): lbl_username = QLabel('Creators Full Name') txt_username = QLineEdit() lbl_dir = QLabel('Project Directory') bt_dir = QPushButton("...") bt_dir.setFixedSize(30, 20) bt_dir.clicked.connect(self.get_work_dir) # to use in get_work_dir function self.txt_dir = QLineEdit() self.txt_dir.setText(self.workspace) self.txt_dir.setCursorPosition(0) ###################################### lbl_file_name = QLabel('Module (Library) name: ') txt_file_name = QLineEdit() txt_file_name.setText('sim800') self.config = Configuration(txt_username, self.txt_dir, txt_file_name) self.confs_layout.addWidget(lbl_username, 0, 0) self.confs_layout.addWidget(txt_username, 0, 1, 1, 20) self.confs_layout.addWidget(lbl_dir, 1, 0) self.confs_layout.addWidget(self.txt_dir, 1, 1, 1, 20) self.confs_layout.addWidget(bt_dir, 1, 21) self.confs_layout.addWidget(lbl_file_name, 2, 0) self.confs_layout.addWidget(txt_file_name, 2, 1, 1, 20) self.conf_box.setLayout(self.confs_layout) def get_work_dir(self): self.workspace = str(QFileDialog.getExistingDirectory(self, 'Select Directory')) self.txt_dir.setText(self.workspace) self.txt_dir.setCursorPosition(0) def addFunction(self): lbls = [QLabel('Return Type'), QLabel('Scope'), QLabel('Function Name'), QLabel('Arguments')] for lbl in lbls: lbl.setAlignment(Qt.AlignCenter) type = QComboBox(self.functions_box) type.addItems(['void', 'int', 'char *', 'bool', 'uint32_t']) type.setEditable(True) visibility = QComboBox(self.functions_box) visibility.addItems(['private', 'public']) visibility.setFixedWidth(100) name = QLineEdit() #arg_cnt = QSpinBox(self.functions_box) argv = QLineEdit() self.functions_list.append(Function(self.functions_layout, type, visibility, name, argv)) self.functions_layout.addWidget(lbls[0], 1, 0) self.functions_layout.addWidget(lbls[1], 1, 1) self.functions_layout.addWidget(lbls[2], 1, 4) self.functions_layout.addWidget(lbls[3], 1, 18) self.functions_layout.addWidget(type, 2 + self.num_of_funcs, 0) self.functions_layout.addWidget(visibility, 2 + self.num_of_funcs, 1) self.functions_layout.addWidget(name, 2 + self.num_of_funcs, 2, 1, 6) self.functions_layout.addWidget(argv, 2 + self.num_of_funcs, 8, 1, 20) self.num_of_funcs += 1 self.functions_box.setLayout(self.functions_layout) def addGenerateButton(self): generateButton = QPushButton(' Generate') generateButton.clicked.connect(self.generateCode) generateButton.setIcon(QtGui.QIcon('img/generate.jpg')) hbox = QHBoxLayout() hbox.addStretch(1) hbox.addWidget(generateButton) vbox = QVBoxLayout() vbox.addStretch(1) vbox.addLayout(hbox) self.layout.addLayout(vbox, 1, 0) def generateCode(self): generator.generateModule(self.config, self.functions_list, [], [])
def __init__(self, parent: 'ElectrumWindow', config: 'SimpleConfig'): WindowModalDialog.__init__(self, parent, _('Preferences')) self.config = config self.window = parent self.need_restart = False self.fx = self.window.fx self.wallet = self.window.wallet vbox = QVBoxLayout() tabs = QTabWidget() gui_widgets = [] tx_widgets = [] oa_widgets = [] # language lang_help = _('Select which language is used in the GUI (after restart).') lang_label = HelpLabel(_('Language') + ':', lang_help) lang_combo = QComboBox() lang_combo.addItems(list(languages.values())) lang_keys = list(languages.keys()) lang_cur_setting = self.config.get("language", '') try: index = lang_keys.index(lang_cur_setting) except ValueError: # not in list index = 0 lang_combo.setCurrentIndex(index) if not self.config.is_modifiable('language'): for w in [lang_combo, lang_label]: w.setEnabled(False) def on_lang(x): lang_request = list(languages.keys())[lang_combo.currentIndex()] if lang_request != self.config.get('language'): self.config.set_key("language", lang_request, True) self.need_restart = True lang_combo.currentIndexChanged.connect(on_lang) gui_widgets.append((lang_label, lang_combo)) nz_help = _('Number of zeros displayed after the decimal point. For example, if this is set to 2, "1." will be displayed as "1.00"') nz_label = HelpLabel(_('Zeros after decimal point') + ':', nz_help) nz = QSpinBox() nz.setMinimum(0) nz.setMaximum(self.config.decimal_point) nz.setValue(self.config.num_zeros) if not self.config.is_modifiable('num_zeros'): for w in [nz, nz_label]: w.setEnabled(False) def on_nz(): value = nz.value() if self.config.num_zeros != value: self.config.num_zeros = value self.config.set_key('num_zeros', value, True) self.window.need_update.set() nz.valueChanged.connect(on_nz) gui_widgets.append((nz_label, nz)) use_rbf = bool(self.config.get('use_rbf', True)) use_rbf_cb = QCheckBox(_('Use Replace-By-Fee')) use_rbf_cb.setChecked(use_rbf) use_rbf_cb.setToolTip( _('If you check this box, your transactions will be marked as non-final,') + '\n' + \ _('and you will have the possibility, while they are unconfirmed, to replace them with transactions that pay higher fees.') + '\n' + \ _('Note that some merchants do not accept non-final transactions until they are confirmed.')) def on_use_rbf(x): self.config.set_key('use_rbf', bool(x)) batch_rbf_cb.setEnabled(bool(x)) use_rbf_cb.stateChanged.connect(on_use_rbf) tx_widgets.append((use_rbf_cb, None)) batch_rbf_cb = QCheckBox(_('Batch RBF transactions')) batch_rbf_cb.setChecked(bool(self.config.get('batch_rbf', False))) batch_rbf_cb.setEnabled(use_rbf) batch_rbf_cb.setToolTip( _('If you check this box, your unconfirmed transactions will be consolidated into a single transaction.') + '\n' + \ _('This will save fees.')) def on_batch_rbf(x): self.config.set_key('batch_rbf', bool(x)) batch_rbf_cb.stateChanged.connect(on_batch_rbf) tx_widgets.append((batch_rbf_cb, None)) # lightning lightning_widgets = [] help_recov = _(messages.MSG_RECOVERABLE_CHANNELS) recov_cb = QCheckBox(_("Create recoverable channels")) enable_toggle_use_recoverable_channels = bool(self.wallet.lnworker and self.wallet.lnworker.can_have_recoverable_channels()) recov_cb.setEnabled(enable_toggle_use_recoverable_channels) recov_cb.setToolTip(messages.to_rtf(help_recov)) recov_cb.setChecked(bool(self.config.get('use_recoverable_channels', True)) and enable_toggle_use_recoverable_channels) def on_recov_checked(x): self.config.set_key('use_recoverable_channels', bool(x)) recov_cb.stateChanged.connect(on_recov_checked) lightning_widgets.append((recov_cb, None)) help_trampoline = _(messages.MSG_HELP_TRAMPOLINE) trampoline_cb = QCheckBox(_("Use trampoline routing (disable gossip)")) trampoline_cb.setToolTip(messages.to_rtf(help_trampoline)) trampoline_cb.setChecked(not bool(self.config.get('use_gossip', False))) def on_trampoline_checked(use_trampoline): use_gossip = not bool(use_trampoline) self.config.set_key('use_gossip', use_gossip) if use_gossip: self.window.network.start_gossip() else: self.window.network.run_from_another_thread( self.window.network.stop_gossip()) util.trigger_callback('ln_gossip_sync_progress') # FIXME: update all wallet windows util.trigger_callback('channels_updated', self.wallet) trampoline_cb.stateChanged.connect(on_trampoline_checked) lightning_widgets.append((trampoline_cb, None)) help_remote_wt = ' '.join([ _("A watchtower is a daemon that watches your channels and prevents the other party from stealing funds by broadcasting an old state."), _("If you have private a watchtower, enter its URL here."), _("Check our online documentation if you want to configure Electrum as a watchtower."), ]) remote_wt_cb = QCheckBox(_("Use a remote watchtower")) remote_wt_cb.setToolTip('<p>'+help_remote_wt+'</p>') remote_wt_cb.setChecked(bool(self.config.get('use_watchtower', False))) def on_remote_wt_checked(x): self.config.set_key('use_watchtower', bool(x)) self.watchtower_url_e.setEnabled(bool(x)) remote_wt_cb.stateChanged.connect(on_remote_wt_checked) watchtower_url = self.config.get('watchtower_url') self.watchtower_url_e = QLineEdit(watchtower_url) self.watchtower_url_e.setEnabled(self.config.get('use_watchtower', False)) def on_wt_url(): url = self.watchtower_url_e.text() or None watchtower_url = self.config.set_key('watchtower_url', url) self.watchtower_url_e.editingFinished.connect(on_wt_url) lightning_widgets.append((remote_wt_cb, self.watchtower_url_e)) msg = _('OpenAlias record, used to receive coins and to sign payment requests.') + '\n\n'\ + _('The following alias providers are available:') + '\n'\ + '\n'.join(['https://cryptoname.co/', 'http://xmr.link']) + '\n\n'\ + 'For more information, see https://openalias.org' alias_label = HelpLabel(_('OpenAlias') + ':', msg) alias = self.config.get('alias','') self.alias_e = QLineEdit(alias) self.set_alias_color() self.alias_e.editingFinished.connect(self.on_alias_edit) oa_widgets.append((alias_label, self.alias_e)) msat_cb = QCheckBox(_("Show amounts with msat precision")) msat_cb.setChecked(bool(self.config.get('amt_precision_post_satoshi', False))) def on_msat_checked(v): prec = 3 if v == Qt.Checked else 0 if self.config.amt_precision_post_satoshi != prec: self.config.amt_precision_post_satoshi = prec self.config.set_key('amt_precision_post_satoshi', prec) self.window.need_update.set() msat_cb.stateChanged.connect(on_msat_checked) lightning_widgets.append((msat_cb, None)) # units units = base_units_list msg = (_('Base unit of your wallet.') + '\n1 GRLC = 1000 mGRLC. 1 mGRLC = 1000 uGRLC. 1 uGRLC = 100 sat.\n' + _('This setting affects the Send tab, and all balance related fields.')) unit_label = HelpLabel(_('Base unit') + ':', msg) unit_combo = QComboBox() unit_combo.addItems(units) unit_combo.setCurrentIndex(units.index(self.window.base_unit())) def on_unit(x, nz): unit_result = units[unit_combo.currentIndex()] if self.window.base_unit() == unit_result: return edits = self.window.amount_e, self.window.receive_amount_e amounts = [edit.get_amount() for edit in edits] self.config.set_base_unit(unit_result) nz.setMaximum(self.config.decimal_point) self.window.update_tabs() for edit, amount in zip(edits, amounts): edit.setAmount(amount) self.window.update_status() unit_combo.currentIndexChanged.connect(lambda x: on_unit(x, nz)) gui_widgets.append((unit_label, unit_combo)) thousandsep_cb = QCheckBox(_("Add thousand separators to bitcoin amounts")) thousandsep_cb.setChecked(bool(self.config.get('amt_add_thousands_sep', False))) def on_set_thousandsep(v): checked = v == Qt.Checked if self.config.amt_add_thousands_sep != checked: self.config.amt_add_thousands_sep = checked self.config.set_key('amt_add_thousands_sep', checked) self.window.need_update.set() thousandsep_cb.stateChanged.connect(on_set_thousandsep) gui_widgets.append((thousandsep_cb, None)) qr_combo = QComboBox() qr_combo.addItem("Default", "default") msg = (_("For scanning QR codes.") + "\n" + _("Install the zbar package to enable this.")) qr_label = HelpLabel(_('Video Device') + ':', msg) from .qrreader import find_system_cameras system_cameras = find_system_cameras() for cam_desc, cam_path in system_cameras.items(): qr_combo.addItem(cam_desc, cam_path) index = qr_combo.findData(self.config.get("video_device")) qr_combo.setCurrentIndex(index) on_video_device = lambda x: self.config.set_key("video_device", qr_combo.itemData(x), True) qr_combo.currentIndexChanged.connect(on_video_device) gui_widgets.append((qr_label, qr_combo)) colortheme_combo = QComboBox() colortheme_combo.addItem(_('Light'), 'default') colortheme_combo.addItem(_('Dark'), 'dark') index = colortheme_combo.findData(self.config.get('qt_gui_color_theme', 'default')) colortheme_combo.setCurrentIndex(index) colortheme_label = QLabel(_('Color theme') + ':') def on_colortheme(x): self.config.set_key('qt_gui_color_theme', colortheme_combo.itemData(x), True) self.need_restart = True colortheme_combo.currentIndexChanged.connect(on_colortheme) gui_widgets.append((colortheme_label, colortheme_combo)) updatecheck_cb = QCheckBox(_("Automatically check for software updates")) updatecheck_cb.setChecked(bool(self.config.get('check_updates', False))) def on_set_updatecheck(v): self.config.set_key('check_updates', v == Qt.Checked, save=True) updatecheck_cb.stateChanged.connect(on_set_updatecheck) gui_widgets.append((updatecheck_cb, None)) filelogging_cb = QCheckBox(_("Write logs to file")) filelogging_cb.setChecked(bool(self.config.get('log_to_file', False))) def on_set_filelogging(v): self.config.set_key('log_to_file', v == Qt.Checked, save=True) self.need_restart = True filelogging_cb.stateChanged.connect(on_set_filelogging) filelogging_cb.setToolTip(_('Debug logs can be persisted to disk. These are useful for troubleshooting.')) gui_widgets.append((filelogging_cb, None)) preview_cb = QCheckBox(_('Advanced preview')) preview_cb.setChecked(bool(self.config.get('advanced_preview', False))) preview_cb.setToolTip(_("Open advanced transaction preview dialog when 'Pay' is clicked.")) def on_preview(x): self.config.set_key('advanced_preview', x == Qt.Checked) preview_cb.stateChanged.connect(on_preview) tx_widgets.append((preview_cb, None)) usechange_cb = QCheckBox(_('Use change addresses')) usechange_cb.setChecked(self.window.wallet.use_change) if not self.config.is_modifiable('use_change'): usechange_cb.setEnabled(False) def on_usechange(x): usechange_result = x == Qt.Checked if self.window.wallet.use_change != usechange_result: self.window.wallet.use_change = usechange_result self.window.wallet.db.put('use_change', self.window.wallet.use_change) multiple_cb.setEnabled(self.window.wallet.use_change) usechange_cb.stateChanged.connect(on_usechange) usechange_cb.setToolTip(_('Using change addresses makes it more difficult for other people to track your transactions.')) tx_widgets.append((usechange_cb, None)) def on_multiple(x): multiple = x == Qt.Checked if self.wallet.multiple_change != multiple: self.wallet.multiple_change = multiple self.wallet.db.put('multiple_change', multiple) multiple_change = self.wallet.multiple_change multiple_cb = QCheckBox(_('Use multiple change addresses')) multiple_cb.setEnabled(self.wallet.use_change) multiple_cb.setToolTip('\n'.join([ _('In some cases, use up to 3 change addresses in order to break ' 'up large coin amounts and obfuscate the recipient address.'), _('This may result in higher transactions fees.') ])) multiple_cb.setChecked(multiple_change) multiple_cb.stateChanged.connect(on_multiple) tx_widgets.append((multiple_cb, None)) def fmt_docs(key, klass): lines = [ln.lstrip(" ") for ln in klass.__doc__.split("\n")] return '\n'.join([key, "", " ".join(lines)]) choosers = sorted(coinchooser.COIN_CHOOSERS.keys()) if len(choosers) > 1: chooser_name = coinchooser.get_name(self.config) msg = _('Choose coin (UTXO) selection method. The following are available:\n\n') msg += '\n\n'.join(fmt_docs(*item) for item in coinchooser.COIN_CHOOSERS.items()) chooser_label = HelpLabel(_('Coin selection') + ':', msg) chooser_combo = QComboBox() chooser_combo.addItems(choosers) i = choosers.index(chooser_name) if chooser_name in choosers else 0 chooser_combo.setCurrentIndex(i) def on_chooser(x): chooser_name = choosers[chooser_combo.currentIndex()] self.config.set_key('coin_chooser', chooser_name) chooser_combo.currentIndexChanged.connect(on_chooser) tx_widgets.append((chooser_label, chooser_combo)) def on_unconf(x): self.config.set_key('confirmed_only', bool(x)) conf_only = bool(self.config.get('confirmed_only', False)) unconf_cb = QCheckBox(_('Spend only confirmed coins')) unconf_cb.setToolTip(_('Spend only confirmed inputs.')) unconf_cb.setChecked(conf_only) unconf_cb.stateChanged.connect(on_unconf) tx_widgets.append((unconf_cb, None)) def on_outrounding(x): self.config.set_key('coin_chooser_output_rounding', bool(x)) enable_outrounding = bool(self.config.get('coin_chooser_output_rounding', True)) outrounding_cb = QCheckBox(_('Enable output value rounding')) outrounding_cb.setToolTip( _('Set the value of the change output so that it has similar precision to the other outputs.') + '\n' + _('This might improve your privacy somewhat.') + '\n' + _('If enabled, at most 100 satoshis might be lost due to this, per transaction.')) outrounding_cb.setChecked(enable_outrounding) outrounding_cb.stateChanged.connect(on_outrounding) tx_widgets.append((outrounding_cb, None)) block_explorers = sorted(util.block_explorer_info().keys()) BLOCK_EX_CUSTOM_ITEM = _("Custom URL") if BLOCK_EX_CUSTOM_ITEM in block_explorers: # malicious translation? block_explorers.remove(BLOCK_EX_CUSTOM_ITEM) block_explorers.append(BLOCK_EX_CUSTOM_ITEM) msg = _('Choose which online block explorer to use for functions that open a web browser') block_ex_label = HelpLabel(_('Online Block Explorer') + ':', msg) block_ex_combo = QComboBox() block_ex_custom_e = QLineEdit(str(self.config.get('block_explorer_custom') or '')) block_ex_combo.addItems(block_explorers) block_ex_combo.setCurrentIndex( block_ex_combo.findText(util.block_explorer(self.config) or BLOCK_EX_CUSTOM_ITEM)) def showhide_block_ex_custom_e(): block_ex_custom_e.setVisible(block_ex_combo.currentText() == BLOCK_EX_CUSTOM_ITEM) showhide_block_ex_custom_e() def on_be_combo(x): if block_ex_combo.currentText() == BLOCK_EX_CUSTOM_ITEM: on_be_edit() else: be_result = block_explorers[block_ex_combo.currentIndex()] self.config.set_key('block_explorer_custom', None, False) self.config.set_key('block_explorer', be_result, True) showhide_block_ex_custom_e() block_ex_combo.currentIndexChanged.connect(on_be_combo) def on_be_edit(): val = block_ex_custom_e.text() try: val = ast.literal_eval(val) # to also accept tuples except: pass self.config.set_key('block_explorer_custom', val) block_ex_custom_e.editingFinished.connect(on_be_edit) block_ex_hbox = QHBoxLayout() block_ex_hbox.setContentsMargins(0, 0, 0, 0) block_ex_hbox.setSpacing(0) block_ex_hbox.addWidget(block_ex_combo) block_ex_hbox.addWidget(block_ex_custom_e) block_ex_hbox_w = QWidget() block_ex_hbox_w.setLayout(block_ex_hbox) tx_widgets.append((block_ex_label, block_ex_hbox_w)) # Fiat Currency hist_checkbox = QCheckBox() hist_capgains_checkbox = QCheckBox() fiat_address_checkbox = QCheckBox() ccy_combo = QComboBox() ex_combo = QComboBox() def update_currencies(): if not self.window.fx: return currencies = sorted(self.fx.get_currencies(self.fx.get_history_config())) ccy_combo.clear() ccy_combo.addItems([_('None')] + currencies) if self.fx.is_enabled(): ccy_combo.setCurrentIndex(ccy_combo.findText(self.fx.get_currency())) def update_history_cb(): if not self.fx: return hist_checkbox.setChecked(self.fx.get_history_config()) hist_checkbox.setEnabled(self.fx.is_enabled()) def update_fiat_address_cb(): if not self.fx: return fiat_address_checkbox.setChecked(self.fx.get_fiat_address_config()) def update_history_capgains_cb(): if not self.fx: return hist_capgains_checkbox.setChecked(self.fx.get_history_capital_gains_config()) hist_capgains_checkbox.setEnabled(hist_checkbox.isChecked()) def update_exchanges(): if not self.fx: return b = self.fx.is_enabled() ex_combo.setEnabled(b) if b: h = self.fx.get_history_config() c = self.fx.get_currency() exchanges = self.fx.get_exchanges_by_ccy(c, h) else: exchanges = self.fx.get_exchanges_by_ccy('USD', False) ex_combo.blockSignals(True) ex_combo.clear() ex_combo.addItems(sorted(exchanges)) ex_combo.setCurrentIndex(ex_combo.findText(self.fx.config_exchange())) ex_combo.blockSignals(False) def on_currency(hh): if not self.fx: return b = bool(ccy_combo.currentIndex()) ccy = str(ccy_combo.currentText()) if b else None self.fx.set_enabled(b) if b and ccy != self.fx.ccy: self.fx.set_currency(ccy) update_history_cb() update_exchanges() self.window.update_fiat() def on_exchange(idx): exchange = str(ex_combo.currentText()) if self.fx and self.fx.is_enabled() and exchange and exchange != self.fx.exchange.name(): self.fx.set_exchange(exchange) def on_history(checked): if not self.fx: return self.fx.set_history_config(checked) update_exchanges() self.window.history_model.refresh('on_history') if self.fx.is_enabled() and checked: self.fx.trigger_update() update_history_capgains_cb() def on_history_capgains(checked): if not self.fx: return self.fx.set_history_capital_gains_config(checked) self.window.history_model.refresh('on_history_capgains') def on_fiat_address(checked): if not self.fx: return self.fx.set_fiat_address_config(checked) self.window.address_list.refresh_headers() self.window.address_list.update() update_currencies() update_history_cb() update_history_capgains_cb() update_fiat_address_cb() update_exchanges() ccy_combo.currentIndexChanged.connect(on_currency) hist_checkbox.stateChanged.connect(on_history) hist_capgains_checkbox.stateChanged.connect(on_history_capgains) fiat_address_checkbox.stateChanged.connect(on_fiat_address) ex_combo.currentIndexChanged.connect(on_exchange) fiat_widgets = [] fiat_widgets.append((QLabel(_('Fiat currency')), ccy_combo)) fiat_widgets.append((QLabel(_('Source')), ex_combo)) fiat_widgets.append((QLabel(_('Show history rates')), hist_checkbox)) fiat_widgets.append((QLabel(_('Show capital gains in history')), hist_capgains_checkbox)) fiat_widgets.append((QLabel(_('Show Fiat balance for addresses')), fiat_address_checkbox)) tabs_info = [ (gui_widgets, _('General')), (tx_widgets, _('Transactions')), (lightning_widgets, _('Lightning')), (fiat_widgets, _('Fiat')), (oa_widgets, _('OpenAlias')), ] for widgets, name in tabs_info: tab = QWidget() tab_vbox = QVBoxLayout(tab) grid = QGridLayout() for a,b in widgets: i = grid.rowCount() if b: if a: grid.addWidget(a, i, 0) grid.addWidget(b, i, 1) else: grid.addWidget(a, i, 0, 1, 2) tab_vbox.addLayout(grid) tab_vbox.addStretch(1) tabs.addTab(tab, name) vbox.addWidget(tabs) vbox.addStretch(1) vbox.addLayout(Buttons(CloseButton(self))) self.setLayout(vbox)
class SubwindowBrowserSources(QWidget): """Show connections settings sub window.""" current_tab = -1 def createWindow(self, mainWindow, tab=''): """Create window.""" try: parent = None super().__init__(parent) # self.setWindowFlags(Qt.WindowStaysOnTopHint) self.setWindowIcon( QIcon(scctool.settings.getResFile('browser.png'))) self.setWindowModality(Qt.ApplicationModal) self.mainWindow = mainWindow self.passEvent = False self.controller = mainWindow.controller self.__dataChanged = False self.createButtonGroup() self.createTabs(tab) mainLayout = QVBoxLayout() mainLayout.addWidget(self.tabs) mainLayout.addLayout(self.buttonGroup) self.setLayout(mainLayout) self.resize( QSize(int(mainWindow.size().width() * 0.8), self.sizeHint().height())) relativeChange = QPoint(int(mainWindow.size().width() / 2), int(mainWindow.size().height() / 3)) -\ QPoint(int(self.size().width() / 2), int(self.size().height() / 3)) self.move(mainWindow.pos() + relativeChange) self.setWindowTitle(_("Browser Sources")) except Exception: module_logger.exception("message") def createTabs(self, tab): """Create tabs.""" self.tabs = QTabWidget() self.createFormGroupIntro() self.createFormGroupMapstats() self.createFormGroupMapBox() self.createFormGroupMapLandscape() self.createFormGroupVetoes() # Add tabs self.tabs.addTab(self.formGroupIntro, _("Intros")) self.tabs.addTab(self.formGroupMapstats, _("Mapstats")) self.tabs.addTab(self.formGroupMapBox, _("Box Map Icons")) self.tabs.addTab(self.formGroupMapLandscape, _("Landscape Map Icons")) self.tabs.addTab(self.formGroupVetoes, _("Veto Icons")) table = dict() table['intro'] = 0 table['mapstats'] = 1 table['mapicons_box'] = 2 table['mapicons_landscape'] = 3 table['vetoes'] = 4 self.tabs.setCurrentIndex( table.get(tab, SubwindowBrowserSources.current_tab)) self.tabs.currentChanged.connect(self.tabChanged) @classmethod def tabChanged(cls, idx): """Save the current tab.""" SubwindowBrowserSources.current_tab = idx def addHotkey(self, ident, label): """Add a hotkey to the layout.""" element = HotkeyLayout( self, ident, label, scctool.settings.config.parser.get("Intros", ident)) self.hotkeys[ident] = element return element def connectHotkeys(self): """Connect the hotkeys.""" for ident, key in self.hotkeys.items(): if ident == 'hotkey_debug': for ident2, key2 in self.hotkeys.items(): if ident == ident2: continue key.modified.connect(key2.check_dublicate) key.modified.connect(self.hotkeyChanged) def hotkeyChanged(self, key, ident): """Handle change of hotkeys.""" self.changed() if (ident == 'hotkey_player1' and self.cb_single_hotkey.isChecked()): self.hotkeys['hotkey_player2'].setData( self.hotkeys['hotkey_player1'].getKey()) if not key: return if ((ident == 'hotkey_player1' and key == self.hotkeys['hotkey_player2'].getKey()['name']) or (ident == 'hotkey_player2' and key == self.hotkeys['hotkey_player1'].getKey()['name'])): self.cb_single_hotkey.setChecked(True) if (ident in ['hotkey_player1', 'hotkey_player2'] and key == self.hotkeys['hotkey_debug'].getKey()['name']): self.hotkeys['hotkey_debug'].clear() def singleHotkeyChanged(self): """Handle single hotkey changed event.""" checked = self.cb_single_hotkey.isChecked() self.hotkeys['hotkey_player2'].setDisabled(checked) if checked: self.hotkeys['hotkey_player2'].setData( self.hotkeys['hotkey_player1'].getKey()) elif (self.hotkeys['hotkey_player1'].getKey() == self.hotkeys['hotkey_player2'].getKey()): self.hotkeys['hotkey_player2'].clear() def createFormGroupMapstats(self): """Create the form group for mapstats.""" self.formGroupMapstats = QWidget() mainLayout = QVBoxLayout() box = QGroupBox(_("General")) layout = QFormLayout() container = QHBoxLayout() self.qb_boxStyle = StyleComboBox( scctool.settings.casting_html_dir + "/src/css/mapstats", "mapstats") self.qb_boxStyle.connect2WS(self.controller, 'mapstats') label = QLabel(_("Style:")) label.setMinimumWidth(120) button = QPushButton(_("Show in Browser")) button.clicked.connect(lambda: self.openHTML( scctool.settings.casting_html_dir + "/mapstats.html")) container.addWidget(self.qb_boxStyle, 2) container.addWidget(button, 1) layout.addRow(label, container) self.cb_mappool = QComboBox() self.cb_mappool.addItem(_("Current Ladder Map Pool")) self.cb_mappool.addItem(_("Custom Map Pool (defined below)")) self.cb_mappool.addItem(_("Currently entered Maps only")) self.cb_mappool.setCurrentIndex( self.controller.mapstatsManager.getMapPoolType()) self.cb_mappool.currentIndexChanged.connect(self.changed) layout.addRow(QLabel(_("Map Pool:")), self.cb_mappool) self.cb_autoset_map = QCheckBox(_("Select the next map automatically")) self.cb_autoset_map.setChecked( scctool.settings.config.parser.getboolean("Mapstats", "autoset_next_map")) self.cb_autoset_map.stateChanged.connect(self.changed) label = QLabel(_("Next Map:")) label.setMinimumWidth(120) layout.addRow(label, self.cb_autoset_map) self.cb_mark_played = QCheckBox(_("Mark already played maps")) self.cb_mark_played.setChecked( scctool.settings.config.parser.getboolean("Mapstats", "mark_played")) self.cb_mark_played.stateChanged.connect(self.changed) label = QLabel(_("Mark:")) label.setMinimumWidth(120) layout.addRow(label, self.cb_mark_played) self.cb_mark_vetoed = QCheckBox(_("Mark vetoed maps")) self.cb_mark_vetoed.setChecked( scctool.settings.config.parser.getboolean("Mapstats", "mark_vetoed")) self.cb_mark_vetoed.stateChanged.connect(self.changed) label = QLabel(" ") label.setMinimumWidth(120) layout.addRow(label, self.cb_mark_vetoed) self.cb_sort_maps = QCheckBox(_("Sort currently entered maps")) self.cb_sort_maps.setChecked( scctool.settings.config.parser.getboolean("Mapstats", "sort_maps")) self.cb_sort_maps.stateChanged.connect(self.changed) label = QLabel(_("Sort:")) label.setMinimumWidth(120) layout.addRow(label, self.cb_sort_maps) box.setLayout(layout) mainLayout.addWidget(box) box = QGroupBox(_("Custom Map Pool")) layout = QGridLayout() self.maplist = QListWidget() self.maplist.setSortingEnabled(True) ls = list(self.controller.mapstatsManager.getCustomMapPool()) self.maplist.addItems(ls) self.maplist.setCurrentItem(self.maplist.item(0)) layout.addWidget(self.maplist, 0, 0, 3, 1) qb_add = QPushButton() pixmap = QIcon(scctool.settings.getResFile('add.png')) qb_add.setIcon(pixmap) qb_add.clicked.connect(self.addMap) layout.addWidget(qb_add, 0, 1) qb_remove = QPushButton() pixmap = QIcon(scctool.settings.getResFile('delete.png')) qb_remove.clicked.connect(self.removeMap) qb_remove.setIcon(pixmap) layout.addWidget(qb_remove, 1, 1) self.sc_removeMap = QShortcut(QKeySequence("Del"), self) self.sc_removeMap.setAutoRepeat(False) self.sc_removeMap.activated.connect(self.removeMap) box.setLayout(layout) mainLayout.addWidget(box) mainLayout.addItem( QSpacerItem(0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)) self.formGroupMapstats.setLayout(mainLayout) def addMap(self): """Add a map to the list.""" maplist = list(scctool.settings.maps) for i in range(self.maplist.count()): sc2map = str(self.maplist.item(i).text()) if sc2map in maplist: maplist.remove(sc2map) if len(maplist) > 0: sc2map, ok = QInputDialog.getItem(self, _('Add Map'), _('Please select a map') + ':', maplist, editable=False) if ok: self.__dataChanged = True item = QListWidgetItem(sc2map) self.maplist.addItem(item) self.maplist.setCurrentItem(item) else: QMessageBox.information( self, _("No maps available"), _('All available maps have already been added.')) def removeMap(self): """Remove a map from the list.""" item = self.maplist.currentItem() if item: self.maplist.takeItem(self.maplist.currentRow()) self.__dataChanged = True def createFormGroupMapBox(self): """Create a QWidget for boxed map icons.""" self.formGroupMapBox = QWidget() mainLayout = QVBoxLayout() box = QGroupBox(_("General")) layout = QFormLayout() container = QHBoxLayout() self.qb_boxStyle = StyleComboBox( scctool.settings.casting_html_dir + "/src/css/mapicons_box", "mapicons_box") self.qb_boxStyle.connect2WS(self.controller, 'mapicons_box') label = QLabel(_("Style:")) label.setMinimumWidth(120) button = QPushButton(_("Show in Browser")) button.clicked.connect(lambda: self.openHTML( scctool.settings.casting_html_dir + "/mapicons_box_1.html")) container.addWidget(self.qb_boxStyle, 2) container.addWidget(button, 1) layout.addRow(label, container) self.sb_padding_box = QDoubleSpinBox() self.sb_padding_box.setRange(0, 50) self.sb_padding_box.setDecimals(1) self.sb_padding_box.setValue( scctool.settings.config.parser.getfloat("MapIcons", "padding_box")) self.sb_padding_box.setSuffix(" " + _("Pixel")) self.sb_padding_box.valueChanged.connect( lambda x: self.changePadding('box', x)) layout.addRow(QLabel(_("Icon Padding:") + " "), self.sb_padding_box) box.setLayout(layout) mainLayout.addWidget(box) options = self.controller.matchControl.scopes self.scope_box = dict() for idx in range(3): self.scope_box[idx] = ScopeGroupBox( _("Icon Set {} Scope".format(idx + 1)), options, f'box_{idx + 1}', self.controller, self) self.scope_box[idx].dataModified.connect(self.changed) mainLayout.addWidget(self.scope_box[idx]) mainLayout.addItem( QSpacerItem(0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)) self.formGroupMapBox.setLayout(mainLayout) def createFormGroupVetoes(self): """Create a QWidget for veto icons.""" self.formGroupVetoes = QWidget() mainLayout = QVBoxLayout() box = QGroupBox(_("General")) layout = QFormLayout() container = QHBoxLayout() self.qb_boxStyle = StyleComboBox( scctool.settings.casting_html_dir + "/src/css/vetoes", "vetoes") self.qb_boxStyle.connect2WS(self.controller, 'vetoes') label = QLabel(_("Style:")) label.setMinimumWidth(120) button = QPushButton(_("Show in Browser")) button.clicked.connect(lambda: self.openHTML( scctool.settings.casting_html_dir + "/vetoes.html")) container.addWidget(self.qb_boxStyle, 2) container.addWidget(button, 1) layout.addRow(label, container) self.sb_padding_box = QDoubleSpinBox() self.sb_padding_box.setRange(0, 50) self.sb_padding_box.setDecimals(1) self.sb_padding_box.setValue( scctool.settings.config.parser.getfloat("Vetoes", "padding")) self.sb_padding_box.setSuffix(" " + _("Pixel")) self.sb_padding_box.valueChanged.connect( lambda x: self.changePadding('vetoes', x)) layout.addRow(QLabel(_("Icon Padding:") + " "), self.sb_padding_box) box.setLayout(layout) mainLayout.addWidget(box) mainLayout.addItem( QSpacerItem(0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)) self.formGroupVetoes.setLayout(mainLayout) def createFormGroupMapLandscape(self): """Create a QWidget for the landscape map icons.""" self.formGroupMapLandscape = QWidget() mainLayout = QVBoxLayout() box = QGroupBox(_("General")) layout = QFormLayout() container = QHBoxLayout() self.qb_boxStyle = StyleComboBox( scctool.settings.casting_html_dir + "/src/css/mapicons_landscape", "mapicons_landscape") self.qb_boxStyle.connect2WS(self.controller, 'mapicons_landscape') label = QLabel(_("Style:")) label.setMinimumWidth(120) button = QPushButton(_("Show in Browser")) button.clicked.connect(lambda: self.openHTML( scctool.settings.casting_html_dir + "/mapicons_landscape_1.html")) container.addWidget(self.qb_boxStyle, 2) container.addWidget(button, 1) layout.addRow(label, container) self.sb_padding_landscape = QDoubleSpinBox() self.sb_padding_landscape.setRange(0, 50) self.sb_padding_landscape.setDecimals(1) self.sb_padding_landscape.setValue( scctool.settings.config.parser.getfloat("MapIcons", "padding_landscape")) self.sb_padding_landscape.setSuffix(" " + _("Pixel")) self.sb_padding_landscape.valueChanged.connect( lambda x: self.changePadding('landscape', x)) layout.addRow(QLabel(_("Icon Padding:") + " "), self.sb_padding_landscape) box.setLayout(layout) mainLayout.addWidget(box) options = self.controller.matchControl.scopes self.scope_landscape = dict() for idx in range(3): self.scope_landscape[idx] = ScopeGroupBox( _("Icon Set {} Scope".format(idx + 1)), options, f'landscape_{idx + 1}', self.controller, self) self.scope_landscape[idx].dataModified.connect(self.changed) mainLayout.addWidget(self.scope_landscape[idx]) mainLayout.addItem( QSpacerItem(0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)) self.formGroupMapLandscape.setLayout(mainLayout) def createFormGroupIntro(self): """Create forms for websocket connection to intro.""" self.formGroupIntro = QWidget() mainLayout = QVBoxLayout() box = QGroupBox(_("Style")) layout = QHBoxLayout() styleqb = StyleComboBox( scctool.settings.casting_html_dir + "/src/css/intro", "intro") styleqb.connect2WS(self.controller, 'intro') button = QPushButton(_("Show in Browser")) button.clicked.connect(lambda: self.openHTML( scctool.settings.casting_html_dir + "/intro.html")) layout.addWidget(styleqb, 2) layout.addWidget(button, 1) box.setLayout(layout) mainLayout.addWidget(box) self.behaviorIntroBox = QGroupBox(_("Behavior")) layout = QVBoxLayout() self.cb_hardcode_players = QCheckBox( _("Read player names and order in 1vs1 mode from SCCT instead of SC2" )) self.cb_hardcode_players.setChecked( scctool.settings.config.parser.getboolean("Intros", "hardcode_players")) self.cb_hardcode_players.stateChanged.connect(self.changed) layout.addWidget(self.cb_hardcode_players) self.behaviorIntroBox.setLayout(layout) mainLayout.addWidget(self.behaviorIntroBox) self.hotkeyBox = QGroupBox(_("Hotkeys")) layout = QVBoxLayout() self.controller.websocketThread.unregister_hotkeys(force=True) self.cb_single_hotkey = QCheckBox( _("Use a single hotkey for both players")) self.cb_single_hotkey.stateChanged.connect(self.singleHotkeyChanged) layout.addWidget(self.cb_single_hotkey) self.hotkeys = dict() layout.addLayout(self.addHotkey("hotkey_player1", _("Player 1"))) layout.addLayout(self.addHotkey("hotkey_player2", _("Player 2"))) layout.addLayout(self.addHotkey("hotkey_debug", _("Debug"))) self.cb_single_hotkey.setChecked(self.hotkeys['hotkey_player1'].getKey( ) == self.hotkeys['hotkey_player2'].getKey()) self.connectHotkeys() label = QLabel( _("Player 1 is always the player your observer" " camera is centered on at start of a game.")) layout.addWidget(label) self.hotkeyBox.setLayout(layout) mainLayout.addWidget(self.hotkeyBox) self.introBox = QGroupBox(_("Animation")) layout = QFormLayout() self.cb_animation = QComboBox() animation = scctool.settings.config.parser.get("Intros", "animation") currentIdx = 0 idx = 0 options = dict() options['Fly-In'] = _("Fly-In") options['Slide'] = _("Slide") options['Fanfare'] = _("Fanfare") for key, item in options.items(): self.cb_animation.addItem(item, key) if (key == animation): currentIdx = idx idx += 1 self.cb_animation.setCurrentIndex(currentIdx) self.cb_animation.currentIndexChanged.connect(self.changed) label = QLabel(_("Animation:") + " ") label.setMinimumWidth(120) layout.addRow(label, self.cb_animation) self.sb_displaytime = QDoubleSpinBox() self.sb_displaytime.setRange(0, 10) self.sb_displaytime.setDecimals(1) self.sb_displaytime.setValue( scctool.settings.config.parser.getfloat("Intros", "display_time")) self.sb_displaytime.setSuffix(" " + _("Seconds")) self.sb_displaytime.valueChanged.connect(self.changed) layout.addRow(QLabel(_("Display Duration:") + " "), self.sb_displaytime) self.sl_sound = QSlider(Qt.Horizontal) self.sl_sound.setMinimum(0) self.sl_sound.setMaximum(20) self.sl_sound.setValue( scctool.settings.config.parser.getint("Intros", "sound_volume")) self.sl_sound.setTickPosition(QSlider.TicksBothSides) self.sl_sound.setTickInterval(1) self.sl_sound.valueChanged.connect(self.changed) layout.addRow(QLabel(_("Sound Volume:") + " "), self.sl_sound) self.introBox.setLayout(layout) mainLayout.addWidget(self.introBox) self.ttsBox = QGroupBox(_("Text-to-Speech")) layout = QFormLayout() self.cb_tts_active = QCheckBox() self.cb_tts_active.setChecked( scctool.settings.config.parser.getboolean("Intros", "tts_active")) self.cb_tts_active.stateChanged.connect(self.changed) label = QLabel(_("Activate Text-to-Speech:") + " ") label.setMinimumWidth(120) layout.addRow(label, self.cb_tts_active) self.icons = {} self.icons['MALE'] = QIcon(scctool.settings.getResFile('male.png')) self.icons['FEMALE'] = QIcon(scctool.settings.getResFile('female.png')) self.cb_tts_voice = QComboBox() currentIdx = 0 idx = 0 tts_voices = self.controller.tts.getVoices() tts_voice = scctool.settings.config.parser.get("Intros", "tts_voice") for voice in tts_voices: self.cb_tts_voice.addItem(self.icons[voice['ssmlGender']], ' ' + voice['name'], voice['name']) if (voice['name'] == tts_voice): currentIdx = idx idx += 1 self.cb_tts_voice.setCurrentIndex(currentIdx) self.cb_tts_voice.currentIndexChanged.connect(self.changed) layout.addRow(QLabel(_("Voice:") + " "), self.cb_tts_voice) self.ttsBox.setStyleSheet("QComboBox { combobox-popup: 0; }") self.ttsBox.setLayout(layout) mainLayout.addWidget(self.ttsBox) self.sb_tts_pitch = QDoubleSpinBox() self.sb_tts_pitch.setRange(-20, 20) self.sb_tts_pitch.setDecimals(2) self.sb_tts_pitch.setValue( scctool.settings.config.parser.getfloat("Intros", "tts_pitch")) self.sb_tts_pitch.valueChanged.connect(self.changed) layout.addRow(QLabel(_("Pitch:") + " "), self.sb_tts_pitch) self.sb_tts_rate = QDoubleSpinBox() self.sb_tts_rate.setRange(0.25, 4.00) self.sb_tts_rate.setSingleStep(0.1) self.sb_tts_rate.setDecimals(2) self.sb_tts_rate.setValue( scctool.settings.config.parser.getfloat("Intros", "tts_rate")) self.sb_tts_rate.valueChanged.connect(self.changed) layout.addRow(QLabel(_("Rate:") + " "), self.sb_tts_rate) self.cb_tts_scope = QComboBox() scope = scctool.settings.config.parser.get("Intros", "tts_scope") currentIdx = 0 idx = 0 options = self.controller.tts.getOptions() for key, item in options.items(): self.cb_tts_scope.addItem(item['desc'], key) if (key == scope): currentIdx = idx idx += 1 self.cb_tts_scope.setCurrentIndex(currentIdx) self.cb_tts_scope.currentIndexChanged.connect(self.changed) layout.addRow(QLabel(_("Line:") + " "), self.cb_tts_scope) self.sl_tts_sound = QSlider(Qt.Horizontal) self.sl_tts_sound.setMinimum(0) self.sl_tts_sound.setMaximum(20) self.sl_tts_sound.setValue( scctool.settings.config.parser.getint("Intros", "tts_volume")) self.sl_tts_sound.setTickPosition(QSlider.TicksBothSides) self.sl_tts_sound.setTickInterval(1) self.sl_tts_sound.valueChanged.connect(self.changed) layout.addRow(QLabel(_("Sound Volume:") + " "), self.sl_tts_sound) text = _( "Text-to-Speech provided by Google-Cloud is paid for " "by StarCraft Casting Tool Patrons. To keep this service up " "consider becoming a <a href='{patreon}'>Patron</a> yourself. " "You can test all voices at {tts}.") patreon = 'https://www.patreon.com/StarCraftCastingTool' url = 'https://cloud.google.com/text-to-speech/' tts = "<a href='{}'>cloud.google.com/text-to-speech</a>" tts = tts.format(url) label = QLabel(text.format(patreon=patreon, tts=tts)) label.setAlignment(Qt.AlignJustify) label.setOpenExternalLinks(True) label.setWordWrap(True) label.setMargin(5) layout.addRow(label) mainLayout.addItem( QSpacerItem(0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)) self.formGroupIntro.setLayout(mainLayout) def createButtonGroup(self): """Create buttons.""" try: layout = QHBoxLayout() layout.addWidget(QLabel("")) buttonCancel = QPushButton(_('Cancel')) buttonCancel.clicked.connect(self.closeWindow) layout.addWidget(buttonCancel) buttonSave = QPushButton(_('&Save && Close')) buttonSave.setToolTip(_("Shortcut: {}").format("Ctrl+S")) self.shortcut = QShortcut(QKeySequence("Ctrl+S"), self) self.shortcut.setAutoRepeat(False) self.shortcut.activated.connect(self.saveCloseWindow) buttonSave.clicked.connect(self.saveCloseWindow) layout.addWidget(buttonSave) self.buttonGroup = layout except Exception: module_logger.exception("message") def changed(self, *values): """Handle changed data.""" self.__dataChanged = True def saveData(self): """Save the data to config.""" if (self.__dataChanged): self.saveWebsocketdata() maps = list() for i in range(self.maplist.count()): maps.append(str(self.maplist.item(i).text()).strip()) self.controller.mapstatsManager.setCustomMapPool(maps) self.controller.mapstatsManager.setMapPoolType( self.cb_mappool.currentIndex()) scctool.settings.config.parser.set( "Mapstats", "autoset_next_map", str(self.cb_autoset_map.isChecked())) scctool.settings.config.parser.set( "Mapstats", "mark_played", str(self.cb_mark_played.isChecked())) scctool.settings.config.parser.set( "Mapstats", "mark_vetoed", str(self.cb_mark_vetoed.isChecked())) scctool.settings.config.parser.set( "Mapstats", "sort_maps", str(self.cb_sort_maps.isChecked())) scctool.settings.config.parser.set( "Intros", "hardcode_players", str(self.cb_hardcode_players.isChecked())) self.controller.mapstatsManager.sendMapPool() self.mainWindow.updateAllMapButtons() for idx in range(3): scctool.settings.config.parser.set( "MapIcons", "scope_box_{}".format(idx + 1), self.scope_box[idx].getScope()) scctool.settings.config.parser.set( "MapIcons", "scope_landscape_{}".format(idx + 1), self.scope_landscape[idx].getScope()) self.controller.matchMetaDataChanged() self.__dataChanged = False # self.controller.refreshButtonStatus() def saveWebsocketdata(self): """Save Websocket data.""" for ident, key in self.hotkeys.items(): string = scctool.settings.config.dumpHotkey(key.getKey()) scctool.settings.config.parser.set("Intros", ident, string) scctool.settings.config.parser.set("Intros", "display_time", str(self.sb_displaytime.value())) scctool.settings.config.parser.set("Intros", "sound_volume", str(self.sl_sound.value())) scctool.settings.config.parser.set( "Intros", "animation", self.cb_animation.currentData().strip()) scctool.settings.config.parser.set( "Intros", "tts_voice", '' if self.cb_tts_voice.currentData() is None else self.cb_tts_voice.currentData().strip()) scctool.settings.config.parser.set( "Intros", "tts_scope", self.cb_tts_scope.currentData().strip()) scctool.settings.config.parser.set("Intros", "tts_active", str(self.cb_tts_active.isChecked())) scctool.settings.config.parser.set("Intros", "tts_volume", str(self.sl_tts_sound.value())) scctool.settings.config.parser.set("Intros", "tts_pitch", str(self.sb_tts_pitch.value())) scctool.settings.config.parser.set("Intros", "tts_rate", str(self.sb_tts_rate.value())) def openHTML(self, file): """Open file in browser.""" self.controller.openURL(scctool.settings.getAbsPath(file)) def changePadding(self, scope, padding): """Change the padding.""" if scope == 'vetoes': scctool.settings.config.parser.set("Vetoes", "padding", str(padding)) self.controller.websocketThread.changePadding("vetoes", padding) else: scctool.settings.config.parser.set("MapIcons", f"padding_{scope}", str(padding)) self.controller.websocketThread.changePadding( f"mapicons_{scope}", padding) def saveCloseWindow(self): """Save and close window.""" self.saveData() self.closeWindow() def closeWindow(self): """Close window without save.""" self.passEvent = True self.close() def closeEvent(self, event): """Handle close event.""" try: if (not self.__dataChanged): self.controller.updateHotkeys() event.accept() return if (not self.passEvent): if (self.isMinimized()): self.showNormal() buttonReply = QMessageBox.question( self, _('Save data?'), _("Do you want to save the data?"), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if buttonReply == QMessageBox.Yes: self.saveData() self.controller.updateHotkeys() event.accept() except Exception: module_logger.exception("message")
class WidgetGallery(QDialog): def __init__(self, parent=None): super(WidgetGallery, self).__init__(parent) self.originalPalette = QApplication.palette() styleComboBox = QComboBox() styleComboBox.addItems(QStyleFactory.keys()) styleLabel = QLabel("&Style:") styleLabel.setBuddy(styleComboBox) self.useStylePaletteCheckBox = QCheckBox( "&Use style's standard palette") self.useStylePaletteCheckBox.setChecked(True) disableWidgetsCheckBox = QCheckBox("&Disable widgets") self.createTopLeftGroupBox() self.createTopRightGroupBox() self.createBottomLeftTabWidget() self.createBottomRightGroupBox() mainLayout = QGridLayout() mainLayout.addWidget(self.topLeftGroupBox, 1, 0) mainLayout.addWidget(self.topRightGroupBox, 1, 1) mainLayout.addWidget(self.bottomLeftTabWidget, 2, 0) mainLayout.addWidget(self.bottomRightGroupBox, 2, 1) mainLayout.setRowStretch(1, 1) mainLayout.setRowStretch(2, 1) mainLayout.setColumnStretch(0, 1) mainLayout.setColumnStretch(1, 1) self.setLayout(mainLayout) self.setWindowTitle("Bridge2Africa") self.changeStyle('Windows') def changeStyle(self, styleName): QApplication.setStyle(QStyleFactory.create(styleName)) self.changePalette() def changePalette(self): if (self.useStylePaletteCheckBox.isChecked()): QApplication.setPalette(QApplication.style().standardPalette()) else: QApplication.setPalette(self.originalPalette) def createTopLeftGroupBox(self): self.topLeftGroupBox = QGroupBox("Select Mode") radioButton1 = QRadioButton("Tutorial Mode") radioButton2 = QRadioButton("Active Mode: Both audio and Braille") radioButton3 = QRadioButton("Passive Mode: Braille") radioButton1.setChecked(True) checkBox = QCheckBox("Include Assessibility Rating in Search Results") checkBox.setTristate(True) checkBox.setCheckState(Qt.PartiallyChecked) layout = QVBoxLayout() layout.addWidget(radioButton1) layout.addWidget(radioButton2) layout.addWidget(radioButton3) layout.addWidget(checkBox) layout.addStretch(1) self.topLeftGroupBox.setLayout(layout) def createTopRightGroupBox(self): self.topRightGroupBox = QGroupBox("Some sample buttons") nameLabel_1 = QLabel(self) nameLabel_1.setText('Read Braille:') line_1 = QLineEdit(self) line_1.setText("test") nameLabel_2 = QLabel(self) nameLabel_2.setText('Activate Arduino:') line_2 = QLineEdit(self) nameLabel_3 = QLabel(self) nameLabel_3.setText('Navgiation:') line_3 = QLineEdit(self) nameLabel_4 = QLabel(self) nameLabel_4.setText('Acccessibility:') line_4 = QLineEdit(self) nameLabel_5 = QLabel(self) nameLabel_5.setText('Hierarchy:') line_5 = QLineEdit(self) nameLabel_6 = QLabel(self) nameLabel_6.setText('Minus Index:') line_6 = QLineEdit(self) nameLabel_7 = QLabel(self) nameLabel_7.setText('Plus Index:') line_7 = QLineEdit(self) nameLabel_8 = QLabel(self) nameLabel_8.setText('Speak:') line_8 = QLineEdit(self) nameLabel_9 = QLabel(self) nameLabel_9.setText('Braille Read Quit:') line_9 = QLineEdit(self) nameLabel_10 = QLabel(self) nameLabel_10.setText('Braille Read Contiue:') line_10 = QLineEdit(self) layout = QVBoxLayout() layout.addWidget(nameLabel_1) layout.addWidget(line_1) layout.addWidget(nameLabel_2) layout.addWidget(line_2) layout.addWidget(nameLabel_3) layout.addWidget(line_3) layout.addWidget(nameLabel_4) layout.addWidget(line_4) layout.addWidget(nameLabel_5) layout.addWidget(line_5) layout.addWidget(nameLabel_6) layout.addWidget(line_6) layout.addWidget(nameLabel_7) layout.addWidget(line_7) layout.addWidget(nameLabel_8) layout.addWidget(line_8) layout.addWidget(nameLabel_9) layout.addWidget(line_9) layout.addWidget(nameLabel_10) layout.addWidget(line_10) layout.addStretch(1) self.topRightGroupBox.setLayout(layout) def createBottomLeftTabWidget(self): self.bottomLeftTabWidget = QTabWidget() self.bottomLeftTabWidget.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Ignored) tab1 = QWidget() tableWidget = QTableWidget(10, 10) tab1hbox = QHBoxLayout() tab1hbox.setContentsMargins(5, 5, 5, 5) tab1hbox.addWidget(tableWidget) tab1.setLayout(tab1hbox) tab2 = QWidget() textEdit = QTextEdit() textEdit.setPlainText( "Test your Braille display and audio output. \n Enter sample text here.\n" ) tab2hbox = QHBoxLayout() tab2hbox.setContentsMargins(5, 5, 5, 5) tab2hbox.addWidget(textEdit) tab2.setLayout(tab2hbox) self.bottomLeftTabWidget.addTab(tab2, "Calibrate") def createBottomRightGroupBox(self): self.bottomRightGroupBox = QGroupBox("Audio Speed") lineEdit = QLineEdit('s3cRe7') lineEdit.setEchoMode(QLineEdit.Password) spinBox = QSpinBox(self.bottomRightGroupBox) spinBox.setValue(50) slider = QSlider(Qt.Horizontal, self.bottomRightGroupBox) slider.setValue(40) scrollBar = QScrollBar(Qt.Horizontal, self.bottomRightGroupBox) scrollBar.setValue(60) dial = QDial(self.bottomRightGroupBox) dial.setValue(30) dial.setNotchesVisible(True) layout = QGridLayout() layout.addWidget(spinBox, 1, 0, 1, 2) layout.addWidget(slider, 3, 0) layout.addWidget(scrollBar, 4, 0) layout.addWidget(dial, 3, 1, 2, 1) self.bottomRightGroupBox.setLayout(layout)
class MainWindow(QMainWindow): """Main Window for the application""" def __init__(self): super().__init__() self.tabs = QTabWidget(self) self.tabs.setMovable(True) self.tabs.setTabsClosable(True) self.tabs.tabCloseRequested.connect(self.close_tab) self.setCentralWidget(self.tabs) self.last_open_directory = '' self.last_save_directory = '' self.setWindowTitle('Melee Dat Editor') self.setWindowIcon(QIcon('resources/icon-256.ico')) self.statusBar().showMessage('') # enable status bar self.setup_menus() self.setAcceptDrops(True) self.resize(QSize(640, 480)) self.show() def setup_menus(self): menubar = self.menuBar() style = self.style() file_menu = menubar.addMenu('File') open_action = file_menu.addAction( style.standardIcon(QStyle.SP_DialogOpenButton), 'Open PlXx.dat...') open_action.setShortcut(QKeySequence('Ctrl+O')) open_action.triggered.connect(self.open_file_dialog) # open_action.setStatusTip('Open a dat file') save_action = file_menu.addAction( style.standardIcon(QStyle.SP_DialogSaveButton), 'Save') save_action.setShortcut(QKeySequence('Ctrl+S')) save_action.triggered.connect(self.save) saveas_action = file_menu.addAction( style.standardIcon(QStyle.SP_DialogSaveButton), 'Save As...') saveas_action.setShortcut(QKeySequence('Ctrl+Shift+S')) saveas_action.triggered.connect(self.saveas) file_menu.addSeparator() reload_action = file_menu.addAction( style.standardIcon(QStyle.SP_BrowserReload), 'Reload From Disk') reload_action.triggered.connect(self.reload) close_action = file_menu.addAction( style.standardIcon(QStyle.SP_DialogCloseButton), 'Close') close_action.triggered.connect(self.close_current) help_menu = menubar.addMenu('Help') about_action = help_menu.addAction( style.standardIcon(QStyle.SP_MessageBoxInformation), 'About...') about_action.triggered.connect(self.about) def open_file_dialog(self): """Spawn an open file dialog and open the selected dat file""" fname = QFileDialog.getOpenFileName( self, 'Open Moveset File', self.last_open_directory, 'Moveset dat files (*.dat);;All Files (*.*)')[0] if fname: self.open_file(fname) def open_file(self, fname): # TODO: when DatEx is implemented, replace MoveSetDatFile # constructor with a factory that examines the file and returns # an instance of the correct class, standard vs ex (vs other?) # and probably also updates old ex versions to newer ones # if necessary try: e = MovesetDatEditor(fname, self.last_save_directory, self) except Exception: import traceback print(traceback.format_exc()) mbox = QMessageBox(self) mbox.setWindowTitle(self.windowTitle()) mbox.setText(f"Error opening {fname}.\n\n" + traceback.format_exc()) mbox.exec_() return self.last_open_directory = os.path.dirname(fname) self.tabs.addTab(e, os.path.basename(fname)) self.tabs.setCurrentWidget(e) self.updateGeometry() self.resize(self.sizeHint()) QApplication.instance().processEvents() def save(self): if self.current_editor(): self.current_editor().save() def saveas(self): if self.current_editor(): self.current_editor().saveas() def reload(self): if self.current_editor(): self.current_editor().reload() def current_editor(self): return self.tabs.currentWidget() def close_tab(self, index): e = self.tabs.widget(index) self.tabs.removeTab(index) if e: e.close() def close_current(self): self.close_tab(self.tabs.currentIndex()) def dragEnterEvent(self, event): if event.mimeData().hasUrls(): event.accept() else: event.ignore() def dropEvent(self, event): for url in event.mimeData().urls(): fname = url.toLocalFile() if os.path.isfile(fname): self.open_file(fname) def about(self): mbox = QMessageBox(self) mbox.setText(ABOUT_TEXT) mbox.setWindowTitle(self.windowTitle()) mbox.exec_()
class pl_main(QWidget): def __init__(self): QWidget.__init__(self) self.main_vbox = QVBoxLayout() self.setWindowIcon(icon_get("preferences-system")) self.setWindowTitle( _("Luminescence editor") + " (https://www.gpvdm.com)") toolbar = QToolBar() toolbar.setIconSize(QSize(48, 48)) spacer = QWidget() spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) toolbar.addWidget(spacer) self.help = QAction(icon_get("help"), _("Help"), self) self.help.setStatusTip(_("Help")) self.help.triggered.connect(self.callback_help) toolbar.addAction(self.help) self.main_vbox.addWidget(toolbar) self.notebook = QTabWidget() css_apply(self, "tab_default.css") self.main_vbox.addWidget(self.notebook) self.setLayout(self.main_vbox) self.notebook.setTabsClosable(True) self.notebook.setMovable(True) bar = QHTabBar() bar.setStyleSheet("QTabBar::tab { height: 35px; width: 200px; }") self.notebook.setTabBar(bar) self.notebook.setTabPosition(QTabWidget.West) global_object_register("pl_update", self.update) self.update() def update(self): self.notebook.clear() files = epitaxy_get_dos_files() for i in range(0, epitaxy_get_layers()): pl_file = epitaxy_get_pl_file(i) if pl_file.startswith("pl") == True: widget = QWidget() name = _("Luminescence of ") + epitaxy_get_name(i) widget = tab_class(pl_file + ".inp") self.notebook.addTab(widget, name) def callback_help(self, widget): webbrowser.open('http://www.gpvdm.com/man/index.html') def help(self): help_window().help_set_help([ "tab.png", _("<big><b>Luminescence</b></big>\nIf you set 'Turn on luminescence' to true, the simulation will assume recombination is a raditave process and intergrate it to produce Voltage-Light intensity curves (lv.dat). Each number in the tab tells the model how efficient each recombination mechanism is at producing photons." ) ])