예제 #1
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()      
예제 #2
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)
예제 #3
0
 def insertDockWidgets(self):
     """ adds the Tree-DockWidget to the GUI <br>
         this function is connected to the signal SignalProxy::insertDockWidgets() """
     dock = QDockWidget(self.name)
     dock.setObjectName(self.name + "View")
     dock.setWidget(self.view)
     self.distributedObjects.signalProxy.emitAddDockWidget(Qt.BottomDockWidgetArea, dock, True)
예제 #4
0
파일: __init__.py 프로젝트: koll00/Gui_SM
    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)
예제 #5
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
예제 #6
0
class OLOverview(object):

    def __init__(self, iface, olLayerTypeRegistry):
        self._iface = iface
        self._olLayerTypeRegistry = olLayerTypeRegistry
        self._dockwidget = None
        self._oloWidget = None

    # Private
    def _setDocWidget(self):
        self._dockwidget = QDockWidget(QApplication.translate("OpenLayersOverviewWidget", "OpenLayers Overview"), self._iface.mainWindow())
        self._dockwidget.setObjectName("dwOpenlayersOverview")
        self._oloWidget = OpenLayersOverviewWidget(self._iface, self._dockwidget, self._olLayerTypeRegistry)
        self._dockwidget.setWidget(self._oloWidget)

    def _initGui(self):
        self._setDocWidget()
        self._iface.addDockWidget(Qt.LeftDockWidgetArea, self._dockwidget)

    def _unload(self):
        self._dockwidget.close()
        self._iface.removeDockWidget(self._dockwidget)
        del self._oloWidget
        self._dockwidget = None

    # Public
    def setVisible(self, visible):
        if visible:
            if self._dockwidget is None:
                self._initGui()
        else:
            if not self._dockwidget is None:
                self._unload()
예제 #7
0
 def _createDock(self):
     dock = QDockWidget("")
     dock.setObjectName("ERTGUI Workflow")
     dock.setWidget(self.contentsWidget)
     dock.setFeatures(QDockWidget.DockWidgetClosable)
     dock.setAllowedAreas(Qt.LeftDockWidgetArea)
     return dock
예제 #8
0
class StackController(QObject):
    def __init__(self, distributedObjects):
        QObject.__init__(self)
        self.distributedObjects = distributedObjects

        self.editorController = distributedObjects.editorController

        self.stackModel = StackModel(
            self, self.distributedObjects.debugController, self.distributedObjects.gdb_connector
        )
        self.stackView = StackView(self)

        self.stackView.stackView.setModel(self.stackModel)

        QObject.connect(
            self.distributedObjects.signalProxy,
            SIGNAL("inferiorStoppedNormally(PyQt_PyObject)"),
            self.stackModel.update,
        )
        QObject.connect(
            self.distributedObjects.signalProxy, SIGNAL("inferiorHasExited(PyQt_PyObject)"), self.stackModel.clear
        )
        QObject.connect(self.distributedObjects.signalProxy, SIGNAL("executableOpened()"), self.stackModel.clear)
        QObject.connect(
            self.distributedObjects.signalProxy, SIGNAL("inferiorIsRunning(PyQt_PyObject)"), self.removeStackMarkers
        )
        QObject.connect(self.stackView.showStackTrace, SIGNAL("stateChanged(int)"), self.showStackTraceChanged)

        QObject.connect(self.distributedObjects.signalProxy, SIGNAL("insertDockWidgets()"), self.insertDockWidgets)

    def insertDockWidgets(self):
        self.stackDock = QDockWidget("Stack")
        self.stackDock.setObjectName("StackView")
        self.stackDock.setWidget(self.stackView)
        self.distributedObjects.signalProxy.addDockWidget(Qt.BottomDockWidgetArea, self.stackDock, True)

    def stackInStackViewActivated(self, index):
        item = index.internalPointer()
        self.distributedObjects.gdb_connector.selectStackFrame(item.level)
        self.distributedObjects.signalProxy.openFile(item.fullname, item.line)
        # FIXME: make locals view etc change their view too!

    def insertStackMarkers(self):
        if self.stackView.showStackTrace.checkState() == Qt.Checked:
            for entry in self.stackModel.stack:
                if int(entry.level) != 0 and hasattr(entry, "fullname") and hasattr(entry, "line"):
                    self.editorController.addStackMarker(entry.fullname, entry.line)

    def removeStackMarkers(self):
        for entry in self.stackModel.stack:
            if int(entry.level) != 0 and hasattr(entry, "fullname"):
                self.editorController.delStackMarkers(entry.fullname)

    def showStackTraceChanged(self, state):
        if state == Qt.Checked:
            self.insertStackMarkers()
        elif state == Qt.Unchecked:
            self.removeStackMarkers()
예제 #9
0
파일: uiMainWindow.py 프로젝트: gxgjnn/live
 def createDock(self, widgetClass, widgetName, widgetArea):
     """创建停靠组件"""
     widget = widgetClass(self.mainEngine, self.eventEngine)
     dock = QDockWidget(widgetName)
     dock.setWidget(widget)
     dock.setObjectName(widgetName)
     dock.setFeatures(dock.DockWidgetFloatable | dock.DockWidgetMovable)
     self.addDockWidget(widgetArea, dock)
     return widget, dock
예제 #10
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
예제 #11
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
예제 #12
0
	def setup_dock(self, widget, name, area):
		"""Helps to setup docks more semantically"""
		dock = QDockWidget(name, self)
		dock.setObjectName(name)
		
		yield dock
		
		self.addDockWidget(area, dock)
		dock.setWidget(widget)
예제 #13
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
예제 #14
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
예제 #15
0
    def insertDockWidget(self, widget, name, area, addToggleViewAction):
        d = QDockWidget(name, self)
        d.setObjectName(name)
        d.setWidget(widget)

        self.addDockWidget(area, d)
        if addToggleViewAction:
            self.ui.menuShow_View.addAction(d.toggleViewAction())

        return d
예제 #16
0
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setStyleSheet("QMainWindow::separator {background: lightGray; width: 2px}")

        self.tree_widget = SetupsView()
        self.eqn_widget = ResizableImage("latex/eqn.png", 100, .5, 2)
        self.outputs_dock_area = DockArea()

        file_menu = self.menuBar().addMenu("File")
        save_action = QAction("Save", self)
        save_action.triggered.connect(self.save_configuration)
        file_menu.addAction(save_action)
        load_action = QAction("Load", self)
        load_action.triggered.connect(self.load_configuration)
        file_menu.addAction(load_action)

        docks = []
        view_menu = self.menuBar().addMenu("View")
        for dock_name in ["Project Manager", "Properties", "Equation"]:
            dock = QDockWidget(dock_name)
            dock.setObjectName(method_style(dock_name))
            view_menu.addAction(dock.toggleViewAction())
            docks.append(dock)
        self.tree_dock, self.props_dock, self.eqn_dock = docks

        self.tree_dock.setWidget(self.tree_widget)
        self.eqn_dock.setWidget(self.eqn_widget)
        placeholder = QLabel("No Item Selected")
        placeholder.setAlignment(Qt.AlignCenter)
        placeholder.setMinimumSize(200, 100)
        self.props_dock.setWidget(placeholder)

        self.setCentralWidget(self.outputs_dock_area)
        self.setCorner(Qt.BottomLeftCorner, Qt.LeftDockWidgetArea)
        self.setCorner(Qt.TopLeftCorner, Qt.LeftDockWidgetArea)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.tree_dock)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.props_dock)
        self.addDockWidget(Qt.TopDockWidgetArea, self.eqn_dock)

        self.tree_widget.add_setup()
        self.tree_widget.clicked.connect(self.set_props_widget)

        self.status_label = QLabel("")
        self.progress_bar = QProgressBar()
        self.statusBar().addWidget(self.status_label)
        self.statusBar().addWidget(self.progress_bar, 1)

        time_toolbar = self.addToolBar("Time")
        time_toolbar.addWidget(QLabel("Time"))
        self.time_slider = QSlider(Qt.Horizontal)
        time_toolbar.addWidget(self.time_slider)

        self.restoreGeometry(settings.value("geometry").toByteArray())
        self.restoreState(settings.value("state").toByteArray(), __ui_version__)
예제 #17
0
 def __createDockWindow(self, name):
     """
     Private method to create a dock window with common properties.
     
     @param name object name of the new dock window (string)
     @return the generated dock window (QDockWindow)
     """
     dock = QDockWidget()
     dock.setObjectName(name)
     dock.setFeatures(
         QDockWidget.DockWidgetFeatures(QDockWidget.AllDockWidgetFeatures))
     return dock
예제 #18
0
 def __createDockWindow(self, name):
     """
     Private method to create a dock window with common properties.
     
     @param name object name of the new dock window (string)
     @return the generated dock window (QDockWindow)
     """
     dock = QDockWidget()
     dock.setObjectName(name)
     dock.setFeatures(
         QDockWidget.DockWidgetFeatures(QDockWidget.AllDockWidgetFeatures))
     return dock
예제 #19
0
class GdbIoController(QObject):
    def __init__(self, distributedObjects):
        QObject.__init__(self)
        self.distributedObjects = distributedObjects

        self.gdbioView = GdbIoView(self.distributedObjects.debugController)

        self.distributedObjects.signalProxy.insertDockWidgets.connect(self.insertDockWidgets)

    def insertDockWidgets(self):
        self.gdbioDock = QDockWidget("GDB Console")
        self.gdbioDock.setObjectName("GdbIoView")
        self.gdbioDock.setWidget(self.gdbioView)
        self.distributedObjects.signalProxy.emitAddDockWidget(Qt.BottomDockWidgetArea, self.gdbioDock, True)
예제 #20
0
class InferiorIoController(QObject):
    def __init__(self, distributedObjects):
        QObject.__init__(self)
        self.distributedObjects = distributedObjects

        self.inferiorioView = InferiorIoView(self.distributedObjects.debugController)

        QObject.connect(self.distributedObjects.signalProxy, SIGNAL('insertDockWidgets()'), self.insertDockWidgets)

    def insertDockWidgets(self):
        self.inferiorioDock = QDockWidget("Output")
        self.inferiorioDock.setObjectName("InferiorIoView")
        self.inferiorioDock.setWidget(self.inferiorioView)
        self.distributedObjects.signalProxy.addDockWidget(Qt.BottomDockWidgetArea, self.inferiorioDock, True)
예제 #21
0
class PyIoController(QObject):
    
    def __init__(self, distributed_objects):
        QObject.__init__(self)
        self.distributed_objects = distributed_objects
        
        self.pyioView = PyIoView(self.distributed_objects.debug_controller)
        
        QObject.connect(self.distributed_objects.signal_proxy, SIGNAL('insertDockWidgets()'), self.insertDockWidgets)
        
    def insertDockWidgets(self):
        self.pyioDock = QDockWidget("Python Console")
        self.pyioDock.setObjectName("PyIoView")
        self.pyioDock.setWidget(self.pyioView)
        self.distributed_objects.signal_proxy.addDockWidget(Qt.BottomDockWidgetArea, self.pyioDock, True)
예제 #22
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)
예제 #23
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)
예제 #24
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)
예제 #25
0
class ValueTool:
    def __init__(self, iface):
        # save reference to the QGIS interface
        self.iface = iface

    def initGui(self):
        # create action that will start plugin configuration
        # self.action = QAction(QIcon(":/plugins/valuetool/icon.png"), "Value Tool", self.iface.getMainWindow())
        # self.action.setWhatsThis("Value Tool")
        # QObject.connect(self.action, SIGNAL("activated()"), self.run)
        # # add toolbar button and menu item
        # self.iface.addToolBarIcon(self.action)
        # self.iface.addPluginMenu("Analyses", self.action)
        # # add the tool to select feature
        # self.tool = selectPointTool(self.iface.getMapCanvas(),self.action)

        # create the widget to display information
        self.valuewidget = ValueWidget(self.iface)
        # create the dockwidget with the correct parent and add the valuewidget
        self.valuedockwidget = QDockWidget("Value Tool",
                                           self.iface.mainWindow())
        self.valuedockwidget.setObjectName("Value Tool")
        self.valuedockwidget.setWidget(self.valuewidget)
        QObject.connect(self.valuedockwidget,
                        SIGNAL('visibilityChanged ( bool )'),
                        self.showHideDockWidget)

        self.iface.addDockWidget(Qt.LeftDockWidgetArea, self.valuedockwidget)
        # self.valuewidget.show()
        # ##Qt.AllDockWidgetAreas

    def unload(self):
        self.valuedockwidget.close()
        self.valuewidget.disconnect()
        # remove the dockwidget from iface
        self.iface.removeDockWidget(self.valuedockwidget)
        # remove the plugin menu item and icon
        # self.iface.removePluginMenu("Analyses",self.action)
        # self.iface.removeToolBarIcon(self.action)

    def showHideDockWidget(self):
        if self.valuedockwidget.isVisible(
        ) and self.valuewidget.cbxActive.isChecked():
            state = Qt.Checked
        else:
            state = Qt.Unchecked
        self.valuewidget.changeActive(state)
예제 #26
0
class ValueTool:

    def __init__(self, iface):
        # save reference to the QGIS interface
        self.iface = iface

    def initGui(self):
        # create action that will start plugin configuration
        # self.action = QAction(QIcon(":/plugins/valuetool/icon.png"), "Value Tool", self.iface.getMainWindow())
        # self.action.setWhatsThis("Value Tool")
        # QObject.connect(self.action, SIGNAL("activated()"), self.run)
        # # add toolbar button and menu item
        # self.iface.addToolBarIcon(self.action)
        # self.iface.addPluginMenu("Analyses", self.action)
        # # add the tool to select feature
        # self.tool = selectPointTool(self.iface.getMapCanvas(),self.action)

        # create the widget to display information
        self.valuewidget = ValueWidget(self.iface)
        # create the dockwidget with the correct parent and add the valuewidget
        self.valuedockwidget = QDockWidget("Value Tool", self.iface.mainWindow())
        self.valuedockwidget.setObjectName("Value Tool")
        self.valuedockwidget.setWidget(self.valuewidget)
        QObject.connect(self.valuedockwidget, SIGNAL('visibilityChanged ( bool )'), self.showHideDockWidget)

        self.iface.addDockWidget(Qt.LeftDockWidgetArea, self.valuedockwidget)
        # self.valuewidget.show()
        # ##Qt.AllDockWidgetAreas

    def unload(self):
        self.valuedockwidget.close()
        self.valuewidget.disconnect()
        # remove the dockwidget from iface
        self.iface.removeDockWidget(self.valuedockwidget)
        # remove the plugin menu item and icon
        # self.iface.removePluginMenu("Analyses",self.action)
        # self.iface.removeToolBarIcon(self.action)

    def showHideDockWidget(self):
        if self.valuedockwidget.isVisible() and self.valuewidget.cbxActive.isChecked():
            state = Qt.Checked
        else:
            state = Qt.Unchecked
        self.valuewidget.changeActive(state)
예제 #27
0
class SideBar(QToolBar):
    def __init__(self, parent):
        self.parent = parent
        QToolBar.__init__(self)
        self.setObjectName('sideBar')
        self.parent.addToolBar(Qt.LeftToolBarArea, self)

        self.setIconSize(
            QSize(48, 48))
        self.setMovable(False)

        self.dock = QDockWidget()
        self.dock.setObjectName('sideBarDock')
        self.dock.stack = QStackedWidget()
        self.stack = self.dock.stack
        self.dock.setWidget(self.stack)
        self.parent.addDockWidget(Qt.LeftDockWidgetArea, self.dock)

        self.dock.hide()
예제 #28
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)
예제 #29
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)
예제 #30
0
    def __init__(self):
        super().__init__()

        daq = Traces(args)
        dock_daq = QDockWidget('DAQ', self)
        dock_daq.setWidget(daq)
        dock_daq.setObjectName('DAQ')
        dock_daq.setFeatures(QDockWidget.DockWidgetMovable)
        self.addDockWidget(Qt.TopDockWidgetArea, dock_daq)

        widgets = {
            'daq': daq,
        }
        self.controlpanel = ControlPanel(widgets)
        self.setCentralWidget(self.controlpanel)

        window_geometry = settings.value('window/geometry')
        if window_geometry is not None:
            self.restoreGeometry(window_geometry)
        window_state = settings.value('window/state')
        if window_state is not None:
            self.restoreState(window_state, float(VERSION))
예제 #31
0
class LocalsController(QObject):
    
    def __init__(self, distributed_objects):
        QObject.__init__(self)
        self.distributedObjects = distributed_objects
        
        self.vwFactory = LocalsVWFactory()
        
        self.localsModel = LocalsModel(self, self.distributedObjects)
        self.localsView = LocalsView()
        
        self.localsView.treeView.setModel(self.localsModel)
        self.localsVariableList = VariableList(self.vwFactory, self.distributedObjects)
        
        QObject.connect(self.distributedObjects.signal_proxy, SIGNAL('inferiorHasStopped(PyQt_PyObject)'), self.getLocals)
        QObject.connect(self.distributedObjects.signal_proxy, SIGNAL('insertDockWidgets()'), self.insertDockWidgets)
        QObject.connect(self.distributedObjects.signal_proxy, SIGNAL('cleanupModels()'), self.clearLocals)
        
    def insertDockWidgets(self):
        self.localsDock = QDockWidget("Locals")
        self.localsDock.setObjectName("LocalsView")
        self.localsDock.setWidget(self.localsView)
        self.distributedObjects.signal_proxy.addDockWidget(Qt.BottomDockWidgetArea, self.localsDock, True)
        
    def clearLocals(self):
        # clear lists
        del self.localsVariableList.list[:]
        self.localsModel.clear()

        
    def getLocals(self):
        self.clearLocals()
        self.localsVariableList.addLocals()
        
        for vw in self.localsVariableList.list:
            vw.setParent(self.localsModel.root)
            # add variable to root children
            self.localsModel.root.addChild(vw)
            self.localsModel.addVar(vw)
예제 #32
0
class FileListController(QObject):
    def __init__(self, distributedObjects):
        QObject.__init__(self)
        self.distributedObjects = distributedObjects

        self.fileListModel = FileListModel(self.distributedObjects.debugController, self.distributedObjects.gdb_connector)
        self.fileListView = FileListView(self)

        self.fileListView.treeView.setModel(self.fileListModel)

        self.distributedObjects.signalProxy.insertDockWidgets.connect(self.insertDockWidgets)

    def insertDockWidgets(self):
        self.fileListDock = QDockWidget("Files")
        self.fileListDock.setObjectName("FileListView")
        self.fileListDock.setWidget(self.fileListView)
        self.distributedObjects.signalProxy.emitAddDockWidget(Qt.LeftDockWidgetArea, self.fileListDock, True)

    def fileInFileListViewActivated(self, index):
        item = index.internalPointer()
        filename = item.data(1)
        if len(filename) > 0:
            self.distributedObjects.signalProxy.openFile(filename, 0)
