Exemple #1
0
    def create_dockwidget(self):
        """Add to parent QMainWindow as a dock widget"""

        # This is not clear yet why the following do not work...
        # (see Issue #880)
##         # Using Qt.Window window flags solves Issue #880 (detached dockwidgets
##         # are not painted after restarting Spyder and restoring their hexstate)
##         # but it does not work with PyQt <=v4.7 (dockwidgets can't be docked)
##         # or non-Windows platforms (lot of warnings are printed out)
##         # (so in those cases, we use the default window flags: Qt.Widget):
##         flags = Qt.Widget if is_old_pyqt or os.name != 'nt' else Qt.Window
        dock = QDockWidget(self.get_plugin_title(), self.main)#, flags)

        dock.setObjectName(self.__class__.__name__+"_dw")
        dock.setAllowedAreas(self.ALLOWED_AREAS)
        dock.setFeatures(self.FEATURES)
        dock.setWidget(self)
        self.update_margins()
        self.connect(dock, SIGNAL('visibilityChanged(bool)'),
                     self.visibility_changed)
        self.dockwidget = dock
        short = self.get_option("shortcut", None)
        if short is not None:
            shortcut = QShortcut(QKeySequence(short),
                                 self.main, self.switch_to_plugin)
            self.register_shortcut(shortcut, "_",
                                   "Switch to %s" % self.CONF_SECTION,
                                   default=short)
        return (dock, self.LOCATION)
Exemple #2
0
 def setupUI(self):
     
     self.browser = browser = SimpleServerBrowser()
     self.player = player = video.Player() #VideoPlayer()        
     
     dock = QDockWidget(u'Przeglądarka serwerów', self)
     dock.setContentsMargins(0, 0, 0, 0)
     
     dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
     dock.setWidget(browser)        
     
     self.addDockWidget(Qt.LeftDockWidgetArea, dock)        
             
     #self.setCentralWidget(player.videoWidget())
     self.setCentralWidget(player.videoWidget)
     
     dock = QDockWidget(self)
     dock.setAllowedAreas(Qt.BottomDockWidgetArea)
     dock.setWidget(player.controlPanel)
     
     dock.setFloating(False)
     dock.setFeatures(QDockWidget.NoDockWidgetFeatures)
     self.addDockWidget(Qt.BottomDockWidgetArea, dock)
 
     QWidget.connect(self.browser, SIGNAL("play"), self.play)
     self.resize(800, 480)
Exemple #3
0
def add_widget_into_main(parent):
    """add a widget into the main window of LabGuiMain
    
    create a QDock widget and store a reference to the widget
    """
    


            
    

    mywidget = SimpleConnectWidget(parent = parent)
    
    #create a QDockWidget
    simpleconnectDockWidget = QDockWidget("Simple instrument console",
                                                parent)
    simpleconnectDockWidget.setObjectName("simpleConnectWidgetDockWidget")
    simpleconnectDockWidget.setAllowedAreas(
            Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
        
    #fill the dictionnary with the widgets added into LabGuiMain
    parent.widgets['ConnectTerminalWidget'] = mywidget
    
    simpleconnectDockWidget.setWidget(mywidget)
    parent.addDockWidget(Qt.RightDockWidgetArea, simpleconnectDockWidget)
    
    #Enable the toggle view action
    parent.windowMenu.addAction(simpleconnectDockWidget.toggleViewAction())
    simpleconnectDockWidget.hide()      
Exemple #4
0
 def _createDock(self):
     dock = QDockWidget("")
     dock.setObjectName("ERTGUI Workflow")
     dock.setWidget(self.contentsWidget)
     dock.setFeatures(QDockWidget.DockWidgetClosable)
     dock.setAllowedAreas(Qt.LeftDockWidgetArea)
     return dock
Exemple #5
0
    def create_dockwidget(self):
        """Add to parent QMainWindow as a dock widget"""

        # This is not clear yet why the following do not work...
        # (see Issue #880)
        ##         # Using Qt.Window window flags solves Issue #880 (detached dockwidgets
        ##         # are not painted after restarting Spyder and restoring their hexstate)
        ##         # but it does not work with PyQt <=v4.7 (dockwidgets can't be docked)
        ##         # or non-Windows platforms (lot of warnings are printed out)
        ##         # (so in those cases, we use the default window flags: Qt.Widget):
        ##         flags = Qt.Widget if is_old_pyqt or os.name != 'nt' else Qt.Window
        dock = QDockWidget(self.get_plugin_title(), self.main)  #, flags)

        dock.setObjectName(self.__class__.__name__ + "_dw")
        dock.setAllowedAreas(self.ALLOWED_AREAS)
        dock.setFeatures(self.FEATURES)
        dock.setWidget(self)
        self.update_margins()
        self.connect(dock, SIGNAL('visibilityChanged(bool)'),
                     self.visibility_changed)
        self.dockwidget = dock
        short = self.get_option("shortcut", None)
        if short is not None:
            shortcut = QShortcut(QKeySequence(short), self.main,
                                 self.switch_to_plugin)
            self.register_shortcut(shortcut,
                                   "_",
                                   "Switch to %s" % self.CONF_SECTION,
                                   default=short)
        return (dock, self.LOCATION)
Exemple #6
0
 def _createDock(self):
     dock = QDockWidget("Workflow")
     dock.setObjectName("ERTGUI Workflow")
     dock.setWidget(self.contentsWidget)
     dock.setFeatures(QDockWidget.DockWidgetClosable)
     dock.setAllowedAreas(Qt.LeftDockWidgetArea)
     return dock
Exemple #7
0
    def addDock(self, name, widget, area=Qt.LeftDockWidgetArea, allowed_areas=Qt.AllDockWidgetAreas):
        dock_widget = QDockWidget(name)
        dock_widget.setObjectName("%sDock" % name)
        dock_widget.setWidget(widget)
        dock_widget.setAllowedAreas(allowed_areas)
        dock_widget.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable)

        self.addDockWidget(area, dock_widget)
        return dock_widget
Exemple #8
0
    def addDock(self, name, widget, area=Qt.LeftDockWidgetArea, allowed_areas=Qt.AllDockWidgetAreas):
        dock_widget = QDockWidget(name)
        dock_widget.setObjectName("%sDock" % name)
        dock_widget.setWidget(widget)
        dock_widget.setAllowedAreas(allowed_areas)
        dock_widget.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable)

        self.addDockWidget(area, dock_widget)
        return dock_widget
Exemple #9
0
	def __init__(self, layer, prop):
		QMainWindow.__init__(self)
		
		self.setWindowTitle('PostGIS Viewer - %s' % (layer.name()))
		
		self.canvas = QgsMapCanvas()
		self.canvas.setCanvasColor(Qt.white)
		self.canvas.enableAntiAliasing(True)
		
		tmp = QgsMapLayerRegistry.instance()
		tmp.addMapLayer(layer)
		
		self.canvas.setExtent(layer.extent())
		self.canvas.setLayerSet( [ QgsMapCanvasLayer(layer) ] )
		
		self.setCentralWidget(self.canvas)
		
		actionZoomIn = QAction(QString("Zoom in"), self)
		actionZoomOut = QAction(QString("Zoom out"), self)
		actionPan = QAction(QString("Pan"), self)
		
		actionZoomIn.setCheckable(True)
		actionZoomOut.setCheckable(True)
		actionPan.setCheckable(True)
		
		self.connect(actionZoomIn, SIGNAL("triggered()"), self.zoomIn)
		self.connect(actionZoomOut, SIGNAL("triggered()"), self.zoomOut)
		self.connect(actionPan, SIGNAL("triggered()"), self.pan)
		
		self.toolbar = self.addToolBar("Canvas actions")
		self.toolbar.addAction(actionZoomIn)
		self.toolbar.addAction(actionZoomOut)
		self.toolbar.addAction(actionPan)
		
		# create the map tools
		self.toolPan = QgsMapToolPan(self.canvas)
		self.toolPan.setAction(actionPan)
		self.toolZoomIn = QgsMapToolZoom(self.canvas, False) # false = in
		self.toolZoomIn.setAction(actionZoomIn)
		self.toolZoomOut = QgsMapToolZoom(self.canvas, True) # true = out
		self.toolZoomOut.setAction(actionZoomOut)
		
		self.pan()
		
		dock_layer_prop = QDockWidget(self.tr('Layer Properties'), self)
		dock_layer_prop.setAllowedAreas(Qt.BottomDockWidgetArea)
		self.layer_prop = QListWidget(dock_layer_prop)
		self.layer_prop.addItems(QStringList()
			<< "Layer: %s" % layer.name()
			<< "Source: %s" % layer.source()
			<< "Geometry: %s" % prop['geom_type']
			<< "Extent: %s" % layer.extent().toString()
			<< "PostGIS: %s" % prop['postgis_version']
			)
		dock_layer_prop.setWidget(self.layer_prop)
		self.addDockWidget(Qt.BottomDockWidgetArea, dock_layer_prop)
Exemple #10
0
    def addDock(self, name, widget, area=Qt.RightDockWidgetArea, allowed_areas=Qt.AllDockWidgetAreas):
        dock_widget = QDockWidget(name)
        dock_widget.setObjectName("%sDock" % name)
        dock_widget.setWidget(widget)
        dock_widget.setAllowedAreas(allowed_areas)

        self.addDockWidget(area, dock_widget)

        self.__view_menu.addAction(dock_widget.toggleViewAction())
        return dock_widget
Exemple #11
0
    def addDock(self, name, widget, area=Qt.RightDockWidgetArea, allowed_areas=Qt.AllDockWidgetAreas):
        dock_widget = QDockWidget(name)
        dock_widget.setObjectName("%sDock" % name)
        dock_widget.setWidget(widget)
        dock_widget.setAllowedAreas(allowed_areas)

        self.addDockWidget(area, dock_widget)

        self.__view_menu.addAction(dock_widget.toggleViewAction())
        return dock_widget
Exemple #12
0
 def create_dockwidget(self):
     """Add to parent QMainWindow as a dock widget"""
     dock = QDockWidget(self.get_plugin_title(), self.main)#, self.FLAGS) -> bug in Qt 4.4
     dock.setObjectName(self.__class__.__name__+"_dw")
     dock.setAllowedAreas(self.ALLOWED_AREAS)
     dock.setFeatures(self.FEATURES)
     dock.setWidget(self)
     self.connect(dock, SIGNAL('visibilityChanged(bool)'),
                  self.visibility_changed)
     self.dockwidget = dock
     self.refresh_plugin()
     short = CONF.get(self.ID, "shortcut", None)
     if short is not None:
         QShortcut(QKeySequence(short), self.main,
                   lambda: self.visibility_changed(True))
     return (dock, self.LOCATION)
Exemple #13
0
    def create_widgets(self):

        logDockWidget = QDockWidget("Log", self)
        logDockWidget.setObjectName("LogDockWidget")
        logDockWidget.setAllowedAreas(Qt.LeftDockWidgetArea |
                                      Qt.RightDockWidgetArea)
        self.listWidget = QListWidget()
        logDockWidget.setWidget(self.listWidget)
        self.addDockWidget(Qt.RightDockWidgetArea, logDockWidget)

        self.sizeLabel = QLabel()
        self.sizeLabel.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken)
        self.status = self.statusBar()
        self.status.setSizeGripEnabled(False)
        self.status.addPermanentWidget(self.sizeLabel)
        self.status.showMessage("Ready", 5000)
Exemple #14
0
 def create_dockwidget(self):
     """Add to parent QMainWindow as a dock widget"""
     dock = QDockWidget(self.get_widget_title(), self.main)#, self.flags) -> bug in Qt 4.4
     dock.setObjectName(self.__class__.__name__+"_dw")
     dock.setAllowedAreas(self.allowed_areas)
     dock.setFeatures(self.features)
     dock.setWidget(self)
     self.connect(dock, SIGNAL('visibilityChanged(bool)'),
                  self.visibility_changed)
     self.dockwidget = dock
     self.refresh()
     short = CONF.get(self.ID, "shortcut", None)
     if short is not None:
         QShortcut(QKeySequence(short), self.main,
                   lambda: self.visibility_changed(True))
     return (dock, self.location)
Exemple #15
0
    def create_widgets(self):
        self.imageLabel = QLabel()
        self.imageLabel.setMinimumSize(200, 200)
        self.imageLabel.setAlignment(Qt.AlignCenter)
        self.imageLabel.setContextMenuPolicy(Qt.ActionsContextMenu)
        self.setCentralWidget(self.imageLabel)

        logDockWidget = QDockWidget("Log", self)
        logDockWidget.setObjectName("LogDockWidget")
        logDockWidget.setAllowedAreas(Qt.LeftDockWidgetArea
                                      | Qt.RightDockWidgetArea)
        self.listWidget = QListWidget()
        logDockWidget.setWidget(self.listWidget)
        self.addDockWidget(Qt.RightDockWidgetArea, logDockWidget)

        self.sizeLabel = QLabel()
        self.sizeLabel.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken)
        status = self.statusBar()
        status.setSizeGripEnabled(False)
        status.addPermanentWidget(self.sizeLabel)
        status.showMessage("Ready", 5000)
    def create_widgets(self):
        self.imageLabel = QLabel()
        self.imageLabel.setMinimumSize(200, 200)
        self.imageLabel.setAlignment(Qt.AlignCenter)
        self.imageLabel.setContextMenuPolicy(Qt.ActionsContextMenu)
        self.setCentralWidget(self.imageLabel)

        logDockWidget = QDockWidget("Log", self)
        logDockWidget.setObjectName("LogDockWidget")
        logDockWidget.setAllowedAreas(Qt.LeftDockWidgetArea|
                                      Qt.RightDockWidgetArea)
        self.listWidget = QListWidget()
        logDockWidget.setWidget(self.listWidget)
        self.addDockWidget(Qt.RightDockWidgetArea, logDockWidget)

        self.sizeLabel = QLabel()
        self.sizeLabel.setFrameStyle(QFrame.StyledPanel|QFrame.Sunken)
        status = self.statusBar()
        status.setSizeGripEnabled(False)
        status.addPermanentWidget(self.sizeLabel)
        status.showMessage("Ready", 5000)
