示例#1
0
    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)
示例#2
0
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 &copy; 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)
示例#4
0
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&nbsp;Name", itemName),
									 ("Item&nbsp;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()
示例#5
0
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()
示例#7
0
文件: srss.py 项目: jhtervay/SRSS
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)
示例#8
0
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)
示例#9
0
文件: FeedLol.py 项目: bodil/feedlol
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 &copy; 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))
示例#11
0
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 &copy; 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)