def setupCommandGUI(self, commands): for name, node in sorted(commands.items(), key=natural_keys): row = self.ui.gridLayout.rowCount() + 1 label = QLabel(self.ui.groupBox) if not node.category: label.setText((' ' * node.level) + node.name.replace('___', ' ')) else: label.setText((' ' * node.level) + '<b>' + node.name.replace('___', ' ') + '</b>') label.setObjectName('lableCommand_' + node.name) if not node.category: buttonStart = QPushButton(self.ui.groupBox) buttonStart.setText('Start') buttonStart.setObjectName('pushButtonCommand_' + node.name + '_start') buttonStart.clicked.connect(partial(self.onStart, name)) buttonStop = QPushButton(self.ui.groupBox) buttonStop.setText('Stop') buttonStop.setObjectName('pushButtonCommand_' + node.name + '_stop') buttonStop.clicked.connect(partial(self.onStop, name)) buttonRestart = QPushButton(self.ui.groupBox) buttonRestart.setText('Restart') buttonRestart.setObjectName('pushButtonCommand_' + node.name + '_restart') buttonRestart.clicked.connect(partial(self.onRestart, name)) progressBar = None if node.name in self.progressTopics: progressBar = QProgressBar(self.ui.groupBox) progressBar.setObjectName('progressBarCommand_' + node.name) progressBar.setValue(0) progressBar.setMaximum(100) progressBar.setMaximumWidth(300) # if node.level == 0 or (node.level == 1 and node.parent.category): # buttonStart.setEnabled(True) # buttonStop.setEnabled(True) # buttonRestart.setEnabled(True) # else: # buttonStart.setEnabled(False) # buttonStop.setEnabled(False) # buttonRestart.setEnabled(False) self.ui.gridLayout.addWidget(buttonStart, row, 1) self.ui.gridLayout.addWidget(buttonStop, row, 2) self.ui.gridLayout.addWidget(buttonRestart, row, 3) if not progressBar is None: self.ui.gridLayout.addWidget(progressBar, row, 4) self.ui.gridLayout.addWidget(label, row, 0) self.setupCommandGUI(node.childs)
class MSMainWindow(QMainWindow): """Gui of the main window""" # MAX_RECENT_FILES = 10 # start putting links spyder numpy scipy et tutti quanti links = ( "http://numpy.scipy.org/", "http://packages.python.org/spyder/", "http://www.riverbankcomputing.co.uk/software/pyqt/intro", ) pluginPath = path.normcase("pluginmanager/plugins/") def __init__(self, availablePlugins): """ Constructor with all the models needed setup menus """ QMainWindow.__init__(self) self.setDockOptions(QMainWindow.VerticalTabs | QMainWindow.AnimatedDocks) self.plugins = availablePlugins self.pluginsInst = [] settings = QSettings( "INRA/INSA", "-".join([QApplication.instance().APPLICATION_NAME_STR, QApplication.instance().VERSION_STR]) ) self.recentFiles = list(settings.value("RecentFiles").toStringList()) self.setStyleSheet(stylesheet) self.pipeline = MSPipelineToolBar("Pipeline toolbar", parent=self) self.addToolBar(0x1, self.pipeline) self._setupModels() self._setupUi() self._setupMenus() def _setupModels(self): """ Warning:Causes segfault when horizontal labels set to True on aura peu etre a la fin un model par sampleList c'est ce qui parait le plus logique """ # drag and drop table sample self.sampleModel = QStandardItemModel(self) self.sampleModel.setHorizontalHeaderLabels(["Sample", "Class"]) # treeView1 self.spectraModel = QStandardItemModel(self) # treeview2 self.peakModel = QStandardItemModel(self) # treeview3 self.clusterModel = QStandardItemModel(self) def _setupMenus(self): # file self.fileMenu = QMenu("&File") self.fileMenu.setTearOffEnabled(True) self.op = QMenu("&Open...", self.fileMenu) self.op.setIcon(QIcon(path.normcase("gui/icons/fileopen.png"))) open_ = QAction("&Open rawfiles", self) open_.setToolTip("Open an mzXML or netCDF file") open_.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_O)) open_icon = QIcon(path.normcase("gui/icons/fileopen.png")) open_.setIcon(open_icon) self.op.addAction(open_) load_ = QAction("&Open projects...", self) load_.setToolTip("load binary file containing saved objects") load_.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_S)) load_icon = QIcon(QPixmap(path.normcase("gui/icons/project_open.png"))) load_.setIcon(load_icon) self.op.addAction(load_) self.fileMenu.addMenu(self.op) save_ = QAction("&Save...", self) save_.setToolTip("save the actual application model") save_.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_S)) save_icon = QIcon(path.normcase("gui/icons/save_all.png")) save_.setIcon(save_icon) self.fileMenu.addAction(save_) pkl = QAction("&load a peaklist", self) # TODO:load peaklist pkl.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_P)) pkl.setToolTip("load a peaklist and process it") pkl.setIcon(QIcon(path.normcase("gui/icons/featuredetect.png"))) self.fileMenu.addAction(pkl) convert_ = QAction("&Convert...", self) convert_.setEnabled(False) convert_.setToolTip("Convert a .wiff file if Analyst(c) is installed") convert_icon = QIcon(path.normcase("gui/icons/goto.png")) convert_.setIcon(convert_icon) self.fileMenu.addAction(convert_) a = self.fileMenu.addAction(QIcon(path.normcase("gui/icons/process.png")), "&Launch a batch") a.setEnabled(False) b = self.fileMenu.addAction(QIcon(path.normcase("gui/icons/process.png")), "&Merge") b.setToolTip("Merge MRM file") # b.setEnabled(False) self.fileMenu.addSeparator() # # for i in xrange(self.MAX_RECENT_FILES): # a = QAction('', self) # a.setVisible(False) # self.fileMenu.addAction(a) # # for i in xrange(min(self.MAX_RECENT_FILES, len(self.recentFiles))): # self.fileMenu.actions()[5+i].setVisible(True) # self.fileMenu.actions()[5+i].setText(self.recentFiles[i].split('/')[-1]) exit_action = QAction("&Exit", self) exit_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_Q)) exit_action.setIcon(QIcon(QPixmap(path.normcase("gui/icons/exit.png")))) self.fileMenu.addAction(exit_action) self.menuBar().addMenu(self.fileMenu) self.editMenu = QMenu("&Edit") self.editMenu.setTearOffEnabled(True) self.editMenu.addAction(QIcon(path.normcase("gui/icons/edit_undo.png")), "&Undo...") self.editMenu.addAction(QIcon(path.normcase("gui/icons/edit_redo.png")), "&Redo...") self.editMenu.actions()[0].setEnabled(False) self.editMenu.actions()[1].setEnabled(False) self.editMenu.addSeparator() self.editMenu.addAction(QIcon(path.normcase("gui/icons/run.png")), "&Preferences") self.exportMenu = QMenu("&Export...") self.exportMenu.setIcon(QIcon(path.normcase("gui/icons/file_export.png"))) self.exportMenu.addAction("&Peaklist") self.exportMenu.addAction("&Clusters intensity matrix") self.editMenu.addMenu(self.exportMenu) self.menuBar().addMenu(self.editMenu) # view self.viewMenu = QMenu("&View") self.viewMenu.setTearOffEnabled(True) self.viewMenu.addAction( QIcon(path.normcase("gui/icons/window_duplicate")), "&Cascade View", self.mdiArea.cascadeSubWindows, QKeySequence(Qt.CTRL + Qt.Key_K), ) self.viewMenu.addAction( QIcon(path.normcase("gui/icons/view_icon")), "&Title View", self.mdiArea.tileSubWindows, QKeySequence(Qt.CTRL + Qt.Key_N), ) self.viewMenu.addAction( QIcon(path.normcase("gui/icons/stop_process.png")), "&Close all subWindows", self.mdiArea.closeAllSubWindows, QKeySequence(Qt.CTRL + Qt.Key_W), ) self.plotting = QMenu("&Plotting...") self.plotting.setIcon(QIcon(QPixmap(path.normcase("gui/icons/plot.png")))) self.plotting.addAction("&3D Plot") # self.plotting.addAction("&Cytoscape web") self.plotting.addAction("&Spectrogram Plot") # self.multiplePlot = QAction("&Visualize Raw/Treated Data", self) # self.multiplePlot.setCheckable(True) # self.multiplePlot.setEnabled(False) # self.sub_plot_.addAction(self.multiplePlot) self.viewMenu.addMenu(self.plotting) self.viewMenu.addSeparator() self.show_hide = QMenu("&Show/Hide") m = self.createPopupMenu() m.setTitle("&Show/Hide") self.viewMenu.addMenu(m) # self.pref = QMenu("&Preferences") # self.pref.addAction(self.multiplePlot) # self.viewMenu.addMenu(self.pref) self.menuBar().addMenu(self.viewMenu) # algorithm self.algoMenu = QMenu("&Algorithm") self.algoMenu.setTearOffEnabled(True) self.preProcessing = QMenu("&PreProcessing(experimental)") self.preProcessing.addAction("&Smoothing raw data...") self.preProcessing.addAction("&Cut off raw data...") self.preProcessing.addAction("&Calibration (mz dimension)") self.preProcessing.addAction("&Resize sample...") self.algoMenu.addMenu(self.preProcessing) self.peakPickingMenu = QMenu("&Peack Picking & Alignement(XCMS)", self) self.peakPickingMenu.setIcon(QIcon(path.normcase("gui/icons/pickedpeakicon.png"))) matched = QAction("&MatchedFiltered", self) matched.setIcon(QIcon(path.normcase("gui/icons/RLogo"))) matched.setToolTip("Peak Detection and Integration using MatchedFiltered algorithm") self.peakPickingMenu.addAction(matched) centwave = QAction("&CentWave", self) centwave.setIcon(QIcon(path.normcase("gui/icons/RLogo"))) centwave.setToolTip("Peak Detection and Integration using CentWave algorithm") self.peakPickingMenu.addAction(centwave) # peak_.setShortcut(.QKeySequence(CTRL + Key_P)) # peak_icon=.QIcon(.QPixmap(path.normcase("gui/icons/pickedpeakicon.png"))) # peak_.setIcon(peak_icon) self.algoMenu.addMenu(self.peakPickingMenu) self.alignment = QMenu("&Alignment") self.alignment.setIcon(QIcon(path.normcase("gui/icons/format_indent_more.png"))) self.alignment.addAction("&Polynomial fitting(exp)") self.alignment.addAction("&DynamicTimeWarping") self.alignment.addAction("&ObiWarp") self.alignment.actions()[2].setEnabled(False) self.algoMenu.addMenu(self.alignment) self.algoMenu.addAction("Normalization") clust_ = QAction("&Clustering", self) clust_.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_L)) clust_icon = QIcon(QPixmap(path.normcase("gui/icons/cluster.png"))) clust_.setIcon(clust_icon) self.algoMenu.addAction(clust_) id_ = QAction("&Identification", self) id_.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_I)) id_.setToolTip("Try to identify peaks with several methods") id_.setIcon(QIcon(QPixmap(path.normcase("gui/icons/findcompound.png")))) self.algoMenu.addAction(id_) self.menuBar().addMenu(self.algoMenu) # tools self.toolsMenu = QMenu("&Tools") self.toolsMenu.setTearOffEnabled(True) web = QAction("&Web Browser", self) web.setIcon(QIcon(QPixmap(path.normcase("gui/icons/applications_internet.png")))) self.toolsMenu.addAction(web) # cyto = QAction("&cytoscape", self) # cyto_icon =QIcon(QPixmap(path.normcase("gui/icons/cytoscape.jpeg"))) # cyto.setIcon(cyto_icon) # self.toolsMenu.addAction(cyto) editor = QAction("&Editor", self) editor.setIcon(QIcon(QPixmap(path.normcase("gui/icons/document_sign.png")))) self.toolsMenu.addAction(editor) pet = QAction("&Short Periodic Table", self) pet.setIcon(QIcon(QPixmap(path.normcase("gui/icons/pet.jpg")))) self.toolsMenu.addAction(pet) self.menuBar().addMenu(self.toolsMenu) # plugins self.pluginMenu = QMenu("&Plugins") self.pluginMenu.setTearOffEnabled(True) instPl = QAction("&Install a plugin", self) instPl.setIcon(QIcon(path.normcase("gui/icons/pluginInstall.png"))) self.pluginMenu.addAction(instPl) self.launchingMenu = QMenu("&Launch PLugins", self) self.launchingMenu.setIcon(QIcon(path.normcase("gui/icons/plugin"))) for plug in self.plugins: # fullname="".join([self.pluginPath, str(plug)]) mod = imp.load_source(self.__module__, plug) if mod.autoActivation: qApp = QApplication.instance() name = getattr(mod, "className") cls = getattr(mod, name) p = cls(qApp.model, self, parent=self) # p=qApp.pluginManager.loadPlugin(qApp.model, self, plug.split('/')[-1]) self.pluginsInst.append(p) else: self.launchingMenu.addAction(plug.split("/")[-1]) self.pluginMenu.addMenu(self.launchingMenu) self.pluginMenu.addAction(QIcon(path.normcase("gui/icons/process_stop.png")), "&Remove loaded Plugin") self.menuBar().addMenu(self.pluginMenu) # about self.aboutMenu = QMenu("&About") self.aboutMenu.setTearOffEnabled(True) metms = QAction(QIcon(path.normcase("gui/icons/deluge.png")), "&about metMS...", self) self.aboutMenu.addAction(metms) pyqt = QAction("&about PyQt4...", self) pyqt_icon = QIcon(QPixmap(path.normcase("gui/icons/logo_QT4.png"))) pyqt.setIcon(pyqt_icon) self.aboutMenu.addAction(pyqt) metms = QAction("&metMS Documentation", self) metms_icon = QIcon(QPixmap(path.normcase("gui/icons/deluge.png"))) metms.setIcon(metms_icon) self.aboutMenu.addAction(metms) self.menuBar().addMenu(self.aboutMenu) def _setupUi(self, background=None): """ Make the GUI """ # mdi self.mdiArea = MSMdiArea(self) self.mdiArea.setBackground(QBrush(QPixmap(path.normcase("gui/icons/blac2.png")))) # QColor(Qt.blue).darker())) self.setCentralWidget(self.mdiArea) # sample dock widget self.sampleDockWidget = QDockWidget("Samples", self) # sampleWidget = QWidget() self.sampleTableView = MSDragFromTableView() self.sampleTableView.setModel(self.sampleModel) self.sampleTableView.setSelectionBehavior(1) self.sampleTableView.verticalHeader().hide() self.sampleTableView.verticalHeader().setDefaultSectionSize(15) self.sampleTableView.horizontalHeader().setDefaultSectionSize(150) self.sampleDockWidget.setWidget(self.sampleTableView) # sampleWidget) self.sampleDockWidget.visible = True # workflow dock self.workflowDockWidget = QDockWidget("Visualizer", self) self.workflowDockWidget.visible = True a = QWidget(self) v = QVBoxLayout(a) q = QToolBar() # self.workingSample = QLabel("Working Sample:None") # q.addWidget(self.workingSample) q.addWidget(QLabel("ppm :")) self.ppmEditer = QDoubleSpinBox() self.usePpm = QCheckBox("use ?") q.addWidget(self.ppmEditer) q.addWidget(self.usePpm) q.addSeparator() self.removeButton = QToolButton(self) self.removeButton.setIcon(QIcon(path.normcase("gui/icons/delete.png"))) q.addWidget(self.removeButton) self.markAsGood = QAction(QIcon(path.normcase("gui/icons/button_ok.png")), "mark peak as good", self) self.markAsBad = QAction(QIcon(path.normcase("gui/icons/stop.png")), "mark peak as bad", self) self.hideItem = QAction(QIcon(path.normcase("gui/icons/list_remove.png")), "Hide Item", self) q.addAction(self.markAsGood) q.addAction(self.markAsBad) q.addAction(self.hideItem) v.addWidget(q) self.tabWidget = QTabWidget() self.tab = QWidget() verticalLayout = QVBoxLayout(self.tab) self.treeView = MSToDropTableView() self.treeView.verticalHeader().setDefaultSectionSize(20) self.treeView.setModel(self.spectraModel) self.spectraLabel = QLabel("Sample: None") verticalLayout.addWidget(self.treeView) verticalLayout.addWidget(self.spectraLabel) self.tabWidget.addTab(self.tab, QIcon(path.normcase("gui/icons/spectrumicon.png")), "Spectra") self.tab_2 = QWidget() verticalLayout_4 = QVBoxLayout(self.tab_2) self.treeView_2 = MSToDropTableView() # MSTreeView(self.tab_2)# QTableView(self)# self.treeView_2.verticalHeader().setDefaultSectionSize(20) self.treeView_2.setModel(self.peakModel) self.peakLabel = QLabel("Sample: None") verticalLayout_4.addWidget(self.treeView_2) verticalLayout_4.addWidget(self.peakLabel) self.tabWidget.addTab(self.tab_2, QIcon(path.normcase("gui/icons/peakicon.png")), "Peaks List") self.tab_3 = QWidget() verticalLayout_5 = QVBoxLayout(self.tab_3) self.treeView_3 = MSToDropTreeView() self.treeView_3.setAnimated(True) self.treeView_3.setModel(self.clusterModel) self.clusterLabel = QLabel("Sample: None") verticalLayout_5.addWidget(self.treeView_3) verticalLayout_5.addWidget(self.clusterLabel) self.tabWidget.addTab(self.tab_3, QIcon(path.normcase("gui/icons/clustering.png")), "Clusters") self.tabWidget.setCurrentIndex(0) for l in (self.spectraLabel, self.peakLabel, self.clusterLabel): l.setAutoFillBackground(True) v.addWidget(self.tabWidget) self.workflowDockWidget.setWidget(a) self.addDockWidget(Qt.DockWidgetArea(0x2), self.workflowDockWidget) from gui.MetBaseGui import MSIsoCalculator self.isoCalc = MSIsoCalculator(self) self.isoCalcDockWidget = QDockWidget("isotopes calculation", self) self.isoCalcDockWidget.setWidget(self.isoCalc) self.addDockWidget(Qt.DockWidgetArea(0x2), self.isoCalcDockWidget) self.isoCalcDockWidget.setVisible(False) self.isoCalcDockWidget.visible = False from gui.MetBaseGui import FormulaGenerator self.generator = FormulaGenerator(self) self.generatorDockWidget = QDockWidget("formula generator", self) self.generatorDockWidget.setWidget(self.generator) self.addDockWidget(Qt.DockWidgetArea(0x2), self.generatorDockWidget) self.generatorDockWidget.setVisible(False) self.generatorDockWidget.visible = False self.compoundTreeView = MSCompoundTreeView(self) self.compoundDockWidget = QDockWidget("Compounds", self) self.compoundDockWidget.setWidget(self.compoundTreeView) self.addDockWidget(Qt.DockWidgetArea(0x2), self.compoundDockWidget) self.compoundDockWidget.setVisible(False) self.compoundDockWidget.visible = False self.comparativeTableView = QTableView(self) self.comparativeTableView.horizontalHeader().setStretchLastSection(True) self.comparativeTableView.verticalHeader().setDefaultSectionSize(20) self.comparativeDock = QDockWidget("Comparative View", self) self.comparativeDock.setWidget(self.comparativeTableView) self.addDockWidget(Qt.DockWidgetArea(0x8), self.comparativeDock) self.comparativeDock.setVisible(False) self.comparativeDock.visible = False self.tabifyDockWidget(self.compoundDockWidget, self.isoCalcDockWidget) self.tabifyDockWidget(self.isoCalcDockWidget, self.workflowDockWidget) self.tabifyDockWidget(self.workflowDockWidget, self.generatorDockWidget) # set the end # WARNING: possible that the internal shell widget cause random segfault # with the error of QObject::killTimers...? not sure ! self.shell = QWidget() # InternalShell(namespace={'metms': QApplication.instance()}, # parent=self, # multithreaded=False) self.shellDock = QDockWidget("Python Shell", self) self.shellDock.setWindowIcon(QIcon(path.normcase("gui/icons/stop.png"))) self.shellDock.setWidget(self.shell) self.shellDock.setMinimumWidth(255) self.shellDock.visible = True self.addDockWidget(0x2, self.shellDock) self.addDockWidget(0x2, self.sampleDockWidget) self.tabifyDockWidget(self.shellDock, self.sampleDockWidget) self.pb = QProgressBar(self) self.pb.setMaximumWidth(245) self.stopProcess = QToolButton(self) self.stopProcess.setIcon(QIcon(path.normcase("gui/icons/process_stop.png"))) m = QMenu() # self.connect(m, SIGNAL('triggered(QAction*'), QApplication.instance().taskManager.abortByName) self.stopProcess.setMenu(m) self.stopProcess.setPopupMode(1) # Menu Button # self.connect(self.stopProcess, SIGNAL("clicked()"), self.stopThread) self.statusBar().addPermanentWidget(self.stopProcess) self.statusBar().addPermanentWidget(self.pb) def updateStopProcessMenu(self): """ update the menu of the stop process button, based directly on the processes stored by the task manager """ self.stopProcess.menu().clear() for c in QApplication.instance().taskManager: self.stopProcess.menu().addAction(c.title) # QApplication.instance().taskManager.abort(QApplication.instance().taskManager[-1]) def addMdiSubWindow(self, plot, title="", showMaximized=False): """ Allow addition of new window in the mdiarea """ win = self.mdiArea.addSubWindow(plot) # print "widget parent", plot.parent() win.setAttribute(Qt.WA_DeleteOnClose) # win.connect(win, SIGNAL('destroyed(QObject *)'), self.testdestroy) # plot.setParent(win) win.setWindowTitle(title) if showMaximized: win.showMaximized() else: win.resize(400, 300) win.show() return win def updateTreeView(self): """ Tree View update switch spectre/chromato """ if self.treeView.model() == self.spectraModel: self.treeView.setModel(self.chromaModel) self.tabWidget.setTabText(0, "Chroma") else: self.treeView.setModel(self.spectraModel) # self.treeView.setSelectionMode(1) self.tabWidget.setTabText(0, "Spectra") def addTreeViewModel(self, model1, model2): """Add a model """ self.chromaModel.appendRow(model1) self.spectraModel.appendRow(model2) def _actionHovered(self, action): """emulate tooltip cause they do not work that much""" tip = action.toolTip() QToolTip.showText(QCursor.pos(), tip) def showErrorMessage(self, title, string): QMessageBox.critical(self, title, string, 0, 0) def showWarningMessage(self, title, string): return QMessageBox.warning(self, title, string, QMessageBox.Ok | QMessageBox.Cancel) def showInformationMessage(self, title, string): QMessageBox.information(self, title, string, 0) def updateProgressBar(self, i): """update the value of the progress bar for all the treatment""" self.pb.setValue(min(i, 100)) def to_indetermined_mode(self): self.pb.setMaximum(0) def to_determined_mode(self): self.pb.setMaximum(100) def showInStatusBar(self, string, time=5000): self.statusBar().showMessage(string, time) def addInterpreterDock(self, shell): self.shellDock = QDockWidget(self) self.shellDock.setWidget(shell) self.shellDock.setWindowTitle("shell") self.addDockWidget(0x2, self.shellDock) def showMetMSInformation(self): QMessageBox.about( self, self.tr("About %1").arg("metMS"), self.tr( """<b>%1 %2</b> <br>metabolite Mass Spectrometry <p>Copyright © 2010 Marco INSA, INRA <br>Licensed under the terms of the CeciLL License <p>Developed and maintained by Marco <br>Bug reports and feature requests: <a href="http://github.com/jerkos/metms">metMS site</a><br> Discussions around the project: <a href="http://groups.google.com/group/spyderlib">Google Group</a> <p>This project is part of the BRIDGE project <p>Python %3, Qt %4, PyQt %5""" ) .arg("metMS") .arg(__version__) .arg(platform.python_version()) .arg(QT_VERSION_STR) .arg(PYQT_VERSION_STR), )
def accept(self): """Event handler for when OK is pressed.""" LOGGER.debug('run the tools') self.get_user_options() if self.site_layer is None: self.show_site_layer_information_message() return if self.parcel_layer is None: self.show_parcel_layer_information_message() return # check if no feature is selected if (not self.layer_has_selection(self.site_layer) and self.selected_sites_only.isChecked()): self.show_no_selection_warning() return if self.output_directory is '' or not os.path.exists( self.output_directory): self.show_output_directory_information_message() return message_bar = self.iface.messageBar().createMessage( self.tr('Download SG Diagram'), self.tr('Please stand by while download process is in progress.'), self.iface.mainWindow()) progress_bar = QProgressBar() progress_bar.setMaximumWidth(150) progress_bar.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) message_bar.layout().addWidget(progress_bar) self.iface.messageBar().pushWidget( message_bar, self.iface.messageBar().INFO) self.message_bar = message_bar self.save_state() self.close() def progress_callback(current, maximum, message=None): """GUI based callback implementation for showing progress. :param current: Current progress. :type current: int :param maximum: Maximum range (point at which task is complete. :type maximum: int :param message: Optional message to display in the progress bar :type message: str, QString """ if message is not None: message_bar.setText(message) if progress_bar is not None: progress_bar.setMaximum(maximum) progress_bar.setValue(current) report = download_sg_diagrams( self.database_manager, self.site_layer, self.parcel_layer, self.sg_code_field, self.output_directory, self.all_features, callback=progress_callback) # Get rid of the message bar again. self.iface.messageBar().popWidget(message_bar) #QgsMapLayerRegistry.instance().addMapLayers([layer]) self.iface.messageBar().pushMessage( self.tr('Download completed.'), self.tr('Your files are available in %s.' % self.output_directory), level=QgsMessageBar.INFO, duration=10) write_log(report, self.log_file) self.show_log(report, self.log_file)
class Form(QMainWindow, Ui_MainWindow): """IT Query Main Window.""" def __init__(self, initIds, initErrIds, parent=None): """Setup main window and populate with data(if given).""" super(Form, self).__init__(parent) self.setupUi(self) self.setWindowTitle("IT Query {0}".format(__version__)) self.selectedIds = initIds self.errorIds = initErrIds LOG_LEVEL = logging.INFO currTime = time.localtime() runDate = time.strftime("%Y-%m-%d", currTime) self.dbPath = DB.Db.Info.Path LOG_FNAME = "{0}\{1}-{2}.{3}".format(self.dbPath, "itquery", runDate, "txt") if LOG_LEVEL == logging.INFO: LOG_FORMAT = "%(asctime)s\t%(message)s" else: LOG_FORMAT = ("%(asctime)s - %(levelname)s - %(funcName)s " " - %(message)s") self.logger = logging.getLogger("itquery") self.logger.setLevel(LOG_LEVEL) self.handler = logging.FileHandler(LOG_FNAME) formatter = logging.Formatter(LOG_FORMAT) self.handler.setFormatter(formatter) self.logger.addHandler(self.handler) for action, slot in ((self.updateButton, self.updateSelection), (self.bionumericsButton, self.bnSelectFields), (self.itemTrackerButton, self.itSelectFields)): action.clicked.connect(slot) for action, slot in ((self.actionCollapseAll, self.collapseAll), (self.actionExpandAll, self.expandAll), (self.actionCollapseItem, self.collapseItem), (self.actionCherryPicking, self.cherryPicking), (self.actionExpandItem, self.expandItem), (self.actionSelectAll, self.selectAll), (self.actionSelectDNA, self.selectDNA), (self.actionSelectFrozenStock, self.selectFrozenStock), (self.actionSelectInvert, self.selectInvert), (self.actionSelectNone, self.selectNone), (self.actionGetAllSelected, self.getAllSelected), (self.actionRefresh, self.refresh), (self.actionAbout, self.about), (self.actionViewTree, self.viewTree), (self.actionClearLog, self.clearLog), (self.actionLegend, self.legend), (self.actionExportTraceList, self.exportTraceList), (self.actionExportDNAList, self.exportDNAList), (self.actionClose, self.close)): action.triggered.connect(slot) self.treeWidget.itemSelectionChanged.connect(self.updateInfo) self.viewMenu.addAction(self.logDockWidget.toggleViewAction()) icon = QIcon(":/text-x-log.png") self.logDockWidget.toggleViewAction().setIcon(icon) self.actionSelectInBionumerics.toggled.connect(self.selectInBionumerics) self.userComboBox.currentIndexChanged.connect(self.userChanged) self.statusComboBox.currentIndexChanged.connect(self.statusChanged) self.treeActions = QActionGroup(self) self.treeActions.addAction(self.actionExpandItem) self.treeActions.addAction(self.actionCollapseItem) self.treeActions.addAction(self.actionExpandAll) self.treeActions.addAction(self.actionCollapseAll) self.selectActions = QActionGroup(self) self.selectActions.addAction(self.actionSelectAll) self.selectActions.addAction(self.actionSelectNone) self.selectActions.addAction(self.actionSelectInvert) self.selectActions.addAction(self.actionSelectDNA) self.selectActions.addAction(self.actionSelectFrozenStock) self.exportActions = QActionGroup(self) self.exportActions.addAction(self.actionExportDNAList) self.exportActions.addAction(self.actionExportTraceList) self.statusbar.setSizeGripEnabled(True) # user label at the right end of status bar # db = lims.DATABASE db = "No information" dbLabel = QLabel("Database: <b>{0}</b>".format(db)) self.statusbar.addPermanentWidget(dbLabel) user = os.environ.get("USERNAME") or "Demo user" label = QLabel("Logged in as: <b>{0}</b>".format(user)) self.statusbar.addPermanentWidget(label) # restore main window state settings = QSettings() size = settings.value("MainWindow/Size", QVariant(QSize(600, 500))).toSize() self.resize(size) position = settings.value("MainWindow/Position", QVariant(QPoint(0, 0))).toPoint() self.move(position) self.restoreState(settings.value("MainWindow/State").toByteArray()) splitterState = settings.value("MainWindow/SplitState").toByteArray() self.splitter.restoreState(splitterState) # selected fields self.dbName = bns.ConnectedDb.ConnectDb.GetList() regKey = "Bionumerics/{0}/SelFields".format(self.dbName) regBnFields = settings.value(regKey).toStringList() self.bnSelectedFields = [unicode(item) for item in regBnFields] regItFields = settings.value("ItemTracker/SelFields").toStringList() self.itSelectedFields = [unicode(item) for item in regItFields] # progress bar self.progressBar = QProgressBar(self) self.progressBar.setMaximumWidth(200) self.statusbar.insertPermanentWidget(0, self.progressBar) self.progressBar.hide() # initialize variables self.itemIds = {} self.itemNames = {} # bnFields - bionumerics information in the info panel self.bnFields = {} self.strainInfo = {} # maintains list of keys that are updated self.updatedStrains = [] self.selectRadioButton.setChecked(True) self.itemProperties = {} self.tableResults = [] self.getBnFields() self.mkInfo("{0}. Log: {1}".format(time.asctime(), LOG_FNAME)) self.populatedTree = False self.populatedTable = False self.populatedCherry = False idField = "ItemTracker ID" # Field with ItemTracker ID self.itemIdsAll, errors = bn.getItemIds(idField, DB.Db.Entries) if len(errors): for key, message in errors.iteritems(): self.mkError("Key: {0}, {1}".format(key, message)) self.database = None self.updateUi() self.proxyModel = SortFilterProxyModel(self) self.proxyModel.setDynamicSortFilter(True) self.cherryView.setModel(self.proxyModel) self.cherryView.setAlternatingRowColors(True) self.cherryView.setSortingEnabled(True) self.cherryView.verticalHeader().setVisible(False) self.cherryView.setEditTriggers(QAbstractItemView.NoEditTriggers) self.cherryView.horizontalHeader().setStretchLastSection(True) #self.populateTree() # testing QTimer.singleShot(0, self.populateTree) def bnSelectFields(self): """Bionumerics field selection dialog.""" try: fieldNames = bn.getFieldNames() except RuntimeError as e: self.mkError("Failed to get Bionumerics field names: {0}".format(e)) dialog = selectfieldsdlg.selectFieldsDialog(fieldNames, self) if self.bnSelectedFields is not None: dialog.setSelected(self.bnSelectedFields) if dialog.exec_(): self.bnSelectedFields = dialog.getSelected() self.updateInfo() def addCherryData(self, model, row): """Inserts row into model""" model.insertRow(0) for position, value in enumerate(row): model.setData(model.index(0, position), value) def createCherryModel(self, data, parent): """Creates a model for the tableview using data retrieved from the cherry picking database. """ total = len(data) self.progressBar.setMaximum(total) self.progressBar.show() model = QStandardItemModel(0, len(CHERRY_COLUMNS), parent) for position, column in enumerate(CHERRY_COLUMNS): model.setHeaderData(position, Qt.Horizontal, column) # get additional data for each item keys = [item[CHERRY_COLUMNS.index("Key")] for item in data] itemIds = [] missing = [] itemIdsAll = dict((v, k) for k, v in self.itemIdsAll.iteritems()) for key in keys: if key in itemIdsAll: itemIds.append(itemIdsAll[key]) else: missing.append(key) if len(missing): msg = ("Keys exist in cherry picking database but absent " "in Bionumerics {0}".format(", ".join(missing))) self.mkWarn(msg) if not len(itemIds): msg = "No entries in cherry picking database" self.statusBar().showMessage(msg, 5000) self.mkInfo(msg) return None itemIds = list(set(itemIds)) (dnaData, noData, errors) = lims.GetNewestDNAForCherryPicking(itemIds) if len(noData): msg = ", ".join(str(item) for item in noData) self.mkWarn("{0}: {1}".format("No DNA's for these strains", msg)) if len(errors): msg = ", ".join(errors) self.mkError(msg) for count, result in enumerate(data): result = list(result) key = result[0] if key in itemIdsAll: self.progressBar.setValue(count) #QApplication.processEvents() parentID = itemIdsAll[key] if parentID in dnaData: properties = dnaData[parentID] for value in ("ItemName", "DNA concentration", "Volume", "Freezer", "Rack", "Shelf", "PlateRack", "Position"): if value in properties: result.append(properties[value]) else: result.append("") self.addCherryData(model, result) return model def cherryPicking(self): """Populate the cherry picking table""" if self.populatedCherry: if not self.stackedWidget.currentIndex() == 2: self.stackedWidget.setCurrentIndex(2) self.updateUi() return self.statusbar.showMessage("Getting data from cherry picking database") db = DB.Db.Info.Name cherryData = pgdb.get_data(db) if not len(cherryData): msg = "No cherry picking entries for this database" self.statusbar.showMessage(msg, 5000) self.mkInfo(msg) self.stackedWidget.setCurrentIndex(2) self.updateUi() return self.userComboBox.clear() self.statusComboBox.clear() # filter combo boxes for label, combo in (("Username", self.userComboBox), ("Status", self.statusComboBox)): position = CHERRY_COLUMNS.index(label) comboItems = set([item[position] for item in cherryData]) combo.addItem("All") combo.addItems(list(comboItems)) self.proxyModel.traceStatus = self.statusComboBox.currentText() self.cherryView.reset() self.cherryView.setDisabled(True) self.statusbar.showMessage("Getting data from ItemTracker") model = self.createCherryModel(cherryData, self) if not model: self.cherryView.setEnabled(False) self.filterGroupBox.setDisabled(True) else: self.proxyModel.setSourceModel(model) self.cherryView.setEnabled(True) self.filterGroupBox.setEnabled(True) self.cherryView.resizeColumnsToContents() self.updateCounts() self.stackedWidget.setCurrentIndex(2) # switch view to table self.statusbar.clearMessage() self.progressBar.setValue(len(cherryData)) self.progressBar.hide() self.populatedCherry = True self.updateUi() def statusChanged(self): """Filter cherry picking based on current trace status from combo box.""" self.proxyModel.setTraceStatus(self.statusComboBox.currentText()) self.updateCounts() def userChanged(self): """Filter cherry picking based on current user from combo box.""" user = self.userComboBox.currentText() if user == "All": user = "******" regExp = QRegExp(user, Qt.CaseInsensitive, QRegExp.RegExp2) self.proxyModel.setFilterRegExp(regExp) self.updateCounts() def updateCounts(self): """Update counts of strains, traces and DNA in cherry picking""" strains = [] traces = self.proxyModel.rowCount() dna = [] for i in range(traces): for field, totals in (("Key", strains), ("DNA", dna)): index = self.proxyModel.index(i, CHERRY_COLUMNS.index(field)) data = self.proxyModel.data(index).toString().trimmed() if len(data) and data not in totals: totals.append(data) self.strainsLcdNumber.display(len(strains)) self.tracesLcdNumber.display(traces) self.dnaLcdNumber.display(len(dna)) def getSaveFile(self, caption=""): """Opens the save file dialog and returns the file name.""" if not len(caption): caption = "Save File As" fn = QFileDialog.getSaveFileName(self, caption, self.dbPath, "Text files (*.txt);;All Files (*.*)") if fn: if QFileInfo(fn).suffix().isEmpty(): fn += ".txt" return fn def exportTextFile(self, fh=None, header=None, data=None): """Writes data to the given file. Accepts column names and the data as arguments """ if not fh: self.mkError("Could not open file for writing") return if not data: data = [] if not len(data): self.mkWarn("No data to write") return fname = QFile(fh) if fname.open(QFile.WriteOnly | QFile.Text): txt = QTextStream(fname) if header: txt << ", ".join(col for col in header) txt << "\n" txt << "\n".join(", ".join(item) for item in data) msg = "File export complete: {0}".format(str(fname.fileName())) self.mkSuccess(msg) def exportDNAList(self): """Export list of DNA's displayed in cherry picking.""" data = [] keys = [] columns = CHERRY_COLUMNS[:] excludeColumns = ["Gene", "Orientation"] exclude = [] for item in excludeColumns: exclude.append(CHERRY_COLUMNS.index(item)) columns.remove(item) keyIndex = CHERRY_COLUMNS.index("Key") dnaIndex = CHERRY_COLUMNS.index("DNA") for i in range(0, self.proxyModel.rowCount()): # continue if key exists in keys index = self.proxyModel.index(i, keyIndex) key = self.proxyModel.data(index).toString() if key in keys: continue # continue if DNA column is empty index = self.proxyModel.index(i, dnaIndex) dna = self.proxyModel.data(index).toString() if dna.isEmpty(): continue row = [] for j in range(self.proxyModel.columnCount()): if j in exclude: continue index = self.proxyModel.index(i, j) value = self.proxyModel.data(index).toString() if not value.isEmpty(): row.append(str(value)) else: row.append("") data.append(row) keys.append(key) fh = self.getSaveFile("Export DNA List") self.exportTextFile(fh, columns, data) def exportTraceList(self): """Export list of traces displayed in cherry picking.""" data = [] for i in range(0, self.proxyModel.rowCount()): row = [] for j in range(self.proxyModel.columnCount()): index = self.proxyModel.index(i, j) value = self.proxyModel.data(index).toString() if not value.isEmpty(): row.append(str(value)) else: row.append("") data.append(row) fh = self.getSaveFile("Export Trace List") columns = CHERRY_COLUMNS[:] self.exportTextFile(fh, columns, data) def clearLog(self): """Clears the log window""" self.logBrowser.clear() def closeEvent(self, event): """Called on closing the window. Save settings and exit.""" self.handler.close() self.logger.removeHandler(self.handler) if self.okToContinue(): settings = QSettings() settings.setValue("MainWindow/Size", QVariant(self.size())) settings.setValue("MainWindow/Position", QVariant(self.pos())) settings.setValue("MainWindow/State", QVariant(self.saveState())) settings.setValue("MainWindow/SplitState", self.splitter.saveState()) bnSelectedFields = QVariant(self.bnSelectedFields) \ if self.bnSelectedFields else QVariant() regkey = "Bionumerics/{0}/SelFields".format(self.dbName) settings.setValue(regkey, bnSelectedFields) itSelectedFields = QVariant(self.itSelectedFields) \ if self.itSelectedFields else QVariant() settings.setValue("ItemTracker/SelFields", itSelectedFields) else: event.ignore() def collapseItem(self): """Collapse selected item.""" try: selected = self.treeWidget.selectedItems()[0] except IndexError: selected = None self.statusbar.showMessage("No item selected", 2000) if selected: self.treeWidget.collapseItem(selected) def collapseAll(self): """Collapse all items.""" self.treeWidget.collapseAll() def disableWidgets(self, widgets): """Disable group of widgets. Does not change visibility.""" for widget in widgets: if widget.isEnabled(): widget.setDisabled(True) def enableWidgets(self, widgets): """Enable group of widgets. Set visible if not visible.""" for widget in widgets: if not widget.isEnabled(): widget.setEnabled(True) if not widget.isVisible(): widget.setVisible(True) def expandItem(self): """Expand selected item.""" try: selected = self.treeWidget.selectedItems()[0] except IndexError: selected = None self.statusbar.showMessage("No item selected", 2000) if selected: self.treeWidget.expandItem(selected) def expandAll(self): """Expands all items.""" self.treeWidget.expandAll() def getBnFields(self): """Get bionumerics field information required for the info panel.""" bnFields = bn.getFieldNames() strainFields = ["Strain", "STRAIN"] for field in strainFields: if (field in bnFields) and (field not in self.bnSelectedFields): self.bnSelectedFields.append(field) for key in self.selectedIds.values(): if not self.bnFields.get(key): self.bnFields[key] = bn.getSelectedFields(key, bnFields) def getParent(self, item): """Returns the top level parent of an item.""" parentItem = None while item.parent(): parentItem = item.parent() item = parentItem return parentItem def getData(self, items, itemid): """Returns parent and children for data received from GetDictionary.""" if len(items): children = items[itemid].keys() yield itemid, children items = items[itemid] for child in children: for res in self.getData(items, child): yield res return def getAllItemIds(self): """Gets all ItemTracker IDs in the current Bionumerics database.""" itemIds = {} field = "ItemTracker ID" value = None for i in range(len(DB.Db.Entries)): value = DB.Db.Entries[i].Field(field).Content # bugfix: don't display if ItemTracker ID contains spaces value = value.strip() if not len(value): continue key = DB.Db.Entries[i].Key key = key.strip() if key in itemIds: itemIds.pop(key) msg = "Duplicate keys in database: {0}. Not processed".format(key) self.mkWarn(msg) continue try: value = int(value) except (ValueError, TypeError): self.mkWarn("Invalid ItemTracker ID {0} for entry " "{1} in Bionumerics".format(value, key)) if isinstance(value, int): if value in itemIds.values(): msg = ("Duplicate ItemTracker ID: {0}. " "Keys: {1}, ".format(value, key)) for k, v in itemIds.items(): if v == value: itemIds.pop(k) msg += k self.mkWarn(msg) else: itemIds[key] = value return itemIds def getAllSelected(self): """Get all selected items by user.""" if self.populatedTable: self.stackedWidget.setCurrentIndex(1) self.updateUi() return msg = "Getting all selected entries from ItemTracker. Please wait..." self.statusbar.showMessage(msg) if len(self.itemIdsAll): try: self.tableResults = \ lims.SelectAllselectedEntries(self.itemIdsAll.keys()) except: raise RuntimeError else: self.mkInfo("No ItemTracker IDs to process") if not len(self.tableResults): user = os.environ.get("USERNAME") msg = "No selected entries for user {0}".format(user) self.statusbar.showMessage(msg, 5000) self.mkInfo(msg) self.stackedWidget.setCurrentIndex(1) self.populatedTable = False self.updateUi() else: QTimer.singleShot(0, self.populateTable) def getItemtrackerFields(self): """Returns all ItemTracker fields returned from GetDictionary.""" fields = [] alwaysFields = ["ItemID", "ItemName", "Position"] for item in self.itemProperties: for field in self.itemProperties[item].keys(): if (field not in fields) and (field not in alwaysFields): fields.append(field) return fields def getWidget(self): """Returns the current active widget.""" index = self.stackedWidget.currentIndex() if index == 0: widget = self.treeWidget elif index == 1: widget = self.selectedWidget elif index == 2: widget = self.cherryView return widget def about(self): """About box.""" import platform msg = """\ <b>IT Query</b> version {0} <p>An interface to query ItemTracker from Bionumerics</p>Python {1} - Qt {2} - PyQt {3} on {4}\ """.format(__version__, platform.python_version(), QT_VERSION_STR, PYQT_VERSION_STR, platform.system()) msg += """<br>Icons from the <a href="http://www.oxygen-icons.org/">Oxygen project</a> </p>""" QMessageBox.about(self, "About IT Query", msg) def legend(self): """A simple dialog displaying the color legend used in treeview.""" dialog = legenddlg.legendDialog(self) dialog.exec_() def itSelectFields(self): """ItemTracker field selection dialog.""" fieldNames = self.getItemtrackerFields() dialog = selectfieldsdlg.selectFieldsDialog(fieldNames, self) if self.itSelectedFields is not None: dialog.setSelected(self.itSelectedFields) if dialog.exec_(): self.itSelectedFields = dialog.getSelected() self.updateInfo() def mkWarn(self, msg): """Orange color""" bgColor = "235,115,49" self.mkTable(bgColor, "WARNING", msg) def mkError(self, msg): """Red color""" bgColor = "226,8,0" self.mkTable(bgColor, "ERROR", msg) def mkSuccess(self, msg): """Green color""" bgColor = "55,164,44" self.mkTable(bgColor, "SUCCESS", msg) def mkInfo(self, msg): """Blue color""" bgColor = "0,87,174" self.mkTable(bgColor, "INFO", msg) def mkTable(self, bgColor, status, msg): """Formats message displayed in the log window.""" formatStatus = ('<font style="color:rgb({0})"><strong>{1}</strong>' '</font>'.format(bgColor, status)) self.logBrowser.append("{0}: {1}".format(formatStatus, msg)) def okToContinue(self): """Check before closing.""" if len(self.updatedStrains): reply = QMessageBox(QMessageBox.Question, "Selection", "Entry selection in Bionumerics", QMessageBox.NoButton, self) originalButton = QPushButton("Keep Original Selection") updatedButton = QPushButton("Updated Items Only") cancelButton = QPushButton("Cancel") reply.addButton(originalButton, QMessageBox.ActionRole) reply.addButton(updatedButton, QMessageBox.ActionRole) reply.addButton(cancelButton, QMessageBox.RejectRole) reply.exec_() if reply.clickedButton() == cancelButton: return False elif reply.clickedButton() == originalButton: bn.selectEntries(self.selectedIds.values() +\ self.errorIds.keys()) elif reply.clickedButton() == updatedButton: bn.selectEntries(self.updatedStrains) return True def populateTable(self): """Populates table with data from ItemTracker.""" self.selectedWidget.clear() self.selectedWidget.setSortingEnabled(False) numRows = len(self.tableResults) self.mkInfo("Selected items in ItemTracker: {0}".format(numRows)) self.selectedWidget.setAlternatingRowColors(True) header = ["ItemID", "StrainID", "ItemType", "ItemName", "BacteriaItemID"] self.selectedWidget.setColumnCount(len(header)) self.selectedWidget.setHeaderLabels(header) # use result and populate table for result in self.tableResults: properties = [unicode(i) for i in result] item = QTreeWidgetItem(self.selectedWidget, properties) item.setCheckState(0, Qt.Unchecked) self.selectedWidget.setSortingEnabled(True) for i in range(len(header)): self.selectedWidget.resizeColumnToContents(i) self.stackedWidget.setCurrentIndex(1) # switch view to table self.statusbar.clearMessage() self.populatedTable = True self.updateUi() def populateTree(self): """Populates tree view with information from ItemTracker.""" if len(self.errorIds): self.mkError("{0} entries do not have valid " "ItemTracker IDs in Bionumerics.".format(len(self.errorIds))) for key, msg in self.errorIds.iteritems(): self.mkError("KEY: {0} {1}".format(key, msg)) if not len(self.selectedIds): self.statusbar.showMessage("No items to process", 5000) return parents = {} headers = ["Items", "Selected", "SelectedBy", "Viability", "Volume", "DNA concentration", "UserName", "TubePresent", "InputDate", "AlternID", "Status"] self.treeWidget.setItemsExpandable(True) self.treeWidget.setAlternatingRowColors(True) self.treeWidget.setColumnCount(len(headers)) self.treeWidget.setHeaderLabels(headers) msg = "Getting information from ItemTracker. Please wait..." self.statusbar.showMessage(msg) self.progressBar.setMinimum(0) self.progressBar.setMaximum(0) self.progressBar.show() (treeData, self.itemProperties, message) = lims.GetDictionary((self.selectedIds.keys())) if len(message): for msg in message: self.mkError("ItemTracker error: {0}".format(msg)) if not len(treeData): self.mkError("Could not get data from ItemTracker for" "selected entries") self.statusBar().clearMessage() self.progressBar.hide() self.updateUi() return # bugfix: If ItemType property does not exist for the first item # self.database is not set and tree view is not updated. db = None if not self.database: for item in self.itemProperties.values(): try: db = item["ItemType"] except KeyError: pass if db == "Salmonella": self.database = db break elif db == "Listeria": self.database = db break self.progressBar.setMaximum(len(treeData)) count = 0 for key, value in treeData.iteritems(): count += 1 self.progressBar.setValue(count) if not(value and isinstance(value, dict)): self.mkWarn("No data returned for key {0}".format(key)) continue items = {} items[key] = value for results in self.getData(items, key): parent = parents.get(results[0]) if not parent: parent_id = self.selectedIds[results[0]] self.strainInfo[parent_id] = {self.database:[], "Frozen Stock":[], "DNA":[]} parent = QTreeWidgetItem(self.treeWidget, [unicode(parent_id)]) brush = QBrush() brush.setColor(Qt.blue) parent.setForeground(0, brush) parent.setIcon(0, QIcon(":/branch-closed.png")) parent.setData(0, Qt.CheckStateRole, QVariant()) parents[results[0]] = parent for children in results[1]: itemName = self.itemProperties[children]["ItemName"] if not self.itemIds.get(itemName): self.itemIds[itemName] = children childprops = [] childprops.append(unicode(itemName)) for header in headers[1:]: try: childprop = self.itemProperties[children][header] if childprop is None or childprop == "": childprops.append(unicode("")) else: childprops.append(unicode(childprop)) except KeyError: childprops.append(unicode("")) continue childs = parents.get(children) if not childs: childs = QTreeWidgetItem(parent, childprops) if self.itemProperties[children]["TubePresent"] == "-": childs.setBackgroundColor(0, QColor(232, 87, 82)) childs.setForeground(0, QColor(255, 255, 255)) if self.itemProperties[children]["Selected"] == "yes": childs.setBackgroundColor(0, QColor(119, 183, 83)) childs.setForeground(0, QColor(255, 255, 255)) itype = self.itemProperties[children]["ItemType"] if itype: self.strainInfo[parent_id][itype].append(itemName) parents[children] = childs childs.setCheckState(0, Qt.Unchecked) self.treeWidget.expandAll() for i in range(len(headers)): self.treeWidget.resizeColumnToContents(i) if not self.treeWidget.isEnabled(): self.treeWidget.setEnabled(True) self.mkInfo("Processed <b>{0}</b> entries".format(len(treeData))) self.progressBar.setValue(len(treeData)) self.progressBar.hide() self.populatedTree = True self.updateUi() self.statusbar.showMessage("Ready", 5000) def selectAll(self): """All items are selected (checked).""" index = self.stackedWidget.currentIndex() widget = self.getWidget() it = QTreeWidgetItemIterator(widget, QTreeWidgetItemIterator.NotChecked) count = 0 if index == 0: while it.value(): if it.value().parent(): it.value().setCheckState(0, Qt.Checked) count += 1 it += 1 elif index == 1: while it.value(): it.value().setCheckState(0, Qt.Checked) count += 1 it += 1 if count: self.statusbar.showMessage("Selected {0} items".format(count), 3000) def selectDNA(self): """Select all DNA items.""" self.selectItems("DNA") def selectFrozenStock(self): """Select all Frozen Stock items.""" self.selectItems("Frozen Stock") def selectNone(self): """Clears the selection.""" widget = self.getWidget() it = QTreeWidgetItemIterator(widget, QTreeWidgetItemIterator.Checked) while it.value(): it.value().setCheckState(0, Qt.Unchecked) it += 1 def selectInvert(self): """Inverts the selection.""" index = self.stackedWidget.currentIndex() widget = self.getWidget() it = QTreeWidgetItemIterator(widget) if index == 0: while it.value(): if it.value().parent(): if it.value().checkState(0) == Qt.Checked: it.value().setCheckState(0, Qt.Unchecked) else: it.value().setCheckState(0, Qt.Checked) it += 1 else: while it.value(): if it.value().checkState(0) == Qt.Checked: it.value().setCheckState(0, Qt.Unchecked) else: it.value().setCheckState(0, Qt.Checked) it += 1 def selectItems(self, itemType): """Select all items of a given ItemType.""" self.statusbar.showMessage("Selecting all {0}'s. " "Please wait...".format(itemType)) items = [] itemsAll = [] index = self.stackedWidget.currentIndex() if index == 0: position = 0 items = [item[itemType] for item in self.strainInfo.values()] for item in items: if len(item): itemsAll += item else: position = 3 for item in self.tableResults: if item[2] == itemType: itemsAll.append(item[3]) if not len(itemsAll): self.statusbar.showMessage("No {0}'s in list".format(itemType), 5000) return self.selectNone() widget = self.getWidget() it = QTreeWidgetItemIterator(widget) while it.value(): if it.value().text(position) in itemsAll: it.value().setCheckState(0, Qt.Checked) it += 1 self.statusbar.showMessage("Selected {0} {1}'s".format(len(itemsAll), itemType), 3000) def selectInBionumerics(self, on): """Selects Bionumerics entries with checked items from table view (get all selected) """ actionGroup = QActionGroup(self) actionGroup.addAction(self.actionViewTree) actionGroup.addAction(self.refresh_action) actionGroup.addAction(self.actionSelectAll) actionGroup.addAction(self.actionSelectInvert) actionGroup.addAction(self.actionSelectNone) actionGroup.addAction(self.actionSelectDNA) actionGroup.addAction(self.actionSelectFrozenStock) if on: actionGroup.setEnabled(False) if not len(self.itemNames): self.itemNames = bn.createIdMap() it = QTreeWidgetItemIterator(self.selectedWidget, QTreeWidgetItemIterator.Checked) checkedItems = [] while it.value(): parentCode = unicode(it.value().text(4)) bnStrain = self.itemNames[int(parentCode)] if bnStrain not in checkedItems: checkedItems.append(bnStrain) it += 1 if len(checkedItems): bn.selectEntries(checkedItems) else: self.statusbar.showMessage("No items checked", 3000) else: actionGroup.setEnabled(True) bn.selectEntries(self.selectedIds.values() + self.errorIds.keys()) def updateSelection(self): """Updates selection status in ItemTracker.""" if self.actionSelectInBionumerics.isChecked(): self.selectInBionumerics(False) self.actionSelectInBionumerics.setChecked(False) self.updateButton.setEnabled(False) self.statusbar.showMessage("Updating selection. Please wait...") if self.selectRadioButton.isChecked(): selectedAction = "SELECT" elif self.deselectRadioButton.isChecked(): selectedAction = "DESELECT" checkedItems = {} updatedItems = [] failedItems = [] index = self.stackedWidget.currentIndex() widget = self.getWidget() it = QTreeWidgetItemIterator(widget, QTreeWidgetItemIterator.Checked) if index == 0: while it.value(): itemName = unicode(it.value().text(0)) itemId = self.itemIds[itemName] checkedItems[itemName] = itemId parentItem = self.getParent(it.value()) strain = unicode(parentItem.text(0)) if strain not in self.updatedStrains: self.updatedStrains.append(strain) it += 1 elif index == 1: if not len(self.itemNames): self.itemNames = bn.createIdMap() while it.value(): itemId = unicode(it.value().text(0)) itemName = unicode(it.value().text(3)) checkedItems[itemName] = int(itemId) parentCode = unicode(it.value().text(4)) strain = self.itemNames[int(parentCode)] if strain not in self.updatedStrains: self.updatedStrains.append(strain) it += 1 if not len(checkedItems): self.statusbar.showMessage("No items checked", 5000) self.updateButton.setEnabled(True) return for itemName, itemId in checkedItems.iteritems(): if selectedAction == "SELECT": result = lims.SelectItem(itemId) elif selectedAction == "DESELECT": result = lims.UnselectItem(itemId) if not len(result): updatedItems.append(itemName) else: failedItems.append(itemName) if len(updatedItems): self.mkSuccess("{0}ED {1} items".format(selectedAction, len(updatedItems))) self.logBrowser.append("{0}".format(", ".join(updatedItems))) self.logger.info("{0}\t{1}".format(selectedAction, ", ".join(updatedItems))) if len(failedItems): self.mkError("{0} failed for {1} items".format(selectedAction, len(failedItems))) self.logBrowser.append("{0}".format(", ".join(failedItems))) self.logger.info("{0}\t{1}".format(selectedAction, ", ".join(failedItems))) self.updateButton.setEnabled(True) if len(updatedItems) or len(failedItems): self.populatedTree = False self.populatedTable = False self.refresh() def updateUi(self): """Updates interface based on the view.""" index = self.stackedWidget.currentIndex() # only show export actions in cherry picking if index != 2: widgets = [self.exportToolBar, self.exportActions] self.disableWidgets(widgets) for widget in widgets: widget.setVisible(False) # disable select menu in cherry picking (not implemented) if index == 2: self.selectMenu.setEnabled(False) else: self.selectMenu.setEnabled(True) if index == 0: # Tree View self.disableWidgets([self.actionViewTree, self.actionSelectInBionumerics]) self.enableWidgets([self.actionGetAllSelected, self.actionCherryPicking]) for widget in [self.actionSelectInBionumerics, self.getSelectedToolBar]: widget.setVisible(False) #self.fieldsGroupBox.setVisible(True) widgets = [self.widget, self.treeWidget, self.selectGroupBox, self.fieldsGroupBox, self.actionLegend, self.treeToolBar, self.treeActions, self.selectActions] for widget in widgets: if not widget.isVisible(): widget.setVisible(True) if self.populatedTree: self.enableWidgets(widgets) else: self.disableWidgets(widgets) try: self.treeWidget.selectedItems()[0] except IndexError: self.infoBrowser.setDisabled(True) self.fieldsGroupBox.setEnabled(self.infoBrowser.isEnabled()) elif index == 1: self.widget.setVisible(True) self.enableWidgets([self.actionViewTree, self.actionCherryPicking]) self.actionSelectInBionumerics.setVisible(True) self.getSelectedToolBar.setVisible(True) for widget in [self.actionLegend, self.fieldsGroupBox, self.treeToolBar, self.treeActions]: widget.setVisible(False) self.disableWidgets([self.actionGetAllSelected, self.actionLegend, self.treeToolBar, self.treeActions]) widgets = [self.widget, self.selectedWidget, self.selectGroupBox, self.actionSelectInBionumerics, self.getSelectedToolBar, self.selectActions] if self.populatedTable: self.enableWidgets(widgets) else: self.disableWidgets(widgets) elif index == 2: self.widget.setVisible(False) # ItemTracker and field selection self.actionCherryPicking.setEnabled(False) self.exportToolBar.setVisible(True) self.exportActions.setVisible(True) for action in [self.actionViewTree, self.actionGetAllSelected]: action.setEnabled(True) widgets = [self.selectActions, self.actionSelectInBionumerics, self.actionLegend, self.treeActions, self.treeToolBar, self.getSelectedToolBar] self.disableWidgets(widgets) for widget in widgets: widget.setVisible(False) widgets = [self.cherryView, self.filterGroupBox, self.lcdGroupBox, self.exportActions, self.exportToolBar] if self.populatedCherry: self.enableWidgets(widgets) else: self.disableWidgets(widgets) def updateInfo(self): """Infobar displaying ItemTracker and Bionumerics fields.""" content = ('<table border="0" cellspacing="0" ' 'cellpadding="5" width="100%">') self.infoBrowser.clear() try: selected = self.treeWidget.selectedItems()[0] except IndexError: return else: self.infoBrowser.setEnabled(True) self.fieldsGroupBox.setEnabled(True) try: parentName = self.getParent(selected).text(0) except AttributeError: parentName = None if parentName: itemName = unicode(selected.text(0)) itemId = self.itemIds[itemName] if itemId: content += """\ <tr bgcolor="#85026C"> <th colspan="2" align="left"> <font color="white">ITEMTRACKER</font> </th> </tr>\ """ count = 0 for field, value in (("Strain", parentName), ("Item Name", itemName), ("Item ID", itemId)): if count % 2 == 0: content += """\ <tr> <td>{0}</td> <td>{1}</td> </tr>\ """.format(field, value) else: content += """\ <tr bgcolor="#eee"> <td>{0}</td> <td>{1}</td> </tr>\ """.format(field, value) count += 1 try: properties = self.itemProperties[int(itemId)] except KeyError: self.mkWarn("Could not get properties for " "ItemTracker ID {0}".format(itemId)) if len(properties): try: location = properties["Position"] except KeyError: location = [] if len(location): for field, value in (("Freezer", location[0]), ("Rack", location[1]), ("Shelf", location[2]), ("Plate Rack", location[3]), ("Position", location[4])): if count % 2 == 0: content += """\ <tr> <td>{0}</td> <td>{1}</td> </tr>\ """.format(field, value) else: content += """\ <tr bgcolor="#eee"> <td>{0}</td> <td>{1}</td> </tr>\ """.format(field, value) count += 1 if len(self.itSelectedFields): for itField in self.itSelectedFields: try: itemProperty = properties[itField] except KeyError: itemProperty = "" if count % 2 == 0: content += """\ <tr> <td>{0}</td> <td>{1}</td> </tr>\ """.format(itField, itemProperty) else: content += """\ <tr bgcolor="#eee"> <td>{0}</td> <td>{1}</td> </tr>\ """.format(itField, itemProperty) count += 1 else: content += """\ <tr> <td colspan="2">No information</td> </tr>""" self.infoBrowser.setHtml(QString(content)) content += """\ <tr bgcolor="#CF4913"> <th colspan="2" align="left"> <font color="white">BIONUMERICS</font> </th> </tr>\ """ strainInfo = {} try: strainInfo = self.bnFields.get(unicode(parentName)) except KeyError: self.mkWarn("Could not get information for {0}".format(parentName)) if len(strainInfo): count = 0 for field in self.bnSelectedFields: if count % 2 == 0: content += """\ <tr> <td>{0}</td> <td>{1}</td> </tr>\ """.format(field, strainInfo[field]) else: content += """\ <tr bgcolor="#eee"> <td>{0}</td> <td>{1}</td> </tr>\ """.format(field, strainInfo[field]) count += 1 else: self.mkWarn("No information for {0}".format(parentName)) content += "</table>" else: strainName = unicode(selected.text(0)) itemId = None for ids, keys in self.selectedIds.iteritems(): if keys == strainName: itemId = ids break if not itemId: self.infoBrowser.setHtml(QString(content)) return content = """\ <table border="0" cellpadding="5" cellspacing="0" width="100%"> <tr bgcolor="#85026C"> <th colspan="2" align="left"> <font color="white">ITEMTRACKER</font> </th> </tr> <tr bgcolor="#eee"> <td>AlternID</td> <td>{0}</td> </tr> <tr> <td>OriginalID</td> <td>{1}</td> </tr>\ """.format(self.itemProperties[itemId]["AlternID"], self.itemProperties[itemId]["OriginalID"]) content += "</table>" content += """\ <table border="0" cellpadding="5" cellspacing="0" width="100%"> <tr bgcolor="#BF0361"> <th align="left"> <font color="white">{0}</font> </th> <th align="right"> <font color="white">{1}</font> </th> </tr> <tr> <td colspan="2">{2}</td> </tr>\ """.format(self.database.upper(), len(self.strainInfo[strainName][self.database]), ", ".join(self.strainInfo[strainName][self.database])) content += """\ <tr bgcolor="#00438A"> <th align="left"> <font color="white">FROZEN STOCK</font> </th> <th align="right"> <font color="white">{0}</font> </th> </tr> <tr> <td colspan="2">{1}</td> </tr>\ """.format(len(self.strainInfo[strainName]["Frozen Stock"]), ", ".join(self.strainInfo[strainName]["Frozen Stock"])) content += """\ <tr bgcolor="#00734D"> <th align="left"> <font color="white">DNA</font> </th> <th align="right"> <font color="white">{0}</font> </th> </tr> <tr> <td colspan="2">{1}</td> </tr>\ """.format(len(self.strainInfo[strainName]["DNA"]), ", ".join(self.strainInfo[strainName]["DNA"])) content += "</table>" self.infoBrowser.setHtml(QString(content)) def viewTree(self): """Toolbar button/action to switch to tree view.""" self.selectRadioButton.setChecked(True) if not self.populatedTree: self.stackedWidget.setCurrentIndex(0) self.refresh() self.stackedWidget.setCurrentIndex(0) self.updateUi() def refresh(self): """Updates view(s).""" index = self.stackedWidget.currentIndex() if index == 1: self.populatedTable = False self.selectedWidget.clear() self.getAllSelected() elif index == 0: self.populatedTree = False self.treeWidget.clear() self.treeWidget.setDisabled(True) bnField = "ItemTracker ID" self.selectedIds = {} self.errorIds = {} selection = DB.Db.Selection self.selectedIds, self.errorIds = bn.getItemIds(bnField, selection) if len(self.selectedIds): self.strainInfo = {} self.itemIds = {} self.getBnFields() # self.populateTree() QTimer.singleShot(0, self.populateTree) elif index == 2: self.populatedCherry = False QTimer.singleShot(0, self.cherryPicking) self.updateUi()
class QuadStatusBar(QHBoxLayout): positionChanged = pyqtSignal(int, int, int) # x,y,z def __init__(self, parent=None ): QHBoxLayout.__init__(self, parent) self.setContentsMargins(0,4,0,0) self.setSpacing(0) self.timeControlFontSize = 12 def showXYCoordinates(self): self.zLabel.setHidden(True) self.zSpinBox.setHidden(True) def showXYZCoordinates(self): self.zLabel.setHidden(False) self.zSpinBox.setHidden(False) def hideTimeSlider(self,flag): self.timeSlider.setHidden(flag) self.timeEndButton.setHidden(flag) self.timeStartButton.setHidden(flag) def setToolTipTimeButtonsCrop(self,croppingFlag=False): if croppingFlag==True: self.timeStartButton.setToolTip("Set the time coordinate to the beginning of the current crop.") self.timeEndButton.setToolTip("Set the time coordinate to the end of the current crop.") else: self.timeStartButton.setToolTip("Set the time coordinate to the beginning of the current dataset.") self.timeEndButton.setToolTip("Set the time coordinate to the end of the current dataset.") def setToolTipTimeSliderCrop(self,croppingFlag=False): if croppingFlag==True: self.timeSlider.setToolTip("Choose the time coordinate of the current crop.") else: self.timeSlider.setToolTip("Choose the time coordinate of the current dataset.") def createQuadViewStatusBar(self, xbackgroundColor, xforegroundColor, ybackgroundColor, yforegroundColor, zbackgroundColor, zforegroundColor): self.xLabel, self.xSpinBox = _get_pos_widget('X', xbackgroundColor, xforegroundColor) self.yLabel, self.ySpinBox = _get_pos_widget('Y', ybackgroundColor, yforegroundColor) self.zLabel, self.zSpinBox = _get_pos_widget('Z', zbackgroundColor, zforegroundColor) self.xSpinBox.delayedValueChanged.connect( partial(self._handlePositionBoxValueChanged, 'x') ) self.ySpinBox.delayedValueChanged.connect( partial(self._handlePositionBoxValueChanged, 'y') ) self.zSpinBox.delayedValueChanged.connect( partial(self._handlePositionBoxValueChanged, 'z') ) self.addWidget(self.xLabel) self.addWidget(self.xSpinBox) self.addWidget(self.yLabel) self.addWidget(self.ySpinBox) self.addWidget(self.zLabel) self.addWidget(self.zSpinBox) self.addSpacing(10) self.busyIndicator = QProgressBar() self.busyIndicator.setMaximumWidth(200) self.busyIndicator.setMaximum(0) self.busyIndicator.setMinimum(0) self.busyIndicator.setVisible(False) self.busyIndicator.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self.addWidget( self.busyIndicator ) self.setStretchFactor(self.busyIndicator, 1) self.addStretch() self.addSpacing(10) self.positionCheckBox = QCheckBox() self.positionCheckBox.setChecked(True) self.positionCheckBox.setCheckable(True) self.positionCheckBox.setText("Position") self.addWidget(self.positionCheckBox) self.addSpacing(20) self.timeSpinBox = DelayedSpinBox(750) self.timeStartButton = QPushButton("Start") self.addWidget(self.timeStartButton) self.timeStartButton.clicked.connect(self._onTimeStartButtonClicked) self.timeSlider = QSlider(Qt.Horizontal) self.timeSlider.setMinimumWidth(10) self.timeSlider.setMaximumWidth(200) self.setToolTipTimeSliderCrop() self.addWidget(self.timeSlider) self.timeSlider.valueChanged.connect(self._onTimeSliderChanged) self.timeEndButton = QPushButton("End") self.timeEndButton.setFixedWidth(4*self.timeControlFontSize) self.timeStartButton.setFixedWidth(4*self.timeControlFontSize) self.setToolTipTimeButtonsCrop() self.addWidget(self.timeEndButton) self.timeEndButton.clicked.connect(self._onTimeEndButtonClicked) self.timeLabel = QLabel(" Time:") self.addWidget(self.timeLabel) timeControlFont = self.timeSpinBox.font() if self.timeControlFontSize > timeControlFont.pointSize(): timeControlFont.setPixelSize(self.timeControlFontSize) self.timeStartButton.setFont(timeControlFont) self.timeEndButton.setFont(timeControlFont) self.timeLabel.setFont(timeControlFont) self.timeSpinBox.setFont(timeControlFont) self.addWidget(self.timeSpinBox) self.timeSpinBox.delayedValueChanged.connect(self._onTimeSpinBoxChanged) def _onTimeStartButtonClicked(self): self.timeSpinBox.setValue(self.parent().parent().parent().editor.cropModel.get_roi_t()[0]) def _onTimeEndButtonClicked(self): self.timeSpinBox.setValue(self.parent().parent().parent().editor.cropModel.get_roi_t()[1]) def _onTimeSpinBoxChanged(self): editor = self.parent().parent().parent().editor cropModel = editor.cropModel minValueT = cropModel.get_roi_t()[0] maxValueT = cropModel.get_roi_t()[1] if cropModel.get_scroll_time_outside_crop(): if minValueT > self.timeSpinBox.value() or maxValueT < self.timeSpinBox.value(): for imgView in editor.imageViews: imgView._croppingMarkers._shading_item.set_paint_full_frame(True) else: for imgView in editor.imageViews: imgView._croppingMarkers._shading_item.set_paint_full_frame(False) self.timeSlider.setValue(self.timeSpinBox.value()) else: for imgView in editor.imageViews: imgView._croppingMarkers._shading_item.set_paint_full_frame(False) if minValueT > self.timeSpinBox.value(): self.timeSlider.setValue(minValueT) elif maxValueT < self.timeSpinBox.value(): self.timeSlider.setValue(maxValueT) elif minValueT <= self.timeSpinBox.value() and self.timeSpinBox.value() <= maxValueT: self.timeSlider.setValue(self.timeSpinBox.value()) def _onTimeSliderChanged(self): cropModel = self.parent().parent().parent().editor.cropModel minValueT = cropModel.get_roi_t()[0] maxValueT = cropModel.get_roi_t()[1] if cropModel.get_scroll_time_outside_crop(): self.timeSpinBox.setValue(self.timeSlider.value()) else: if minValueT > self.timeSlider.value(): self.timeSpinBox.setValue(minValueT) self.timeSlider.setValue(minValueT) elif self.timeSlider.value() > maxValueT: self.timeSpinBox.setValue(maxValueT) self.timeSlider.setValue(maxValueT) elif minValueT <= self.timeSlider.value() and self.timeSlider.value() <= maxValueT: self.timeSpinBox.setValue(self.timeSlider.value()) def _handlePositionBoxValueChanged(self, axis, value): new_position = [self.xSpinBox.value(), self.ySpinBox.value(), self.zSpinBox.value()] changed_axis = ord(axis) - ord('x') new_position[changed_axis] = value self.positionChanged.emit(*new_position) def updateShape5D(self, shape5D): self.timeSpinBox.setMaximum(shape5D[0]-1) self.xSpinBox.setMaximum(shape5D[1]-1) self.ySpinBox.setMaximum(shape5D[2]-1) self.zSpinBox.setMaximum(shape5D[3]-1) def updateShape5Dcropped(self, shape5DcropMin, shape5Dmax): self.timeSpinBox.setMaximum(shape5Dmax[0]-1) self.xSpinBox.setMaximum(shape5Dmax[1]-1) self.ySpinBox.setMaximum(shape5Dmax[2]-1) self.zSpinBox.setMaximum(shape5Dmax[3]-1) self.timeSlider.setMaximum(shape5Dmax[0]-1) self.timeSpinBox.setValue(shape5DcropMin[0]) self.xSpinBox.setValue(shape5DcropMin[1]) self.ySpinBox.setValue(shape5DcropMin[2]) self.zSpinBox.setValue(shape5DcropMin[3]) self.timeSlider.setValue(shape5DcropMin[0]) def setMouseCoords(self, x, y, z): self.xSpinBox.setValueWithoutSignal(x) self.ySpinBox.setValueWithoutSignal(y) self.zSpinBox.setValueWithoutSignal(z)
class SGMapTool(QgsMapTool): """A map tool that lets you click on a parcel to download its SG Diagram. """ def __init__(self, iface, provinces_layer): """Constructor. :param iface: A QGIS QgisInterface instance. :type iface: QgisInterface :param provinces_layer: A layer containing provincial boundaries. :type provinces_layer: QgsVectorLayer """ canvas = iface.mapCanvas() QgsMapTool.__init__(self, canvas) self.canvas = canvas self.iface = iface self.provinces_layer = provinces_layer self.message_bar = None self.progress_bar = None def canvasPressEvent(self, event): """Slot called when a mouse press occurs on the canvas. :param event: Canvas event containing position of click, which button was clicked etc. """ pass def canvasMoveEvent(self, event): """Slot called when a mouse move event occurs on the canvas. :param event: Canvas event containing position of click, which button was clicked etc. """ pass def setup_messagebar(self): """Setup a QgsMessageBar for use from callback and user notifications. """ if self.message_bar is not None: return self.message_bar = self.iface.messageBar().createMessage( self.tr('SG Diagram Downloader'), self.tr('Please stand by while download process is in progress.'), self.iface.mainWindow()) # Set up message bar for progress reporting self.progress_bar = QProgressBar() self.progress_bar.setMaximumWidth(150) self.progress_bar.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.message_bar.layout().addWidget(self.progress_bar) self.iface.messageBar().pushWidget( self.message_bar, self.iface.messageBar().INFO) def canvasReleaseEvent(self, event): """Slot called when the mouse button is released on the canvas. :param event: Canvas event containing position of click, which button was clicked etc. """ if not event.button() == Qt.LeftButton: return def progress_callback(current, maximum, message=None): """GUI based callback implementation for showing progress. :param current: Current progress. :type current: int :param maximum: Maximum range (point at which task is complete. :type maximum: int :param message: Optional message to display in the progress bar :type message: str, QString """ if message is not None: self.message_bar.setText(message) if self.progress_bar is not None: self.progress_bar.setMaximum(maximum) self.progress_bar.setValue(current) self.iface.messageBar().pushMessage( self.tr('SG Downloader.'), self.tr('Preparing for download'), level=QgsMessageBar.INFO) # No need to check that it is a valid, polygon layer # as the QAction for this map tool already does that layer = self.canvas.currentLayer() place = self.toMapCoordinates(event.pos()) rectangle = point_to_rectangle(place) request = QgsFeatureRequest(QgsFeatureRequest.FilterRect) # Ensure only those features really intersecting the rect are returned request.setFlags(QgsFeatureRequest.ExactIntersect) request.setFilterRect(rectangle) polygons = layer.getFeatures(request) feature = QgsFeature() fetch_list = [] all_fields = layer.pendingFields() text_fields = [] # Ignore any columns that don't contain text data for field in all_fields: if field.typeName() == 'TEXT': text_fields.append(field) self.setup_messagebar() sg_field = None while polygons.nextFeature(feature): geom = feature.geometry() attributes = feature.attributes() matched = False sg_code = None if sg_field is None: for field in text_fields: value = str(feature[field.name()]) if not is_valid_sg_code(value): continue sg_field = field.name() fetch_list.append(value) else: # We already know which column has SG codes value = str(feature[sg_field]) fetch_list.append(value) if len(fetch_list) == 0: self.iface.messageBar().pushMessage( self.tr('SG Downloader.'), self.tr('No parcels found with a valid 21 Digit code'), level=QgsMessageBar.WARNING, duration=10) return province = province_for_point(place, self.provinces_layer) result = '' output_path = diagram_directory() for sg_code in fetch_list: result += download_sg_diagram( sg_code, province, output_path, progress_callback) log = file('sg_downloader.log', 'a') log.write(result) log.close()
class Main(QMainWindow): def __init__(self): global debug QMainWindow.__init__(self) self.mainWidget = QWidget(self) self.statusBar = self.statusBar() self.progressBar = QProgressBar() self.enterButton = QPushButton(self) if debug: self.line = QLineEdit(self) self.initialize_ui() def initialize_ui(self): global debug if debug: self.line.setMinimumSize(400, 30) self.line.setStyleSheet("font-size: 15px;") self.enterButton.resize(0, 0) self.enterButton.clicked.connect(self.press_enter) self.enterButton.setShortcut("Return") self.progressBar.setMaximumWidth(120) self.webView = QWebView(loadProgress=self.progressBar.setValue, loadFinished=self.progressBar.hide, loadStarted=self.progressBar.show, titleChanged=self.setWindowTitle) self.webView.setMinimumSize(400, 400) direct = QDir('resources/index.html') self.webView.load(QUrl('file:///' + direct.absolutePath())) self.webView.urlChanged.connect(self.update_url) self.webView.page().linkHovered.connect(self.show_link_hovered) grid = QGridLayout() if debug: grid.addWidget(self.line, 0, 3, 1, 1) grid.addWidget(self.webView, 2, 0, 1, 6) self.mainWidget.setLayout(grid) self.setGeometry(50, 50, 1360, 768) self.setWindowTitle("SRSS") self.statusBar.addPermanentWidget(self.progressBar) self.statusBar.hide() self.setCentralWidget(self.mainWidget) def press_enter(self): global url url = self.line.text() http = "http://" www = "www." if www in url and http not in url: url = http + url elif "." not in url: url = "http://www.google.com/search?q=" + url elif http in url and www not in url: url = url[:7] + www + url[7:] elif http and www not in url: url = http + www + url self.line.setText(url) self.webView.load(QUrl(url)) self.statusBar.show() def update_url(self): self.line.setText(self.webView.url().toString()) def show_link_hovered(self, l): self.statusBar.showMessage(l)
class QuadStatusBar(QHBoxLayout): positionChanged = pyqtSignal(int, int, int) # x,y,z def __init__(self, parent=None ): QHBoxLayout.__init__(self, parent) self.setContentsMargins(0,4,0,0) self.setSpacing(0) self.timeControlFontSize = 12 def showXYCoordinates(self): self.zLabel.setHidden(True) self.zSpinBox.setHidden(True) def showXYZCoordinates(self): self.zLabel.setHidden(False) self.zSpinBox.setHidden(False) def hideTimeSlider(self,flag): self.timeSlider.setHidden(flag) self.timeEndButton.setHidden(flag) self.timeStartButton.setHidden(flag) def setToolTipTimeButtonsCrop(self,croppingFlag=False): if croppingFlag==True: self.timeStartButton.setToolTip("Set the time coordinate to the beginning of the current crop.") self.timeEndButton.setToolTip("Set the time coordinate to the end of the current crop.") self.timePreviousButton.setToolTip("Set the time coordinate to the previous time frame.") self.timeNextButton.setToolTip("Set the time coordinate to the next time frame.") else: self.timeStartButton.setToolTip("Set the time coordinate to the beginning of the current dataset.") self.timeEndButton.setToolTip("Set the time coordinate to the end of the current dataset.") self.timePreviousButton.setToolTip("Set the time coordinate to the previous time frame.") self.timeNextButton.setToolTip("Set the time coordinate to the next time frame.") def setToolTipTimeSliderCrop(self,croppingFlag=False): if croppingFlag==True: self.timeSlider.setToolTip("Choose the time coordinate of the current crop.") else: self.timeSlider.setToolTip("Choose the time coordinate of the current dataset.") def createQuadViewStatusBar(self, xbackgroundColor, xforegroundColor, ybackgroundColor, yforegroundColor, zbackgroundColor, zforegroundColor): self.xLabel, self.xSpinBox = _get_pos_widget('X', xbackgroundColor, xforegroundColor) self.yLabel, self.ySpinBox = _get_pos_widget('Y', ybackgroundColor, yforegroundColor) self.zLabel, self.zSpinBox = _get_pos_widget('Z', zbackgroundColor, zforegroundColor) self.xSpinBox.delayedValueChanged.connect( partial(self._handlePositionBoxValueChanged, 'x') ) self.ySpinBox.delayedValueChanged.connect( partial(self._handlePositionBoxValueChanged, 'y') ) self.zSpinBox.delayedValueChanged.connect( partial(self._handlePositionBoxValueChanged, 'z') ) self.addWidget(self.xLabel) self.addWidget(self.xSpinBox) self.addWidget(self.yLabel) self.addWidget(self.ySpinBox) self.addWidget(self.zLabel) self.addWidget(self.zSpinBox) self.addSpacing(10) self.busyIndicator = QProgressBar() self.busyIndicator.setMaximumWidth(200) self.busyIndicator.setMaximum(0) self.busyIndicator.setMinimum(0) self.busyIndicator.setVisible(False) self.busyIndicator.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self.addWidget( self.busyIndicator ) self.setStretchFactor(self.busyIndicator, 1) self.addStretch() self.addSpacing(10) self.positionCheckBox = QCheckBox() self.positionCheckBox.setChecked(False) self.positionCheckBox.setCheckable(True) self.positionCheckBox.setText("Position") self.addWidget(self.positionCheckBox) self.addSpacing(20) self.timeSpinBox = DelayedSpinBox(750) self.timeStartButton = QPushButton("|<") self.addWidget(self.timeStartButton) self.timeStartButton.clicked.connect(self._onTimeStartButtonClicked) self.timePreviousButton = QPushButton("<") self.addWidget(self.timePreviousButton) self.timePreviousButton.clicked.connect(self._onTimePreviousButtonClicked) self.timePreviousButton.setFixedWidth(4*self.timeControlFontSize) self.timeSlider = QSlider(Qt.Horizontal) self.timeSlider.setMinimumWidth(10) self.timeSlider.setMaximumWidth(200) self.setToolTipTimeSliderCrop() self.addWidget(self.timeSlider) self.timeSlider.valueChanged.connect(self._onTimeSliderChanged) self.timeNextButton = QPushButton(">") self.addWidget(self.timeNextButton) self.timeNextButton.clicked.connect(self._onTimeNextButtonClicked) self.timeNextButton.setFixedWidth(4*self.timeControlFontSize) self.timeEndButton = QPushButton(">|") self.timeEndButton.setFixedWidth(4*self.timeControlFontSize) self.timeStartButton.setFixedWidth(4*self.timeControlFontSize) self.setToolTipTimeButtonsCrop() self.addWidget(self.timeEndButton) self.timeEndButton.clicked.connect(self._onTimeEndButtonClicked) self.timeLabel = QLabel(" Time:") self.addWidget(self.timeLabel) timeControlFont = self.timeSpinBox.font() if self.timeControlFontSize > timeControlFont.pointSize(): timeControlFont.setPixelSize(2*self.timeControlFontSize) self.timeStartButton.setFont(timeControlFont) self.timeEndButton.setFont(timeControlFont) self.timeLabel.setFont(timeControlFont) self.timeSpinBox.setFont(timeControlFont) self.addWidget(self.timeSpinBox) self.timeSpinBox.delayedValueChanged.connect(self._onTimeSpinBoxChanged) def _onTimeStartButtonClicked(self): self.timeSpinBox.setValue(self.parent().parent().parent().editor.cropModel.get_roi_t()[0]) def _onTimeEndButtonClicked(self): self.timeSpinBox.setValue(self.parent().parent().parent().editor.cropModel.get_roi_t()[1]) def _onTimePreviousButtonClicked(self): self.timeSpinBox.setValue(self.timeSpinBox.value()-1) def _onTimeNextButtonClicked(self): self.timeSpinBox.setValue(self.timeSpinBox.value()+1) def _onTimeSpinBoxChanged(self): editor = self.parent().parent().parent().editor cropModel = editor.cropModel minValueT = cropModel.get_roi_t()[0] maxValueT = cropModel.get_roi_t()[1] if cropModel.get_scroll_time_outside_crop(): if minValueT > self.timeSpinBox.value() or maxValueT < self.timeSpinBox.value(): for imgView in editor.imageViews: imgView._croppingMarkers._shading_item.set_paint_full_frame(True) else: for imgView in editor.imageViews: imgView._croppingMarkers._shading_item.set_paint_full_frame(False) self.timeSlider.setValue(self.timeSpinBox.value()) else: for imgView in editor.imageViews: imgView._croppingMarkers._shading_item.set_paint_full_frame(False) if minValueT > self.timeSpinBox.value(): self.timeSlider.setValue(minValueT) elif maxValueT < self.timeSpinBox.value(): self.timeSlider.setValue(maxValueT) elif minValueT <= self.timeSpinBox.value() and self.timeSpinBox.value() <= maxValueT: self.timeSlider.setValue(self.timeSpinBox.value()) def _onTimeSliderChanged(self): cropModel = self.parent().parent().parent().editor.cropModel minValueT = cropModel.get_roi_t()[0] maxValueT = cropModel.get_roi_t()[1] if cropModel.get_scroll_time_outside_crop(): self.timeSpinBox.setValue(self.timeSlider.value()) else: if minValueT > self.timeSlider.value(): self.timeSpinBox.setValue(minValueT) self.timeSlider.setValue(minValueT) elif self.timeSlider.value() > maxValueT: self.timeSpinBox.setValue(maxValueT) self.timeSlider.setValue(maxValueT) elif minValueT <= self.timeSlider.value() and self.timeSlider.value() <= maxValueT: self.timeSpinBox.setValue(self.timeSlider.value()) def _handlePositionBoxValueChanged(self, axis, value): new_position = [self.xSpinBox.value(), self.ySpinBox.value(), self.zSpinBox.value()] changed_axis = ord(axis) - ord('x') new_position[changed_axis] = value self.positionChanged.emit(*new_position) def updateShape5D(self, shape5D): self.timeSpinBox.setMaximum(shape5D[0]-1) self.xSpinBox.setMaximum(shape5D[1]-1) self.ySpinBox.setMaximum(shape5D[2]-1) self.zSpinBox.setMaximum(shape5D[3]-1) def updateShape5Dcropped(self, shape5DcropMin, shape5Dmax): self.timeSpinBox.setMaximum(shape5Dmax[0]-1) self.xSpinBox.setMaximum(shape5Dmax[1]-1) self.ySpinBox.setMaximum(shape5Dmax[2]-1) self.zSpinBox.setMaximum(shape5Dmax[3]-1) self.timeSlider.setMaximum(shape5Dmax[0]-1) self.timeSpinBox.setValue(shape5DcropMin[0]) self.xSpinBox.setValue(shape5DcropMin[1]) self.ySpinBox.setValue(shape5DcropMin[2]) self.zSpinBox.setValue(shape5DcropMin[3]) self.timeSlider.setValue(shape5DcropMin[0]) def setMouseCoords(self, x, y, z): self.xSpinBox.setValueWithoutSignal(x) self.ySpinBox.setValueWithoutSignal(y) self.zSpinBox.setValueWithoutSignal(z)
class FeedLol(QMainWindow): def __init__(self, parent = None): QMainWindow.__init__(self, parent) self.setWindowTitle("FeedLol") self.aboutAction = QAction(QIcon("data/icons/help-about.svg"), "&About FeedLol...", self) self.connect(self.aboutAction, SIGNAL("triggered()"), self.slotAbout) self.reloadAction = QAction(QIcon("data/icons/view-refresh.svg"), "&Reload", self) self.reloadAction.setShortcut(QKeySequence.Refresh) self.homeAction = QAction(QIcon("data/icons/go-home.svg"), "Go &Home", self) self.homeAction.setShortcut("Alt+Home") self.userAction = QAction(QIcon("data/icons/user-identity.svg"), "&Me", self) self.userAction.setShortcut("Ctrl+M") self.logoutAction = QAction(QIcon("data/icons/dialog-close.svg"), "Log&out", self) self.logoutAction.setShortcut(QKeySequence.Close) self.settingsAction = QAction(QIcon("data/icons/configure.svg"), "&Preferences...", self) self.connect(self.settingsAction, SIGNAL("triggered()"), self.slotSettings) self.toolbar = QToolBar("Toolbar", self) self.toolbar.setObjectName("toolbar") self.toolbar.addAction(self.homeAction) self.toolbar.addAction(self.userAction) self.toolbar.addAction(self.reloadAction) self.toolbar.addSeparator() self.toolbar.addAction(self.logoutAction) self.toolbar.addSeparator() self.toolbar.addAction(self.settingsAction) self.toolbar.addAction(self.aboutAction) self.addToolBar(self.toolbar) self.loadStatus = QProgressBar(self) self.loadStatus.setRange(0, 100) self.loadStatus.setMaximumWidth(200) self.loadStatus.setTextVisible(False) self.loadStatus.hide() self.statusBar().addPermanentWidget(self.loadStatus) self.feedView = FeedView(self) self.setCentralWidget(self.feedView) self.connect(self.feedView, SIGNAL("titleChanged(const QString&)"), self.slotSetTitle) self.connect(self.feedView, SIGNAL("statusBarMessage(const QString&)"), self.statusBar(), SLOT("showMessage(const QString&)")) self.connect(self.feedView, SIGNAL("loadStarted()"), self.loadStart) self.connect(self.feedView, SIGNAL("loadFinished(bool)"), self.loadStop) self.connect(self.feedView, SIGNAL("loadProgress(int)"), self.loadProgress) self.connect(self.reloadAction, SIGNAL("triggered()"), self.feedView.reload) self.connect(self.homeAction, SIGNAL("triggered()"), self.feedView.goHome) self.connect(self.userAction, SIGNAL("triggered()"), self.feedView.goToUserPage) self.connect(self.logoutAction, SIGNAL("triggered()"), self.feedView.logout) self.connect(self.feedView.page(), SIGNAL("linkHovered(const QString&, const QString&, const QString&)"), self.linkHovered) self.settingsDialog = SettingsDialog(self.feedView, self) settings = QSettings() if settings.contains("proxy/type"): proxy = QNetworkProxy() proxyType = settings.value("proxy/type").toInt()[0] proxy.setType( (proxyType == 2) and QNetworkProxy.Socks5Proxy or ( (proxyType == 1) and QNetworkProxy.HttpProxy or QNetworkProxy.NoProxy ) ) if proxy.type() != QNetworkProxy.NoProxy: proxy.setHostName(settings.value("proxy/host").toString()) proxy.setPort(settings.value("proxy/port").toInt()[0]) if settings.value("proxy/user").toString(): proxy.setUser(settings.value("proxy/user").toString()) proxy.setPassword(settings.value("proxy/password").toString()) QNetworkProxy.setApplicationProxy(proxy) if settings.contains("mainWindow/geometry"): self.restoreGeometry(settings.value("mainWindow/geometry").toByteArray()) else: self.resize(320,480) if settings.contains("mainWindow/state"): self.restoreState(settings.value("mainWindow/state").toByteArray()) self.feedView.goHome() def saveConfig(self): settings = QSettings() settings.setValue("mainWindow/geometry", QVariant(self.saveGeometry())) settings.setValue("mainWindow/state", QVariant(self.saveState())) session = self.feedView.siteServer.session from cPickle import dumps session = dumps(session) settings.setValue("session", QVariant(session)) proxy = QNetworkProxy.applicationProxy() proxyType = (proxy.type() == QNetworkProxy.Socks5Proxy) and 2 or ( (proxy.type() == QNetworkProxy.HttpProxy) and 1 or 0 ) settings.setValue("proxy/type", QVariant(proxyType)) settings.setValue("proxy/host", QVariant(proxy.hostName())) settings.setValue("proxy/port", QVariant(proxy.port())) settings.setValue("proxy/user", QVariant(proxy.user())) settings.setValue("proxy/password", QVariant(proxy.password())) def slotAbout(self): from PyQt4.QtGui import QMessageBox QMessageBox.about(self, "FeedLol", "<h2>FeedLol 0.1</h2><p>Copyright © 2008 <a href=\"mailto:[email protected]\">Bodil Stokke</a></p>") def slotSettings(self): self.settingsDialog.updateSettings() if self.settingsDialog.exec_() == QDialog.Accepted: self.settingsDialog.applySettings() def slotSetTitle(self, title): self.setWindowTitle("FeedLol: " + title) def loadStart(self): self.loadStatus.show() def loadStop(self): self.loadStatus.hide() def loadProgress(self, progress): self.loadStatus.setValue(progress) def linkHovered(self, url, title, text): if url and QUrl(url).scheme() != "chrome": self.statusBar().showMessage(url) else: self.statusBar().clearMessage()
class SGMapTool(QgsMapTool): """A map tool that lets you click on a parcel to download its SG Diagram. """ def __init__(self, iface): """Constructor. :param iface: A QGIS QgisInterface instance. :type iface: QgisInterface """ canvas = iface.mapCanvas() QgsMapTool.__init__(self, canvas) self.canvas = canvas self.iface = iface self.message_bar = None self.progress_bar = None self.output_directory = None self.log_file = None self.restore_state() sg_diagrams_database = os.path.join(DATA_DIR, 'sg_diagrams.sqlite') self.db_manager = DatabaseManager(sg_diagrams_database) def canvasPressEvent(self, event): """Slot called when a mouse press occurs on the canvas. :param event: Canvas event containing position of click, which button was clicked etc. """ pass def canvasMoveEvent(self, event): """Slot called when a mouse move event occurs on the canvas. :param event: Canvas event containing position of click, which button was clicked etc. """ pass def setup_message_bar(self): """Setup a QgsMessageBar for use from callback and user notifications. """ if self.message_bar is not None: return self.message_bar = self.iface.messageBar().createMessage( self.tr('SG Diagram Downloader'), self.tr('Please stand by while download process is in progress.'), self.iface.mainWindow()) # Set up message bar for progress reporting self.progress_bar = QProgressBar() self.progress_bar.setMaximumWidth(150) self.progress_bar.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.message_bar.layout().addWidget(self.progress_bar) self.iface.messageBar().pushWidget(self.message_bar, self.iface.messageBar().INFO) def canvasReleaseEvent(self, event): """Slot called when the mouse button is released on the canvas. :param event: Canvas event containing position of click, which button was clicked etc. """ if not event.button() == Qt.LeftButton: return def progress_callback(current, maximum, message=None): """GUI based callback implementation for showing progress. :param current: Current progress. :type current: int :param maximum: Maximum range (point at which task is complete. :type maximum: int :param message: Optional message to display in the progress bar :type message: str, QString """ if message is not None: self.message_bar.setText(message) if self.progress_bar is not None: self.progress_bar.setMaximum(maximum) self.progress_bar.setValue(current) self.iface.messageBar().pushMessage(self.tr('SG Downloader.'), self.tr('Preparing for download'), level=QgsMessageBar.INFO, duration=10) # No need to check that it is a valid, polygon layer # as the QAction for this map tool already does that layer = self.canvas.currentLayer() place = self.toMapCoordinates(event.pos()) rectangle = point_to_rectangle(place) request = QgsFeatureRequest(QgsFeatureRequest.FilterRect) # Ensure only those features really intersecting the rect are returned request.setFlags(QgsFeatureRequest.ExactIntersect) request.setFilterRect(rectangle) polygons = layer.getFeatures(request) feature = QgsFeature() fetch_list = [] all_fields = layer.pendingFields() text_fields = [] # Ignore any columns that don't contain text data for field in all_fields: if field.typeName() == 'String' or field.typeName() == 'Text': text_fields.append(field) self.setup_message_bar() sg_field = None while polygons.nextFeature(feature): # geom = feature.geometry() # attributes = feature.attributes() # matched = False # sg_code = None if sg_field is None: for field in text_fields: value = str(feature[field.name()]) if not is_valid_sg_code(value): continue sg_field = field.name() fetch_list.append(value) else: # We already know which column has SG codes value = str(feature[sg_field]) fetch_list.append(value) if len(fetch_list) == 0: self.iface.messageBar().pushMessage( self.tr('SG Downloader.'), self.tr('No parcels found with a valid 21 Digit code'), level=QgsMessageBar.WARNING, duration=10) return province = province_for_point(self.db_manager, place) report = '' sg_diagrams_database = os.path.join(DATA_DIR, 'sg_diagrams.sqlite') data_manager = DatabaseManager(sg_diagrams_database) i = 0 for sg_code in fetch_list: i += 1 message = 'Downloading SG Code %s from %s' % (sg_code, province) progress_callback(i, len(fetch_list), message) report += download_sg_diagram(data_manager, sg_code, province, self.output_directory, callback=progress_callback) data_manager.close() try: write_log(report, self.log_file) except IOError as e: print e self.show_log(report, self.log_file) def show_log(self, log, log_path): """Show log dialog. :param log: Log in text :type log: str :param log_path: Log file path. :type log_path: str """ dialog = LogDialog(self.iface) dialog.set_log(log, log_path) dialog.exec_() def restore_state(self): """Restore state from previous session.""" home_user = expanduser("~") default_log_file = os.path.join(home_user, 'sg_downloader.log') previous_settings = QSettings() self.output_directory = str( previous_settings.value('sg-diagram-downloader/output_directory', home_user, type=str)) self.log_file = str( previous_settings.value('sg-diagram-downloader/log_file', default_log_file, type=str))
class MSMainWindow(QMainWindow): """Gui of the main window""" #MAX_RECENT_FILES = 10 #start putting links spyder numpy scipy et tutti quanti links=('http://numpy.scipy.org/', 'http://packages.python.org/spyder/', 'http://www.riverbankcomputing.co.uk/software/pyqt/intro') pluginPath=path.normcase('pluginmanager/plugins/') def __init__(self, availablePlugins): """ Constructor with all the models needed setup menus """ QMainWindow.__init__(self) self.setDockOptions(QMainWindow.VerticalTabs | QMainWindow.AnimatedDocks) self.plugins = availablePlugins self.pluginsInst=[] settings=QSettings('INRA/INSA', '-'.join([QApplication.instance().APPLICATION_NAME_STR, QApplication.instance().VERSION_STR])) self.recentFiles = list(settings.value("RecentFiles").toStringList()) self.setStyleSheet(stylesheet) self.pipeline = MSPipelineToolBar("Pipeline toolbar", parent=self) self.addToolBar(0x1,self.pipeline) self._setupModels() self._setupUi() self._setupMenus() def _setupModels(self): """ Warning:Causes segfault when horizontal labels set to True on aura peu etre a la fin un model par sampleList c'est ce qui parait le plus logique """ #drag and drop table sample self.sampleModel = QStandardItemModel(self) self.sampleModel.setHorizontalHeaderLabels(["Sample", "Class"]) #treeView1 self.spectraModel = QStandardItemModel(self) #treeview2 self.peakModel = QStandardItemModel(self) #treeview3 self.clusterModel = QStandardItemModel(self) def _setupMenus(self): #file self.fileMenu = QMenu('&File') self.fileMenu.setTearOffEnabled(True) self.op=QMenu("&Open...",self.fileMenu) self.op.setIcon(QIcon(path.normcase("gui/icons/fileopen.png"))) open_=QAction("&Open rawfiles", self) open_.setToolTip("Open an mzXML or netCDF file") open_.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_O)) open_icon=QIcon(path.normcase("gui/icons/fileopen.png")) open_.setIcon(open_icon) self.op.addAction(open_) load_=QAction("&Open projects...", self) load_.setToolTip("load binary file containing saved objects") load_.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_S)) load_icon=QIcon(QPixmap(path.normcase("gui/icons/project_open.png"))) load_.setIcon(load_icon) self.op.addAction(load_) self.fileMenu.addMenu(self.op) save_=QAction("&Save...", self) save_.setToolTip("save the actual application model") save_.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_S)) save_icon=QIcon(path.normcase("gui/icons/save_all.png")) save_.setIcon(save_icon) self.fileMenu.addAction(save_) pkl = QAction("&load a peaklist", self) #TODO:load peaklist pkl.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_P)) pkl.setToolTip("load a peaklist and process it") pkl.setIcon(QIcon(path.normcase("gui/icons/featuredetect.png"))) self.fileMenu.addAction(pkl) convert_=QAction("&Convert...", self) convert_.setEnabled(False) convert_.setToolTip("Convert a .wiff file if Analyst(c) is installed") convert_icon=QIcon(path.normcase("gui/icons/goto.png")) convert_.setIcon(convert_icon) self.fileMenu.addAction(convert_) a = self.fileMenu.addAction(QIcon(path.normcase("gui/icons/process.png")), "&Launch a batch") a.setEnabled(False) b = self.fileMenu.addAction(QIcon(path.normcase("gui/icons/process.png")), "&Merge") b.setToolTip("Merge MRM file") #b.setEnabled(False) self.fileMenu.addSeparator() # # for i in xrange(self.MAX_RECENT_FILES): # a = QAction('', self) # a.setVisible(False) # self.fileMenu.addAction(a) # # for i in xrange(min(self.MAX_RECENT_FILES, len(self.recentFiles))): # self.fileMenu.actions()[5+i].setVisible(True) # self.fileMenu.actions()[5+i].setText(self.recentFiles[i].split('/')[-1]) exit_action =QAction("&Exit", self) exit_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_Q)) exit_action.setIcon(QIcon(QPixmap(path.normcase('gui/icons/exit.png')))) self.fileMenu.addAction(exit_action) self.menuBar().addMenu(self.fileMenu) self.editMenu=QMenu("&Edit") self.editMenu.setTearOffEnabled(True) self.editMenu.addAction(QIcon(path.normcase('gui/icons/edit_undo.png')), '&Undo...') self.editMenu.addAction(QIcon(path.normcase('gui/icons/edit_redo.png')), '&Redo...') self.editMenu.actions()[0].setEnabled(False) self.editMenu.actions()[1].setEnabled(False) self.editMenu.addSeparator() self.editMenu.addAction(QIcon(path.normcase('gui/icons/run.png')), '&Preferences') self.exportMenu = QMenu("&Export...") self.exportMenu.setIcon(QIcon(path.normcase('gui/icons/file_export.png'))) self.exportMenu.addAction("&Peaklist") self.exportMenu.addAction("&Clusters intensity matrix") self.editMenu.addMenu(self.exportMenu) self.menuBar().addMenu(self.editMenu) #view self.viewMenu =QMenu("&View") self.viewMenu.setTearOffEnabled(True) self.viewMenu.addAction(QIcon(path.normcase('gui/icons/window_duplicate')), "&Cascade View", self.mdiArea.cascadeSubWindows, QKeySequence(Qt.CTRL + Qt.Key_K)) self.viewMenu.addAction(QIcon(path.normcase('gui/icons/view_icon')), "&Title View", self.mdiArea.tileSubWindows, QKeySequence(Qt.CTRL + Qt.Key_N)) self.viewMenu.addAction(QIcon(path.normcase("gui/icons/stop_process.png")), "&Close all subWindows", self.mdiArea.closeAllSubWindows, QKeySequence(Qt.CTRL+Qt.Key_W)) self.plotting =QMenu("&Plotting...") self.plotting.setIcon(QIcon(QPixmap(path.normcase("gui/icons/plot.png")))) self.plotting.addAction("&3D Plot") #self.plotting.addAction("&Cytoscape web") self.plotting.addAction("&Spectrogram Plot") #self.multiplePlot = QAction("&Visualize Raw/Treated Data", self) #self.multiplePlot.setCheckable(True) #self.multiplePlot.setEnabled(False) #self.sub_plot_.addAction(self.multiplePlot) self.viewMenu.addMenu(self.plotting) self.viewMenu.addSeparator() self.show_hide=QMenu("&Show/Hide") m=self.createPopupMenu() m.setTitle("&Show/Hide") self.viewMenu.addMenu(m) #self.pref = QMenu("&Preferences") #self.pref.addAction(self.multiplePlot) #self.viewMenu.addMenu(self.pref) self.menuBar().addMenu(self.viewMenu) #algorithm self.algoMenu= QMenu("&Algorithm") self.algoMenu.setTearOffEnabled(True) self.preProcessing=QMenu("&PreProcessing(experimental)") self.preProcessing.addAction("&Smoothing raw data...") self.preProcessing.addAction("&Cut off raw data...") self.preProcessing.addAction('&Calibration (mz dimension)') self.preProcessing.addAction("&Resize sample...") self.algoMenu.addMenu(self.preProcessing) self.peakPickingMenu = QMenu("&Peack Picking & Alignement(XCMS)", self) self.peakPickingMenu.setIcon(QIcon(path.normcase("gui/icons/pickedpeakicon.png"))) matched = QAction("&MatchedFiltered", self) matched.setIcon(QIcon(path.normcase('gui/icons/RLogo'))) matched.setToolTip("Peak Detection and Integration using MatchedFiltered algorithm") self.peakPickingMenu.addAction(matched) centwave=QAction("&CentWave", self) centwave.setIcon(QIcon(path.normcase('gui/icons/RLogo'))) centwave.setToolTip("Peak Detection and Integration using CentWave algorithm") self.peakPickingMenu.addAction(centwave) #peak_.setShortcut(.QKeySequence(CTRL + Key_P)) # peak_icon=.QIcon(.QPixmap(path.normcase("gui/icons/pickedpeakicon.png"))) #peak_.setIcon(peak_icon) self.algoMenu.addMenu(self.peakPickingMenu) self.alignment = QMenu("&Alignment") self.alignment.setIcon(QIcon(path.normcase('gui/icons/format_indent_more.png'))) self.alignment.addAction("&Polynomial fitting(exp)") self.alignment.addAction("&DynamicTimeWarping") self.alignment.addAction("&ObiWarp") self.alignment.actions()[2].setEnabled(False) self.algoMenu.addMenu(self.alignment) self.algoMenu.addAction("Normalization") clust_ = QAction("&Clustering", self) clust_.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_L)) clust_icon=QIcon(QPixmap(path.normcase("gui/icons/cluster.png"))) clust_.setIcon(clust_icon) self.algoMenu.addAction(clust_) id_ = QAction("&Identification", self) id_.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_I)) id_.setToolTip("Try to identify peaks with several methods") id_.setIcon(QIcon(QPixmap(path.normcase("gui/icons/findcompound.png")))) self.algoMenu.addAction(id_) self.menuBar().addMenu(self.algoMenu) #tools self.toolsMenu =QMenu("&Tools") self.toolsMenu.setTearOffEnabled(True) web = QAction("&Web Browser", self) web.setIcon(QIcon(QPixmap(path.normcase("gui/icons/applications_internet.png")))) self.toolsMenu.addAction(web) #cyto = QAction("&cytoscape", self) #cyto_icon =QIcon(QPixmap(path.normcase("gui/icons/cytoscape.jpeg"))) #cyto.setIcon(cyto_icon) #self.toolsMenu.addAction(cyto) editor = QAction("&Editor", self) editor.setIcon(QIcon(QPixmap(path.normcase("gui/icons/document_sign.png")))) self.toolsMenu.addAction(editor) pet=QAction("&Short Periodic Table", self) pet.setIcon(QIcon(QPixmap(path.normcase("gui/icons/pet.jpg")))) self.toolsMenu.addAction(pet) self.menuBar().addMenu(self.toolsMenu) #plugins self.pluginMenu = QMenu('&Plugins') self.pluginMenu.setTearOffEnabled(True) instPl= QAction("&Install a plugin", self) instPl.setIcon(QIcon(path.normcase('gui/icons/pluginInstall.png'))) self.pluginMenu.addAction(instPl) self.launchingMenu = QMenu("&Launch PLugins", self) self.launchingMenu.setIcon(QIcon(path.normcase('gui/icons/plugin'))) for plug in self.plugins: #fullname="".join([self.pluginPath, str(plug)]) mod=imp.load_source(self.__module__, plug) if mod.autoActivation: qApp=QApplication.instance() name=getattr(mod, 'className') cls=getattr(mod, name) p=cls(qApp.model, self, parent=self) #p=qApp.pluginManager.loadPlugin(qApp.model, self, plug.split('/')[-1]) self.pluginsInst.append(p) else: self.launchingMenu.addAction(plug.split('/')[-1]) self.pluginMenu.addMenu(self.launchingMenu) self.pluginMenu.addAction(QIcon(path.normcase("gui/icons/process_stop.png")), "&Remove loaded Plugin") self.menuBar().addMenu(self.pluginMenu) #about self.aboutMenu= QMenu("&About") self.aboutMenu.setTearOffEnabled(True) metms = QAction(QIcon(path.normcase('gui/icons/deluge.png')), "&about metMS...", self) self.aboutMenu.addAction(metms) pyqt = QAction("&about PyQt4...", self) pyqt_icon =QIcon(QPixmap(path.normcase("gui/icons/logo_QT4.png"))) pyqt.setIcon(pyqt_icon) self.aboutMenu.addAction(pyqt) metms = QAction("&metMS Documentation", self) metms_icon =QIcon(QPixmap(path.normcase("gui/icons/deluge.png"))) metms.setIcon(metms_icon) self.aboutMenu.addAction(metms) self.menuBar().addMenu(self.aboutMenu) def _setupUi(self, background=None): """ Make the GUI """ #mdi self.mdiArea = MSMdiArea(self) self.mdiArea.setBackground(QBrush(QPixmap(path.normcase('gui/icons/blac2.png'))))#QColor(Qt.blue).darker())) self.setCentralWidget(self.mdiArea) #sample dock widget self.sampleDockWidget = QDockWidget("Samples", self) #sampleWidget = QWidget() self.sampleTableView = MSDragFromTableView() self.sampleTableView.setModel(self.sampleModel) self.sampleTableView.setSelectionBehavior(1) self.sampleTableView.verticalHeader().hide() self.sampleTableView.verticalHeader().setDefaultSectionSize(15) self.sampleTableView.horizontalHeader().setDefaultSectionSize(150) self.sampleDockWidget.setWidget(self.sampleTableView)#sampleWidget) self.sampleDockWidget.visible=True #workflow dock self.workflowDockWidget = QDockWidget("Visualizer", self) self.workflowDockWidget.visible = True a=QWidget(self) v=QVBoxLayout(a) q=QToolBar() #self.workingSample = QLabel("Working Sample:None") #q.addWidget(self.workingSample) q.addWidget(QLabel("ppm :")) self.ppmEditer=QDoubleSpinBox() self.usePpm=QCheckBox("use ?") q.addWidget(self.ppmEditer) q.addWidget(self.usePpm) q.addSeparator() self.removeButton=QToolButton(self) self.removeButton.setIcon(QIcon(path.normcase("gui/icons/delete.png"))) q.addWidget(self.removeButton) self.markAsGood=QAction(QIcon(path.normcase("gui/icons/button_ok.png")),"mark peak as good", self) self.markAsBad=QAction(QIcon(path.normcase("gui/icons/stop.png")), "mark peak as bad", self) self.hideItem = QAction(QIcon(path.normcase("gui/icons/list_remove.png")), "Hide Item", self) q.addAction(self.markAsGood) q.addAction(self.markAsBad) q.addAction(self.hideItem) v.addWidget(q) self.tabWidget = QTabWidget() self.tab = QWidget() verticalLayout = QVBoxLayout(self.tab) self.treeView = MSToDropTableView() self.treeView.verticalHeader().setDefaultSectionSize(20) self.treeView.setModel(self.spectraModel) self.spectraLabel = QLabel("Sample: None") verticalLayout.addWidget(self.treeView) verticalLayout.addWidget(self.spectraLabel) self.tabWidget.addTab(self.tab, QIcon(path.normcase("gui/icons/spectrumicon.png")),"Spectra") self.tab_2 = QWidget() verticalLayout_4 = QVBoxLayout(self.tab_2) self.treeView_2 = MSToDropTableView()#MSTreeView(self.tab_2)# QTableView(self)# self.treeView_2.verticalHeader().setDefaultSectionSize(20) self.treeView_2.setModel(self.peakModel) self.peakLabel = QLabel("Sample: None") verticalLayout_4.addWidget(self.treeView_2) verticalLayout_4.addWidget(self.peakLabel) self.tabWidget.addTab(self.tab_2,QIcon(path.normcase("gui/icons/peakicon.png")), "Peaks List") self.tab_3 = QWidget() verticalLayout_5 = QVBoxLayout(self.tab_3) self.treeView_3 = MSToDropTreeView() self.treeView_3.setAnimated(True) self.treeView_3.setModel(self.clusterModel) self.clusterLabel = QLabel("Sample: None") verticalLayout_5.addWidget(self.treeView_3) verticalLayout_5.addWidget(self.clusterLabel) self.tabWidget.addTab(self.tab_3, QIcon(path.normcase("gui/icons/clustering.png")), "Clusters") self.tabWidget.setCurrentIndex(0) for l in (self.spectraLabel, self.peakLabel, self.clusterLabel): l.setAutoFillBackground(True) v.addWidget(self.tabWidget) self.workflowDockWidget.setWidget(a) self.addDockWidget(Qt.DockWidgetArea(0x2),self.workflowDockWidget) from gui.MetBaseGui import MSIsoCalculator self.isoCalc = MSIsoCalculator(self) self.isoCalcDockWidget=QDockWidget('isotopes calculation', self) self.isoCalcDockWidget.setWidget(self.isoCalc) self.addDockWidget(Qt.DockWidgetArea(0x2), self.isoCalcDockWidget) self.isoCalcDockWidget.setVisible(False) self.isoCalcDockWidget.visible=False from gui.MetBaseGui import FormulaGenerator self.generator=FormulaGenerator(self) self.generatorDockWidget=QDockWidget('formula generator', self) self.generatorDockWidget.setWidget(self.generator) self.addDockWidget(Qt.DockWidgetArea(0x2), self.generatorDockWidget) self.generatorDockWidget.setVisible(False) self.generatorDockWidget.visible=False self.compoundTreeView = MSCompoundTreeView(self) self.compoundDockWidget = QDockWidget("Compounds", self) self.compoundDockWidget.setWidget(self.compoundTreeView) self.addDockWidget(Qt.DockWidgetArea(0x2),self.compoundDockWidget) self.compoundDockWidget.setVisible(False) self.compoundDockWidget.visible=False self.comparativeTableView = QTableView(self) self.comparativeTableView.horizontalHeader().setStretchLastSection(True) self.comparativeTableView.verticalHeader().setDefaultSectionSize(20) self.comparativeDock = QDockWidget("Comparative View", self) self.comparativeDock.setWidget(self.comparativeTableView) self.addDockWidget(Qt.DockWidgetArea(0x8), self.comparativeDock) self.comparativeDock.setVisible(False) self.comparativeDock.visible = False self.tabifyDockWidget(self.compoundDockWidget, self.isoCalcDockWidget) self.tabifyDockWidget(self.isoCalcDockWidget, self.workflowDockWidget ) self.tabifyDockWidget(self.workflowDockWidget, self.generatorDockWidget) #set the end #WARNING: possible that the internal shell widget cause random segfault #with the error of QObject::killTimers...? not sure ! self.shell = QWidget()#InternalShell(namespace={'metms': QApplication.instance()}, # parent=self, # multithreaded=False) self.shellDock = QDockWidget("Python Shell", self) self.shellDock.setWindowIcon(QIcon(path.normcase('gui/icons/stop.png'))) self.shellDock.setWidget(self.shell) self.shellDock.setMinimumWidth(255) self.shellDock.visible=True self.addDockWidget(0x2, self.shellDock) self.addDockWidget(0x2, self.sampleDockWidget) self.tabifyDockWidget(self.shellDock, self.sampleDockWidget) self.pb = QProgressBar(self) self.pb.setMaximumWidth(245) self.stopProcess = QToolButton(self) self.stopProcess.setIcon(QIcon(path.normcase("gui/icons/process_stop.png"))) m = QMenu() #self.connect(m, SIGNAL('triggered(QAction*'), QApplication.instance().taskManager.abortByName) self.stopProcess.setMenu(m) self.stopProcess.setPopupMode(1) #Menu Button #self.connect(self.stopProcess, SIGNAL("clicked()"), self.stopThread) self.statusBar().addPermanentWidget(self.stopProcess) self.statusBar().addPermanentWidget(self.pb) def updateStopProcessMenu(self): """ update the menu of the stop process button, based directly on the processes stored by the task manager """ self.stopProcess.menu().clear() for c in QApplication.instance().taskManager: self.stopProcess.menu().addAction(c.title) #QApplication.instance().taskManager.abort(QApplication.instance().taskManager[-1]) def addMdiSubWindow(self, plot, title="", showMaximized=False): """ Allow addition of new window in the mdiarea """ win=self.mdiArea.addSubWindow(plot) #print "widget parent", plot.parent() win.setAttribute(Qt.WA_DeleteOnClose) #win.connect(win, SIGNAL('destroyed(QObject *)'), self.testdestroy) #plot.setParent(win) win.setWindowTitle(title) if showMaximized: win.showMaximized() else: win.resize(400, 300) win.show() return win def updateTreeView(self): """ Tree View update switch spectre/chromato """ if self.treeView.model() == self.spectraModel: self.treeView.setModel(self.chromaModel) self.tabWidget.setTabText(0, "Chroma") else: self.treeView.setModel(self.spectraModel) #self.treeView.setSelectionMode(1) self.tabWidget.setTabText(0, "Spectra") def addTreeViewModel (self,model1, model2): """Add a model """ self.chromaModel.appendRow(model1) self.spectraModel.appendRow(model2) def _actionHovered(self, action): """emulate tooltip cause they do not work that much""" tip = action.toolTip() QToolTip.showText(QCursor.pos(), tip) def showErrorMessage(self, title, string): QMessageBox.critical(self, title, string, 0, 0) def showWarningMessage(self, title, string): return QMessageBox.warning(self, title, string, QMessageBox.Ok|QMessageBox.Cancel) def showInformationMessage(self, title, string): QMessageBox.information(self, title, string, 0) def updateProgressBar(self, i): """update the value of the progress bar for all the treatment""" self.pb.setValue(min(i, 100)) def to_indetermined_mode(self): self.pb.setMaximum(0) def to_determined_mode(self): self.pb.setMaximum(100) def showInStatusBar(self, string, time=5000): self.statusBar().showMessage(string, time) def addInterpreterDock(self, shell): self.shellDock = QDockWidget(self) self.shellDock.setWidget(shell) self.shellDock.setWindowTitle("shell") self.addDockWidget(0x2, self.shellDock) def showMetMSInformation(self): QMessageBox.about(self, self.tr("About %1").arg("metMS"), self.tr("""<b>%1 %2</b> <br>metabolite Mass Spectrometry <p>Copyright © 2010 Marco INSA, INRA <br>Licensed under the terms of the CeciLL License <p>Developed and maintained by Marco <br>Bug reports and feature requests: <a href="http://github.com/jerkos/metms">metMS site</a><br> Discussions around the project: <a href="http://groups.google.com/group/spyderlib">Google Group</a> <p>This project is part of the BRIDGE project <p>Python %3, Qt %4, PyQt %5""") \ .arg("metMS").arg(__version__) \ .arg(platform.python_version()).arg(QT_VERSION_STR) \ .arg(PYQT_VERSION_STR))
class SGMapTool(QgsMapTool): """A map tool that lets you click on a parcel to download its SG Diagram. """ def __init__(self, iface): """Constructor. :param iface: A QGIS QgisInterface instance. :type iface: QgisInterface """ canvas = iface.mapCanvas() QgsMapTool.__init__(self, canvas) self.canvas = canvas self.iface = iface self.message_bar = None self.progress_bar = None self.output_directory = None self.log_file = None self.restore_state() sg_diagrams_database = os.path.join(DATA_DIR, 'sg_diagrams.sqlite') self.db_manager = DatabaseManager(sg_diagrams_database) def canvasPressEvent(self, event): """Slot called when a mouse press occurs on the canvas. :param event: Canvas event containing position of click, which button was clicked etc. """ pass def canvasMoveEvent(self, event): """Slot called when a mouse move event occurs on the canvas. :param event: Canvas event containing position of click, which button was clicked etc. """ pass def setup_message_bar(self): """Setup a QgsMessageBar for use from callback and user notifications. """ if self.message_bar is not None: return self.message_bar = self.iface.messageBar().createMessage( self.tr('SG Diagram Downloader'), self.tr('Please stand by while download process is in progress.'), self.iface.mainWindow()) # Set up message bar for progress reporting self.progress_bar = QProgressBar() self.progress_bar.setMaximumWidth(150) self.progress_bar.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.message_bar.layout().addWidget(self.progress_bar) self.iface.messageBar().pushWidget( self.message_bar, self.iface.messageBar().INFO) def canvasReleaseEvent(self, event): """Slot called when the mouse button is released on the canvas. :param event: Canvas event containing position of click, which button was clicked etc. """ if not event.button() == Qt.LeftButton: return def progress_callback(current, maximum, message=None): """GUI based callback implementation for showing progress. :param current: Current progress. :type current: int :param maximum: Maximum range (point at which task is complete. :type maximum: int :param message: Optional message to display in the progress bar :type message: str, QString """ if message is not None: self.message_bar.setText(message) if self.progress_bar is not None: self.progress_bar.setMaximum(maximum) self.progress_bar.setValue(current) self.iface.messageBar().pushMessage( self.tr('SG Downloader.'), self.tr('Preparing for download'), level=QgsMessageBar.INFO, duration=10) # No need to check that it is a valid, polygon layer # as the QAction for this map tool already does that layer = self.canvas.currentLayer() place = self.toMapCoordinates(event.pos()) rectangle = point_to_rectangle(place) request = QgsFeatureRequest(QgsFeatureRequest.FilterRect) # Ensure only those features really intersecting the rect are returned request.setFlags(QgsFeatureRequest.ExactIntersect) request.setFilterRect(rectangle) polygons = layer.getFeatures(request) feature = QgsFeature() fetch_list = [] all_fields = layer.pendingFields() text_fields = [] # Ignore any columns that don't contain text data for field in all_fields: if field.typeName() == 'String' or field.typeName() == 'Text': text_fields.append(field) self.setup_message_bar() sg_field = None while polygons.nextFeature(feature): # geom = feature.geometry() # attributes = feature.attributes() # matched = False # sg_code = None if sg_field is None: for field in text_fields: value = str(feature[field.name()]) if not is_valid_sg_code(value): continue sg_field = field.name() fetch_list.append(value) else: # We already know which column has SG codes value = str(feature[sg_field]) fetch_list.append(value) if len(fetch_list) == 0: self.iface.messageBar().pushMessage( self.tr('SG Downloader.'), self.tr('No parcels found with a valid 21 Digit code'), level=QgsMessageBar.WARNING, duration=10) return province = province_for_point(self.db_manager, place) report = '' sg_diagrams_database = os.path.join(DATA_DIR, 'sg_diagrams.sqlite') data_manager = DatabaseManager(sg_diagrams_database) i = 0 for sg_code in fetch_list: i += 1 message = 'Downloading SG Code %s from %s' % (sg_code, province) progress_callback(i, len(fetch_list), message) report += download_sg_diagram( data_manager, sg_code, province, self.output_directory, callback=progress_callback) data_manager.close() try: write_log(report, self.log_file) except IOError as e: print e self.show_log(report, self.log_file) def show_log(self, log, log_path): """Show log dialog. :param log: Log in text :type log: str :param log_path: Log file path. :type log_path: str """ dialog = LogDialog(self.iface) dialog.set_log(log, log_path) dialog.exec_() def restore_state(self): """Restore state from previous session.""" home_user = expanduser("~") default_log_file = os.path.join(home_user, 'sg_downloader.log') previous_settings = QSettings() self.output_directory = str(previous_settings.value( 'sg-diagram-downloader/output_directory', home_user, type=str)) self.log_file = str(previous_settings.value( 'sg-diagram-downloader/log_file', default_log_file, type=str))
class QuadStatusBar(QHBoxLayout): positionChanged = pyqtSignal(int, int, int) # x,y,z def __init__(self, parent=None): QHBoxLayout.__init__(self, parent) self.setContentsMargins(0, 4, 0, 0) self.setSpacing(0) self.timeControlFontSize = 12 def showXYCoordinates(self): self.zLabel.setHidden(True) self.zSpinBox.setHidden(True) def showXYZCoordinates(self): self.zLabel.setHidden(False) self.zSpinBox.setHidden(False) def hideTimeSlider(self, flag): visibleBefore = not self.timeSlider.isHidden() self.timeSlider.setHidden(flag) self.timeEndButton.setHidden(flag) self.timeStartButton.setHidden(flag) self.timePreviousButton.setHidden(flag) self.timeNextButton.setHidden(flag) self._registerTimeframeShortcuts(enabled=not flag, remove=visibleBefore) def setToolTipTimeButtonsCrop(self, croppingFlag=False): if croppingFlag == True: self.timeStartButton.setToolTip( "Jump to lirst frame of current crop") self.timeEndButton.setToolTip("Jump to last frame of current crop") self.timePreviousButton.setToolTip("Previous Frame") self.timeNextButton.setToolTip("Next Frame") else: self.timeStartButton.setToolTip("First Frame") self.timeEndButton.setToolTip("Last Frame") self.timePreviousButton.setToolTip("Previous Frame") self.timeNextButton.setToolTip("Next Frame") def setToolTipTimeSliderCrop(self, croppingFlag=False): if croppingFlag == True: self.timeSlider.setToolTip( "Choose the time coordinate of the current crop.") else: self.timeSlider.setToolTip( "Choose the time coordinate of the current dataset.") def createQuadViewStatusBar(self, xbackgroundColor, xforegroundColor, ybackgroundColor, yforegroundColor, zbackgroundColor, zforegroundColor): self.xLabel, self.xSpinBox = _get_pos_widget('X', xbackgroundColor, xforegroundColor) self.yLabel, self.ySpinBox = _get_pos_widget('Y', ybackgroundColor, yforegroundColor) self.zLabel, self.zSpinBox = _get_pos_widget('Z', zbackgroundColor, zforegroundColor) self.xSpinBox.delayedValueChanged.connect( partial(self._handlePositionBoxValueChanged, 'x')) self.ySpinBox.delayedValueChanged.connect( partial(self._handlePositionBoxValueChanged, 'y')) self.zSpinBox.delayedValueChanged.connect( partial(self._handlePositionBoxValueChanged, 'z')) self.addWidget(self.xLabel) self.addWidget(self.xSpinBox) self.addWidget(self.yLabel) self.addWidget(self.ySpinBox) self.addWidget(self.zLabel) self.addWidget(self.zSpinBox) self.addSpacing(10) self.crosshairsCheckbox = QCheckBox() self.crosshairsCheckbox.setChecked(False) self.crosshairsCheckbox.setCheckable(True) self.crosshairsCheckbox.setText("Crosshairs") self.addWidget(self.crosshairsCheckbox) self.addSpacing(10) self.busyIndicator = QProgressBar() self.busyIndicator.setMaximumWidth(200) self.busyIndicator.setMaximum(0) self.busyIndicator.setMinimum(0) self.busyIndicator.setVisible(False) self.busyIndicator.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self.addWidget(self.busyIndicator) self.setStretchFactor(self.busyIndicator, 1) self.addStretch() self.addSpacing(20) self.timeSpinBox = DelayedSpinBox(750) icons_dir = os.path.dirname(volumina.__file__) + "/icons" self.timeStartButton = QToolButton() self.timeStartButton.setIcon(QIcon(icons_dir + "/skip-start.png")) self.addWidget(self.timeStartButton) self.timeStartButton.clicked.connect(self._onTimeStartButtonClicked) #self.timeStartButton.setFixedWidth(4*self.timeControlFontSize) self.timePreviousButton = QToolButton() self.timePreviousButton.setIcon(QIcon(icons_dir + "/play-reverse.png")) self.addWidget(self.timePreviousButton) self.timePreviousButton.clicked.connect( self._onTimePreviousButtonClicked) #self.timePreviousButton.setFixedWidth(4*self.timeControlFontSize) self.timeSlider = QSlider(Qt.Horizontal) self.timeSlider.setMinimumWidth(10) self.timeSlider.setMaximumWidth(200) self.setToolTipTimeSliderCrop() self.addWidget(self.timeSlider) self.timeSlider.valueChanged.connect(self._onTimeSliderChanged) self.timeNextButton = QToolButton() self.timeNextButton.setIcon(QIcon(icons_dir + "/play.png")) self.addWidget(self.timeNextButton) self.timeNextButton.clicked.connect(self._onTimeNextButtonClicked) #self.timeNextButton.setFixedWidth(4*self.timeControlFontSize) self.timeEndButton = QToolButton() self.timeEndButton.setIcon(QIcon(icons_dir + "/skip-end.png")) #self.timeEndButton.setFixedWidth(4*self.timeControlFontSize) self.setToolTipTimeButtonsCrop() self.addWidget(self.timeEndButton) self.timeEndButton.clicked.connect(self._onTimeEndButtonClicked) self.timeLabel = QLabel(" Time:") self.addWidget(self.timeLabel) timeControlFont = self.timeSpinBox.font() if self.timeControlFontSize > timeControlFont.pointSize(): timeControlFont.setPixelSize(2 * self.timeControlFontSize) self.timeStartButton.setFont(timeControlFont) self.timeEndButton.setFont(timeControlFont) self.timeLabel.setFont(timeControlFont) self.timeSpinBox.setFont(timeControlFont) self.addWidget(self.timeSpinBox) self.timeSpinBox.delayedValueChanged.connect( self._onTimeSpinBoxChanged) self._registerTimeframeShortcuts() def _registerTimeframeShortcuts(self, enabled=True, remove=True): """ Register or deregister "," and "." as keyboard shortcuts for scrolling in time """ mgr = ShortcutManager() ActionInfo = ShortcutManager.ActionInfo def action(key, actionInfo): if enabled: mgr.register(key, actionInfo) else: if remove: mgr.unregister(actionInfo) action( "<", ActionInfo("Navigation", "Go to next time frame", "Go to next time frame", self._onTimeNextButtonClicked, self.timeNextButton, self.timeNextButton)) action( ">", ActionInfo("Navigation", "Go to previous time frame", "Go to previous time frame", self._onTimePreviousButtonClicked, self.timePreviousButton, self.timePreviousButton)) def _onTimeStartButtonClicked(self): self.timeSpinBox.setValue( self.parent().parent().parent().editor.cropModel.get_roi_t()[0]) def _onTimeEndButtonClicked(self): self.timeSpinBox.setValue( self.parent().parent().parent().editor.cropModel.get_roi_t()[1]) def _onTimePreviousButtonClicked(self): self.timeSpinBox.setValue(self.timeSpinBox.value() - 1) def _onTimeNextButtonClicked(self): self.timeSpinBox.setValue(self.timeSpinBox.value() + 1) def _onTimeSpinBoxChanged(self): editor = self.parent().parent().parent().editor cropModel = editor.cropModel minValueT = cropModel.get_roi_t()[0] maxValueT = cropModel.get_roi_t()[1] if cropModel.get_scroll_time_outside_crop(): if minValueT > self.timeSpinBox.value( ) or maxValueT < self.timeSpinBox.value(): for imgView in editor.imageViews: imgView._croppingMarkers._shading_item.set_paint_full_frame( True) else: for imgView in editor.imageViews: imgView._croppingMarkers._shading_item.set_paint_full_frame( False) self.timeSlider.setValue(self.timeSpinBox.value()) else: for imgView in editor.imageViews: imgView._croppingMarkers._shading_item.set_paint_full_frame( False) if minValueT > self.timeSpinBox.value(): self.timeSlider.setValue(minValueT) elif maxValueT < self.timeSpinBox.value(): self.timeSlider.setValue(maxValueT) elif minValueT <= self.timeSpinBox.value( ) and self.timeSpinBox.value() <= maxValueT: self.timeSlider.setValue(self.timeSpinBox.value()) def _onTimeSliderChanged(self): cropModel = self.parent().parent().parent().editor.cropModel minValueT = cropModel.get_roi_t()[0] maxValueT = cropModel.get_roi_t()[1] if cropModel.get_scroll_time_outside_crop(): self.timeSpinBox.setValue(self.timeSlider.value()) else: if minValueT > self.timeSlider.value(): self.timeSpinBox.setValue(minValueT) self.timeSlider.setValue(minValueT) elif self.timeSlider.value() > maxValueT: self.timeSpinBox.setValue(maxValueT) self.timeSlider.setValue(maxValueT) elif minValueT <= self.timeSlider.value( ) and self.timeSlider.value() <= maxValueT: self.timeSpinBox.setValue(self.timeSlider.value()) def _handlePositionBoxValueChanged(self, axis, value): new_position = [ self.xSpinBox.value(), self.ySpinBox.value(), self.zSpinBox.value() ] changed_axis = ord(axis) - ord('x') new_position[changed_axis] = value self.positionChanged.emit(*new_position) def updateShape5D(self, shape5D): self.timeSpinBox.setMaximum(shape5D[0] - 1) self.xSpinBox.setMaximum(shape5D[1] - 1) self.ySpinBox.setMaximum(shape5D[2] - 1) self.zSpinBox.setMaximum(shape5D[3] - 1) def updateShape5Dcropped(self, shape5DcropMin, shape5Dmax): self.timeSpinBox.setMaximum(shape5Dmax[0] - 1) self.xSpinBox.setMaximum(shape5Dmax[1] - 1) self.ySpinBox.setMaximum(shape5Dmax[2] - 1) self.zSpinBox.setMaximum(shape5Dmax[3] - 1) self.timeSlider.setMaximum(shape5Dmax[0] - 1) self.timeSpinBox.setValue(shape5DcropMin[0]) self.xSpinBox.setValue(shape5DcropMin[1]) self.ySpinBox.setValue(shape5DcropMin[2]) self.zSpinBox.setValue(shape5DcropMin[3]) self.timeSlider.setValue(shape5DcropMin[0]) def setMouseCoords(self, x, y, z): self.xSpinBox.setValueWithoutSignal(x) self.ySpinBox.setValueWithoutSignal(y) self.zSpinBox.setValueWithoutSignal(z)
def accept(self): """Event handler for when OK is pressed.""" LOGGER.debug('run the tools') self.get_user_options() if self.site_layer is None: self.show_site_layer_information_message() return if self.parcel_layer is None: self.show_parcel_layer_information_message() return # check if no feature is selected if (not self.layer_has_selection(self.site_layer) and self.selected_sites_only.isChecked()): self.show_no_selection_warning() return if self.output_directory is '' or not os.path.exists( self.output_directory): self.show_output_directory_information_message() return message_bar = self.iface.messageBar().createMessage( self.tr('Download SG Diagram'), self.tr('Please stand by while download process is in progress.'), self.iface.mainWindow()) progress_bar = QProgressBar() progress_bar.setMaximumWidth(150) progress_bar.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) message_bar.layout().addWidget(progress_bar) self.iface.messageBar().pushWidget(message_bar, self.iface.messageBar().INFO) self.message_bar = message_bar self.save_state() self.close() def progress_callback(current, maximum, message=None): """GUI based callback implementation for showing progress. :param current: Current progress. :type current: int :param maximum: Maximum range (point at which task is complete. :type maximum: int :param message: Optional message to display in the progress bar :type message: str, QString """ if message is not None: message_bar.setText(message) if progress_bar is not None: progress_bar.setMaximum(maximum) progress_bar.setValue(current) report = download_sg_diagrams(self.database_manager, self.site_layer, self.parcel_layer, self.sg_code_field, self.output_directory, self.all_features, callback=progress_callback) # Get rid of the message bar again. self.iface.messageBar().popWidget(message_bar) #QgsMapLayerRegistry.instance().addMapLayers([layer]) self.iface.messageBar().pushMessage( self.tr('Download completed.'), self.tr('Your files are available in %s.' % self.output_directory), level=QgsMessageBar.INFO, duration=10) write_log(report, self.log_file) self.show_log(report, self.log_file)