Exemple #17
0
class OrbitPlotMainWindow(QMainWindow):
    """
    the main window has three major widgets: current, orbit tabs and element
    editor.
    """
    def __init__(self, parent=None, machines=[], **kwargs):
        QMainWindow.__init__(self, parent)
        self.iqtApp = kwargs.get("iqt", None)

        self.setIconSize(QSize(32, 32))
        self.error_bar = True
        self._dlgOrbitCor = None
        # logging
        self.logdock = QDockWidget("Log")
        self.logdock.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
        textedit = QPlainTextEdit(self.logdock)

        self.logger = logging.getLogger(__name__)

        self.guilogger = logging.getLogger("aphla.gui")
        # the "aphla" include lib part logging. When the lib is inside
        # QThread, logging message will be sent to TextEdit which is cross
        # thread.
        # self.guilogger = logging.getLogger("aphla")
        handler = QTextEditLoggingHandler(textedit)
        self.guilogger.addHandler(handler)
        self.guilogger.setLevel(logging.INFO)
        self.logdock.setWidget(textedit)
        self.logdock.setAllowedAreas(Qt.BottomDockWidgetArea)
        self.logdock.setFeatures(QDockWidget.DockWidgetMovable
                                 | QDockWidget.DockWidgetClosable)
        self.logdock.setFloating(False)
        self.logdock.setMinimumHeight(20)
        self.logdock.setMaximumHeight(100)
        self.logdock.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
        self.logdock.resize(200, 60)
        #print self.logdock.sizeHint()
        self.addDockWidget(Qt.BottomDockWidgetArea, self.logdock)
        #print self.logdock.sizeHint()
        #print self.logdock.minimumSize()
        #print self.logdock.maximumSize()
        #self.logger.info("INFO")
        #self.logdock.setMinimumHeight(40)
        #self.logdock.setMaximumHeight(160)

        for msg in kwargs.get("infos", []):
            self.logger.info(msg)
        # dict of (machine, (lattice dict, default_lat, pvm))
        self._mach = dict([(v[0], (v[1], v[2], v[3])) for v in machines])
        for m, (lats, lat0, pvm) in self._mach.items():
            self.logger.info(
                "machine '%s' initialized: [%s]" %
                (m, ", ".join([lat.name for k, lat in lats.items()])))
            if pvm:
                for pv in pvm.dead():
                    self.logger.warn("'{0}' is disconnected.".format(pv))
        ## DCCT current plot
        #self.dcct = DcctCurrentPlot()
        #self.dcct.setMinimumHeight(100)
        #self.dcct.setMaximumHeight(150)

        #t0 = time.time()
        #t = np.linspace(t0 - 8*3600*24, t0, 100)
        #self.dcct.curve.t = t
        #v = 500*np.exp((t[0] - t[:50])/(4*3600*24))
        #self.dcct.curve.v = v.tolist()+v.tolist()
        #self.dcct.updatePlot()

        ## MDI area
        self.mdiarea = QMdiArea()
        self.connect(self.mdiarea, SIGNAL("subWindowActivated(QMdiSubWindow)"),
                     self.updateMachineLatticeNames)
        self.mdiarea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.physics = ApOrbitPhysics(self.mdiarea, iqt=self.iqtApp)
        self.live_orbit = True

        self.setCentralWidget(self.mdiarea)

        #self._elemed = ElementPropertyTabs()
        #self.elemeditor = ElementEditorDock(parent=self)
        #self.elemeditor.setAllowedAreas(Qt.RightDockWidgetArea)
        #self.elemeditor.setFeatures(QDockWidget.DockWidgetMovable|
        #                            QDockWidget.DockWidgetClosable)
        #self.elemeditor.setFloating(False)
        #self.elemeditor.setEnabled(False)
        #self.elemeditor.setMinimumWidth(400)
        #self.elemeditor.setWidget(self._elemed)
        #self.elemeditor.show()
        #self.elemeditor.hide()
        #self.connect(self.elemeditor,
        #             SIGNAL("elementChecked(PyQt_PyObject, bool)"),
        #             self.physics.elementChecked)
        #self.addDockWidget(Qt.RightDockWidgetArea, self.elemeditor)

        self.createMenuToolBar()

        # the first machine is the default
        self.machBox.addItems([v for v in self._mach.keys()])
        self.reloadLatticeNames(self.machBox.currentText())
        self.connect(self.machBox, SIGNAL("currentIndexChanged(QString)"),
                     self.reloadLatticeNames)

        # update at 1/2Hz
        self.dt, self.itimer = 1500, 0
        #self.timerId = None
        self.timerId = self.startTimer(self.dt)

        self.vbpm = None
        self.statusBar().showMessage("Welcome")

        #self.initMachine("nsls2v2")
        #self._newVelemPlot("V2SR", aphla.machines.HLA_VBPM, 'x',
        #                   "H Orbit", c = None)
        #print "Thread started", self.machinit.isRunning()

        #self.newElementPlots("BPM", "x, y")
        #self.newElementPlot("BPM", "y")
        #self.newElementPlot("HCOR", "x")
        #self.newElementPlot("VCOR", "y")
        #self.newElementPlot("QUAD", "b1")
        #self.newElementPlot("SEXT", "b2")

    def updateMachineLatticeNames(self, wsub):
        i = self.machBox.findText(wsub.machlat[0])
        self.machBox.setCurrentIndex(i)
        self.reloadLatticeNames(wsub.machlat[0])

    def reloadLatticeNames(self, mach):
        self.latBox.clear()
        cur_mach = str(self.machBox.currentText())
        lats, lat0, pvm = self._mach.get(cur_mach, ({}, None, None))
        self.latBox.addItems([lat for lat in lats.keys()])
        if lat0:
            i = self.latBox.findText(lat0.name)
            self.latBox.setCurrentIndex(i)

    def closeEvent(self, event):
        self.physics.close()
        self.mdiarea.closeAllSubWindows()
        event.accept()

    def createMenuToolBar(self):
        #
        # file menu
        #
        #self.machMenu = self.menuBar().addMenu("&Machines")
        #self.connect(self.machMenu, SIGNAL("aboutToShow()"),
        #             self.updateMachMenu)
        self.openMenu = self.menuBar().addMenu("&Open")
        self.openMenu.addAction("New Plot ...", self.openNewPlot)
        self.openMenu.addAction("New Tune Plot", self.openTunePlot)
        self.openMenu.addAction("New BPM Plot",
                                partial(self.newElementPlots, "BPM", "x,y"))
        self.openMenu.addAction("New HCOR Plot",
                                partial(self.newElementPlots, "HCOR", "x"))
        self.openMenu.addAction("New VCOR Plot",
                                partial(self.newElementPlots, "VCOR", "y"))

        self.openMenu.addSeparator()
        self.openMenu.addAction("Open ORM", self.loadOrm)

        self.openMenu.addSeparator()
        self.openMenu.addAction("Save Lattice ...", self.saveSnapshot)

        fileQuitAction = QAction(QIcon(":/file_quit.png"), "&Quit", self)
        fileQuitAction.setShortcut("Ctrl+Q")
        fileQuitAction.setToolTip("Quit the application")
        fileQuitAction.setStatusTip("Quit the application")
        #fileQuitAction.setIcon(Qt.QIcon(":/filequit.png"))
        self.connect(fileQuitAction, SIGNAL("triggered()"), self.close)
        self.openMenu.addAction(fileQuitAction)

        # view
        self.viewMenu = self.menuBar().addMenu("&View")

        mkmenu = QMenu("&Mark", self.viewMenu)
        for fam in ["BPM", "COR", "QUAD", "SEXT", "INSERTION"]:
            famAct = QAction(fam, self)
            famAct.setCheckable(True)
            self.connect(famAct, SIGNAL("toggled(bool)"), self.click_markfam)
            mkmenu.addAction(famAct)
        #

        # errorbar
        #viewErrorBarAction = QAction(QIcon(":/view_errorbar.png"),
        #                            "Errorbar", self)
        #viewErrorBarAction.setCheckable(True)
        #viewErrorBarAction.setChecked(True)
        #self.connect(viewErrorBarAction, SIGNAL("toggled(bool)"),
        #             self.errorBar)
        #
        #zoomM = QMenu("Zoom", self.viewMenu)

        #
        #
        #drift_from_now = QAction("Drift from Now", self)
        #drift_from_now.setCheckable(True)
        #drift_from_now.setShortcut("Ctrl+N")
        #drift_from_golden = QAction("Drift from Golden", self)
        #drift_from_golden.setCheckable(True)
        #drift_from_none = QAction("None", self)
        #drift_from_none.setCheckable(True)

        #self.viewMenu.addAction(viewLiveAction)
        #self.viewMenu.addAction(viewSingleShotAction)
        #self.viewMenu.addSeparator()

        #self.viewMenu.addAction(drift_from_now)
        #self.viewMenu.addAction(drift_from_golden)
        #self.viewMenu.addAction(drift_from_none)
        #self.viewMenu.addAction(viewAutoScale)
        #self.viewMenu.addAction(viewErrorBarAction)
        #self.viewMenu.addSeparator()

        self.viewMenu.addMenu(mkmenu)

        #drift_group = QActionGroup(self)
        #drift_group.addAction(drift_from_none)
        #drift_group.addAction(drift_from_now)
        #drift_group.addAction(drift_from_golden)
        #drift_from_none.setChecked(True)

        sep = self.viewMenu.addSeparator()
        #sep.setText("Drift")
        #self.connect(drift_from_now, SIGNAL("triggered()"), self.setDriftNow)
        #self.connect(drift_from_none, SIGNAL("triggered()"), self.setDriftNone)
        #self.connect(drift_from_golden, SIGNAL("triggered()"),
        #             self.setDriftGolden)

        #viewStyle = QMenu("Line Style", self.viewMenu)
        #for act in ["Increase Point Size", "Decrease Point Size", None,
        #            "NoCurve", "Lines", "Sticks", None,
        #            "Solid Line", "Dashed Line", "Dotted Line", None,
        #            "Increase Line Width", "Decrease Line Width", None,
        #            "NoSymbol", "Ellipse", "Rect", "Diamond", "Triangle",
        #            "Cross", "XCross", "HLine", "VLine",
        #            "Star1", "Star2", "Hexagon", None,
        #            "Red", "Blue", "Green"]:
        #    if act is None:
        #        viewStyle.addSeparator()
        #    else:
        #        viewStyle.addAction(act, self.setPlotStyle)
        #self.viewMenu.addMenu(viewStyle)

        #self.viewMenu.addSeparator()
        #self.viewMenu.addAction(viewZoomOut15Action)
        #self.viewMenu.addAction(viewZoomIn15Action)
        #self.viewMenu.addAction(viewZoomAutoAction)
        #self.viewMenu.addSeparator()
        self.viewMenu.addAction("ORM SV", self.plotSVD)
        # a bug in PyQwt5 for datetime x-axis, waiting for Debian 7
        #self.viewMenu.addAction(viewDcct)
        #for ac in self.viewMenu.actions(): ac.setDisabled(True)

        #
        self.controlMenu = self.menuBar().addMenu("&Tools")

        self.controlMenu.addAction(QIcon(":/control_choosebpm.png"),
                                   "En-/Disable BPM",
                                   partial(chooseElement, 'BPM'))
        self.controlMenu.addAction("En-/Disable COR",
                                   partial(chooseElement, 'COR'))
        #self.controlMenu.addAction(controlResetPvDataAction)
        self.controlMenu.addSeparator()
        self.controlMenu.addAction("Lattice Snapshot ...", self.openSnapshot)
        #self.controlMenu.addAction(controlZoomInPlot1Action)
        #self.controlMenu.addAction(controlZoomOutPlot1Action)
        #self.controlMenu.addAction(controlZoomInPlot2Action)
        #self.controlMenu.addAction(controlZoomOutPlot2Action)
        self.controlMenu.addSeparator()
        self.controlMenu.addAction("Correct Hor. orbit",
                                   partial(aphla.correctOrbit, plane="H"))
        self.controlMenu.addAction("Correct Vert. orbit",
                                   partial(aphla.correctOrbit, plane="V"))
        self.controlMenu.addAction(QIcon(":/control_corrorbit.png"),
                                   "Correct orbit",
                                   partial(aphla.correctOrbit, plane="HV"))
        #steer_orbit.setDisabled(True)
        self.controlMenu.addAction("Local Bump ...", self.createLocalBump)
        self.controlMenu.addAction("Element Editor ...",
                                   self.showElementEditor)
        self.controlMenu.addSeparator()
        self.controlMenu.addAction("meas Beta", self.physics.measBeta)
        self.controlMenu.addAction("meas Dispersion",
                                   self.physics.measDispersion)
        self.controlMenu.addAction("beam based alignment", self.runBba)
        #for ac in self.controlMenu.actions(): ac.setDisabled(True)

        # Window
        self.windowMenu = self.menuBar().addMenu("&Windows")
        #self.windowMenu.addAction(self.elemeditor.toggleViewAction())
        self.windowMenu.addAction(self.logdock.toggleViewAction())
        #viewDcct = QAction("Beam Current", self)
        #viewDcct.setCheckable(True)
        #viewDcct.setChecked(True)
        #self.connect(viewDcct, SIGNAL("toggled(bool)"), self.dcct.setVisible)
        #self.windowMenu.addAction(viewDcct)
        self.windowMenu.addSeparator()
        self.windowMenu.addAction("Cascade", self.mdiarea.cascadeSubWindows)
        self.windowMenu.addAction("Tile", self.mdiarea.tileSubWindows)
        self.windowMenu.addAction("Tile Horizontally",
                                  self.tileSubWindowsHorizontally)
        # "ctrl+page up", "ctrl+page down"
        self.windowMenu.addAction("Previous",
                                  self.mdiarea.activatePreviousSubWindow,
                                  "Ctrl+Left")
        self.windowMenu.addAction("Next", self.mdiarea.activateNextSubWindow,
                                  "Ctrl+Right")
        self.windowMenu.addSeparator()

        # debug
        self.debugMenu = self.menuBar().addMenu("&Debug")
        self.debugMenu.addAction("_Reset Correctors_", self._reset_correctors)
        self.debugMenu.addAction("_Reset Quadrupoles_",
                                 self._reset_quadrupoles)
        self.debugMenu.addAction("_Random V Kick_", self._random_vkick)
        self.debugMenu.addAction("_Random H Kick_", self._random_hkick)
        #for ac in self.debugMenu.actions(): ac.setDisabled(True)

        # help
        self.helpMenu = self.menuBar().addMenu("&Help")
        self.helpMenu.addAction("About mleap", self.showAbout)

        #toolbar
        machToolBar = self.addToolBar("Machines")
        self.machBox = QtGui.QComboBox()
        self.latBox = QtGui.QComboBox()
        #self.connect(self.latBox, SIGNAL("currentIndexChanged(QString)"),
        #             self.__setLattice)
        machToolBar.addWidget(self.machBox)
        machToolBar.addWidget(self.latBox)
        #toolbar = QToolBar(self)
        #self.addToolBar(toolbar)
        #fileToolBar = self.addToolBar("File")
        #fileToolBar.setObjectName("FileToolBar")
        #fileToolBar.addAction(fileQuitAction)

        #
        viewToolBar1 = self.addToolBar("Live View")
        #viewToolBar.setObjectName("ViewToolBar")
        #viewToolBar.addAction(viewZoomOut15Action)
        #viewToolBar.addAction(viewZoomIn15Action)
        #viewToolBar.addAction(viewZoomAutoAction)
        #viewToolBar1.addAction(viewLiveAction)
        #viewToolBar1.addAction(viewSingleShotAction)
        #viewToolBar1.addSeparator()
        viewToolBar1.addAction(QIcon(":/new_bpm.png"), "Orbits",
                               partial(self.newElementPlots, "BPM", "x,y"))
        viewToolBar1.addAction(QIcon(":/new_cor.png"), "Correctors",
                               partial(self.newElementPlots, "COR", "x,y"))
        viewToolBar1.addAction(QIcon(":/new_quad.png"), "Quadrupoles",
                               partial(self.newElementPlots, "QUAD", "b1"))
        viewToolBar1.addAction(QIcon(":/new_sext.png"), "Sextupoles",
                               partial(self.newElementPlots, "SEXT", "b2"))
        #viewToolBar.addAction(viewErrorBarAction)
        #viewToolBar.addAction(QWhatsThis.createAction(self))

        #viewToolBar2 = self.addToolBar("Scale Plot")
        #zoomActions = [(":/view_zoom_xy.png", "Fit", self.scalePlot),
        #               (None, None, None),
        #               (":/view_zoom_y.png", "Fit In Y", self.scalePlot),
        #               (":/view_zoomin_y.png", "Zoom In Y", self.scalePlot),
        #               (":/view_zoomout_y.png", "Zoom Out Y", self.scalePlot),
        #               (":/view_move_up.png", "Move Up", self.scalePlot),
        #               (":/view_move_down.png", "Move Down", self.scalePlot),
        #               (None, None, None),
        #               (":/view_zoom_x.png", "Fit In X", self.scalePlot),
        #               (":/view_zoomin_x.png", "Zoom In X", self.scalePlot),
        #               (":/view_zoomout_x.png", "Zoom Out X", self.scalePlot),
        #               (":/view_move_left.png", "Move Left", self.scalePlot),
        #               (":/view_move_right.png", "Move Right", self.scalePlot),
        #               ]
        #for ico,name,hdl in zoomActions:
        #    if hdl is None: continue
        #    viewToolBar2.addAction(QIcon(ico), name, hdl)

        controlToolBar = self.addToolBar("Control")
        controlToolBar.addAction(QIcon(":/control_orbitcor.png"),
                                 "Correct Orbit", aphla.correctOrbit)
        controlToolBar.addAction(QIcon(":/control_localbump.png"),
                                 "Local Bump ...", self.createLocalBump)
        #controlToolBar.addAction(controlResetPvDataAction)

    def showAbout(self):
        QMessageBox.about(
            self, self.tr("mleap"),
            (self.tr("""<b>Machine/Lattice Editor And Plotter</b> v %1
                <p>Copyright &copy; Lingyun Yang, BNL, 2013-2014. 
                All rights reserved.
                <p>This application can be used to perform
                high level accelerator controls.
                <p>Python %2 - Qt %3 - PyQt %4 
                on %5""").arg(aphla.version.version).arg(
                platform.python_version()).arg(QtCore.QT_VERSION_STR).arg(
                    QtCore.PYQT_VERSION_STR).arg(platform.system())))

    def showElementEditor(self):
        mach, lat = self.getCurrentMachLattice()
        ed = ElementEditor(lat, parent=self)
        ed.setWindowFlags(Qt.Window)
        ed.setAttribute(Qt.WA_DeleteOnClose)
        ed.show()

    def getCurrentMachLattice(self, cadata=False):
        """return the current machine name and lattice object"""
        mach = str(self.machBox.currentText())
        latname = str(self.latBox.currentText())
        lat_dict, lat0, pvm = self._mach[mach]
        if not cadata:
            return mach, lat_dict[latname]
        else:
            return mach, lat_dict[latname], pvm

    def newElementPlots(self, elem, fields, **kw):
        self.logger.info("new plots: %s %s" % (elem, fields))
        _mach, _lat, _pvm = self.getCurrentMachLattice(cadata=True)
        mach, lat = kw.get("machlat", (_mach, _lat))
        handle = kw.get("handle", "readback")
        elems = lat.getElementList(elem)
        x, pvs = [], []
        field_list = re.findall(r'[^ ,]+', fields)
        for fld in field_list:
            si, pvsi = [], []
            for e in elems:
                if not e.isEnabled(): continue
                epv = e.pv(field=fld, handle=handle)
                if not epv: continue
                pvsi.append(epv[0])
                si.append(e.sb)
            x.append(si)
            pvs.append(pvsi)

        if not pvs:
            self.logger.error("no data found for elements '{0}' "
                              "and field '{1}'".format(elem, field))
            return

        p = ApMdiSubPlot(pvs=pvs,
                         x=x,
                         labels=["%s.%s" % (elem, fld) for fld in field_list],
                         magprof=lat.getBeamlineProfile(),
                         iqt=self.iqtApp,
                         **kw)
        #QObject.installEventFilter(p.aplot)
        #p.data = ManagedPvData(pvm, s, pvs, element=elemnames,
        #                       label="{0}.{1}".format(elem,field))
        p.setAttribute(Qt.WA_DeleteOnClose)
        str_elem = "{0}".format(elem)
        if len(str_elem) > 12: str_elem = str_elem[:9] + "..."
        str_field = "{0}".format(fields)
        if len(str_field) > 12: str_field = str_field[:9] + "..."
        p.setWindowTitle("[%s.%s] %s %s" %
                         (mach, lat.name, str_elem, str_field))
        self.connect(p, SIGNAL("elementSelected(PyQt_PyObject)"),
                     self.elementSelected)
        self.connect(p, SIGNAL("destroyed()"), self.subPlotDestroyed)
        #p.updatePlot()
        # set the zoom stack
        #p.aplot.setErrorBar(self.error_bar)
        #p.wid.autoScaleXY()
        #p.aplot.replot()
        self.mdiarea.addSubWindow(p)
        #print "Show"
        p.show()

        ##print "Enable the buttons"
        #if len(self.mdiarea.subWindowList()) > 0:
        #    self.elemeditor.setEnabled(True)

    def subPlotDestroyed(self):
        #if len(self.mdiarea.subWindowList()) == 0:
        #    self.elemeditor.setEnabled(False)
        pass

    def loadOrm(self):
        fileName = QtGui.QFileDialog.getOpenFileName(
            self, "Open Orbit Response Matrix", "",
            "ORM Files (*.h5 *.hdf5);;Text File (*.txt);;All Files(*)")
        fileName = str(fileName)
        try:
            m = np.loadtxt(fileName)
        except:
            QMessageBox.critical(self, "Abort", "Invalid matrix data")
            return
        mach, lat = self.getCurrentMachLattice()
        # assuming we already have the PV, name, field but just want to
        # replace the matrix elements.
        assert np.shape(m) == np.shape(lat.ormdata.m)
        nx, ny = np.shape(lat.ormdata.m)
        for i in range(nx):
            for j in range(ny):
                lat.ormdata.m[i, j] = m[i, j]

    def saveSnapshot(self):
        latdict = dict([(k, v[0]) for k, v in self._mach.items()])
        mach, lat = self.getCurrentMachLattice()
        snapdlg = SaveSnapshotDialog(latdict, mach)
        snapdlg.exec_()

    def saveLatSnapshot(self):
        mach, lat = self.getCurrentMachLattice()
        dpath = self._prepare_parent_dirs(mach)
        if not dpath:
            QMessageBox.warning(self, "Abort", "Aborted")
            return
        dt = datetime.datetime.now()
        fname = os.path.join(
            dpath,
            dt.strftime("snapshot_%d_%H%M%S_") + lat.name + ".hdf5")
        fileName = QtGui.QFileDialog.getSaveFileName(
            self, "Save Lattice Snapshot Data", fname,
            "Data Files (*.h5 *.hdf5);;All Files(*)")
        fileName = str(fileName)
        if not fileName: return
        aphla.catools.save_lat_epics(fileName, lat, mode='a')
        self.logger.info("snapshot created '%s'" % fileName)

    def saveMachSnapshot(self):
        mach, lat = self.getCurrentMachLattice()
        dpath = self._prepare_parent_dirs(mach)
        if not dpath:
            QMessageBox.warning(self, "Abort", "Aborted")
            return
        dt = datetime.datetime.now()
        fname = os.path.join(dpath, dt.strftime("snapshot_%d_%H%M%S.hdf5"))
        fileName = QtGui.QFileDialog.getSaveFileName(
            self, "Save Lattice Snapshot Data", fname,
            "Data Files (*.h5 *.hdf5);;All Files(*)")
        if not fileName: return
        fileName = str(fileName)
        import h5py
        f = h5py.File(str(fileName), 'w')
        f.close()
        self.logger.info("clean snapshot file created: '%s'" % fileName)
        for k, lat in self._mach[mach][0].items():
            aphla.catools.save_lat_epics(fileName, lat, mode='a')
            self.logger.info("lattice snapshot appended for '%s'" % lat.name)

    def openSnapshot(self):
        #self.logger.info("loading snapshot?")
        latdict = dict([(k, v[0]) for k, v in self._mach.items()])
        mach, lat = self.getCurrentMachLattice()
        lv = LatSnapshotMain(self, latdict, mach, self.logger)
        lv.setWindowFlags(Qt.Window)
        #self.logger.info("initialized")
        #lv.loadLatSnapshotH5()
        lv.exec_()

    def openTunePlot(self):
        mach, lat = self.getCurrentMachLattice()
        nu = lat.getElementList('tune')
        pvs = [(e.pv(field="x",
                     handle="readback")[0], e.pv(field="y",
                                                 handle="readback")[0])
               for e in nu]
        labels = [e.name for e in nu]
        twiss = lat.getElementList("VA")
        pvs.extend([(e.pv(field="nux", handle="readback")[0],
                     e.pv(field="nuy", handle="readback")[0]) for e in twiss])
        labels.extend([e.name for e in twiss])

        p = ApMdiSubPlot(pvs=pvs, labels=labels, dtype="Tunes")
        #QObject.installEventFilter(p.aplot)
        #p.data = ManagedPvData(pvm, s, pvs, element=elemnames,
        #                       label="{0}.{1}".format(elem,field))
        p.setAttribute(Qt.WA_DeleteOnClose)
        p.setWindowTitle("[%s.%s] Tunes" % (mach, lat.name))
        self.connect(p, SIGNAL("elementSelected(PyQt_PyObject)"),
                     self.elementSelected)
        self.connect(p, SIGNAL("destroyed()"), self.subPlotDestroyed)
        #p.updatePlot()
        # set the zoom stack
        #p.aplot.setErrorBar(self.error_bar)
        #p.wid.autoScaleXY()
        #p.aplot.replot()
        self.mdiarea.addSubWindow(p)
        #print "Show"
        p.show()

    def openNewPlot(self):
        mach, lat = self.getCurrentMachLattice()
        fl = QtGui.QFormLayout()
        fl.addRow("Machine", QtGui.QLabel("%s" % mach))
        fl.addRow("Lattice", QtGui.QLabel("%s" % lat.name))
        elem, fld = QtGui.QLineEdit(), QtGui.QLineEdit()
        fl.addRow("Elements", elem)
        fl.addRow("Field", fld)
        dtype = QtGui.QComboBox()
        for tx in ["Array", "Waveform", "Time Series"]:
            dtype.addItem(tx)
        fl.addRow("Data Type", dtype)
        dlg = QtGui.QDialog()
        bx = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok
                                    | QtGui.QDialogButtonBox.Cancel)
        self.connect(bx, SIGNAL("accepted()"), dlg.accept)
        self.connect(bx, SIGNAL("rejected()"), dlg.reject)
        h1 = QtGui.QHBoxLayout()
        h1.addStretch()
        h1.addWidget(bx)
        v1 = QtGui.QVBoxLayout()
        v1.addLayout(fl)
        v1.addLayout(h1)
        dlg.setLayout(v1)

        if dlg.exec_():
            self.newElementPlots(str(elem.text()),
                                 str(fld.text()),
                                 machlat=(mach, lat),
                                 dtype=str(dtype.currentText()))

    def click_markfam(self, on):
        famname = self.sender().text()
        mks = []
        mach, lat = self.getCurrentMachLattice()
        # need to convert to python str
        for elem in lat.getElementList(str(famname)):
            if elem.family != famname: continue
            if elem.virtual: continue
            mks.append([elem.name, 0.5 * (elem.sb + elem.se)])

        for w in self.mdiarea.subWindowList():
            w.setMarkers(mks, on)
        #print self._machlat.keys()

    def _reset_correctors(self):
        self.logger.info("reset correctors")
        aphla.hlalib._reset_trims()

    def _reset_quadrupoles(self):
        self.logger.info("reset quadrupoles")
        aphla.hlalib._reset_quad()

    def _random_hkick(self):
        mach, lat = self.getCurrentMachLattice()
        hcors = lat.getElementList('HCOR')
        for k in range(3):
            i = np.random.randint(len(hcors))
            self.logger.info("Setting {0}/{1} HCOR".format(i, len(hcors)))
            hcors[i].x += np.random.rand() * 2e-6

    def _random_vkick(self):
        mach, lat = self.getCurrentMachLattice()
        cors = lat.getElementList('VCOR')
        for k in range(3):
            i = np.random.randint(len(cors))
            cors[i].y += np.random.rand() * 1e-6
            self.logger.info("increased kicker '{0}' by 1e-7 ({1} {2})".format(
                cors[i].name, cors[i].y, cors[i].getUnit('y', None)))

    def viewDcctPlot(self, on):
        self.dcct.setVisible(on)

    def liveData(self, on):
        """Switch on/off live data taking"""
        self.live_orbit = on

    def scalePlot(self):
        w = self.mdiarea.currentSubWindow()
        if not w: return
        st, p = self.sender().text(), w.aplot
        if st == "Fit":
            p.scaleXBottom()
            p.scaleYLeft()
            # a hack
            bound = p.curvesBound()
            p.zoomer1.setZoomStack([bound])
        elif st == "Fit In Y":
            p.scaleYLeft()
        elif st == "Zoom In Y":
            p.scaleYLeft(1. / 1.5)
        elif st == "Zoom Out Y":
            p.scaleYLeft(1.5)
        elif st == "Move Up":
            p.moveCurves(Qwt.QwtPlot.yLeft, 0.8)
        elif st == "Move Down":
            p.moveCurves(Qwt.QwtPlot.yLeft, -0.8)
        elif st == "Fit In X":
            p.scaleXBottom()
        elif st == "Zoom In X":
            p.scaleXBottom(1.0 / 1.5)
        elif st == "Zoom Out X":
            p.scaleXBottom(1.5)
        elif st == "Move Left":
            p.moveCurves(Qwt.QwtPlot.xBottom, 0.8)
        elif st == "Move Right":
            p.moveCurves(Qwt.QwtPlot.xBottom, -0.8)
        else:
            self.logger.error("unknow action '{0}'".format(st))

    def getVisibleRange(self):
        w = self.mdiarea.currentSubWindow()
        if not w:
            mach, lat = self.getCurrentMachLattice()
            self.logger.warn(
                "no active plot, use full range of {0}.{1}".format(
                    mach, lat.name))
            return lat.getLocationRange()
        else:
            return w.currentXlim()

    def getVisibleElements(self, elemname, sb=None, se=None):
        w = self.mdiarea.currentSubWindow()
        mach, lat = self.getCurrentMachLattice()
        elems = lat.getElementList(elemname)
        if sb is not None:
            elems = [e for e in elems if e.sb >= sb]
        if se is not None:
            elems = [e for e in elems if e.se <= se]

        self.logger.info("searching for '{0}' in range [{1}, {2}]".format(
            elemname, sb, se))

        return elems

    def timerEvent(self, e):
        if e.timerId() != self.timerId: return

        #if not self.elemeditor.isHidden():
        #    self.elemeditor.updateModelData()

        #if self.live_orbit:
        #    self.itimer += 1
        #    #self.updatePlots()
        #    #self.updateStatus()
        #    for w in self.mdiarea.subWindowList():
        #        if not isinstance(w, ApMdiSubPlot): continue
        #        if not w.live: continue
        #        w.updatePlot()
        #    self.statusBar().showMessage("plot updated: {0}".format(
        #        time.strftime("%F %T")))
        #else:
        #    self.statusBar().showMessage("live update disabled")

    def singleShot(self):
        for w in self.mdiarea.subWindowList():
            if not isinstance(w, ApMdiSubPlot): continue
            w.updatePlot()

        self.statusBar().showMessage("plot updated: {0}".format(
            time.strftime("%F %T")))

    def elementSelected(self, elems):
        """this action is ignored"""
        mach, lat, elemnames = elems
        #_lat = self._machlat[mach][lat]
        self.logger.info("element selected")

        #elemobjs = _lat.getElementList(elemnames)
        #self._elemed.addElements(elemobjs)

    def activeOrbitPlot(self, field):
        mach = str(self.machBox.currentText())
        lat = str(self.latBox.currentText())
        for w in self.mdiarea.subWindowList():
            #print w.machine(), w.lattice(), w.data.yfield
            if not isinstance(w, ApMdiSubPlot): continue
            if w.machine() != mach: continue
            if w.lattice() != lat: continue
            if w.data.yfield != field: continue
            return w

        return None

    def createLocalBump_(self):
        """create local bump"""
        if self._dlgOrbitCor is None:
            bpms = ap.getElements("BPM")
            cors = ap.getElements("COR")
            self._dlgOrbitCor = OrbitCorrDlg(bpms, cors)
            #corbitdlg.resize(600, 500)
            self._dlgOrbitCor.setWindowTitle("Create Local Bump")
        self._dlgOrbitCor.show()
        self._dlgOrbitCor.raise_()
        self._dlgOrbitCor.activateWindow()

    def createLocalBump(self):
        """create local bump"""
        bpms = ap.getElements("BPM")
        cors = ap.getElements("COR")
        dlgOrbitCor = OrbitCorrDlg(bpms, cors, parent=self)
        #corbitdlg.resize(600, 500)
        dlgOrbitCor.setWindowTitle("Create Local Bump")
        dlgOrbitCor.show()
        dlgOrbitCor.raise_()
        dlgOrbitCor.activateWindow()
        dlgOrbitCor.setAttribute(Qt.WA_DeleteOnClose)

    def runBba(self):
        mach, lat = self.getCurrentMachLattice()
        bpms = [
            e for e in lat.getElementList('BPM')
            if e not in self.physics.deadelems
        ]
        self.physics.runBba(bpms)

    def plotSVD(self):
        mach, lat = self.getCurrentMachLattice()
        if not lat.ormdata:
            QMessageBox.critical(self, "ORM SVD",
                                 "machine '%s' ORM data is not available" % \
                                 mach,
                                 QMessageBox.Ok)
            return
        m, brec, trec = lat.ormdata.getMatrix(None,
                                              None,
                                              full=False,
                                              ignore=self.getDeadElements())
        U, s, V = np.linalg.svd(m, full_matrices=True)
        #print np.shape(s), s
        self.sp = ApSvdPlot(s)
        self.sp.show()

    def tileSubWindowsHorizontally(self):
        pos = QtCore.QPoint(0, 0)
        subwins = self.mdiarea.subWindowList()
        for w in subwins:
            height = self.mdiarea.height() / len(subwins)
            rect = QtCore.QRect(0, 0, self.mdiarea.width(), height)
            w.setGeometry(rect)
            w.move(pos)
            pos.setY(pos.y() + w.height())
