コード例 #1
0
ファイル: mainWindow.py プロジェクト: pgollor/pyGUI
	def setVisible(self, visible):
		QDockWidget.setVisible(self, visible)
		
		if (visible):
			# set as current widget
			mainWindowDockWidget.setAsCurrent(self)
			
			# If dock widget is tabbed, then show on top.
			otherTabbedWidgets = self.parent().tabifiedDockWidgets(self)
			
			if (otherTabbedWidgets != []):
				self.raise_()
コード例 #2
0
    def lauchGUI(self, WorkSpace, aCase, sobjXML, Args):
        """
        mw.dockWidgetBrowser is the Browser of the CFD MainView
        """
        log.debug("lauchGUI")
        from cs_gui import process_cmd_line

        if CFD_Code() == CFD_Saturne:
            from cs_package import package
            from code_saturne.Base.MainView import MainView
        elif CFD_Code() == CFD_Neptune:
            from nc_package import package
            from neptune_cfd.core.MainView import MainView

        if sobjXML == None:
            Title = "unnamed"
        else:
            Title = sobjXML.GetName()

        self.Workspace = WorkSpace
        pkg = package()
        case, splash = process_cmd_line(Args)
        mw = MainView(pkg, case, aCase)

        # Put the standard panel of the MainView inside a QDockWidget
        # in the SALOME Desktop
        aTitle = self.setWindowTitle_CFD(mw, aCase, Title)
        dsk = sgPyQt.getDesktop()
        dock = QDockWidget(aTitle)

        dock.setWidget(mw.frame)
        dock.setMinimumWidth(520)
        dsk.addDockWidget(Qt.RightDockWidgetArea, dock)

        dock.setVisible(True)
        dock.show()

        # Put the QTreeView of the MainView which is already inside a QDockWidget
        # in the SALOME Desktop
        BrowserTitle = aTitle  + " Browser"
        mw.dockWidgetBrowser.setWindowTitle(BrowserTitle)
        dsk.addDockWidget(Qt.LeftDockWidgetArea, mw.dockWidgetBrowser)

        mw.dockWidgetBrowser.setVisible(True)
        mw.dockWidgetBrowser.show()
        mw.dockWidgetBrowser.raise_()
        dock.raise_()

        #Add Dock windows are managed by CFDGUI_Management class
        studyId = sgPyQt.getStudyId()
        aStudyCFD = aCase.GetFather()
        aCaseCFD  = aCase
        xmlFileName = str(Title)
        _c_CFDGUI.set_d_CfdCases(studyId, dock, mw.dockWidgetBrowser, mw, aStudyCFD, aCaseCFD, xmlFileName, sobjXML)

        self.connect(dock, SIGNAL("visibilityChanged(bool)"), self.setdockWindowBrowserActivated)
        self.connect(mw.dockWidgetBrowser, SIGNAL("visibilityChanged(bool)"),self.setdockWindowActivated)

        self.connect(dock.toggleViewAction(), SIGNAL("toggled(bool)"), self.setdockWB)
        self.connect(mw.dockWidgetBrowser.toggleViewAction(), SIGNAL("toggled(bool)"), self.setdock)

        _c_CFDGUI.tabifyDockWindows(dsk, studyId)
        self.showDockWindows(studyId, xmlFileName, aCaseCFD.GetName(), aStudyCFD.GetName())
        updateObjectBrowser()

        return mw
コード例 #3
0
ファイル: MetMainGui.py プロジェクト: jerkos/metms
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),
        )