예제 #33
0
class MikiWindow(QMainWindow):
    def __init__(self, settings, parent=None):
        super(MikiWindow, self).__init__(parent)
        self.setObjectName("mikiWindow")
        self.settings = settings
        self.notePath = settings.notePath

        ################ Setup core components ################
        self.notesTree = MikiTree(self)
        self.quickNoteNav = QLineEdit()
        self.notesTab = QWidget()
        self.completer = SlashPleter()
        self.completer.setModel(self.notesTree.model())
        self.quickNoteNav.setCompleter(self.completer)
        self.notesTree.setObjectName("notesTree")
        self.initTree(self.notePath, self.notesTree)
        self.notesTree.sortItems(0, Qt.AscendingOrder)

        self.ix = None
        self.setupWhoosh()

        self.viewedList = QToolBar(self.tr('Recently Viewed'), self)
        self.viewedList.setIconSize(QSize(16, 16))
        self.viewedList.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        self.viewedListActions = []
        self.noteSplitter = QSplitter(Qt.Horizontal)

        self.dockIndex = QDockWidget("Index")
        self.dockSearch = QDockWidget("Search")
        self.searchEdit = QLineEdit()
        self.searchView = MikiSearch(self)
        self.searchTab = QWidget()
        self.dockToc = QDockWidget("TOC")
        self.tocTree = TocTree()
        self.dockAttachment = QDockWidget("Attachment")
        self.attachmentView = AttachmentView(self)

        self.notesEdit = MikiEdit(self)
        self.notesEdit.setObjectName("notesEdit")
        MikiHighlighter(self.notesEdit)
        self.notesView = MikiView(self)

        self.findBar = QToolBar(self.tr('Find'), self)
        self.findBar.setFixedHeight(30)
        self.findEdit = QLineEdit(self.findBar)
        self.checkBox = QCheckBox(self.tr('Match case'), self.findBar)

        self.statusBar = QStatusBar(self)
        self.statusLabel = QLabel(self)

        self.altPressed = False


        ################ Setup actions ################
        self.actions = dict()
        self.setupActions()


        ################ Setup mainwindow ################
        self.setupMainWindow()

        # show changelogs after upgrade mikidown
        if self.settings.version < __version__:
            self.changelogHelp()
            self.settings.qsettings.setValue("version", __version__)


    def setupActions(self):

        # Global Actions
        actTabIndex = self.act(self.tr('Switch to Index Tab'),
            lambda: self.raiseDock(self.dockIndex), 'Ctrl+Shift+I')
        actTabSearch = self.act(self.tr('Switch to Search Tab'),
            lambda: self.raiseDock(self.dockSearch), 'Ctrl+Shift+F')
        self.addAction(actTabIndex)
        self.addAction(actTabSearch)

        ################ Menu Actions ################
        # actions in menuFile
        actionNewPage = self.act(self.tr('&New Page...'),
            self.notesTree.newPage, QKeySequence.New)
        self.actions.update(newPage=actionNewPage)

        actionNewSubpage = self.act(self.tr('New Sub&page...'),
            self.notesTree.newSubpage, 'Ctrl+Shift+N')
        self.actions.update(newSubpage=actionNewSubpage)

        actionImportPage = self.act(self.tr('&Import Page...'), self.importPage)
        self.actions.update(importPage=actionImportPage)

        actionNBSettings = self.act(self.tr('Notebook Set&tings...'), self.notebookSettings)
        self.actions.update(NBSettings=actionNBSettings)

        actionMDSettings = self.act(self.tr('&Mikidown Settings...'), self.mikidownSettings)
        self.actions.update(MDSettings=actionMDSettings)

        actionOpenNotebook = self.act(self.tr('&Open Notebook...'),
            self.openNotebook, QKeySequence.Open)
        self.actions.update(openNotebook=actionOpenNotebook)

        actionReIndex = self.act(self.tr('Re-index'), self.reIndex)
        self.actions.update(reIndex=actionReIndex)

        actionSave = self.act(self.tr('&Save'),
            self.saveCurrentNote, QKeySequence.Save)
        actionSave.setEnabled(False)
        self.actions.update(save=actionSave)

        actionSaveAs = self.act(self.tr('Save &As...'),
            self.saveNoteAs, QKeySequence.SaveAs)
        self.actions.update(saveAs=actionSaveAs)

        actionHtml = self.act(self.tr('to &HTML'), self.notesEdit.saveAsHtml)
        self.actions.update(html=actionHtml)

        actionPrint = self.act(self.tr('&Print'),
            self.printNote, QKeySequence.Print)
        self.actions.update(print_=actionPrint)

        actionRenamePage = self.act(self.tr('&Rename Page...'),
            self.notesTree.renamePage, 'F2')
        self.actions.update(renamePage=actionRenamePage)

        actionDelPage = self.act(self.tr('&Delete Page'),
            self.notesTree.delPageWrapper, QKeySequence.Delete)
        self.actions.update(delPage=actionDelPage)

        actionQuit = self.act(self.tr('&Quit'), self.close, QKeySequence.Quit)
        actionQuit.setMenuRole(QAction.QuitRole)
        self.actions.update(quit=actionQuit)

        # actions in menuEdit
        actionUndo = self.act(self.tr('&Undo'),
            lambda: self.notesEdit.undo(), QKeySequence.Undo)
        actionUndo.setEnabled(False)
        self.notesEdit.undoAvailable.connect(actionUndo.setEnabled)
        self.actions.update(undo=actionUndo)

        actionRedo = self.act(self.tr('&Redo'),
            lambda: self.notesEdit.redo(), QKeySequence.Redo)
        actionRedo.setEnabled(False)
        self.notesEdit.redoAvailable.connect(actionRedo.setEnabled)
        self.actions.update(redo=actionRedo)

        actionFindText = self.act(self.tr('&Find Text'),
            self.findBar.setVisible, QKeySequence.Find, True)
        self.actions.update(findText=actionFindText)

        actionFind = self.act(self.tr('Next'),
            self.findText, QKeySequence.FindNext)
        self.actions.update(find=actionFind)

        actionFindPrev = self.act(self.tr('Previous'),
            lambda: self.findText(back=True), QKeySequence.FindPrevious)
        self.actions.update(findPrev=actionFindPrev)

        actionSortLines = self.act(self.tr('&Sort Lines'), self.sortLines)
        self.actions.update(sortLines=actionSortLines)

        actionQuickNav = self.act(self.tr("&Quick Open Note"),
                        self.quickNoteNav.setFocus, 'Ctrl+G')
        self.addAction(actionQuickNav)

        actionInsertImage = self.act(self.tr('&Insert Attachment'),
            self.notesEdit.insertAttachmentWrapper, 'Ctrl+I')
        actionInsertImage.setEnabled(False)
        self.actions.update(insertImage=actionInsertImage)

        # actions in menuView
        actionEdit = self.act(self.tr('Edit'), self.edit, 'Ctrl+E',
            True, QIcon(':/icons/edit.svg'), 'Edit mode (Ctrl+E)')
        self.actions.update(edit=actionEdit)

        actionSplit = self.act(self.tr('Split'), self.liveView, 'Ctrl+R',
            True, QIcon(':/icons/split.svg'), 'Split mode (Ctrl+R)')
        self.actions.update(split=actionSplit)

        actionFlipEditAndView = self.act(self.tr('Flip Edit and View'),
            self.flipEditAndView)
        actionFlipEditAndView.setEnabled(False)
        self.actions.update(flipEditAndView=actionFlipEditAndView)

        #actionLeftAndRight = self.act(
        #    self.tr('Split into Left and Right'), trig=self.leftAndRight)
        #actionUpAndDown = self.act(
        #    self.tr('Split into Up and Down'), trig=self.upAndDown)
        # self.actionLeftAndRight.setEnabled(False)
        # self.actionUpAndDown.setEnabled(False)

        # actions in menuHelp
        actionReadme = self.act(self.tr('README'), self.readmeHelp)
        self.actions.update(readme=actionReadme)

        actionChangelog = self.act(self.tr('Changelog'), self.changelogHelp)
        self.actions.update(changelog=actionChangelog)

        actionAboutQt = self.act(self.tr('About Qt'), qApp.aboutQt)
        self.actions.update(aboutQt=actionAboutQt)


    def setupMainWindow(self):
        self.resize(800, 600)
        screen = QDesktopWidget().screenGeometry()
        size = self.geometry()
        self.move((
            screen.width()-size.width())/2, (screen.height()-size.height())/2)
        self.setWindowTitle(
            '{} - {}'.format(self.settings.notebookName, __appname__))

        self.viewedList.setFixedHeight(25)
        self.noteSplitter.addWidget(self.notesEdit)
        self.noteSplitter.addWidget(self.notesView)
        mainSplitter = QSplitter(Qt.Vertical)
        mainSplitter.setChildrenCollapsible(False)
        mainSplitter.addWidget(self.viewedList)
        mainSplitter.addWidget(self.noteSplitter)
        mainSplitter.addWidget(self.findBar)
        self.setCentralWidget(mainSplitter)

        self.searchEdit.returnPressed.connect(self.searchNote)
        self.quickNoteNav.returnPressed.connect(self.openFuncWrapper)
        searchLayout = QVBoxLayout()
        searchLayout.addWidget(self.searchEdit)
        searchLayout.addWidget(self.searchView)
        self.searchTab.setLayout(searchLayout)
        self.tocTree.header().close()

        indexLayout = QVBoxLayout(self.notesTab)
        indexLayout.addWidget(self.quickNoteNav)
        indexLayout.addWidget(self.notesTree)

        self.dockIndex.setObjectName("Index")
        self.dockIndex.setWidget(self.notesTab)
        self.dockSearch.setObjectName("Search")
        self.dockSearch.setWidget(self.searchTab)
        self.dockToc.setObjectName("TOC")
        self.dockToc.setWidget(self.tocTree)
        self.dockAttachment.setObjectName("Attachment")
        self.dockAttachment.setWidget(self.attachmentView)

        self.setDockOptions(QMainWindow.VerticalTabs)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.dockIndex)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.dockSearch)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.dockToc)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.dockAttachment)
        self.tabifyDockWidget(self.dockIndex, self.dockSearch)
        self.tabifyDockWidget(self.dockSearch, self.dockToc)
        self.tabifyDockWidget(self.dockToc, self.dockAttachment)
        self.setTabPosition(Qt.LeftDockWidgetArea, QTabWidget.North)
        self.dockIndex.raise_()      # Put dockIndex on top of the tab stack

        menuBar = QMenuBar(self)
        self.setMenuBar(menuBar)
        menuFile = menuBar.addMenu(self.tr('&File'))
        menuEdit = menuBar.addMenu(self.tr('&Edit'))
        menuView = menuBar.addMenu(self.tr('&View'))
        menuHelp = menuBar.addMenu(self.tr('&Help'))
        # menuFile
        menuFile.addAction(self.actions['newPage'])
        menuFile.addAction(self.actions['newSubpage'])
        menuFile.addAction(self.actions['NBSettings'])
        menuFile.addAction(self.actions['MDSettings'])
        menuFile.addAction(self.actions['importPage'])
        menuFile.addAction(self.actions['openNotebook'])
        menuFile.addAction(self.actions['reIndex'])
        menuFile.addSeparator()
        menuFile.addAction(self.actions['save'])
        menuFile.addAction(self.actions['saveAs'])
        menuFile.addAction(self.actions['print_'])
        menuExport = menuFile.addMenu(self.tr('&Export'))
        menuExport.addAction(self.actions['html'])
        menuFile.addSeparator()
        menuFile.addAction(self.actions['renamePage'])
        menuFile.addAction(self.actions['delPage'])
        menuFile.addSeparator()
        menuFile.addAction(self.actions['quit'])
        # menuEdit
        menuEdit.addAction(self.actions['undo'])
        menuEdit.addAction(self.actions['redo'])
        menuEdit.addAction(self.actions['findText'])
        menuEdit.addSeparator()
        menuEdit.addAction(self.actions['sortLines'])
        menuEdit.addAction(self.actions['insertImage'])
        # menuView
        menuView.addAction(self.actions['edit'])
        menuView.addAction(self.actions['split'])
        menuView.addAction(self.actions['flipEditAndView'])
        menuShowHide = menuView.addMenu(self.tr('Show/Hide'))
        menuShowHide.addAction(self.dockIndex.toggleViewAction())
        menuShowHide.addAction(self.dockSearch.toggleViewAction())
        menuShowHide.addAction(self.dockToc.toggleViewAction())
        menuShowHide.addAction(self.dockAttachment.toggleViewAction())
        #menuMode = menuView.addMenu(self.tr('Mode'))
        #menuMode.addAction(self.actionLeftAndRight)
        #menuMode.addAction(self.actionUpAndDown)
        # menuHelp
        menuHelp.addAction(self.actions['readme'])
        menuHelp.addAction(self.actions['changelog'])
        menuHelp.addAction(self.actions['aboutQt'])

        toolBar = QToolBar(self.tr("toolbar"), self)
        toolBar.setObjectName("toolbar")       # needed in saveState()
        toolBar.setIconSize(QSize(16, 16))
        toolBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        self.addToolBar(Qt.TopToolBarArea, toolBar)
        toolBar.addAction(self.actions['edit'])
        toolBar.addAction(self.actions['split'])
        self.findEdit.returnPressed.connect(self.findText)
        self.findBar.addWidget(self.findEdit)
        self.findBar.addWidget(self.checkBox)
        self.findBar.addAction(self.actions['findPrev'])
        self.findBar.addAction(self.actions['find'])
        self.findBar.setVisible(False)
        self.findBar.visibilityChanged.connect(self.findBarVisibilityChanged)

        self.setStatusBar(self.statusBar)
        self.statusBar.addWidget(self.statusLabel, 1)

        self.notesTree.currentItemChanged.connect(
            self.currentItemChangedWrapper)
        self.tocTree.itemClicked.connect(self.tocNavigate)
        self.notesEdit.textChanged.connect(self.noteEditted)

        self.notesEdit.document(
        ).modificationChanged.connect(self.modificationChanged)

        self.updateRecentViewedNotes()
        notes = self.settings.recentViewedNotes()
        if len(notes) != 0:
            item = self.notesTree.pageToItem(notes[0])
            self.notesTree.setCurrentItem(item)

    def openFuncWrapper(self):
        self.openFunction(self.quickNoteNav.text())()

    def setupWhoosh(self):
        # Initialize whoosh index, make sure notePath/.indexdir exists
        indexdir = self.settings.indexdir
        try:
            self.ix = open_dir(indexdir)
        except:
            QDir().mkpath(indexdir)
            self.ix = create_in(indexdir, self.settings.schema)
            # Fork a process to update index, which benefit responsiveness.
            p = Thread(target=self.whoosh_index, args=())
            p.start()


    def restore(self):
        """ Restore saved geometry and state.
            Set the status of side panels in View Menu correspondently.
        """
        if self.settings.geometry:
            self.restoreGeometry(self.settings.geometry)
        if self.settings.windowstate:
            self.restoreState(self.settings.windowstate)

    def initTree(self, notePath, parent):
        ''' When there exist foo.md, foo.mkd, foo.markdown,
            only one item will be shown in notesTree.
        '''
        if not QDir(notePath).exists():
            return
        notebookDir = QDir(notePath)
        notesList = notebookDir.entryInfoList(['*.md', '*.mkd', '*.markdown'],
                                               QDir.NoFilter,
                                               QDir.Name|QDir.IgnoreCase)
        nl = [note.completeBaseName() for note in notesList]
        noduplicate = list(set(nl))
        for name in noduplicate:
            item = QTreeWidgetItem(parent, [name])
            path = notePath + '/' + name
            self.initTree(path, item)

    def updateToc(self):
        ''' TOC is updated in `updateView`
            tocTree fields: [hdrText, hdrPosition, hdrAnchor]
        '''
        root = self.notesTree.currentPage()
        self.tocTree.clear()
        item = QTreeWidgetItem(self.tocTree, [root, '0'])
        curLevel = 0
        for (level, h, p, a) in parseHeaders(self.notesEdit.toPlainText()):
            val = [h, str(p), a]
            if level == curLevel:
                item = QTreeWidgetItem(item.parent(), val)
            elif level < curLevel:
                item = QTreeWidgetItem(item.parent().parent(), val)
                curLevel = level
            else:
                item = QTreeWidgetItem(item, val)
                curLevel = level
        self.tocTree.expandAll()

    def updateAttachmentView(self):
        # Update attachmentView to show corresponding attachments.
        item = self.notesTree.currentItem()
        index = self.attachmentView.model.index(
            self.notesTree.itemToAttachmentDir(item))
        self.attachmentView.setRootIndex(index)

    def openFile(self, filename):
        fh = QFile(filename)
        try:
            if not fh.open(QIODevice.ReadOnly):
                raise IOError(fh.errorString())
        except IOError as e:
            QMessageBox.warning(self, 'Read Error',
                                'Failed to open %s: %s' % (filename, e))
        finally:
            if fh is not None:
                noteBody = QTextStream(fh).readAll()
                fh.close()
                self.notesEdit.setPlainText(noteBody)
                self.notesView.scrollPosition = QPoint(0, 0)
                # self.actionSave.setEnabled(False)
                self.notesEdit.document().setModified(False)
                self.notesView.updateView()
                self.setCurrentNote()
                self.updateRecentViewedNotes()
                #self.statusLabel.setText(noteFullName)

    def currentItemChangedWrapper(self, current, previous):
        if current is None:
            return
        #if previous != None and self.notesTree.pageExists(previous):
        prev = self.notesTree.itemToPage(previous)
        if self.notesTree.pageExists(prev):
            self.saveNote(previous)

        currentFile = self.notesTree.itemToFile(current)
        self.openFile(currentFile)

        # Update attachmentView to show corresponding attachments.
        index = self.attachmentView.model.index(
            self.notesTree.itemToAttachmentDir(current))
        self.attachmentView.setRootIndex(index)

    def tocNavigate(self, current):
        ''' works for notesEdit now '''
        if current is None:
            return
        pos = int(current.text(1))
        link = "file://" + self.notePath + "/#" + current.text(2)
        # Move cursor to END first will ensure
        # header is positioned at the top of visual area.
        self.notesEdit.moveCursor(QTextCursor.End)
        cur = self.notesEdit.textCursor()
        cur.setPosition(pos, QTextCursor.MoveAnchor)
        self.notesEdit.setTextCursor(cur)
        self.notesView.load(QUrl(link))

    def switchNote(self, num):
        if num < len(self.viewedListActions):
            self.viewedListActions[num].trigger()

    def saveCurrentNote(self):
        item = self.notesTree.currentItem()
        self.saveNote(item)

    def saveNote(self, item):
        if self.notesEdit.document().isModified():
            self.notesEdit.document().setModified(False)
        else:
            return
        self.notesEdit.save(item)

    def saveNoteAs(self):
        self.saveCurrentNote()
        fileName = QFileDialog.getSaveFileName(self, self.tr('Save as'), '',
            '(*.md *.mkd *.markdown);;'+self.tr('All files(*)'))
        if fileName == '':
            return
        if not QFileInfo(fileName).suffix():
            fileName += '.md'
        fh = QFile(fileName)
        fh.open(QIODevice.WriteOnly)
        savestream = QTextStream(fh)
        savestream << self.notesEdit.toPlainText()
        fh.close()

    def printNote(self):
        printer = QPrinter(QPrinter.HighResolution)
        printer.setCreator(__appname__ + ' ' + __version__)
        printer.setDocName(self.notesTree.currentItem().text(0))
        printdialog = QPrintDialog(printer, self)
        if printdialog.exec() == QDialog.Accepted:
            self.notesView.print_(printer)

    def noteEditted(self):
        """ Continuously get fired while editing"""
        self.updateToc()
        self.notesView.updateLiveView()

    def modificationChanged(self, changed):
        """ Fired one time: modified or not """
        self.actions['save'].setEnabled(changed)
        name = self.notesTree.currentPage()
        self.statusBar.clearMessage()
        if changed:
            self.statusLabel.setText(name + '*')
        else:
            self.statusLabel.setText(name)

    def importPage(self):
        filename = QFileDialog.getOpenFileName(
            self, self.tr('Import file'), '',
            '(*.md *.mkd *.markdown *.txt);;'+self.tr('All files(*)'))
        if filename == '':
            return
        self.importPageCore(filename)

    def importPageCore(self, filename):
        fh = QFile(filename)
        fh.open(QIODevice.ReadOnly)
        fileBody = QTextStream(fh).readAll()
        fh.close()
        page = QFileInfo(filename).completeBaseName()
        fh = QFile(self.notesTree.pageToFile(page))
        if fh.exists():
            QMessageBox.warning(self, 'Import Error',
                'Page already exists: %s' % page)
            dialog = LineEditDialog(self.notePath, self)
            if dialog.exec_():
                page = dialog.editor.text()
                fh.close()
                fh = QFile(self.notesTree.pageToFile(page))
            else:
                return
        fh.open(QIODevice.WriteOnly)
        savestream = QTextStream(fh)
        savestream << fileBody
        fh.close()
        item = QTreeWidgetItem(self.notesTree, [page])
        self.notesTree.sortItems(0, Qt.AscendingOrder)
        self.notesTree.setCurrentItem(item)

    def openNotebook(self):
        dialog = NotebookListDialog(self)
        if dialog.exec_():
            pass

    def notebookSettings(self):
        dialog = NotebookSettingsDialog(self)
        if dialog.exec_():
            pass

    def mikidownSettings(self):
        dialog = MikidownCfgDialog(self)
        if dialog.exec_():
            pass


    def reIndex(self):
        """ Whoosh index breaks for unknown reasons (sometimes) """
        shutil.rmtree(self.settings.indexdir)
        self.setupWhoosh()

    def act(self, name, trig, shortcut=None, checkable=False,
            icon=None, tooltip=None):
        """ A wrapper to several QAction methods """
        if icon:
            action = QAction(icon, name, self)
        else:
            action = QAction(name, self)
        if shortcut:
            action.setShortcut(QKeySequence(shortcut))
        action.setCheckable(checkable)
        if tooltip:
            action.setToolTip(tooltip)
        action.triggered.connect(trig)
        return action

    def edit(self, viewmode):
        """ Switch between EDIT and VIEW mode. """

        if self.actions['split'].isChecked():
            self.actions['split'].setChecked(False)
        self.notesView.setVisible(not viewmode)
        self.notesEdit.setVisible(viewmode)

        # Gives the keyboard input focus to notesEdit/notesView.
        # Without this, keyboard input may change note text even when
        # notesEdit is invisible.
        if viewmode:
            self.notesEdit.setFocus()
        else:
            self.notesView.setFocus()

        self.saveCurrentNote()
        self.actions['insertImage'].setEnabled(viewmode)
        #self.actionLeftAndRight.setEnabled(True)
        #self.actionUpAndDown.setEnabled(True)

        # Render the note text as it is.
        self.notesView.updateView()

    def liveView(self, viewmode):
        """ Switch between VIEW and LIVE VIEW mode. """

        self.actions['split'].setChecked(viewmode)
        sizes = self.noteSplitter.sizes()
        if self.actions['edit'].isChecked():
            self.actions['edit'].setChecked(False)
            self.notesView.setVisible(viewmode)
            splitSize = [sizes[0]*0.45, sizes[0]*0.55]
        else:
            self.notesEdit.setVisible(viewmode)
            splitSize = [sizes[1]*0.45, sizes[1]*0.55]

        # setFocus for the same reason as in edit(self, viewmode)
        if viewmode:
            self.notesEdit.setFocus()
        else:
            self.notesView.setFocus()

        self.actions['flipEditAndView'].setEnabled(viewmode)
        #self.actionUpAndDown.setEnabled(viewmode)
        self.actions['insertImage'].setEnabled(viewmode)
        self.noteSplitter.setSizes(splitSize)
        self.saveCurrentNote()

        # Render the note text as it is.
        self.notesView.updateView()

    def findBarVisibilityChanged(self, visible):
        self.actions['findText'].setChecked(visible)
        if visible:
            self.findEdit.setFocus(Qt.ShortcutFocusReason)

    def findText(self, back=False):
        flags = 0
        if back:
            flags = QTextDocument.FindBackward
        if self.checkBox.isChecked():
            flags = flags | QTextDocument.FindCaseSensitively
        text = self.findEdit.text()
        if not self.findMain(text, flags):
            if text in self.notesEdit.toPlainText():
                cursor = self.notesEdit.textCursor()
                if back:
                    cursor.movePosition(QTextCursor.End)
                else:
                    cursor.movePosition(QTextCursor.Start)
                self.notesEdit.setTextCursor(cursor)
                self.findMain(text, flags)
        # self.notesView.findText(text, flags)

    def findMain(self, text, flags):
        viewFlags = QWebPage.FindFlags(
            flags) | QWebPage.FindWrapsAroundDocument
        if flags:
            self.notesView.findText(text, viewFlags)
            return self.notesEdit.find(text, flags)
        else:
            self.notesView.findText(text)
            return self.notesEdit.find(text)

    def sortLines(self):
        ''' sort selected lines
            TODO: second sort reverse the order
        '''
        cursor = self.notesEdit.textCursor()
        start = cursor.selectionStart()
        end = cursor.selectionEnd()
        cursor.setPosition(start)
        cursor.movePosition(QTextCursor.StartOfLine)
        cursor.setPosition(end, mode=QTextCursor.KeepAnchor)
        cursor.movePosition(QTextCursor.EndOfLine, mode=QTextCursor.KeepAnchor)
        text = cursor.selectedText()
        lines = text.split('\u2029')      # '\u2029' is the line break
        sortedLines = sorted(lines)
        cursor.insertText('\n'.join(sortedLines))

    def notesEditInFocus(self, e):
        if e.gotFocus:
            self.actions['insertImage'].setEnabled(True)
        # if e.lostFocus:
        #    self.actionInsertImage.setEnabled(False)

        # QWidget.focusInEvent(self,f)

    def searchNote(self):
        """ Sorting criteria: "title > path > content"
            Search matches are organized into html source.
        """

        pattern = self.searchEdit.text()
        if not pattern:
            return
        results = []
        print("Searching using", pattern)
        with self.ix.searcher() as searcher:
            matches = []
            for f in ["title", "path", "content"]:
                queryp = QueryParser(f, self.ix.schema)
                queryp.add_plugin(RegexPlugin())
                # r"pattern" is the desired regex term format
                query = queryp.parse('r"' + pattern + '"')
                ms = searcher.search(query, limit=None) # default limit is 10!
                for m in ms:
                    if not m in matches:
                        matches.append(m)

            for r in matches:
                title = r['title']
                path = r['path']
                term = r.highlights("content")
                results.append([title, path, term])

            html = ""
            for title, path, hi in results:
                html += ("<p><a href='" + path + "'>" + title +
                         "</a><br/><span class='path'>" +
                         path + "</span><br/>" + hi + "</p>")
            self.searchView.setHtml(html)
            print("Finished searching", pattern)

    def whoosh_index(self):
        it = QTreeWidgetItemIterator(
            self.notesTree, QTreeWidgetItemIterator.All)
        print("Starting complete indexing.")
        writer = self.ix.writer()
        while it.value():
            treeItem = it.value()
            name = self.notesTree.itemToPage(treeItem)
            path = os.path.join(self.notesTree.pageToFile(name)).replace(os.sep, '/')
            print(path)
            fileobj = open(path, 'r')
            content = fileobj.read()
            fileobj.close()
            writer.add_document(
                path=name, title=parseTitle(content, name), content=content)
            it += 1
        writer.commit()
        print("Finished completely reindexing.")

    def listItemChanged(self, row):
        if row != -1:
            item = self.searchList.currentItem().data(Qt.UserRole)
            self.notesTree.setCurrentItem(item)
            flags = QWebPage.HighlightAllOccurrences
            self.notesView.findText(self.searchEdit.text(), flags)

    def setCurrentNote(self):
        item = self.notesTree.currentItem()
        name = self.notesTree.itemToPage(item)

        # Current note is inserted to head of list.
        notes = self.settings.recentViewedNotes()
        for f in notes:
            if f == name:
                notes.remove(f)
        notes.insert(0, name)

        recent_notes_n = Mikibook.settings.value('recentNotesNumber',type=int, defaultValue=20)
        if len(notes) > recent_notes_n:
            del notes[recent_notes_n:]
        self.settings.updateRecentViewedNotes(notes)

    def updateRecentViewedNotes(self):
        """ Switching notes will trigger this.
            When Alt pressed, show note number.
        """

        self.viewedList.clear()
        self.viewedListActions = []

        # Check notes exists.
        viewedNotes = self.settings.recentViewedNotes()
        existedNotes = []
        i = 0
        for f in viewedNotes:
            if self.notesTree.pageExists(f):
                existedNotes.append(f)
                names = f.split('/')
                if self.altPressed and i in range(1, 10):
                    action = self.act(names[-1], self.openFunction(f),
                        'Alt+'+str(i), True, ViewedNoteIcon(i), 'Alt+'+str(i))
                else:
                    action = self.act(names[-1], self.openFunction(f),
                        None, True)
                self.viewedListActions.append(action)
                i += 1

        if not self.altPressed:
            self.settings.updateRecentViewedNotes(existedNotes)
        for action in self.viewedListActions:
            self.viewedList.addAction(action)
        if len(self.viewedListActions):
            self.viewedListActions[0].setChecked(True)

    def openFunction(self, name):
        item = self.notesTree.pageToItem(name)
        return lambda: self.notesTree.setCurrentItem(item)

    def raiseDock(self, widget):
        if not widget.isVisible():
            widget.show()
        if widget == self.dockSearch:
            self.searchEdit.setFocus()
        widget.raise_()

    def flipEditAndView(self):
        index = self.noteSplitter.indexOf(self.notesEdit)
        if index == 0:
            self.noteSplitter.insertWidget(1, self.notesEdit)
        else:
            self.noteSplitter.insertWidget(0, self.notesEdit)

    def leftAndRight(self):
        self.liveView(True)
        self.noteSplitter.setOrientation(Qt.Horizontal)
        #self.actionLeftAndRight.setEnabled(False)
        #self.actionUpAndDown.setEnabled(True)

    def upAndDown(self):
        self.liveView(True)
        self.noteSplitter.setOrientation(Qt.Vertical)
        #self.actionUpAndDown.setEnabled(False)
        #self.actionLeftAndRight.setEnabled(True)

    def readmeHelp(self):
        readmeFile = '/usr/share/mikidown/README.mkd'
        if not os.path.exists(readmeFile):
            readmeFile = os.path.join(
                os.path.dirname(os.path.dirname(__file__)), 'README.mkd').replace(os.sep, '/')
        self.importPageCore(readmeFile)

    def changelogHelp(self):
        changeLog = "/usr/share/mikidown/Changelog.md"
        if not os.path.exists(changeLog):
            changeLog = os.path.join(
                os.path.dirname(os.path.dirname(__file__)), 'Changelog.md').replace(os.sep, '/')
        self.importPageCore(changeLog)

    def keyPressEvent(self, event):
        """ When Alt pressed, note number will be shown in viewedList. """
        if event.key() == Qt.Key_Alt:
            self.altPressed = True
            self.updateRecentViewedNotes()
        else:
            QMainWindow.keyPressEvent(self, event)

    def keyReleaseEvent(self, event):
        if event.key() == Qt.Key_Alt:
            self.altPressed = False
            self.updateRecentViewedNotes()
        else:
            QMainWindow.keyPressEvent(self, event)

    def closeEvent(self, event):
        """
            saveGeometry: Saves the current geometry and state for
                          top-level widgets
            saveState: Restores the state of this mainwindow's toolbars
                       and dockwidgets
        """
        self.saveCurrentNote()
        self.settings.saveGeometry(self.saveGeometry())
        self.settings.saveWindowState(self.saveState())
        event.accept()
예제 #34
0
class ComposerWrapper(QObject):
    """
    Embeds custom STDM tools in a QgsComposer instance for managing map-based
    STDM document templates.
    """
    dataSourceSelected = pyqtSignal(str)

    def __init__(self, composerView):
        QObject.__init__(self, composerView)

        self._compView = composerView
        self._stdmTB = self.mainWindow().addToolBar("STDM")
        self._selectMoveAction = None

        #Container for custom editor widgets
        self._widgetMappings = {}

        #Create dock widget for configuring STDM data source
        self._stdmDataSourceDock = QDockWidget(
            QApplication.translate("ComposerWrapper", "STDM Data Source"),
            self.mainWindow())
        self._stdmDataSourceDock.setObjectName("STDMDataSourceDock")
        self._stdmDataSourceDock.setMinimumWidth(300)
        self._stdmDataSourceDock.setFeatures(QDockWidget.DockWidgetMovable
                                             | QDockWidget.DockWidgetClosable)
        self.mainWindow().addDockWidget(Qt.RightDockWidgetArea,
                                        self._stdmDataSourceDock)

        dataSourceWidget = ComposerDataSourceSelector()
        self._stdmDataSourceDock.setWidget(dataSourceWidget)
        self._stdmDataSourceDock.show()

        #Create dock widget for configuring STDM item properties
        self._stdmItemPropDock = QDockWidget(
            QApplication.translate("ComposerWrapper", "STDM data properties"),
            self.mainWindow())
        self._stdmItemPropDock.setObjectName("STDMItemDock")
        self._stdmItemPropDock.setMinimumWidth(300)
        self._stdmItemPropDock.setFeatures(QDockWidget.DockWidgetMovable
                                           | QDockWidget.DockWidgetClosable)
        self.mainWindow().addDockWidget(Qt.RightDockWidgetArea,
                                        self._stdmItemPropDock)
        self._stdmItemPropDock.show()

        if self.itemDock() != None:
            self.mainWindow().tabifyDockWidget(self.itemDock(),
                                               self._stdmItemPropDock)

        if self.atlasDock() != None:
            self.atlasDock().hide()

        if self.generalDock() != None:
            self.generalDock().raise_()

        #Connect signals
        self.composition().itemRemoved.connect(self._onItemRemoved)
        dataSourceWidget.cboDataSource.currentIndexChanged[str].connect(
            self.propagateDataSourceSelection)
        self.composerView().selectedItemChanged.connect(self._onItemSelected)

        #Current template document file
        self._currDocFile = None

    def _removeActions(self):
        """
        Remove inapplicable actions and their corresponding toolbars and menus.
        """
        removeActions = [
            "mActionSaveProject", "mActionNewComposer",
            "mActionDuplicateComposer"
        ]

        composerToolbar = self.composerMainToolBar()
        if composerToolbar != None:
            saveProjectAction = None

            for itemAction in composerToolbar.actions():
                if itemAction.objectName() == "mActionSaveProject":
                    saveProjectAction = itemAction
                    break

            if saveProjectAction != None:
                composerMenu = saveProjectAction.menu()

    def configure(self):
        #Create instances of custom STDM composer item configurations
        for ciConfig in ComposerItemConfig.itemConfigurations:
            ciConfigObj = ciConfig(self)

    def addWidgetMapping(self, uniqueIdentifier, widget):
        """
        Add custom STDM editor widget based on the unique identifier of the composer item
        """
        self._widgetMappings[uniqueIdentifier] = widget

    def widgetMappings(self):
        """
        Returns a dictionary containing uuid values of composer items linked to STDM widgets.
        """
        return self._widgetMappings

    def clearWidgetMappings(self):
        """
        Resets the widget mappings collection.
        """
        self._widgetMappings = {}

    def mainWindow(self):
        """
        Returns the QMainWindow used by the composer view.
        """
        return self._compView.composerWindow()

    def stdmToolBar(self):
        """
        Returns the instance of the STDM toolbar added to the QgsComposer.
        """
        return self._stdmTB

    def composerView(self):
        """
        Returns the composer view.
        """
        return self._compView

    def composition(self):
        """
        Returns the QgsComposition instance used in the composer view.
        """
        return self._compView.composition()

    def composerItemToolBar(self):
        """
        Returns the toolbar containing actions for adding composer items.
        """
        return self.mainWindow().findChild(QToolBar, "mItemToolbar")

    def composerMainToolBar(self):
        """
        Returns the toolbar containing actions for managing templates.
        """
        return self.mainWindow().findChild(QToolBar, "mComposerToolbar")

    def selectMoveAction(self):
        """
        Returns the QAction for selecting or moving composer items.
        """
        if self.composerItemToolBar() != None:
            if self._selectMoveAction == None:
                for itemAction in self.composerItemToolBar().actions():
                    if itemAction.objectName() == "mActionSelectMoveItem":
                        self._selectMoveAction = itemAction
                        break

        return self._selectMoveAction

    def checkedItemAction(self):
        """
        Returns the currently selected composer item action.
        """
        if self.selectMoveAction() != None:
            return self.selectMoveAction().actionGroup().checkedAction()

        return None

    def itemDock(self):
        """
        Get the 'Item Properties' dock widget.
        """
        return self.mainWindow().findChild(QDockWidget, "ItemDock")

    def atlasDock(self):
        """
        Get the 'Atlas generation' dock widget.
        """
        return self.mainWindow().findChild(QDockWidget, "AtlasDock")

    def generalDock(self):
        """
        Get the 'Composition' dock widget.
        """
        return self.mainWindow().findChild(QDockWidget, "CompositionDock")

    def stdmDataSourceDock(self):
        """
        Returns the STDM data source dock widget.
        """
        return self._stdmDataSourceDock

    def stdmItemDock(self):
        """
        Returns the STDM item dock widget.
        """
        return self._stdmItemPropDock

    def documentFile(self):
        """
        Returns the QFile instance associated with the current document. 'None' will be returned for
        new, unsaved documents.
        """
        return self._currDocFile

    def setDocumentFile(self, docFile):
        """
        Sets the document file.
        """
        if not isinstance(docFile, QFile):
            return

        self._currDocFile = docFile

    def selectedDataSource(self):
        """
        Returns the name of the data source specified by the user.
        """
        return self._stdmDataSourceDock.widget().cboDataSource.currentText()

    def selectedDataSourceCategory(self):
        """
        Returns the category (view or table) that the data source belongs to.
        """
        if self.stdmDataSourceDock().widget() != None:
            return self.stdmDataSourceDock().widget().category()

        return ""

    def propagateDataSourceSelection(self, dataSourceName):
        """
        Propagates the signal when a user select a data source. Listening objects can hook on to it.
        """
        self.dataSourceSelected.emit(dataSourceName)

    def loadTemplate(self, filePath):
        """
        Loads a document template into the view and updates the necessary STDM-related controls.
        """
        if not QFile.exists(filePath):
            QMessageBox.critical(self.composerView(), QApplication.translate("OpenTemplateConfig","Open Template Error"), \
                                        QApplication.translate("OpenTemplateConfig","The specified template does not exist."))
            return

        templateFile = QFile(filePath)

        if not templateFile.open(QIODevice.ReadOnly):
            QMessageBox.critical(self.composerView(), QApplication.translate("ComposerWrapper","Open Operation Error"), \
                                            "{0}\n{1}".format(QApplication.translate("ComposerWrapper","Cannot read template file."), \
                                                      templateFile.errorString()
                                                      ))
            return

        templateDoc = QDomDocument()

        if templateDoc.setContent(templateFile):
            #Load items into the composition and configure STDM data controls
            self.composition().loadFromTemplate(templateDoc)
            self.clearWidgetMappings()

            #Load data controls
            composerDS = ComposerDataSource.create(templateDoc)
            self._configureDataControls(composerDS)

            #Load symbol editors
            spatialFieldsConfig = SpatialFieldsConfiguration.create(
                templateDoc)
            self._configureSpatialSymbolEditor(spatialFieldsConfig)

    def saveTemplate(self):
        """
        Creates and saves a new document template.
        """
        #Validate if the user has specified the data source
        if self.selectedDataSource() == "":
            QMessageBox.critical(self.composerView(), QApplication.translate("ComposerWrapper","Error"), \
                                            QApplication.translate("ComposerWrapper","Please specify the " \
                                                                   "data source name for the document composition."))
            return

        #If it is a new unsaved document template then prompt for the document name.
        docFile = self.documentFile()

        if docFile == None:
            docName,ok = QInputDialog.getText(self.composerView(), \
                                              QApplication.translate("ComposerWrapper","Template Name"), \
                                              QApplication.translate("ComposerWrapper","Please enter the template name below"), \
                                              )
            if ok and docName != "":
                templateDir = self._composerTemplatesPath()

                if templateDir == None:
                    QMessageBox.critical(self.composerView(), QApplication.translate("ComposerWrapper","Error"), \
                                            QApplication.translate("ComposerWrapper","Directory for document templates could not be found."))
                    return

                absPath = templateDir + "/" + docName + ".sdt"
                docFile = QFile(absPath)

            else:
                return

        docFileInfo = QFileInfo(docFile)

        if not docFile.open(QIODevice.WriteOnly):
            QMessageBox.critical(self.composerView(), QApplication.translate("ComposerWrapper","Save Operation Error"), \
                                            "{0}\n{1}".format(QApplication.translate("ComposerWrapper","Could not save template file."), \
                                                      docFile.errorString()
                                                      ))
            return

        templateDoc = QDomDocument()
        self._writeXML(templateDoc, docFileInfo.completeBaseName())

        if docFile.write(templateDoc.toByteArray()) == -1:
            QMessageBox.critical(self.composerView(), QApplication.translate("ComposerWrapper","Save Error"), \
                                            QApplication.translate("ComposerWrapper","Could not save template file."))
            return

        docFile.close()
        self.setDocumentFile(docFile)

    def _writeXML(self, xmlDoc, docName):
        """
        Write the template configuration into the XML document.
        """
        #Write default composer configuration
        composerElement = xmlDoc.createElement("Composer")
        composerElement.setAttribute("title", docName)
        composerElement.setAttribute("visible", 1)

        xmlDoc.appendChild(composerElement)

        self.composition().writeXML(composerElement, xmlDoc)

        #Write STDM data field configurations
        dataSourceElement = ComposerDataSource.domElement(self, xmlDoc)
        composerElement.appendChild(dataSourceElement)

        #Write spatial field configurations
        spatialColumnsElement = SpatialFieldsConfiguration.domElement(
            self, xmlDoc)
        dataSourceElement.appendChild(spatialColumnsElement)

    def _configureDataControls(self, composerDataSource):
        """
        Configure the data source and data field controls based on the composer data
        source configuration.
        """
        if self.stdmDataSourceDock().widget() != None:
            #Set data source
            dataSourceWidget = self.stdmDataSourceDock().widget()
            dataSourceWidget.setCategory(composerDataSource.category())
            dataSourceWidget.setSelectedSource(composerDataSource.name())

            #Set data field controls
            for composerId in composerDataSource.dataFieldMappings().reverse:
                #Use composer item id since the uuid is stripped off
                composerItem = self.composition().getComposerItemById(
                    composerId)

                if composerItem != None:
                    compFieldSelector = ComposerFieldSelector(
                        self, composerItem, self.composerView())
                    compFieldSelector.selectFieldName(
                        composerDataSource.dataFieldName(composerId))

                    #Add widget to the collection but now use the current uuid of the composition item
                    self.addWidgetMapping(composerItem.uuid(),
                                          compFieldSelector)

    def _configureSpatialSymbolEditor(self, spatialFieldConfig):
        """
        Configure symbol editor controls.
        """
        if self.stdmDataSourceDock().widget() != None:
            for itemId, spFieldsMappings in spatialFieldConfig.spatialFieldsMapping(
            ).iteritems():
                mapItem = self.composition().getComposerItemById(itemId)

                if mapItem != None:
                    composerSymbolEditor = ComposerSymbolEditor(
                        self, self.composerView())
                    composerSymbolEditor.addSpatialFieldMappings(
                        spFieldsMappings)

                    #Add widget to the collection but now use the current uuid of the composer map
                    self.addWidgetMapping(mapItem.uuid(), composerSymbolEditor)

    def _composerTemplatesPath(self):
        """
        Reads the path of composer templates in the registry.
        """
        regConfig = RegistryConfig()
        keyName = "ComposerTemplates"

        valueCollection = regConfig.read([keyName])

        if len(valueCollection) == 0:
            return None

        else:
            return valueCollection[keyName]

    def _onItemRemoved(self, item):
        """
        Slot raised when a composer item is removed from the scene.
        """
        """
        Code will not work since a QObject instance is returned instead of a QgsComposerItem
        if item.uuid() in self._widgetMappings:
            del self._widgetMappings[item.uuid()]
        """
        pass

    def _onItemSelected(self, item):
        """
        Slot raised when a composer item is selected. Load the corresponding field selector
        if the selection is an STDM data field label.
        QComposerLabel is returned as a QObject in the slot argument hence, we have resorted to 
        capturing the currently selected items in the composition.
        """
        selectedItems = self.composition().selectedComposerItems()

        if len(selectedItems) == 0:
            self._stdmItemPropDock.setWidget(None)

        elif len(selectedItems) == 1:
            composerItem = selectedItems[0]

            if composerItem.uuid() in self._widgetMappings:
                stdmWidget = self._widgetMappings[composerItem.uuid()]

                if stdmWidget == self._stdmItemPropDock.widget():
                    return

                else:
                    self._stdmItemPropDock.setWidget(stdmWidget)

                #Playing it safe in applying the formatting for the editor controls where applicable
                itemFormatter = None
                if isinstance(composerItem, QgsComposerArrow):
                    itemFormatter = LineFormatter()
                elif isinstance(composerItem, QgsComposerLabel):
                    itemFormatter = DataLabelFormatter()
                elif isinstance(composerItem, QgsComposerMap):
                    itemFormatter = MapFormatter()

                if itemFormatter != None:
                    itemFormatter.apply(composerItem, self, True)

            else:
                self._stdmItemPropDock.setWidget(None)

        elif len(selectedItems) > 1:
            self._stdmItemPropDock.setWidget(None)