class DBMainWindow(QMainWindow):
    """Main Window and Portal
    
    .. todo:: Remember the dock position
    """

    W_NAME = "DBMainWindow"

    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)

        self.db = None

        self.setWindowTitle("PyQtDb")
        self.setWindowIcon(Ico.icon(Ico.FavIcon))

        self.setMinimumWidth(800)
        self.setMinimumHeight(800)
        """
        topBar = QToolBar()
        self.addToolBar(Qt.TopToolBarArea, topBar)
        
        topBar.addAction("New Server")
        """

        ## Servers Widget
        self.dockServers = QDockWidget("Servers")
        self.dockServers.setFeatures(QDockWidget.DockWidgetMovable)
        self.dockServers.setAllowedAreas(Qt.LeftDockWidgetArea
                                         | Qt.RightDockWidgetArea)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.dockServers)

        self.serversWidget = DBServersWidget.DBServersWidget(self)
        """Instance of :py:class:`~pyqtdb.DBServersWidget.DBServersWidget` in dock"""
        self.dockServers.setWidget(self.serversWidget)
        self.connect(self.serversWidget, SIGNAL("open_server"),
                     self.on_open_server)

        self.cenWid = QWidget()
        self.setCentralWidget(self.cenWid)

        self.mainLayout = QHBoxLayout()
        self.mainLayout.setContentsMargins(0, 0, 0, 0)
        self.mainLayout.setSpacing(0)
        self.cenWid.setLayout(self.mainLayout)

        self.tabWidget = QTabWidget()
        """The main tabs"""
        self.tabWidget.setTabsClosable(True)
        self.mainLayout.addWidget(self.tabWidget)

        G.settings.restore_window(self)

    def on_open_server(self, srv):
        """Opens server by adding a :py:class:`~pyqtdb.DBBrowser.DBBrowser` in the the tabWidget"""
        server = G.settings.get_server(str(srv))
        print "oopen", srv, server
        widget = DBBrowser.DBBrowser(self, server)
        self.tabWidget.addTab(widget, Ico.icon(Ico.Server), server['server'])
        self.tabWidget.setCurrentIndex(self.tabWidget.indexOf(widget))

    def closeEvent(self, event):
        """Save window settings on close with :py:class:`~pyqtdb.XSettings.XSettings.save_window` """
        G.settings.save_window(self)
class MainWindow(KXmlGuiWindow):

    "Class which displays the main Danbooru Client window."

    def __init__(self,  *args):

        "Initialize a new main window."

        super(MainWindow,  self).__init__(*args)
        self.cache = KPixmapCache("danbooru")
        self.preferences = preferences.Preferences()
        self.api = None
        self.__ratings = None
        self.__step = 0

        self.url_list = self.preferences.boards_list
        self.max_retrieve = self.preferences.thumbnail_no

        self.statusbar = self.statusBar()
        self.progress = QProgressBar()
        self.thumbnailarea = None
        self.tag_dock = None
        self.pool_dock = None
        self.first_fetch_widget = None

        self.progress.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)

        # FIXME: Hackish, but how to make it small otherwise?
        self.progress.setMinimumSize(100, 1)
        self.statusbar.addPermanentWidget(self.progress)
        self.progress.hide()

        self.setup_welcome_widget()
        self.setup_actions()

    def reload_config(self):

        """Reload configuration after a change"""

        urls = self.preferences.boards_list

        if self.first_fetch_widget is not None:
            self.first_fetch_widget.setup_urls(urls)

        if self.thumbnailarea is not None:

            max_thumbnail = self.preferences.thumbnail_no
            max_rating = self.preferences.max_allowed_rating

            self.thumbnailarea.fetchwidget.limit = max_thumbnail
            self.thumbnailarea.fetchwidget.rating = max_rating
            self.thumbnailarea.fetchwidget.update_values()

            self.thumbnailarea.connectwidget.setup_urls(urls)

        self.url_list = self.preferences.boards_list
        self.max_retrieve = self.preferences.thumbnail_no




    def setup_welcome_widget(self):

        """Load the welcome widget at startup."""

        widget = QWidget()
        layout = QVBoxLayout()

        welcome = QLabel(parent=self)
        pix = QPixmap(KStandardDirs.locate("appdata","logo.png"))

        welcome.setPixmap(pix)
        welcome.setAlignment(Qt.AlignCenter)

        self.first_fetch_widget = connectwidget.ConnectWidget(
        self.preferences.boards_list, self)

        self.statusbar.addPermanentWidget(self.first_fetch_widget, 300)

        self.first_fetch_widget.connectionEstablished.connect(
            self.handle_connection)
        self.first_fetch_widget.rejected.connect(
            self.first_fetch_widget.hide)

        self.first_fetch_widget.hide()

        self.first_fetch_widget.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)

        layout.addWidget(self.first_fetch_widget)
        layout.addWidget(welcome)
        widget.setLayout(layout)

        self.setCentralWidget(widget)

    def setup_tooltips(self):

        """Set tooltips for the actions."""

        self.connect_action.setToolTip(i18n("Connect to a Danbooru board"))
        self.fetch_action.setToolTip(
            i18n("Fetch thumbnails from a Danbooru board")
        )
        self.batch_download_action.setToolTip(i18n("Batch download images"))

    def create_actions(self):

        """Create actions for the main window."""

        self.connect_action = KAction(KIcon("document-open-remote"),
                                 i18n("Connect"), self)
        self.fetch_action = KAction(KIcon("download"), i18n("Download"),
                                    self)
        self.clean_action = KAction(KIcon("trash-empty"),
                               i18n("Clear thumbnail cache"),
                               self)
        self.batch_download_action = KAction(KIcon("download"),
                                             i18n("Batch download"), self)
        self.pool_toggle_action = KToggleAction(KIcon("image-x-generic"),
                                            i18n("Pools"), self)
        self.tag_display_action = KDualAction(i18n("Show tags"),
                                              i18n("Hide tags"),
                                              self)
        self.tag_display_action.setIconForStates(KIcon("image-x-generic"))
        self.tag_display_action.setEnabled(False)

        # Shortcuts
        connect_default = KAction.ShortcutTypes(KAction.DefaultShortcut)
        connect_active = KAction.ShortcutTypes(KAction.ActiveShortcut)

        self.connect_action.setShortcut(KStandardShortcut.open())
        self.fetch_action.setShortcut(KStandardShortcut.find())

        self.fetch_action.setEnabled(False)
        self.batch_download_action.setEnabled(False)
        self.pool_toggle_action.setEnabled(False)

    def setup_action_collection(self):

        """Set up the action collection by adding the actions."""

        action_collection = self.actionCollection()

        # Addition to the action collection
        action_collection.addAction("connect", self.connect_action)
        action_collection.addAction("fetch", self.fetch_action)
        action_collection.addAction("clean", self.clean_action)
        action_collection.addAction("batchDownload", self.batch_download_action)
        action_collection.addAction("poolDownload", self.pool_toggle_action)
        action_collection.addAction("tagDisplay", self.tag_display_action)

        KStandardAction.quit (self.close, action_collection)
        KStandardAction.preferences(self.show_preferences,
                                    action_collection)

        action_collection.removeAction(
            action_collection.action("help_contents"))
        action_collection.actionHovered.connect(self.setup_action_tooltip)

    def setup_actions(self):

        """Set up the relevant actions, tooltips, and load the RC file."""

        self.create_actions()
        self.setup_tooltips()
        self.setup_action_collection()

        # Connect signals
        self.connect_action.triggered.connect(self.connect)
        self.fetch_action.triggered.connect(self.get_posts)
        self.clean_action.triggered.connect(self.clean_cache)
        self.batch_download_action.triggered.connect(self.batch_download)
        self.pool_toggle_action.toggled.connect(self.pool_toggle)
        self.tag_display_action.activeChanged.connect(self.tag_display)

        window_options = self.StandardWindowOption(self.ToolBar| self.Keys |
                                                   self.Create | self.Save |
                                                   self.StatusBar)

        setupGUI_args = [
            QSize(500, 400), self.StandardWindowOption(window_options)
        ]

        #Check first in standard locations for danbooruui.rc

        rc_file = KStandardDirs.locate("appdata", "danbooruui.rc")

        if rc_file.isEmpty():
            setupGUI_args.append(os.path.join(sys.path [0],
                                              "danbooruui.rc"))
        else:
            setupGUI_args.append(rc_file)

        self.setupGUI(*setupGUI_args)

    def setup_action_tooltip(self, action):

        "Show statusbar help when actions are hovered."

        if action.isEnabled():
            self.statusBar().showMessage(action.toolTip(), 2000)

    def setup_connections(self):

        """Set up connections for post and tag retrieval."""

        if self.api is None:
            return

        self.api.postRetrieved.connect(self.update_progress)
        self.api.postDownloadFinished.connect(self.download_finished)
        self.api.tagRetrieved.connect(self.tag_dock.widget().add_tags)
        self.tag_dock.widget().itemDoubleClicked.connect(
            self.fetch_tagged_items)

    def show_preferences(self):

        "Show the preferences dialog."

        if KConfigDialog.showDialog("Preferences dialog"):
            return
        else:
            dialog = preferences.PreferencesDialog(self, "Preferences dialog",
                                                   self.preferences)
            dialog.show()
            dialog.settingsChanged.connect(self.reload_config)

    def connect(self, ok):

        "Connect to a Danbooru board."

        if self.thumbnailarea is None:
            self.first_fetch_widget.show()
        else:
            self.thumbnailarea.connectwidget.show()


    def restore(self):

        self.statusbar.removeWidget(self.connect_widget)

    def handle_connection(self, connection):

        self.api = None
        self.api = connection
        self.api.cache = self.cache

        if self.pool_dock is not None:
            self.pool_dock.hide()
            self.pool_dock.widget().clear()
            self.pool_toggle_action.setChecked(False)

        if self.thumbnailarea is not None:
            #TODO: Investigate usability
            self.clear(clear_pool=True)
            self.thumbnailarea.clear()
            self.thumbnailarea.api_data = self.api
            self.setup_connections()

        else:
            self.first_fetch_widget.connectionEstablished.disconnect()
            self.first_fetch_widget.rejected.disconnect()
            self.statusbar.removeWidget(self.first_fetch_widget)
            self.setup_area()

        self.api.cache = self.cache

        self.statusBar().showMessage(i18n("Connected to %s" % self.api.url),
                                     3000)
        self.fetch_action.setEnabled(True)

        # Set up pool widget

        pool_widget = poolwidget.DanbooruPoolWidget(self.api)
        self.pool_dock = QDockWidget("Pools", self)
        self.pool_dock.setObjectName("PoolDock")
        self.pool_dock.setAllowedAreas(Qt.BottomDockWidgetArea)
        self.pool_dock.setWidget(pool_widget)
        #self.pool_dock.setFeatures(QDockWidget.NoDockWidgetFeatures)
        self.addDockWidget(Qt.BottomDockWidgetArea, self.pool_dock)
        self.pool_dock.widget().poolDownloadRequested.connect(
            self.pool_prepare)
        self.pool_dock.hide()

        self.pool_toggle_action.setEnabled(True)
        self.clear() # Needed to show properly the stuff after connecting

        self.api.get_post_list(tags="", limit=self.thumbnailarea.post_limit,
                               rating=self.preferences.max_allowed_rating,
                               blacklist=list(self.preferences.tag_blacklist))
        self.api.get_tag_list(name="",blacklist=list(self.preferences.tag_blacklist),
                              limit=20)

    def get_posts(self, ok):

        "Get posts from the connected Danbooru board."

        if not self.api:
            return

        self.thumbnailarea.fetchwidget.show()



    def handle_fetching(self, tags, max_rating, limit):

        """Slot connected to the dataSent signal of the fetch widget.

        The widgets are set up if they don't exist, and the API is queried
        to do the actual downloading of tags and

        """

        self.clear()

        self.thumbnailarea.fetchwidget.hide()

        if self.tag_dock is not None:
            self.tag_dock.widget().clear()

        self.thumbnailarea.post_limit = limit
        blacklist= list(self.preferences.tag_blacklist)
        self.api.get_post_list(tags=tags, limit=limit,
                               rating=max_rating,
                               blacklist=blacklist)

        tags = [item for item in tags if item]

        if not tags:
            # No related tags, fetch the most recent 20
            tags = ""
            self.api.get_tag_list(name=tags,blacklist=blacklist,
                                  limit=20)
        else:
            self.api.get_related_tags(tags=tags, blacklist=blacklist)

    def fetch_tagged_items(self, item):

        """Fetch items found in the tag list widget."""

        tag_name = unicode(item.text())
        self.clear()

        blacklist = self.preferences.tag_blacklist
        limit = self.preferences.thumbnail_no
        rating = self.preferences.max_allowed_rating

        self.api.get_post_list(page=1, tags=[tag_name],
                                blacklist=blacklist,
                                limit=limit,
                                rating=rating)
        self.api.get_related_tags(tags=[tag_name], blacklist=blacklist)

    def pool_toggle(self, checked):

        "Toggle the presence/absence of the pool dock."

        if not self.api:
            return

        if not checked:
            self.pool_dock.hide()
        else:
            self.pool_dock.show()

    def pool_prepare(self, pool_id):

        """Prepare the central area for pool image loading."""

        if self.thumbnailarea is None:
            self.setup_area()
        else:
            self.clear(clear_pool=False)

        self.api.get_pool(pool_id, blacklist=self.preferences.tag_blacklist,
                          rating=self.preferences.max_allowed_rating)

    def batch_download(self, ok):

        "Download images in batch."

        selected_items = self.thumbnailarea.selected_images()

        if not selected_items:
            return

        start_url = KUrl("kfiledialog:///danbooru")
        caption = i18n("Select a directory to save the images to")
        directory = KFileDialog.getExistingDirectoryUrl(start_url, self,
                                                        caption)

        if directory.isEmpty():
            return

        for item in selected_items:

            file_url = item.url_label.url()
            tags = item.data.tags

            # Make a local copy to append paths as addPath works in-place
            destination = KUrl(directory)

            file_name = KUrl(file_url).fileName()
            destination.addPath(file_name)

            job = KIO.file_copy(KUrl(file_url), destination, -1)
            job.setProperty("tags", QVariant(tags))
            job.result.connect(self.batch_download_slot)

    def setup_area(self):

        "Set up the central widget to display thumbnails."

        self.thumbnailarea = thumbnailarea.DanbooruTabWidget(self.api,
            self.preferences, self.preferences.thumbnail_no, self)

        self.setCentralWidget(self.thumbnailarea)

        self.thumbnailarea.connectwidget.connectionEstablished.connect(
                    self.handle_connection, type=Qt.UniqueConnection)
        self.thumbnailarea.connectwidget.rejected.connect(
            self.thumbnailarea.connectwidget.hide, type=Qt.UniqueConnection)

        self.thumbnailarea.fetchwidget.dataSent.connect(
            self.handle_fetching, type=Qt.UniqueConnection)
        self.thumbnailarea.fetchwidget.rejected.connect(
            self.thumbnailarea.fetchwidget.hide, type=Qt.UniqueConnection)

        # Set up tag widget

        blacklist = self.preferences.tag_blacklist
        tag_widget = tagwidget.DanbooruTagWidget(blacklist, self)
        self.tag_display_action.setActive(True)
        self.tag_display_action.setEnabled(True)
        self.tag_dock = QDockWidget("Similar tags", self)
        self.tag_dock.setObjectName("TagDock")
        self.tag_dock.setAllowedAreas(Qt.RightDockWidgetArea)
        self.tag_dock.setWidget(tag_widget)
        #self.tag_dock.setFeatures(QDockWidget.NoDockWidgetFeatures)
        self.addDockWidget(Qt.RightDockWidgetArea, self.tag_dock)
        self.tag_dock.hide()

        # Container signal-slot connections

        self.setup_connections()

    def download_finished(self):

        """Slot called when all the data has been completed. Clears the progress
        bar and resets it to 0."""

        if not self.batch_download_action.isEnabled():
            self.batch_download_action.setEnabled(True)

        self.__step = 0
        self.progress.hide()

    def update_progress(self):

        "Update the progress bar."

        if not self.progress.isVisible():
            self.progress.show()

        self.__step += 1
        self.progress.setValue(self.__step)

    def clear(self, clear_pool=True):

        "Clear the central widget."

        if self.thumbnailarea is None:
            return

        self.thumbnailarea.clear()
        self.tag_dock.widget().clear()
        if clear_pool:
            self.pool_dock.widget().clear()
        self.batch_download_action.setEnabled(False)

    def clean_cache(self):

        "Purge the thumbnail cache."

        self.cache.discard()
        self.statusBar().showMessage(i18n("Thumbnail cache cleared."))

    def batch_download_slot(self, job):

        """Slot called when doing batch download, for each file retrieved.

        If Nepomuk tagging is enabled, each file is tagged using the item's
        respective tags.

        """

        if job.error():
            job.ui().showErrorMessage()
        else:
            if self.preferences.nepomuk_enabled:
                tags = job.property("tags").toPyObject()
                #danbooru2nepomuk.tag_danbooru_item(job.destUrl().path(),
                #                                   tags)

    def tag_display(self, state):

        """Display or hide the tag dock."""

        if self.tag_dock is None:
            self.tag_display_action.setActive(False)
            return

        if state:
            self.tag_dock.show()
        else:
            self.tag_dock.hide()