コード例 #4
0
class MenuBuilderDialog(QDialog, Ui_Dialog):
    def __init__(self, uiparent):
        super(MenuBuilderDialog, self).__init__()

        self.setupUi(self)

        # reference to caller
        self.uiparent = uiparent

        self.combo_profile.lineEdit().setPlaceholderText(
            self.tr("Profile name"))

        # add icons
        self.button_add_menu.setIcon(
            QIcon(":/plugins/MenuBuilder/resources/plus.svg"))
        self.button_delete_profile.setIcon(
            QIcon(":/plugins/MenuBuilder/resources/delete.svg"))

        # custom qtreeview
        self.target = CustomQtTreeView(self)
        self.target.setGeometry(QRect(440, 150, 371, 451))
        self.target.setAcceptDrops(True)
        self.target.setDragEnabled(True)
        self.target.setDragDropMode(QAbstractItemView.DragDrop)
        self.target.setObjectName("target")
        self.target.setDropIndicatorShown(True)
        self.target.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.target.setHeaderHidden(True)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.target.sizePolicy().hasHeightForWidth())
        self.target.setSizePolicy(sizePolicy)
        self.target.setAutoFillBackground(True)
        self.verticalLayout_2.addWidget(self.target)

        self.browser = QgsBrowserModel()
        self.source.setModel(self.browser)
        self.source.setHeaderHidden(True)
        self.source.setDragEnabled(True)
        self.source.setSelectionMode(QAbstractItemView.ExtendedSelection)

        self.menumodel = MenuTreeModel(self)
        self.target.setModel(self.menumodel)
        self.target.setAnimated(True)

        # add a dock widget
        self.dock_widget = QDockWidget("Menus")
        self.dock_widget.resize(400, 300)
        self.dock_widget.setFloating(True)
        self.dock_widget.setObjectName(self.tr("Menu Tree"))
        self.dock_widget_content = QWidget()
        self.dock_widget.setWidget(self.dock_widget_content)
        dock_layout = QVBoxLayout()
        self.dock_widget_content.setLayout(dock_layout)
        self.dock_view = DockQtTreeView(self.dock_widget_content)
        self.dock_view.setDragDropMode(QAbstractItemView.DragOnly)
        self.dock_menu_filter = QLineEdit()
        self.dock_menu_filter.setPlaceholderText(
            self.tr("Filter by table description (postgis only)"))
        dock_layout.addWidget(self.dock_menu_filter)
        dock_layout.addWidget(self.dock_view)
        self.dock_view.setHeaderHidden(True)
        self.dock_view.setDragEnabled(True)
        self.dock_view.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.dock_view.setAnimated(True)
        self.dock_view.setObjectName("treeView")
        self.proxy_model = LeafFilterProxyModel(self)
        self.proxy_model.setFilterRole(Qt.ToolTipRole)
        self.proxy_model.setFilterCaseSensitivity(Qt.CaseInsensitive)

        self.profile_list = []
        self.table = 'qgis_menubuilder_metadata'

        self.layer_handler = {
            'vector': self.load_vector,
            'raster': self.load_raster
        }

        # connect signals and handlers
        self.combo_database.activated.connect(
            partial(self.set_connection, dbname=None))
        self.combo_schema.activated.connect(self.update_profile_list)
        self.combo_profile.activated.connect(
            partial(self.update_model_idx, self.menumodel))
        self.button_add_menu.released.connect(self.add_menu)
        self.button_delete_profile.released.connect(self.delete_profile)
        self.dock_menu_filter.textEdited.connect(self.filter_update)
        self.dock_view.doubleClicked.connect(self.load_from_index)

        self.buttonBox.rejected.connect(self.reject)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.button(QDialogButtonBox.Apply).clicked.connect(
            self.apply)

    def filter_update(self):
        text = self.dock_menu_filter.displayText()
        self.proxy_model.setFilterRegExp(text)

    def show_dock(self, state, profile=None, schema=None):
        if not state:
            # just hide widget
            self.dock_widget.setVisible(state)
            return
        # dock must be read only and deepcopy of model is not supported (c++ inside!)
        self.dock_model = MenuTreeModel(self)
        if profile:
            # bypass combobox
            self.update_model(self.dock_model, schema, profile)
        else:
            self.update_model_idx(self.dock_model,
                                  self.combo_profile.currentIndex())
        self.dock_model.setHorizontalHeaderLabels(["Menus"])
        self.dock_view.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.proxy_model.setSourceModel(self.dock_model)
        self.dock_view.setModel(self.proxy_model)
        self.dock_widget.setVisible(state)

    def show_menus(self, state, profile=None, schema=None):
        if state:
            self.load_menus(profile=profile, schema=schema)
            return
        # remove menus
        for menu in self.uiparent.menus:
            self.uiparent.iface.mainWindow().menuBar().removeAction(
                menu.menuAction())

    def add_menu(self):
        """
        Add a menu inside qtreeview
        """
        item = QStandardItem('NewMenu')
        item.setIcon(QIcon(':/plugins/MenuBuilder/resources/menu.svg'))
        # select current index selected and insert as a sibling
        brother = self.target.selectedIndexes()

        if not brother or not brother[0].parent():
            # no selection, add menu at the top level
            self.menumodel.insertRow(self.menumodel.rowCount(), item)
            return

        parent = self.menumodel.itemFromIndex(brother[0].parent())
        if not parent:
            self.menumodel.insertRow(self.menumodel.rowCount(), item)
            return
        parent.appendRow(item)

    def update_database_list(self):
        """update list of defined postgres connections"""
        settings = QSettings()
        settings.beginGroup("/PostgreSQL/connections")
        keys = settings.childGroups()
        self.combo_database.clear()
        self.combo_schema.clear()
        self.menumodel.clear()
        self.combo_database.addItems(keys)
        self.combo_database.setCurrentIndex(-1)
        settings.endGroup()
        # clear profile list
        self.combo_profile.clear()
        self.combo_profile.setCurrentIndex(-1)

    def set_connection(self, databaseidx, dbname=None):
        """
        Connect to selected postgresql database
        """
        selected = self.combo_database.itemText(databaseidx) or dbname
        if not selected:
            return

        settings = QSettings()
        settings.beginGroup("/PostgreSQL/connections/{}".format(selected))

        if not settings.contains("database"):
            # no entry?
            QMessageBox.critical(self, "Error",
                                 "There is no defined database connection")
            return

        uri = QgsDataSourceURI()

        settingsList = [
            "service", "host", "port", "database", "username", "password"
        ]
        service, host, port, database, username, password = map(
            lambda x: settings.value(x, "", type=str), settingsList)

        useEstimatedMetadata = settings.value("estimatedMetadata",
                                              False,
                                              type=bool)
        sslmode = settings.value("sslmode",
                                 QgsDataSourceURI.SSLprefer,
                                 type=int)

        settings.endGroup()

        if service:
            uri.setConnection(service, database, username, password, sslmode)
        else:
            uri.setConnection(host, port, database, username, password,
                              sslmode)

        uri.setUseEstimatedMetadata(useEstimatedMetadata)

        # connect to db
        self.connect_to_uri(uri)
        # update schema list
        self.update_schema_list()

    @contextmanager
    def transaction(self):
        try:
            yield
            self.connection.commit()
        except self.pg_error_types() as e:
            self.connection.rollback()
            raise e

    def check_connected(func):
        """
        Decorator that checks if a database connection is active before executing function
        """
        @wraps(func)
        def wrapped(inst, *args, **kwargs):
            if not getattr(inst, 'connection', False):
                QMessageBox(
                    QMessageBox.Warning, "Menu Builder",
                    inst.tr(
                        "Not connected to any database, please select one"),
                    QMessageBox.Ok, inst).exec_()
                return
            if inst.connection.closed:
                QMessageBox(
                    QMessageBox.Warning, "Menu Builder",
                    inst.tr(
                        "Not connected to any database, please select one"),
                    QMessageBox.Ok, inst).exec_()
                return
            return func(inst, *args, **kwargs)

        return wrapped

    def connect_to_uri(self, uri):
        self.close_connection()
        self.host = uri.host() or os.environ.get('PGHOST')
        self.port = uri.port() or os.environ.get('PGPORT')

        username = uri.username() or os.environ.get(
            'PGUSER') or os.environ.get('USER')
        password = uri.password() or os.environ.get('PGPASSWORD')

        try:
            self.connection = psycopg2.connect(uri.connectionInfo())
        except self.pg_error_types() as e:
            err = str(e)
            conninfo = uri.connectionInfo()

            ok, username, password = QgsCredentials.instance().get(
                conninfo, username, password, err)
            if not ok:
                raise Exception(e)

            if username:
                uri.setUsername(username)

            if password:
                uri.setPassword(password)

            self.connection = psycopg2.connect(uri.connectionInfo())

        self.pgencoding = self.connection.encoding

        return True

    def pg_error_types(self):
        return (psycopg2.InterfaceError, psycopg2.OperationalError,
                psycopg2.ProgrammingError)

    @check_connected
    def update_schema_list(self):
        self.combo_schema.clear()
        with self.transaction():
            cur = self.connection.cursor()
            cur.execute("""
                select nspname
                from pg_namespace
                where nspname not ilike 'pg_%'
                and nspname not in ('pg_catalog', 'information_schema')
                """)
            schemas = [row[0] for row in cur.fetchall()]
            self.combo_schema.addItems(schemas)

    @check_connected
    def update_profile_list(self, schemaidx):
        """
        update profile list from database
        """
        schema = self.combo_schema.itemText(schemaidx)
        with self.transaction():
            cur = self.connection.cursor()
            cur.execute("""
                select 1
                from pg_tables
                    where schemaname = '{0}'
                    and tablename = '{1}'
                union
                select 1
                from pg_matviews
                    where schemaname = '{0}'
                    and matviewname = '{1}'
                """.format(schema, self.table))
            tables = cur.fetchone()
            if not tables:
                box = QMessageBox(
                    QMessageBox.Warning, "Menu Builder",
                    self.tr("Table '{}.{}' not found in this database, "
                            "would you like to create it now ?").format(
                                schema, self.table),
                    QMessageBox.Cancel | QMessageBox.Yes, self)
                ret = box.exec_()
                if ret == QMessageBox.Cancel:
                    return False
                elif ret == QMessageBox.Yes:
                    cur.execute("""
                        create table {}.{} (
                            id serial,
                            name varchar,
                            profile varchar,
                            model_index varchar,
                            datasource_uri text
                        )
                        """.format(schema, self.table))
                    self.connection.commit()
                    return False

            cur.execute("""
                select distinct(profile) from {}.{}
                """.format(schema, self.table))
            profiles = [row[0] for row in cur.fetchall()]
            saved_profile = self.combo_profile.currentText()
            self.combo_profile.clear()
            self.combo_profile.addItems(profiles)
            self.combo_profile.setCurrentIndex(
                self.combo_profile.findText(saved_profile))

    @check_connected
    def delete_profile(self):
        """
        Delete profile currently selected
        """
        idx = self.combo_profile.currentIndex()
        schema = self.combo_schema.currentText()
        profile = self.combo_profile.itemText(idx)
        box = QMessageBox(QMessageBox.Warning, "Menu Builder",
                          self.tr("Delete '{}' profile ?").format(profile),
                          QMessageBox.Cancel | QMessageBox.Yes, self)
        ret = box.exec_()
        if ret == QMessageBox.Cancel:
            return False
        elif ret == QMessageBox.Yes:
            self.combo_profile.removeItem(idx)
            with self.transaction():
                cur = self.connection.cursor()
                cur.execute("""
                    delete from {}.{}
                    where profile = '{}'
                    """.format(schema, self.table, profile))
        self.menumodel.clear()
        self.combo_profile.setCurrentIndex(-1)

    def update_model_idx(self, model, profile_index):
        """
        wrapper that checks combobox
        """
        profile = self.combo_profile.itemText(profile_index)
        schema = self.combo_schema.currentText()
        self.update_model(model, schema, profile)

    def sortby_modelindex(self, rows):
        return sorted(
            rows,
            key=lambda line: '/'.join(
                ['{:04}'.format(elem[0]) for elem in json.loads(line[2])]))

    @check_connected
    def update_model(self, model, schema, profile):
        """
        Update the model by retrieving the profile given in database
        """
        menudict = {}

        with self.transaction():
            cur = self.connection.cursor()
            select = """
                select name, profile, model_index, datasource_uri
                from {}.{}
                where profile = '{}'
                """.format(schema, self.table, profile)
            cur.execute(select)
            rows = cur.fetchall()
            model.clear()
            for name, profile, model_index, datasource_uri in self.sortby_modelindex(
                    rows):
                menu = model.invisibleRootItem()
                indexes = json.loads(model_index)
                parent = ''
                for idx, subname in indexes[:-1]:
                    parent += '{}-{}/'.format(idx, subname)
                    if parent in menudict:
                        # already created entry
                        menu = menudict[parent]
                        continue
                    # create menu
                    item = QStandardItem(subname)
                    uri_struct = QgsMimeDataUtils.Uri(datasource_uri)
                    item.setData(uri_struct)
                    item.setIcon(
                        QIcon(':/plugins/MenuBuilder/resources/menu.svg'))
                    item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsUserCheckable
                                  | Qt.ItemIsEnabled | Qt.ItemIsDropEnabled
                                  | Qt.ItemIsEditable)
                    item.setWhatsThis("menu")
                    menu.appendRow(item)
                    menudict[parent] = item
                    # set current menu to the new created item
                    menu = item

                # add leaf (layer item)
                item = QStandardItem(name)
                uri_struct = QgsMimeDataUtils.Uri(datasource_uri)
                # fix layer name instead of table name
                # usefull when the layer has been renamed in menu
                uri_struct.name = name
                if uri_struct.providerKey in ICON_MAPPER:
                    item.setIcon(QIcon(ICON_MAPPER[uri_struct.providerKey]))
                item.setData(uri_struct)
                # avoid placing dragged layers on it
                item.setDropEnabled(False)
                if uri_struct.providerKey == 'postgres':
                    # set tooltip to postgres comment
                    comment = self.get_table_comment(uri_struct.uri)
                    item.setToolTip(comment)
                menudict[parent].appendRow(item)

    @check_connected
    def save_changes(self, save_to_db=True):
        """
        Save changes in the postgres table
        """
        schema = self.combo_schema.currentText()
        profile = self.combo_profile.currentText()
        if not profile:
            QMessageBox(QMessageBox.Warning, "Menu Builder",
                        self.tr("Profile cannot be empty"), QMessageBox.Ok,
                        self).exec_()
            return False

        if save_to_db:
            try:
                with self.transaction():
                    cur = self.connection.cursor()
                    cur.execute(
                        "delete from {}.{} where profile = '{}'".format(
                            schema, self.table, profile))
                    for item, data in self.target.iteritems():
                        if not data:
                            continue
                        cur.execute(
                            """
                        insert into {}.{} (name,profile,model_index,datasource_uri)
                        values (%s, %s, %s, %s)
                        """.format(schema, self.table),
                            (item[-1][1], profile, json.dumps(item),
                             data.data()))
            except Exception as exc:
                QMessageBox(QMessageBox.Warning, "Menu Builder",
                            exc.message.decode(self.pgencoding),
                            QMessageBox.Ok, self).exec_()
                return False

        self.save_session(self.combo_database.currentText(), schema, profile,
                          self.activate_dock.isChecked(),
                          self.activate_menubar.isChecked())
        self.update_profile_list(self.combo_schema.currentIndex())
        self.show_dock(self.activate_dock.isChecked())
        self.show_menus(self.activate_menubar.isChecked())
        return True

    @check_connected
    def load_menus(self, profile=None, schema=None):
        """
        Load menus in the main windows qgis bar
        """
        if not schema:
            schema = self.combo_schema.currentText()
        if not profile:
            profile = self.combo_profile.currentText()
        # remove previous menus
        for menu in self.uiparent.menus:
            self.uiparent.iface.mainWindow().menuBar().removeAction(
                menu.menuAction())

        with self.transaction():
            cur = self.connection.cursor()
            select = """
                select name, profile, model_index, datasource_uri
                from {}.{}
                where profile = '{}'
                """.format(schema, self.table, profile)
            cur.execute(select)
            rows = cur.fetchall()
        # item accessor ex: '0-menu/0-submenu/1-item/'
        menudict = {}
        # reference to parent item
        parent = ''
        # reference to qgis main menu bar
        menubar = self.uiparent.iface.mainWindow().menuBar()

        for name, profile, model_index, datasource_uri in self.sortby_modelindex(
                rows):
            uri_struct = QgsMimeDataUtils.Uri(datasource_uri)
            indexes = json.loads(model_index)
            # root menu
            parent = '{}-{}/'.format(indexes[0][0], indexes[0][1])
            if parent not in menudict:
                menu = QMenu(self.uiparent.iface.mainWindow())
                self.uiparent.menus.append(menu)
                menu.setObjectName(indexes[0][1])
                menu.setTitle(indexes[0][1])
                menubar.insertMenu(
                    self.uiparent.iface.firstRightStandardMenu().menuAction(),
                    menu)
                menudict[parent] = menu
            else:
                # menu already there
                menu = menudict[parent]

            for idx, subname in indexes[1:-1]:
                # intermediate submenus
                parent += '{}-{}/'.format(idx, subname)
                if parent not in menudict:
                    submenu = menu.addMenu(subname)
                    submenu.setObjectName(subname)
                    submenu.setTitle(subname)
                    menu = submenu
                    # store it for later use
                    menudict[parent] = menu
                    continue
                # already treated
                menu = menudict[parent]

            # last item = layer
            layer = QAction(name, self.uiparent.iface.mainWindow())

            if uri_struct.providerKey in ICON_MAPPER:
                layer.setIcon(QIcon(ICON_MAPPER[uri_struct.providerKey]))

            if uri_struct.providerKey == 'postgres':
                # set tooltip to postgres comment
                comment = self.get_table_comment(uri_struct.uri)
                layer.setStatusTip(comment)
                layer.setToolTip(comment)

            layer.setData(uri_struct.uri)
            layer.setWhatsThis(uri_struct.providerKey)
            layer.triggered.connect(self.layer_handler[uri_struct.layerType])
            menu.addAction(layer)

    def get_table_comment(self, uri):
        schema, table = re.match('.*table=(.*)\(.*',
                                 uri).group(1).strip().replace('"',
                                                               '').split('.')
        with self.transaction():
            cur = self.connection.cursor()
            select = """
                select description from pg_description
                join pg_class on pg_description.objoid = pg_class.oid
                join pg_namespace on pg_class.relnamespace = pg_namespace.oid
                where relname = '{}' and nspname='{}'
                """.format(table, schema)
            cur.execute(select)
            row = cur.fetchone()
            if row:
                return row[0]
        return ''

    def load_from_index(self, index):
        """Load layers from selected item index"""
        item = self.dock_model.itemFromIndex(
            self.proxy_model.mapToSource(index))
        if item.whatsThis() == 'menu':
            return
        if item.data().layerType == 'vector':
            layer = QgsVectorLayer(
                item.data().uri,  # uri
                item.text(),  # layer name
                item.data().providerKey  # provider name
            )
        elif item.data().layerType == 'raster':
            layer = QgsRasterLayer(
                item.data().uri,  # uri
                item.text(),  # layer name
                item.data().providerKey  # provider name
            )
        if not layer:
            return
        QgsMapLayerRegistry.instance().addMapLayer(layer)

    def load_vector(self):
        action = self.sender()
        layer = QgsVectorLayer(
            action.data(),  # uri
            action.text(),  # layer name
            action.whatsThis()  # provider name
        )
        QgsMapLayerRegistry.instance().addMapLayer(layer)

    def load_raster(self):
        action = self.sender()
        layer = QgsRasterLayer(
            action.data(),  # uri
            action.text(),  # layer name
            action.whatsThis()  # provider name
        )
        QgsMapLayerRegistry.instance().addMapLayer(layer)

    def accept(self):
        if self.save_changes():
            QDialog.reject(self)
            self.close_connection()

    def apply(self):
        if self.save_changes(save_to_db=False):
            QDialog.reject(self)

    def reject(self):
        self.close_connection()
        QDialog.reject(self)

    def close_connection(self):
        """close current pg connection if exists"""
        if getattr(self, 'connection', False):
            if self.connection.closed:
                return
            self.connection.close()

    def save_session(self, database, schema, profile, dock, menubar):
        """save current profile for next session"""
        settings = QSettings()
        settings.setValue("MenuBuilder/database", database)
        settings.setValue("MenuBuilder/schema", schema)
        settings.setValue("MenuBuilder/profile", profile)
        settings.setValue("MenuBuilder/dock", dock)
        settings.setValue("MenuBuilder/menubar", menubar)

    def restore_session(self):
        settings = QSettings()
        database = settings.value("MenuBuilder/database", False)
        schema = settings.value("MenuBuilder/schema", 'public')
        profile = settings.value("MenuBuilder/profile", False)
        dock = settings.value("MenuBuilder/dock", False)
        menubar = settings.value("MenuBuilder/menubar", False)
        if not any([database, profile]):
            return

        self.set_connection(0, dbname=database)
        self.show_dock(bool(dock), profile=profile, schema=schema)
        if bool(dock):
            self.uiparent.iface.addDockWidget(Qt.LeftDockWidgetArea,
                                              self.dock_widget)
        self.show_menus(bool(menubar), profile=profile, schema=schema)