예제 #35
0
class BreakpointController(QObject):
    def __init__(self, distributedObjects):
        """ init breakpoint controller and members.
        @param distributedObjects: passing distributed objects
        @note There are following signals: \n
            * insertDockWidgets() : necessary for plugin system\n
            * cleanupModels(): clear Breakpoints\n
        """
        QObject.__init__(self)
        self.distributedObjects = distributedObjects

        self._model = BreakpointModel(self.distributedObjects.gdb_connector)
        self.breakpointView = BreakpointView()

        self.breakpointView.breakpointView.setModel(self._model)

        #register with session manager to save breakpoints
        self.distributedObjects.signalProxy.emitRegisterWithSessionManager(self, "Breakpoints")

        QObject.connect(self.distributedObjects.signalProxy, SIGNAL("insertDockWidgets()"), self.insertDockWidgets)
        QObject.connect(self.distributedObjects.signalProxy, SIGNAL("cleanupModels()"), self._model.clearBreakpoints)

    def insertDockWidgets(self):
        """ needed for plugin system"""
        self.breakpointDock = QDockWidget("Breakpoints")
        self.breakpointDock.setObjectName("BreakpointView")
        self.breakpointDock.setWidget(self.breakpointView)
        self.distributedObjects.signalProxy.addDockWidget(Qt.BottomDockWidgetArea, self.breakpointDock, True)

    def insertBreakpoint(self, file_, line):
        """insert a breakpoint in specified file on specified line
        @param file: (string), full name (incl. path) of file where breakpoint should be inserted
        @param line: (integer), line number where breakpoint should be inserted
        @return: (integer), returns the line as number where the breakpoint finally is inserted
        @note sometimes it is not possible for gdb to insert a breakpoint on specified line because the line is
        empty or has no effect. therefore it is necessary to observe the real line number of inserted breakpoint
        """
        return self._model.insertBreakpoint(file_, line)

    def deleteBreakpoint(self, file_, line):
        """deletes a breakpoint in specified file on specified line
        @param file: (string), full name (incl. path) of file
        @param line: (int), line number where breakpoint should be deleted
        """
        self._model.deleteBreakpoint(file_, line)

    def toggleBreakpoint(self, file_, line):
        """ toggles the breakpoint in file file_ with linenumber line
        @param file_: (string), fullname of file
        @param line: (int), linenumber where the breakpoint should be toggled
        """
        return self._model.toggleBreakpoint(file_, line)

    def getBreakpointsFromModel(self):
        """returns a list of all breakpoints in model
        @return breakpoints: (List<ExtendedBreakpoint>), a list of breakpoints
        """
        return self._model.getBreakpoints()

    def setBreakpointsForModel(self, bpList):
        self._model.setBreakpoints(bpList)

    def saveSession(self, xmlHandler):
        """Insert session info to xml file"""
        bpparent = xmlHandler.createNode("Breakpoints")
        for bp in self._model.getBreakpoints():
            xmlHandler.createNode("Breakpoint", bpparent, {"file": bp.file, "line": bp.line})

    def loadSession(self, xmlHandler):
        """load session info to xml file"""
        bpparent = xmlHandler.getNode("Breakpoints")
        if bpparent != None:
            childnodes = bpparent.childNodes()
            for i in range(childnodes.size()):
                attr = xmlHandler.getAttributes(childnodes.at(i))
                self._model.insertBreakpoint(attr["file"], attr["line"])

    def model(self):
        return self._model
예제 #36
0
class TracepointController(QObject):
    def __init__(self, distributedObjects):
        """ init tracepoint controller and members.
        @param distributedObjects: passing distributed objects
        @note There are following signals: \n
            * insertDockWidgets() : necessary for plugin system\n
            * clicked(QModelIndex): if a row in tracepointView is clicked\n
            * cleanupModels(): clear Tracepoints\n
            * runClicked((): clear Tracepoint Data on every click on run button\n
        """

        QObject.__init__(self)
        self.distributedObjects = distributedObjects

        """@var self._model: (TracepointModel), this class provides the model for tracepointView"""
        self._model = TracepointModel(self.distributedObjects)
        """@var self.tracepointView: (TracepointView), this class presents data from _model"""
        self.tracepointView = TracepointView()
        self.tracepointView.tracepointView.setModel(self._model)

        #register with session manager to save Tracepoints
        self.distributedObjects.signalProxy.emitRegisterWithSessionManager(self, "Tracepoints")

        self.distributedObjects.signalProxy.insertDockWidgets.connect(self.insertDockWidgets)
        self.tracepointView.tracepointView.clicked.connect(self.updateWaveforms)
        self.distributedObjects.signalProxy.inferiorStoppedNormally.connect(self.updateWaveforms)
        self.distributedObjects.signalProxy.cleanupModels.connect(self._model.clearTracepoints)
        self.distributedObjects.signalProxy.runClicked.connect(self._model.clearTracepointData)

    def updateWaveforms(self):
        '''update tracepoint waveforms'''
        index = self.tracepointView.getSelectedRow()
        if index != None:
            self._model.selectionMade(index)

    def insertDockWidgets(self):
        """needed for plugin system"""
        self.tracepointDock = QDockWidget("Tracepoints")
        self.tracepointDock.setObjectName("TracepointView")
        self.tracepointDock.setWidget(self.tracepointView)
        self.distributedObjects.signalProxy.emitAddDockWidget(Qt.BottomDockWidgetArea, self.tracepointDock, True)

    def toggleTracepoint(self, file_, line):
        """ toggles the breakpoint in file file_ with linenumber line
        @param file_: (string), fullname of file
        @param line: (int), linenumber where the breakpoint should be toggled
        """
        return self._model.toggleTracepoint(file_, line)

    def getTracepointsFromModel(self):
        """returns a list of tracepoints
        @return tracepoints: a list of tracepoints
        """
        return self._model.getTracepoints()

    def saveSession(self, xmlHandler):
        """Insert session info to xml file"""
        tpparent = xmlHandler.createNode("Tracepoints")
        for tp in self._model.getTracepoints():
            tpnode = xmlHandler.createNode("Tracepoint", tpparent, {"file": tp.file, "line": tp.line})
            for var in tp.wave:
                xmlHandler.createNode("TracepointVariable", tpnode, {"name": var.name})

    def loadSession(self, xmlHandler):
        """load session info to xml file"""
        tpparent = xmlHandler.getNode("Tracepoints")
        if tpparent != None:
            childnodes = tpparent.childNodes()
            for i in range(childnodes.size()):
                attr = xmlHandler.getAttributes(childnodes.at(i))
                self._model.insertTracepoint(attr["file"], attr["line"])

                for j in range(vars.size()):
                    attr = xmlHandler.getAttributes(vars.at(j))
                    self._model.getTracepoints()[i].addVar(attr["name"])

    def model(self):
        return self._model
예제 #37
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_()
예제 #38
0
class MikiWindow(QMainWindow):
    def __init__(self, settings, parent=None):
        super(MikiWindow, self).__init__(parent)
        self.setObjectName("mikiWindow")
        self.settings = settings
        self.notePath = settings.notePath
        lockPath = os.path.join(settings.notebookPath, '.mikidown_lock')
        if not os.path.exists(lockPath):
            self.lockPathFH = os.open(lockPath,
                                      os.O_CREAT | os.O_EXCL | os.O_RDWR)
        ################ Setup core components ################
        self.notesTree = MikiTree(self)
        self.quickNoteNav = QLineEdit()
        self.notesTab = QWidget()
        self.completer = SlashPleter()
        self.completer.setModel(self.notesTree.model())
        self.quickNoteNav.setCompleter(self.completer)
        self.notesTree.setObjectName("notesTree")
        self.initTree(self.notePath, self.notesTree)
        self.notesTree.sortItems(0, Qt.AscendingOrder)

        self.ix = None
        self.setupWhoosh()

        self.viewedList = QToolBar(self.tr('Recently Viewed'), self)
        self.viewedList.setIconSize(QSize(16, 16))
        self.viewedList.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        self.viewedListActions = []
        self.noteSplitter = QSplitter(Qt.Horizontal)

        self.dockIndex = QDockWidget(self.tr("Index"))
        self.dockSearch = QDockWidget(self.tr("Search"))
        self.searchEdit = QLineEdit()
        self.searchView = MikiSearch(self)
        self.searchTab = QWidget()
        self.dockToc = QDockWidget(self.tr("TOC"))
        self.tocTree = TocTree()
        self.dockAttachment = QDockWidget(self.tr("Attachment"))
        self.attachmentView = AttachmentView(self)

        self.notesEdit = MikiEdit(self)
        self.notesEdit.setObjectName(self.tr("notesEdit"))
        self.loadHighlighter()
        self.notesView = MikiView(self)

        self.findBar = QToolBar(self.tr('Find'), self)
        self.findBar.setFixedHeight(30)
        self.findEdit = QLineEdit(self.findBar)
        self.checkBox = QCheckBox(self.tr('Match case'), self.findBar)

        self.statusBar = QStatusBar(self)
        self.statusLabel = QLabel(self)

        self.altPressed = False

        ################ Setup actions ################
        self.actions = dict()
        self.setupActions()

        ################ Setup mainwindow ################
        self.setupMainWindow()

        # show changelogs after upgrade mikidown
        if self.settings.version < __version__ or Mikibook.settings.value(
                "version", defaultValue="0") < __version__:
            self.changelogHelp()
            self.settings.qsettings.setValue("version", __version__)
            Mikibook.settings.setValue("version", __version__)

    def loadHighlighter(self):
        fnt = Mikibook.settings.value('editorFont', defaultValue=None)
        fntsize = Mikibook.settings.value('editorFontSize',
                                          type=int,
                                          defaultValue=12)
        header_scales_font = Mikibook.settings.value('headerScaleFont',
                                                     type=bool,
                                                     defaultValue=True)
        if fnt is not None:
            self.notesEdit.setFontFamily(fnt)
            self.notesEdit.setFontPointSize(fntsize)
        h = MikiHighlighter(parent=self.notesEdit,
                            scale_font_sizes=header_scales_font)
        tw = Mikibook.settings.value('tabWidth', type=int, defaultValue=4)
        qfm = QFontMetrics(h.patterns[0][1].font())
        self.notesEdit.setTabStopWidth(tw * qfm.width(' '))

    def setupActions(self):

        # Global Actions
        actTabIndex = self.act(self.tr('Switch to Index Tab'),
                               lambda: self.raiseDock(self.dockIndex),
                               self.tr('Ctrl+Shift+I'))
        actTabSearch = self.act(self.tr('Switch to Search Tab'),
                                lambda: self.raiseDock(self.dockSearch),
                                self.tr('Ctrl+Shift+F'))
        self.addAction(actTabIndex)
        self.addAction(actTabSearch)

        ################ Menu Actions ################
        # actions in menuFile
        actionNewPage = self.act(self.tr('&New Page...'),
                                 self.notesTree.newPage, QKeySequence.New)
        self.actions.update(newPage=actionNewPage)

        actionNewSubpage = self.act(self.tr('New Sub&page...'),
                                    self.notesTree.newSubpage,
                                    self.tr('Ctrl+Shift+N'))
        self.actions.update(newSubpage=actionNewSubpage)

        actionImportPage = self.act(self.tr('&Import Page...'),
                                    self.importPage)
        self.actions.update(importPage=actionImportPage)

        actionNBSettings = self.act(self.tr('Notebook Set&tings...'),
                                    self.notebookSettings)
        self.actions.update(NBSettings=actionNBSettings)

        actionMDSettings = self.act(self.tr('&Mikidown Settings...'),
                                    self.mikidownSettings)
        self.actions.update(MDSettings=actionMDSettings)

        actionOpenNotebook = self.act(self.tr('&Open Notebook...'),
                                      self.openNotebook, QKeySequence.Open)
        self.actions.update(openNotebook=actionOpenNotebook)

        actionReIndex = self.act(self.tr('Re-index'), self.reIndex)
        self.actions.update(reIndex=actionReIndex)

        actionSave = self.act(self.tr('&Save'), self.saveCurrentNote,
                              QKeySequence.Save)
        actionSave.setEnabled(False)
        self.actions.update(save=actionSave)

        actionSaveAs = self.act(self.tr('Save &As...'), self.saveNoteAs,
                                QKeySequence.SaveAs)
        self.actions.update(saveAs=actionSaveAs)

        actionHtml = self.act(self.tr('to &HTML'), self.notesEdit.saveAsHtml)
        self.actions.update(html=actionHtml)

        actionPrint = self.act(self.tr('&Print'), self.printNote,
                               QKeySequence.Print)
        self.actions.update(print_=actionPrint)

        actionRenamePage = self.act(self.tr('&Rename Page...'),
                                    self.notesTree.renamePage, 'F2')
        self.actions.update(renamePage=actionRenamePage)

        actionDelPage = self.act(self.tr('&Delete Page'),
                                 self.notesTree.delPageWrapper,
                                 QKeySequence.Delete)
        self.actions.update(delPage=actionDelPage)

        actionQuit = self.act(self.tr('&Quit'), self.close, QKeySequence.Quit)
        actionQuit.setMenuRole(QAction.QuitRole)
        self.actions.update(quit=actionQuit)

        # actions in menuEdit
        actionUndo = self.act(self.tr('&Undo'), lambda: self.notesEdit.undo(),
                              QKeySequence.Undo)
        actionUndo.setEnabled(False)
        self.notesEdit.undoAvailable.connect(actionUndo.setEnabled)
        self.actions.update(undo=actionUndo)

        actionRedo = self.act(self.tr('&Redo'), lambda: self.notesEdit.redo(),
                              QKeySequence.Redo)
        actionRedo.setEnabled(False)
        self.notesEdit.redoAvailable.connect(actionRedo.setEnabled)
        self.actions.update(redo=actionRedo)

        actionFindText = self.act(self.tr('&Find Text'),
                                  self.findBar.setVisible, QKeySequence.Find,
                                  True)
        self.actions.update(findText=actionFindText)

        actionFindRepl = self.act(self.tr('Find and Replace'),
                                  FindReplaceDialog(self.notesEdit).open,
                                  QKeySequence.Replace)
        self.actions.update(findRepl=actionFindRepl)

        actionFind = self.act(self.tr('Next'), self.findText,
                              QKeySequence.FindNext)
        self.actions.update(find=actionFind)

        actionFindPrev = self.act(self.tr('Previous'),
                                  lambda: self.findText(back=True),
                                  QKeySequence.FindPrevious)
        self.actions.update(findPrev=actionFindPrev)

        actionSortLines = self.act(self.tr('&Sort Lines'), self.sortLines)
        self.actions.update(sortLines=actionSortLines)

        actionQuickNav = self.act(self.tr("&Quick Open Note"),
                                  self.quickNoteNav.setFocus,
                                  self.tr('Ctrl+G'))
        self.addAction(actionQuickNav)

        actionInsertImage = self.act(self.tr('&Insert Attachment'),
                                     self.notesEdit.insertAttachmentWrapper,
                                     self.tr('Ctrl+I'))
        actionInsertImage.setEnabled(False)
        self.actions.update(insertImage=actionInsertImage)

        # actions in menuView
        QIcon.setThemeName(
            Mikibook.settings.value('iconTheme', QIcon.themeName()))
        #print(QIcon.themeName())
        actionEdit = self.act(self.tr('Edit'), self.edit, self.tr('Ctrl+E'),
                              True, QIcon.fromTheme('document-edit'),
                              self.tr('Edit mode (Ctrl+E)'))
        self.actions.update(edit=actionEdit)

        actionSplit = self.act(self.tr('Split'), self.liveView,
                               self.tr('Ctrl+R'), True,
                               QIcon.fromTheme('view-split-left-right'),
                               self.tr('Split mode (Ctrl+R)'))
        self.actions.update(split=actionSplit)

        actionFlipEditAndView = self.act(self.tr('Flip Edit and View'),
                                         self.flipEditAndView)
        actionFlipEditAndView.setEnabled(False)
        self.actions.update(flipEditAndView=actionFlipEditAndView)

        #actionLeftAndRight = self.act(
        #    self.tr('Split into Left and Right'), trig=self.leftAndRight)
        #actionUpAndDown = self.act(
        #    self.tr('Split into Up and Down'), trig=self.upAndDown)
        # self.actionLeftAndRight.setEnabled(False)
        # self.actionUpAndDown.setEnabled(False)

        # actions in menuHelp
        actionReadme = self.act(self.tr('README'), self.readmeHelp)
        self.actions.update(readme=actionReadme)

        actionChangelog = self.act(self.tr('Changelog'), self.changelogHelp)
        self.actions.update(changelog=actionChangelog)

        actionAboutQt = self.act(self.tr('About Qt'), qApp.aboutQt)
        self.actions.update(aboutQt=actionAboutQt)

    def setupMainWindow(self):
        self.resize(800, 600)
        screen = QDesktopWidget().screenGeometry()
        size = self.geometry()
        self.move((screen.width() - size.width()) / 2,
                  (screen.height() - size.height()) / 2)
        self.setWindowTitle('{} - {}'.format(self.settings.notebookName,
                                             __appname__))

        self.viewedList.setFixedHeight(25)
        self.noteSplitter.addWidget(self.notesEdit)
        self.noteSplitter.addWidget(self.notesView)
        mainSplitter = QSplitter(Qt.Vertical)
        mainSplitter.setChildrenCollapsible(False)
        mainSplitter.addWidget(self.viewedList)
        mainSplitter.addWidget(self.noteSplitter)
        mainSplitter.addWidget(self.findBar)
        self.setCentralWidget(mainSplitter)

        self.searchEdit.returnPressed.connect(self.searchNote)
        self.quickNoteNav.returnPressed.connect(self.openFuncWrapper)
        searchLayout = QVBoxLayout()
        searchLayout.addWidget(self.searchEdit)
        searchLayout.addWidget(self.searchView)
        self.searchTab.setLayout(searchLayout)

        indexLayout = QVBoxLayout(self.notesTab)
        indexLayout.addWidget(self.quickNoteNav)
        indexLayout.addWidget(self.notesTree)

        self.dockIndex.setObjectName("Index")
        self.dockIndex.setWidget(self.notesTab)
        self.dockSearch.setObjectName("Search")
        self.dockSearch.setWidget(self.searchTab)
        self.dockToc.setObjectName("TOC")
        self.dockToc.setWidget(self.tocTree)
        self.dockAttachment.setObjectName("Attachment")
        self.dockAttachment.setWidget(self.attachmentView)

        self.setDockOptions(QMainWindow.VerticalTabs)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.dockIndex)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.dockSearch)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.dockToc)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.dockAttachment)
        self.tabifyDockWidget(self.dockIndex, self.dockSearch)
        self.tabifyDockWidget(self.dockSearch, self.dockToc)
        self.tabifyDockWidget(self.dockToc, self.dockAttachment)
        self.setTabPosition(Qt.LeftDockWidgetArea, QTabWidget.North)
        self.dockIndex.raise_()  # Put dockIndex on top of the tab stack

        menuBar = QMenuBar(self)
        self.setMenuBar(menuBar)
        menuFile = menuBar.addMenu(self.tr('&File'))
        menuEdit = menuBar.addMenu(self.tr('&Edit'))
        menuView = menuBar.addMenu(self.tr('&View'))
        menuHelp = menuBar.addMenu(self.tr('&Help'))
        # menuFile
        menuFile.addAction(self.actions['newPage'])
        menuFile.addAction(self.actions['newSubpage'])
        menuFile.addAction(self.actions['NBSettings'])
        menuFile.addAction(self.actions['MDSettings'])
        menuFile.addAction(self.actions['importPage'])
        menuFile.addAction(self.actions['openNotebook'])
        menuFile.addAction(self.actions['reIndex'])
        menuFile.addSeparator()
        menuFile.addAction(self.actions['save'])
        menuFile.addAction(self.actions['saveAs'])
        menuFile.addAction(self.actions['print_'])
        menuExport = menuFile.addMenu(self.tr('&Export'))
        menuExport.addAction(self.actions['html'])
        menuFile.addSeparator()
        menuFile.addAction(self.actions['renamePage'])
        menuFile.addAction(self.actions['delPage'])
        menuFile.addSeparator()
        menuFile.addAction(self.actions['quit'])
        # menuEdit
        menuEdit.addAction(self.actions['undo'])
        menuEdit.addAction(self.actions['redo'])
        menuEdit.addAction(self.actions['findText'])
        menuEdit.addAction(self.actions['findRepl'])
        menuEdit.addSeparator()
        menuEdit.addAction(self.actions['sortLines'])
        menuEdit.addAction(self.actions['insertImage'])
        # menuView
        menuView.addAction(self.actions['edit'])
        menuView.addAction(self.actions['split'])
        menuView.addAction(self.actions['flipEditAndView'])
        menuShowHide = menuView.addMenu(self.tr('Show/Hide'))
        menuShowHide.addAction(self.dockIndex.toggleViewAction())
        menuShowHide.addAction(self.dockSearch.toggleViewAction())
        menuShowHide.addAction(self.dockToc.toggleViewAction())
        menuShowHide.addAction(self.dockAttachment.toggleViewAction())
        #menuMode = menuView.addMenu(self.tr('Mode'))
        #menuMode.addAction(self.actionLeftAndRight)
        #menuMode.addAction(self.actionUpAndDown)
        # menuHelp
        menuHelp.addAction(self.actions['readme'])
        menuHelp.addAction(self.actions['changelog'])
        menuHelp.addAction(self.actions['aboutQt'])

        toolBar = QToolBar(self.tr("toolbar"), self)
        toolBar.setObjectName("toolbar")  # needed in saveState()
        #toolBar.setIconSize(QSize(16, 16))
        toolBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        self.addToolBar(Qt.TopToolBarArea, toolBar)
        toolBar.addAction(self.actions['edit'])
        toolBar.addAction(self.actions['split'])
        self.findEdit.returnPressed.connect(self.findText)
        self.findBar.addWidget(self.findEdit)
        self.findBar.addWidget(self.checkBox)
        self.findBar.addAction(self.actions['findPrev'])
        self.findBar.addAction(self.actions['find'])
        self.findBar.setVisible(False)
        self.findBar.visibilityChanged.connect(self.findBarVisibilityChanged)

        self.setStatusBar(self.statusBar)
        self.statusBar.addWidget(self.statusLabel, 1)

        self.notesTree.currentItemChanged.connect(
            self.currentItemChangedWrapper)
        self.notesTree.nvwCallback = self.newNoteDisplay
        self.notesTree.nvwtCallback = self.newPlainTextNoteDisplay
        self.tocTree.itemClicked.connect(self.tocNavigate)
        self.notesEdit.textChanged.connect(self.noteEditted)

        self.notesEdit.document().modificationChanged.connect(
            self.modificationChanged)

        self.updateRecentViewedNotes()
        notes = self.settings.recentViewedNotes()
        if len(notes) != 0:
            item = self.notesTree.pageToItem(notes[0])
            self.notesTree.setCurrentItem(item)

    def newNoteDisplay(self, item, anchor=None):
        msn = MikiSepNote(self.settings,
                          item.text(0),
                          self.notesTree.itemToFile(item),
                          plain_text=False,
                          parent=self)
        if anchor:
            msn.note_view.page().mainFrame().scrollToAnchor(anchor)
        msn.show()

    def newPlainTextNoteDisplay(self, item, anchor=None):
        msn = MikiSepNote(self.settings,
                          item.text(0),
                          self.notesTree.itemToFile(item),
                          plain_text=True,
                          parent=self)
        if anchor:
            item = msn.findItemByAnchor(anchor)[0]
            msn.tocNavigate(item)
        msn.show()

    def openFuncWrapper(self):
        self.openFunction(self.quickNoteNav.text())()

    def setupWhoosh(self):
        # Initialize whoosh index, make sure notePath/.indexdir exists
        indexdir = self.settings.indexdir
        try:
            self.ix = open_dir(indexdir)
        except:
            QDir().mkpath(indexdir)
            self.ix = create_in(indexdir, self.settings.schema)
            # Fork a process to update index, which benefit responsiveness.
            p = Thread(target=self.whoosh_index, args=())
            p.start()

    def restore(self):
        """ Restore saved geometry and state.
            Set the status of side panels in View Menu correspondently.
        """
        if self.settings.geometry:
            self.restoreGeometry(self.settings.geometry)
        if self.settings.windowstate:
            self.restoreState(self.settings.windowstate)

    def initTree(self, notePath, parent):
        ''' When there exist foo.md, foo.mkd, foo.markdown,
            only one item will be shown in notesTree.
        '''
        if not QDir(notePath).exists():
            return
        notebookDir = QDir(notePath)
        notesList = notebookDir.entryInfoList(['*.md', '*.mkd', '*.markdown'],
                                              QDir.NoFilter,
                                              QDir.Name | QDir.IgnoreCase)
        nl = [note.completeBaseName() for note in notesList]
        noduplicate = list(set(nl))
        for name in noduplicate:
            item = QTreeWidgetItem(parent, [name])
            path = notePath + '/' + name
            self.initTree(path, item)

    def updateToc(self):
        ''' TOC is updated in `updateView`
            tocTree fields: [hdrText, hdrPosition, hdrAnchor]
        '''
        root = self.notesTree.currentPage()
        strip_math_for_header_parsing = False
        strip_fence_for_header_parsing = False
        if 'asciimathml' in self.settings.extensions:
            strip_math_for_header_parsing = True
        if 'fenced_code' in self.settings.extensions or 'extra' in self.settings.extensions:
            strip_fence_for_header_parsing = True
        self.tocTree.updateToc(
            root,
            parseHeaders(self.notesEdit.toPlainText(),
                         strip_fenced_block=strip_fence_for_header_parsing,
                         strip_ascii_math=strip_math_for_header_parsing))

    def updateAttachmentView(self):
        # Update attachmentView to show corresponding attachments.
        item = self.notesTree.currentItem()
        index = self.attachmentView.model.index(
            self.notesTree.itemToAttachmentDir(item))
        self.attachmentView.setRootIndex(index)

    def openFile(self, filename):
        fh = QFile(filename)
        try:
            if not fh.open(QIODevice.ReadOnly):
                raise IOError(fh.errorString())
        except IOError as e:
            QMessageBox.warning(
                self, self.tr('Read Error'),
                self.tr('Failed to open %s: %s') % (filename, e))
        finally:
            if fh is not None:
                noteBody = QTextStream(fh).readAll()
                fh.close()
                self.notesEdit.setPlainText(noteBody)
                self.notesView.scrollPosition = QPoint(0, 0)
                # self.actionSave.setEnabled(False)
                self.notesEdit.document().setModified(False)
                self.notesView.updateView()
                self.setCurrentNote()
                self.updateRecentViewedNotes()
                #self.statusLabel.setText(noteFullName)

    def currentItemChangedWrapper(self, current, previous):
        if current is None:
            return
        #if previous != None and self.notesTree.pageExists(previous):
        prev = self.notesTree.itemToPage(previous)
        if self.notesTree.pageExists(prev):
            self.saveNote(previous)

        currentFile = self.notesTree.itemToFile(current)
        self.openFile(currentFile)

        # Update attachmentView to show corresponding attachments.
        index = self.attachmentView.model.index(
            self.notesTree.itemToAttachmentDir(current))
        self.attachmentView.setRootIndex(index)

    def tocNavigate(self, current):
        ''' works for notesEdit now '''
        if current is None:
            return
        pos = int(current.text(1))
        link = "file://" + self.notePath + "/#" + current.text(2)
        # Move cursor to END first will ensure
        # header is positioned at the top of visual area.
        self.notesEdit.moveCursor(QTextCursor.End)
        cur = self.notesEdit.textCursor()
        cur.setPosition(pos, QTextCursor.MoveAnchor)
        self.notesEdit.setTextCursor(cur)
        self.notesView.load(QUrl(link))

    def switchNote(self, num):
        if num < len(self.viewedListActions):
            self.viewedListActions[num].trigger()

    def saveCurrentNote(self):
        item = self.notesTree.currentItem()
        self.saveNote(item)

    def saveNote(self, item):
        if self.notesEdit.document().isModified():
            self.notesEdit.document().setModified(False)
        else:
            return
        self.notesEdit.save(item)

    def saveNoteAs(self):
        self.saveCurrentNote()
        fileName = QFileDialog.getSaveFileName(
            self, self.tr('Save as'), '',
            '(*.md *.mkd *.markdown);;' + self.tr('All files(*)'))
        if fileName == '':
            return
        if not QFileInfo(fileName).suffix():
            fileName += '.md'
        fh = QFile(fileName)
        fh.open(QIODevice.WriteOnly)
        savestream = QTextStream(fh)
        savestream << self.notesEdit.toPlainText()
        fh.close()

    def printNote(self):
        printer = QPrinter(QPrinter.HighResolution)
        printer.setCreator(__appname__ + ' ' + __version__)
        printer.setDocName(self.notesTree.currentItem().text(0))
        printdialog = QPrintDialog(printer, self)
        if printdialog.exec() == QDialog.Accepted:
            self.notesView.print_(printer)

    def noteEditted(self):
        """ Continuously get fired while editing"""
        self.updateToc()
        self.notesView.updateLiveView()

    def modificationChanged(self, changed):
        """ Fired one time: modified or not """
        self.actions['save'].setEnabled(changed)
        name = self.notesTree.currentPage()
        self.statusBar.clearMessage()
        if changed:
            self.statusLabel.setText(name + '*')
        else:
            self.statusLabel.setText(name)

    def importPage(self):
        filename = QFileDialog.getOpenFileName(
            self, self.tr('Import file'), '',
            '(*.md *.mkd *.markdown *.txt);;' + self.tr('All files(*)'))
        if filename == '':
            return
        self.importPageCore(filename)

    def importPageCore(self, filename):
        fh = QFile(filename)
        fh.open(QIODevice.ReadOnly)
        fileBody = QTextStream(fh).readAll()
        fh.close()
        page = QFileInfo(filename).completeBaseName()
        fh = QFile(self.notesTree.pageToFile(page))
        if fh.exists():
            QMessageBox.warning(self, self.tr("Import Error"),
                                self.tr("Page already exists: %s") % page)
            dialog = LineEditDialog(self.notePath, self)
            if dialog.exec_():
                page = dialog.editor.text()
                fh.close()
                fh = QFile(self.notesTree.pageToFile(page))
            else:
                return
        fh.open(QIODevice.WriteOnly)
        savestream = QTextStream(fh)
        savestream << fileBody
        fh.close()
        item = QTreeWidgetItem(self.notesTree, [page])
        self.notesTree.sortItems(0, Qt.AscendingOrder)
        self.notesTree.setCurrentItem(item)

    def openNotebook(self):
        dialog = NotebookListDialog(self)
        if dialog.exec_():
            pass

    def notebookSettings(self):
        dialog = NotebookSettingsDialog(self)
        if dialog.exec_():
            pass

    def mikidownSettings(self):
        dialog = MikidownCfgDialog(self)
        if dialog.exec_():
            pass

    def reIndex(self):
        """ Whoosh index breaks for unknown reasons (sometimes) """
        shutil.rmtree(self.settings.indexdir)
        self.setupWhoosh()

    def act(self,
            name,
            trig,
            shortcut=None,
            checkable=False,
            icon=None,
            tooltip=None):
        """ A wrapper to several QAction methods """
        if icon:
            action = QAction(icon, name, self)
        else:
            action = QAction(name, self)
        if shortcut:
            action.setShortcut(QKeySequence(shortcut))
        action.setCheckable(checkable)
        if tooltip:
            action.setToolTip(tooltip)
        action.triggered.connect(trig)
        return action

    def edit(self, viewmode):
        """ Switch between EDIT and VIEW mode. """

        if self.actions['split'].isChecked():
            self.actions['split'].setChecked(False)
        self.notesView.setVisible(not viewmode)
        self.notesEdit.setVisible(viewmode)

        # Gives the keyboard input focus to notesEdit/notesView.
        # Without this, keyboard input may change note text even when
        # notesEdit is invisible.
        if viewmode:
            self.notesEdit.setFocus()
        else:
            self.notesView.setFocus()

        self.saveCurrentNote()
        self.actions['insertImage'].setEnabled(viewmode)
        #self.actionLeftAndRight.setEnabled(True)
        #self.actionUpAndDown.setEnabled(True)

        # Render the note text as it is.
        self.notesView.updateView()

    def liveView(self, viewmode):
        """ Switch between VIEW and LIVE VIEW mode. """

        self.actions['split'].setChecked(viewmode)
        sizes = self.noteSplitter.sizes()
        if self.actions['edit'].isChecked():
            self.actions['edit'].setChecked(False)
            self.notesView.setVisible(viewmode)
            splitSize = [sizes[0] * 0.45, sizes[0] * 0.55]
        else:
            self.notesEdit.setVisible(viewmode)
            splitSize = [sizes[1] * 0.45, sizes[1] * 0.55]

        # setFocus for the same reason as in edit(self, viewmode)
        if viewmode:
            self.notesEdit.setFocus()
        else:
            self.notesView.setFocus()

        self.actions['flipEditAndView'].setEnabled(viewmode)
        #self.actionUpAndDown.setEnabled(viewmode)
        self.actions['insertImage'].setEnabled(viewmode)
        self.noteSplitter.setSizes(splitSize)
        self.saveCurrentNote()

        # Render the note text as it is.
        self.notesView.updateView()

    def findBarVisibilityChanged(self, visible):
        self.actions['findText'].setChecked(visible)
        if visible:
            self.findEdit.setFocus(Qt.ShortcutFocusReason)

    def findText(self, back=False):
        flags = 0
        if back:
            flags = QTextDocument.FindBackward
        if self.checkBox.isChecked():
            flags = flags | QTextDocument.FindCaseSensitively
        text = self.findEdit.text()
        if not self.findMain(text, flags):
            if text in self.notesEdit.toPlainText():
                cursor = self.notesEdit.textCursor()
                if back:
                    cursor.movePosition(QTextCursor.End)
                else:
                    cursor.movePosition(QTextCursor.Start)
                self.notesEdit.setTextCursor(cursor)
                self.findMain(text, flags)
        # self.notesView.findText(text, flags)

    def findMain(self, text, flags):
        viewFlags = QWebPage.FindFlags(
            flags) | QWebPage.FindWrapsAroundDocument
        if flags:
            self.notesView.findText(text, viewFlags)
            return self.notesEdit.find(text, flags)
        else:
            self.notesView.findText(text)
            return self.notesEdit.find(text)

    def sortLines(self):
        ''' sort selected lines
            TODO: second sort reverse the order
        '''
        cursor = self.notesEdit.textCursor()
        start = cursor.selectionStart()
        end = cursor.selectionEnd()
        cursor.setPosition(start)
        cursor.movePosition(QTextCursor.StartOfLine)
        cursor.setPosition(end, mode=QTextCursor.KeepAnchor)
        cursor.movePosition(QTextCursor.EndOfLine, mode=QTextCursor.KeepAnchor)
        text = cursor.selectedText()
        lines = text.split('\u2029')  # '\u2029' is the line break
        sortedLines = sorted(lines)
        cursor.insertText('\n'.join(sortedLines))

    def notesEditInFocus(self, e):
        if e.gotFocus:
            self.actions['insertImage'].setEnabled(True)
        # if e.lostFocus:
        #    self.actionInsertImage.setEnabled(False)

        # QWidget.focusInEvent(self,f)

    def searchNote(self):
        """ Sorting criteria: "title > path > content"
            Search matches are organized into html source.
        """

        pattern = self.searchEdit.text()
        if not pattern:
            return
        results = []
        print("Searching using", pattern)
        with self.ix.searcher() as searcher:
            matches = []
            queryp = QueryParser("content", self.ix.schema)
            #allow escaped qutoes when regex searching
            queryp.add_plugin(
                RegexPlugin(expr=r'r"(?P<text>[^"\\]*(\\.[^"\\]*)*)"'))
            # ~~r"pattern" is the desired regex term format~~ Don't autoforce regexing
            query = queryp.parse(pattern)
            #print("durp durp", query)
            ms = searcher.search(query, limit=None)  # default limit is 10!
            for m in ms:
                #if not m in matches:
                matches.append(m)

            for r in matches:
                title = r['title']
                path = r['path']
                term = r.highlights("content")
                results.append([title, path, term])

            html = ""
            for title, path, hi in results:
                html += ("<p><a href='" + path + "'>" + title +
                         "</a><br/><span class='path'>" + path +
                         "</span><br/>" + hi + "</p>")
            self.searchView.setHtml(html)
            print("Finished searching", pattern)

    def whoosh_index(self):
        it = QTreeWidgetItemIterator(self.notesTree,
                                     QTreeWidgetItemIterator.All)
        print("Starting complete indexing.")
        #writer = self.ix.writer()
        writer = AsyncWriter(self.ix)
        while it.value():
            treeItem = it.value()
            name = self.notesTree.itemToPage(treeItem)
            path = os.path.join(self.notesTree.pageToFile(name)).replace(
                os.sep, '/')
            print(path)
            fileobj = open(path, 'r', encoding='utf-8')
            content = fileobj.read()
            fileobj.close()
            if METADATA_CHECKER.match(
                    content) and 'meta' in self.settings.extensions:
                no_metadata_content = METADATA_CHECKER.sub("",
                                                           content,
                                                           count=1).lstrip()
                self.settings.md.reset().convert(content)
                writer.update_document(
                    path=name,
                    title=parseTitle(content, name),
                    content=no_metadata_content,
                    tags=','.join(self.settings.md.Meta.get('tags',
                                                            [])).strip())
            else:
                writer.add_document(path=name,
                                    title=parseTitle(content, name),
                                    content=content,
                                    tags='')

            it += 1
        writer.commit()
        print("Finished completely reindexing.")

    def listItemChanged(self, row):
        if row != -1:
            item = self.searchList.currentItem().data(Qt.UserRole)
            self.notesTree.setCurrentItem(item)
            flags = QWebPage.HighlightAllOccurrences
            self.notesView.findText(self.searchEdit.text(), flags)

    def setCurrentNote(self):
        item = self.notesTree.currentItem()
        name = self.notesTree.itemToPage(item)

        # Current note is inserted to head of list.
        notes = self.settings.recentViewedNotes()
        for f in notes:
            if f == name:
                notes.remove(f)
        notes.insert(0, name)

        recent_notes_n = Mikibook.settings.value('recentNotesNumber',
                                                 type=int,
                                                 defaultValue=20)
        if len(notes) > recent_notes_n:
            del notes[recent_notes_n:]
        self.settings.updateRecentViewedNotes(notes)

    def updateRecentViewedNotes(self):
        """ Switching notes will trigger this.
            When Alt pressed, show note number.
        """

        self.viewedList.clear()
        self.viewedListActions = []

        # Check notes exists.
        viewedNotes = self.settings.recentViewedNotes()
        existedNotes = []
        i = 0
        for f in viewedNotes:
            if self.notesTree.pageExists(f):
                existedNotes.append(f)
                names = f.split('/')
                if self.altPressed and i in range(1, 10):
                    action = self.act(names[-1], self.openFunction(f),
                                      'Alt+' + str(i), True, ViewedNoteIcon(i),
                                      'Alt+' + str(i))
                else:
                    action = self.act(names[-1], self.openFunction(f), None,
                                      True)
                self.viewedListActions.append(action)
                i += 1

        if not self.altPressed:
            self.settings.updateRecentViewedNotes(existedNotes)
        for action in self.viewedListActions:
            self.viewedList.addAction(action)
        if len(self.viewedListActions):
            self.viewedListActions[0].setChecked(True)

    def openFunction(self, name):
        item = self.notesTree.pageToItem(name)
        return lambda: self.notesTree.setCurrentItem(item)

    def raiseDock(self, widget):
        if not widget.isVisible():
            widget.show()
        if widget == self.dockSearch:
            self.searchEdit.setFocus()
        widget.raise_()

    def flipEditAndView(self):
        index = self.noteSplitter.indexOf(self.notesEdit)
        if index == 0:
            self.noteSplitter.insertWidget(1, self.notesEdit)
        else:
            self.noteSplitter.insertWidget(0, self.notesEdit)

    def leftAndRight(self):
        self.liveView(True)
        self.noteSplitter.setOrientation(Qt.Horizontal)
        #self.actionLeftAndRight.setEnabled(False)
        #self.actionUpAndDown.setEnabled(True)

    def upAndDown(self):
        self.liveView(True)
        self.noteSplitter.setOrientation(Qt.Vertical)
        #self.actionUpAndDown.setEnabled(False)
        #self.actionLeftAndRight.setEnabled(True)

    def readmeHelp(self):
        readmeFile = '/usr/share/mikidown/README.mkd'
        if not os.path.exists(readmeFile):
            readmeFile = os.path.join(
                os.path.dirname(os.path.dirname(__file__)),
                'README.mkd').replace(os.sep, '/')
        self.importPageCore(readmeFile)

    def changelogHelp(self):
        changeLog = "/usr/share/mikidown/Changelog.md"
        if not os.path.exists(changeLog):
            changeLog = os.path.join(
                os.path.dirname(os.path.dirname(__file__)),
                'Changelog.md').replace(os.sep, '/')
        self.importPageCore(changeLog)

    def keyPressEvent(self, event):
        """ When Alt pressed, note number will be shown in viewedList. """
        if event.key() == Qt.Key_Alt:
            self.altPressed = True
            self.updateRecentViewedNotes()
        else:
            QMainWindow.keyPressEvent(self, event)

    def keyReleaseEvent(self, event):
        if event.key() == Qt.Key_Alt:
            self.altPressed = False
            self.updateRecentViewedNotes()
        else:
            QMainWindow.keyPressEvent(self, event)

    def closeEvent(self, event):
        """
            saveGeometry: Saves the current geometry and state for
                          top-level widgets
            saveState: Restores the state of this mainwindow's toolbars
                       and dockwidgets
        """
        self.saveCurrentNote()
        self.ix.close()
        self.notesEdit.ix.close()
        if hasattr(self.notesTree, 'ix'):
            self.notesTree.ix.close()
        self.settings.saveGeometry(self.saveGeometry())
        self.settings.saveWindowState(self.saveState())
        event.accept()
        os.close(self.lockPathFH)
        lockPath = os.path.join(self.settings.notebookPath, '.mikidown_lock')
        os.remove(lockPath)