Exemple #20
0
class DBMainWindow(QMainWindow):
    """Main Window and Portal
    
    .. todo:: Remember the dock position
    """
    
    W_NAME =  "DBMainWindow"

    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)

        
        
        self.db = None
        
        self.setWindowTitle("PyQtDb")
        self.setWindowIcon(Ico.icon(Ico.FavIcon))

        self.setMinimumWidth(800)
        self.setMinimumHeight(800)
        
        """
        topBar = QToolBar()
        self.addToolBar(Qt.TopToolBarArea, topBar)
        
        topBar.addAction("New Server")
        """
        
        ## Servers Widget
        self.dockServers = QDockWidget("Servers")
        self.dockServers.setFeatures(QDockWidget.DockWidgetMovable)
        self.dockServers.setAllowedAreas(Qt.LeftDockWidgetArea|Qt.RightDockWidgetArea)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.dockServers)
        
        self.serversWidget = DBServersWidget.DBServersWidget(self)
        """Instance of :py:class:`~pyqtdb.DBServersWidget.DBServersWidget` in dock"""
        self.dockServers.setWidget(self.serversWidget)
        self.connect(self.serversWidget, SIGNAL("open_server"), self.on_open_server)

        self.cenWid = QWidget()
        self.setCentralWidget(self.cenWid)
        
        self.mainLayout = QHBoxLayout()
        self.mainLayout.setContentsMargins(0, 0, 0, 0)
        self.mainLayout.setSpacing(0)
        self.cenWid.setLayout( self.mainLayout )
        
        self.tabWidget = QTabWidget()
        """The main tabs"""
        self.tabWidget.setTabsClosable(True)
        self.mainLayout.addWidget(self.tabWidget)
        
        G.settings.restore_window(self)
        
    def on_open_server(self, srv):
        """Opens server by adding a :py:class:`~pyqtdb.DBBrowser.DBBrowser` in the the tabWidget"""
        server = G.settings.get_server( str(srv) )
        print "oopen", srv, server
        widget = DBBrowser.DBBrowser(self, server)
        self.tabWidget.addTab(widget, Ico.icon(Ico.Server), server['server'])
        self.tabWidget.setCurrentIndex(self.tabWidget.indexOf(widget))
    
    def closeEvent( self, event ):
        """Save window settings on close with :py:class:`~pyqtdb.XSettings.XSettings.save_window` """ 
        G.settings.save_window( self )
        
        
Exemple #21
0
class apeMain():
    """GUI for the main ape window"""

    def __init__(self, parent):
        self.parent = parent
        
        parent.setObjectName("ape")
        parent.setWindowTitle("ape")
        parent.setGeometry(50, 50, 800, 500)

        self.setupDocks()

        self.setupMenubar()

    def setupMenubar(self):
        self.menubar = self.parent.menuBar()

        newFileAction = QAction("&New file", self.parent)
        newFileAction.triggered.connect(self.parent.newFile)
        self.parent.newFileAction = newFileAction

        newDirectoryAction = QAction("New &directory", self.parent)
        newDirectoryAction.triggered.connect(self.parent.newDirectory)
        self.parent.newDirectoryAction = newDirectoryAction

        saveAction = QAction("&Save", self.parent)
        saveAction.triggered.connect(self.parent.saveDocument)
        saveAction.setShortcut(Qt.CTRL + Qt.Key_S)

        saveAllAction = QAction("S&ave all", self.parent)
        saveAllAction.triggered.connect(self.parent.saveAllDocuments)
        saveAllAction.setShortcut(Qt.CTRL + Qt.SHIFT + Qt.Key_S)

        exitAction = QAction(QIcon("icons/exit.png"), "E&xit", self.parent)
        exitAction.triggered.connect(self.parent.close)

        fileMenu = self.menubar.addMenu("&File")
        newMenu = fileMenu.addMenu("New")

        fileMenu.addAction(saveAction)
        fileMenu.addAction(saveAllAction)
        fileMenu.addAction(exitAction)

        newMenu.addAction(newFileAction)
        newMenu.addAction(newDirectoryAction)

        closeTabAction = QAction("Close tab", self.parent)
        closeTabAction.triggered.connect(self.parent.closeTab)
        closeTabAction.setShortcut(Qt.CTRL + Qt.Key_W)
        closeTabAction.setShortcutContext(Qt.ApplicationShortcut)

        closeOtherTabsAction = QAction("Close other tabs", self.parent)
        closeOtherTabsAction.triggered.connect(self.parent.closeOtherTabs)
        closeOtherTabsAction.setShortcut(Qt.CTRL + Qt.Key_Q)
        closeOtherTabsAction.setShortcutContext(Qt.ApplicationShortcut)

        closeAllTabsAction = QAction("Close all tabs", self.parent)
        closeAllTabsAction.triggered.connect(self.parent.closeAllTabs)
        closeAllTabsAction.setShortcut(Qt.CTRL + Qt.SHIFT + Qt.Key_W)
        closeAllTabsAction.setShortcutContext(Qt.ApplicationShortcut)

        viewMenu = self.menubar.addMenu("&View")
        tabsMenu = viewMenu.addMenu("Tabs")

        tabsMenu.addAction(closeTabAction)
        tabsMenu.addAction(closeOtherTabsAction)
        tabsMenu.addAction(closeAllTabsAction)

        viewMenu.addAction(self.filesDock.toggleViewAction())

    def setupDocks(self):
        self.filesDock = QDockWidget("Files", self.parent)
        self.filesDock.setAllowedAreas(Qt.LeftDockWidgetArea | \
                                        Qt.RightDockWidgetArea)

        self.parent.addDockWidget(Qt.LeftDockWidgetArea, self.filesDock)
Exemple #22
0
class AnnotationManager:
    def __init__(self, iface):
        locale = QSettings().value('locale/userLocale')[0:2]
        locale_path = os.path.join(os.path.dirname(__file__), 'i18n',
                                   'annotationManager_{}.qm'.format(locale))

        self.translator = None
        if os.path.exists(locale_path):
            self.translator = QTranslator()
            self.translator.load(locale_path)

            QCoreApplication.installTranslator(self.translator)

        self.iface = iface
        self.iface.projectRead.connect(self.projectOpen)

        self.dock = QDockWidget(self.tr('Annotations manager'))
        self.manager = QWidget()
        toolbar = QToolBar()

        self.annotationList = QListWidget()
        self.annotationList.itemClicked.connect(self.selectAnnotation)
        self.annotationList.itemChanged.connect(self.checkItem)
        action_refresh = QAction(
            QIcon(':/plugins/annotationManager/resources/mActionDraw.png'),
            self.tr('Refresh the annotations list'), self.manager)
        action_refresh.triggered.connect(self.refreshAnnotations)
        action_remove = QAction(
            QIcon(
                ':/plugins/annotationManager/resources/mActionRemoveAnnotation.png'
            ), self.tr('Remove the selected annotation'), self.manager)
        action_remove.triggered.connect(self.removeAnnotation)
        toolbar.addAction(action_refresh)
        toolbar.addAction(action_remove)
        toolbar.setIconSize(QSize(16, 16))

        p1_vertical = QVBoxLayout()
        p1_vertical.setContentsMargins(0, 0, 0, 0)
        p1_vertical.addWidget(toolbar)
        p1_vertical.addWidget(self.annotationList)
        self.manager.setLayout(p1_vertical)

        self.dock.setWidget(self.manager)
        self.dock.setAllowedAreas(Qt.LeftDockWidgetArea
                                  | Qt.RightDockWidgetArea)
        self.iface.addDockWidget(Qt.LeftDockWidgetArea, self.dock)

        self.rb = QgsRubberBand(self.iface.mapCanvas(), QGis.Polygon)
        self.annotations = []
        self.annotationsName = []

    def checkItem(self, item):
        row = self.annotationList.row(item)
        self.annotationsName[row] = item.text()
        if item.checkState() == Qt.Checked:
            self.annotations[row].show()
        else:
            self.annotations[row].hide()
            if item.isSelected():
                item.setSelected(False)
                self.rb.reset()

    def selectAnnotation(self):
        index = self.annotationList.currentRow()
        self.rb.reset()
        self.rb.setColor(QColor(0, 0, 255, 128))
        mapTool = QgsMapTool(self.iface.mapCanvas())
        point = self.annotations[index].pos().toPoint()
        pt1 = mapTool.toMapCoordinates(QPoint(point.x() - 10, point.y() - 10))
        pt2 = mapTool.toMapCoordinates(QPoint(point.x() + 10, point.y() + 10))
        rect = QgsRectangle(pt1, pt2)
        poly = QgsGeometry().fromRect(rect)
        self.rb.setToGeometry(poly, None)

    def unload(self):
        del self.dock

    def tr(self, message):
        return QCoreApplication.translate('AnnotationManager', message)

    def getAnnotations(self):
        annotations = []
        items = self.iface.mapCanvas().items()
        for item in items:
            if item.data(0) == 'AnnotationItem':
                annotations.append(item)
        return annotations

    def refreshAnnotations(self):
        for annotation in self.getAnnotations():
            if annotation not in self.annotations:
                self.annotations.append(annotation)
                self.annotationsName.append('Annotation')
        i = 0
        to_del = []
        for annotation in self.annotations:
            if annotation not in self.getAnnotations():
                to_del.append(i)
            i += 1
        i = 0
        for index in to_del:
            self.annotations.pop(index)
            self.annotationsName.pop(index)
        self.annotationList.clearSelection()
        self.annotationList.clear()

        # argh
        for annotation in self.annotations:
            item = QListWidgetItem(self.annotationsName[i])
            if annotation.isVisible():
                item.setCheckState(Qt.Checked)
            else:
                item.setCheckState(Qt.Unchecked)
            item.setFlags(item.flags() | Qt.ItemIsEditable)
            self.annotationList.addItem(item)
            i += 1
        # fin argh

    def removeAnnotation(self):
        if len(self.annotationList.selectedItems()) > 0:
            index = self.annotationList.currentRow()
            self.annotationList.takeItem(index)
            self.annotationList.clearSelection()
            self.annotationList.clearFocus()
            self.iface.mapCanvas().scene().removeItem(self.annotations[index])
            self.annotations.pop(index)
            self.annotationsName.pop(index)
            self.rb.reset()

    def projectOpen(self):
        del self.annotations[:]
        del self.annotationsName[:]
        self.refreshAnnotations()

    def initGui(self):
        self.refreshAnnotations()
Exemple #23
0
    slice_settings = SliceSettingsWidget(max_slice_count=nz, color_scales=color_scales.keys())
    slice_settings.inactiveCellsHidden.connect(viewer.hideInactiveCells)
    slice_settings.currentSliceChanged.connect(viewer.setCurrentSlice)
    slice_settings.toggleOrthographicProjection.connect(viewer.useOrthographicProjection)
    slice_settings.toggleLighting.connect(viewer.useLighting)
    slice_settings.colorScalesChanged.connect(viewer.changeColorScale)
    slice_settings.regionToggling.connect(viewer.useRegionScaling)
    slice_settings.toggleInterpolation.connect(viewer.useInterpolationOnData)
    slice_settings.mirrorX.connect(viewer.mirrorX)
    slice_settings.mirrorY.connect(viewer.mirrorY)
    slice_settings.mirrorZ.connect(viewer.mirrorZ)
    slice_settings.toggleFlatPolylines.connect(viewer.toggleFlatPolylines)


    dock_widget = QDockWidget("Settings")
    dock_widget.setObjectName("SliceSettingsDock")
    dock_widget.setWidget(slice_settings)
    dock_widget.setAllowedAreas(Qt.AllDockWidgetAreas)
    dock_widget.setFeatures(QDockWidget.NoDockWidgetFeatures)

    window.addDockWidget(Qt.LeftDockWidgetArea, dock_widget)


    window.setCentralWidget(viewer)

    window.show()
    window.activateWindow()
    window.raise_()
    app.exec_()