コード例 #5
0
class MenuBuilderDialog(QDialog, FORM_CLASS):
    def __init__(self, uiparent):
        super(MenuBuilderDialog, self).__init__()

        self.setupUi(self)

        # reference to caller
        self.uiparent = uiparent

        self.combo_profile.lineEdit().setPlaceholderText(self.tr("Profile name"))

        # add icons
        self.button_add_menu.setIcon(QIcon(":/plugins/MenuBuilder/resources/plus.svg"))
        self.button_delete_profile.setIcon(QIcon(":/plugins/MenuBuilder/resources/delete.svg"))

        # custom qtreeview
        self.target = CustomQtTreeView(self)
        self.target.setGeometry(QRect(440, 150, 371, 451))
        self.target.setAcceptDrops(True)
        self.target.setDragEnabled(True)
        self.target.setDragDropMode(QAbstractItemView.DragDrop)
        self.target.setObjectName("target")
        self.target.setDropIndicatorShown(True)
        self.target.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.target.setHeaderHidden(True)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.target.sizePolicy().hasHeightForWidth())
        self.target.setSizePolicy(sizePolicy)
        self.target.setAutoFillBackground(True)
        self.verticalLayout_2.addWidget(self.target)

        self.browser = QgsBrowserModel()
        self.source.setModel(self.browser)
        self.source.setHeaderHidden(True)
        self.source.setDragEnabled(True)
        self.source.setSelectionMode(QAbstractItemView.ExtendedSelection)

        self.menumodel = MenuTreeModel(self)
        self.target.setModel(self.menumodel)
        self.target.setAnimated(True)

        # add a dock widget
        self.dock_widget = QDockWidget("Menus", self.uiparent.iface.mainWindow())
        self.dock_widget.resize(400, 300)
        self.dock_widget.setFloating(True)
        self.dock_widget.setObjectName(self.tr("Menu Tree"))
        self.dock_widget_content = QWidget()
        self.dock_widget.setWidget(self.dock_widget_content)
        dock_layout = QVBoxLayout()
        self.dock_widget_content.setLayout(dock_layout)
        self.dock_view = DockQtTreeView(self.dock_widget_content)
        self.dock_view.setDragDropMode(QAbstractItemView.DragOnly)
        self.dock_menu_filter = QLineEdit()
        self.dock_menu_filter.setPlaceholderText(self.tr("Filter by table description (postgis only)"))
        dock_layout.addWidget(self.dock_menu_filter)
        dock_layout.addWidget(self.dock_view)
        self.dock_view.setHeaderHidden(True)
        self.dock_view.setDragEnabled(True)
        self.dock_view.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.dock_view.setAnimated(True)
        self.dock_view.setObjectName("treeView")
        self.proxy_model = LeafFilterProxyModel(self)
        self.proxy_model.setFilterRole(Qt.ToolTipRole)
        self.proxy_model.setFilterCaseSensitivity(Qt.CaseInsensitive)

        self.profile_list = []
        self.table = 'qgis_menubuilder_metadata'

        self.layer_handler = {
            'vector': self.load_vector,
            'raster': self.load_raster
        }

        # connect signals and handlers
        self.combo_database.activated.connect(partial(self.set_connection, dbname=None))
        self.combo_schema.activated.connect(self.update_profile_list)
        self.combo_profile.activated.connect(partial(self.update_model_idx, self.menumodel))
        self.button_add_menu.released.connect(self.add_menu)
        self.button_delete_profile.released.connect(self.delete_profile)
        self.dock_menu_filter.textEdited.connect(self.filter_update)
        self.dock_view.doubleClicked.connect(self.load_from_index)

    def filter_update(self):
        text = self.dock_menu_filter.displayText()
        self.proxy_model.setFilterRegExp(text)

    def show_dock(self, state, profile=None, schema=None):
        if not state:
            # just hide widget
            self.dock_widget.setVisible(state)
            return
        # dock must be read only and deepcopy of model is not supported (c++ inside!)
        self.dock_model = MenuTreeModel(self)
        if profile:
            # bypass combobox
            self.update_model(self.dock_model, schema, profile)
        else:
            self.update_model_idx(self.dock_model, self.combo_profile.currentIndex())
        self.dock_model.setHorizontalHeaderLabels(["Menus"])
        self.dock_view.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.proxy_model.setSourceModel(self.dock_model)
        self.dock_view.setModel(self.proxy_model)
        self.dock_widget.setVisible(state)

    def show_menus(self, state, profile=None, schema=None):
        if state:
            self.load_menus(profile=profile, schema=schema)
            return
        # remove menus
        for menu in self.uiparent.menus:
            self.uiparent.iface.mainWindow().menuBar().removeAction(menu.menuAction())

    def add_menu(self):
        """
        Add a menu inside qtreeview
        """
        item = QStandardItem('NewMenu')
        item.setIcon(QIcon(':/plugins/MenuBuilder/resources/menu.svg'))
        # select current index selected and insert as a sibling
        brother = self.target.selectedIndexes()

        if not brother or not brother[0].parent():
            # no selection, add menu at the top level
            self.menumodel.insertRow(self.menumodel.rowCount(), item)
            return

        parent = self.menumodel.itemFromIndex(brother[0].parent())
        if not parent:
            self.menumodel.insertRow(self.menumodel.rowCount(), item)
            return
        parent.appendRow(item)

    def update_database_list(self):
        """update list of defined postgres connections"""
        settings = QSettings()
        settings.beginGroup("/PostgreSQL/connections")
        keys = settings.childGroups()
        self.combo_database.clear()
        self.combo_schema.clear()
        self.menumodel.clear()
        self.combo_database.addItems(keys)
        self.combo_database.setCurrentIndex(-1)
        settings.endGroup()
        # clear profile list
        self.combo_profile.clear()
        self.combo_profile.setCurrentIndex(-1)

    def set_connection(self, databaseidx, dbname=None):
        """
        Connect to selected postgresql database
        """
        selected = self.combo_database.itemText(databaseidx) or dbname
        if not selected:
            return

        settings = QSettings()
        settings.beginGroup("/PostgreSQL/connections/{}".format(selected))

        if not settings.contains("database"):
            # no entry?
            QMessageBox.critical(self, "Error", "There is no defined database connection")
            return

        uri = QgsDataSourceURI()

        settingsList = ["service", "host", "port", "database", "username", "password"]
        service, host, port, database, username, password = map(
            lambda x: settings.value(x, "", type=str), settingsList)

        useEstimatedMetadata = settings.value("estimatedMetadata", False, type=bool)
        sslmode = settings.value("sslmode", QgsDataSourceURI.SSLprefer, type=int)

        settings.endGroup()

        if service:
            uri.setConnection(service, database, username, password, sslmode)
        else:
            uri.setConnection(host, port, database, username, password, sslmode)

        uri.setUseEstimatedMetadata(useEstimatedMetadata)

        # connect to db
        self.connect_to_uri(uri)
        # update schema list
        self.update_schema_list()

    @contextmanager
    def transaction(self):
        try:
            yield
            self.connection.commit()
        except self.pg_error_types() as e:
            self.connection.rollback()
            raise e

    def check_connected(func):
        """
        Decorator that checks if a database connection is active before executing function
        """
        @wraps(func)
        def wrapped(inst, *args, **kwargs):
            if not getattr(inst, 'connection', False):
                QMessageBox(
                    QMessageBox.Warning,
                    "Menu Builder",
                    inst.tr("Not connected to any database, please select one"),
                    QMessageBox.Ok,
                    inst
                ).exec_()
                return
            if inst.connection.closed:
                QMessageBox(
                    QMessageBox.Warning,
                    "Menu Builder",
                    inst.tr("Not connected to any database, please select one"),
                    QMessageBox.Ok,
                    inst
                ).exec_()
                return
            return func(inst, *args, **kwargs)
        return wrapped

    def connect_to_uri(self, uri):
        self.close_connection()
        self.host = uri.host() or os.environ.get('PGHOST')
        self.port = uri.port() or os.environ.get('PGPORT')

        username = uri.username() or os.environ.get('PGUSER') or os.environ.get('USER')
        password = uri.password() or os.environ.get('PGPASSWORD')

        try:
            self.connection = psycopg2.connect(uri.connectionInfo())
        except self.pg_error_types() as e:
            err = str(e)
            conninfo = uri.connectionInfo()

            ok, username, password = QgsCredentials.instance().get(
                conninfo, username, password, err)
            if not ok:
                raise Exception(e)

            if username:
                uri.setUsername(username)

            if password:
                uri.setPassword(password)

            self.connection = psycopg2.connect(uri.connectionInfo())

        self.pgencoding = self.connection.encoding

        return True

    def pg_error_types(self):
        return psycopg2.InterfaceError,\
               psycopg2.OperationalError,\
               psycopg2.ProgrammingError

    @check_connected
    def update_schema_list(self):
        self.combo_schema.clear()
        with self.transaction():
            cur = self.connection.cursor()
            cur.execute("""
                select nspname
                from pg_namespace
                where nspname not ilike 'pg_%'
                and nspname not in ('pg_catalog', 'information_schema')
                """)
            schemas = [row[0] for row in cur.fetchall()]
            self.combo_schema.addItems(schemas)

    @check_connected
    def update_profile_list(self, schemaidx):
        """
        update profile list from database
        """
        schema = self.combo_schema.itemText(schemaidx)
        with self.transaction():
            cur = self.connection.cursor()
            cur.execute("""
                select 1
                from pg_tables
                    where schemaname = '{0}'
                    and tablename = '{1}'
                union
                select 1
                from pg_matviews
                    where schemaname = '{0}'
                    and matviewname = '{1}'
                """.format(schema, self.table))
            tables = cur.fetchone()
            if not tables:
                box = QMessageBox(
                    QMessageBox.Warning,
                    "Menu Builder",
                    self.tr("Table '{}.{}' not found in this database, "
                            "would you like to create it now ?")
                    .format(schema, self.table),
                    QMessageBox.Cancel | QMessageBox.Yes,
                    self
                )
                ret = box.exec_()
                if ret == QMessageBox.Cancel:
                    return False
                elif ret == QMessageBox.Yes:
                    cur.execute("""
                        create table {}.{} (
                            id serial,
                            name varchar,
                            profile varchar,
                            model_index varchar,
                            datasource_uri text
                        )
                        """.format(schema, self.table))
                    self.connection.commit()
                    return False

            cur.execute("""
                select distinct(profile) from {}.{}
                """.format(schema, self.table))
            profiles = [row[0] for row in cur.fetchall()]
            saved_profile = self.combo_profile.currentText()
            self.combo_profile.clear()
            self.combo_profile.addItems(profiles)
            self.combo_profile.setCurrentIndex(self.combo_profile.findText(saved_profile))

    @check_connected
    def delete_profile(self):
        """
        Delete profile currently selected
        """
        idx = self.combo_profile.currentIndex()
        schema = self.combo_schema.currentText()
        profile = self.combo_profile.itemText(idx)
        box = QMessageBox(
            QMessageBox.Warning,
            "Menu Builder",
            self.tr("Delete '{}' profile ?").format(profile),
            QMessageBox.Cancel | QMessageBox.Yes,
            self
        )
        ret = box.exec_()
        if ret == QMessageBox.Cancel:
            return False
        elif ret == QMessageBox.Yes:
            self.combo_profile.removeItem(idx)
            with self.transaction():
                cur = self.connection.cursor()
                cur.execute("""
                    delete from {}.{}
                    where profile = '{}'
                    """.format(schema, self.table, profile))
        self.menumodel.clear()
        self.combo_profile.setCurrentIndex(-1)

    def update_model_idx(self, model, profile_index):
        """
        wrapper that checks combobox
        """
        profile = self.combo_profile.itemText(profile_index)
        schema = self.combo_schema.currentText()
        self.update_model(model, schema, profile)

    def sortby_modelindex(self, rows):
        return sorted(
            rows,
            key=lambda line: '/'.join(
                ['{:04}'.format(elem[0]) for elem in json.loads(line[2])]
            ))

    @check_connected
    def update_model(self, model, schema, profile):
        """
        Update the model by retrieving the profile given in database
        """
        menudict = {}

        with self.transaction():
            cur = self.connection.cursor()
            select = """
                select name, profile, model_index, datasource_uri
                from {}.{}
                where profile = '{}'
                """.format(schema, self.table, profile)
            cur.execute(select)
            rows = cur.fetchall()
            model.clear()
            for name, profile, model_index, datasource_uri in self.sortby_modelindex(rows):
                menu = model.invisibleRootItem()
                indexes = json.loads(model_index)
                parent = ''
                for idx, subname in indexes[:-1]:
                    parent += '{}-{}/'.format(idx, subname)
                    if parent in menudict:
                        # already created entry
                        menu = menudict[parent]
                        continue
                    # create menu
                    item = QStandardItem(subname)
                    uri_struct = QgsMimeDataUtils.Uri(datasource_uri)
                    item.setData(uri_struct)
                    item.setIcon(QIcon(':/plugins/MenuBuilder/resources/menu.svg'))
                    item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsUserCheckable |
                                  Qt.ItemIsEnabled | Qt.ItemIsDropEnabled |
                                  Qt.ItemIsEditable)
                    item.setWhatsThis("menu")
                    menu.appendRow(item)
                    menudict[parent] = item
                    # set current menu to the new created item
                    menu = item

                # add leaf (layer item)
                item = QStandardItem(name)
                uri_struct = QgsMimeDataUtils.Uri(datasource_uri)
                # fix layer name instead of table name
                # usefull when the layer has been renamed in menu
                uri_struct.name = name
                if uri_struct.providerKey in ICON_MAPPER:
                    item.setIcon(QIcon(ICON_MAPPER[uri_struct.providerKey]))
                item.setData(uri_struct)
                # avoid placing dragged layers on it
                item.setDropEnabled(False)
                if uri_struct.providerKey == 'postgres':
                    # set tooltip to postgres comment
                    comment = self.get_table_comment(uri_struct.uri)
                    item.setToolTip(comment)
                menudict[parent].appendRow(item)

    @check_connected
    def save_changes(self):
        """
        Save changes in the postgres table
        """
        schema = self.combo_schema.currentText()
        profile = self.combo_profile.currentText()
        if not profile:
            QMessageBox(
                QMessageBox.Warning,
                "Menu Builder",
                self.tr("Profile cannot be empty"),
                QMessageBox.Ok,
                self
            ).exec_()
            return False

        try:
            with self.transaction():
                cur = self.connection.cursor()
                cur.execute("delete from {}.{} where profile = '{}'".format(
                    schema, self.table, profile))
                for item, data in self.target.iteritems():
                    if not data:
                        continue
                    cur.execute("""
                    insert into {}.{} (name,profile,model_index,datasource_uri)
                    values (%s, %s, %s, %s)
                    """.format(schema, self.table), (
                        item[-1][1],
                        profile,
                        json.dumps(item),
                        data.data())
                    )
        except psycopg2.ProgrammingError as exc:
            QMessageBox(
                QMessageBox.Warning,
                "Menu Builder",
                exc.message.decode(self.pgencoding),
                QMessageBox.Ok,
                self
            ).exec_()

        self.save_session(
            self.combo_database.currentText(),
            schema,
            profile,
            self.activate_dock.isChecked(),
            self.activate_menubar.isChecked()
        )
        self.update_profile_list(self.combo_schema.currentIndex())
        self.show_dock(self.activate_dock.isChecked())
        self.show_menus(self.activate_menubar.isChecked())
        return True

    @check_connected
    def load_menus(self, profile=None, schema=None):
        """
        Load menus in the main windows qgis bar
        """
        if not schema:
            schema = self.combo_schema.currentText()
        if not profile:
            profile = self.combo_profile.currentText()
        # remove previous menus
        for menu in self.uiparent.menus:
            self.uiparent.iface.mainWindow().menuBar().removeAction(menu.menuAction())

        with self.transaction():
            cur = self.connection.cursor()
            select = """
                select name, profile, model_index, datasource_uri
                from {}.{}
                where profile = '{}'
                """.format(schema, self.table, profile)
            cur.execute(select)
            rows = cur.fetchall()
        # item accessor ex: '0-menu/0-submenu/1-item/'
        menudict = {}
        # reference to parent item
        parent = ''
        # reference to qgis main menu bar
        menubar = self.uiparent.iface.mainWindow().menuBar()

        for name, profile, model_index, datasource_uri in self.sortby_modelindex(rows):
            uri_struct = QgsMimeDataUtils.Uri(datasource_uri)
            indexes = json.loads(model_index)
            # root menu
            parent = '{}-{}/'.format(indexes[0][0], indexes[0][1])
            if parent not in menudict:
                menu = QMenu(self.uiparent.iface.mainWindow())
                self.uiparent.menus.append(menu)
                menu.setObjectName(indexes[0][1])
                menu.setTitle(indexes[0][1])
                menubar.insertMenu(
                    self.uiparent.iface.firstRightStandardMenu().menuAction(),
                    menu)
                menudict[parent] = menu
            else:
                # menu already there
                menu = menudict[parent]

            for idx, subname in indexes[1:-1]:
                # intermediate submenus
                parent += '{}-{}/'.format(idx, subname)
                if parent not in menudict:
                    submenu = menu.addMenu(subname)
                    submenu.setObjectName(subname)
                    submenu.setTitle(subname)
                    menu = submenu
                    # store it for later use
                    menudict[parent] = menu
                    continue
                # already treated
                menu = menudict[parent]

            # last item = layer
            layer = QAction(name, self.uiparent.iface.mainWindow())

            if uri_struct.providerKey in ICON_MAPPER:
                layer.setIcon(QIcon(ICON_MAPPER[uri_struct.providerKey]))

            if uri_struct.providerKey == 'postgres':
                # set tooltip to postgres comment
                comment = self.get_table_comment(uri_struct.uri)
                layer.setStatusTip(comment)
                layer.setToolTip(comment)

            layer.setData(uri_struct.uri)
            layer.setWhatsThis(uri_struct.providerKey)
            layer.triggered.connect(self.layer_handler[uri_struct.layerType])
            menu.addAction(layer)

    def get_table_comment(self, uri):
        schema, table = re.match(
            '.*table=(.*)\(.*',
            uri
        ).group(1).strip().replace('"', '').split('.')
        with self.transaction():
            cur = self.connection.cursor()
            select = """
                select description from pg_description
                join pg_class on pg_description.objoid = pg_class.oid
                join pg_namespace on pg_class.relnamespace = pg_namespace.oid
                where relname = '{}' and nspname='{}'
                """.format(table, schema)
            cur.execute(select)
            row = cur.fetchone()
            if row:
                return row[0]
        return ''

    def load_from_index(self, index):
        """Load layers from selected item index"""
        item = self.dock_model.itemFromIndex(self.proxy_model.mapToSource(index))
        if item.whatsThis() == 'menu':
            return
        if item.data().layerType == 'vector':
            layer = QgsVectorLayer(
                item.data().uri,  # uri
                item.text(),  # layer name
                item.data().providerKey  # provider name
            )
        elif item.data().layerType == 'raster':
            layer = QgsRasterLayer(
                item.data().uri,  # uri
                item.text(),  # layer name
                item.data().providerKey  # provider name
            )
        if not layer:
            return
        QgsMapLayerRegistry.instance().addMapLayer(layer)

    def load_vector(self):
        action = self.sender()
        layer = QgsVectorLayer(
            action.data(),  # uri
            action.text(),  # layer name
            action.whatsThis()  # provider name
        )
        QgsMapLayerRegistry.instance().addMapLayer(layer)

    def load_raster(self):
        action = self.sender()
        layer = QgsRasterLayer(
            action.data(),  # uri
            action.text(),  # layer name
            action.whatsThis()  # provider name
        )
        QgsMapLayerRegistry.instance().addMapLayer(layer)

    def accept(self):
        if self.save_changes():
            QDialog.reject(self)
            self.close_connection()

    def reject(self):
        self.close_connection()
        QDialog.reject(self)

    def close_connection(self):
        """close current pg connection if exists"""
        if getattr(self, 'connection', False):
            if self.connection.closed:
                return
            self.connection.close()

    def save_session(self, database, schema, profile, dock, menubar):
        """save current profile for next session"""
        settings = QSettings()
        settings.setValue("MenuBuilder/database", database)
        settings.setValue("MenuBuilder/schema", schema)
        settings.setValue("MenuBuilder/profile", profile)
        settings.setValue("MenuBuilder/dock", dock)
        settings.setValue("MenuBuilder/menubar", menubar)

    def restore_session(self):
        settings = QSettings()
        database = settings.value("MenuBuilder/database", False)
        schema = settings.value("MenuBuilder/schema", 'public')
        profile = settings.value("MenuBuilder/profile", False)
        dock = settings.value("MenuBuilder/dock", False)
        menubar = settings.value("MenuBuilder/menubar", False)
        if not any([database, profile]):
            return

        self.set_connection(0, dbname=database)
        self.show_dock(bool(dock), profile=profile, schema=schema)
        self.show_menus(bool(menubar), profile=profile, schema=schema)