예제 #39
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
        '''
예제 #40
0
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()
예제 #41
0
class PartirUsoSuelo:
    """QGIS Plugin Implementation."""

    def __init__(self, iface):
        """Constructor.

        :param iface: An interface instance that will be passed to this class
            which provides the hook by which you can manipulate the QGIS
            application at run time.
        :type iface: QgsInterface
        """
        # Save reference to the QGIS interface
        self.iface = iface
        # initialize plugin directory
        self.plugin_dir = os.path.dirname(__file__)
        # initialize locale
        locale = QSettings().value('locale/userLocale')[0:2]
        locale_path = os.path.join(
            self.plugin_dir,
            'i18n',
            'PartirUsoSuelo_{}.qm'.format(locale))

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

            if qVersion() > '4.3.3':
                QCoreApplication.installTranslator(self.translator)

        # Create the dialog (after translation) and keep reference

        """ Creamos el dialogo """
        #self.dlg = PartirUsoSueloDialog()

        """ Creamos el DockWidget (le asignamos tambien al nombre dlg para no tener que modificar el codigo)"""
        self.dockWidget = PartirUsoSueloDockWidget()
        self.dlg = self.dockWidget

        # Declare instance attributes
        self.actions = []
        self.menu = self.tr(u'&PartirUsoSuelo')
        # TODO: We are going to let the user set this up in a future iteration
        self.toolbar = self.iface.addToolBar(u'PartirUsoSuelo')
        self.toolbar.setObjectName(u'PartirUsoSuelo')

        """ Estas linias solo lo tiene el dialogo, el dock no """
        # self.dlg.lineEdit.clear()
        # self.dlg.pushButton.clicked.connect(self.abrire_archivo)

        self.dlg.comboBox.currentIndexChanged.connect(self.habilitar_edicion)
        self.dlg.comboBox_2.currentIndexChanged.connect(self.habilitar_edicion)
        self.dlg.pushButton_iniciar.clicked.connect(self.iniciar_edicion)
        self.dlg.pushButton_finalizar.clicked.connect(self.finalizar_edicion)

    # noinspection PyMethodMayBeStatic
    def tr(self, message):
        """Get the translation for a string using Qt translation API.

        We implement this ourselves since we do not inherit QObject.

        :param message: String for translation.
        :type message: str, QString

        :returns: Translated version of message.
        :rtype: QString
        """
        # noinspection PyTypeChecker,PyArgumentList,PyCallByClass
        return QCoreApplication.translate('PartirUsoSuelo', message)

    def add_action(
            self,
            icon_path,
            text,
            callback,
            enabled_flag=True,
            add_to_menu=True,
            add_to_toolbar=True,
            status_tip=None,
            whats_this=None,
            parent=None):
        """Add a toolbar icon to the toolbar.

        :param icon_path: Path to the icon for this action. Can be a resource
            path (e.g. ':/plugins/foo/bar.png') or a normal file system path.
        :type icon_path: str

        :param text: Text that should be shown in menu items for this action.
        :type text: str

        :param callback: Function to be called when the action is triggered.
        :type callback: function

        :param enabled_flag: A flag indicating if the action should be enabled
            by default. Defaults to True.
        :type enabled_flag: bool

        :param add_to_menu: Flag indicating whether the action should also
            be added to the menu. Defaults to True.
        :type add_to_menu: bool

        :param add_to_toolbar: Flag indicating whether the action should also
            be added to the toolbar. Defaults to True.
        :type add_to_toolbar: bool

        :param status_tip: Optional text to show in a popup when mouse pointer
            hovers over the action.
        :type status_tip: str

        :param parent: Parent widget for the new action. Defaults None.
        :type parent: QWidget

        :param whats_this: Optional text to show in the status bar when the
            mouse pointer hovers over the action.

        :returns: The action that was created. Note that the action is also
            added to self.actions list.
        :rtype: QAction
        """

        icon = QIcon(icon_path)
        action = QAction(icon, text, parent)
        action.triggered.connect(callback)
        action.setEnabled(enabled_flag)

        if status_tip is not None:
            action.setStatusTip(status_tip)

        if whats_this is not None:
            action.setWhatsThis(whats_this)

        if add_to_toolbar:
            self.toolbar.addAction(action)

        if add_to_menu:
            self.iface.addPluginToVectorMenu(
                self.menu,
                action)

        self.actions.append(action)

        return action

    def initGui(self):
        """Create the menu entries and toolbar icons inside the QGIS GUI."""

        icon_path = ':/plugins/PartirUsoSuelo/icon.png'
        self.add_action(
            icon_path,
            text=self.tr(u'Partir Uso Suelo'),
            callback=self.run,
            parent=self.iface.mainWindow())

    def unload(self):
        """Removes the plugin menu item and icon from QGIS GUI."""
        for action in self.actions:
            self.iface.removePluginVectorMenu(
                self.tr(u'&PartirUsoSuelo'),
                action)
            self.iface.removeToolBarIcon(action)
        # remove the toolbar
        del self.toolbar

    def habilitar_edicion(self):

        # Guardamos la capa seleccionada
        indiceLayerCortarSeleccionada = self.dlg.comboBox.currentIndex()
        indiceLayerProcesarSeleccionada = self.dlg.comboBox_2.currentIndex()
        layers = self.iface.legendInterface().layers()
        layerCortarSeleccionada = layers[indiceLayerCortarSeleccionada]
        layerProcesarSeleccionada = layers[indiceLayerProcesarSeleccionada]
        self.vlayer = layerCortarSeleccionada
        self.vlayerProcesar = layerProcesarSeleccionada

        # Habilitamos la edicion
        self.dlg.pushButton_iniciar.setEnabled(True)

    def iniciar_edicion(self):
        self.iface.setActiveLayer(self.vlayer)
        self.listado_features_modificadas = []
        self.listado_features_nuevas = []
        self.connect_signals()
        self.vlayer.startEditing()
        self.iface.actionSplitFeatures().trigger()
        self.dlg.pushButton_iniciar.setEnabled(False)
        self.dlg.pushButton_finalizar.setEnabled(True)

    def finalizar_edicion(self):
        self.vlayer.commitChanges()
        self.dlg.pushButton_iniciar.setEnabled(True)
        self.dlg.pushButton_finalizar.setEnabled(False)

        # Obtenemos la lista de campos
        inFields = self.vlayer.dataProvider().fields()

        # Convert its geometry type enum to a string we can pass to
        # QgsVectorLayer's constructor
        inLayerGeometryType = ['Point', 'Line', 'Polygon'][self.vlayer.geometryType()]

        # Convert its CRS to a string we can pass to QgsVectorLayer's constructor
        inLayerCRS = self.vlayer.crs().authid()

        self.listado_features_final = []

        for feature in self.listado_features_nuevas:

            # Make the output layer
            outLayer = QgsVectorLayer(inLayerGeometryType + '?crs=' + inLayerCRS, \
                                      u'parcela_nueva_id_' + str(feature.id()), \
                                      'memory')

            # changes are only possible when editing the layer
            outLayer.startEditing()
            outLayer.dataProvider().addAttributes(inFields.toList())
            outLayer.dataProvider().addFeatures([feature])
            # outLayer.addFeature(feature, True)

            # commit to stop editing the layer
            outLayer.commitChanges()

            # update layer's extent when new features have been added
            # because change of extent in provider is not propagated to the layer
            outLayer.updateExtents()

            # Add it to the map
            QgsMapLayerRegistry.instance().addMapLayer(outLayer)

            # Realizamos la intersección de la feautre nueva con la capa que se quiere procesar
            # interseccion = processing.runalg("qgis:intersection", self.vlayerProcesar, outLayer, None)
            nombre_interseccion = "interseccion_parcela_" + str(feature.id())
            interseccion = processing.runalg("qgis:intersection", self.vlayerProcesar, outLayer,
                                             "C:\\Temp\\" + nombre_interseccion + ".shp")
            # self.iface.addVectorLayer(interseccion.get("OUTPUT"), nombre_interseccion, "ogr")
            # intersectionLayer = QgsMapLayerRegistry.instance().mapLayersByName(nombre_interseccion)[0]
            layer_intersect = QgsVectorLayer(interseccion.get("OUTPUT"), nombre_interseccion, "ogr")
            layer_intersect.startEditing()

            for feature_intersect in layer_intersect.getFeatures():
                feature_intersect['id_parcela'] = feature.id()
                layer_intersect.updateFeature(feature_intersect)

            layer_intersect.commitChanges()

            # Eliminamos los campos que sobran
            numero_campos_original = self.vlayerProcesar.dataProvider().fields().count()
            numero_campos_intersect = layer_intersect.dataProvider().fields().count()
            lista_ids_campos_eliminar = range(numero_campos_original, numero_campos_intersect)

            layer_intersect.dataProvider().deleteAttributes(lista_ids_campos_eliminar)
            layer_intersect.commitChanges()
            layer_intersect.updateExtents()

            # QgsMapLayerRegistry.instance().addMapLayer(layer_intersect)
            QgsMapLayerRegistry.instance().removeMapLayer(outLayer.id())

            # Añadimos la feature nueva al listado final
            self.listado_features_final.extend(layer_intersect.getFeatures())

        for feature in self.listado_features_modificadas:
            outLayer = QgsVectorLayer(inLayerGeometryType + '?crs=' + inLayerCRS, \
                                      u'parcela_modificada_id_' + str(feature.id()), \
                                      'memory')

            # changes are only possible when editing the layer
            outLayer.startEditing()
            outLayer.dataProvider().addAttributes(inFields.toList())
            outLayer.dataProvider().addFeatures([feature])

            outLayer.commitChanges()
            outLayer.updateExtents()

            QgsMapLayerRegistry.instance().addMapLayer(outLayer)

            nombre_interseccion = "interseccion_parcela_" + str(feature.id())
            interseccion = processing.runalg("qgis:intersection", self.vlayerProcesar, outLayer,
                                             "C:\\Temp\\" + nombre_interseccion + ".shp")
            layer_intersect = QgsVectorLayer(interseccion.get("OUTPUT"), nombre_interseccion, "ogr")

            layer_intersect.startEditing()

            # Eliminamos los campos que sobran
            numero_campos_original = self.vlayerProcesar.dataProvider().fields().count()
            numero_campos_intersect = layer_intersect.dataProvider().fields().count()
            lista_ids_campos_eliminar = range(numero_campos_original, numero_campos_intersect)

            layer_intersect.dataProvider().deleteAttributes(lista_ids_campos_eliminar)
            layer_intersect.commitChanges()
            layer_intersect.updateExtents()

            # QgsMapLayerRegistry.instance().addMapLayer(layer_intersect)
            QgsMapLayerRegistry.instance().removeMapLayer(outLayer.id())

            # Añadimos la feature modificada al listado final
            self.listado_features_final.extend(layer_intersect.getFeatures())

        # Unimos las intersecciones
        nombre_layer_final = self.vlayerProcesar.name() + "_procesado"
        layerFinal = QgsVectorLayer(inLayerGeometryType + '?crs=' + inLayerCRS, \
                                    nombre_layer_final, \
                                    'memory')

        # Obtenemos la lista de campos
        campos = self.vlayerProcesar.dataProvider().fields()

        layerFinal.startEditing()
        layerFinal.dataProvider().addAttributes(campos.toList())
        layerFinal.dataProvider().addFeatures(self.listado_features_final)

        layerFinal.commitChanges()
        layerFinal.updateExtents()

        QgsMapLayerRegistry.instance().addMapLayer(layerFinal)

    def abrire_archivo(self):
        hola = "Hola Mundo!"
        self.dlg.lineEdit.setText(hola)
        # layers = self.iface.legendInterface().layers()
        # layer_list = []
        # for layer in layers:
        #     layer_list.append(layer.name())
        #     iter = layer.getFeatures()
        #     for feature in iter:
        #         geom = feature.geometry()
        #         print "Feature ID %d: " % feature.id()

        # layer = self.iface.activeLayer()
        # if layer != None:
        #     self.vlayer = layer
        #     self.connect_signals()
        #     iter = layer.getFeatures()
        #     for feature in iter:
        #         # retrieve every feature with its geometry and attributes
        #         # fetch geometry
        #         geom = feature.geometry()
        #         print "Feature ID %d: " % feature.id()
        #         print "Area:", geom.area()
        #         print "Perimeter:", geom.length()
        #
        #         # show some information about the feature
        #         if geom.type() == QGis.Point:
        #             x = geom.asPoint()
        #             print "Point: " + str(x)
        #         elif geom.type() == QGis.Line:
        #             x = geom.asPolyline()
        #             print "Line: %d points" % len(x)
        #         elif geom.type() == QGis.Polygon:
        #             x = geom.asPolygon()
        #             numPts = 0
        #             for ring in x:
        #                 numPts += len(ring)
        #             print "Polygon: %d rings with %d points" % (len(x), numPts)
        #         else:
        #             print "Unknown"
        #
        #         # fetch attributes
        #         attrs = feature.attributes()
        #
        # else:
        #     self.dlg.lineEdit.setText("Seleccione una capa para editarla")

    def connect_signals(self):
        self.vlayer.editingStarted.connect(self.editing_started)
        self.vlayer.editingStopped.connect(self.editing_stopped)

    def editing_started(self):
        # # Disable attributes dialog
        # QSettings().setValue(
        #     '/qgis/digitizing/disable_enter_attribute_values_dialog', True)
        self.edit_handler = EditHandler(self.vlayer)

    def editing_stopped(self):
        print('Editing stopped')
        self.listado_features_modificadas = self.edit_handler.get_listado_features_modificadas()
        self.listado_features_nuevas = self.edit_handler.get_listado_features_nuevas()
        self.edit_handler.disconnect_committed_signals()
        self.edit_handler = None

    def clean_up(self):
        QgsMapLayerRegistry.instance().removeMapLayer(self.vlayer.id())
        self.iface.mapCanvas().clearCache()
        self.iface.mapCanvas().refresh()

    def crear_widget(self):
        self._widget_demo = QWidget()
        vbox = QGridLayout(self._foglioNotInLavWidget)
        styleSheet = "QLabel{font: bold italic 'DejaVu Sans'; font:14pt; color: darkGray}"
        self._foglioNotInLavWidget.setStyleSheet(styleSheet)
        self.lblFoglioNotInLav1 = QLabel("Selecciona la capa que quieres cortar", self._foglioNotInLavWidget)
        self.lblFoglioNotInLav2 = QLabel("Selecciona la capa que quieres que se actualice", self._foglioNotInLavWidget)
        vbox.addWidget(self.lblFoglioNotInLav1, 0, 0, Qt.AlignCenter)
        vbox.addWidget(self.lblFoglioNotInLav2, 1, 0, Qt.AlignCenter)
        vbox.addWidget(self.btnApriFoglio, 2, 0, Qt.AlignCenter)
        vbox.addWidget(self.btnCercaFoglio, 3, 0, Qt.AlignCenter)

    def crear_dockwidget(self):
        self.crear_widget()
        nombre = "Widget de prueba"
        self.dockWidget = QDockWidget(nombre)
        self.dockWidget.setObjectName(nombre)
        self.dockWidget.setWidget(self._widget_demo)

        self.iface().removeDockWidget(self.dockWidget)
        self.iface().mainWindow().addDockWidget(Qt.LeftDockWidgetArea, self.dockWidget)
        self.dockWidget.show()

    def run(self):
        """Run method that performs all the real work"""
        # lista_algoritmos = processing.alglist()
        # opciones_interseccion = processing.alghelp("qgis:intersection")

        """ Cargamos el listado de capas en los combobox """
        layers = self.iface.legendInterface().layers()
        layer_list = []
        for layer in layers:
            layer_list.append(layer.name())

        self.dlg.comboBox.addItems(layer_list)
        self.dlg.comboBox_2.addItems(layer_list)

        """ Mostramos el dockWidget """
        self.iface.mainWindow().addDockWidget(Qt.LeftDockWidgetArea, self.dockWidget)
        self.dockWidget.show()

        """ Mostramos el dialogo """
예제 #42
0
class ComposerWrapper(QObject):
    """
    Embeds custom STDM tools in a QgsComposer instance for managing map-based
    STDM document templates.
    """
    dataSourceSelected = pyqtSignal(str)

    def __init__(self, composerView, iface):
        QObject.__init__(self, composerView)

        self._compView = composerView
        self._stdmTB = self.mainWindow().addToolBar("STDM Document Designer")
        self._selectMoveAction = None
        self._iface = iface

        #Container for custom editor widgets
        self._widgetMappings = {}

        #Hide default dock widgets
        if self.itemDock() is not None:
            self.itemDock().hide()

        if self.atlasDock() is not None:
            self.atlasDock().hide()

        if self.generalDock() is not None:
            self.generalDock().hide()

        # Remove default toolbars
        self._remove_composer_toolbar('mAtlasToolbar')

        self._remove_composer_toolbar('mComposerToolbar')

        #Create dock widget for configuring STDM data source
        self._stdmDataSourceDock = QDockWidget(
            QApplication.translate("ComposerWrapper", "STDM Data Source"),
            self.mainWindow())
        self._stdmDataSourceDock.setObjectName("STDMDataSourceDock")
        self._stdmDataSourceDock.setMinimumWidth(300)
        self._stdmDataSourceDock.setFeatures(QDockWidget.DockWidgetMovable
                                             | QDockWidget.DockWidgetClosable)
        self.mainWindow().addDockWidget(Qt.RightDockWidgetArea,
                                        self._stdmDataSourceDock)

        self._dataSourceWidget = ComposerDataSourceSelector()
        self._stdmDataSourceDock.setWidget(self._dataSourceWidget)
        self._stdmDataSourceDock.show()

        #Re-insert dock widgets
        if self.generalDock() is not None:
            self.generalDock().show()

        if self.itemDock() is not None:
            self.itemDock().show()

        #Create dock widget for configuring STDM item properties
        self._stdmItemPropDock = QDockWidget(
            QApplication.translate("ComposerWrapper", "STDM item properties"),
            self.mainWindow())

        self._stdmItemPropDock.setObjectName("STDMItemDock")
        self._stdmItemPropDock.setMinimumWidth(300)
        self._stdmItemPropDock.setFeatures(QDockWidget.DockWidgetMovable
                                           | QDockWidget.DockWidgetClosable)
        self.mainWindow().addDockWidget(Qt.RightDockWidgetArea,
                                        self._stdmItemPropDock)
        self._stdmItemPropDock.show()

        #Re-arrange dock widgets and push up STDM data source dock widget
        if self.generalDock() is not None:
            self.mainWindow().splitDockWidget(self._stdmDataSourceDock,
                                              self.generalDock(), Qt.Vertical)

        if self.itemDock() is not None:
            self.mainWindow().splitDockWidget(self._stdmDataSourceDock,
                                              self.itemDock(), Qt.Vertical)
            if self.generalDock() is not None:
                self.mainWindow().tabifyDockWidget(self.generalDock(),
                                                   self.itemDock())

        if self.itemDock() is not None:
            self.mainWindow().splitDockWidget(self.itemDock(),
                                              self._stdmItemPropDock,
                                              Qt.Vertical)

        #Set focus on composition properties window
        if self.generalDock() is not None:
            self.generalDock().activateWindow()
            self.generalDock().raise_()

        #Connect signals
        self.composition().itemRemoved.connect(self._onItemRemoved)
        self._dataSourceWidget.cboDataSource.currentIndexChanged.connect(
            self.propagateDataSourceSelection)
        self.composerView().selectedItemChanged.connect(self._onItemSelected)

        #Current template document file
        self._currDocFile = None

        #Copy of template document file
        self._copy_template_file = None

        self._selected_item_uuid = unicode()

        self._current_ref_table_index = -1

    @property
    def copy_template_file(self):
        return self._copy_template_file

    @copy_template_file.setter
    def copy_template_file(self, value):
        self._copy_template_file = value

    @property
    def selected_item_uuid(self):
        return self._selected_item_uuid

    @selected_item_uuid.setter
    def selected_item_uuid(self, uuid):
        self._selected_item_uuid = uuid

    @property
    def current_ref_table_index(self):
        return self._current_ref_table_index

    @current_ref_table_index.setter
    def current_ref_table_index(self, value):
        self._current_ref_table_index = value

    def _remove_composer_toolbar(self, object_name):
        """
        Removes toolbars from composer window.
        :param object_name: The object name of the toolbar
        :type object_name: String
        :return: None
        :rtype: NoneType
        """
        composers = self._iface.activeComposers()
        for i in range(len(composers)):
            comp = composers[i].composerWindow()
            widgets = comp.findChildren(QToolBar, object_name)
            for widget in widgets:
                comp.removeToolBar(widget)

    def _removeActions(self):
        """
        Remove inapplicable actions and their corresponding toolbars and menus.
        """
        removeActions = [
            "mActionSaveProject", "mActionNewComposer",
            "mActionDuplicateComposer"
        ]

        composerToolbar = self.composerMainToolBar()
        if composerToolbar != None:
            saveProjectAction = None

            for itemAction in composerToolbar.actions():
                if itemAction.objectName() == "mActionSaveProject":
                    saveProjectAction = itemAction
                    break

            if saveProjectAction != None:
                composerMenu = saveProjectAction.menu()

    def configure(self):
        #Create instances of custom STDM composer item configurations
        for ciConfig in ComposerItemConfig.itemConfigurations:
            ciConfig(self)

    def addWidgetMapping(self, uniqueIdentifier, widget):
        """
        Add custom STDM editor widget based on the unique identifier of the composer item
        """
        self._widgetMappings[uniqueIdentifier] = widget

    def widgetMappings(self):
        """
        Returns a dictionary containing uuid values of composer items linked to STDM widgets.
        """
        return self._widgetMappings

    def clearWidgetMappings(self):
        """
        Resets the widget mappings collection.
        """
        self._widgetMappings = {}

    def mainWindow(self):
        """
        Returns the QMainWindow used by the composer view.
        """
        return self._compView.composerWindow()

    def stdmToolBar(self):
        """
        Returns the instance of the STDM toolbar added to the QgsComposer.
        """
        return self._stdmTB

    def composerView(self):
        """
        Returns the composer view.
        """
        return self._compView

    def composition(self):
        """
        Returns the QgsComposition instance used in the composer view.
        """
        return self._compView.composition()

    def composerItemToolBar(self):
        """
        Returns the toolbar containing actions for adding composer items.
        """
        return self.mainWindow().findChild(QToolBar, "mItemToolbar")

    def composerMainToolBar(self):
        """
        Returns the toolbar containing actions for managing templates.
        """
        return self.mainWindow().findChild(QToolBar, "mComposerToolbar")

    def selectMoveAction(self):
        """
        Returns the QAction for selecting or moving composer items.
        """
        if self.composerItemToolBar() != None:
            if self._selectMoveAction == None:
                for itemAction in self.composerItemToolBar().actions():
                    if itemAction.objectName() == "mActionSelectMoveItem":
                        self._selectMoveAction = itemAction
                        break

        return self._selectMoveAction

    def checkedItemAction(self):
        """
        Returns the currently selected composer item action.
        """
        if self.selectMoveAction() != None:
            return self.selectMoveAction().actionGroup().checkedAction()

        return None

    def itemDock(self):
        """
        Get the 'Item Properties' dock widget.
        """
        return self.mainWindow().findChild(QDockWidget, "ItemDock")

    def atlasDock(self):
        """
        Get the 'Atlas generation' dock widget.
        """
        return self.mainWindow().findChild(QDockWidget, "AtlasDock")

    def generalDock(self):
        """
        Get the 'Composition' dock widget.
        """
        return self.mainWindow().findChild(QDockWidget, "CompositionDock")

    def stdmDataSourceDock(self):
        """
        Returns the STDM data source dock widget.
        """
        return self._stdmDataSourceDock

    def stdmItemDock(self):
        """
        Returns the STDM item dock widget.
        """
        return self._stdmItemPropDock

    def documentFile(self):
        """
        Returns the QFile instance associated with the current document. 'None' will be returned for
        new, unsaved documents.
        """
        return self._currDocFile

    def setDocumentFile(self, docFile):
        """
        Sets the document file.
        """
        if not isinstance(docFile, QFile):
            return

        self._currDocFile = docFile

    def selectedDataSource(self):
        """
        Returns the name of the data source specified by the user.
        """
        row = self._stdmDataSourceDock.widget().cboDataSource.currentIndex()
        table_name = self._stdmDataSourceDock.widget().cboDataSource.itemData(
            row)

        return table_name

    def selected_referenced_table(self):
        """
        :return: Returns the name of currently specified referenced table name.
        :rtype: str
        """
        return self._stdmDataSourceDock.widget().referenced_table_name()

    def selectedDataSourceCategory(self):
        """
        Returns the category (view or table) that the data source belongs to.
        """
        if not self.stdmDataSourceDock().widget() is None:
            return self.stdmDataSourceDock().widget().category()

        return ""

    def propagateDataSourceSelection(self, index):
        """
        Propagates the signal when a user select a data source. Listening objects can hook on to it.
        """
        data_source_name = self._stdmDataSourceDock.widget(
        ).cboDataSource.itemData(index)
        self.dataSourceSelected.emit(data_source_name)

    def composer_items(self):
        """
        :return: Returns a list of custom composer items.
        :rtype: list
        """
        return [
            self.composition().getComposerItemById(uuid)
            for uuid in self._widgetMappings.keys()
            if not self.composition().getComposerItemById(uuid) is None
        ]

    def _clear_composition(self):
        """
        Removes composer items which, otherwise, are causing QGIS to crash
        when loading a subsequent document template.
        """
        items = self.composition().items()

        for c_item in items:
            if isinstance(c_item, QgsComposerItem) and not isinstance(
                    c_item, QgsPaperItem):
                if c_item.uuid() in self._widgetMappings:
                    #Remove corresponding widget as well as reference in the collection
                    del self._widgetMappings[c_item.uuid()]

                self.composition().removeItem(c_item)
                self.composition().itemRemoved.emit(c_item)

                del c_item

        self.composition().undoStack().clear()
        self.composition().itemsModel().clear()

    def create_new_document_designer(self, file_path):
        """
        Creates a new document designer and loads the document template
        defined in file path.
        :param file_path: Path to document template
        :type file_path: str
        """
        if len(self.composerView().items()) == 3:
            self.composerView().composerWindow().close()

        document_designer = self._iface.createNewComposer(
            "STDM Document Designer")

        #Embed STDM customizations
        cw = ComposerWrapper(document_designer, self._iface)
        cw.configure()

        #Load template
        cw.loadTemplate(file_path)

    def loadTemplate(self, filePath):
        """
        Loads a document template into the view and updates the necessary STDM-related composer items.
        """
        if not QFile.exists(filePath):
            QMessageBox.critical(
                self.composerView(),
                QApplication.translate("OpenTemplateConfig",
                                       "Open Template Error"),
                QApplication.translate(
                    "OpenTemplateConfig",
                    "The specified template does not exist."))
            return

        copy_file = filePath.replace('sdt', 'cpy')

        # remove existing copy file
        if QFile.exists(copy_file):
            copy_template = QFile(copy_file)
            copy_template.remove()

        orig_template_file = QFile(filePath)

        self.setDocumentFile(orig_template_file)

        # make a copy of the original
        orig_template_file.copy(copy_file)

        #templateFile = QFile(filePath)

        # work with copy
        templateFile = QFile(copy_file)

        self.copy_template_file = templateFile

        if not templateFile.open(QIODevice.ReadOnly):
            QMessageBox.critical(
                self.composerView(),
                QApplication.translate("ComposerWrapper",
                                       "Open Operation Error"),
                "{0}\n{1}".format(
                    QApplication.translate("ComposerWrapper",
                                           "Cannot read template file."),
                    templateFile.errorString()))
            return

        templateDoc = QDomDocument()

        if templateDoc.setContent(templateFile):
            table_config_collection = TableConfigurationCollection.create(
                templateDoc)
            '''
            First load vector layers for the table definitions in the config
            collection before loading the composition from file.
            '''
            load_table_layers(table_config_collection)

            self.clearWidgetMappings()

            #Load items into the composition and configure STDM data controls
            self.composition().loadFromTemplate(templateDoc)

            #Load data controls
            composerDS = ComposerDataSource.create(templateDoc)

            #Set title by appending template name
            title = QApplication.translate("STDMPlugin",
                                           "STDM Document Designer")

            composer_el = templateDoc.documentElement()
            if not composer_el is None:
                template_name = ""
                if composer_el.hasAttribute("title"):
                    template_name = composer_el.attribute("title", "")
                elif composer_el.hasAttribute("_title"):
                    template_name = composer_el.attribute("_title", "")

                if template_name:
                    win_title = u"{0} - {1}".format(title, template_name)
                    self.mainWindow().setWindowTitle(template_name)

            self._configure_data_controls(composerDS)

            #Load symbol editors
            spatialFieldsConfig = SpatialFieldsConfiguration.create(
                templateDoc)
            self._configureSpatialSymbolEditor(spatialFieldsConfig)

            #Load photo editors
            photo_config_collection = PhotoConfigurationCollection.create(
                templateDoc)
            self._configure_photo_editors(photo_config_collection)

            # Load table editors
            self._configure_table_editors(table_config_collection)

            items = self.composerView().items()
            items = []

            #Load chart property editors
            chart_config_collection = ChartConfigurationCollection.create(
                templateDoc)
            self._configure_chart_editors(chart_config_collection)

            # Load QR code property editors
            qrc_config_collection = QRCodeConfigurationCollection.create(
                templateDoc)
            self._configure_qr_code_editors(qrc_config_collection)

            self._sync_ids_with_uuids()

    def saveTemplate(self):
        """
        Creates and saves a new document template.
        """
        # Validate if the user has specified the data source
        if not self.selectedDataSource():
            QMessageBox.critical(
                self.composerView(),
                QApplication.translate("ComposerWrapper", "Error"),
                QApplication.translate(
                    "ComposerWrapper", "Please specify the "
                    "data source name for the document composition."))
            return

        # Assert if the referenced table name has been set
        if not self.selected_referenced_table():
            QMessageBox.critical(
                self.composerView(),
                QApplication.translate("ComposerWrapper", "Error"),
                QApplication.translate(
                    "ComposerWrapper", "Please specify the "
                    "referenced table name for the selected data source."))
            return

        # If it is a new unsaved document template then prompt for the document name.
        docFile = self.documentFile()

        if docFile is None:
            docName, ok = QInputDialog.getText(
                self.composerView(),
                QApplication.translate("ComposerWrapper", "Template Name"),
                QApplication.translate("ComposerWrapper",
                                       "Please enter the template name below"),
            )

            if not ok:
                return

            if ok and not docName:
                QMessageBox.critical(
                    self.composerView(),
                    QApplication.translate("ComposerWrapper", "Error"),
                    QApplication.translate("ComposerWrapper",
                                           "Please enter a template name!"))
                self.saveTemplate()

            if ok and docName:
                templateDir = self._composerTemplatesPath()

                if templateDir is None:
                    QMessageBox.critical(
                        self.composerView(),
                        QApplication.translate("ComposerWrapper", "Error"),
                        QApplication.translate(
                            "ComposerWrapper",
                            "Directory for document templates cannot not be found."
                        ))

                    return

                absPath = templateDir + "/" + docName + ".sdt"

                #Check if there is an existing document with the same name
                caseInsenDic = CaseInsensitiveDict(documentTemplates())
                if docName in caseInsenDic:
                    result = QMessageBox.warning(
                        self.composerView(),
                        QApplication.translate("ComposerWrapper",
                                               "Existing Template"),
                        u"'{0}' {1}.\nDo you want to replace the "
                        "existing template?".format(
                            docName,
                            QApplication.translate("ComposerWrapper",
                                                   "already exists")),
                        QMessageBox.Yes | QMessageBox.No)

                    if result == QMessageBox.Yes:
                        #Delete the existing template
                        delFile = QFile(absPath)
                        remStatus = delFile.remove()
                        if not remStatus:
                            QMessageBox.critical(
                                self.composerView(),
                                QApplication.translate("ComposerWrapper",
                                                       "Delete Error"),
                                "'{0}' {1}.".format(
                                    docName,
                                    QApplication.translate(
                                        "ComposerWrapper",
                                        "template could not be removed by the system,"
                                        " please remove it manually from the document templates directory."
                                    )))
                            return

                    else:
                        return

                docFile = QFile(absPath)

            else:
                return

        docFileInfo = QFileInfo(docFile)

        if not docFile.open(QIODevice.WriteOnly):
            QMessageBox.critical(
                self.composerView(),
                QApplication.translate("ComposerWrapper",
                                       "Save Operation Error"),
                "{0}\n{1}".format(
                    QApplication.translate("ComposerWrapper",
                                           "Could not save template file."),
                    docFile.errorString()))

            return

        templateDoc = QDomDocument()
        template_name = docFileInfo.completeBaseName()

        # Catch exception raised when writing items' elements
        try:
            self._writeXML(templateDoc, template_name)
        except Exception as exc:
            msg = unicode(exc)
            QMessageBox.critical(
                self.composerView(),
                QApplication.translate("ComposerWrapper", "Save Error"), msg)
            docFile.close()
            docFile.remove()

            return

        if docFile.write(templateDoc.toByteArray()) == -1:
            QMessageBox.critical(
                self.composerView(),
                QApplication.translate("ComposerWrapper", "Save Error"),
                QApplication.translate("ComposerWrapper",
                                       "Could not save template file."))

            return

        else:
            self.mainWindow().setWindowTitle(template_name)

        self.setDocumentFile(docFile)
        docFile.close()

        if self.copy_template_file:
            self.copy_template_file.close()

    def _writeXML(self, xml_doc, doc_name):
        """
        Write the template configuration into the XML document.
        """
        #Write default composer configuration
        composer_element = xml_doc.createElement("Composer")
        composer_element.setAttribute("title", doc_name)
        composer_element.setAttribute("visible", 1)

        xml_doc.appendChild(composer_element)

        self.composition().writeXML(composer_element, xml_doc)

        #Write STDM data field configurations
        dataSourceElement = ComposerDataSource.domElement(self, xml_doc)
        composer_element.appendChild(dataSourceElement)

        #Write spatial field configurations
        spatialColumnsElement = SpatialFieldsConfiguration.domElement(
            self, xml_doc)
        dataSourceElement.appendChild(spatialColumnsElement)

        #Write photo configuration
        photos_element = PhotoConfigurationCollection.dom_element(
            self, xml_doc)
        dataSourceElement.appendChild(photos_element)

        #Write table configuration
        tables_element = TableConfigurationCollection.dom_element(
            self, xml_doc)
        dataSourceElement.appendChild(tables_element)

        #Write chart configuration
        charts_element = ChartConfigurationCollection.dom_element(
            self, xml_doc)
        dataSourceElement.appendChild(charts_element)

        # Write QRCode configuration
        qr_codes_element = QRCodeConfigurationCollection.dom_element(
            self, xml_doc)
        dataSourceElement.appendChild(qr_codes_element)

    def _configure_data_controls(self, composer_data_source):
        """
        Configure the data source and data field controls based on the composer data
        source configuration.
        """
        if not self.stdmDataSourceDock().widget() is None:
            #Set data source
            dataSourceWidget = self.stdmDataSourceDock().widget()
            dataSourceWidget.setCategory(composer_data_source.category())
            dataSourceWidget.setSelectedSource(composer_data_source.name())
            dataSourceWidget.set_referenced_table(
                composer_data_source.referenced_table_name)

            #Set data field controls
            for composerId in composer_data_source.dataFieldMappings().reverse:
                #Use composer item id since the uuid is stripped off
                composerItem = self.composition().getComposerItemById(
                    composerId)

                if not composerItem is None:
                    compFieldSelector = ComposerFieldSelector(
                        self, composerItem, self.composerView())
                    compFieldSelector.selectFieldName(
                        composer_data_source.dataFieldName(composerId))

                    #Add widget to the collection but now use the current uuid of the composition item
                    self.addWidgetMapping(composerItem.uuid(),
                                          compFieldSelector)

    def _configureSpatialSymbolEditor(self, spatial_field_config):
        """
        Configure symbol editor controls.
        """
        if not self.stdmDataSourceDock().widget() is None:
            for item_id, spFieldsMappings in spatial_field_config.spatialFieldsMapping(
            ).iteritems():
                mapItem = self.composition().getComposerItemById(item_id)

                if not mapItem is None:
                    composerSymbolEditor = ComposerSymbolEditor(
                        self, self.composerView())
                    composerSymbolEditor.add_spatial_field_mappings(
                        spFieldsMappings)

                    #Add widget to the collection but now use the current uuid of the composer map
                    self.addWidgetMapping(mapItem.uuid(), composerSymbolEditor)

    def _configure_photo_editors(self, photo_config_collection):
        """
        Creates widgets for editing photo data sources.
        :param photo_config_collection: PhotoConfigurationCollection instance.
        :type photo_config_collection: PhotoConfigurationCollection
        """
        if self.stdmDataSourceDock().widget() is None:
            return

        for item_id, photo_config in photo_config_collection.mapping(
        ).iteritems():
            pic_item = self.composition().getComposerItemById(item_id)

            if not pic_item is None:
                photo_editor = ComposerPhotoDataSourceEditor(
                    self, self.composerView())
                photo_editor.set_configuration(photo_config)

                self.addWidgetMapping(pic_item.uuid(), photo_editor)

    def _configure_chart_editors(self, chart_config_collection):
        """
        Creates widgets for editing chart properties.
        :param chart_config_collection: ChartConfigurationCollection instance.
        :type chart_config_collection: ChartConfigurationCollection
        """
        if self.stdmDataSourceDock().widget() is None:
            return

        for item_id, chart_config in chart_config_collection.mapping(
        ).iteritems():
            chart_item = self.composition().getComposerItemById(item_id)

            if not chart_item is None:
                chart_editor = ComposerChartConfigEditor(
                    self, self.composerView())
                chart_editor.set_configuration(chart_config)

                self.addWidgetMapping(chart_item.uuid(), chart_editor)

    def _configure_table_editors(self, table_config_collection):
        """
        Creates widgets for editing table data sources.
        :param table_config_collection: TableConfigurationCollection instance.
        :type table_config_collection: TableConfigurationCollection
        """
        if self.stdmDataSourceDock().widget() is None:
            return

        for item_id, table_config in table_config_collection.mapping(
        ).iteritems():
            table_item = self.composition().getComposerItemById(item_id)
            if table_item is not None:
                table_editor = ComposerTableDataSourceEditor(
                    self, table_item, self.composerView())

                table_editor.set_configuration(table_config)

                table_editor.ref_table.cbo_ref_table.currentIndexChanged[
                    str].connect(table_editor.set_table_vector_layer)

                self.addWidgetMapping(table_item.uuid(), table_editor)

    def _configure_qr_code_editors(self, qr_code_config_collection):
        """
        Creates widgets for editing QR code properties.
        :param qr_code_config_collection: QRCodeConfigurationCollection instance.
        :type qr_code_config_collection: QRCodeConfigurationCollection
        """
        if self.stdmDataSourceDock().widget() is None:
            return

        for item_id, qrc_config in qr_code_config_collection.mapping(
        ).iteritems():
            qrc_item = self.composition().getComposerItemById(item_id)

            if not qrc_item is None:
                qrc_editor_cls = qr_code_config_collection.editor_type
                qrc_editor = qrc_editor_cls(self, self.composerView())
                qrc_editor.set_configuration(qrc_config)

                self.addWidgetMapping(qrc_item.uuid(), qrc_editor)

    def _sync_ids_with_uuids(self):
        """
        Matches IDs of custom STDM items with the corresponding UUIDs. This
        is applied when loading existing templates so that the saved
        document contains a matching pair of ID and UUID for each composer
        item.
        """
        items = self._widgetMappings.keys()
        for item_uuid in self._widgetMappings.keys():
            item = self.composition().getComposerItemByUuid(item_uuid)
            if not item is None:
                item.setId(item_uuid)

    def _composerTemplatesPath(self):
        """
        Reads the path of composer templates in the registry.
        """
        regConfig = RegistryConfig()
        keyName = "ComposerTemplates"

        valueCollection = regConfig.read([keyName])

        if len(valueCollection) == 0:
            return None

        else:
            return valueCollection[keyName]

    def _onItemRemoved(self, item):
        """
        Slot raised when a composer item is removed from the scene.
        """
        """
        Code will not work since a QObject instance is returned instead of a QgsComposerItem
        if item.uuid() in self._widgetMappings:
            del self._widgetMappings[item.uuid()]
        """
        pass

    def _onItemSelected(self, item):
        """
        Slot raised when a composer item is selected. Load the corresponding field selector
        if the selection is an STDM data field label.
        QComposerLabel is returned as a QObject in the slot argument hence, we have resorted to
        capturing the current selected items in the composition.
        """
        selectedItems = self.composition().selectedComposerItems()

        if len(selectedItems) == 0:
            self._stdmItemPropDock.setWidget(None)

        elif len(selectedItems) == 1:
            composer_item = selectedItems[0]

            if composer_item.uuid() in self._widgetMappings:
                stdmWidget = self._widgetMappings[composer_item.uuid()]

                self.selected_item_uuid = composer_item.uuid()

                if stdmWidget == self._stdmItemPropDock.widget():
                    return
                else:
                    self._stdmItemPropDock.setWidget(stdmWidget)

                #Playing it safe in applying the formatting for the editor controls where applicable
                itemFormatter = None

                if isinstance(stdmWidget, ComposerTableDataSourceEditor):
                    itemFormatter = TableFormatter()

                if isinstance(composer_item, QgsComposerArrow):
                    itemFormatter = LineFormatter()

                elif isinstance(composer_item, QgsComposerLabel):
                    itemFormatter = DataLabelFormatter()

                elif isinstance(composer_item, QgsComposerMap):
                    itemFormatter = MapFormatter()

                elif isinstance(composer_item, QgsComposerPicture):
                    """
                    Use widget attribute to distinguish type i.e.
                    whether it is a photo, graph etc.
                    """
                    editor_widget = self._widgetMappings[composer_item.uuid()]

                    if isinstance(editor_widget,
                                  ComposerPhotoDataSourceEditor):
                        itemFormatter = PhotoFormatter()

                    elif isinstance(editor_widget, ComposerChartConfigEditor):
                        itemFormatter = ChartFormatter()

                    elif isinstance(editor_widget,
                                    QRCodeConfigurationCollection.editor_type):
                        itemFormatter = QRCodeFormatter()

                elif isinstance(composer_item, QgsComposerAttributeTableV2):
                    itemFormatter = TableFormatter()

                if itemFormatter is not None:
                    itemFormatter.apply(composer_item, self, True)

            else:
                self._stdmItemPropDock.setWidget(None)

        elif len(selectedItems) > 1:
            self._stdmItemPropDock.setWidget(None)
예제 #43
0
class DataGraphController(QObject):
    """ the Controller for the DataGraph """

    def __init__(self, distributedObjects):
        """ Constructor <br>
            Creates a DataGraphView, a DataGraphVWFactory and a VariableList <br>
            Listens to the following Signals: SignalProxy::insertDockWidgets() and SignalProxy::cleanupModels()
        @param distributedObjects    distributedobjects.DistributedObjects, the DistributedObjects-Instance
        """
        QObject.__init__(self)

        # controllers
        ## @var distributedObjects
        # distributedobjects.DistributedObjects, the DistributedObjects-Instance
        self.distributedObjects = distributedObjects
        ## @var signalProxy
        # signalproxy.SignalProxy, the SignalProxy-Instance from the DistributedObjects
        self.signalProxy = distributedObjects.signalProxy
        ## @var debugController
        # debugcontroller.DebugController, the DebugController-Instance from the DistributedObjects
        self.debugController = distributedObjects.debugController
        ## @var variablePool
        # variables.variablepool.VariablePool, the variablePool-Instance from the DistributedObjects
        self.variablePool = distributedObjects.variablePool

        # views
        ## @var data_graph_view
        # datagraph.datagraphview.DataGraphView, private, self-created DataGraphView <br>
        # GUI-Element that shows the DataGraphView
        self.data_graph_view = DataGraphView(None, self)

        # models
        ## @var vwFactory
        # datagraph.datagraphvwfactory.DataGraphVWFactory, private, self-created DataGraphVWFactory
        self.vwFactory = DataGraphVWFactory(self.distributedObjects)
        ## @var variableList
        # variables.variablelist.VariableList, private, self-created VariableList
        self.variableList = VariableList(self.vwFactory, self.distributedObjects)

        self.pointerList = []

        #register with session manager to save Graph
        self.signalProxy.emitRegisterWithSessionManager(self, "Graph")

        # connect signals
        #QObject.connect(self.variableList, SIGNAL('reset()'), self.repaintDataGraph)
        QObject.connect(self.signalProxy, SIGNAL('insertDockWidgets()'), self.insertDockWidgets)
        QObject.connect(self.signalProxy, SIGNAL('cleanupModels()'), self.clearDataGraph)

    def insertDockWidgets(self):
        """ adds the Datagraph-DockWidget to the GUI <br>
            this function is connected to the signal SignalProxy::insertDockWidgets() """
        self.dataGraphDock = QDockWidget("Graph")
        self.dataGraphDock.setObjectName("DataGraphView")
        self.dataGraphDock.setWidget(self.data_graph_view)
        self.signalProxy.addDockWidget(Qt.LeftDockWidgetArea, self.dataGraphDock, True)

    def addWatch(self, watch, xPos=0, yPos=0):
        """ adds the Variable watch to the VariableList and its wrapper to the DataGraph
        @param watch    variables.variable.Variable, the Variable to watch to add
        @param xPos     Integer, the X-Coordinate of the Position where to add the Variable
        @param yPos     Integer, the Y-Coordinate of the Position where to add the Variable
        """
        varWrapper = self.variableList.addVarByName(watch)
        self.addVar(varWrapper, xPos, yPos, False)
        return varWrapper

    def addVar(self, varWrapper, xPos=0, yPos=0, addVarToList=True):
        """ adds the given VariableWrapper varWrapper to the DataGraph and - if addVarToList is true -
            also to the VariableList
        @param varWrapper      variables.variablewrapper.VariableWrapper, the VariableWrapper to add
        @param xPos            Integer, the X-Coordinate of the Position where to add the VariableWrapper
        @param yPos            Integer, the Y-Coordinate of the Position where to add the VariableWrapper
        @param addVarToList    Boolean, tells if varWrapper should be added to the VariableList too
        """
        varWrapper.createView()
        try:
            varWrapper.getView().render()
        except:
            from mako import exceptions
            logging.error("Caught exception while rendering template: %s", exceptions.text_error_template().render())
        varWrapper.setXPos(xPos)
        varWrapper.setYPos(yPos)
        self.data_graph_view.addItem(varWrapper.getView())
        if addVarToList:
            self.variableList.addVar(varWrapper)
        QObject.connect(varWrapper, SIGNAL('replace(PyQt_PyObject, PyQt_PyObject)'), self.replaceVariable)

    def replaceVariable(self, pendingVar, newVar):
        """ replaces existing variable in list with new one
        @param pendingVar    variables.variable.Variable, the pending Variable to replace with newVar
        @param newVar        variables.variable.Variable, the new Variable pendingVar is replaced with
        """
        self.removeVar(pendingVar)
        newVW = newVar.makeWrapper(self.vwFactory)
        self.addVar(newVW, pendingVar.getXPos(), pendingVar.getYPos())
        #for pointer in pendingVar.getView().getIncomingPointers():
        #    self.addPointer(pointer.getFromView(), newVW.getView())
        #for pointer in pendingVar.getView().getOutgoingPointers():
        #    self.addPointer(newVW.getView(), pointer.getToView())

    def removeVar(self, varWrapper):
        """ removes the given varWrapper from the DataGraphView and the PointerList
        @param varWrapper    variables.variablewrapper.VariableWrapper, the VariableWrapper to remove
        """
        self.variableList.removeVar(varWrapper)
        self.data_graph_view.removeItem(varWrapper.getView())

    def addPointer(self, fromView, toView):
        """ fromView and toView are QGraphicsWebViews
        @param fromView  datagraph.htmlvariableview.HtmlVariableView, starting point of the Pointer
        @param toView    datagraph.htmlvariableview.HtmlVariableView, end point of the Pointer
        """
        pointer = Pointer(None, fromView, toView, self.distributedObjects)
        self.data_graph_view.addItem(pointer)
        self.pointerList.append(pointer)

    def removePointer(self, pointer):
        """ removes the given pointer from the DataGraphView and the PointerList
        @param pointer    datagraph.pointer.Pointer, pointer to remove
        """
        self.data_graph_view.removeItem(pointer)
        self.pointerList.remove(pointer)

    def clearDataGraph(self):
        """ clears the DataGraphView and the VariableList <br>
            this function is connected to the signal SignalProxy::cleanupModels()
        """
        self.variableList.clear()
        self.data_graph_view.clear()

    def saveSession(self, xmlHandler):
        """ Insert session info to xml file
        @param xmlHandler    sessionmanager.XmlHandler, handler to write to the session-xml-file
        """
        dgWatches = xmlHandler.createNode("GraphWatches")
        for vw in self.variableList:
            xmlHandler.createNode("Watch", dgWatches, {'expression': vw.getExp(), 'xPos': vw.getXPos(), 'yPos': vw.getYPos()})
        #dgPointers = xmlHandler.createNode("Pointers")
        #for pointer in self.pointerList:
        #    xmlHandler.createNode("Pointer", dgPointers, { 'expFrom': pointer.fromView.var.getExp(), 'expTo': pointer.toView.var.getExp() })

    def loadSession(self, xmlHandler):
        """ load session info to xml file
        @param xmlHandler    sessionmanager.XmlHandler, handler to read from the session-xml-file
        """
        dgParent = xmlHandler.getNode("GraphWatches")
        if dgParent != None:
            childnodes = dgParent.childNodes()
            for i in range(childnodes.size()):
                attr = xmlHandler.getAttributes(childnodes.at(i))
                self.addWatch(attr["expression"], int(attr["xPos"]), int(attr["yPos"]))
예제 #44
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)
예제 #45
0
파일: ui.py 프로젝트: bindx/EE-Book
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)
예제 #46
0
class ComposerWrapper(QObject):
    """
    Embeds custom STDM tools in a QgsComposer instance for managing map-based
    STDM document templates.
    """
    dataSourceSelected = pyqtSignal(str)
    
    def __init__(self, composerView, iface):
        QObject.__init__(self, composerView)
        
        self._compView = composerView
        self._stdmTB = self.mainWindow().addToolBar("STDM")
        self._selectMoveAction = None
        self._iface = iface
        
        #Container for custom editor widgets
        self._widgetMappings = {}

        #Hide default dock widgets
        if not self.itemDock() is None:
            self.itemDock().hide()

        if not self.atlasDock() is None:
            self.atlasDock().hide()

        if not self.generalDock() is None:
            self.generalDock().hide()
        
        #Create dock widget for configuring STDM data source
        self._stdmDataSourceDock = QDockWidget(
            QApplication.translate("ComposerWrapper","STDM Data Source"),
            self.mainWindow())
        self._stdmDataSourceDock.setObjectName("STDMDataSourceDock")
        self._stdmDataSourceDock.setMinimumWidth(300)
        self._stdmDataSourceDock.setFeatures(QDockWidget.DockWidgetMovable|QDockWidget.DockWidgetClosable)
        self.mainWindow().addDockWidget(Qt.RightDockWidgetArea,
                                        self._stdmDataSourceDock)
        
        self._dataSourceWidget = ComposerDataSourceSelector()
        self._stdmDataSourceDock.setWidget(self._dataSourceWidget)
        self._stdmDataSourceDock.show()

        #Re-insert dock widgets
        if not self.generalDock() is None:
            self.generalDock().show()

        if not self.itemDock() is None:
            self.itemDock().show()
        
        #Create dock widget for configuring STDM item properties
        self._stdmItemPropDock = QDockWidget(
            QApplication.translate("ComposerWrapper","STDM item properties"),
            self.mainWindow())

        self._stdmItemPropDock.setObjectName("STDMItemDock")
        self._stdmItemPropDock.setMinimumWidth(300)
        self._stdmItemPropDock.setFeatures(QDockWidget.DockWidgetMovable|QDockWidget.DockWidgetClosable)
        self.mainWindow().addDockWidget(Qt.RightDockWidgetArea,self._stdmItemPropDock)
        self._stdmItemPropDock.show()

        #Re-arrange dock widgets and push up STDM data source dock widget
        if not self.generalDock() is None:
            self.mainWindow().splitDockWidget(self._stdmDataSourceDock,
                                              self.generalDock(),Qt.Vertical)
        
        if not self.itemDock() is None:
            self.mainWindow().splitDockWidget(self._stdmDataSourceDock,
                                             self.itemDock(),Qt.Vertical)
            if not self.generalDock() is None:
                self.mainWindow().tabifyDockWidget(self.generalDock(),
                                              self.itemDock())

        if not self.itemDock() is None:
            self.mainWindow().splitDockWidget(self.itemDock(),
                                              self._stdmItemPropDock,
                                              Qt.Vertical)

        #Set focus on composition properties window
        if not self.generalDock() is None:
            self.generalDock().activateWindow()
            self.generalDock().raise_()
            
        #Connect signals
        self.composition().itemRemoved.connect(self._onItemRemoved)
        self._dataSourceWidget.cboDataSource.currentIndexChanged[str].connect(
            self.propagateDataSourceSelection
        )
        self.composerView().selectedItemChanged.connect(self._onItemSelected)
        
        #Current template document file
        self._currDocFile = None
        
    def _removeActions(self):
        """
        Remove inapplicable actions and their corresponding toolbars and menus.
        """
        removeActions = ["mActionSaveProject","mActionNewComposer","mActionDuplicateComposer"]
        
        composerToolbar = self.composerMainToolBar()
        if composerToolbar != None:
            saveProjectAction = None
            
            for itemAction in composerToolbar.actions():
                if itemAction.objectName() == "mActionSaveProject":
                    saveProjectAction = itemAction
                    break
                
            if saveProjectAction != None:
                composerMenu = saveProjectAction.menu()
        
    def configure(self):
        #Create instances of custom STDM composer item configurations
        for ciConfig in ComposerItemConfig.itemConfigurations:
            ciConfigObj = ciConfig(self)
            
    def addWidgetMapping(self,uniqueIdentifier,widget):
        """
        Add custom STDM editor widget based on the unique identifier of the composer item
        """
        self._widgetMappings[uniqueIdentifier] = widget
        
    def widgetMappings(self):
        """
        Returns a dictionary containing uuid values of composer items linked to STDM widgets.
        """
        return self._widgetMappings
    
    def clearWidgetMappings(self):
        """
        Resets the widget mappings collection.
        """
        self._widgetMappings = {}
        
    def mainWindow(self):
        """
        Returns the QMainWindow used by the composer view.
        """
        return self._compView.composerWindow()
    
    def stdmToolBar(self):
        """
        Returns the instance of the STDM toolbar added to the QgsComposer.
        """
        return self._stdmTB
    
    def composerView(self):
        """
        Returns the composer view.
        """
        return self._compView
    
    def composition(self):
        """
        Returns the QgsComposition instance used in the composer view.
        """
        return self._compView.composition()
    
    def composerItemToolBar(self):
        """
        Returns the toolbar containing actions for adding composer items.
        """
        return self.mainWindow().findChild(QToolBar,"mItemToolbar")
    
    def composerMainToolBar(self):
        """
        Returns the toolbar containing actions for managing templates.
        """
        return self.mainWindow().findChild(QToolBar,"mComposerToolbar")
    
    def selectMoveAction(self):
        """
        Returns the QAction for selecting or moving composer items.
        """
        if self.composerItemToolBar() != None:
            if self._selectMoveAction == None:
                for itemAction in self.composerItemToolBar().actions():
                    if itemAction.objectName() == "mActionSelectMoveItem":
                        self._selectMoveAction = itemAction
                        break
        
        return self._selectMoveAction
    
    def checkedItemAction(self):
        """
        Returns the currently selected composer item action.
        """
        if self.selectMoveAction() != None:
            return self.selectMoveAction().actionGroup().checkedAction()
        
        return None
    
    def itemDock(self):
        """
        Get the 'Item Properties' dock widget.
        """
        return self.mainWindow().findChild(QDockWidget,"ItemDock")
    
    def atlasDock(self):
        """
        Get the 'Atlas generation' dock widget.
        """
        return self.mainWindow().findChild(QDockWidget,"AtlasDock")
    
    def generalDock(self):
        """
        Get the 'Composition' dock widget.
        """
        return self.mainWindow().findChild(QDockWidget,"CompositionDock")
    
    def stdmDataSourceDock(self):
        """
        Returns the STDM data source dock widget.
        """
        return self._stdmDataSourceDock
    
    def stdmItemDock(self):
        """
        Returns the STDM item dock widget.
        """
        return self._stdmItemPropDock
    
    def documentFile(self):
        """
        Returns the QFile instance associated with the current document. 'None' will be returned for
        new, unsaved documents.
        """
        return self._currDocFile
    
    def setDocumentFile(self,docFile):
        """
        Sets the document file.
        """
        if not isinstance(docFile,QFile):
            return
        
        self._currDocFile = docFile
    
    def selectedDataSource(self):
        """
        Returns the name of the data source specified by the user.
        """
        return self._stdmDataSourceDock.widget().cboDataSource.currentText()
    
    def selectedDataSourceCategory(self):
        """
        Returns the category (view or table) that the data source belongs to.
        """
        if self.stdmDataSourceDock().widget() != None:
            return self.stdmDataSourceDock().widget().category()
        
        return ""
    
    def propagateDataSourceSelection(self, dataSourceName):
        """
        Propagates the signal when a user select a data source. Listening objects can hook on to it.
        """
        self.dataSourceSelected.emit(dataSourceName)

    def composer_items(self):
        """
        :return: Returns a list of custom composer items.
        :rtype: list
        """
        return [self.composition().getComposerItemById(uuid) for uuid in self._widgetMappings.keys()
                if not self.composition().getComposerItemById(uuid) is None]

    def _clear_composition(self):
        """
        Removes composer items which, otherwise, are causing QGIS to crash
        when loading a subsequent document template.
        """
        items = self.composition().items()

        for c_item in items:
            if isinstance(c_item, QgsComposerItem) and not isinstance(c_item, QgsPaperItem):
                if c_item.uuid() in self._widgetMappings:
                    #Remove corresponding widget as well as reference in the collection
                    del self._widgetMappings[c_item.uuid()]

                self.composition().removeItem(c_item)
                self.composition().itemRemoved.emit(c_item)

                del c_item

        self.composition().undoStack().clear()
        self.composition().itemsModel().clear()

    def create_new_document_designer(self, file_path):
        """
        Creates a new document designer and loads the document template
        defined in file path.
        :param file_path: Path to document template
        :type file_path: str
        """
        document_designer = self._iface.createNewComposer("STDM Document Designer")

        #Embed STDM customizations
        cw = ComposerWrapper(document_designer, self._iface)
        cw.configure()

        #Load template
        cw.loadTemplate(file_path)
        
    def loadTemplate(self, filePath):
        """
        Loads a document template into the view and updates the necessary STDM-related composer items.
        """
        if not QFile.exists(filePath):
                QMessageBox.critical(self.composerView(),
                                     QApplication.translate("OpenTemplateConfig",
                                                            "Open Template Error"),
                                    QApplication.translate("OpenTemplateConfig",
                                                           "The specified template does not exist."))
                return
            
        templateFile = QFile(filePath)
        
        if not templateFile.open(QIODevice.ReadOnly):
            QMessageBox.critical(self.composerView(),
                                 QApplication.translate("ComposerWrapper",
                                                        "Open Operation Error"),
                                            "{0}\n{1}".format(QApplication.translate(
                                                "ComposerWrapper",
                                                "Cannot read template file."),
                                                      templateFile.errorString()
                                                      ))
            return    
         
        templateDoc = QDomDocument()
        
        if templateDoc.setContent(templateFile):
            table_config_collection = TableConfigurationCollection.create(templateDoc)

            '''
            First load vector layers for the table definitions in the config
            collection before loading rhe composition from file.
            '''
            load_table_layers(table_config_collection)

            #Load items into the composition and configure STDM data controls
            self.composition().loadFromTemplate(templateDoc)

            self.clearWidgetMappings()
            
            #Load data controls
            composerDS = ComposerDataSource.create(templateDoc)

            #Set title by appending template name
            title = QApplication.translate("STDMPlugin", "STDM Document Designer")

            composer_el = templateDoc.documentElement()
            if not composer_el is None:
                template_name = ""
                if composer_el.hasAttribute("title"):
                    template_name = composer_el.attribute("title", "")
                elif composer_el.hasAttribute("_title"):
                    template_name = composer_el.attribute("_title", "")

                if template_name:
                    win_title = u"{0} - {1}".format(title, template_name)
                    self.mainWindow().setWindowTitle(template_name)

            self._configure_data_controls(composerDS)
            
            #Load symbol editors
            spatialFieldsConfig = SpatialFieldsConfiguration.create(templateDoc)
            self._configureSpatialSymbolEditor(spatialFieldsConfig)

            #Load photo editors
            photo_config_collection = PhotoConfigurationCollection.create(templateDoc)
            self._configure_photo_editors(photo_config_collection)

            #Load table editors
            self._configure_table_editors(table_config_collection)

            #Load chart property editors
            chart_config_collection = ChartConfigurationCollection.create(templateDoc)
            self._configure_chart_editors(chart_config_collection)

            self._sync_ids_with_uuids()
            
    def saveTemplate(self):
        """
        Creates and saves a new document template.
        """
        #Validate if the user has specified the data source
        if not self.selectedDataSource():
            QMessageBox.critical(self.composerView(),
                                 QApplication.translate("ComposerWrapper","Error"),
                                QApplication.translate("ComposerWrapper","Please specify the "
                                            "data source name for the document composition."))
            return
            
        #If it is a new unsaved document template then prompt for the document name.
        docFile = self.documentFile()
        
        if docFile is None:
            docName,ok = QInputDialog.getText(self.composerView(),
                            QApplication.translate("ComposerWrapper","Template Name"),
                            QApplication.translate("ComposerWrapper","Please enter the template name below"),
                            )

            if ok and docName:
                templateDir = self._composerTemplatesPath()
                
                if templateDir is None:
                    QMessageBox.critical(self.composerView(),
                        QApplication.translate("ComposerWrapper","Error"),
                        QApplication.translate("ComposerWrapper",
                        "Directory for document templates cannot not be found."))

                    return

                absPath = templateDir + "/" + docName + ".sdt"

                #Check if there is an existing document with the same name
                caseInsenDic = CaseInsensitiveDict(documentTemplates())
                if docName in caseInsenDic:
                    result = QMessageBox.warning(self.composerView(),
                            QApplication.translate("ComposerWrapper",
                                                   "Existing Template"),
                                            u"'{0}' {1}.\nDo you want to replace the "
                                            "existing template?".format(docName,
                                            QApplication.translate("ComposerWrapper",
                                                                   "already exists")),
                                            QMessageBox.Yes|QMessageBox.No)

                    if result == QMessageBox.Yes:
                        #Delete the existing template
                        delFile = QFile(absPath)
                        remStatus = delFile.remove()
                        if not remStatus:
                            QMessageBox.critical(self.composerView(),
                            QApplication.translate("ComposerWrapper",
                                                   "Delete Error"),
                                            "'{0}' {1}.".format(docName,
                            QApplication.translate("ComposerWrapper",
                            "template could not be removed by the system,"
                            " please remove it manually from the document templates directory.")))
                            return

                    else:
                        return

                docFile= QFile(absPath)
            
            else:
                return
        
        docFileInfo = QFileInfo(docFile)
        
        if not docFile.open(QIODevice.WriteOnly):
            QMessageBox.critical(self.composerView(),
                                 QApplication.translate("ComposerWrapper",
                                "Save Operation Error"),
                                "{0}\n{1}".format(QApplication.translate("ComposerWrapper",
                                "Could not save template file."),
                                                      docFile.errorString()
                                ))

            return
                                              
        templateDoc = QDomDocument()
        template_name = docFileInfo.completeBaseName()
        self._writeXML(templateDoc, template_name)
        
        if docFile.write(templateDoc.toByteArray()) == -1:
            QMessageBox.critical(self.composerView(),
            QApplication.translate("ComposerWrapper","Save Error"),
            QApplication.translate("ComposerWrapper","Could not save template file."))

            return

        else:
            self.mainWindow().setWindowTitle(template_name)
        
        docFile.close()
        
    def _writeXML(self, xml_doc, doc_name):
        """
        Write the template configuration into the XML document.
        """        
        #Write default composer configuration
        composer_element = xml_doc.createElement("Composer")
        composer_element.setAttribute("title", doc_name)
        composer_element.setAttribute("visible", 1)
        
        xml_doc.appendChild(composer_element)
        
        self.composition().writeXML(composer_element, xml_doc)
        
        #Write STDM data field configurations
        dataSourceElement = ComposerDataSource.domElement(self, xml_doc)
        composer_element.appendChild(dataSourceElement)
        
        #Write spatial field configurations
        spatialColumnsElement = SpatialFieldsConfiguration.domElement(self, xml_doc)
        dataSourceElement.appendChild(spatialColumnsElement)

        #Write photo configuration
        tables_element = PhotoConfigurationCollection.dom_element(self, xml_doc)
        dataSourceElement.appendChild(tables_element)

        #Write table configuration
        tables_element = TableConfigurationCollection.dom_element(self, xml_doc)
        dataSourceElement.appendChild(tables_element)

        #Write chart configuration
        charts_element = ChartConfigurationCollection.dom_element(self, xml_doc)
        dataSourceElement.appendChild(charts_element)
        
    def _configure_data_controls(self, composer_data_source):
        """
        Configure the data source and data field controls based on the composer data
        source configuration.
        """
        if not self.stdmDataSourceDock().widget() is None:
            #Set data source
            dataSourceWidget = self.stdmDataSourceDock().widget()
            dataSourceWidget.setCategory(composer_data_source.category())
            dataSourceWidget.setSelectedSource(composer_data_source.name())
            
            #Set data field controls
            for composerId in composer_data_source.dataFieldMappings().reverse:
                #Use composer item id since the uuid is stripped off
                composerItem = self.composition().getComposerItemById(composerId)
                
                if not composerItem is None:
                    compFieldSelector = ComposerFieldSelector(self, composerItem, self.composerView())
                    compFieldSelector.selectFieldName(composer_data_source.dataFieldName(composerId))
                    
                    #Add widget to the collection but now use the current uuid of the composition item
                    self.addWidgetMapping(composerItem.uuid(), compFieldSelector)
                    
    def _configureSpatialSymbolEditor(self,spatial_field_config):
        """
        Configure symbol editor controls.
        """
        if not self.stdmDataSourceDock().widget() is None:
            for item_id, spFieldsMappings in spatial_field_config.spatialFieldsMapping().iteritems():
                mapItem = self.composition().getComposerItemById(item_id)
                
                if not mapItem is None:
                    composerSymbolEditor = ComposerSymbolEditor(self, self.composerView())
                    composerSymbolEditor.add_spatial_field_mappings(spFieldsMappings)
                    
                    #Add widget to the collection but now use the current uuid of the composer map
                    self.addWidgetMapping(mapItem.uuid(), composerSymbolEditor)

    def _configure_photo_editors(self, photo_config_collection):
        """
        Creates widgets for editing photo data sources.
        :param photo_config_collection: PhotoConfigurationCollection instance.
        :type photo_config_collection: PhotoConfigurationCollection
        """
        if self.stdmDataSourceDock().widget() is None:
            return

        for item_id, photo_config in photo_config_collection.mapping().iteritems():
            pic_item = self.composition().getComposerItemById(item_id)

            if not pic_item is None:
                photo_editor = ComposerPhotoDataSourceEditor(self, self.composerView())
                photo_editor.set_configuration(photo_config)

                self.addWidgetMapping(pic_item.uuid(), photo_editor)


    def _configure_chart_editors(self, chart_config_collection):
        """
        Creates widgets for editing chart properties.
        :param chart_config_collection: ChartConfigurationCollection instance.
        :type chart_config_collection: ChartConfigurationCollection
        """
        if self.stdmDataSourceDock().widget() is None:
            return

        for item_id, chart_config in chart_config_collection.mapping().iteritems():
            chart_item = self.composition().getComposerItemById(item_id)

            if not chart_item is None:
                chart_editor = ComposerChartConfigEditor(self, self.composerView())
                chart_editor.set_configuration(chart_config)

                self.addWidgetMapping(chart_item.uuid(), chart_editor)

    def _configure_table_editors(self, table_config_collection):
        """
        Creates widgets for editing table data sources.
        :param table_config_collection: TableConfigurationCollection instance.
        :type table_config_collection: TableConfigurationCollection
        """
        if self.stdmDataSourceDock().widget() is None:
            return

        for item_id, table_config in table_config_collection.mapping().iteritems():
            table_item = self.composition().getComposerItemById(item_id)

            if not table_item is None:
                table_editor = ComposerTableDataSourceEditor(self, table_item, self.composerView())
                table_editor.set_configuration(table_config)

                self.addWidgetMapping(table_item.uuid(), table_editor)

    def _sync_ids_with_uuids(self):
        """
        Matches IDs of custom STDM items with the corresponding UUIDs. This
        is applied when loading existing templates so that the saved
        document contains a matching pair of ID and UUID for each composer
        item.
        """
        items = self._widgetMappings.keys()
        for item_uuid in self._widgetMappings.keys():
            item = self.composition().getComposerItemByUuid(item_uuid)
            if not item is None:
                item.setId(item_uuid)
                        
    def _composerTemplatesPath(self):
        """
        Reads the path of composer templates in the registry.
        """
        regConfig = RegistryConfig()
        keyName = "ComposerTemplates"
        
        valueCollection = regConfig.read([keyName])
        
        if len(valueCollection) == 0:
            return None
        
        else:
            return valueCollection[keyName]
    
    def _onItemRemoved(self,item):
        """
        Slot raised when a composer item is removed from the scene.
        """
        """
        Code will not work since a QObject instance is returned instead of a QgsComposerItem
        if item.uuid() in self._widgetMappings:
            del self._widgetMappings[item.uuid()]
        """
        pass
    
    def _onItemSelected(self, item):
        """
        Slot raised when a composer item is selected. Load the corresponding field selector
        if the selection is an STDM data field label.
        QComposerLabel is returned as a QObject in the slot argument hence, we have resorted to 
        capturing the current selected items in the composition.
        """
        selectedItems = self.composition().selectedComposerItems()
        
        if len(selectedItems) == 0:
            self._stdmItemPropDock.setWidget(None)
        
        elif len(selectedItems) == 1:
            composer_item = selectedItems[0]
            
            if composer_item.uuid() in self._widgetMappings:
                stdmWidget = self._widgetMappings[composer_item.uuid()]
                
                if stdmWidget == self._stdmItemPropDock.widget():
                    return
                
                else:
                    self._stdmItemPropDock.setWidget(stdmWidget)
                    
                #Playing it safe in applying the formatting for the editor controls where applicable
                itemFormatter = None

                if isinstance(composer_item, QgsComposerArrow):
                    itemFormatter = LineFormatter()

                elif isinstance(composer_item, QgsComposerLabel):
                    itemFormatter = DataLabelFormatter()

                elif isinstance(composer_item, QgsComposerMap):
                    itemFormatter = MapFormatter()

                elif isinstance(composer_item, QgsComposerPicture):
                    """
                    Use widget attribute to distinguish type i.e.
                    whether it is a photo, graph etc.
                    """
                    editor_widget = self._widgetMappings[composer_item.uuid()]

                    if isinstance(editor_widget, ComposerPhotoDataSourceEditor):
                        itemFormatter = PhotoFormatter()

                    elif isinstance(editor_widget, ComposerChartConfigEditor):
                        itemFormatter = ChartFormatter()

                elif isinstance(composer_item, QgsComposerAttributeTable):
                    itemFormatter = TableFormatter()
                        
                if not itemFormatter is None:
                    itemFormatter.apply(composer_item, self, True)
                    
            else:
                self._stdmItemPropDock.setWidget(None)
            
        elif len(selectedItems) > 1:
            self._stdmItemPropDock.setWidget(None)
예제 #47
0
파일: db_manager.py 프로젝트: jarped/QGIS
class DBManager(QMainWindow):
    def __init__(self, iface, parent=None):
        QMainWindow.__init__(self, parent)
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.setupUi()
        self.iface = iface

        # restore the window state
        settings = QSettings()
        self.restoreGeometry(
            settings.value("/DB_Manager/mainWindow/geometry",
                           QByteArray(),
                           type=QByteArray))
        self.restoreState(
            settings.value("/DB_Manager/mainWindow/windowState",
                           QByteArray(),
                           type=QByteArray))

        self.connect(self.tabs, SIGNAL("currentChanged(int)"), self.tabChanged)
        self.connect(self.tree, SIGNAL("selectedItemChanged"),
                     self.itemChanged)
        self.itemChanged(None)

    def closeEvent(self, e):
        self.unregisterAllActions()

        # save the window state
        settings = QSettings()
        settings.setValue("/DB_Manager/mainWindow/windowState",
                          self.saveState())
        settings.setValue("/DB_Manager/mainWindow/geometry",
                          self.saveGeometry())

        QMainWindow.closeEvent(self, e)

    def refreshItem(self, item=None):
        QApplication.setOverrideCursor(Qt.WaitCursor)
        try:
            if item is None:
                item = self.tree.currentItem()
            self.tree.refreshItem(item)  # refresh item children in the db tree
        except BaseError as e:
            DlgDbError.showError(e, self)
            return
        finally:
            QApplication.restoreOverrideCursor()

    def itemChanged(self, item):
        QApplication.setOverrideCursor(Qt.WaitCursor)
        try:
            self.reloadButtons()
            self.refreshTabs()
        except BaseError as e:
            DlgDbError.showError(e, self)
            return
        finally:
            QApplication.restoreOverrideCursor()

    def reloadButtons(self):
        db = self.tree.currentDatabase()
        if not hasattr(self, '_lastDb'):
            self._lastDb = db

        elif db == self._lastDb:
            return

        # remove old actions
        if self._lastDb is not None:
            self.unregisterAllActions()

        # add actions of the selected database
        self._lastDb = db
        if self._lastDb is not None:
            self._lastDb.registerAllActions(self)

    def tabChanged(self, index):
        QApplication.setOverrideCursor(Qt.WaitCursor)
        try:
            self.refreshTabs()
        except BaseError as e:
            DlgDbError.showError(e, self)
            return
        finally:
            QApplication.restoreOverrideCursor()

    def refreshTabs(self):
        index = self.tabs.currentIndex()
        item = self.tree.currentItem()
        table = self.tree.currentTable()

        # enable/disable tabs
        self.tabs.setTabEnabled(self.tabs.indexOf(self.table), table
                                is not None)
        self.tabs.setTabEnabled(
            self.tabs.indexOf(self.preview), table is not None
            and table.type in [table.VectorType, table.RasterType]
            and table.geomColumn is not None)
        # show the info tab if the current tab is disabled
        if not self.tabs.isTabEnabled(index):
            self.tabs.setCurrentWidget(self.info)

        current_tab = self.tabs.currentWidget()
        if current_tab == self.info:
            self.info.showInfo(item)
        elif current_tab == self.table:
            self.table.loadData(item)
        elif current_tab == self.preview:
            self.preview.loadPreview(item)

    def refreshActionSlot(self):
        self.info.setDirty()
        self.table.setDirty()
        self.preview.setDirty()
        self.refreshItem()

    def importActionSlot(self):
        db = self.tree.currentDatabase()
        if db is None:
            self.infoBar.pushMessage(
                self.tr(
                    "No database selected or you are not connected to it."),
                QgsMessageBar.INFO, self.iface.messageTimeout())
            return

        outUri = db.uri()
        schema = self.tree.currentSchema()
        if schema:
            outUri.setDataSource(schema.name, "", "", "")

        from .dlg_import_vector import DlgImportVector

        dlg = DlgImportVector(None, db, outUri, self)
        dlg.exec_()

    def exportActionSlot(self):
        table = self.tree.currentTable()
        if table is None:
            self.infoBar.pushMessage(
                self.tr("Select the table you want export to file."),
                QgsMessageBar.INFO, self.iface.messageTimeout())
            return

        inLayer = table.toMapLayer()

        from .dlg_export_vector import DlgExportVector

        dlg = DlgExportVector(inLayer, table.database(), self)
        dlg.exec_()

        inLayer.deleteLater()

    def runSqlWindow(self):
        db = self.tree.currentDatabase()
        if db is None:
            self.infoBar.pushMessage(
                self.tr(
                    "No database selected or you are not connected to it."),
                QgsMessageBar.INFO, self.iface.messageTimeout())
            # force displaying of the message, it appears on the first tab (i.e. Info)
            self.tabs.setCurrentIndex(0)
            return

        from dlg_sql_window import DlgSqlWindow

        query = DlgSqlWindow(self.iface, db, self)
        dbname = db.connection().connectionName()
        tabname = self.tr("Query") + u" (%s)" % dbname
        index = self.tabs.addTab(query, tabname)
        self.tabs.setTabIcon(index, db.connection().icon())
        self.tabs.setCurrentIndex(index)
        query.nameChanged.connect(
            functools.partial(self.update_query_tab_name, index, dbname))

    def update_query_tab_name(self, index, dbname, queryname):
        if not queryname:
            queryname = self.tr("Query")
        tabname = u"%s (%s)" % (queryname, dbname)
        self.tabs.setTabText(index, tabname)

    def showSystemTables(self):
        self.tree.showSystemTables(self.actionShowSystemTables.isChecked())

    def registerAction(self, action, menuName, callback=None):
        """ register an action to the manager's main menu """
        if not hasattr(self, '_registeredDbActions'):
            self._registeredDbActions = {}

        if callback is not None:
            invoke_callback = lambda x: self.invokeCallback(callback)

        if menuName is None or menuName == "":
            self.addAction(action)

            if menuName not in self._registeredDbActions:
                self._registeredDbActions[menuName] = list()
            self._registeredDbActions[menuName].append(action)

            if callback is not None:
                QObject.connect(action, SIGNAL("triggered(bool)"),
                                invoke_callback)
            return True

        # search for the menu
        actionMenu = None
        helpMenuAction = None
        for a in self.menuBar.actions():
            if not a.menu() or a.menu().title() != menuName:
                continue
            if a.menu() != self.menuHelp:
                helpMenuAction = a

            actionMenu = a
            break

        # not found, add a new menu before the help menu
        if actionMenu is None:
            menu = QMenu(menuName, self)
            if helpMenuAction is not None:
                actionMenu = self.menuBar.insertMenu(helpMenuAction, menu)
            else:
                actionMenu = self.menuBar.addMenu(menu)

        menu = actionMenu.menu()
        menuActions = menu.actions()

        # get the placeholder's position to insert before it
        pos = 0
        for pos in range(len(menuActions)):
            if menuActions[pos].isSeparator() and menuActions[pos].objectName(
            ).endswith("_placeholder"):
                menuActions[pos].setVisible(True)
                break

        if pos < len(menuActions):
            before = menuActions[pos]
            menu.insertAction(before, action)
        else:
            menu.addAction(action)

        actionMenu.setVisible(True)  # show the menu

        if menuName not in self._registeredDbActions:
            self._registeredDbActions[menuName] = list()
        self._registeredDbActions[menuName].append(action)

        if callback is not None:
            QObject.connect(action, SIGNAL("triggered(bool)"), invoke_callback)

        return True

    def invokeCallback(self, callback, *params):
        """ Call a method passing the selected item in the database tree,
                the sender (usually a QAction), the plugin mainWindow and
                optionally additional parameters.

                This method takes care to override and restore the cursor,
                but also catches exceptions and displays the error dialog.
        """
        QApplication.setOverrideCursor(Qt.WaitCursor)
        try:
            callback(self.tree.currentItem(), self.sender(), self, *params)

        except BaseError as e:
            # catch database errors and display the error dialog
            DlgDbError.showError(e, self)
            return

        finally:
            QApplication.restoreOverrideCursor()

    def unregisterAction(self, action, menuName):
        if not hasattr(self, '_registeredDbActions'):
            return

        if menuName is None or menuName == "":
            self.removeAction(action)

            if menuName in self._registeredDbActions:
                if self._registeredDbActions[menuName].count(action) > 0:
                    self._registeredDbActions[menuName].remove(action)

            action.deleteLater()
            return True

        for a in self.menuBar.actions():
            if not a.menu() or a.menu().title() != menuName:
                continue

            menu = a.menu()
            menuActions = menu.actions()

            menu.removeAction(action)
            if menu.isEmpty():  # hide the menu
                a.setVisible(False)

            if menuName in self._registeredDbActions:
                if self._registeredDbActions[menuName].count(action) > 0:
                    self._registeredDbActions[menuName].remove(action)

                # hide the placeholder if there're no other registered actions
                if len(self._registeredDbActions[menuName]) <= 0:
                    for i in range(len(menuActions)):
                        if menuActions[i].isSeparator() and menuActions[
                                i].objectName().endswith("_placeholder"):
                            menuActions[i].setVisible(False)
                            break

            action.deleteLater()
            return True

        return False

    def unregisterAllActions(self):
        if not hasattr(self, '_registeredDbActions'):
            return

        for menuName in self._registeredDbActions:
            for action in list(self._registeredDbActions[menuName]):
                self.unregisterAction(action, menuName)
        del self._registeredDbActions

    def close_tab(self, index):
        widget = self.tabs.widget(index)
        if widget not in [self.info, self.table, self.preview]:
            self.tabs.removeTab(index)
            widget.deleteLater()

    def setupUi(self):
        self.setWindowTitle(self.tr("DB Manager"))
        self.setWindowIcon(QIcon(":/db_manager/icon"))
        self.resize(QSize(700, 500).expandedTo(self.minimumSizeHint()))

        # create central tab widget and add the first 3 tabs: info, table and preview
        self.tabs = QTabWidget()
        self.info = InfoViewer(self)
        self.tabs.addTab(self.info, self.tr("Info"))
        self.table = TableViewer(self)
        self.tabs.addTab(self.table, self.tr("Table"))
        self.preview = LayerPreview(self)
        self.tabs.addTab(self.preview, self.tr("Preview"))
        self.setCentralWidget(self.tabs)

        # display close button for all tabs but the first 3 ones, i.e.
        # HACK: just hide the close button where not needed (GS)
        self.tabs.setTabsClosable(True)
        self.tabs.tabCloseRequested.connect(self.close_tab)
        tabbar = self.tabs.tabBar()
        for i in range(3):
            btn = tabbar.tabButton(i, QTabBar.RightSide) if tabbar.tabButton(
                i, QTabBar.RightSide) else tabbar.tabButton(
                    i, QTabBar.LeftSide)
            btn.resize(0, 0)
            btn.hide()

        # Creates layout for message bar
        self.layout = QGridLayout(self.info)
        self.layout.setContentsMargins(0, 0, 0, 0)
        spacerItem = QSpacerItem(20, 40, QSizePolicy.Minimum,
                                 QSizePolicy.Expanding)
        self.layout.addItem(spacerItem, 1, 0, 1, 1)
        # init messageBar instance
        self.infoBar = QgsMessageBar(self.info)
        sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)
        self.infoBar.setSizePolicy(sizePolicy)
        self.layout.addWidget(self.infoBar, 0, 0, 1, 1)

        # create database tree
        self.dock = QDockWidget("Tree", self)
        self.dock.setObjectName("DB_Manager_DBView")
        self.dock.setFeatures(QDockWidget.DockWidgetMovable)
        self.tree = DBTree(self)
        self.dock.setWidget(self.tree)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.dock)

        # create status bar
        self.statusBar = QStatusBar(self)
        self.setStatusBar(self.statusBar)

        # create menus
        self.menuBar = QMenuBar(self)
        self.menuDb = QMenu(self.tr("&Database"), self)
        self.menuBar.addMenu(self.menuDb)
        self.menuSchema = QMenu(self.tr("&Schema"), self)
        actionMenuSchema = self.menuBar.addMenu(self.menuSchema)
        self.menuTable = QMenu(self.tr("&Table"), self)
        actionMenuTable = self.menuBar.addMenu(self.menuTable)
        self.menuHelp = None  # QMenu(self.tr("&Help"), self)
        # actionMenuHelp = self.menuBar.addMenu(self.menuHelp)

        self.setMenuBar(self.menuBar)

        # create toolbar
        self.toolBar = QToolBar("Default", self)
        self.toolBar.setObjectName("DB_Manager_ToolBar")
        self.addToolBar(self.toolBar)

        # create menus' actions

        # menu DATABASE
        sep = self.menuDb.addSeparator()
        sep.setObjectName("DB_Manager_DbMenu_placeholder")
        sep.setVisible(False)

        self.actionRefresh = self.menuDb.addAction(
            QIcon(":/db_manager/actions/refresh"), self.tr("&Refresh"),
            self.refreshActionSlot, QKeySequence("F5"))
        self.actionSqlWindow = self.menuDb.addAction(
            QIcon(":/db_manager/actions/sql_window"), self.tr("&SQL window"),
            self.runSqlWindow, QKeySequence("F2"))
        self.menuDb.addSeparator()
        self.actionClose = self.menuDb.addAction(QIcon(), self.tr("&Exit"),
                                                 self.close,
                                                 QKeySequence("CTRL+Q"))

        # menu SCHEMA
        sep = self.menuSchema.addSeparator()
        sep.setObjectName("DB_Manager_SchemaMenu_placeholder")
        sep.setVisible(False)

        actionMenuSchema.setVisible(False)

        # menu TABLE
        sep = self.menuTable.addSeparator()
        sep.setObjectName("DB_Manager_TableMenu_placeholder")
        sep.setVisible(False)

        self.actionImport = self.menuTable.addAction(
            QIcon(":/db_manager/actions/import"),
            self.tr("&Import layer/file"), self.importActionSlot)
        self.actionExport = self.menuTable.addAction(
            QIcon(":/db_manager/actions/export"), self.tr("&Export to file"),
            self.exportActionSlot)
        self.menuTable.addSeparator()
        #self.actionShowSystemTables = self.menuTable.addAction(self.tr("Show system tables/views"), self.showSystemTables)
        #self.actionShowSystemTables.setCheckable(True)
        #self.actionShowSystemTables.setChecked(True)
        actionMenuTable.setVisible(False)

        # add actions to the toolbar
        self.toolBar.addAction(self.actionRefresh)
        self.toolBar.addAction(self.actionSqlWindow)
        self.toolBar.addAction(self.actionImport)
        self.toolBar.addAction(self.actionExport)
예제 #48
0
class OneClockAddon:

    def __init__(self):
        self.db = TomatoDB("_TomatoClock.db")
        self.dlg = OneClock(mw)

        self.pb = None
        self._connect_slots()
        self._set_style_sheet(mw)
        self.tm = None
        self.dlg_rest = None
        self.pb_w = None

        self.replace_mw_overview()
        self.replace_mw_deckbrowser()

    def replace_mw_overview(self):
        mw.overview = anki_overview(self.dlg, self.db)

    def replace_mw_reviewer(self):
        mw.reviewer = anki_reviewer(self.dlg.mode, self.db)

    def replace_mw_deckbrowser(self):
        mw.deckBrowser = anki_deckbrowser(self.db)
        mw.deckBrowser.refresh()

    @staticmethod
    def _set_style_sheet(obj):
        with open(os.path.join(os.path.dirname(__file__), "ui", "designer", "style.css"), "r") as f:
            obj.setStyleSheet(f.read())

    def _connect_slots(self):
        self.dlg.btn_start.clicked.connect(self.on_btn_start_clicked)

    def perform_hooks(self, func):
        func('reviewCleanup', self.on_review_cleanup)
        func('profileLoaded', self.on_profile_loaded)
        func('afterStateChange', self.after_anki_state_change)

    def on_profile_loaded(self):
        ProfileConfig.donate_alerted = False
        UserConfig.BREAK_MINUTES  # just ensure json file is generated
        try:
            if UserConfig.LIVE_CODE_DOWNLOAD:
                thr = _live_chart_py_downloader()
                thr.start()
        except:
            pass

    def on_review_cleanup(self):
        mw.setWindowIcon(QIcon(":/icons/anki.png"))
        if self.tm and self.tm.isActive():
            self.tm.stop()
        if self.pb:
            self.pb_w.hide()
            self.pb.reset()

        if self.dlg_rest:
            self.dlg_rest.hide()

        try:
            mw.reviewer.restore_layouts()
        except AttributeError:  # just in case "replace_mw_reviewer" is not called
            pass

    def on_btn_start_clicked(self):
        self.replace_mw_reviewer()

        mw.setWindowIcon(QIcon(":/icon/tomato.png"))
        assert isinstance(mw, AnkiQt)

        self.setup_progressbar()
        self.pb.set_seconds(self.dlg.min * MIN_SECS)
        if not self.tm:
            self.tm = Timer(mw)
            self.tm.timeout.connect(self.on_timer)
        self.tm.start()

        # click study button
        mw.overview._linkHandler("study")

        self.db.start_session(
            self.dlg.min,
            UserConfig.ANSWER_TIMEOUT_SECONDS,
            self.dlg.mode
        )

    def after_anki_state_change(self, state, oldState):
        if state == 'overview' and oldState == 'review':
            self.on_tomato(False)
            mw.overview.refresh()

    def on_tomato(self, from_timer=True):
        self.db.end_session()
        if self.tm:
            self.tm.stop()
        self.pb_w.hide()
        self.pb.reset()
        if from_timer:
            mw.moveToState("overview")
            if not self.dlg_rest:
                self.dlg_rest = RestDialog(mw)
                self._set_style_sheet(self.dlg_rest)
                self.dlg_rest.accepted.connect(self.on_dlg_rest_accepted)
                self.dlg_rest.rejected.connect(self.on_dlg_rest_rejected)
            if UserConfig.PLAY_SOUNDS["break"]:
                play(BREAK)
            self.dlg_rest.exec_(self.dlg.min)

    @staticmethod
    def on_dlg_rest_accepted():
        mw.overview._linkHandler("tomato_clock")

    def on_dlg_rest_rejected(self):
        pass

    def on_timer(self):
        if self.pb:
            self.pb_w.show()
            self.pb.on_timer()
        self.db.commit()

    def setup_progressbar(self):

        dockArea = Qt.TopDockWidgetArea
        # dockArea = Qt.LeftDockWidgetArea
        # dockArea = Qt.BottomDockWidgetArea

        self.pb_w = QDockWidget(mw)
        self.pb_w.setObjectName("progress_dock")
        if not self.pb:
            self.pb = ClockProgress(mw, dockArea)
            self.pb.tomato.connect(self.on_tomato)
        else:
            self.pb.reset()

        self.pb.set_seconds(self.dlg.min * MIN_SECS)
        self.pb_w.setWidget(self.pb)
        w = QWidget(self.pb_w)
        w.setFixedHeight(self.pb.height())
        self.pb_w.setTitleBarWidget(w)
        self.pb_w.setFeatures(QDockWidget.NoDockWidgetFeatures)

        # first check existing widgets
        existing_widgets = [widget for widget in mw.findChildren(QDockWidget) if mw.dockWidgetArea(widget) == dockArea]

        # then add ourselves
        mw.addDockWidget(dockArea, self.pb_w)

        # stack with any existing widgets
        if len(existing_widgets) > 0:
            mw.setDockNestingEnabled(True)

            if dockArea == Qt.TopDockWidgetArea or dockArea == Qt.BottomDockWidgetArea:
                stack_method = Qt.Vertical
            if dockArea == Qt.LeftDockWidgetArea or dockArea == Qt.RightDockWidgetArea:
                stack_method = Qt.Horizontal
            mw.splitDockWidget(existing_widgets[0], self.pb_w, stack_method)

        mw.web.setFocus()
        self._set_style_sheet(self.pb)
예제 #49
0
class WatchController(QObject):
    """ the Controller for the WatchView """
    
    def __init__(self, distributedObjects):
        """ Constructor <br>
            Create a WatchView, a WatchVWFactory and a VariableList <br>
            Listens to the following Signals: SignalProxy::AddWatch(QString), SignalProxy::insertDockWidgets() and SignalProxy::cleanupModels()
        @param distributedObjects    distributedobjects.DistributedObjects, the DistributedObjects-Instance
        """
        QObject.__init__(self)
        self.distributedObjects = distributedObjects
        #self.root = RootVarWrapper()
        
        self.vwFactory = WatchVWFactory()
        
        self.variableModel = VariableModel(self, self.distributedObjects)
        self.watchView = WatchView(self)
        
        self.watchView.treeView.setModel(self.variableModel)
        self.watchVariableList = VariableList(self.vwFactory, self.distributedObjects)
        
        QObject.connect(self.distributedObjects.signal_proxy, SIGNAL('AddWatch(QString)'), self.addWatch)
        QObject.connect(self.distributedObjects.signal_proxy, SIGNAL('insertDockWidgets()'), self.insertDockWidgets)
        QObject.connect(self.distributedObjects.signal_proxy, SIGNAL('cleanupModels()'), self.clearVars)
        
    def clearVars(self):
        """ clears the WatchView and the VariableList <br>
            this function is connected to the signal SignalProxy::cleanupModels()
        """
        # clear lists
        del self.watchVariableList.list[:]
        self.variableModel.clear()     
        
    def insertDockWidgets(self):
        """ adds the Watch-DockWidget to the GUI <br>
            this function is connected to the signal SignalProxy::insertDockWidgets() """

        self.watchDock = QDockWidget("Watch")
        self.watchDock.setObjectName("WatchView")
        self.watchDock.setWidget(self.watchView)
        self.distributedObjects.signal_proxy.addDockWidget(Qt.BottomDockWidgetArea, self.watchDock, True)
        
    def removeSelected(self, row, parent): 
        """ remove selected variable from WatchView
        @param row     int, selected row
        @param parent  TreeItem, parent item from selectected item
        """ 
        self.variableModel.removeRow(row, parent)
    
    def addWatch(self, watch):
        """ adds the Variable watch to the VariableList and its wrapper to the WatchView
            this function is connected to the signal SignalProxy::AddWatch(QString)
        @param watch    Variable, the Variable to add to watch
        """
        vw = self.watchVariableList.addVarByName(watch)
        # connect changed and replace signal from wrapper
        QObject.connect(vw, SIGNAL('changed()'), vw.hasChanged)  
        QObject.connect(vw, SIGNAL('replace(PyQt_PyObject, PyQt_PyObject)'), self.replaceVariable)  
        
        # set parent for root variable
        vw.setParent(self.variableModel.root)
        
        # add variable to root children
        self.variableModel.root.addChild(vw)
        self.variableModel.addVar(vw)
        
    def replaceVariable(self, pendingVar, newVar):
        """ replaces a variable in the variablelist
        @param pendingVar    variables.variablewrapper.VariableWrapper, VariableWrapper to replace in the list
        @param newVar        variables.Variable, new Variable which replaces existing VariableWrapper in List
        """
        vwOld = self.watchVariableList.getVariableWrapper(pendingVar)
        
        vwNew = self.watchVariableList.replaceVar(pendingVar, newVar)
        QObject.connect(vwNew, SIGNAL('changed()'), vwNew.hasChanged)  
        QObject.connect(vwNew, SIGNAL('replace(PyQt_PyObject, PyQt_PyObject)'), self.replaceVariable)  
        
        # set parent for root variable
        vwNew.setParent(self.variableModel.root)
        
        # add variable to root children
        self.variableModel.root.replaceChild(vwOld, vwNew)
        
        vwNew.setChanged(True)
        self.variableModel.update()
        
    def saveSession(self, xmlHandler):
        """ Insert session info to xml file
        @param xmlHandler    sessionmanager.XmlHandler, handler to write to the session-xml-file
        """
        watchParent = xmlHandler.createNode("Watches")
        for var in self.variableModel.getVariables():
            xmlHandler.createNode("Watch", watchParent, { 'exp': var.getExp()})
             
    def loadSession(self, xmlHandler): 
        """ load session info to xml file
        @param xmlHandler    sessionmanager.XmlHandler, handler to read from the session-xml-file
        """   
        watchParent = xmlHandler.getNode("Watches")
        if watchParent != None:
            childnodes = watchParent.childNodes()
            for i in range(childnodes.size()):
                attr = xmlHandler.getAttributes(childnodes.at(i))
                self.addWatch(attr["exp"])
예제 #50
0
class MenuBuilderDialog(QDialog, Ui_Dialog):
    def __init__(self, uiparent):
        super(MenuBuilderDialog, self).__init__()

        self.setupUi(self)

        # reference to caller
        self.uiparent = uiparent

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        uri = QgsDataSourceURI()

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

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

        settings.endGroup()

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

        uri.setUseEstimatedMetadata(useEstimatedMetadata)

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

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

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

        return wrapped

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

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

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

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

            if username:
                uri.setUsername(username)

            if password:
                uri.setPassword(password)

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

        self.pgencoding = self.connection.encoding

        return True

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        self.set_connection(0, dbname=database)
        self.show_dock(bool(dock), profile=profile, schema=schema)
        if bool(dock):
            self.uiparent.iface.addDockWidget(Qt.LeftDockWidgetArea,
                                              self.dock_widget)
        self.show_menus(bool(menubar), profile=profile, schema=schema)
예제 #51
0
파일: db_manager.py 프로젝트: jarped/QGIS
class DBManager(QMainWindow):

    def __init__(self, iface, parent=None):
        QMainWindow.__init__(self, parent)
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.setupUi()
        self.iface = iface

        # restore the window state
        settings = QSettings()
        self.restoreGeometry(settings.value("/DB_Manager/mainWindow/geometry", QByteArray(), type=QByteArray))
        self.restoreState(settings.value("/DB_Manager/mainWindow/windowState", QByteArray(), type=QByteArray))

        self.connect(self.tabs, SIGNAL("currentChanged(int)"), self.tabChanged)
        self.connect(self.tree, SIGNAL("selectedItemChanged"), self.itemChanged)
        self.itemChanged(None)

    def closeEvent(self, e):
        self.unregisterAllActions()

        # save the window state
        settings = QSettings()
        settings.setValue("/DB_Manager/mainWindow/windowState", self.saveState())
        settings.setValue("/DB_Manager/mainWindow/geometry", self.saveGeometry())

        QMainWindow.closeEvent(self, e)

    def refreshItem(self, item=None):
        QApplication.setOverrideCursor(Qt.WaitCursor)
        try:
            if item is None:
                item = self.tree.currentItem()
            self.tree.refreshItem(item)  # refresh item children in the db tree
        except BaseError as e:
            DlgDbError.showError(e, self)
            return
        finally:
            QApplication.restoreOverrideCursor()

    def itemChanged(self, item):
        QApplication.setOverrideCursor(Qt.WaitCursor)
        try:
            self.reloadButtons()
            self.refreshTabs()
        except BaseError as e:
            DlgDbError.showError(e, self)
            return
        finally:
            QApplication.restoreOverrideCursor()

    def reloadButtons(self):
        db = self.tree.currentDatabase()
        if not hasattr(self, '_lastDb'):
            self._lastDb = db

        elif db == self._lastDb:
            return

        # remove old actions
        if self._lastDb is not None:
            self.unregisterAllActions()

        # add actions of the selected database
        self._lastDb = db
        if self._lastDb is not None:
            self._lastDb.registerAllActions(self)

    def tabChanged(self, index):
        QApplication.setOverrideCursor(Qt.WaitCursor)
        try:
            self.refreshTabs()
        except BaseError as e:
            DlgDbError.showError(e, self)
            return
        finally:
            QApplication.restoreOverrideCursor()

    def refreshTabs(self):
        index = self.tabs.currentIndex()
        item = self.tree.currentItem()
        table = self.tree.currentTable()

        # enable/disable tabs
        self.tabs.setTabEnabled(self.tabs.indexOf(self.table), table is not None)
        self.tabs.setTabEnabled(self.tabs.indexOf(self.preview), table is not None and table.type in [table.VectorType,
                                                                                                      table.RasterType] and table.geomColumn is not None)
        # show the info tab if the current tab is disabled
        if not self.tabs.isTabEnabled(index):
            self.tabs.setCurrentWidget(self.info)

        current_tab = self.tabs.currentWidget()
        if current_tab == self.info:
            self.info.showInfo(item)
        elif current_tab == self.table:
            self.table.loadData(item)
        elif current_tab == self.preview:
            self.preview.loadPreview(item)

    def refreshActionSlot(self):
        self.info.setDirty()
        self.table.setDirty()
        self.preview.setDirty()
        self.refreshItem()

    def importActionSlot(self):
        db = self.tree.currentDatabase()
        if db is None:
            self.infoBar.pushMessage(self.tr("No database selected or you are not connected to it."),
                                     QgsMessageBar.INFO, self.iface.messageTimeout())
            return

        outUri = db.uri()
        schema = self.tree.currentSchema()
        if schema:
            outUri.setDataSource(schema.name, "", "", "")

        from .dlg_import_vector import DlgImportVector

        dlg = DlgImportVector(None, db, outUri, self)
        dlg.exec_()

    def exportActionSlot(self):
        table = self.tree.currentTable()
        if table is None:
            self.infoBar.pushMessage(self.tr("Select the table you want export to file."), QgsMessageBar.INFO,
                                     self.iface.messageTimeout())
            return

        inLayer = table.toMapLayer()

        from .dlg_export_vector import DlgExportVector

        dlg = DlgExportVector(inLayer, table.database(), self)
        dlg.exec_()

        inLayer.deleteLater()

    def runSqlWindow(self):
        db = self.tree.currentDatabase()
        if db is None:
            self.infoBar.pushMessage(self.tr("No database selected or you are not connected to it."),
                                     QgsMessageBar.INFO, self.iface.messageTimeout())
            # force displaying of the message, it appears on the first tab (i.e. Info)
            self.tabs.setCurrentIndex(0)
            return

        from dlg_sql_window import DlgSqlWindow

        query = DlgSqlWindow(self.iface, db, self)
        dbname = db.connection().connectionName()
        tabname = self.tr("Query") + u" (%s)" % dbname
        index = self.tabs.addTab(query, tabname)
        self.tabs.setTabIcon(index, db.connection().icon())
        self.tabs.setCurrentIndex(index)
        query.nameChanged.connect(functools.partial(self.update_query_tab_name, index, dbname))

    def update_query_tab_name(self, index, dbname, queryname):
        if not queryname:
            queryname = self.tr("Query")
        tabname = u"%s (%s)" % (queryname, dbname)
        self.tabs.setTabText(index, tabname)

    def showSystemTables(self):
        self.tree.showSystemTables(self.actionShowSystemTables.isChecked())

    def registerAction(self, action, menuName, callback=None):
        """ register an action to the manager's main menu """
        if not hasattr(self, '_registeredDbActions'):
            self._registeredDbActions = {}

        if callback is not None:
            invoke_callback = lambda x: self.invokeCallback(callback)

        if menuName is None or menuName == "":
            self.addAction(action)

            if menuName not in self._registeredDbActions:
                self._registeredDbActions[menuName] = list()
            self._registeredDbActions[menuName].append(action)

            if callback is not None:
                QObject.connect(action, SIGNAL("triggered(bool)"), invoke_callback)
            return True

        # search for the menu
        actionMenu = None
        helpMenuAction = None
        for a in self.menuBar.actions():
            if not a.menu() or a.menu().title() != menuName:
                continue
            if a.menu() != self.menuHelp:
                helpMenuAction = a

            actionMenu = a
            break

        # not found, add a new menu before the help menu
        if actionMenu is None:
            menu = QMenu(menuName, self)
            if helpMenuAction is not None:
                actionMenu = self.menuBar.insertMenu(helpMenuAction, menu)
            else:
                actionMenu = self.menuBar.addMenu(menu)

        menu = actionMenu.menu()
        menuActions = menu.actions()

        # get the placeholder's position to insert before it
        pos = 0
        for pos in range(len(menuActions)):
            if menuActions[pos].isSeparator() and menuActions[pos].objectName().endswith("_placeholder"):
                menuActions[pos].setVisible(True)
                break

        if pos < len(menuActions):
            before = menuActions[pos]
            menu.insertAction(before, action)
        else:
            menu.addAction(action)

        actionMenu.setVisible(True)  # show the menu

        if menuName not in self._registeredDbActions:
            self._registeredDbActions[menuName] = list()
        self._registeredDbActions[menuName].append(action)

        if callback is not None:
            QObject.connect(action, SIGNAL("triggered(bool)"), invoke_callback)

        return True

    def invokeCallback(self, callback, *params):
        """ Call a method passing the selected item in the database tree,
                the sender (usually a QAction), the plugin mainWindow and
                optionally additional parameters.

                This method takes care to override and restore the cursor,
                but also catches exceptions and displays the error dialog.
        """
        QApplication.setOverrideCursor(Qt.WaitCursor)
        try:
            callback(self.tree.currentItem(), self.sender(), self, *params)

        except BaseError as e:
            # catch database errors and display the error dialog
            DlgDbError.showError(e, self)
            return

        finally:
            QApplication.restoreOverrideCursor()

    def unregisterAction(self, action, menuName):
        if not hasattr(self, '_registeredDbActions'):
            return

        if menuName is None or menuName == "":
            self.removeAction(action)

            if menuName in self._registeredDbActions:
                if self._registeredDbActions[menuName].count(action) > 0:
                    self._registeredDbActions[menuName].remove(action)

            action.deleteLater()
            return True

        for a in self.menuBar.actions():
            if not a.menu() or a.menu().title() != menuName:
                continue

            menu = a.menu()
            menuActions = menu.actions()

            menu.removeAction(action)
            if menu.isEmpty():  # hide the menu
                a.setVisible(False)

            if menuName in self._registeredDbActions:
                if self._registeredDbActions[menuName].count(action) > 0:
                    self._registeredDbActions[menuName].remove(action)

                # hide the placeholder if there're no other registered actions
                if len(self._registeredDbActions[menuName]) <= 0:
                    for i in range(len(menuActions)):
                        if menuActions[i].isSeparator() and menuActions[i].objectName().endswith("_placeholder"):
                            menuActions[i].setVisible(False)
                            break

            action.deleteLater()
            return True

        return False

    def unregisterAllActions(self):
        if not hasattr(self, '_registeredDbActions'):
            return

        for menuName in self._registeredDbActions:
            for action in list(self._registeredDbActions[menuName]):
                self.unregisterAction(action, menuName)
        del self._registeredDbActions

    def close_tab(self, index):
        widget = self.tabs.widget(index)
        if widget not in [self.info, self.table, self.preview]:
            self.tabs.removeTab(index)
            widget.deleteLater()

    def setupUi(self):
        self.setWindowTitle(self.tr("DB Manager"))
        self.setWindowIcon(QIcon(":/db_manager/icon"))
        self.resize(QSize(700, 500).expandedTo(self.minimumSizeHint()))

        # create central tab widget and add the first 3 tabs: info, table and preview
        self.tabs = QTabWidget()
        self.info = InfoViewer(self)
        self.tabs.addTab(self.info, self.tr("Info"))
        self.table = TableViewer(self)
        self.tabs.addTab(self.table, self.tr("Table"))
        self.preview = LayerPreview(self)
        self.tabs.addTab(self.preview, self.tr("Preview"))
        self.setCentralWidget(self.tabs)

        # display close button for all tabs but the first 3 ones, i.e.
        # HACK: just hide the close button where not needed (GS)
        self.tabs.setTabsClosable(True)
        self.tabs.tabCloseRequested.connect(self.close_tab)
        tabbar = self.tabs.tabBar()
        for i in range(3):
            btn = tabbar.tabButton(i, QTabBar.RightSide) if tabbar.tabButton(i, QTabBar.RightSide) else tabbar.tabButton(i, QTabBar.LeftSide)
            btn.resize(0, 0)
            btn.hide()

        # Creates layout for message bar
        self.layout = QGridLayout(self.info)
        self.layout.setContentsMargins(0, 0, 0, 0)
        spacerItem = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
        self.layout.addItem(spacerItem, 1, 0, 1, 1)
        # init messageBar instance
        self.infoBar = QgsMessageBar(self.info)
        sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)
        self.infoBar.setSizePolicy(sizePolicy)
        self.layout.addWidget(self.infoBar, 0, 0, 1, 1)

        # create database tree
        self.dock = QDockWidget("Tree", self)
        self.dock.setObjectName("DB_Manager_DBView")
        self.dock.setFeatures(QDockWidget.DockWidgetMovable)
        self.tree = DBTree(self)
        self.dock.setWidget(self.tree)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.dock)

        # create status bar
        self.statusBar = QStatusBar(self)
        self.setStatusBar(self.statusBar)

        # create menus
        self.menuBar = QMenuBar(self)
        self.menuDb = QMenu(self.tr("&Database"), self)
        self.menuBar.addMenu(self.menuDb)
        self.menuSchema = QMenu(self.tr("&Schema"), self)
        actionMenuSchema = self.menuBar.addMenu(self.menuSchema)
        self.menuTable = QMenu(self.tr("&Table"), self)
        actionMenuTable = self.menuBar.addMenu(self.menuTable)
        self.menuHelp = None  # QMenu(self.tr("&Help"), self)
        # actionMenuHelp = self.menuBar.addMenu(self.menuHelp)

        self.setMenuBar(self.menuBar)

        # create toolbar
        self.toolBar = QToolBar("Default", self)
        self.toolBar.setObjectName("DB_Manager_ToolBar")
        self.addToolBar(self.toolBar)

        # create menus' actions

        # menu DATABASE
        sep = self.menuDb.addSeparator()
        sep.setObjectName("DB_Manager_DbMenu_placeholder")
        sep.setVisible(False)

        self.actionRefresh = self.menuDb.addAction(QIcon(":/db_manager/actions/refresh"), self.tr("&Refresh"),
                                                   self.refreshActionSlot, QKeySequence("F5"))
        self.actionSqlWindow = self.menuDb.addAction(QIcon(":/db_manager/actions/sql_window"), self.tr("&SQL window"),
                                                     self.runSqlWindow, QKeySequence("F2"))
        self.menuDb.addSeparator()
        self.actionClose = self.menuDb.addAction(QIcon(), self.tr("&Exit"), self.close, QKeySequence("CTRL+Q"))

        # menu SCHEMA
        sep = self.menuSchema.addSeparator()
        sep.setObjectName("DB_Manager_SchemaMenu_placeholder")
        sep.setVisible(False)

        actionMenuSchema.setVisible(False)

        # menu TABLE
        sep = self.menuTable.addSeparator()
        sep.setObjectName("DB_Manager_TableMenu_placeholder")
        sep.setVisible(False)

        self.actionImport = self.menuTable.addAction(QIcon(":/db_manager/actions/import"),
                                                     self.tr("&Import layer/file"), self.importActionSlot)
        self.actionExport = self.menuTable.addAction(QIcon(":/db_manager/actions/export"), self.tr("&Export to file"),
                                                     self.exportActionSlot)
        self.menuTable.addSeparator()
        #self.actionShowSystemTables = self.menuTable.addAction(self.tr("Show system tables/views"), self.showSystemTables)
        #self.actionShowSystemTables.setCheckable(True)
        #self.actionShowSystemTables.setChecked(True)
        actionMenuTable.setVisible(False)

        # add actions to the toolbar
        self.toolBar.addAction(self.actionRefresh)
        self.toolBar.addAction(self.actionSqlWindow)
        self.toolBar.addAction(self.actionImport)
        self.toolBar.addAction(self.actionExport)
예제 #52
0
class fdtm:
    """QGIS Plugin Implementation."""
    def __init__(self, iface):
        """Constructor.

        :param iface: An interface instance that will be passed to this class
            which provides the hook by which you can manipulate the QGIS
            application at run time.
        :type iface: QgsInterface
        """
        # Save reference to the QGIS interface
        self.iface = iface

        # initialize plugin directory
        self.plugin_dir = os.path.dirname(__file__)

        # initialize locale
        locale = QSettings().value('locale/userLocale')[0:2]
        locale_path = os.path.join(self.plugin_dir, 'i18n',
                                   'fdtm_{}.qm'.format(locale))

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

            if qVersion() > '4.3.3':
                QCoreApplication.installTranslator(self.translator)

        # Declare instance attributes
        self.actions = []
        self.menu = self.tr(u'&fdtm')
        # TODO: We are going to let the user set this up in a future iteration
        self.toolbar = self.iface.addToolBar(u'fdtm')
        self.toolbar.setObjectName(u'fdtm')

        self.pluginIsActive = False

    # noinspection PyMethodMayBeStatic
    def tr(self, message):
        """Get the translation for a string using Qt translation API.

        We implement this ourselves since we do not inherit QObject.

        :param message: String for translation.
        :type message: str, QString

        :returns: Translated version of message.
        :rtype: QString
        """
        # noinspection PyTypeChecker,PyArgumentList,PyCallByClass
        return QCoreApplication.translate('fdtm', message)

    def add_action(self,
                   icon_path,
                   text,
                   callback,
                   enabled_flag=True,
                   add_to_menu='toolbar',
                   add_to_toolbar=True,
                   status_tip=None,
                   whats_this=None,
                   isMenu=None,
                   checkable=None,
                   checked=None,
                   parent=None):

        if not parent:
            parent = self.iface.mainWindow()

        icon = QIcon(icon_path)
        if add_to_menu == 'toolbar':
            action = QAction(icon, text, parent)
        else:
            action = self.tools[add_to_menu].menu().addAction(text)
            action.setActionGroup(self.tools[add_to_menu].actionGroup)
            add_to_toolbar = False

        if checkable:
            action.setCheckable(True)
            if checked:
                action.setChecked(True)
            if callback:
                action.toggled.connect(callback)
        else:
            if callback:
                action.triggered.connect(callback)
        action.setEnabled(enabled_flag)

        if status_tip is not None:
            action.setStatusTip(status_tip)

        if whats_this is not None:
            action.setWhatsThis(whats_this)

        if add_to_toolbar:
            self.toolbar.addAction(action)

        if isMenu:
            newMenu = QMenu()
            action.setMenu(newMenu)
            newActionGroup = QActionGroup(newMenu)
            action.actionGroup = newActionGroup

        if add_to_menu == 'toolbar':
            self.iface.addPluginToMenu(self.menu, action)

        self.actions.append(action)

        return action

    def initGui(self):
        """Create the menu entries and toolbar icons inside the QGIS GUI."""
        self.tools = {
            'about':
            self.add_action(
                os.path.join(self.plugin_dir, 'res', 'icon_00_about.png'),
                text=self.tr(u'about FDTM plugin'),
                callback=self.run_about,
            ),
            'settings':
            self.add_action(
                os.path.join(self.plugin_dir, 'res', 'icon_01_settings.png'),
                text=self.tr(u'settings'),
                callback=self.run_settings,
            ),
            'print':
            self.add_action(
                os.path.join(self.plugin_dir, 'res', 'icon_07_print.png'),
                text=self.tr(u'print'),
                callback=self.run_print,
                enabled_flag=False,
                isMenu=True,
            ),
            'summary':
            self.add_action(
                os.path.join(self.plugin_dir, 'res', 'icon_08_summary.png'),
                text=self.tr(u'summary'),
                callback=self.toggle_summary,
                enabled_flag=False,
            ),
            'info':
            self.add_action(
                os.path.join(self.plugin_dir, 'res', 'icon_06_info.png'),
                text=self.tr(u'info summary'),
                callback=self.run_info,
                enabled_flag=False,
                checkable=True,
            ),
            'EP':
            self.add_action(
                os.path.join(self.plugin_dir, 'res', 'icon_02_EP.png'),
                text=self.tr(u'input/edit strategies'),
                callback=self.run_EP,
                enabled_flag=False,
                checkable=True,
            ),
            'EA':
            self.add_action(
                os.path.join(self.plugin_dir, 'res', 'icon_03_EA.png'),
                text=self.tr(u'input/edit strategies'),
                callback=self.run_EA,
                enabled_flag=False,
                checkable=True,
            ),
            'WR':
            self.add_action(
                os.path.join(self.plugin_dir, 'res', 'icon_04_WR.png'),
                text=self.tr(u'input/edit water_rec'),
                callback=self.run_WR,
                enabled_flag=False,
                checkable=True,
                isMenu=True,
            ),
            'WDS':
            self.add_action(
                os.path.join(self.plugin_dir, 'res', 'icon_05_WDS.png'),
                text=self.tr(u'input/edit water_ds'),
                callback=self.run_WDS,
                enabled_flag=False,
                checkable=True,
            ),
            'DSV':
            self.add_action(
                os.path.join(self.plugin_dir, 'res', 'icon_09_DSV.png'),
                text=self.tr(u'rebuild dranaige system valve'),
                callback=self.run_DSV,
                enabled_flag=False,
                checkable=False,
            ),
        }

        self.tools['WRp'] = self.add_action(
            os.path.join(self.plugin_dir, 'res', 'icon_04_WR.png'),
            text=self.tr(u'point water_rec'),
            callback=None,  #self.check_WR,
            enabled_flag=True,
            checkable=True,
            add_to_menu='WR',
        )

        self.tools['WRg'] = self.add_action(
            os.path.join(self.plugin_dir, 'res', 'icon_04_WR.png'),
            text=self.tr(u'green roof water_rec'),
            callback=None,  #self.check_WR,
            enabled_flag=True,
            checkable=True,
            add_to_menu='WR')

        self.tools['WRl'] = self.add_action(
            os.path.join(self.plugin_dir, 'res', 'icon_04_WR.png'),
            text=self.tr(u'limited water_rec'),
            callback=None,  #self.check_WR,
            enabled_flag=True,
            checked=True,
            checkable=True,
            add_to_menu='WR')

        self.tools['Print project report'] = self.add_action(
            os.path.join(self.plugin_dir, 'res', 'icon_04_WR.png'),
            text=self.tr(u'print global report'),
            callback=self.print_global,
            enabled_flag=True,
            add_to_menu='print')

        self.tools['Print EP report'] = self.add_action(
            os.path.join(self.plugin_dir, 'res', 'icon_04_WR.png'),
            text=self.tr(u'print EP report'),
            callback=self.print_EP,
            enabled_flag=True,
            add_to_menu='print')

        self.tools['Print EA report'] = self.add_action(
            os.path.join(self.plugin_dir, 'res', 'icon_04_WR.png'),
            text=self.tr(u'print EA report'),
            callback=self.print_EA,
            enabled_flag=True,
            add_to_menu='print')

        self.tools['Print WR report'] = self.add_action(
            os.path.join(self.plugin_dir, 'res', 'icon_04_WR.png'),
            text=self.tr(u'print WR report'),
            callback=self.print_WR,
            enabled_flag=True,
            add_to_menu='print')

        self.tools['Print WDS report'] = self.add_action(
            os.path.join(self.plugin_dir, 'res', 'icon_04_WR.png'),
            text=self.tr(u'print WDS report'),
            callback=self.print_WDS,
            enabled_flag=True,
            add_to_menu='print')

        self.dlg_EA = fdtmEADialog()
        self.dlg_EP = fdtmEPDialog()
        self.dlg_WR = fdtmWRDialog()
        self.dlg_WDS = fdtmWDSDialog()
        self.dlg_info = fdtmInfoDialog()
        self.dlg_print = fdtmPrintDialog()
        self.dlg_settings = fdtmSettingsDialog(self)
        self.dlg_about = fdtmAboutDialog()
        self.dlg_about.webView.page().setNetworkAccessManager(
            QgsNetworkAccessManager.instance())
        # ---------------------------------------------------------------------

        self.dlg_settings.validated.connect(self.enableTools)

        self.dlg_summary = self.dlg_settings.getSummaryWidget()
        self.fdtmDockwidget = QDockWidget("FDTM summary",
                                          self.iface.mainWindow())
        self.fdtmDockwidget.setObjectName("fdtmSummary")
        self.fdtmDockwidget.setWidget(self.dlg_summary)
        self.iface.addDockWidget(Qt.BottomDockWidgetArea, self.fdtmDockwidget)
        self.fdtmDockwidget.hide()

    #--------------------------------------------------------------------------

    def enableTools(self, validated):
        tool_set = {
            'print': 'icon_07_print',
            'EP': 'icon_02_EP',
            'EA': 'icon_03_EA',
            'info': 'icon_06_info',
            'WR': 'icon_04_WR',
            'WDS': 'icon_05_WDS',
            'DSV': 'icon_09_DSV',
            'summary': 'icon_08_summary'
        }  #'print':'icon_07_print','WR':'icon_04_WR','WDS':'icon_05_WDS'
        if validated:
            disabled_sufx = ''
            self.fdtmDockwidget.show()
        else:
            disabled_sufx = '_disabled'
            self.fdtmDockwidget.hide()
        for t, f in tool_set.items():
            self.tools[t].setEnabled(validated)
            icon = QIcon(
                os.path.join(self.plugin_dir, 'res',
                             f + disabled_sufx + '.png'))
            self.tools[t].setIcon(icon)
        if self.dlg_settings.optionalDrainageSystemLayer.isChecked(
        ) and self.dlg_settings.optionalDrainageSystemLayer.DSVLayer():
            self.tools['DSV'].setEnabled(True)
            self.tools['DSV'].setIcon(
                QIcon(os.path.join(self.plugin_dir, 'res', 'icon_09_DSV.png')))
        else:
            self.tools['DSV'].setEnabled(False)
            self.tools['DSV'].setIcon(
                QIcon(
                    os.path.join(self.plugin_dir, 'res',
                                 'icon_09_DSV_disabled.png')))

    def unload(self):
        """Removes the plugin menu item and icon from QGIS GUI."""

        for action in self.actions:
            self.iface.removePluginMenu(self.tr(u'&fdtm'), action)
            self.iface.removeToolBarIcon(action)
        # remove the toolbar
        self.dlg_settings.deactivate()
        self.iface.removeDockWidget(self.fdtmDockwidget)
        del self.toolbar

    #--------------------------------------------------------------------------

    def setUncheckedActions(self, uncheckedActions):
        for action in uncheckedActions:
            self.tools[action].setChecked(False)

    def run_EP(self, checked):
        if checked:
            self.setUncheckedActions(['EA', 'WR', 'WDS'])
            self.dlg_settings.datasetWrapper.EPpWrapper.fdtm_startEditing()
        else:
            self.dlg_settings.datasetWrapper.EPpWrapper.confirmEdits()

    def run_EA(self, checked):
        if checked:
            self.setUncheckedActions(['EP', 'WR', 'WDS'])
            self.dlg_settings.datasetWrapper.EApWrapper.fdtm_startEditing()
        else:
            self.dlg_settings.datasetWrapper.EApWrapper.confirmEdits()

    def check_WR(self):
        self.tools['WR'].setChecked(True)

    def run_WR(self, checked):
        if checked:
            self.setUncheckedActions(['EA', 'EP', 'WDS'])
            if self.tools['WR'].actionGroup.checkedAction(
            ) == self.tools['WRp']:
                WRType = 'point'
            elif self.tools['WR'].actionGroup.checkedAction(
            ) == self.tools['WRl']:
                WRType = 'limited'
            elif self.tools['WR'].actionGroup.checkedAction(
            ) == self.tools['WRg']:
                WRType = 'greenroof'
            self.dlg_settings.datasetWrapper.WRWrapper.fdtm_startEditing(
                WRType)
            self.tools['WR'].actionGroup.setEnabled(False)
        else:
            self.dlg_settings.datasetWrapper.WRWrapper.confirmEdits()
            self.tools['WR'].actionGroup.setEnabled(True)

    def run_WDS(self, checked):
        if checked:
            self.setUncheckedActions(['EA', 'WR', 'EP'])
            self.dlg_settings.datasetWrapper.WDSWrapper.fdtm_startEditing()
        else:
            self.dlg_settings.datasetWrapper.WDSWrapper.confirmEdits()

    def toggle_summary(self):
        if self.fdtmDockwidget.isVisible():
            self.fdtmDockwidget.hide()
        else:
            self.fdtmDockwidget.show()

    def run_info(self, checked):
        if checked:
            self.backupMapTool = self.iface.mapCanvas().mapTool()
            layerList = [
                self.dlg_settings.EApLayer, self.dlg_settings.EPpLayer,
                self.dlg_settings.EPlLayer, self.dlg_settings.WRLayer,
                self.dlg_settings.WDSLayer
            ]
            if self.dlg_settings.optionalDrainageSystemLayer.DSVLayer():
                self.drainageSystemLayerManagement = True
                layerList.append(
                    self.dlg_settings.datasetWrapper.DSVWrapper.lyr)
            else:
                self.drainageSystemLayerManagement = False
            #print layerList
            self.fdtm_infoMapTool = IdentifyGeometry(
                self.iface.mapCanvas(), layerList, self.dlg_settings.DEMLayer)
            self.fdtm_infoMapTool.geomIdentified.connect(self.editFeature)
            self.iface.mapCanvas().setMapTool(self.fdtm_infoMapTool)
            self.iface.mapCanvas().mapToolSet.connect(self.restoreInfoAction)
        else:
            if self.backupMapTool:
                self.iface.mapCanvas().mapToolSet.disconnect(
                    self.restoreInfoAction)
                self.iface.mapCanvas().setMapTool(self.backupMapTool)

    def restoreInfoAction(self, MT):
        self.iface.mapCanvas().mapToolSet.disconnect(self.restoreInfoAction)
        self.backupMapTool = None
        self.tools['info'].setChecked(False)

    def editFeature(self, selLayer, selFeature, identifyPoint):
        if selLayer == self.dlg_settings.DEMLayer:
            if self.dlg_settings.datasetWrapper.DEMWrapper.contains(
                    identifyPoint):
                self.dlg_settings.datasetWrapper.DEMWrapper.viewSample(
                    identifyPoint)
            else:
                self.iface.messageBar().pushMessage(
                    "Info tool error",
                    "Sampling outside digital elevation model boundary",
                    level=1,
                    duration=3)  # QgsMessageBar.Warning
        elif self.drainageSystemLayerManagement and selLayer == self.dlg_settings.datasetWrapper.DSVWrapper.lyr:
            self.dlg_settings.datasetWrapper.DSVWrapper.fdtm_startEditing(
                changeActiveLayer=False)
            self.dlg_settings.datasetWrapper.DSVWrapper.editAttributes(
                selFeature)
            self.dlg_settings.datasetWrapper.DSVWrapper.fdtm_commitChanges()
        else:
            selLayer.fdtm_wrapper.editAttributes(selFeature)

    def run_settings(self):
        """Run method that loads and starts the plugin"""
        self.dlg_settings.show()

    def run_about(self):
        """Run method that loads and starts the plugin"""
        self.dlg_about.webView.load(QUrl("http://brigaid.eu/"))
        self.dlg_about.show()

    def run_print(self):
        """Run method that loads and starts the plugin"""
        self.tools['print'].menu().exec_(
            self.toolbar.mapToGlobal(QPoint(0, self.toolbar.height())))

    def print_global(self):
        fdtmPrint.exportGlobalReport(self.dlg_settings)

    def print_EP(self):
        fdtmPrint.exportEP(self.dlg_settings)

    def print_EA(self):
        fdtmPrint.exportEA(self.dlg_settings)

    def print_WR(self):
        fdtmPrint.exportWR(self.dlg_settings)

    def print_WDS(self):
        fdtmPrint.exportWDS(self.dlg_settings)

    def undef(self):
        pass

    def run_DSV(self):
        self.dlg_settings.datasetWrapper.DSVWrapper.rebuildLayer()
예제 #53
0
class MainWindow(QMainWindow, Ui_MainWindow):
    """The Main window of Luma.
    """

    logger = logging.getLogger(__name__)
    languages = {}
    translator = None
    languageHandler = None
    currentLanguage = ''

    def __init__(self, parent=None):
        """The constructor sets up the MainWindow widget, and connects
        all necessary signals and slots
        """
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        # We store the window size to make sure the previous window size
        # is restored when leaving fullscreen mode. This varible is used
        # in the toggleFullscreen slot.
        self.__tmpWinSize = self.size()
        self.eventFilter = LumaEventFilter(self)

        self.mainTabs.installEventFilter(self.eventFilter)

        self.translator = QTranslator()
        self.languageHandler = LanguageHandler()
        self.languages = self.languageHandler.availableLanguages

        #self.__createPluginToolBar()
        self.__createLoggerWidget()
        self.__loadSettings()
        self.__createLanguageOptions()

        self.setStatusBar(self.statusBar)

        self.mainTabs.setTabsClosable(True)
        self.mainTabs.setContextMenuPolicy(Qt.CustomContextMenu)
        self.mainTabs.customContextMenuRequested.connect(
            self.__mainTabsContextMenu)

        self.defaultTabStyle = ''
        self.lumaHeadStyle = 'background: url(:/icons/luma-gray);\n' + \
                     'background-position: bottom right;\n' + \
                     'background-attachment: fixed;\n' + \
                     'background-repeat:  no-repeat;'

        #Sets up pluginWidget
        #self in parameter is used to call pluginSelected here...
        self.pluginWidget = PluginListWidget(self)
        self.showPlugins()

        self.welcomeTab = WelcomeTab()
        self.welcomeTab.textBrowser.setStyleSheet(self.lumaHeadStyle)

        #This value comes from __loadSettings()
        #Its a checkbox set in WelcomeTab
        if self.showWelcomeSettings == 2:
            self.showWelcome()
        else:
            # Let's do some styling of the tab widget when no tabs are opened
            if self.mainTabs.currentIndex() == -1:
                self.__setTabWidgetStyle(self.lumaHeadStyle)

            self.actionShowWelcomeTab.setEnabled(True)

        self.serversChangedMessage = QErrorMessage(self)

    def __mainTabsContextMenu(self, pos):
        menu = QMenu()
        if self.mainTabs.count() > 0:
            return
            # The menu is displayed even when the rightclick is not
            # done over the actual tabs so to avoid confusion the
            # function is disabled entirey
            #menu.addAction(QApplication.translate(
            #    "MainWindow", "Close all plugin-tabs"), self.tabCloseAll)
        else:
            # If there's no tabs, offer to display the pluginlist
            menu.addAction(self.actionShowPluginList)
        menu.exec_(self.mainTabs.mapToGlobal(pos))

    def __createPluginToolBar(self):
        """Creates the pluign toolbar.
        """
        self.pluginToolBar = PluginToolBar(self)
        self.pluginToolBar.setWindowTitle(
            QApplication.translate('MainWindow', 'Plugintoolbar', None,
                                   QApplication.UnicodeUTF8))
        self.pluginToolBar.setObjectName('pluginToolBar')
        self.addToolBar(self.pluginToolBar)
        self.pluginToolBar.hide()

    def __createLoggerWidget(self):
        """Creates the logger widget.
        """
        self.loggerDockWindow = QDockWidget(self)
        self.loggerDockWindow.setObjectName('loggerDockWindow')
        self.loggerDockWindow.visibilityChanged[bool].connect(
            self.actionShowLogger.setChecked)
        self.loggerDockWindow.setWindowTitle(
            QApplication.translate('MainWindow', 'Logger', None,
                                   QApplication.UnicodeUTF8))
        self.loggerWidget = LoggerWidget(self.loggerDockWindow)
        self.loggerDockWindow.setWidget(self.loggerWidget)
        self.addDockWidget(Qt.BottomDockWidgetArea, self.loggerDockWindow)
        self.loggerDockWindow.hide()

    def __createLanguageOptions(self):
        """Creates the language selection in the menubar.
        """
        self.langGroup = QActionGroup(self)
        self.langGroup.setExclusive(True)
        self.langGroup.triggered['QAction*'].connect(self.languageChanged)

        for key, name in self.languages.iteritems():
            action = QAction(self)
            action.setCheckable(True)
            action.setData(key)
            action.setText(name[0])
            action.setStatusTip(name[1])
            action.setActionGroup(self.langGroup)
            self.menuLanguage.addAction(action)
            if key == self.currentLanguage:
                action.setChecked(True)

    def __loadSettings(self, mainWin=True):
        """Loads settings from file.

        :param mainWin: If set to ``False``, neither the values for the
         window size or the window position will be loaded. This is
         i.e done when the settings dialog returns 1.
        :type mainWin: bool
        """
        settings = Settings()
        # We might want to use these methods to restore the
        # application state and geometry.
        if mainWin:
            self.restoreGeometry(settings.geometry)
        #self.restoreState(settings.state)

        # If the geometry saved inticates fullscreen mode,
        # we need to explicitly set the fullscreen menuaction checkbox
        if self.isFullScreen():
            self.actionFullscreen.setChecked(True)

        # Logger

        # Logger
        # The `allwaysShowLoggerOnStart` a precedence on the
        # `showLogger` value.
        if settings.showLoggerOnStart:
            self.actionShowLogger.setChecked(True)
        else:
            self.actionShowLogger.setChecked(settings.showLogger)

        self.loggerWidget.errorBox.setChecked(settings.showErrors)
        self.loggerWidget.debugBox.setChecked(settings.showDebug)
        self.loggerWidget.infoBox.setChecked(settings.showInfo)

        self.toggleLoggerWindow(self.actionShowLogger.isChecked())

        # Language
        self.loadLanguage(settings.language)

        #Tabs
        self.showWelcomeSettings = settings.value("showWelcome", 2).toInt()[0]

    def __writeSettings(self):
        """Save settings to file.
        """
        settings = Settings()
        # We might want to use these methods to restore the
        # application state and geometry.
        settings.geometry = self.saveGeometry()
        #settings.state = self.saveState()

        # Mainwin
        #max = self.isMaximized()
        #settings.maximize = max
        #if not max:
        #    settings.size = self.size()
        #    settings.position = self.pos()

        # The global logger settings is managed from the settings dialog.
        # Logger
        settings.showLogger = self.actionShowLogger.isChecked()
        settings.showErrors = self.loggerWidget.errorBox.isChecked()
        settings.showDebug = self.loggerWidget.debugBox.isChecked()
        settings.showInfo = self.loggerWidget.infoBox.isChecked()

        # Language
        settings.language = self.currentLanguage

    def __switchTranslator(self, translator, qmFile):
        """Called when a new language is loaded.

        :param translator: The translator object to install.
        :type translator: QTranslator
        :qmFile: The translation file for the loaded language.
        :type qmFile: string
        """
        qApp.removeTranslator(translator)
        if translator.load(qmFile):
            qApp.installTranslator(translator)

    def __setTabWidgetStyle(self, stylesheet):
        self.mainTabs.setStyleSheet(stylesheet)

    @pyqtSlot('QAction*')
    @pyqtSlot(int)
    def languageChanged(self, value):
        """This slot is called by actions and signals related to
        application translations. The slot contains validation for
        those parameters defined by the pyqtSlot meta info in the
        method header.

        :param value: Can be either a ``QAction`` or an integer value.
         I.e. menu actions provide ``QActions`` but a ``QCombobox``
         might send it's index.
        :type value: QAction/int
        """
        locale = None
        if isinstance(value, int):
            locale = self.languageSelector.itemData(value).toString()
        elif isinstance(value, QAction):
            locale = value.data().toString()
        #else:
        #    locale = value
        if locale:
            self.loadLanguage(locale)

    def loadLanguage(self, locale):
        """Loads a language by the given language iso code.

        :param locale: A twoletter lowercase ISO 639 language code and
         possibly a twoletter uppercase ISO 3166 country code separeted
         by a underscore.
        :type locale: string
        """
        if self.currentLanguage != locale:
            self.currentLanguage = locale
            qmFile = self.languageHandler.getQmFile(locale)
            self.__switchTranslator(self.translator, qmFile)

    def changeEvent(self, event):
        """This event is called when a new translator is loaded or the
        system language (locale) is changed.

        :param event: The event that generated the `changeEvent`.
        :type event: QEvent
        """
        if None != event:
            type = event.type()
            if QEvent.LanguageChange == type or QEvent.LocaleChange == type:
                self.retranslateUi(self)
                self.loggerWidget.retranslateUi(self.loggerWidget)

    def showAboutLuma(self):
        """Slot for displaying the about dialog.
        """
        AboutDialog().exec_()

    @pyqtSlot(bool)
    def toggleLoggerWindow(self, show):
        """Slot for toggling the logger window.

        :param show: a boolean value indicating whether the logger window
         should be shown or not.
        :type show: bool
        """
        if show:
            self.loggerDockWindow.show()
        else:
            self.loggerDockWindow.hide()

    @pyqtSlot(bool)
    def toggleStatusbar(self, show):
        """Slot for toggling the logger window.

        :param show: a boolean value indicating whether the statusbar
         should be shown or not.
        :type show: bool
        """
        if show:
            self.statusBar.show()
        else:
            self.statusBar.hide()

    @pyqtSlot(bool)
    def toggleFullscreen(self, fullscreen):
        """Slot for toggling the logger window.

        :param fullscreen: a boolean value indicating whether to enter
         fullscreenmode or not.
        :type fullcreen: bool
        """
        if fullscreen:
            self.__tmpWinSize = self.size()
            self.showFullScreen()
        else:
            self.showNormal()
            self.resize(self.__tmpWinSize)

    def showServerEditor(self):
        """Slot to display the server editor dialog.
        """
        serverEditor = ServerDialog()
        r = serverEditor.exec_()
        if r:
            #TODO -- only display if plugins open:
            self.serversChangedMessage.showMessage(
                QApplication.translate(
                    "MainWindow",
                    "You may need to restart plugins for changes to take effect."
                ))

    def showTempPasswordDialog(self):
        """ Sets overridePassword for a server.
        Using this one doesn't actually have to enter the password
        in the ServerDialog (and by extension save to disk).
        """
        serverList = ServerList()

        # Create a stringlist to be used by the qinputdialog
        stringList = []
        for server in serverList.getTable():
            stringList.append(server.name)

        # Display list of servers
        (serverString, ok) = QInputDialog.getItem(
            self,
            QApplication.translate("MainWindow", "Select server"),
            QApplication.translate("MainWindow", "Server:"),
            stringList,
            editable=False)
        if ok:
            server = serverList.getServerObjectByName(serverString)
            if server != None:
                # Ask for password
                (value, ok) = QInputDialog.getText(
                    self,
                    QApplication.translate("MainWindow", "Temporary password"),
                    QApplication.translate("MainWindow", "Enter password:"******"""Slot to display the settings dialog. If the settings dialog
        returns 1, i.e. the user has clicked the ok button, the
        loadSettings method is called with mainWin=False, to load the
        (assumed) newly changed settings.

        :param tab: The index of the tab to display in the settings
         dialog.
        :type tab: int
        """
        #settingsDialog = SettingsDialog(self.currentLanguage, self.languages)
        settingsDialog = SettingsDialog()
        if tab < 0:
            tab = 0
        settingsDialog.tabWidget.setCurrentIndex(tab)
        if settingsDialog.exec_():
            self.reloadPlugins()


#            # We assume that some settings is changed
#            # if the user clicked the ok button, and
#            # reloads the application settings
#            self.__loadSettings(mainWin=False)
#            # A Hack but it'll do for now
#            for a in self.langGroup.actions():
#                if a.data().toString() == self.currentLanguage:
#                    a.setChecked(True)

    def configurePlugins(self):
        """Slot to display the plugins configuration. This currently
        calls `showSettingsDialog` with tab index set to 2.
        """
        self.showSettingsDialog(1)

    def reloadPlugins(self):
        """Slot to reload plugins.
        """
        self.pluginWidget.updatePlugins()

    def pluginSelected(self, item):
        """This method will be called from the `PluginListWidget`.
        """
        # Clear the stylesheet when a tab is opened
        self.__setTabWidgetStyle(self.defaultTabStyle)

        widget = item.plugin.getPluginWidget(None, self)

        if platform.system() == "Windows":
            scroll = QScrollArea()
            scroll.setWidget(widget)
            scroll.setWidgetResizable(True)
            index = self.mainTabs.addTab(scroll, item.icon(),
                                         item.plugin.pluginUserString)
        else:
            index = self.mainTabs.addTab(widget, item.icon(),
                                         item.plugin.pluginUserString)

        self.mainTabs.setCurrentIndex(index)

    def tabClose(self, index):
        """Slot for the signal `tabCloseRequest(int)` for the tabMains.
        """

        widget = self.mainTabs.widget(index)

        # If the tab closed is one of these, enable the toggle-action
        if widget == self.pluginWidget:
            self.actionShowPluginList.setEnabled(True)
        if widget == self.welcomeTab:
            self.actionShowWelcomeTab.setEnabled(True)

        self.mainTabs.removeTab(index)

        # Unparent the widget since it was reparented by the QTabWidget
        # so it's garbage collected
        widget.setParent(None)

        # In case the widget contained circular references
        # -- force GC to take care of the objects since there can be
        #    quite many if it was BrowserWidget that was closed.
        # Can't call it directly since that'll be too soon
        QTimer.singleShot(1000, self.gc)

        # Let's do some styling of the tab widget when no tabs are opened
        if self.mainTabs.currentIndex() == -1:
            self.__setTabWidgetStyle(self.lumaHeadStyle)

    def gc(self):
        """Runs Python's garbage-collection manually.
        Used to make sure circular references are taken care of *now*.
        """
        gc.collect()

    def showWelcome(self):
        """Shows the Welcome-tab
        """
        self.__setTabWidgetStyle(self.defaultTabStyle)
        index = self.mainTabs.addTab(
            self.welcomeTab, QApplication.translate("MainWindow", "Welcome"))

        self.mainTabs.setCurrentIndex(index)
        self.actionShowWelcomeTab.setEnabled(False)

    def showPlugins(self):
        """Will show the pluginlistwidget-tab
        """
        self.__setTabWidgetStyle(self.defaultTabStyle)
        if self.mainTabs.indexOf(self.pluginWidget) == -1:
            index = self.mainTabs.addTab(
                self.pluginWidget,
                QApplication.translate("MainWindow", "Plugins"))
            self.mainTabs.setCurrentIndex(index)
            self.actionShowPluginList.setEnabled(False)

    def closeEvent(self, e):
        """Overrides the ``QMainWindow.closeEvent`` slot to save
        settings before we tear down the application.
        """
        self.__writeSettings()
        QMainWindow.closeEvent(self, e)
예제 #54
0
class ViewerWnd(QMainWindow):
    def __init__(self, app, dictOpts):
        QMainWindow.__init__(self)
        self.setWindowTitle("PostGIS Layer Viewer - v.1.6.1")
        self.setTabPosition(Qt.BottomDockWidgetArea, QTabWidget.North)

        self.canvas = QgsMapCanvas()
        self.canvas.setCanvasColor(Qt.white)
        self.canvas.useImageToRender(True)
        self.canvas.enableAntiAliasing(True)
        self.setCentralWidget(self.canvas)

        actionZoomIn = QAction(QIcon(imgs_dir + "mActionZoomIn.png"),
                               QString("Zoom in"), self)
        actionZoomOut = QAction(QIcon(imgs_dir + "mActionZoomOut.png"),
                                QString("Zoom out"), self)
        actionPan = QAction(QIcon(imgs_dir + "mActionPan.png"), QString("Pan"),
                            self)
        actionZoomFullExtent = QAction(
            QIcon(imgs_dir + "mActionZoomFullExtent.png"),
            QString("Zoom full"), 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.connect(actionZoomFullExtent, SIGNAL("triggered()"),
                     self.zoomFullExtent)

        self.actionGroup = QActionGroup(self)
        self.actionGroup.addAction(actionPan)
        self.actionGroup.addAction(actionZoomIn)
        self.actionGroup.addAction(actionZoomOut)

        # Create the toolbar
        self.toolbar = self.addToolBar("Map tools")
        self.toolbar.addAction(actionPan)
        self.toolbar.addAction(actionZoomIn)
        self.toolbar.addAction(actionZoomOut)
        self.toolbar.addAction(actionZoomFullExtent)

        # 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)

        # Create the statusbar
        self.statusbar = QStatusBar(self)
        self.statusbar.setObjectName("statusbar")
        self.setStatusBar(self.statusbar)

        self.lblXY = QLabel()
        self.lblXY.setFrameStyle(QFrame.Box)
        self.lblXY.setMinimumWidth(170)
        self.lblXY.setAlignment(Qt.AlignCenter)
        self.statusbar.setSizeGripEnabled(False)
        self.statusbar.addPermanentWidget(self.lblXY, 0)

        self.lblScale = QLabel()
        self.lblScale.setFrameStyle(QFrame.StyledPanel)
        self.lblScale.setMinimumWidth(140)
        self.statusbar.addPermanentWidget(self.lblScale, 0)

        self.createLegendWidget()  # Create the legend widget

        self.connect(app, SIGNAL("loadPgLayer"), self.loadLayer)
        self.connect(self.canvas, SIGNAL("scaleChanged(double)"),
                     self.changeScale)
        self.connect(self.canvas, SIGNAL("xyCoordinates(const QgsPoint&)"),
                     self.updateXY)

        self.pan()  # Default

        self.plugins = Plugins(self, self.canvas, dictOpts['-h'],
                               dictOpts['-p'], dictOpts['-d'], dictOpts['-U'],
                               dictOpts['-W'])

        self.createAboutWidget()
        self.layerSRID = '-1'
        self.loadLayer(dictOpts)

    def zoomIn(self):
        self.canvas.setMapTool(self.toolZoomIn)

    def zoomOut(self):
        self.canvas.setMapTool(self.toolZoomOut)

    def pan(self):
        self.canvas.setMapTool(self.toolPan)

    def zoomFullExtent(self):
        self.canvas.zoomToFullExtent()

    def about(self):
        pass

    def createLegendWidget(self):
        """ Create the map legend widget and associate it to the canvas """
        self.legend = Legend(self)
        self.legend.setCanvas(self.canvas)
        self.legend.setObjectName("theMapLegend")

        self.LegendDock = QDockWidget("Layers", self)
        self.LegendDock.setObjectName("legend")
        self.LegendDock.setTitleBarWidget(QWidget())
        self.LegendDock.setWidget(self.legend)
        self.LegendDock.setContentsMargins(0, 0, 0, 0)
        self.addDockWidget(Qt.BottomDockWidgetArea, self.LegendDock)

    def createAboutWidget(self):
        self.AboutDock = QDockWidget("About", self)
        self.AboutDock.setObjectName("about")
        self.AboutDock.setTitleBarWidget(QWidget())
        self.AboutDock.setContentsMargins(0, 0, 0, 0)
        self.tabifyDockWidget(self.LegendDock, self.AboutDock)
        self.LegendDock.raise_()  # legendDock at the top

        from PyQt4.QtCore import QRect
        from PyQt4.QtGui import QSizePolicy, QGridLayout, QFont
        font = QFont()
        font.setFamily("Sans Serif")
        font.setPointSize(8.7)
        self.AboutWidget = QWidget()
        self.AboutWidget.setFont(font)
        self.AboutWidget.setObjectName("AboutWidget")
        self.AboutDock.setWidget(self.AboutWidget)
        self.labelAbout = QLabel(self.AboutWidget)
        self.labelAbout.setAlignment(Qt.AlignCenter)
        self.labelAbout.setWordWrap(True)
        self.gridLayout = QGridLayout(self.AboutWidget)
        self.gridLayout.setContentsMargins(0, 0, 0, 0)
        self.gridLayout.setObjectName("gridLayout")
        self.gridLayout.addWidget(self.labelAbout, 0, 1, 1, 1)
        self.labelAbout.setTextInteractionFlags(Qt.LinksAccessibleByMouse
                                                | Qt.LinksAccessibleByKeyboard
                                                | Qt.TextSelectableByKeyboard
                                                | Qt.TextSelectableByMouse)
        self.labelAbout.setOpenExternalLinks(True)
        self.labelAbout.setText("<html><head/><body><a href=\"http://geotux.tuxfamily.org/index.php/en/geo-blogs/item/293-consola-sql-para-plugin-pgadmin-postgis-viewer\">PostGIS Layer Viewer</a> v.1.6.1 (2015.02.24)<br \><br \>" \
            "Copyright (c) 2010 Ivan Mincik,<br \>[email protected]<br \>" \
            u"Copyright (c) 2011-2015 Germán Carrillo,<br \>[email protected]<br \><br \>" \
            "<i>Licensed under the terms of GNU GPL v.2.0</i><br \><br \>" \
            "Based on PyQGIS. Plugin Fast SQL Layer by Pablo T. Carreira.</body></html>" )

    def loadLayer(self, dictOpts):
        print 'I: Loading the layer...'
        self.layerSRID = dictOpts[
            'srid']  # To access the SRID when querying layer properties

        if not self.isActiveWindow():
            self.activateWindow()
            self.raise_()

        if dictOpts['type'] == 'vector':
            # QGIS connection
            uri = QgsDataSourceURI()
            uri.setConnection(dictOpts['-h'], dictOpts['-p'], dictOpts['-d'],
                              dictOpts['-U'], dictOpts['-W'])
            uri.setDataSource(dictOpts['-s'], dictOpts['-t'], dictOpts['-g'])
            layer = QgsVectorLayer(uri.uri(),
                                   dictOpts['-s'] + '.' + dictOpts['-t'],
                                   "postgres")
        elif dictOpts['type'] == 'raster':
            connString = "PG: dbname=%s host=%s user=%s password=%s port=%s mode=2 " \
                "schema=%s column=%s table=%s" % ( dictOpts['-d'], dictOpts['-h'],
                dictOpts['-U'], dictOpts['-W'], dictOpts['-p'], dictOpts['-s'],
                dictOpts['col'], dictOpts['-t'] )
            layer = QgsRasterLayer(connString,
                                   dictOpts['-s'] + '.' + dictOpts['-t'])

            if layer.isValid():
                layer.setContrastEnhancement(
                    QgsContrastEnhancement.StretchToMinimumMaximum)

        self.addLayer(layer, self.layerSRID)

    def addLayer(self, layer, srid='-1'):
        if layer.isValid():
            # Only in case that srid != -1, read the layer SRS properties, otherwise don't since it will return 4326
            if srid != '-1':
                self.layerSRID = layer.crs().description() + ' (' + str(
                    layer.crs().postgisSrid()) + ')'
            else:
                self.layerSRID = 'Unknown SRS (-1)'

            if self.canvas.layerCount() == 0:
                self.canvas.setExtent(layer.extent())

                if srid != '-1':
                    print 'I: Map SRS (EPSG): %s' % self.layerSRID
                    self.canvas.setMapUnits(layer.crs().mapUnits())
                else:
                    print 'I: Unknown Reference System'
                    self.canvas.setMapUnits(0)  # 0: QGis.Meters

            return QgsMapLayerRegistry.instance().addMapLayer(layer)
        return False

    def activeLayer(self):
        """ Returns the active layer in the layer list widget """
        return self.legend.activeLayer()

    def getLayerProperties(self, l):
        """ Create a layer-properties string (l:layer)"""
        print 'I: Generating layer properties...'
        if l.type() == 0:  # Vector
            wkbType = [
                "WKBUnknown", "WKBPoint", "WKBLineString", "WKBPolygon",
                "WKBMultiPoint", "WKBMultiLineString", "WKBMultiPolygon",
                "WKBNoGeometry", "WKBPoint25D", "WKBLineString25D",
                "WKBPolygon25D", "WKBMultiPoint25D", "WKBMultiLineString25D",
                "WKBMultiPolygon25D"
            ]
            properties = "Source: %s\n" \
                         "Geometry type: %s\n" \
                         "Number of features: %s\n" \
                         "Number of fields: %s\n" \
                         "SRS (EPSG): %s\n" \
                         "Extent: %s " \
                          % ( l.source(), wkbType[l.wkbType()], l.featureCount(),
                              l.dataProvider().fields().count(), self.layerSRID,
                              l.extent().toString() )
        elif l.type() == 1:  # Raster
            rType = [
                "GrayOrUndefined (single band)", "Palette (single band)",
                "Multiband", "ColorLayer"
            ]
            properties = "Source: %s\n" \
                         "Raster type: %s\n" \
                         "Width-Height (pixels): %sx%s\n" \
                         "Bands: %s\n" \
                         "SRS (EPSG): %s\n" \
                         "Extent: %s" \
                         % ( l.source(), rType[l.rasterType()], l.width(), l.height(),
                             l.bandCount(), self.layerSRID, l.extent().toString() )

        self.layerSRID = '-1'  # Initialize the srid
        return properties

    def changeScale(self, scale):
        self.lblScale.setText("Scale 1:" + formatNumber(scale))

    def updateXY(self, p):
        if self.canvas.mapUnits() == 2:  # Degrees
            self.lblXY.setText( formatToDegrees( p.x() ) + " | " \
                + formatToDegrees( p.y() ) )
        else:  # Unidad lineal
            self.lblXY.setText( formatNumber( p.x() ) + " | " \
                + formatNumber( p.y() ) + "" )
예제 #55
0
파일: main.py 프로젝트: terrence2/millipede
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)