Exemple #24
0
class OrbitPlotMainWindow(QMainWindow):
    """
    the main window has three major widgets: current, orbit tabs and element
    editor.
    """
    def __init__(self, parent = None, machines=[], **kwargs):
        QMainWindow.__init__(self, parent)
        self.iqtApp = kwargs.get("iqt", None)

        self.setIconSize(QSize(32, 32))
        self.error_bar = True
        self._dlgOrbitCor = None
        # logging
        self.logdock = QDockWidget("Log")
        self.logdock.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
        textedit = QPlainTextEdit(self.logdock)
        
        self.logger = logging.getLogger(__name__)

        self.guilogger = logging.getLogger("aphla.gui")
        # the "aphla" include lib part logging. When the lib is inside
        # QThread, logging message will be sent to TextEdit which is cross
        # thread.
        # self.guilogger = logging.getLogger("aphla")
        handler = QTextEditLoggingHandler(textedit)
        self.guilogger.addHandler(handler)
        self.guilogger.setLevel(logging.INFO)
        self.logdock.setWidget(textedit)
        self.logdock.setAllowedAreas(Qt.BottomDockWidgetArea)
        self.logdock.setFeatures(QDockWidget.DockWidgetMovable|
                                 QDockWidget.DockWidgetClosable)
        self.logdock.setFloating(False)
        self.logdock.setMinimumHeight(20)
        self.logdock.setMaximumHeight(100)
        self.logdock.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
        self.logdock.resize(200, 60)
        #print self.logdock.sizeHint()
        self.addDockWidget(Qt.BottomDockWidgetArea, self.logdock)
        #print self.logdock.sizeHint()
        #print self.logdock.minimumSize()
        #print self.logdock.maximumSize()
        #self.logger.info("INFO")
        #self.logdock.setMinimumHeight(40)
        #self.logdock.setMaximumHeight(160)

        for msg in kwargs.get("infos", []):
            self.logger.info(msg)
        # dict of (machine, (lattice dict, default_lat, pvm))
        self._mach = dict([(v[0], (v[1],v[2],v[3])) for v in machines])
        for m,(lats,lat0,pvm) in self._mach.items():
            self.logger.info("machine '%s' initialized: [%s]" % (
                m, ", ".join([lat.name for k,lat in lats.items()])))
            if pvm:
                for pv in pvm.dead():
                    self.logger.warn("'{0}' is disconnected.".format(pv))
        ## DCCT current plot
        #self.dcct = DcctCurrentPlot()
        #self.dcct.setMinimumHeight(100)
        #self.dcct.setMaximumHeight(150)

        #t0 = time.time()
        #t = np.linspace(t0 - 8*3600*24, t0, 100)
        #self.dcct.curve.t = t
        #v = 500*np.exp((t[0] - t[:50])/(4*3600*24))
        #self.dcct.curve.v = v.tolist()+v.tolist()
        #self.dcct.updatePlot()

        ## MDI area
        self.mdiarea = QMdiArea()
        self.connect(self.mdiarea, SIGNAL("subWindowActivated(QMdiSubWindow)"),
                     self.updateMachineLatticeNames)
        self.mdiarea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.physics = ApOrbitPhysics(self.mdiarea, iqt=self.iqtApp)
        self.live_orbit = True

        self.setCentralWidget(self.mdiarea)

        #self._elemed = ElementPropertyTabs()
        #self.elemeditor = ElementEditorDock(parent=self)
        #self.elemeditor.setAllowedAreas(Qt.RightDockWidgetArea)
        #self.elemeditor.setFeatures(QDockWidget.DockWidgetMovable|
        #                            QDockWidget.DockWidgetClosable)
        #self.elemeditor.setFloating(False)
        #self.elemeditor.setEnabled(False)
        #self.elemeditor.setMinimumWidth(400)
        #self.elemeditor.setWidget(self._elemed)
        #self.elemeditor.show()
        #self.elemeditor.hide()
        #self.connect(self.elemeditor, 
        #             SIGNAL("elementChecked(PyQt_PyObject, bool)"),
        #             self.physics.elementChecked)
        #self.addDockWidget(Qt.RightDockWidgetArea, self.elemeditor)

        self.createMenuToolBar()
        
        # the first machine is the default
        self.machBox.addItems([v for v in self._mach.keys()])
        self.reloadLatticeNames(self.machBox.currentText())
        self.connect(self.machBox, SIGNAL("currentIndexChanged(QString)"),
                     self.reloadLatticeNames)
        
        # update at 1/2Hz
        self.dt, self.itimer = 1500, 0
        #self.timerId = None
        self.timerId = self.startTimer(self.dt)

        self.vbpm = None
        self.statusBar().showMessage("Welcome")

        #self.initMachine("nsls2v2")
        #self._newVelemPlot("V2SR", aphla.machines.HLA_VBPM, 'x', 
        #                   "H Orbit", c = None)
        #print "Thread started", self.machinit.isRunning()

        #self.newElementPlots("BPM", "x, y")
        #self.newElementPlot("BPM", "y")
        #self.newElementPlot("HCOR", "x")
        #self.newElementPlot("VCOR", "y")
        #self.newElementPlot("QUAD", "b1")
        #self.newElementPlot("SEXT", "b2")
        

    def updateMachineLatticeNames(self, wsub):
        i = self.machBox.findText(wsub.machlat[0])
        self.machBox.setCurrentIndex(i)
        self.reloadLatticeNames(wsub.machlat[0])

    def reloadLatticeNames(self, mach):
        self.latBox.clear()
        cur_mach = str(self.machBox.currentText())
        lats, lat0, pvm = self._mach.get(cur_mach, ({}, None, None))
        self.latBox.addItems([lat for lat in lats.keys()])
        if lat0:
            i = self.latBox.findText(lat0.name)
            self.latBox.setCurrentIndex(i)

    def closeEvent(self, event):
        self.physics.close()
        self.mdiarea.closeAllSubWindows()
        event.accept()

    def createMenuToolBar(self):
        #
        # file menu
        #
        #self.machMenu = self.menuBar().addMenu("&Machines")
        #self.connect(self.machMenu, SIGNAL("aboutToShow()"),
        #             self.updateMachMenu)
        self.openMenu = self.menuBar().addMenu("&Open")
        self.openMenu.addAction("New Plot ...", self.openNewPlot)
        self.openMenu.addAction("New Tune Plot", self.openTunePlot)
        self.openMenu.addAction("New BPM Plot", partial(
                self.newElementPlots, "BPM", "x,y"))
        self.openMenu.addAction("New HCOR Plot", partial(
                self.newElementPlots, "HCOR", "x"))
        self.openMenu.addAction("New VCOR Plot", partial(
                self.newElementPlots, "VCOR", "y"))

        self.openMenu.addSeparator()
        self.openMenu.addAction("Open ORM", self.loadOrm)

        self.openMenu.addSeparator()        
        self.openMenu.addAction("Save Lattice ...", self.saveSnapshot)

        fileQuitAction = QAction(QIcon(":/file_quit.png"), "&Quit", self)
        fileQuitAction.setShortcut("Ctrl+Q")
        fileQuitAction.setToolTip("Quit the application")
        fileQuitAction.setStatusTip("Quit the application")
        #fileQuitAction.setIcon(Qt.QIcon(":/filequit.png"))
        self.connect(fileQuitAction, SIGNAL("triggered()"),
                     self.close)
        self.openMenu.addAction(fileQuitAction)

        # view
        self.viewMenu = self.menuBar().addMenu("&View")

        mkmenu = QMenu("&Mark", self.viewMenu)
        for fam in ["BPM", "COR", "QUAD", "SEXT", "INSERTION"]:
            famAct = QAction(fam, self)
            famAct.setCheckable(True)
            self.connect(famAct, SIGNAL("toggled(bool)"), self.click_markfam)
            mkmenu.addAction(famAct)
        # 
        
        # errorbar
        #viewErrorBarAction = QAction(QIcon(":/view_errorbar.png"),
        #                            "Errorbar", self)
        #viewErrorBarAction.setCheckable(True)
        #viewErrorBarAction.setChecked(True)
        #self.connect(viewErrorBarAction, SIGNAL("toggled(bool)"),
        #             self.errorBar)
        #
        #zoomM = QMenu("Zoom", self.viewMenu)

        #
        #
        #drift_from_now = QAction("Drift from Now", self)
        #drift_from_now.setCheckable(True)
        #drift_from_now.setShortcut("Ctrl+N")
        #drift_from_golden = QAction("Drift from Golden", self)
        #drift_from_golden.setCheckable(True)
        #drift_from_none = QAction("None", self)
        #drift_from_none.setCheckable(True)

        #self.viewMenu.addAction(viewLiveAction)
        #self.viewMenu.addAction(viewSingleShotAction)
        #self.viewMenu.addSeparator()

        #self.viewMenu.addAction(drift_from_now)
        #self.viewMenu.addAction(drift_from_golden)
        #self.viewMenu.addAction(drift_from_none)
        #self.viewMenu.addAction(viewAutoScale)
        #self.viewMenu.addAction(viewErrorBarAction)
        #self.viewMenu.addSeparator()

        self.viewMenu.addMenu(mkmenu)

        #drift_group = QActionGroup(self)
        #drift_group.addAction(drift_from_none)
        #drift_group.addAction(drift_from_now)
        #drift_group.addAction(drift_from_golden)
        #drift_from_none.setChecked(True)

        sep = self.viewMenu.addSeparator()
        #sep.setText("Drift")
        #self.connect(drift_from_now, SIGNAL("triggered()"), self.setDriftNow)
        #self.connect(drift_from_none, SIGNAL("triggered()"), self.setDriftNone)
        #self.connect(drift_from_golden, SIGNAL("triggered()"), 
        #             self.setDriftGolden)

        #viewStyle = QMenu("Line Style", self.viewMenu)
        #for act in ["Increase Point Size", "Decrease Point Size", None,
        #            "NoCurve", "Lines", "Sticks", None,
        #            "Solid Line", "Dashed Line", "Dotted Line", None,
        #            "Increase Line Width", "Decrease Line Width", None,
        #            "NoSymbol", "Ellipse", "Rect", "Diamond", "Triangle",
        #            "Cross", "XCross", "HLine", "VLine",
        #            "Star1", "Star2", "Hexagon", None,
        #            "Red", "Blue", "Green"]:
        #    if act is None:
        #        viewStyle.addSeparator()
        #    else:
        #        viewStyle.addAction(act, self.setPlotStyle)
        #self.viewMenu.addMenu(viewStyle)

        #self.viewMenu.addSeparator()
        #self.viewMenu.addAction(viewZoomOut15Action)
        #self.viewMenu.addAction(viewZoomIn15Action)
        #self.viewMenu.addAction(viewZoomAutoAction)
        #self.viewMenu.addSeparator()
        self.viewMenu.addAction("ORM SV", self.plotSVD)
        # a bug in PyQwt5 for datetime x-axis, waiting for Debian 7
        #self.viewMenu.addAction(viewDcct)
        #for ac in self.viewMenu.actions(): ac.setDisabled(True)

        #
        self.controlMenu = self.menuBar().addMenu("&Tools")
        
        self.controlMenu.addAction(
            QIcon(":/control_choosebpm.png"), "En-/Disable BPM",
            partial(chooseElement, 'BPM'))
        self.controlMenu.addAction(
            "En-/Disable COR", partial(chooseElement, 'COR'))
        #self.controlMenu.addAction(controlResetPvDataAction)
        self.controlMenu.addSeparator()
        self.controlMenu.addAction("Lattice Snapshot ...", self.openSnapshot)
        #self.controlMenu.addAction(controlZoomInPlot1Action)
        #self.controlMenu.addAction(controlZoomOutPlot1Action)
        #self.controlMenu.addAction(controlZoomInPlot2Action)
        #self.controlMenu.addAction(controlZoomOutPlot2Action)
        self.controlMenu.addSeparator()
        self.controlMenu.addAction("Correct Hor. orbit",
            partial(aphla.correctOrbit, plane="H"))
        self.controlMenu.addAction("Correct Vert. orbit",
            partial(aphla.correctOrbit, plane="V"))
        self.controlMenu.addAction(
            QIcon(":/control_corrorbit.png"), "Correct orbit",
            partial(aphla.correctOrbit, plane="HV"))
        #steer_orbit.setDisabled(True)
        self.controlMenu.addAction("Local Bump ...", self.createLocalBump)
        self.controlMenu.addAction("Element Editor ...", self.showElementEditor)
        self.controlMenu.addSeparator()
        self.controlMenu.addAction("meas Beta", self.physics.measBeta)
        self.controlMenu.addAction("meas Dispersion", self.physics.measDispersion)
        self.controlMenu.addAction("beam based alignment", self.runBba)
        #for ac in self.controlMenu.actions(): ac.setDisabled(True)

        # Window
        self.windowMenu = self.menuBar().addMenu("&Windows")
        #self.windowMenu.addAction(self.elemeditor.toggleViewAction())
        self.windowMenu.addAction(self.logdock.toggleViewAction())
        #viewDcct = QAction("Beam Current", self)
        #viewDcct.setCheckable(True)
        #viewDcct.setChecked(True)
        #self.connect(viewDcct, SIGNAL("toggled(bool)"), self.dcct.setVisible)
        #self.windowMenu.addAction(viewDcct)
        self.windowMenu.addSeparator()
        self.windowMenu.addAction("Cascade", self.mdiarea.cascadeSubWindows)
        self.windowMenu.addAction("Tile", self.mdiarea.tileSubWindows)
        self.windowMenu.addAction("Tile Horizontally",
                                  self.tileSubWindowsHorizontally)
        # "ctrl+page up", "ctrl+page down"
        self.windowMenu.addAction("Previous", self.mdiarea.activatePreviousSubWindow, "Ctrl+Left")
        self.windowMenu.addAction("Next", self.mdiarea.activateNextSubWindow, "Ctrl+Right")
        self.windowMenu.addSeparator()

        # debug
        self.debugMenu = self.menuBar().addMenu("&Debug")
        self.debugMenu.addAction("_Reset Correctors_", self._reset_correctors)
        self.debugMenu.addAction("_Reset Quadrupoles_", self._reset_quadrupoles)
        self.debugMenu.addAction("_Random V Kick_", self._random_vkick)
        self.debugMenu.addAction("_Random H Kick_", self._random_hkick)
        #for ac in self.debugMenu.actions(): ac.setDisabled(True)

        # help
        self.helpMenu = self.menuBar().addMenu("&Help")
        self.helpMenu.addAction("About mleap", self.showAbout)
                                                                         
        #toolbar
        machToolBar = self.addToolBar("Machines")
        self.machBox = QtGui.QComboBox()
        self.latBox = QtGui.QComboBox()
        #self.connect(self.latBox, SIGNAL("currentIndexChanged(QString)"), 
        #             self.__setLattice)
        machToolBar.addWidget(self.machBox)
        machToolBar.addWidget(self.latBox)
        #toolbar = QToolBar(self)
        #self.addToolBar(toolbar)
        #fileToolBar = self.addToolBar("File")
        #fileToolBar.setObjectName("FileToolBar")
        #fileToolBar.addAction(fileQuitAction)

        #
        viewToolBar1 = self.addToolBar("Live View")
        #viewToolBar.setObjectName("ViewToolBar")
        #viewToolBar.addAction(viewZoomOut15Action)
        #viewToolBar.addAction(viewZoomIn15Action)
        #viewToolBar.addAction(viewZoomAutoAction)
        #viewToolBar1.addAction(viewLiveAction)
        #viewToolBar1.addAction(viewSingleShotAction)
        #viewToolBar1.addSeparator()
        viewToolBar1.addAction(
            QIcon(":/new_bpm.png"), "Orbits",
            partial(self.newElementPlots, "BPM", "x,y"))
        viewToolBar1.addAction(
            QIcon(":/new_cor.png"), "Correctors",
            partial(self.newElementPlots, "COR", "x,y"))
        viewToolBar1.addAction(
            QIcon(":/new_quad.png"), "Quadrupoles",
            partial(self.newElementPlots, "QUAD", "b1"))
        viewToolBar1.addAction(
            QIcon(":/new_sext.png"), "Sextupoles",
            partial(self.newElementPlots, "SEXT", "b2"))
        #viewToolBar.addAction(viewErrorBarAction)
        #viewToolBar.addAction(QWhatsThis.createAction(self))

        #viewToolBar2 = self.addToolBar("Scale Plot")
        #zoomActions = [(":/view_zoom_xy.png", "Fit", self.scalePlot),
        #               (None, None, None),
        #               (":/view_zoom_y.png", "Fit In Y", self.scalePlot),
        #               (":/view_zoomin_y.png", "Zoom In Y", self.scalePlot),
        #               (":/view_zoomout_y.png", "Zoom Out Y", self.scalePlot),
        #               (":/view_move_up.png", "Move Up", self.scalePlot),
        #               (":/view_move_down.png", "Move Down", self.scalePlot),
        #               (None, None, None),
        #               (":/view_zoom_x.png", "Fit In X", self.scalePlot),
        #               (":/view_zoomin_x.png", "Zoom In X", self.scalePlot),
        #               (":/view_zoomout_x.png", "Zoom Out X", self.scalePlot),
        #               (":/view_move_left.png", "Move Left", self.scalePlot),
        #               (":/view_move_right.png", "Move Right", self.scalePlot),
        #               ]
        #for ico,name,hdl in zoomActions:
        #    if hdl is None: continue
        #    viewToolBar2.addAction(QIcon(ico), name, hdl)

        controlToolBar = self.addToolBar("Control")
        controlToolBar.addAction(
            QIcon(":/control_orbitcor.png"), "Correct Orbit",
            aphla.correctOrbit)
        controlToolBar.addAction(
            QIcon(":/control_localbump.png"), "Local Bump ...",
            self.createLocalBump)
        #controlToolBar.addAction(controlResetPvDataAction)

    def showAbout(self):
        QMessageBox.about(
            self, self.tr("mleap"),
            (self.tr("""<b>Machine/Lattice Editor And Plotter</b> v %1
                <p>Copyright &copy; Lingyun Yang, BNL, 2013-2014. 
                All rights reserved.
                <p>This application can be used to perform
                high level accelerator controls.
                <p>Python %2 - Qt %3 - PyQt %4 
                on %5""").arg(aphla.version.version)
                .arg(platform.python_version()).arg(QtCore.QT_VERSION_STR)
                .arg(QtCore.PYQT_VERSION_STR).arg(platform.system())))

    def showElementEditor(self):
        mach, lat = self.getCurrentMachLattice()
        ed = ElementEditor(lat, parent=self)
        ed.setWindowFlags(Qt.Window)
        ed.setAttribute(Qt.WA_DeleteOnClose)
        ed.show()

    def getCurrentMachLattice(self, cadata = False):
        """return the current machine name and lattice object"""
        mach     = str(self.machBox.currentText())
        latname  = str(self.latBox.currentText())
        lat_dict, lat0, pvm = self._mach[mach]
        if not cadata:
            return mach, lat_dict[latname]
        else:
            return mach, lat_dict[latname], pvm

    def newElementPlots(self, elem, fields, **kw):
        self.logger.info("new plots: %s %s" % (elem, fields))
        _mach, _lat, _pvm = self.getCurrentMachLattice(cadata=True)
        mach, lat = kw.get("machlat", (_mach, _lat))
        handle = kw.get("handle", "readback")
        elems = lat.getElementList(elem)
        x, pvs = [], []
        field_list = re.findall(r'[^ ,]+', fields)
        for fld in field_list:
            si, pvsi = [], []
            for e in elems:
                if not e.isEnabled(): continue
                epv = e.pv(field=fld, handle=handle)
                if not epv: continue
                pvsi.append(epv[0])
                si.append(e.sb)
            x.append(si)
            pvs.append(pvsi)

        if not pvs:
            self.logger.error("no data found for elements '{0}' "
                              "and field '{1}'".format(elem, field))
            return

        p = ApMdiSubPlot(pvs=pvs, x = x, 
                         labels=["%s.%s" % (elem,fld) for fld in field_list],
                         magprof = lat.getBeamlineProfile(),
                         iqt = self.iqtApp,
                         **kw)
        #QObject.installEventFilter(p.aplot)
        #p.data = ManagedPvData(pvm, s, pvs, element=elemnames,
        #                       label="{0}.{1}".format(elem,field))
        p.setAttribute(Qt.WA_DeleteOnClose)
        str_elem = "{0}".format(elem)
        if len(str_elem) > 12: str_elem = str_elem[:9] + "..."
        str_field = "{0}".format(fields)
        if len(str_field) > 12: str_field = str_field[:9] + "..."
        p.setWindowTitle("[%s.%s] %s %s" % (
                mach, lat.name, str_elem, str_field))
        self.connect(p, SIGNAL("elementSelected(PyQt_PyObject)"), 
                     self.elementSelected)
        self.connect(p, SIGNAL("destroyed()"), self.subPlotDestroyed)
        #p.updatePlot()
        # set the zoom stack
        #p.aplot.setErrorBar(self.error_bar)
        #p.wid.autoScaleXY()
        #p.aplot.replot()
        self.mdiarea.addSubWindow(p)
        #print "Show"
        p.show()

        ##print "Enable the buttons"
        #if len(self.mdiarea.subWindowList()) > 0:
        #    self.elemeditor.setEnabled(True)

    def subPlotDestroyed(self):
        #if len(self.mdiarea.subWindowList()) == 0:
        #    self.elemeditor.setEnabled(False)
        pass

    def loadOrm(self):
        fileName = QtGui.QFileDialog.getOpenFileName(
            self, "Open Orbit Response Matrix",
            "",
            "ORM Files (*.h5 *.hdf5);;Text File (*.txt);;All Files(*)")
        fileName = str(fileName)
        try:
            m = np.loadtxt(fileName)
        except:
            QMessageBox.critical(self, "Abort", "Invalid matrix data")
            return
        mach, lat = self.getCurrentMachLattice()
        # assuming we already have the PV, name, field but just want to
        # replace the matrix elements.
        assert np.shape(m) == np.shape(lat.ormdata.m)
        nx, ny = np.shape(lat.ormdata.m)
        for i in range(nx):
            for j in range(ny):
                lat.ormdata.m[i,j] = m[i,j]


    def saveSnapshot(self):
        latdict = dict([(k,v[0]) for k,v in self._mach.items()])
        mach, lat = self.getCurrentMachLattice()
        snapdlg = SaveSnapshotDialog(latdict, mach)
        snapdlg.exec_()

    def saveLatSnapshot(self):
        mach, lat = self.getCurrentMachLattice()
        dpath = self._prepare_parent_dirs(mach)
        if not dpath:
            QMessageBox.warning(self, "Abort", "Aborted")
            return
        dt = datetime.datetime.now()
        fname = os.path.join(dpath,
            dt.strftime("snapshot_%d_%H%M%S_") + lat.name + ".hdf5")
        fileName = QtGui.QFileDialog.getSaveFileName(
            self, "Save Lattice Snapshot Data",
            fname,
            "Data Files (*.h5 *.hdf5);;All Files(*)")
        fileName = str(fileName)
        if not fileName: return
        aphla.catools.save_lat_epics(fileName, lat, mode='a')
        self.logger.info("snapshot created '%s'" % fileName)

    def saveMachSnapshot(self):
        mach, lat = self.getCurrentMachLattice()
        dpath = self._prepare_parent_dirs(mach)
        if not dpath:
            QMessageBox.warning(self, "Abort", "Aborted")
            return
        dt = datetime.datetime.now()
        fname = os.path.join(dpath, dt.strftime("snapshot_%d_%H%M%S.hdf5"))
        fileName = QtGui.QFileDialog.getSaveFileName(
            self, "Save Lattice Snapshot Data",
            fname,
            "Data Files (*.h5 *.hdf5);;All Files(*)")
        if not fileName: return
        fileName = str(fileName)
        import h5py
        f = h5py.File(str(fileName), 'w')
        f.close()
        self.logger.info("clean snapshot file created: '%s'" % fileName)
        for k,lat in self._mach[mach][0].items():
            aphla.catools.save_lat_epics(fileName, lat, mode='a')
            self.logger.info("lattice snapshot appended for '%s'" % lat.name)

    def openSnapshot(self):
        #self.logger.info("loading snapshot?")
        latdict = dict([(k,v[0]) for k,v in self._mach.items()])
        mach, lat = self.getCurrentMachLattice()
        lv = LatSnapshotMain(self, latdict, mach, self.logger)
        lv.setWindowFlags(Qt.Window)
        #self.logger.info("initialized")
        #lv.loadLatSnapshotH5()
        lv.exec_()

    def openTunePlot(self):
        mach, lat = self.getCurrentMachLattice()
        nu = lat.getElementList('tune')
        pvs = [(e.pv(field="x", handle="readback")[0],
                e.pv(field="y", handle="readback")[0])
               for e in nu]
        labels = [e.name for e in nu]
        twiss = lat.getElementList("VA")
        pvs.extend([(e.pv(field="nux", handle="readback")[0],
                     e.pv(field="nuy", handle="readback")[0])
                    for e in twiss])
        labels.extend([e.name for e in twiss])

        p = ApMdiSubPlot(pvs=pvs, labels=labels, dtype = "Tunes")
        #QObject.installEventFilter(p.aplot)
        #p.data = ManagedPvData(pvm, s, pvs, element=elemnames,
        #                       label="{0}.{1}".format(elem,field))
        p.setAttribute(Qt.WA_DeleteOnClose)
        p.setWindowTitle("[%s.%s] Tunes" % (mach, lat.name))
        self.connect(p, SIGNAL("elementSelected(PyQt_PyObject)"), 
                     self.elementSelected)
        self.connect(p, SIGNAL("destroyed()"), self.subPlotDestroyed)
        #p.updatePlot()
        # set the zoom stack
        #p.aplot.setErrorBar(self.error_bar)
        #p.wid.autoScaleXY()
        #p.aplot.replot()
        self.mdiarea.addSubWindow(p)
        #print "Show"
        p.show()

    def openNewPlot(self):
        mach, lat = self.getCurrentMachLattice()
        fl = QtGui.QFormLayout()
        fl.addRow("Machine", QtGui.QLabel("%s" % mach))
        fl.addRow("Lattice", QtGui.QLabel("%s" % lat.name))
        elem, fld = QtGui.QLineEdit(), QtGui.QLineEdit()
        fl.addRow("Elements", elem)
        fl.addRow("Field", fld)
        dtype = QtGui.QComboBox()
        for tx in ["Array", "Waveform", "Time Series"]:
            dtype.addItem(tx)
        fl.addRow("Data Type", dtype)
        dlg = QtGui.QDialog()
        bx = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok |
                                    QtGui.QDialogButtonBox.Cancel)
        self.connect(bx, SIGNAL("accepted()"), dlg.accept)
        self.connect(bx, SIGNAL("rejected()"), dlg.reject)
        h1 = QtGui.QHBoxLayout()
        h1.addStretch()
        h1.addWidget(bx)
        v1 = QtGui.QVBoxLayout()
        v1.addLayout(fl)
        v1.addLayout(h1)
        dlg.setLayout(v1)

        if dlg.exec_():
            self.newElementPlots(str(elem.text()), str(fld.text()),
                                 machlat=(mach, lat),
                                 dtype = str(dtype.currentText()))

    def click_markfam(self, on):
        famname = self.sender().text()
        mks = []
        mach, lat = self.getCurrentMachLattice()
        # need to convert to python str
        for elem in lat.getElementList(str(famname)):
            if elem.family != famname: continue
            if elem.virtual: continue
            mks.append([elem.name, 0.5*(elem.sb+elem.se)])

        for w in self.mdiarea.subWindowList(): w.setMarkers(mks, on)
        #print self._machlat.keys()

    def _reset_correctors(self):
        self.logger.info("reset correctors")
        aphla.hlalib._reset_trims()

    def _reset_quadrupoles(self):
        self.logger.info("reset quadrupoles")
        aphla.hlalib._reset_quad()

    def _random_hkick(self):
        mach, lat = self.getCurrentMachLattice()
        hcors = lat.getElementList('HCOR')
        for k in range(3):
            i = np.random.randint(len(hcors))
            self.logger.info("Setting {0}/{1} HCOR".format(i, len(hcors)))
            hcors[i].x += np.random.rand() * 2e-6


    def _random_vkick(self):
        mach, lat = self.getCurrentMachLattice()
        cors = lat.getElementList('VCOR')
        for k in range(3):
            i = np.random.randint(len(cors))
            cors[i].y += np.random.rand() * 1e-6
            self.logger.info("increased kicker '{0}' by 1e-7 ({1} {2})".format(
                cors[i].name, cors[i].y, cors[i].getUnit('y', None)))

    def viewDcctPlot(self, on):
        self.dcct.setVisible(on)

    def liveData(self, on):
        """Switch on/off live data taking"""
        self.live_orbit = on

    def scalePlot(self):
        w = self.mdiarea.currentSubWindow()
        if not w: return
        st, p = self.sender().text(), w.aplot
        if st == "Fit":
            p.scaleXBottom()
            p.scaleYLeft()
            # a hack
            bound = p.curvesBound()
            p.zoomer1.setZoomStack([bound])
        elif st == "Fit In Y":
            p.scaleYLeft()
        elif st == "Zoom In Y":
            p.scaleYLeft(1./1.5)
        elif st == "Zoom Out Y":
            p.scaleYLeft(1.5)
        elif st == "Move Up":
            p.moveCurves(Qwt.QwtPlot.yLeft, 0.8)
        elif st == "Move Down":
            p.moveCurves(Qwt.QwtPlot.yLeft, -0.8)
        elif st == "Fit In X":
            p.scaleXBottom()
        elif st == "Zoom In X":
            p.scaleXBottom(1.0/1.5)
        elif st == "Zoom Out X":
            p.scaleXBottom(1.5)            
        elif st == "Move Left":
            p.moveCurves(Qwt.QwtPlot.xBottom, 0.8)
        elif st == "Move Right":
            p.moveCurves(Qwt.QwtPlot.xBottom, -0.8)
        else:
            self.logger.error("unknow action '{0}'".format(st))

    def getVisibleRange(self):
        w = self.mdiarea.currentSubWindow()
        if not w: 
            mach, lat = self.getCurrentMachLattice()
            self.logger.warn("no active plot, use full range of {0}.{1}".format(
                mach, lat.name))
            return lat.getLocationRange()
        else:
            return w.currentXlim()
        
    def getVisibleElements(self, elemname, sb = None, se = None):
        w = self.mdiarea.currentSubWindow()
        mach, lat = self.getCurrentMachLattice()
        elems = lat.getElementList(elemname)
        if sb is not None: 
            elems = [e for e in elems if e.sb >= sb]
        if se is not None:
            elems = [e for e in elems if e.se <= se]

        self.logger.info("searching for '{0}' in range [{1}, {2}]".format(
            elemname, sb, se))

        return elems

    def timerEvent(self, e):
        if e.timerId() != self.timerId: return

        #if not self.elemeditor.isHidden():
        #    self.elemeditor.updateModelData()

        #if self.live_orbit:
        #    self.itimer += 1
        #    #self.updatePlots()
        #    #self.updateStatus()
        #    for w in self.mdiarea.subWindowList():
        #        if not isinstance(w, ApMdiSubPlot): continue
        #        if not w.live: continue
        #        w.updatePlot()
        #    self.statusBar().showMessage("plot updated: {0}".format(
        #        time.strftime("%F %T")))
        #else:
        #    self.statusBar().showMessage("live update disabled")
            
            
    def singleShot(self):
        for w in self.mdiarea.subWindowList():
            if not isinstance(w, ApMdiSubPlot):  continue
            w.updatePlot()

        self.statusBar().showMessage("plot updated: {0}".format(
            time.strftime("%F %T")))


    def elementSelected(self, elems):
        """this action is ignored"""
        mach, lat, elemnames = elems
        #_lat = self._machlat[mach][lat]
        self.logger.info("element selected")

        #elemobjs = _lat.getElementList(elemnames)
        #self._elemed.addElements(elemobjs)

    def activeOrbitPlot(self, field):
        mach = str(self.machBox.currentText())
        lat = str(self.latBox.currentText())
        for w in self.mdiarea.subWindowList():
            #print w.machine(), w.lattice(), w.data.yfield
            if not isinstance(w, ApMdiSubPlot):  continue
            if w.machine() != mach: continue
            if w.lattice() != lat: continue
            if w.data.yfield != field: continue
            return w

        return None

    def createLocalBump_(self):
        """create local bump"""
        if self._dlgOrbitCor is None:
            bpms = ap.getElements("BPM")
            cors = ap.getElements("COR")
            self._dlgOrbitCor = OrbitCorrDlg(bpms, cors)
            #corbitdlg.resize(600, 500)
            self._dlgOrbitCor.setWindowTitle("Create Local Bump")
        self._dlgOrbitCor.show()
        self._dlgOrbitCor.raise_()
        self._dlgOrbitCor.activateWindow()

    def createLocalBump(self):
        """create local bump"""
        bpms = ap.getElements("BPM")
        cors = ap.getElements("COR")
        dlgOrbitCor = OrbitCorrDlg(bpms, cors, parent=self)
        #corbitdlg.resize(600, 500)
        dlgOrbitCor.setWindowTitle("Create Local Bump")
        dlgOrbitCor.show()
        dlgOrbitCor.raise_()
        dlgOrbitCor.activateWindow()
        dlgOrbitCor.setAttribute(Qt.WA_DeleteOnClose)

    def runBba(self):
        mach, lat = self.getCurrentMachLattice()
        bpms = [e for e in lat.getElementList('BPM') 
                if e not in self.physics.deadelems]
        self.physics.runBba(bpms)

    def plotSVD(self):
        mach, lat = self.getCurrentMachLattice()
        if not lat.ormdata:
            QMessageBox.critical(self, "ORM SVD", 
                                 "machine '%s' ORM data is not available" % \
                                 mach,
                                 QMessageBox.Ok)
            return
        m, brec, trec = lat.ormdata.getMatrix(None, None, full=False, 
                                              ignore=self.getDeadElements())
        U, s, V = np.linalg.svd(m, full_matrices=True)
        #print np.shape(s), s
        self.sp = ApSvdPlot(s)
        self.sp.show()


    def tileSubWindowsHorizontally(self):
        pos = QtCore.QPoint(0, 0)
        subwins = self.mdiarea.subWindowList()
        for w in subwins:
            height = self.mdiarea.height()/len(subwins)
            rect = QtCore.QRect(0, 0, self.mdiarea.width(), height)
            w.setGeometry(rect)
            w.move(pos)
            pos.setY(pos.y() + w.height())