コード例 #6
0
ファイル: MetMainGui.py プロジェクト: jerkos/metms
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))
コード例 #7
0
    def lauchGUI(self, WorkSpace, aCase, sobjXML, Args):
        """
        mw.dockWidgetBrowser is the Browser of the CFD MainView
        """
        log.debug("lauchGUI")
        from cs_gui import process_cmd_line

        if CFD_Code() == CFD_Saturne:
            from cs_package import package
            from code_saturne.Base.MainView import MainView
        elif CFD_Code() == CFD_Neptune:
            from nc_package import package
            from neptune_cfd.core.MainView import MainView

        if sobjXML == None:
            Title = "unnamed"
        else:
            Title = sobjXML.GetName()

        self.Workspace = WorkSpace
        pkg = package()
        case, splash = process_cmd_line(Args)
        mw = MainView(pkg, case, aCase)

        # Put the standard panel of the MainView inside a QDockWidget
        # in the SALOME Desktop
        aTitle = self.setWindowTitle_CFD(mw, aCase, Title)
        dsk = sgPyQt.getDesktop()
        dock = QDockWidget(aTitle)

        dock.setWidget(mw.frame)
        dock.setMinimumWidth(520)
        dsk.addDockWidget(Qt.RightDockWidgetArea, dock)

        dock.setVisible(True)
        dock.show()

        # Put the QTreeView of the MainView which is already inside a QDockWidget
        # in the SALOME Desktop
        BrowserTitle = aTitle + " Browser"
        mw.dockWidgetBrowser.setWindowTitle(BrowserTitle)
        dsk.addDockWidget(Qt.LeftDockWidgetArea, mw.dockWidgetBrowser)

        mw.dockWidgetBrowser.setVisible(True)
        mw.dockWidgetBrowser.show()
        mw.dockWidgetBrowser.raise_()
        dock.raise_()

        #Add Dock windows are managed by CFDGUI_Management class
        studyId = sgPyQt.getStudyId()
        aStudyCFD = aCase.GetFather()
        aCaseCFD = aCase
        xmlFileName = str(Title)
        _c_CFDGUI.set_d_CfdCases(studyId, dock, mw.dockWidgetBrowser, mw,
                                 aStudyCFD, aCaseCFD, xmlFileName, sobjXML)

        self.connect(dock, SIGNAL("visibilityChanged(bool)"),
                     self.setdockWindowBrowserActivated)
        self.connect(mw.dockWidgetBrowser, SIGNAL("visibilityChanged(bool)"),
                     self.setdockWindowActivated)

        self.connect(dock.toggleViewAction(), SIGNAL("toggled(bool)"),
                     self.setdockWB)
        self.connect(mw.dockWidgetBrowser.toggleViewAction(),
                     SIGNAL("toggled(bool)"), self.setdock)

        _c_CFDGUI.tabifyDockWindows(dsk, studyId)
        self.showDockWindows(studyId, xmlFileName, aCaseCFD.GetName(),
                             aStudyCFD.GetName())
        updateObjectBrowser()

        return mw