Exemple #25
0
class MpMainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        # one MpCodeEdit for each view in the tabwidget
        self.views = {}

        # the core widget is a tabpane
        self.tabPane = QTabWidget()
        self.tabPane.setDocumentMode(True)
        self.tabPane.setMovable(True)
        self.tabPane.setTabsClosable(True)
        self.tabPane.tabCloseRequested.connect(self.onTabCloseRequested)
        self.setCentralWidget(self.tabPane)

        self.actionQuit = QAction(QIcon.fromTheme("application-exit"), "&Quit", self)
        self.actionQuit.triggered.connect(self.onQuitTriggered)

        self.fileMenu = self.menuBar().addMenu("&File")
        self.fileMenu.addAction(self.actionQuit)
        # self.fileMenu.addAction(openAct)
        # self.fileMenu.addAction(saveAct)

        """
		self.projectsList = MpProjectListWidget(self)
		self.dockProjectList = QDockWidget("Project List", self)
		self.dockProjectList.setObjectName('dockProjectList')
		self.dockProjectList.setAllowedAreas(QtCore.Qt.LeftDockWidgetArea | QtCore.Qt.RightDockWidgetArea)
		self.dockProjectList.setWidget(self.projectsList)
		self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.dockProjectList)
		"""

        self.projectBrowser = MpProjectTreeWidget(self)
        self.dockProjectTree = QDockWidget("Project Browser", self)
        self.dockProjectTree.setObjectName("dockProjectTree")
        self.dockProjectTree.setAllowedAreas(QtCore.Qt.LeftDockWidgetArea | QtCore.Qt.RightDockWidgetArea)
        self.dockProjectTree.setWidget(self.projectBrowser)
        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.dockProjectTree)

        self.symInfo = MpSymbolInfoWidget(self)
        self.dockSymInfo = QDockWidget("Symbol Info", self)
        self.dockSymInfo.setObjectName("dockSymbolInfo")
        self.dockSymInfo.setAllowedAreas(QtCore.Qt.LeftDockWidgetArea | QtCore.Qt.RightDockWidgetArea)
        self.dockSymInfo.setWidget(self.symInfo)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.dockSymInfo)

    def closeEvent(self, *args):
        QCoreApplication.instance().onQuitTriggered()

    def onQuitTriggered(self):
        QCoreApplication.instance().onQuitTriggered()

    def onTabCloseRequested(self, index: int):
        view = self.tabPane.widget(index)
        self.tabPane.removeTab(index)
        del self.views[view.edit.document().filename]
        QCoreApplication.instance().view_closed(view.edit.document().filename)

    def show_document(self, doc: MpCodeDocument):
        # show and return the existing view
        if doc.filename in self.views:
            self.tabPane.setCurrentWidget(self.views[doc.filename])
            return self.views[doc.filename]

            # create a new view and tab for the view
        self.views[doc.filename] = MpCodeView(doc, None)
        self.tabPane.addTab(self.views[doc.filename], QIcon.fromTheme("text-x-generic"), os.path.basename(doc.filename))
        self.tabPane.setCurrentIndex(self.tabPane.count() - 1)

        return self.views[doc.filename]

    def show_symbol(self, doc: MpCodeDocument, node: Name):
        view = self.show_document(doc)
        view.edit.show_symbol(node)

        self.projectBrowser.show_symbol(node)
        self.symInfo.show_symbol(node)
Exemple #26
0
    slice_settings.inactiveCellsHidden.connect(viewer.hideInactiveCells)
    slice_settings.currentSliceChanged.connect(viewer.setCurrentSlice)

    slice_settings.toggleOrthographicProjection.connect(viewer.useOrthographicProjection)

    slice_settings.toggleLighting.connect(viewer.useLighting)
    slice_settings.colorScalesChanged.connect(viewer.changeColorScale)
    slice_settings.regionToggling.connect(viewer.useRegionScaling)
    slice_settings.toggleInterpolation.connect(viewer.useInterpolationOnData)
    slice_settings.mirrorX.connect(viewer.mirrorX)
    slice_settings.mirrorY.connect(viewer.mirrorY)
    slice_settings.mirrorZ.connect(viewer.mirrorZ)
    slice_settings.toggleFlatPolylines.connect(viewer.toggleFlatPolylines)


    dock_widget = QDockWidget("Settings")
    dock_widget.setObjectName("SliceSettingsDock")
    dock_widget.setWidget(slice_settings)
    dock_widget.setAllowedAreas(Qt.AllDockWidgetAreas)
    dock_widget.setFeatures(QDockWidget.NoDockWidgetFeatures)

    window.addDockWidget(Qt.LeftDockWidgetArea, dock_widget)


    window.setCentralWidget(viewer)

    window.show()
    window.activateWindow()
    window.raise_()
    app.exec_()
Exemple #27
0
class MainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        # super(MainWindow, self).__init__(parent)
        QtGui.QMainWindow.__init__(self, parent)

        self.filename = ""
        self.read_method_build_in = False  # 若为False, 用系统自带的EPub阅读器打开
        self.library = get_library()

        self.book_view = BookView()
        # ###########actions############################
        self.addBookAction = self.create_action(u"添加EPub格式的电子书", self.add_book,
                                                QKeySequence.Open,
                                                QtGui.QIcon(":/open.png"),
                                                u"从文件系统中添加")
        # TODO: 切图标
        self.removeAction = self.create_action(u"移除Epub格式的电子书",
                                               self.remove_book, None,
                                               QtGui.QIcon(":/remove.png"),
                                               u"移除EPub格式电子书")
        # TODO: 切图标
        self.downloadAction = self.create_action(u"制作EPub格式电子书",
                                                 self.make_book, None,
                                                 QtGui.QIcon(":/download.png"),
                                                 u"制作EPub格式电子书")
        # TODO: 阅读电子书的图标
        self.readAction = self.create_action(
            u"阅读电子书",
            self.view_book,
            None,  # TODO
            QtGui.QIcon(":/read.png"),
            u"阅读电子书")
        self.toolbarAction = self.create_action(
            u"切换工具栏",
            self.toggle_toolbar,
            None,
            None,
            None,
        )
        self.statusbarAction = self.create_action(u"切换状态栏",
                                                  self.toggle_statusbar, None,
                                                  None, None)
        self.bookDetailAction = self.create_action(u"打开书籍详情窗口",
                                                   self.create_book_info_dock,
                                                   None, None, None)
        self.aboutHelpAction = self.create_action(
            u"帮助",
            self.about_help,
            None,
            None,
            None,
        )
        self.setViewerAction = self.create_action(u"设置EPub阅读器",
                                                  self.set_viewer, None, None,
                                                  u"设置默认的电子书阅读器")
        self.open_with_build_in_action = self.create_action(
            u"用软件自带EPub阅读器打开", self.view_book_with_build_in, None, None, None)

        self.open_with_os_action = self.create_action(u"用系统默认EPub阅读器打开",
                                                      self.view_book_with_os,
                                                      None, None, None)

        # ContextMenu
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.showContextMenu)

        self.contextMenu = QMenu(self)
        self.add_actions(
            self.contextMenu,
            (self.open_with_build_in_action, self.open_with_os_action))

        # ###########toolbar############################
        self.toolbar = self.addToolBar("&Options")
        self.toolbar.setObjectName('Options')
        self.add_actions(self.toolbar, (self.addBookAction, self.removeAction,
                                        self.readAction, self.downloadAction))
        self.addToolBarBreak()
        self.toolbar.setVisible(True)
        # ###########menubar############################
        self.menu_bar = self.menuBar()
        self.editBook = self.menu_bar.addMenu("&Books")
        self.add_actions(
            self.editBook,
            (self.addBookAction, self.removeAction, self.downloadAction))

        self.viewMenu = self.menu_bar.addMenu("&View")
        self.add_actions(
            self.viewMenu,
            (self.toolbarAction, self.statusbarAction, self.bookDetailAction))

        self.settingMenu = self.menu_bar.addMenu("&Setting")
        self.add_actions(self.settingMenu, (self.setViewerAction, ))

        self.helpMenu = self.menu_bar.addMenu("&Help")
        self.add_actions(self.helpMenu, (self.aboutHelpAction, ))

        # Initialize a statusbar for the window
        status = self.statusBar()
        status.setSizeGripEnabled(False)

        self.setGeometry(100, 100, 1030, 800)

        self.centralWidget = QtGui.QWidget(self)

        self.search_label = QtGui.QLabel(self.centralWidget)
        self.search_label.setText(u'搜索:')
        self.searchLineEdit = QtGui.QLineEdit(self.centralWidget)
        self.library_table = LibraryTableWidget(self.book_view)
        self.library_table.setVisible(True)

        self.gridLayout = QtGui.QGridLayout(self.centralWidget)
        self.gridLayout.addWidget(self.search_label, 0, 0, 1, 1)
        self.gridLayout.addWidget(self.searchLineEdit, 0, 1, 1, 15)
        self.gridLayout.addWidget(self.library_table, 1, 0, 1, 16)
        # self.scrollArea = QScrollArea()

        self.setCentralWidget(self.centralWidget)

        self.create_book_info_dock()
        settings = QSettings()
        size = settings.value("MainWindow/Size",
                              QVariant(QSize(1030, 800))).toSize()
        self.resize(size)

        position = settings.value("MainWindow/Position",
                                  QVariant(QPoint(120, 100))).toPoint()
        self.move(position)
        self.restoreState(settings.value("MainWindow/State").toByteArray())

        self.setWindowTitle("EE-Book")
        QTimer.singleShot(0, self.loadInitialFile)
        self.update_library()
        self.create_connections()

    def create_book_info_dock(self):
        if getattr(self, 'dock', None):
            self.dock.show()
            return

        self.dock = QDockWidget("book details", self)
        self.dock.setObjectName('book details')
        self.dock.setAllowedAreas(Qt.LeftDockWidgetArea
                                  | Qt.RightDockWidgetArea)
        self.book_detail = BookDetails(self.book_view)
        self.dock.setWidget(self.book_detail)
        self.addDockWidget(Qt.RightDockWidgetArea, self.dock)

    def showContextMenu(self, pos):
        u"""
        右键点击时调用的函数
        """
        # 菜单显示前,将它移动到鼠标点击的位置
        self.contextMenu.exec_(QCursor.pos())  # 在鼠标位置显示

    def update_library(self):
        self.library = get_library()

        self.library_table.clear()
        self.library_table.setStyleSheet(
            "selection-background-color: blue")  # 设置选中背景色
        self.library_table.setRowCount(len(self.library['books']))
        self.library_table.setColumnCount(5)  # TODO: 改掉硬编码??
        self.library_table.setHorizontalHeaderLabels(
            ['Title', 'Authors', 'Tags', 'Date', 'Size(MB)'])

        self.library_table.setAlternatingRowColors(True)
        self.library_table.setEditTriggers(QTableWidget.NoEditTriggers)
        self.library_table.setSelectionBehavior(QTableWidget.SelectRows)
        self.library_table.setSelectionMode(QTableWidget.SingleSelection)

        self.model = QtGui.QStandardItemModel(self)
        for i, book in enumerate(self.library['books']):
            for j, cell in enumerate(
                (book['title'], book['author'], book['tags'], book['date'],
                 book['size'])):
                item = QTableWidgetItem(cell)
                item.setTextAlignment(Qt.AlignCenter)
                self.library_table.setItem(i, j, item)

        self.library_table.resizeColumnsToContents()

    def create_action(self,
                      text,
                      slot=None,
                      shortcut=None,
                      icon=None,
                      tip=None,
                      checkable=False,
                      signal="triggered()"):
        u"""

        :param text:
        :param slot:
        :param shortcut:
        :param icon:
        :param tip:
        :param checkable:
        :param signal:
        :return:
        """
        action = QAction(text, self)
        if slot is not None:
            self.connect(action, SIGNAL(signal), slot)
        if shortcut is not None:
            action.setShortcut(shortcut)
        if icon is not None:
            action.setIcon(icon)
        if tip is not None:
            action.setToolTip(tip)
        if checkable is not None:
            action.setCheckable(checkable)
        return action

    def add_actions(self, target, actions):
        for action in actions:
            if action is None:
                target.addSeparator()
            else:
                target.addAction(action)

    def closeEvent(self, event):
        settings = QSettings()
        settings.setValue("MainWindow/Size", QVariant(self.size()))
        settings.setValue("MainWindow/Position", QVariant(self.pos()))
        settings.setValue("MainWindow/State", QVariant(self.saveState()))

    def loadInitialFile(self):
        settings = QSettings()
        fname = settings.value("LastFile").toString()
        if fname and QFile.exists(fname):
            ok, msg = self.movies.load(fname)
            self.statusBar().showMessage(msg, 5000)

    def toggle_toolbar(self):
        state = self.toolbar.isVisible()
        self.toolbar.setVisible(not state)

    def toggle_statusbar(self):
        state = self.statusbar.isVisible()
        self.statusbar.setVisible(not state)

    def add_book(self):
        u"""
        打开已经在文件系统的电子书到电子书管理器中
        :return:
        """
        # Get filename and show only .epub files    Mac 系统下返回的是native fiel dialog
        book_path = QtGui.QFileDialog.getOpenFileName(self, u'打开Epub格式电子书',
                                                      ".", "(*.epub)")

        if str(book_path) is '':
            # 没有选中电子书
            return

        if os.path.dirname(str(book_path)) + os.sep != str(LIBRARY_DIR):
            shutil.copy(str(book_path), LIBRARY_DIR)

        file_name = os.path.basename(str(book_path))
        book_id = file_name.split('.epub')[0]
        bookdata_book_catalog = LIBRARY_DIR + book_id

        Path.mkdir(bookdata_book_catalog)

        Debug.logger.debug(u"移入bookdata中的是:" + str(LIBRARY_DIR + file_name))
        Debug.logger.debug(u"bookdata中的书:" + str(bookdata_book_catalog))
        Debug.logger.debug(u"book_path:" + os.path.dirname(str(book_path)))
        if os.path.dirname(str(book_path)) != bookdata_book_catalog:
            try:
                shutil.move(LIBRARY_DIR + file_name, bookdata_book_catalog)
            except shutil.Error:
                Debug.logger.debug(u"TODO:添加过这个书,删除原来的书")
                pass
        else:
            Debug.logger.debug(u"是相同文件夹, 添加的是bookdata中的书")
        os.remove(LIBRARY_DIR + file_name)
        book = Book(book_id)
        book.date = time.strftime(ISOTIMEFORMAT, time.localtime())
        insert_library(book)
        self.update_library()

    def remove_book(self):
        u"""
        移除电子书
        :return:
        """
        book_id = self.library['books'][
            self.library_table.currentRow()]['book_id']
        remove_from_library(book_id)
        self.update_library()

    def make_book(self):
        u"""
        制作电子书
        :return:
        """
        download = QtGui.QDialog()
        ui = DownloadDialog(RecipeModel(),
                            self.book_view)  # TODO: 将任务交给jobs模块,

        ui.exec_()
        self.update_library()
        del download

    def create_connections(self):
        self.library_table.itemDoubleClicked.connect(self.view_book)
        self.library_table.itemClicked.connect(self.row_clicked)
        self.searchLineEdit.textChanged.connect(self.search_text_changed)

    def row_clicked(self):
        current_row = self.library_table.currentRow()
        current_book = self.library['books'][current_row]
        self.book_detail.show_data(current_book)
        pass

    def view_book(self):
        u"""
        用电子书阅读器打开选中的电子书
        :return:
        """
        if not self.library_table.isItemSelected(
                self.library_table.currentItem()):
            QMessageBox.information(self, u"Error", u"请选定要打开的电子书")
            return

        # 判断是否用软件内置的EPub阅读器打开
        if self.read_method_build_in:
            self.view_book_with_build_in()
        else:
            self.view_book_with_os()

    def view_book_with_build_in(self):
        book_id = self.library['books'][
            self.library_table.currentRow()]['book_id']
        self.book_view.load_book(book_id)
        self.book_view.show()

    def view_book_with_os(self):
        book_id = self.library['books'][
            self.library_table.currentRow()]['book_id']
        epub_path = LIBRARY_DIR + '%s/%s.epub' % (book_id, book_id)
        if isosx:
            subprocess.call(["open", epub_path])
        elif iswindows:
            os.startfile(file)  # TODO: 需要测试
        elif islinux:
            subprocess.call(["xdg-open", file])  # TODO: 需要测试

    def set_viewer(self):
        u"""
        设置默认的EPub阅读器
        :return:
        """
        if self.read_method_build_in:
            read_method_info = u"系统默认的EPub格式阅读器"
        else:
            read_method_info = u"软件内置的EPub格式阅读器"
        question_info = u"""
        现在设定的EPub阅读器是 %s, 目前软件自带的EPub阅读器正在开发中, 还比较简陋, 但可以用来预览(如果系统没有装EPub格式阅读器), 点击确定进行切换, 点击取消不切换
        """ % read_method_info
        clicked = QMessageBox.question(self, "设置EPub阅读器", question_info,
                                       QMessageBox.Ok | QMessageBox.Cancel,
                                       QMessageBox.Ok)
        if clicked:
            self.read_method_build_in = not self.read_method_build_in

    def about_help(self):
        form = HelpForm("index.html")
        form.setWindowTitle('EE-Book Help')
        form.show()
        form.exec_()

    def search_text_changed(self, text):
        for i in range(self.library_table.rowCount()):
            match = False
            for j in range(self.library_table.columnCount()):
                item = self.library_table.item(i, j)
                if item.text().contains(text):
                    match = True
                    break
            self.library_table.setRowHidden(i, not match)
class MainWindow(KXmlGuiWindow):

    "Class which displays the main Danbooru Client window."

    def __init__(self, *args):

        "Initialize a new main window."

        super(MainWindow, self).__init__(*args)
        self.cache = KPixmapCache("danbooru")
        self.preferences = preferences.Preferences()
        self.api = None
        self.__ratings = None
        self.__step = 0

        self.url_list = self.preferences.boards_list
        self.max_retrieve = self.preferences.thumbnail_no

        self.statusbar = self.statusBar()
        self.progress = QProgressBar()
        self.thumbnailarea = None
        self.tag_dock = None
        self.pool_dock = None
        self.first_fetch_widget = None

        self.progress.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)

        # FIXME: Hackish, but how to make it small otherwise?
        self.progress.setMinimumSize(100, 1)
        self.statusbar.addPermanentWidget(self.progress)
        self.progress.hide()

        self.setup_welcome_widget()
        self.setup_actions()

    def reload_config(self):
        """Reload configuration after a change"""

        urls = self.preferences.boards_list

        if self.first_fetch_widget is not None:
            self.first_fetch_widget.setup_urls(urls)

        if self.thumbnailarea is not None:

            max_thumbnail = self.preferences.thumbnail_no
            max_rating = self.preferences.max_allowed_rating

            self.thumbnailarea.fetchwidget.limit = max_thumbnail
            self.thumbnailarea.fetchwidget.rating = max_rating
            self.thumbnailarea.fetchwidget.update_values()

            self.thumbnailarea.connectwidget.setup_urls(urls)

        self.url_list = self.preferences.boards_list
        self.max_retrieve = self.preferences.thumbnail_no

    def setup_welcome_widget(self):
        """Load the welcome widget at startup."""

        widget = QWidget()
        layout = QVBoxLayout()

        welcome = QLabel(parent=self)
        pix = QPixmap(KStandardDirs.locate("appdata", "logo.png"))

        welcome.setPixmap(pix)
        welcome.setAlignment(Qt.AlignCenter)

        self.first_fetch_widget = connectwidget.ConnectWidget(
            self.preferences.boards_list, self)

        self.statusbar.addPermanentWidget(self.first_fetch_widget, 300)

        self.first_fetch_widget.connectionEstablished.connect(
            self.handle_connection)
        self.first_fetch_widget.rejected.connect(self.first_fetch_widget.hide)

        self.first_fetch_widget.hide()

        self.first_fetch_widget.setSizePolicy(QSizePolicy.Preferred,
                                              QSizePolicy.Fixed)

        layout.addWidget(self.first_fetch_widget)
        layout.addWidget(welcome)
        widget.setLayout(layout)

        self.setCentralWidget(widget)

    def setup_tooltips(self):
        """Set tooltips for the actions."""

        self.connect_action.setToolTip(i18n("Connect to a Danbooru board"))
        self.fetch_action.setToolTip(
            i18n("Fetch thumbnails from a Danbooru board"))
        self.batch_download_action.setToolTip(i18n("Batch download images"))

    def create_actions(self):
        """Create actions for the main window."""

        self.connect_action = KAction(KIcon("document-open-remote"),
                                      i18n("Connect"), self)
        self.fetch_action = KAction(KIcon("download"), i18n("Download"), self)
        self.clean_action = KAction(KIcon("trash-empty"),
                                    i18n("Clear thumbnail cache"), self)
        self.batch_download_action = KAction(KIcon("download"),
                                             i18n("Batch download"), self)
        self.pool_toggle_action = KToggleAction(KIcon("image-x-generic"),
                                                i18n("Pools"), self)
        self.tag_display_action = KDualAction(i18n("Show tags"),
                                              i18n("Hide tags"), self)
        self.tag_display_action.setIconForStates(KIcon("image-x-generic"))
        self.tag_display_action.setEnabled(False)

        # Shortcuts
        connect_default = KAction.ShortcutTypes(KAction.DefaultShortcut)
        connect_active = KAction.ShortcutTypes(KAction.ActiveShortcut)

        self.connect_action.setShortcut(KStandardShortcut.open())
        self.fetch_action.setShortcut(KStandardShortcut.find())

        self.fetch_action.setEnabled(False)
        self.batch_download_action.setEnabled(False)
        self.pool_toggle_action.setEnabled(False)

    def setup_action_collection(self):
        """Set up the action collection by adding the actions."""

        action_collection = self.actionCollection()

        # Addition to the action collection
        action_collection.addAction("connect", self.connect_action)
        action_collection.addAction("fetch", self.fetch_action)
        action_collection.addAction("clean", self.clean_action)
        action_collection.addAction("batchDownload",
                                    self.batch_download_action)
        action_collection.addAction("poolDownload", self.pool_toggle_action)
        action_collection.addAction("tagDisplay", self.tag_display_action)

        KStandardAction.quit(self.close, action_collection)
        KStandardAction.preferences(self.show_preferences, action_collection)

        action_collection.removeAction(
            action_collection.action("help_contents"))
        action_collection.actionHovered.connect(self.setup_action_tooltip)

    def setup_actions(self):
        """Set up the relevant actions, tooltips, and load the RC file."""

        self.create_actions()
        self.setup_tooltips()
        self.setup_action_collection()

        # Connect signals
        self.connect_action.triggered.connect(self.connect)
        self.fetch_action.triggered.connect(self.get_posts)
        self.clean_action.triggered.connect(self.clean_cache)
        self.batch_download_action.triggered.connect(self.batch_download)
        self.pool_toggle_action.toggled.connect(self.pool_toggle)
        self.tag_display_action.activeChanged.connect(self.tag_display)

        window_options = self.StandardWindowOption(self.ToolBar | self.Keys
                                                   | self.Create | self.Save
                                                   | self.StatusBar)

        setupGUI_args = [
            QSize(500, 400),
            self.StandardWindowOption(window_options)
        ]

        #Check first in standard locations for danbooruui.rc

        rc_file = KStandardDirs.locate("appdata", "danbooruui.rc")

        if rc_file.isEmpty():
            setupGUI_args.append(os.path.join(sys.path[0], "danbooruui.rc"))
        else:
            setupGUI_args.append(rc_file)

        self.setupGUI(*setupGUI_args)

    def setup_action_tooltip(self, action):

        "Show statusbar help when actions are hovered."

        if action.isEnabled():
            self.statusBar().showMessage(action.toolTip(), 2000)

    def setup_connections(self):
        """Set up connections for post and tag retrieval."""

        if self.api is None:
            return

        self.api.postRetrieved.connect(self.update_progress)
        self.api.postDownloadFinished.connect(self.download_finished)
        self.api.tagRetrieved.connect(self.tag_dock.widget().add_tags)
        self.tag_dock.widget().itemDoubleClicked.connect(
            self.fetch_tagged_items)

    def show_preferences(self):

        "Show the preferences dialog."

        if KConfigDialog.showDialog("Preferences dialog"):
            return
        else:
            dialog = preferences.PreferencesDialog(self, "Preferences dialog",
                                                   self.preferences)
            dialog.show()
            dialog.settingsChanged.connect(self.reload_config)

    def connect(self, ok):

        "Connect to a Danbooru board."

        if self.thumbnailarea is None:
            self.first_fetch_widget.show()
        else:
            self.thumbnailarea.connectwidget.show()

    def restore(self):

        self.statusbar.removeWidget(self.connect_widget)

    def handle_connection(self, connection):

        self.api = None
        self.api = connection
        self.api.cache = self.cache

        if self.pool_dock is not None:
            self.pool_dock.hide()
            self.pool_dock.widget().clear()
            self.pool_toggle_action.setChecked(False)

        if self.thumbnailarea is not None:
            #TODO: Investigate usability
            self.clear(clear_pool=True)
            self.thumbnailarea.clear()
            self.thumbnailarea.api_data = self.api
            self.setup_connections()

        else:
            self.first_fetch_widget.connectionEstablished.disconnect()
            self.first_fetch_widget.rejected.disconnect()
            self.statusbar.removeWidget(self.first_fetch_widget)
            self.setup_area()

        self.api.cache = self.cache

        self.statusBar().showMessage(i18n("Connected to %s" % self.api.url),
                                     3000)
        self.fetch_action.setEnabled(True)

        # Set up pool widget

        pool_widget = poolwidget.DanbooruPoolWidget(self.api)
        self.pool_dock = QDockWidget("Pools", self)
        self.pool_dock.setObjectName("PoolDock")
        self.pool_dock.setAllowedAreas(Qt.BottomDockWidgetArea)
        self.pool_dock.setWidget(pool_widget)
        #self.pool_dock.setFeatures(QDockWidget.NoDockWidgetFeatures)
        self.addDockWidget(Qt.BottomDockWidgetArea, self.pool_dock)
        self.pool_dock.widget().poolDownloadRequested.connect(
            self.pool_prepare)
        self.pool_dock.hide()

        self.pool_toggle_action.setEnabled(True)
        self.clear()  # Needed to show properly the stuff after connecting

        self.api.get_post_list(tags="",
                               limit=self.thumbnailarea.post_limit,
                               rating=self.preferences.max_allowed_rating,
                               blacklist=list(self.preferences.tag_blacklist))
        self.api.get_tag_list(name="",
                              blacklist=list(self.preferences.tag_blacklist),
                              limit=20)

    def get_posts(self, ok):

        "Get posts from the connected Danbooru board."

        if not self.api:
            return

        self.thumbnailarea.fetchwidget.show()

    def handle_fetching(self, tags, max_rating, limit):
        """Slot connected to the dataSent signal of the fetch widget.

        The widgets are set up if they don't exist, and the API is queried
        to do the actual downloading of tags and

        """

        self.clear()

        self.thumbnailarea.fetchwidget.hide()

        if self.tag_dock is not None:
            self.tag_dock.widget().clear()

        self.thumbnailarea.post_limit = limit
        blacklist = list(self.preferences.tag_blacklist)
        self.api.get_post_list(tags=tags,
                               limit=limit,
                               rating=max_rating,
                               blacklist=blacklist)

        tags = [item for item in tags if item]

        if not tags:
            # No related tags, fetch the most recent 20
            tags = ""
            self.api.get_tag_list(name=tags, blacklist=blacklist, limit=20)
        else:
            self.api.get_related_tags(tags=tags, blacklist=blacklist)

    def fetch_tagged_items(self, item):
        """Fetch items found in the tag list widget."""

        tag_name = unicode(item.text())
        self.clear()

        blacklist = self.preferences.tag_blacklist
        limit = self.preferences.thumbnail_no
        rating = self.preferences.max_allowed_rating

        self.api.get_post_list(page=1,
                               tags=[tag_name],
                               blacklist=blacklist,
                               limit=limit,
                               rating=rating)
        self.api.get_related_tags(tags=[tag_name], blacklist=blacklist)

    def pool_toggle(self, checked):

        "Toggle the presence/absence of the pool dock."

        if not self.api:
            return

        if not checked:
            self.pool_dock.hide()
        else:
            self.pool_dock.show()

    def pool_prepare(self, pool_id):
        """Prepare the central area for pool image loading."""

        if self.thumbnailarea is None:
            self.setup_area()
        else:
            self.clear(clear_pool=False)

        self.api.get_pool(pool_id,
                          blacklist=self.preferences.tag_blacklist,
                          rating=self.preferences.max_allowed_rating)

    def batch_download(self, ok):

        "Download images in batch."

        selected_items = self.thumbnailarea.selected_images()

        if not selected_items:
            return

        start_url = KUrl("kfiledialog:///danbooru")
        caption = i18n("Select a directory to save the images to")
        directory = KFileDialog.getExistingDirectoryUrl(
            start_url, self, caption)

        if directory.isEmpty():
            return

        for item in selected_items:

            file_url = item.url_label.url()
            tags = item.data.tags

            # Make a local copy to append paths as addPath works in-place
            destination = KUrl(directory)

            file_name = KUrl(file_url).fileName()
            destination.addPath(file_name)

            job = KIO.file_copy(KUrl(file_url), destination, -1)
            job.setProperty("tags", QVariant(tags))
            job.result.connect(self.batch_download_slot)

    def setup_area(self):

        "Set up the central widget to display thumbnails."

        self.thumbnailarea = thumbnailarea.DanbooruTabWidget(
            self.api, self.preferences, self.preferences.thumbnail_no, self)

        self.setCentralWidget(self.thumbnailarea)

        self.thumbnailarea.connectwidget.connectionEstablished.connect(
            self.handle_connection, type=Qt.UniqueConnection)
        self.thumbnailarea.connectwidget.rejected.connect(
            self.thumbnailarea.connectwidget.hide, type=Qt.UniqueConnection)

        self.thumbnailarea.fetchwidget.dataSent.connect(
            self.handle_fetching, type=Qt.UniqueConnection)
        self.thumbnailarea.fetchwidget.rejected.connect(
            self.thumbnailarea.fetchwidget.hide, type=Qt.UniqueConnection)

        # Set up tag widget

        blacklist = self.preferences.tag_blacklist
        tag_widget = tagwidget.DanbooruTagWidget(blacklist, self)
        self.tag_display_action.setActive(True)
        self.tag_display_action.setEnabled(True)
        self.tag_dock = QDockWidget("Similar tags", self)
        self.tag_dock.setObjectName("TagDock")
        self.tag_dock.setAllowedAreas(Qt.RightDockWidgetArea)
        self.tag_dock.setWidget(tag_widget)
        #self.tag_dock.setFeatures(QDockWidget.NoDockWidgetFeatures)
        self.addDockWidget(Qt.RightDockWidgetArea, self.tag_dock)
        self.tag_dock.hide()

        # Container signal-slot connections

        self.setup_connections()

    def download_finished(self):
        """Slot called when all the data has been completed. Clears the progress
        bar and resets it to 0."""

        if not self.batch_download_action.isEnabled():
            self.batch_download_action.setEnabled(True)

        self.__step = 0
        self.progress.hide()

    def update_progress(self):

        "Update the progress bar."

        if not self.progress.isVisible():
            self.progress.show()

        self.__step += 1
        self.progress.setValue(self.__step)

    def clear(self, clear_pool=True):

        "Clear the central widget."

        if self.thumbnailarea is None:
            return

        self.thumbnailarea.clear()
        self.tag_dock.widget().clear()
        if clear_pool:
            self.pool_dock.widget().clear()
        self.batch_download_action.setEnabled(False)

    def clean_cache(self):

        "Purge the thumbnail cache."

        self.cache.discard()
        self.statusBar().showMessage(i18n("Thumbnail cache cleared."))

    def batch_download_slot(self, job):
        """Slot called when doing batch download, for each file retrieved.

        If Nepomuk tagging is enabled, each file is tagged using the item's
        respective tags.

        """

        if job.error():
            job.ui().showErrorMessage()
        else:
            if self.preferences.nepomuk_enabled:
                tags = job.property("tags").toPyObject()
                #danbooru2nepomuk.tag_danbooru_item(job.destUrl().path(),
                #                                   tags)

    def tag_display(self, state):
        """Display or hide the tag dock."""

        if self.tag_dock is None:
            self.tag_display_action.setActive(False)
            return

        if state:
            self.tag_dock.show()
        else:
            self.tag_dock.hide()
Exemple #29
0
class MainWindow(QMainWindow):

    def __init__(self):
        super(MainWindow, self).__init__()

        self.create_layout()
        self.create_actions()
        self.create_menus()
        self.create_connections()

    def create_layout(self):
        self.book = BookView(self)
        self.setCentralWidget(self.book)

        self.create_library_dock()

    def create_library_dock(self):
        if getattr(self, 'dock', None):
            self.dock.show()
            return

        self.dock = QDockWidget("Library", self)
        self.dock.setAllowedAreas(Qt.LeftDockWidgetArea |
                                  Qt.RightDockWidgetArea)

        self.library = Library(self.book)
        self.dock.setWidget(self.library)
        self.addDockWidget(Qt.RightDockWidgetArea, self.dock)

    def create_menus(self):
        file_menu = self.menuBar().addMenu("&File")
        help_menu = self.menuBar().addMenu("&Help")

        file_menu.addAction(self.library_action)
        file_menu.addAction(self.search_action)
        file_menu.addSeparator()
        file_menu.addAction(self.quit_action)

        help_menu.addAction(self.help_action)
        help_menu.addAction(self.about_action)

    def create_actions(self):
        self.library_action = QAction("&Library", self)
        self.search_action = QAction("&Search", self)
        self.quit_action = QAction("&Quit", self)

        self.help_action = QAction("QtBooks Help", self)
        self.about_action = QAction("&About", self)

    def create_connections(self):
        self.connect(self.library_action, SIGNAL("triggered()"),
                     self.create_library_dock)
        self.connect(self.search_action, SIGNAL("triggered()"), self.search)
        self.connect(self.quit_action, SIGNAL("triggered()"),
                     QApplication.instance(), SLOT("closeAllWindows()"))

        self.connect(self.help_action, SIGNAL("triggered()"), self.help)
        self.connect(self.about_action, SIGNAL("triggered()"), self.about)

    def about(self):
        QMessageBox.about(self, "QtBooks", "An ebook reader")


    def help(self):
        QMessageBox.information(self, 'Help', 'Nothing yet!')

    def search(self):
        search = Search(self)
        search.show()
Exemple #30
0
class filexplorerPluginMain(plugin.Plugin):
    ' main class for plugin '
    def initialize(self, *args, **kwargs):
        ' class init '
        global CONFIG_DIR
        ec = ExplorerContainer()
        super(filexplorerPluginMain, self).initialize(*args, **kwargs)

        self.dock = QDockWidget()
        self.dock.setAllowedAreas(Qt.LeftDockWidgetArea |
                                  Qt.RightDockWidgetArea)
        self.dock.setFeatures(QDockWidget.DockWidgetFloatable |
                              QDockWidget.DockWidgetMovable)
        self.dock.setWindowTitle("fileXplorer")
        self.dock.setStyleSheet('QDockWidget::title { text-align: center; }')

        # search for the truth
        self.srch = QLineEdit()
        #self.srch.resize(self.srch.size().height(), self.dock.size().width())
        self.srch.setPlaceholderText(' Search for Python files Local or PyPI ')
        self.srch.returnPressed.connect(self.search)

        # Disk Usage Bar
        self.hdbar = QProgressBar()
        if sys.platform != 'win32':
            self.hdbar.setMaximum(statvfs(HOME).f_blocks *
                statvfs(HOME).f_frsize / 1024 / 1024 / 1024)
            self.hdbar.setValue(statvfs(HOME).f_bfree *
                statvfs(HOME).f_frsize / 1024 / 1024 / 1024)
        self.hdbar.setToolTip(str(self.hdbar.value()) + '% Total Disk Use ')
        #self.hdbar.setStyleSheet('''QProgressBar{background-color:
        #QLinearGradient(spread:pad,x1:0,y1:0,x2:1,y2:1,stop:0 rgba(255,0,0,99),
        #stop:1 rgba(9,255,9,200));color:#fff;border:none;border-radius:9px;}
        #QProgressBar::chunk{background-color:QLinearGradient(spread:pad,y1:0,
        #x1:0,y2:1,x2:0.27,stop:0 rgb(0,0,0),stop:1 rgb(9,99,255));padding:0;
        #border:none;border-radius:9px;height:9px;margin:1px;}''')

        self.model = QDirModel()
        self.fileView = QColumnView(self.dock)
        self.fileView.setAlternatingRowColors(True)
        # self.fileView.setFont(QFont(self.fileView.font().setBold(True)))
        self.fileView.setIconSize(QSize(32, 32))
        self.fileView.setModel(self.model)
        self.fileView.updatePreviewWidget.connect(self.runfile)

        self.sli = QSlider()
        self.sli.setRange(16, 128)
        self.sli.setValue(32)
        self.sli.setToolTip('Icon Size: 32 px. Move Slider to change.')
        self.sli.setOrientation(Qt.Horizontal)
        self.sli.valueChanged.connect(lambda: self.fileView.setIconSize(
            QSize(self.sli.value(), self.sli.value())))
        self.sli.sliderReleased.connect(lambda:
            self.sli.setToolTip('Icon Size: ' + str(self.sli.value())))

        class TransientWidget(QWidget):
            ' persistant widget thingy '
            def __init__(self, widget_list):
                ' init sub class '
                super(TransientWidget, self).__init__()
                vbox = QVBoxLayout(self)
                for each_widget in widget_list:
                    vbox.addWidget(each_widget)

        tw = TransientWidget((self.srch, self.dock, self.sli, self.hdbar))
        ec.addTab(tw, "fileXplorer")

        ####

        self.process = QProcess()
        self.process.finished.connect(self.processFinished)

        self.preview = QLabel(self.fileView)
        self.preview.setTextFormat(0)
        self.preview.setStyleSheet('QLabel{font-size:9px;}')
        self.preview.setAutoFillBackground(True)
        self.fileView.setPreviewWidget(self.preview)
        self.dock.setWidget(self.fileView)

        # take a shot
        self.pic = QAction(QIcon.fromTheme("camera-photo"), 'Screenshot', self)
        self.pic.triggered.connect(lambda: QPixmap.grabWindow(
            QApplication.desktop().winId()).save(QFileDialog.getSaveFileName(
            self.dock, " Save Screenshot As ... ", HOME, ';;(*.png)')))

        # copy time
        self.tim = QAction(QIcon.fromTheme("user-away"),
                           'Date and Time to Clipboard', self)
        self.tim.triggered.connect(lambda: QApplication.clipboard().setText(
            datetime.now().strftime(" %A %B %d-%m-%Y %H:%M:%S %p ")))

        # color chooser
        self.cl = QAction(QIcon.fromTheme("applications-graphics"),
                          'Color Chooser to Clipboard', self)
        self.cl.triggered.connect(lambda: QApplication.clipboard().setText(
            '{}'.format(QColorDialog.getColor().name())))

        # icon chooser
        self.icn = QAction(QIcon.fromTheme("insert-image"),
                          'Icon Chooser to Clipboard', self)
        self.icn.triggered.connect(self.iconChooser)

        # tool bar with actions
        QToolBar(self.dock).addActions((self.cl, self.icn, self.tim, self.pic))

        self.textBrowser = QTextBrowser(self.dock)
        self.textBrowser.setAutoFillBackground(True)
        self.textBrowser.setGeometry(self.dock.geometry())
        self.textBrowser.hide()

    def processFinished(self):
        ' print info of finished processes '
        print(" INFO: OK: QProcess finished . . . ")

    def search(self):
        ' function to search python files '
        # get search results of python filenames local or remote
        pypi_url = 'http://pypi.python.org/pypi'
        # pypi query
        pypi = xmlrpclib.ServerProxy(pypi_url, transport=ProxyTransport())
        try:
            pypi_query = pypi.search({'name': str(self.srch.text()).lower()})
            pypi_fls = list(set(['pypi.python.org/pypi/' + a['name'] +
                   ' | pip install ' + a['name'] for a in pypi_query]))
        except:
            pypi_fls = '<b> ERROR: Internet not available! ಠ_ಠ </b>'
        s_out = ('<br> <br> <br> <h3> Search Local Python files: </h3> <hr> ' +
        # Jedi list comprehension for LOCAL search
        str(["{}/{}".format(root, f) for root, f in list(itertools.chain(*
            [list(itertools.product([root], files))
            for root, dirs, files in walk(str(
            QFileDialog.getExistingDirectory(self.dock,
            'Open Directory to Search', path.expanduser("~"))))]))
            if f.endswith(('.py', '.pyw', '.pth')) and not f.startswith('.')
            and str(self.srch.text()).lower().strip() in f]
        ).replace(',', '<br>') + '<hr><h3> Search PyPI Python files: </h3>' +
        # wraped pypi query REMOTE search
        str(pypi_fls).replace(',', '<br>') + '<hr>Auto-Proxy:ON,DoNotTrack:ON')
        # print(s_out)
        try:
            call('notify-send fileXplorer Searching...', shell=True)
        except:
            pass
        self.srch.clear()
        self.textBrowser.setGeometry(self.dock.geometry())
        self.textBrowser.setHtml(s_out)
        self.textBrowser.show()
        tmr = QTimer(self.fileView)
        tmr.timeout.connect(self.textBrowser.hide)
        tmr.start(20000)

    def iconChooser(self):
        ' Choose a Icon and copy it to clipboard '
        #
        from .std_icon_naming import std_icon_naming as a
        #
        prv = QDialog(self.dock)
        prv.setWindowFlags(Qt.FramelessWindowHint)
        prv.setAutoFillBackground(True)
        prv.setGeometry(self.fileView.geometry())
        table = QTableWidget(prv)
        table.setColumnCount(1)
        table.setRowCount(len(a))
        table.verticalHeader().setVisible(True)
        table.horizontalHeader().setVisible(False)
        table.setShowGrid(True)
        table.setIconSize(QSize(128, 128))
        for index, icon in enumerate(a):
            item = QTableWidgetItem(QIcon.fromTheme(icon), '')
            # item.setData(Qt.UserRole, '')
            item.setToolTip(icon)
            table.setItem(index, 0, item)
        table.clicked.connect(lambda: QApplication.clipboard().setText(
          'QtGui.QIcon.fromTheme("{}")'.format(table.currentItem().toolTip())))
        table.doubleClicked.connect(prv.close)
        table.resizeColumnsToContents()
        table.resizeRowsToContents()
        QLabel('<h3> <br> 1 Click Copy, 2 Clicks Close </h3>', table)
        table.resize(prv.size())
        prv.exec_()

    def runfile(self, index):
        ' run the choosed file '
        s = str(file(self.model.filePath(index), 'r').read().strip())
        f = str(self.model.filePath(index))
        # ctime is NOT crossplatform,metadata change on *nix,creation on Window
        # http://docs.python.org/library/os.path.html#os.path.getctime
        m = ''.join((f, N, str(path.getsize(f) / 1024), ' Kilobytes', N,
            str(len(file(f, 'r').readlines())), ' Lines', N,
            str(len(s.replace(N, ''))), ' Characters', N,
            str(len([a for a in sub('[^a-zA-Z0-9 ]', '', s).split(' ')
                if a != ''])), ' Words', N,
            str(len([a for a in s if a in punctuation])), ' Punctuation', N,
            oct(stat(f).st_mode)[-3:], ' Permissions', N,
            time.ctime(path.getatime(f)), ' Accessed', N,
            time.ctime(path.getmtime(f)), ' Modified', N,
            'Owner: ', str(self.model.fileInfo(index).owner()), N,
            'Is Writable: ', str(self.model.fileInfo(index).isWritable()), N,
            'Is Executable: ', str(self.model.fileInfo(index).isExecutable()),
            N, 'Is Hidden: ', str(self.model.fileInfo(index).isHidden()), N,
            'Is SymLink: ', str(self.model.fileInfo(index).isSymLink()), N,
            'File Extension: ', str(self.model.fileInfo(index).suffix())
        ))
        #print(m)
        self.preview.setToolTip(m)
        self.preview.setText(s)
        self.preview.resize(self.preview.size().width(),
                            self.dock.size().height())
        self.process.start('xdg-open {}'.format(f))
        if not self.process.waitForStarted():
            print((" ERROR: Process {} Failed ! ".format(str(f))))
            return
Exemple #31
0
class MainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        # super(MainWindow, self).__init__(parent)
        QtGui.QMainWindow.__init__(self, parent)

        self.filename = ""
        self.read_method_build_in = False    # 若为False, 用系统自带的EPub阅读器打开
        self.library = get_library()

        self.book_view = BookView()
        # ###########actions############################
        self.addBookAction = self.create_action(
            u"添加EPub格式的电子书", self.add_book, QKeySequence.Open,
            QtGui.QIcon(":/open.png"), u"从文件系统中添加"
        )
        # TODO: 切图标
        self.removeAction = self.create_action(
            u"移除Epub格式的电子书", self.remove_book, None,
            QtGui.QIcon(":/remove.png"), u"移除EPub格式电子书"
        )
        # TODO: 切图标
        self.downloadAction = self.create_action(
            u"制作EPub格式电子书", self.make_book, None,
            QtGui.QIcon(":/download.png"), u"制作EPub格式电子书"
        )
        # TODO: 阅读电子书的图标
        self.readAction = self.create_action(
            u"阅读电子书", self.view_book, None,          # TODO
            QtGui.QIcon(":/read.png"), u"阅读电子书"
        )
        self.toolbarAction = self.create_action(
            u"切换工具栏", self.toggle_toolbar, None, None, None,
        )
        self.statusbarAction = self.create_action(
            u"切换状态栏", self.toggle_statusbar, None, None, None
        )
        self.bookDetailAction = self.create_action(
            u"打开书籍详情窗口", self.create_book_info_dock, None, None, None
        )
        self.aboutHelpAction = self.create_action(
            u"帮助", self.about_help, None, None, None,
        )
        self.setViewerAction = self.create_action(
            u"设置EPub阅读器", self.set_viewer, None,
            None, u"设置默认的电子书阅读器"
        )
        self.open_with_build_in_action = self.create_action(
            u"用软件自带EPub阅读器打开", self.view_book_with_build_in, None,
            None, None
        )

        self.open_with_os_action = self.create_action(
            u"用系统默认EPub阅读器打开", self.view_book_with_os, None,
            None, None
        )

        # ContextMenu
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.showContextMenu)

        self.contextMenu = QMenu(self)
        self.add_actions(self.contextMenu, (self.open_with_build_in_action, self.open_with_os_action))


        # ###########toolbar############################
        self.toolbar = self.addToolBar("&Options")
        self.toolbar.setObjectName('Options')
        self.add_actions(self.toolbar, (self.addBookAction, self.removeAction,
                         self.readAction, self.downloadAction))
        self.addToolBarBreak()
        self.toolbar.setVisible(True)
        # ###########menubar############################
        self.menu_bar = self.menuBar()
        self.editBook = self.menu_bar.addMenu("&Books")
        self.add_actions(self.editBook, (self.addBookAction, self.removeAction, self.downloadAction))

        self.viewMenu = self.menu_bar.addMenu("&View")
        self.add_actions(self.viewMenu, (self.toolbarAction, self.statusbarAction, self.bookDetailAction))

        self.settingMenu = self.menu_bar.addMenu("&Setting")
        self.add_actions(self.settingMenu, (self.setViewerAction, ))

        self.helpMenu = self.menu_bar.addMenu("&Help")
        self.add_actions(self.helpMenu, (self.aboutHelpAction, ))

        # Initialize a statusbar for the window
        status = self.statusBar()
        status.setSizeGripEnabled(False)

        self.setGeometry(100, 100, 1030, 800)

        self.centralWidget = QtGui.QWidget(self)

        self.search_label = QtGui.QLabel(self.centralWidget)
        self.search_label.setText(u'搜索:')
        self.searchLineEdit = QtGui.QLineEdit(self.centralWidget)
        self.library_table = LibraryTableWidget(self.book_view)
        self.library_table.setVisible(True)

        self.gridLayout = QtGui.QGridLayout(self.centralWidget)
        self.gridLayout.addWidget(self.search_label, 0, 0, 1, 1)
        self.gridLayout.addWidget(self.searchLineEdit, 0, 1, 1, 15)
        self.gridLayout.addWidget(self.library_table, 1, 0, 1, 16)
        # self.scrollArea = QScrollArea()

        self.setCentralWidget(self.centralWidget)

        self.create_book_info_dock()
        settings = QSettings()
        size = settings.value("MainWindow/Size", QVariant(QSize(1030, 800))).toSize()
        self.resize(size)

        position = settings.value("MainWindow/Position", QVariant(QPoint(120, 100))).toPoint()
        self.move(position)
        self.restoreState(settings.value("MainWindow/State").toByteArray())

        self.setWindowTitle("EE-Book")
        QTimer.singleShot(0, self.loadInitialFile)
        self.update_library()
        self.create_connections()

    def create_book_info_dock(self):
        if getattr(self, 'dock', None):
            self.dock.show()
            return

        self.dock = QDockWidget("book details", self)
        self.dock.setObjectName('book details')
        self.dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
        self.book_detail = BookDetails(self.book_view)
        self.dock.setWidget(self.book_detail)
        self.addDockWidget(Qt.RightDockWidgetArea, self.dock)


    def showContextMenu(self, pos):
        u"""
        右键点击时调用的函数
        """
        # 菜单显示前,将它移动到鼠标点击的位置
        self.contextMenu.exec_(QCursor.pos())      # 在鼠标位置显示

    def update_library(self):
        self.library = get_library()

        self.library_table.clear()
        self.library_table.setStyleSheet("selection-background-color: blue")  # 设置选中背景色
        self.library_table.setRowCount(len(self.library['books']))
        self.library_table.setColumnCount(5)    # TODO: 改掉硬编码??
        self.library_table.setHorizontalHeaderLabels(['Title', 'Authors', 'Tags', 'Date', 'Size(MB)'])

        self.library_table.setAlternatingRowColors(True)
        self.library_table.setEditTriggers(QTableWidget.NoEditTriggers)
        self.library_table.setSelectionBehavior(QTableWidget.SelectRows)
        self.library_table.setSelectionMode(QTableWidget.SingleSelection)

        self.model = QtGui.QStandardItemModel(self)
        for i, book in enumerate(self.library['books']):
            for j, cell in enumerate((book['title'], book['author'], book['tags'],
                                      book['date'], book['size'])):
                item = QTableWidgetItem(cell)
                item.setTextAlignment(Qt.AlignCenter)
                self.library_table.setItem(i, j, item)

        self.library_table.resizeColumnsToContents()

    def create_action(self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False, signal="triggered()"):
        u"""

        :param text:
        :param slot:
        :param shortcut:
        :param icon:
        :param tip:
        :param checkable:
        :param signal:
        :return:
        """
        action = QAction(text, self)
        if slot is not None:
            self.connect(action, SIGNAL(signal), slot)
        if shortcut is not None:
            action.setShortcut(shortcut)
        if icon is not None:
            action.setIcon(icon)
        if tip is not None:
            action.setToolTip(tip)
        if checkable is not None:
            action.setCheckable(checkable)
        return action

    def add_actions(self, target, actions):
        for action in actions:
            if action is None:
                target.addSeparator()
            else:
                target.addAction(action)

    def closeEvent(self, event):
        settings = QSettings()
        settings.setValue("MainWindow/Size", QVariant(self.size()))
        settings.setValue("MainWindow/Position", QVariant(self.pos()))
        settings.setValue("MainWindow/State", QVariant(self.saveState()))

    def loadInitialFile(self):
        settings = QSettings()
        fname = settings.value("LastFile").toString()
        if fname and QFile.exists(fname):
            ok, msg = self.movies.load(fname)
            self.statusBar().showMessage(msg, 5000)

    def toggle_toolbar(self):
        state = self.toolbar.isVisible()
        self.toolbar.setVisible(not state)

    def toggle_statusbar(self):
        state = self.statusbar.isVisible()
        self.statusbar.setVisible(not state)

    def add_book(self):
        u"""
        打开已经在文件系统的电子书到电子书管理器中
        :return:
        """
        # Get filename and show only .epub files    Mac 系统下返回的是native fiel dialog
        book_path = QtGui.QFileDialog.getOpenFileName(self, u'打开Epub格式电子书', ".", "(*.epub)")

        if str(book_path) is '':
            # 没有选中电子书
            return

        if os.path.dirname(str(book_path))+os.sep != str(LIBRARY_DIR):
            shutil.copy(str(book_path), LIBRARY_DIR)

        file_name = os.path.basename(str(book_path))
        book_id = file_name.split('.epub')[0]
        bookdata_book_catalog = LIBRARY_DIR+book_id

        Path.mkdir(bookdata_book_catalog)

        Debug.logger.debug(u"移入bookdata中的是:" + str(LIBRARY_DIR+file_name))
        Debug.logger.debug(u"bookdata中的书:" + str(bookdata_book_catalog))
        Debug.logger.debug(u"book_path:" + os.path.dirname(str(book_path)))
        if os.path.dirname(str(book_path)) != bookdata_book_catalog:
            try:
                shutil.move(LIBRARY_DIR+file_name, bookdata_book_catalog)
            except shutil.Error:
                Debug.logger.debug(u"TODO:添加过这个书,删除原来的书")
                pass
        else:
            Debug.logger.debug(u"是相同文件夹, 添加的是bookdata中的书")
        os.remove(LIBRARY_DIR+file_name)
        book = Book(book_id)
        book.date = time.strftime(ISOTIMEFORMAT, time.localtime())
        insert_library(book)
        self.update_library()

    def remove_book(self):
        u"""
        移除电子书
        :return:
        """
        book_id = self.library['books'][self.library_table.currentRow()]['book_id']
        remove_from_library(book_id)
        self.update_library()

    def make_book(self):
        u"""
        制作电子书
        :return:
        """
        download = QtGui.QDialog()
        ui = DownloadDialog(RecipeModel(), self.book_view)   # TODO: 将任务交给jobs模块,

        ui.exec_()
        self.update_library()
        del download

    def create_connections(self):
        self.library_table.itemDoubleClicked.connect(self.view_book)
        self.library_table.itemClicked.connect(self.row_clicked)
        self.searchLineEdit.textChanged.connect(self.search_text_changed)

    def row_clicked(self):
        current_row = self.library_table.currentRow()
        current_book = self.library['books'][current_row]
        self.book_detail.show_data(current_book)
        pass

    def view_book(self):
        u"""
        用电子书阅读器打开选中的电子书
        :return:
        """
        if not self.library_table.isItemSelected(self.library_table.currentItem()):
            QMessageBox.information(self, u"Error", u"请选定要打开的电子书")
            return

        # 判断是否用软件内置的EPub阅读器打开
        if self.read_method_build_in:
            self.view_book_with_build_in()
        else:
            self.view_book_with_os()

    def view_book_with_build_in(self):
        book_id = self.library['books'][self.library_table.currentRow()]['book_id']
        self.book_view.load_book(book_id)
        self.book_view.show()

    def view_book_with_os(self):
        book_id = self.library['books'][self.library_table.currentRow()]['book_id']
        epub_path = LIBRARY_DIR + '%s/%s.epub' % (book_id, book_id)
        if isosx:
            subprocess.call(["open", epub_path])
        elif iswindows:
            os.startfile(file)    # TODO: 需要测试
        elif islinux:
            subprocess.call(["xdg-open", file])    # TODO: 需要测试

    def set_viewer(self):
        u"""
        设置默认的EPub阅读器
        :return:
        """
        if self.read_method_build_in:
            read_method_info = u"系统默认的EPub格式阅读器"
        else:
            read_method_info = u"软件内置的EPub格式阅读器"
        question_info = u"""
        现在设定的EPub阅读器是 %s, 目前软件自带的EPub阅读器正在开发中, 还比较简陋, 但可以用来预览(如果系统没有装EPub格式阅读器), 点击确定进行切换, 点击取消不切换
        """ % read_method_info
        clicked = QMessageBox.question(self, "设置EPub阅读器", question_info,
                                       QMessageBox.Ok | QMessageBox.Cancel, QMessageBox.Ok)
        if clicked:
            self.read_method_build_in = not self.read_method_build_in

    def about_help(self):
        form = HelpForm("index.html")
        form.setWindowTitle('EE-Book Help')
        form.show()
        form.exec_()

    def search_text_changed(self, text):
        for i in range(self.library_table.rowCount()):
            match = False
            for j in range(self.library_table.columnCount()):
                item = self.library_table.item(i, j)
                if item.text().contains(text):
                    match = True
                    break
            self.library_table.setRowHidden(i, not match)
Exemple #32
0
    def createDockWidgets(self):
        #Create all dock widgets here, more flexibility than with QtDesigner
        leftDockWidget = QDockWidget(self)
        leftDockWidget.setObjectName(_fromUtf8("leftDockWidget"))
        leftDockWidget.setAllowedAreas(QtCore.Qt.LeftDockWidgetArea| QtCore.Qt.RightDockWidgetArea)

        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, leftDockWidget)
        self.setCorner(QtCore.Qt.TopLeftCorner, QtCore.Qt.LeftDockWidgetArea)
        self.setCorner(QtCore.Qt.BottomLeftCorner, QtCore.Qt.LeftDockWidgetArea)

        #Upper left dock widget - input and data
        self.mainTreeDockWidget = QtGui.QWidget()
        self.mainTreeDockWidget.setObjectName(_fromUtf8("inputDataDockWidget"))
        self.mainTreeDockWidgetHLayout = QtGui.QHBoxLayout(self.mainTreeDockWidget)
        '''
        self.inputTabWidget = QtGui.QTabWidget(self.mainTreeDockWidget)
        self.inputTabWidget.setObjectName(_fromUtf8("inputTabWidget"))
        self.inputTab = QtGui.QWidget()
        self.inputTab.setObjectName(_fromUtf8("inputTab"))
        self.inputTabGridLayout = QtGui.QGridLayout(self.inputTab)
        self.inputTabWidget.addTab(self.inputTab, _fromUtf8("Input explorer"))

        self.dataTab = QtGui.QWidget()
        self.dataTab.setObjectName(_fromUtf8("dataTab"))
        self.inputTabWidget.addTab(self.dataTab, _fromUtf8("Data"))
        '''
        #self.mainTreeDockWidgetHLayout.addWidget(self.inputTabWidget)
        leftDockWidget.setWidget(self.mainTreeDockWidget)
        self.addDockWidget(QtCore.Qt.DockWidgetArea(1), leftDockWidget)

        #Bottom left dock widget - process and view
        self.mainProcessesDockWidget = QtGui.QDockWidget(self)
        self.mainProcessesDockWidget.setObjectName(_fromUtf8("mainProcessesDockWidget"))
        self.processWidget = QtGui.QWidget()
        self.processWidget.setObjectName(_fromUtf8("processWidget"))
        self.processWidgetHLayout = QtGui.QHBoxLayout(self.processWidget)
        self.processTabWidget = QtGui.QTabWidget(self.processWidget)
        self.processTabWidget.setObjectName(_fromUtf8("processTabWidget"))
        self.processTab = QtGui.QWidget()
        self.processTab.setObjectName(_fromUtf8("processTab"))
        self.processTabHLayout = QtGui.QHBoxLayout(self.processTab)
        self.processTreeWidget = QtGui.QTreeWidget(self.processTab)
        self.processTreeWidget.setObjectName(_fromUtf8("processTreeWidget"))
        self.processTreeWidget.headerItem().setText(0, _fromUtf8("Root process"))
        self.processTabHLayout.addWidget(self.processTreeWidget)
        self.processTabWidget.addTab(self.processTab, _fromUtf8("Process explorer"))

        self.tabWindow = QtGui.QWidget()
        self.tabWindow.setObjectName(_fromUtf8("tabWindow"))
        self.processTabWidget.addTab(self.tabWindow, _fromUtf8("Windows"))
        self.processWidgetHLayout.addWidget(self.processTabWidget)
        self.mainProcessesDockWidget.setWidget(self.processWidget)
        self.addDockWidget(QtCore.Qt.DockWidgetArea(1), self.mainProcessesDockWidget)

        #Messages area

        self.bottomDockWidget = QtGui.QDockWidget(self)
        self.bottomDockWidget.setAllowedAreas(QtCore.Qt.BottomDockWidgetArea|QtCore.Qt.RightDockWidgetArea|QtCore.Qt.TopDockWidgetArea)
        self.bottomDockWidget.setObjectName(_fromUtf8("bottomDockWidget"))
        #child widget
        self.mainMessagesDockWidget = QtGui.QWidget()
        self.mainMessagesDockWidget.setObjectName(_fromUtf8("mainMessagesDockWidget"))
        self.mainMessagesDockWidgetHLayout = QtGui.QHBoxLayout(self.mainMessagesDockWidget)
        self.loggerTabWidget = QtGui.QTabWidget(self.mainMessagesDockWidget)
        self.loggerTabWidget.setObjectName(_fromUtf8("loggerTabWidget"))
        self.loggerTab = QtGui.QWidget()
        self.loggerTab.setObjectName(_fromUtf8("loggerTab"))
        self.horizontalLayout_3 = QtGui.QHBoxLayout(self.loggerTab)
        self.horizontalLayout_3.setObjectName(_fromUtf8("horizontalLayout_3"))
        self.scrollArea = QtGui.QScrollArea(self.loggerTab)
        self.scrollArea.setWidgetResizable(True)
        self.scrollArea.setObjectName(_fromUtf8("scrollArea"))
        self.scrollAreaWidgetContents = QtGui.QWidget()
        self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 725, 99))
        self.scrollAreaWidgetContents.setObjectName(_fromUtf8("scrollAreaWidgetContents"))
        self.horizontalLayout_4 = QtGui.QHBoxLayout(self.scrollAreaWidgetContents)
        self.horizontalLayout_4.setObjectName(_fromUtf8("horizontalLayout_4"))
        self.loggerTextBrowser = QtGui.QTextBrowser(self.scrollAreaWidgetContents)
        self.loggerTextBrowser.setObjectName(_fromUtf8("loggerTextBrowser"))
        self.horizontalLayout_4.addWidget(self.loggerTextBrowser)
        self.scrollArea.setWidget(self.scrollAreaWidgetContents)
        self.horizontalLayout_3.addWidget(self.scrollArea)
        self.loggerTabWidget.addTab(self.loggerTab, _fromUtf8("Logger"))
        self.otherTab = QtGui.QWidget()
        self.otherTab.setObjectName(_fromUtf8("otherTab"))
        self.loggerTabWidget.addTab(self.otherTab, _fromUtf8("Other"))
        self.mainMessagesDockWidgetHLayout.addWidget(self.loggerTabWidget)
        self.mainMessagesDockWidget.setSizePolicy(QtGui.QSizePolicy.Minimum,
                                  QtGui.QSizePolicy.Preferred)
        self.bottomDockWidget.setWidget(self.mainMessagesDockWidget)
        self.addDockWidget(QtCore.Qt.DockWidgetArea(8), self.bottomDockWidget)
        
        #see http://stackoverflow.com/questions/13151601/pyqt-dock-on-side-of-stacked-qdockwidgets
        #toolbar widget
        '''
Exemple #33
0
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

        self.create_layout()
        self.create_actions()
        self.create_menus()
        self.create_connections()

    def create_layout(self):
        self.book = BookView(self)
        self.setCentralWidget(self.book)

        self.create_library_dock()

    def create_library_dock(self):
        if getattr(self, 'dock', None):
            self.dock.show()
            return

        self.dock = QDockWidget("Library", self)
        self.dock.setAllowedAreas(Qt.LeftDockWidgetArea
                                  | Qt.RightDockWidgetArea)
        self.library = LibraryTableWidget(self.book)
        self.dock.setWidget(self.library)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.dock)

    def create_menus(self):
        file_menu = self.menuBar().addMenu("&File")
        help_menu = self.menuBar().addMenu("&Help")

        file_menu.addAction(self.library_action)
        file_menu.addAction(self.open_action)
        file_menu.addSeparator()
        file_menu.addAction(self.quit_action)

        help_menu.addAction(self.help_action)
        help_menu.addAction(self.about_action)

    def create_actions(self):
        self.library_action = QAction("&Library", self)
        self.open_action = QAction("&Open", self)
        self.quit_action = QAction("&Quit", self)

        self.help_action = QAction("Help", self)
        self.about_action = QAction("&About", self)

    def create_connections(self):
        self.connect(self.library_action, SIGNAL("triggered()"),
                     self.create_library_dock)
        self.connect(self.open_action, SIGNAL("triggered()"), self.open_book)
        self.connect(self.quit_action, SIGNAL("triggered()"),
                     QApplication.instance(), SLOT("closeAllWindows"))
        self.connect(self.about_action, SIGNAL("triggered()"), self.about)
        self.connect(self.help_action, SIGNAL("triggered()"), self.help)

    def about(self):
        QMessageBox.about(self, "QtBooks", "An ebook reader")

    def help(self):
        QMessageBox.information(self, 'Help', 'Nothing yet!')

    def open_book(self):
        book_path = QFileDialog.getOpenFileName(self, u'打开Epub格式电子书', ".",
                                                "(*.epub)")

        print u"in open_book, book_name is:" + str(book_path)
        print u"in open_book, bookdata path:" + str(LIBRARY_DIR)
        print os.path.dirname(str(book_path))

        if os.path.dirname(str(book_path)) + os.sep != str(LIBRARY_DIR):
            shutil.copy(str(book_path), LIBRARY_DIR)

        file_name = os.path.basename(str(book_path))
        book_id = file_name.split('.epub')[0]
        book = Book(book_id)
        insert_library(book)
        self.library.refresh()