コード例 #1
0
 def start_watching(self):
     self.__watcher = QFileSystemWatcher(self)
     self.connect(self.__watcher, SIGNAL("fileChanged(const QString&)"),
                  self._file_changed)
     if self._file_path is not None:
         self.__mtime = os.path.getmtime(self._file_path)
         self.__watcher.addPath(self._file_path)
コード例 #2
0
    def __init__(self, do):
        QObject.__init__(self)

        self.ptyhandler = PtyHandler()

        self.do = do

        self.connector = self.do.gdb_connector
        self.signalProxy = self.do.signalProxy

        self.executableName = None
        self.lastCmdWasStep = False

        self.ptyhandler.start()
        self.connector.start()

        self.connector.reader.asyncRecordReceived.connect(self.handleAsyncRecord, Qt.QueuedConnection)

        self.__config = DebugConfig()
        self.do.configStore.registerConfigSet(self.__config)
        self.__config.itemsHaveChanged.connect(self.updateConfig)

        self.__binaryWatcher = QFileSystemWatcher()
        self.__binaryWatcher.fileChanged.connect(self.__binaryChanged)

        self.do.signalProxy.addProxy(["openExecutable", "run", "setRecord", "next_", "reverse_next", "step", "reverse_step", "cont", "interrupt", "finish", "reverse_finish", "evaluateExpression", "executeCliCommand", "inferiorUntil", "getStackDepth", "selectStackFrame"], self)
コード例 #3
0
 def _start_file_watcher(self):
     self.watcher = QFileSystemWatcher()
     self.watcher_file_path =  join(abspath("."), self._watcher_file_name)
     log.DEBUG("creating watcher file: %s" %(self.watcher_file_path))
     write_to_file(self.watcher_file_path, "Delete this file to shutdown D2MP\n")
     self.watcher.addPath(abspath("."))
     self.watcher.directoryChanged.connect(self._watcher_changed_callback)
コード例 #4
0
    def __init__(self):
        QTreeWidget.__init__(self)

        self.header().setHidden(True)
        self.setSelectionMode(QTreeWidget.SingleSelection)
        self.setAnimated(True)

        self._actualProject = None
        #self._projects -> key: [Item, folderStructure]
        self._projects = {}
        self.__enableCloseNotification = True
        self._fileWatcher = QFileSystemWatcher()

        self.header().setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel)
        self.header().setResizeMode(0, QHeaderView.ResizeToContents)
        self.header().setStretchLastSection(False)

        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.connect(self, SIGNAL(
            "customContextMenuRequested(const QPoint &)"),
            self._menu_context_tree)
        self.connect(self, SIGNAL("itemClicked(QTreeWidgetItem *, int)"),
            self._open_file)
        self.connect(self._fileWatcher, SIGNAL("directoryChanged(QString)"),
            self._refresh_project_by_path)
コード例 #5
0
    def __init__(self, parent=None):
        super(ProjectWidget, self).__init__(parent)
        self.setupUi(self)
        self.project = None
        self.bar = None
        self.roamapp = None

        menu = QMenu()

        # self.roamVersionLabel.setText("You are running IntraMaps Roam version {}".format(roam.__version__))

        self.openProjectFolderButton.pressed.connect(self.openprojectfolder)
        self.openinQGISButton.pressed.connect(self.openinqgis)
        self.depolyProjectButton.pressed.connect(self.deploy_project)
        self.depolyInstallProjectButton.pressed.connect(functools.partial(self.deploy_project, True))

        self.filewatcher = QFileSystemWatcher()
        self.filewatcher.fileChanged.connect(self.qgisprojectupdated)

        self.projectupdatedlabel.linkActivated.connect(self.reloadproject)
        self.projectupdatedlabel.hide()

        # self.setpage(4)
        self.currentnode = None
        self.form = None

        qgislocation = r'C:\OSGeo4W\bin\qgis.bat'
        qgislocation = roam.config.settings.setdefault('configmanager', {}) \
            .get('qgislocation', "")

        self.qgispathEdit.setText(qgislocation)
        self.qgispathEdit.textChanged.connect(self.save_qgis_path) 
        self.filePickerButton.pressed.connect(self.set_qgis_path)

        self.connect_page_events()
コード例 #6
0
 def __init__(self, ctx):
     from PyQt4.QtCore import QFileSystemWatcher
     self.ctx = ctx
     self.cache = {}
     self.watcher = QFileSystemWatcher()
     self.watcher.fileChanged.connect(self._file_changed)
     self.options = '-I ' + os.path.join(os.path.dirname(__file__),
                                         'kernels')
コード例 #7
0
 def __init__(self, path):
     QObject.__init__(self)
     self._contents = None
     self._watcher = QFileSystemWatcher()
     self._timer = None
     self._path = path
     self.setPath(path)
     self.enable()
コード例 #8
0
 def start_watching(self):
     """Create a file system watcher and connect its fileChanged
     SIGNAL to our _file_changed SLOT"""
     if not self.__watcher:
         self.__watcher = QFileSystemWatcher(self)
         self.connect(self.__watcher, SIGNAL("fileChanged(const QString&)"),
                      self._file_changed)
     if self._file_path is not None:
         self.__mtime = os.path.getmtime(self._file_path)
         self.__watcher.addPath(self._file_path)
コード例 #9
0
ファイル: object_file.py プロジェクト: yoshitomimaehara/edis
    def run_system_watcher(self):
        """ Inicializa el control de monitoreo para modificaciones """

        if self._system_watcher is None:
            self._system_watcher = QFileSystemWatcher()
            self.connect(self._system_watcher,
                         SIGNAL("fileChanged(const QString&)"),
                         self._on_file_changed)
        self._last_modification = os.lstat(self.filename).st_mtime
        self._system_watcher.addPath(self.filename)
        DEBUG("Watching {0}".format(self.filename))
コード例 #10
0
    def __init__(self, path):
        QObject.__init__(self)
        self._contents = None
        self._watcher = QFileSystemWatcher()
        self._timer = None
        self._path = path

        self._lastEmittedModifiedStatus = None
        self._lastEmittedRemovedStatus = None

        self.setPath(path)
        self.enable()
コード例 #11
0
ファイル: mainwindow.py プロジェクト: bernschab/ricodebug
    def __init__(self, parent=None):
        """ init UI """
        QMainWindow.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.ui.actionSaveSession.setEnabled(False)

        self.distributedObjects = DistributedObjects()

        self.act = self.distributedObjects.actions
        self.debugController = self.distributedObjects.debugController
        self.settings = self.debugController.settings
        self.signalproxy = self.distributedObjects.signalProxy
        self.pluginloader = PluginLoader(self.distributedObjects)
        self.editorController = self.distributedObjects.editorController

        self.act = self.distributedObjects.actions
        # init RecentFileHandler
        self.recentFileHandler = RecentFileHandler(self, self.ui.menuRecentlyUsedFiles, self.distributedObjects)
        self.debugController.executableOpened.connect(self.recentFileHandler.addToRecentFiles)
        self.debugController.executableOpened.connect(self.__observeWorkingBinary)
        self.debugController.executableOpened.connect(self.showExecutableName)
        self.debugController.executableOpened.connect(self.disableButtons)
        # signal proxy
        self.signalproxy.inferiorIsRunning.connect(self.targetStartedRunning, Qt.QueuedConnection)
        self.signalproxy.inferiorStoppedNormally.connect(self.targetStopped, Qt.QueuedConnection)
        self.signalproxy.inferiorReceivedSignal.connect(self.targetStopped, Qt.QueuedConnection)
        self.signalproxy.inferiorHasExited.connect(self.targetExited, Qt.QueuedConnection)

        self.signalproxy.addDockWidget.connect(self.addPluginDockWidget)
        self.signalproxy.removeDockWidget.connect(self.removeDockWidget)

        # Plugin Loader
        self.pluginloader.insertPluginAction.connect(self.addPluginAction)

        self.ui.actionSavePlugins.triggered.connect(self.showSavePluginsDialog)
        self.ui.actionLoadPlugins.triggered.connect(self.showLoadPluginsDialog)

        # Add editor to main window.
        self.ui.gridLayout.addWidget(self.distributedObjects.editorController.editor_view, 0, 0, 1, 1)

        self.pluginloader.addAvailablePlugins()

        # Tell everyone to insert their dock widgets into the main window
        self.signalproxy.emitInsertDockWidgets()

        # get filelist dockwidget
        self.filelist_dockwidget = self.findChild(QDockWidget, "FileListView")

        self.setWindowFilePath("<none>")
        self.setupUi()
        self.createInitialWindowPlacement()
        self.readSettings()

        self.quickwatch = QuickWatch(self, self.distributedObjects)

        self.binaryName = None
        self.fileWatcher = QFileSystemWatcher()
        self.fileWatcher.fileChanged.connect(self.__binaryChanged)
コード例 #12
0
ファイル: nfile.py プロジェクト: emilioramirez/ninja-ide
 def start_watching(self):
     self.__watcher = QFileSystemWatcher(self)
     self.connect(self.__watcher, SIGNAL("fileChanged(const QString&)"),
         self._file_changed)
     if self._file_path is not None:
         self.__mtime = os.path.getmtime(self._file_path)
         self.__watcher.addPath(self._file_path)
コード例 #13
0
ファイル: orange.py プロジェクト: scroll/orange
 def __init__(self, ctx):
     from PyQt4.QtCore import QFileSystemWatcher
     self.ctx = ctx
     self.cache = {}
     self.watcher = QFileSystemWatcher()
     self.watcher.fileChanged.connect(self._file_changed)
     self.options = '-I ' + os.path.join(os.path.dirname(__file__), 'kernels')
コード例 #14
0
ファイル: ImageBrowser.py プロジェクト: ChunChia/ipbec
    def __init__(self, settings, parent):
        super(ImageBrowser, self).__init__(parent=parent)
        self.settings = settings
        self.main_window = parent

        self.current_directory = default_image_dir
        self.path_to_dark_file = default_dark_path
        self.path_to_json_db = os.path.join(main_package_dir,
                                            'image_save_info.json')

        self.current_image_info = {}

        self.setupUi(self)
        self.loadSettings()
        self.is_cleaned = False
        self.use_roi_while_cleaning = False

        self.connectSignalsToSlots()

        self.image_list = clt.ImageList()
        self.updateFileList(new_dir=True)
        self.current_image_index = 0

        self.watcher = QFileSystemWatcher(self)
        self.watcher.addPath(self.current_directory)
        self.watcher.directoryChanged.connect(
            self.handleWatcherDirectoryChanged)
        self.updateCommentBox()
コード例 #15
0
ファイル: stracerunner.py プロジェクト: juruen/inspyktor
    def _prepare_trace(self):
        temp_file = kdecore.KTemporaryFile()
        temp_file.setAutoRemove(False)
        temp_file.open()
        temp_file_name = temp_file.fileName()
        temp_file.close()
        self._out_file = QFile(temp_file_name)
        self._out_file.open(QIODevice.ReadOnly | QIODevice.Text)

        kproc_args = []
        kproc_args.extend(['-o', temp_file_name, '-ttt', '-T', '-f'])
        if self.pid() is  None:
            kproc_args.append(self._command)
            kproc_args.extend(self.trace_args())
        else:
            kproc_args.extend(["-p", self.pid()])

        self._strace = kdecore.KProcess(self)
        self._strace.setProgram("/usr/bin/strace", kproc_args)
        print kproc_args

        # Create watcher for temporary ile as that's where strace
        # is oging to dump its output
        self._file_watcher = QFileSystemWatcher([temp_file_name], self)

        self.connect(self._strace,
            SIGNAL('finished(int,QProcess::ExitStatus)'),
            self._slot_process_finished)

        self.connect(self._file_watcher, SIGNAL('fileChanged (QString)'),
            self._slot_ready_read)
コード例 #16
0
    def regenerate(self):
        def recursiveAddPath(filePath):
            """ recursively add files and directories to watcher """
            watcher.addPath(filePath)
            fileList = QDir(filePath).entryInfoList(QDir.Dirs | QDir.Files
                                                    | QDir.NoDotAndDotDot)
            for f in fileList:
                recursiveAddPath(f.absoluteFilePath())

        def directoryChanged(filePath):
            watchedFiles = watcher.directories() + watcher.files()
            fileList = QDir(filePath).entryInfoList(QDir.Dirs | QDir.Files
                                                    | QDir.NoDotAndDotDot)
            for f in fileList:
                if f.absoluteFilePath() not in watchedFiles:
                    watcher.addPath(f.absoluteFilePath())

            self.generate()

        # QFileSystemWatcher won't work without a QApplication!
        app = QApplication(sys.argv)
        watcher = QFileSystemWatcher()
        recursiveAddPath(self.notepath)

        # add/remove file triggers this
        watcher.directoryChanged.connect(directoryChanged)
        # edit file triggers this
        watcher.fileChanged.connect(self.generate)
        sys.exit(app.exec_())
コード例 #17
0
    def __init__(self, appid, *args, **kwargs):
        import webplier

        self.appid = appid
        xdg.DesktopEntry.DesktopEntry.__init__(self, *args, **kwargs)

        self.setWindowWidth = partial(xdg.DesktopEntry.DesktopEntry.set, self, 'X-%s-Window-Width' % APP_NAME)
        self.getWindowWidth = partial(xdg.DesktopEntry.DesktopEntry.get, self, 'X-%s-Window-Width' % APP_NAME)
        self.setWindowHeight = partial(xdg.DesktopEntry.DesktopEntry.set, self, 'X-%s-Window-Height' % APP_NAME)
        self.getWindowHeight = partial(xdg.DesktopEntry.DesktopEntry.get, self, 'X-%s-Window-Height' % APP_NAME)

        self.setBaseUrl = partial(xdg.DesktopEntry.DesktopEntry.set, self, 'X-%s-BaseUrl' % APP_NAME)
        self.getBaseUrl = partial(xdg.DesktopEntry.DesktopEntry.get, self, 'X-%s-BaseUrl' % APP_NAME)

        self.setName = partial(xdg.DesktopEntry.DesktopEntry.set, self, 'Name')

        if not self.hasGroup('Desktop Entry'):
            self.addGroup('Desktop Entry')

        pythonPath = 'python2.7'
        for p in os.environ["PATH"].split(os.pathsep):
            if os.path.exists(os.path.join(p, 'python2.7')):
                pythonPath = os.path.join(p, 'python2.7')
                break

        webplierPath = 'plier'
        for p in os.environ["PATH"].split(os.pathsep):
            if os.path.exists(os.path.join(p, 'plier')):
                webplierPath = os.path.join(p, 'plier')
                break

        if not self.get('Exec'):
            self.set('Exec', '%s %s %s' % (pythonPath, webplierPath, self.appid))

        self.set('X-%s-Type' % APP_NAME, 'Webapp')
        self.set('X-%s-AppId' % APP_NAME, appid)

        self.set('StartupWMClass', appid)

        # TODO: Get this working.

        self.watcher = QFileSystemWatcher()
        self.addPath(getPath('%s-%s.desktop' % (APP_NAME.lower(), self.appid)))
        self.watcher.fileChanged.connect(self._refreshFromFilesystem)

        self.onRefresh = None
コード例 #18
0
ファイル: abstractdocument.py プロジェクト: polovik/enki
 def __init__(self, path):
     QObject.__init__(self)
     self._contents = None
     self._watcher = QFileSystemWatcher()
     self._timer = None
     self._path = path
     self.setPath(path)
     self.enable()
コード例 #19
0
ファイル: mainwindow.py プロジェクト: vermak/ricodebug
    def __init__(self, parent=None):
        """ init UI """
        QMainWindow.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.ui.actionSaveSession.setEnabled(False)

        self.distributedObjects = DistributedObjects(self)

        self.act = self.distributedObjects.actions
        self.debugController = self.distributedObjects.debugController
        self.settings = self.distributedObjects.settings
        self.signalproxy = self.distributedObjects.signalProxy
        self.pluginloader = PluginLoader(self.distributedObjects)
        self.editorController = self.distributedObjects.editorController

        self.act = self.distributedObjects.actions
        # init RecentFileHandler
        self.recentFileHandler = RecentFileHandler(self, self.ui.menuRecentlyUsedFiles, self.distributedObjects)
        self.debugController.executableOpened.connect(self.recentFileHandler.addToRecentFiles)
        self.debugController.executableOpened.connect(self.__observeWorkingBinary)
        self.debugController.executableOpened.connect(self.showExecutableName)
        self.debugController.executableOpened.connect(self.disableButtons)
        # signal proxy
        self.signalproxy.inferiorIsRunning.connect(self.targetStartedRunning)
        self.signalproxy.inferiorStoppedNormally.connect(self.targetStopped)
        self.signalproxy.inferiorReceivedSignal.connect(self.targetStopped)
        self.signalproxy.inferiorHasExited.connect(self.targetExited)

        # Plugin Loader
        self.pluginloader.insertPluginAction.connect(self.addPluginAction)

        self.ui.actionSavePlugins.triggered.connect(self.showSavePluginsDialog)
        self.ui.actionLoadPlugins.triggered.connect(self.showLoadPluginsDialog)

        # Add editor to main window.
        self.ui.gridLayout.addWidget(self.distributedObjects.editorController.editor_view, 0, 0, 1, 1)

        self.pluginloader.addAvailablePlugins()

        self.setWindowFilePath("<none>")
        self.setupUi()
        self.readSettings()

        self.quickwatch = QuickWatch(self, self.distributedObjects)

        self.binaryName = None
        self.fileWatcher = QFileSystemWatcher()
        self.fileWatcher.fileChanged.connect(self.__binaryChanged)

        self.__runWithArgumentsMenu = None
        self.__argumentsEdit = None
        self.__makeRunWithArgumentsMenu()
コード例 #20
0
ファイル: object_file.py プロジェクト: Garjy/edis
    def run_system_watcher(self):
        """ Inicializa el control de monitoreo para modificaciones """

        if self._system_watcher is None:
            self._system_watcher = QFileSystemWatcher()
            self.connect(self._system_watcher,
                         SIGNAL("fileChanged(const QString&)"),
                         self._on_file_changed)
        self._last_modification = os.lstat(self.filename).st_mtime
        self._system_watcher.addPath(self.filename)
        DEBUG("Watching {0}".format(self.filename))
コード例 #21
0
def init(filename):
    info("Initial Syncing excel to shp")
    update_shp_from_excel()
    global filewatcher  # otherwise the object is lost
    filewatcher = QFileSystemWatcher([filename])
    filewatcher.fileChanged.connect(excel_changed)
    shpLayer = layer_from_name(shpName)
    shpLayer.committedFeaturesAdded.connect(added_geom)
    shpLayer.committedFeaturesRemoved.connect(removed_geom)
    shpLayer.committedGeometriesChanges.connect(changed_geom)
    shpLayer.editingStopped.connect(update_excel_from_shp)
コード例 #22
0
ファイル: nfile.py プロジェクト: AnyBucket/ninja-ide
 def start_watching(self):
     """Create a file system watcher and connect its fileChanged
     SIGNAL to our _file_changed SLOT"""
     if not self.__watcher:
         self.__watcher = QFileSystemWatcher(self)
         self.connect(self.__watcher,
                      SIGNAL("fileChanged(const QString&)"),
                      self._file_changed)
     if self._file_path is not None:
         self.__mtime = os.path.getmtime(self._file_path)
         self.__watcher.addPath(self._file_path)
コード例 #23
0
    def __init__(self, excludeFilters, dirToWatch):

        QObject.__init__(self)
        self.__dirWatcher = QFileSystemWatcher(self)

        # data members
        self.__excludeFilter = []  # Files exclude filter
        self.__srcDirsToWatch = set()  # Came from the user

        self.__fsTopLevelSnapshot = {}  # Current snapshot
        self.__fsSnapshot = {}  # Current snapshot

        # Sets of dirs which are currently watched
        self.__dirsToWatch = set()
        self.__topLevelDirsToWatch = set()  # Generated till root

        # precompile filters
        for flt in excludeFilters:
            self.__excludeFilter.append(re.compile(flt))

        # Initialise the list of dirs to watch
        self.__srcDirsToWatch.add(dirToWatch)

        self.__topLevelDirsToWatch = self.__buildTopDirsList(
            self.__srcDirsToWatch)
        self.__fsTopLevelSnapshot = self.__buildTopLevelSnapshot(
            self.__topLevelDirsToWatch, self.__srcDirsToWatch)
        self.__dirsToWatch = self.__buildSnapshot()

        # Here __dirsToWatch and __topLevelDirsToWatch have a complete
        # set of what should be watched

        # Add the dirs to the watcher
        dirs = []
        for path in self.__dirsToWatch | self.__topLevelDirsToWatch:
            dirs.append(path)
        self.__dirWatcher.addPaths(dirs)
        self.__dirWatcher.directoryChanged.connect(self.__onDirChanged)

        # self.debug()
        return
コード例 #24
0
ファイル: document.py プロジェクト: vi/enki
    def __init__(self, path):
        QObject.__init__(self)
        self._contents = None
        self._watcher = QFileSystemWatcher()
        self._timer = None
        self._path = path

        self._lastEmittedModifiedStatus = None
        self._lastEmittedRemovedStatus = None

        self.setPath(path)
        self.enable()
コード例 #25
0
ファイル: text_editor.py プロジェクト: davtoh/RRtools
    def __init__(self):
        super(Edytor,self).__init__()
        self.setupUi(self)
        # Create watcher
        self.watcher = QFileSystemWatcher(self)

        # Register slots
        self.button_close.clicked.connect(self.close)
        self.button_open.clicked.connect(self.file_open)
        self.button_save.clicked.connect(self.file_save)
        self.editor_window.textChanged.connect(self.text_changed)
        self.watcher.fileChanged.connect(self.file_changed)
コード例 #26
0
ファイル: documentwatcher.py プロジェクト: shimpe/frescobaldi
def start():
    """Start the document watcher."""
    global watcher
    if watcher is None:
        watcher = QFileSystemWatcher()
        app.documentLoaded.connect(documentLoaded)
        app.documentUrlChanged.connect(documentUrlChanged)
        app.documentClosed.connect(documentClosed)
        app.documentSaving.connect(whileSaving)
        watcher.fileChanged.connect(fileChanged)
        for d in app.documents:
            documentLoaded(d)
コード例 #27
0
    def __init__(self, parent=None):
        super(ProjectWidget, self).__init__(parent)
        self.setupUi(self)
        self.project = None
        self.mapisloaded = False
        self.bar = None
        self.roamapp = None

        menu = QMenu()
        self.canvas.setCanvasColor(Qt.white)

        self.canvas.enableAntiAliasing(True)
        self.canvas.setWheelAction(QgsMapCanvas.WheelZoomToMouseCursor)
        self.canvas.mapRenderer().setLabelingEngine(QgsPalLabeling())

        # self.roamVersionLabel.setText("You are running IntraMaps Roam version {}".format(roam.__version__))

        self.openProjectFolderButton.pressed.connect(self.openprojectfolder)
        self.openinQGISButton.pressed.connect(self.openinqgis)
        self.depolyProjectButton.pressed.connect(self.deploy_project)
        self.depolyInstallProjectButton.pressed.connect(
            functools.partial(self.deploy_project, True))

        self.filewatcher = QFileSystemWatcher()
        self.filewatcher.fileChanged.connect(self.qgisprojectupdated)

        self.projectupdatedlabel.linkActivated.connect(self.reloadproject)
        self.projectupdatedlabel.hide()

        # self.setpage(4)
        self.currentnode = None
        self.form = None

        qgislocation = r'C:\OSGeo4W\bin\qgis.bat'
        qgislocation = roam.config.settings.setdefault('configmanager', {}) \
            .setdefault('qgislocation', qgislocation)

        self.qgispathEdit.setText(qgislocation)
        self.qgispathEdit.textChanged.connect(self.save_qgis_path)
        self.filePickerButton.pressed.connect(self.set_qgis_path)
コード例 #28
0
ファイル: orange.py プロジェクト: scroll/orange
class ProgramCache(object):
    def __init__(self, ctx):
        from PyQt4.QtCore import QFileSystemWatcher
        self.ctx = ctx
        self.cache = {}
        self.watcher = QFileSystemWatcher()
        self.watcher.fileChanged.connect(self._file_changed)
        self.options = '-I ' + os.path.join(os.path.dirname(__file__), 'kernels')

    def _file_changed(self, path):
        path = str(path)
        del self.cache[path]
        self.watcher.removePath(path)

    def get(self, path):
        prog = self.cache.get(path, None)
        if not prog:
            src = open(path).read()
            prog = cl.Program(self.ctx, src).build(self.options)
            log.info('%s succesfully compiled' % path)
            self.cache[path] = prog
            self.watcher.addPath(path)
        return prog
コード例 #29
0
ファイル: console.py プロジェクト: jonathanverner/qidle
    def __init__(self, widget):
        super(Console, self).__init__()
        self.font_size = 10
        self.font = QFont("Ubuntu Mono", self.font_size)
        self.allow_quit = True
        self.indent = self.DEFAULT_INDENT
        self.widget = widget
        self.hilighter = PythonHighlighter(self.widget.document())
        self.parser = PyParser(self.indent, self.indent)

        self.widget.setFont(self.font)

        # The source file's we are watching
        self.watcher = QFileSystemWatcher()
        self.watcher.fileChanged.connect(self._sourceChanged)
        self._watched_files_menu = QMenu(self.widget.tr("&Watched Files"))
        self._watched_files_actions = {}
        self._lost_files = []

        self._widgetKeyPressEvent = self.widget.keyPressEvent
        self.widget.keyPressEvent = self.keyPressEvent
        self._widgetFocusInEvent = self.widget.focusInEvent
        self.widget.focusInEvent = self.focusInEvent
        self.widget.dragEnterEvent = self.dragEnterEvent
        self.widget.dragMoveEvent = self.dragMoveEvent
        self.widget.dropEvent = self.dropEvent

        # Code Completion
        self.completer = QCompleter(
            [kw for kw in PythonHighlighter.keywords if len(kw) > 3])
        self.completer.setCompletionMode(QCompleter.PopupCompletion)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.activated.connect(self._insertCompletion)
        self.completer.popup().setStyleSheet(
            "QWidget {border-width: 1px; border-color: black;}")
        self.completer.popup().setVerticalScrollBarPolicy(
            Qt.ScrollBarAlwaysOff)
        self.completer.setWidget(self.widget)
        self.completion_enabled = True

        if config.history:
            self.load_history()

        self._lastBlock.setType(TextBlock.TYPE_MESSAGE)
        self._lastBlock.appendText("PyShell v 0.5: Starting ...")
        self._write_message("Python version ", sys.version)
        self.start_editing()

        # Restart shell timer
        self.timer = QTimer(self)
コード例 #30
0
    def initializePage(self):
        super(ScanPage, self).initializePage()
        # api.add_scan_event_subscriber(self)

        self.open_camera()

        if os.path.exists(ORDER_FILE_PATH):
            self.order = scanresults.parse(ORDER_FILE_PATH)

        self.watcher = QFileSystemWatcher()
        self.watcher.fileChanged.connect(self.on_scan_file_change)

        if os.path.exists(TESTS_RESULTS_FILE_PATH):
            self.results = scanresults.parse(TESTS_RESULTS_FILE_PATH)
            self.update_question_tree_widget()
        else:
            with open(TESTS_RESULTS_FILE_PATH, 'w') as f:
                f.write('{}')
            self.results = scanresults.parse(TESTS_RESULTS_FILE_PATH)

        # TODO: Check why this doesn't always work
        self.watcher.addPath(TESTS_RESULTS_FILE_PATH)
        self.last_load_time = time.time()
コード例 #31
0
ファイル: debugcontroller.py プロジェクト: mprska/ricodebug
    def __init__(self, do):
        QObject.__init__(self)

        self.ptyhandler = PtyHandler()

        self.do = do

        self.connector = self.do.gdb_connector
        self.signalProxy = self.do.signalProxy

        self.executableName = None
        self.lastCmdWasStep = False

        self.ptyhandler.start()
        self.connector.start()

        self.connector.reader.asyncRecordReceived.connect(self.handleAsyncRecord, Qt.QueuedConnection)

        self.__config = DebugConfig()
        self.do.configStore.registerConfigSet(self.__config)
        self.__config.itemsHaveChanged.connect(self.updateConfig)

        self.__binaryWatcher = QFileSystemWatcher()
        self.__binaryWatcher.fileChanged.connect(self.__binaryChanged)
コード例 #32
0
class ProgramCache(object):
    def __init__(self, ctx):
        from PyQt4.QtCore import QFileSystemWatcher
        self.ctx = ctx
        self.cache = {}
        self.watcher = QFileSystemWatcher()
        self.watcher.fileChanged.connect(self._file_changed)
        self.options = '-I ' + os.path.join(os.path.dirname(__file__),
                                            'kernels')

    def _file_changed(self, path):
        path = str(path)
        del self.cache[path]
        self.watcher.removePath(path)

    def get(self, path):
        prog = self.cache.get(path, None)
        if not prog:
            src = open(path).read()
            prog = cl.Program(self.ctx, src).build(self.options)
            log.info('%s succesfully compiled' % path)
            self.cache[path] = prog
            self.watcher.addPath(path)
        return prog
コード例 #33
0
ファイル: server.py プロジェクト: fmfi-svt/infoboard
    def __init__(self, schedule_dir):
        self.schedule_dir = schedule_dir
        self.videos = {}
        self.playlist = []

        self.app = QApplication(sys.argv)

        self.view = QDeclarativeView()
        self.view.setSource(QUrl('scene.qml'))
        self.view.setResizeMode(QDeclarativeView.SizeRootObjectToView)

        self.viewRoot = self.view.rootObject()
        self.viewRoot.quit.connect(self.app.quit)
        self.viewRoot.finished.connect(self.show_next)

        self.view.setGeometry(100, 100, 400, 240)
        self.view.showFullScreen()

        self.watcher = QFileSystemWatcher()
コード例 #34
0
ファイル: watcher.py プロジェクト: eaglexmw/codimension
    def __init__( self, excludeFilters, dirToWatch ):

        QObject.__init__( self )
        self.__dirWatcher = QFileSystemWatcher( self )

        # data members
        self.__excludeFilter = []       # Files exclude filter
        self.__srcDirsToWatch = set()   # Came from the user

        self.__fsTopLevelSnapshot = {}  # Current snapshot
        self.__fsSnapshot = {}          # Current snapshot

        # Sets of dirs which are currently watched
        self.__dirsToWatch = set()
        self.__topLevelDirsToWatch = set()      # Generated till root


        # precompile filters
        for flt in excludeFilters:
            self.__excludeFilter.append( re.compile( flt ) )

        # Initialise the list of dirs to watch
        self.__srcDirsToWatch.add( dirToWatch )

        self.__topLevelDirsToWatch = self.__buildTopDirsList(
                                        self.__srcDirsToWatch )
        self.__fsTopLevelSnapshot = self.__buildTopLevelSnapshot(
                                        self.__topLevelDirsToWatch,
                                        self.__srcDirsToWatch )
        self.__dirsToWatch = self.__buildSnapshot()

        # Here __dirsToWatch and __topLevelDirsToWatch have a complete
        # set of what should be watched

        # Add the dirs to the watcher
        dirs = []
        for path in self.__dirsToWatch | self.__topLevelDirsToWatch:
            dirs.append( path )
        self.__dirWatcher.addPaths( dirs )
        self.__dirWatcher.directoryChanged.connect( self.__onDirChanged )

        # self.debug()
        return
コード例 #35
0
ファイル: projectwidget.py プロジェクト: loongfee/Roam
    def __init__(self, parent=None):
        super(ProjectWidget, self).__init__(parent)
        self.setupUi(self)
        self.project = None
        self.mapisloaded = False
        self.bar = None
        self.roamapp = None

        menu = QMenu()
        self.canvas.setCanvasColor(Qt.white)

        self.canvas.enableAntiAliasing(True)
        self.canvas.setWheelAction(QgsMapCanvas.WheelZoomToMouseCursor)
        self.canvas.mapRenderer().setLabelingEngine(QgsPalLabeling())

        # self.roamVersionLabel.setText("You are running IntraMaps Roam version {}".format(roam.__version__))

        self.openProjectFolderButton.pressed.connect(self.openprojectfolder)
        self.openinQGISButton.pressed.connect(self.openinqgis)
        self.depolyProjectButton.pressed.connect(self.deploy_project)
        self.depolyInstallProjectButton.pressed.connect(functools.partial(self.deploy_project, True))

        self.filewatcher = QFileSystemWatcher()
        self.filewatcher.fileChanged.connect(self.qgisprojectupdated)

        self.projectupdatedlabel.linkActivated.connect(self.reloadproject)
        self.projectupdatedlabel.hide()

        # self.setpage(4)
        self.currentnode = None
        self.form = None

        qgislocation = r'C:\OSGeo4W\bin\qgis.bat'
        qgislocation = roam.config.settings.setdefault('configmanager', {}) \
            .setdefault('qgislocation', qgislocation)

        self.qgispathEdit.setText(qgislocation)
        self.qgispathEdit.textChanged.connect(self.save_qgis_path) 
        self.filePickerButton.pressed.connect(self.set_qgis_path)
コード例 #36
0
ファイル: scan_page.py プロジェクト: matcom/autoexam
    def initializePage(self):
        super(ScanPage, self).initializePage()
        # api.add_scan_event_subscriber(self)

        self.open_camera()

        if os.path.exists(ORDER_FILE_PATH):
            self.order = scanresults.parse(ORDER_FILE_PATH)

        self.watcher = QFileSystemWatcher()
        self.watcher.fileChanged.connect(self.on_scan_file_change)

        if os.path.exists(TESTS_RESULTS_FILE_PATH):
            self.results = scanresults.parse(TESTS_RESULTS_FILE_PATH)
            self.update_question_tree_widget()
        else:
            with open(TESTS_RESULTS_FILE_PATH,'w') as f:
                f.write('{}')
            self.results = scanresults.parse(TESTS_RESULTS_FILE_PATH)

        # TODO: Check why this doesn't always work
        self.watcher.addPath(TESTS_RESULTS_FILE_PATH)
        self.last_load_time = time.time()
コード例 #37
0
ファイル: projectwidget.py プロジェクト: skeenp/Roam
    def __init__(self, parent=None):
        super(ProjectWidget, self).__init__(parent)
        self.setupUi(self)
        self.project = None
        self.bar = None
        self.roamapp = None

        menu = QMenu()

        # self.roamVersionLabel.setText("You are running IntraMaps Roam version {}".format(roam.__version__))

        self.openProjectFolderButton.pressed.connect(self.openprojectfolder)
        self.openinQGISButton.pressed.connect(self.openinqgis)
        self.depolyProjectButton.pressed.connect(self.deploy_project)
        self.depolyInstallProjectButton.pressed.connect(functools.partial(self.deploy_project, True))

        self.filewatcher = QFileSystemWatcher()
        self.filewatcher.fileChanged.connect(self.qgisprojectupdated)

        self.projectupdatedlabel.linkActivated.connect(self.reloadproject)
        self.projectupdatedlabel.hide()

        # self.setpage(4)
        self.currentnode = None
        self.form = None

        qgislocation = r'C:\OSGeo4W\bin\qgis.bat'
        qgislocation = roam.config.settings.setdefault('configmanager', {}) \
            .get('qgislocation', "")

        self.qgispathEdit.setText(qgislocation)
        self.qgispathEdit.textChanged.connect(self.save_qgis_path) 
        self.filePickerButton.pressed.connect(self.set_qgis_path)

        self.connect_page_events()

        QgsProject.instance().readProject.connect(self.projectLoaded)
コード例 #38
0
ファイル: shp_excel_sync.py プロジェクト: signedav/shpsync
class Syncer(QObject):
    def __init__(self, settings):
        QObject.__init__(self)
        self.s = settings
        self.filewatcher = None
        self.excelName = settings.excelName  # the layer name
        self.excelSheetName = settings.excelSheetName
        self.excelKeyName = settings.excelKeyName
        self.excelFkIdx = field_idx_from_name(self.excelName,
                                              self.excelKeyName)
        self.excelPath = layer_from_name(self.excelName).publicSource()
        self.excelKeyName = field_name_from_idx(self.excelName,
                                                self.excelFkIdx)
        # shpfile layer
        self.shpName = settings.shpName
        self.shpKeyName = settings.shpKeyName
        self.shpKeyIdx = field_idx_from_name(self.shpName, self.shpKeyName)
        self.skipLines = settings.skipLines
        layer_from_name(self.shpName).setFeatureFormSuppress(
            QgsVectorLayer.SuppressOn if settings.
            hideDialog else QgsVectorLayer.SuppressOff)

        self.join()
        self.clear_edit_state()
        self.initialSync()

    def join(self):
        # join the shp layer to the excel layer, non cached
        # TODO: Ignore if already joined?
        shpLayer = layer_from_name(self.shpName)
        jinfo = QgsVectorJoinInfo()
        jinfo.joinFieldName = self.excelKeyName
        jinfo.targetFieldName = self.shpKeyName
        jinfo.joinLayerId = layer_from_name(self.excelName).id()
        jinfo.memoryCache = False
        jinfo.prefix = ''
        for jinfo2 in shpLayer.vectorJoins():
            if jinfo2 == jinfo:
                info("Join already exists. Will not create it again")
                return
        info("Adding join between master and slave layers")
        shpLayer.addJoin(jinfo)

    def reload_excel(self):
        path = self.excelPath
        layer = layer_from_name(self.excelName)
        fsize = os.stat(self.excelPath).st_size
        info("fsize " + str(fsize))
        if fsize == 0:
            info("File empty. Won't reload yet")
            return
        layer.dataProvider().forceReload()
        show_message_bar("Excel reloaded from disk.")

    def excel_changed(self):
        info("Excel changed on disk - need to sync")
        self.reload_excel()
        self.update_shp_from_excel()

    def get_max_id(self):

        layer = layer_from_name(self.shpName)
        if layer.dataProvider().featureCount() == 0:
            return 0
        maxVal = layer.maximumValue(self.shpKeyIdx)
        if maxVal == None:
            return 0
        else:
            return maxVal

    def renameIds(self, fidToId):
        layer = layer_from_name(self.shpName)
        layer.startEditing()
        feats = query_layer_for_fids(self.shpName, fidToId.keys())
        for f in feats:
            res = layer.changeAttributeValue(f.id(), self.shpKeyIdx,
                                             fidToId[f.id()])
        layer.commitChanges()

    def added_geom(self, layerId, feats):
        info("added feats " + str(feats))
        layer = layer_from_name(self.shpName)
        maxFk = self.get_max_id()
        for i, _ in enumerate(feats):
            _id = maxFk + i + 1
            feats[i].setAttribute(self.shpKeyName, _id)

        self.shpAdd = feats

    def removed_geom_precommit(self, fids):
        #info("Removed fids"+str(fids))
        fks_to_remove = get_fk_set(self.shpName,
                                   self.shpKeyName,
                                   skipFirst=0,
                                   fids=fids,
                                   useProvider=True)
        self.shpRemove = self.shpRemove.union(fks_to_remove)
        info("feat ids to remove" + str(self.shpRemove))

    def changed_geom(self, layerId, geoms):
        fids = geoms.keys()
        feats = query_layer_for_fids(self.shpName, fids)
        fks_to_change = get_fk_set(self.shpName,
                                   self.shpKeyName,
                                   skipFirst=0,
                                   fids=fids)
        self.shpChange = {k: v for (k, v) in zip(fks_to_change, feats)}
        # info("changed"+str(shpChange))

    def get_ignore_indices(self):
        return [
            field_idx_from_name(self.excelName, field)
            for field in self.s.expressions.keys()
        ]

    def write_feature_to_excel(self, sheet, idx, feat):
        sheet.write(idx, self.excelFkIdx, feat[self.shpKeyName])
        for (fieldName, exp) in self.s.expressions.iteritems():
            fieldIdx = field_idx_from_name(self.excelName, fieldName)
            exp = QgsExpression(exp)
            sheet.write(idx, fieldIdx, exp.evaluate(feat))

    def write_rowvals_to_excel(self, sheet, idx, vals, ignore=None):
        if ignore is None:
            ignore = []
        for i, v in enumerate(vals):
            if i not in ignore:
                sheet.write(idx, i, v)

    def update_excel_programmatically(self):

        status_msgs = []

        rb = open_workbook(self.excelPath, formatting_info=True)
        r_sheet = rb.sheet_by_name(self.excelSheetName)  # read only copy
        wb = xlwt.Workbook()
        w_sheet = wb.add_sheet(self.excelSheetName, cell_overwrite_ok=True)
        write_idx = 0

        for row_index in range(r_sheet.nrows):
            if row_index < self.skipLines:  # copy header and/or dummy lines
                vals = r_sheet.row_values(row_index)
                self.write_rowvals_to_excel(w_sheet, write_idx, vals)
                write_idx += 1
                continue
            # print(r_sheet.cell(row_index,1).value)
            fk = r_sheet.cell(row_index, self.excelFkIdx).value
            if fk in self.shpRemove:
                status_msgs.append("Removing feature with id {}".format(fk))
                continue
            if fk in self.shpChange.keys():
                status_msgs.append(
                    "Syncing geometry change to feature with id {}".format(fk))
                shpf = self.shpChange[fk]
                self.write_feature_to_excel(w_sheet, write_idx, shpf)
                vals = r_sheet.row_values(row_index)
                self.write_rowvals_to_excel(w_sheet,
                                            write_idx,
                                            vals,
                                            ignore=self.get_ignore_indices())
            else:  # else just copy the row
                vals = r_sheet.row_values(row_index)
                self.write_rowvals_to_excel(w_sheet, write_idx, vals)

            write_idx += 1

        fidToId = {}
        for shpf in self.shpAdd:
            status_msgs.append("Adding new feature with id {}".format(
                shpf.attribute(self.shpKeyName)))
            fidToId[shpf.id()] = shpf.attribute(self.shpKeyName)
            self.write_feature_to_excel(w_sheet, write_idx, shpf)
            write_idx += 1

        info('\n'.join(status_msgs))
        wb.save(self.excelPath)
        if status_msgs:
            show_message_bar(status_msgs)
        else:
            show_message_bar("No changes to shapefile to sync.")
        return fidToId

    def clear_edit_state(self):
        info("Clearing edit state")
        self.shpAdd = []
        self.shpChange = {}
        self.shpRemove = Set([])

    def update_excel_from_shp(self):
        info("Will now update excel from edited shapefile")
        info("changing:" + str(self.shpChange))
        info("adding:" + str(self.shpAdd))
        info("removing" + str(self.shpRemove))
        self.deactivateFileWatcher()  # so that we don't sync back and forth
        fidToId = self.update_excel_programmatically()
        # need to alter the ids(not fids) of the new features after, because
        # editing the features after they've been commited doesn't work
        if fidToId:
            self.deactivateShpConnections()
            self.renameIds(fidToId)
            self.activateShpConnections()
        self.reload_excel()
        self.activateFileWatcher()
        self.clear_edit_state()

    def updateShpLayer(self, fksToRemove):
        if not fksToRemove:
            return

        prompt_msg = "Attempt to synchronize between Excel and Shapefile. Shapefile has features with ids: ({}) that don't appear in the Excel. Delete those features from the shapefile? ".format(
            ','.join([str(fk) for fk in fksToRemove]))
        reply = QtGui.QMessageBox.question(iface.mainWindow(), 'Message',
                                           prompt_msg, QtGui.QMessageBox.Yes,
                                           QtGui.QMessageBox.No)

        if reply == QtGui.QMessageBox.Yes:
            layer = layer_from_name(self.shpName)
            feats = [f for f in layer.getFeatures()]
            layer.startEditing()
            for f in feats:
                if f.attribute(self.shpKeyName) in fksToRemove:
                    layer.deleteFeature(f.id())
            layer.commitChanges()
        else:
            return

    def update_shp_from_excel(self):
        excelFks = Set(
            get_fk_set(self.excelName,
                       self.excelKeyName,
                       skipFirst=self.skipLines))
        shpFks = Set(get_fk_set(self.shpName, self.shpKeyName, skipFirst=0))
        # TODO also special warning if shp layer is in edit mode
        info("Keys in excel" + str(excelFks))
        info("Keys in shp" + str(shpFks))
        if shpFks == excelFks:
            info("Excel and Shp layer have the same rows. No update necessary")
            return
        inShpButNotInExcel = shpFks - excelFks
        inExcelButNotInShp = excelFks - shpFks
        if inExcelButNotInShp:
            warn(
                "There are rows in the excel file with no matching geometry {}."
                .format(inExcelButNotInShp))
            # FIXME: if those are added later then they will be added twice..
            # However, having an autoincrement id suggests features would be
            # added first from shp only?

        if inShpButNotInExcel:
            self.updateShpLayer(inShpButNotInExcel)

    def activateFileWatcher(self):
        self.filewatcher = QFileSystemWatcher([self.excelPath])
        self.filewatcher.fileChanged.connect(self.excel_changed)

    def deactivateFileWatcher(self):
        self.filewatcher.fileChanged.disconnect(self.excel_changed)
        self.filewatcher.removePath(self.excelPath)

    def activateShpConnections(self):
        shpLayer = layer_from_name(self.shpName)
        shpLayer.committedFeaturesAdded.connect(self.added_geom)
        shpLayer.featuresDeleted.connect(self.removed_geom_precommit)
        shpLayer.committedGeometriesChanges.connect(self.changed_geom)
        shpLayer.editingStopped.connect(self.update_excel_from_shp)
        shpLayer.beforeRollBack.connect(self.clear_edit_state)

    def deactivateShpConnections(self):
        shpLayer = layer_from_name(self.shpName)
        shpLayer.committedFeaturesAdded.disconnect(self.added_geom)
        # shpLayer.featureAdded.disconnect(added_geom_precommit)
        shpLayer.featuresDeleted.disconnect(self.removed_geom_precommit)
        shpLayer.committedGeometriesChanges.disconnect(self.changed_geom)
        shpLayer.editingStopped.disconnect(self.update_excel_from_shp)
        shpLayer.beforeRollBack.disconnect(self.clear_edit_state)

    def initialSync(self):
        info("Initial Syncing excel to shp")
        self.update_shp_from_excel()
        self.activateFileWatcher()
        self.activateShpConnections()

    def __del__(self):
        self.deactivateFileWatcher()
        self.deactivateShpConnections()
コード例 #39
0
class SingleApplication(QApplication):
    def __init__(self, *args):
        QApplication.__init__(self, *args)
        self._memory = QSharedMemory(self)
        self._memory.setKey("d2mp")
        if self._memory.attach():
            self._running = True
        else:
            self._running = False
            if not self._memory.create(1):
                raise RuntimeError(self._memory.errorString().toLocal8Bit().data())

    def is_running(self):
        return self._running
    
    def exec_(self):
        self._create_tray_icon()
        self._create_mod_manager()
        self._start_file_watcher()
        self._create_socket()
        Settings()
        
        return super(SingleApplication, self).exec_()
    def _create_mod_manager(self):
        self.manager = ModManager()
        self.manager.mod_game_info()
        self.manager.signals.message.connect(self.show_message_from_mod_manager)
        self.manager.signals.error.connect(self.show_error_from_mod_manager)
    
    def _create_socket(self):    
        self.socket = ConnectionManager()
        
        self.manager.signals.contact_server.connect(self.socket.send)
        
        self.socket.message.connect(self.show_message_from_socket)
        self.socket.error.connect(self.show_error_from_socket)
        
        
    @property
    def _watcher_file_name(self):
        return "d2mp.pid"
    
    def _start_file_watcher(self):
        self.watcher = QFileSystemWatcher()
        self.watcher_file_path =  join(abspath("."), self._watcher_file_name)
        log.DEBUG("creating watcher file: %s" %(self.watcher_file_path))
        write_to_file(self.watcher_file_path, "Delete this file to shutdown D2MP\n")
        self.watcher.addPath(abspath("."))
        self.watcher.directoryChanged.connect(self._watcher_changed_callback)
    
    def _watcher_changed_callback(self, val):
        if self._watcher_file_name not in os.listdir(val): 
            secs = 3
            self.show_message("Shutdown", "Watcher file was deleted. D2MP will shotdown in %d seconds." %(secs))
            sleep(secs)
            self.exit()
    
    def _create_tray_icon(self):
        self.tray = QSystemTrayIcon(self)
        self.tray.setToolTip("D2Moddin Manager")
        self.tray.setIcon(QIcon(SETTINGS['icon']))
        traymenu = QMenu()
        traymenu.addAction("Restart", self.restart)
        traymenu.addAction("Uninstall", self.uninstall)
        traymenu.addAction("Preferences", UIManager().open_preferences)
        traymenu.addAction("Show mod list", self.show_mod_list)
        traymenu.addSeparator()

        traymenu.addAction("Exit", self.exit)
    
        self.tray.setContextMenu(traymenu)
        self.tray.show()
    
    def restart(self):
        python = sys.executable
        args = set(sys.argv)
        args.add("restart")
        os.execl(python, python, *list(sys.argv))
        self.exit()
    
    def uninstall(self):
        ModManager().delete_mods()
#         ModManager().uninstall_d2mp()
        self.exit()
    
    def exit(self):
        # do some cleanup
        return super(SingleApplication, self).exit()
    
    def show_mod_list(self):
        self.show_message("Mod List", ModManager().mod_names_as_string())
    
    def show_message_from_socket(self, message):
        self.show_message("Server message", message)
        
    def show_error_from_socket(self, message):
        self.show_message("Server error", message, QSystemTrayIcon.Critical)
        
    def show_message_from_mod_manager(self, message):
        self.show_message("ModManager message", message)
        
    def show_error_from_mod_manager(self, message):
        self.show_message("ModManager error", message, QSystemTrayIcon.Critical)
        
    def show_message(self, title, message, icon = QSystemTrayIcon.Information):
        self.tray.showMessage(title, message, icon)
コード例 #40
0
ファイル: windows.py プロジェクト: BloodyD/D2ModdinPyClient
class PreferencesWindow(BaseWindow):
    
    def __init__(self, *args, **kwargs):
        super(PreferencesWindow, self).__init__(layoutCls = QVBoxLayout, *args, **kwargs)
        self.setWindowTitle("Settings")
        self.setWindowIcon(QIcon(SETTINGS['icon']))
        self._add_steam_box()
        self._add_dota_box()
        self._add_additional_prefs()
        self._add_log_box()
        
        self._add_log_watcher()
        Settings().signals.changed.connect(self.update_path)
    
    def _add_log_watcher(self):
        self.watcher = QFileSystemWatcher()
        self.watcher.addPath(abspath(log.file_name))
        self.watcher.fileChanged.connect(self.update_log)
    
    def show(self):
        self.update_log(abspath(log.file_name))
        return super(PreferencesWindow, self).show()
    
    def update_path(self, setting_key, new_value):
        if setting_key == "dota_path":
            self.dota_path.setText(new_value)
        elif setting_key == "steam_path":
            self.steam_path.setText(new_value)
    
    def _add_steam_box(self):
        box = QGroupBox("Steam Location")
        box.setLayout(QHBoxLayout(box))
        
        self.steam_path = QLineEdit(box)
        self.steam_path.setReadOnly(True)
        self.steam_path.setText(Settings().get("steam_path"))

        change_btn = QPushButton("Change...", box)
        change_btn.clicked.connect(self.change_steam_path)
                
        box.layout().addWidget(self.steam_path)
        box.layout().addWidget(change_btn)
        
        self.layout().addWidget(box)
    
    def _add_dota_box(self):
        box = QGroupBox("Dota Location")
        box.setLayout(QHBoxLayout(box))
        
        self.dota_path = QLineEdit(box)
        self.dota_path.setReadOnly(True)
        self.dota_path.setText(Settings().get("dota_path"))
        
        change_btn = QPushButton("Change...", box)
        change_btn.clicked.connect(self.change_dota_path)

        box.layout().addWidget(self.dota_path)
        box.layout().addWidget(change_btn)
        
        self.layout().addWidget(box)
    
    def change_steam_path(self):
        self._change_path("steam_path", is_steam_path_valid)

    def change_dota_path(self):
        self._change_path("dota_path", is_dota_path_valid)
    
    def _change_path(self, path_key, is_valid):
        new_folder = str(QFileDialog.getExistingDirectory(parent=self, caption="Select new path", directory=Settings().get(path_key)) )
        if new_folder and exists(new_folder):
            if is_valid(new_folder):
                Settings().set(path_key, new_folder)
            else:
                from d2mp.ui import Message
                Message.critical("Path is not valid", 
                            "Path was not saved in settings.\nPlease select a directory with the right executable in it!")
    
    def _add_additional_prefs(self):
        box = QGroupBox("Additional Preferences")
        box.setLayout(QHBoxLayout(box))
                
        log_btn = QPushButton("View Log", box)
        log_btn.clicked.connect(self.open_log_file)
        reset_btn = QPushButton("Reset Settings", box)
        reset_btn.clicked.connect(Settings().reset)
                
        box.layout().addWidget(log_btn)
        box.layout().addWidget(reset_btn)
        
        self.layout().addWidget(box)
        
    def _add_log_box(self):
        box = QGroupBox("Application log")
        box.setLayout(QHBoxLayout(box))
        
        self.log_area = QTextBrowser(box)
        self.log_area.setLineWrapMode(QTextEdit.NoWrap)
        
        box.layout().addWidget(self.log_area)
        self.layout().addWidget(box)
    
    def open_log_file(self):
        log.INFO("TODO: open file in standard editor")
        print(abspath(log.file_name))
    
    def update_log(self, log_file):
        content = ""
        for line in open(log_file):
            if "========= new programm start =========" in line:
                content = ""
            else:
                content += line[37:]
        if content:
            self.log_area.setText(content)
コード例 #41
0
ファイル: ImageBrowser.py プロジェクト: ChunChia/ipbec
class ImageBrowser(QWidget, Ui_ImageBrowser):
    """Widget to browse absorption and reference images"""

    windowTitleChanged = pyqtSignal(str)
    imageChanged = pyqtSignal(dict)

    def __init__(self, settings, parent):
        super(ImageBrowser, self).__init__(parent=parent)
        self.settings = settings
        self.main_window = parent

        self.current_directory = default_image_dir
        self.path_to_dark_file = default_dark_path
        self.path_to_json_db = os.path.join(main_package_dir,
                                            'image_save_info.json')

        self.current_image_info = {}

        self.setupUi(self)
        self.loadSettings()
        self.is_cleaned = False
        self.use_roi_while_cleaning = False

        self.connectSignalsToSlots()

        self.image_list = clt.ImageList()
        self.updateFileList(new_dir=True)
        self.current_image_index = 0

        self.watcher = QFileSystemWatcher(self)
        self.watcher.addPath(self.current_directory)
        self.watcher.directoryChanged.connect(
            self.handleWatcherDirectoryChanged)
        self.updateCommentBox()

    def initialEmit(self):
        self.populateAndEmitImageInfo()

    def populateAndEmitImageInfo(self):
        """Populates current_image_info with all the required information about
        the current image. It then emits the imageChanged signal"""
        d = self.current_image_info
        index = self.imageListCombo.currentIndex()
        d['index'] = index
        d['path_to_abs'] = self.image_list.absorption_files[index]
        d['path_to_ref'] = self.image_list.reference_files[index]
        d['path_to_dark'] = self.path_to_dark_file
        d['abs_image'] = clt.readImageFile(d['path_to_abs'])
        d['ref_image'] = clt.readImageFile(d['path_to_ref'])
        d['dark_image'] = clt.readImageFile(d['path_to_dark'])

        modified_time = time.ctime(os.path.getmtime(d['path_to_abs']))
        self.fileDateTime.setText(str(modified_time))

        if self.is_cleaned and self.useCleanedCheck.checkState() == 2:
            ref_image = self.clean_ref_images[index]
        else:
            ref_image = d['ref_image']
        d['div_image'] = clt.dividedImage(d['abs_image'], ref_image,
                                          d['dark_image'],
                                          od_minmax=self.getODMinMax(),
                                          correct_od_saturation=self.getODSaturationParms(),
                                          correct_saturation=self.getSaturationParms())
        d['image_type'] = self.getImageType()
        key = d['path_to_abs']
        if key not in self.global_save_info:
            self.global_save_info[key] = {}
        d['save_info'] = self.global_save_info[key]
        # d['save_info']['comment'] = str(self.commentTextEdit.toPlainText())

        self.imageChanged.emit(d)

    def getImageType(self):
        imtype = str(self.imageTypeCombo.currentText())
        imcode = {'Absorption': 'abs_image', 'Reference': 'ref_image',
                  'Divided': 'div_image', 'Dark': 'dark_image'}
        return imcode[imtype]

    def handleImageIndexValueChanged(self, new_index):
        """Slot: called when the user changes the current index."""
        # just update imageList. handleImageListIndexChanged will take care of
        # the rest
        self.imageListCombo.setCurrentIndex(new_index)

    def handleImageListIndexChanged(self, new_index):
        """Slot: called when the user changes the current image in the combo
        box."""
        # we need to update imageIndexSpin, but also want to avoid recursive
        # updates. Hence we disconnect slots before updating.

        self.saveImageInfo()

        self.imageIndexSpin.valueChanged.disconnect(
            self.handleImageIndexValueChanged)
        self.imageIndexSpin.setValue(new_index)
        self.imageIndexSpin.valueChanged.connect(
            self.handleImageIndexValueChanged)

        self.current_image_index = new_index
        self.updateCommentBox()
        self.populateAndEmitImageInfo()

    def saveImageInfo(self):
        """Get save_info contents of current_image_info and save it in
        global_save_info.

        TODO: write better description of this function.
        """
        comment = str(self.commentTextEdit.toPlainText())
        print(self.current_image_index)
        key = self.image_list.absorption_files[self.current_image_index]
        # if key not in self.global_save_info:
        #     self.global_save_info[key] = {}
        self.global_save_info[key] = self.current_image_info['save_info']
        self.global_save_info[key]['comment'] = comment

    def updateCommentBox(self):
        """Updates comment box to display comment for the current image."""
        key = self.image_list.absorption_files[self.current_image_index]
        if key not in self.global_save_info:
            self.commentTextEdit.setPlainText('')
        else:
            if 'comment' not in self.global_save_info[key]:
                self.global_save_info[key]['comment'] = ''
            comment = self.global_save_info[key]['comment']
            self.commentTextEdit.setPlainText(comment)

    def connectSignalsToSlots(self):
        self.imageIndexSpin.valueChanged.connect(
            self.handleImageIndexValueChanged)
        self.imageListCombo.currentIndexChanged.connect(
            self.handleImageListIndexChanged)

    def updateFileList(self, new_dir=False):
        """Updates image_list to reflect files in current_directory.

        Pass new_dir=True if current_directory has changed.

        If an error occured, gives the user the option to select a different
        directory."""
        done = False
        while not done:
            try:
                if new_dir:
                    self.image_list.updateFileList(self.current_directory)
                else:
                    self.image_list.updateFileList()
            except clt.ImageListError as err:
                info = (' Would you like to open a different directory?'
                        ' Press cancel to quit')
                pressed = QMessageBox.question(self, 'Error opening directory',
                                               str(err) + info,
                                               QMessageBox.No |
                                               QMessageBox.Yes |
                                               QMessageBox.Cancel)
                if pressed == QMessageBox.Yes:
                    self.setCurrentDirectory(self.openDirectoryDialog())
                    new_dir = True
                elif pressed == QMessageBox.No:
                    done = True
                elif pressed == QMessageBox.Cancel:
                    # user pressed cancel, quit!
                    done = True
                    self.main_window.close()
                    # TODO: find graceful way to quit
            else:
                # file updating was successful
                done = True

                if new_dir is False:
                    # This means we are just refreshing the current directory
                    # we probably want to keep the current index
                    previous_text = self.imageListCombo.currentText()

                # disconnect slots before adding items
                self.imageListCombo.currentIndexChanged.disconnect(
                    self.handleImageListIndexChanged)
                self.imageIndexSpin.valueChanged.disconnect(
                    self.handleImageIndexValueChanged)

                # update image List combo
                self.imageListCombo.clear()
                self.imageListCombo.addItems(self.image_list.short_names)

                # update image index
                max_index = self.image_list.n_images - 1
                self.imageIndexSpin.setMaximum(max_index)
                labelString = 'of' + str(max_index)
                self.maxImageIndexLabel.setText(labelString)

                if new_dir is False:
                    # find if the previous image is still around
                    try:
                        ci = self.image_list.short_names.index(previous_text)
                    except ValueError:
                        # nope, it's not there. set current index to max index
                        ci = max_index
                else:
                    # if we have a new folder, then set the index to 0
                    ci = 0
                self.current_image_index = ci
                self.imageListCombo.setCurrentIndex(ci)
                self.imageIndexSpin.setValue(ci)


                # connect slot again once done adding
                self.imageListCombo.currentIndexChanged.connect(
                    self.handleImageListIndexChanged)
                self.imageIndexSpin.valueChanged.connect(
                    self.handleImageIndexValueChanged)

                self.is_cleaned = False
                self.useCleanedCheck.setCheckState(0)

                self.populateAndEmitImageInfo()
                self.purgeNonExistentEntries()

    def setCurrentDirectory(self, new_directory):
        """Sets the current directory.

        Never change self.current_directory directly. Use this function
        instead."""
        self.current_directory = new_directory
        self.windowTitleChanged.emit(self.current_directory)

    def loadSettings(self):
        self.settings.beginGroup('imagebrowser')
        self.setCurrentDirectory(
            str(self.settings.value('current_directory',
                                    default_image_dir).toString()))
        self.path_to_dark_file = str(
            self.settings.value('path_to_dark_file',
            self.path_to_dark_file).toString())
        self.path_to_json_db = str(self.settings.value(
                                   'path_to_json_db',
                                   './image_save_info.json').toString())

        self.settings.endGroup()
        self.loadJsonFile()

    def loadJsonFile(self):
        info = ('\n\nSomething bad has happened and I am not equipped to '
                'handle it. Please check if ' + self.path_to_json_db +
                ' exists. If it does, then make a backup of this file as '
                'it has a lot of information. Press yes if you would like '
                'to select a new database file. This has to be a valid JSON '
                'file. {} is an empty but valid JSON file. '
                'Press no if you want to '
                'create a new empty database at the same location. '
                'Press cancel if you want me to crash horribly but '
                'without touching the database file.')
        done = False
        while not done:
            try:
                with open(self.path_to_json_db, 'r') as f:
                    self.global_save_info = json.loads(f.read())
            except IOError as err:
                (errno, strerror) = err
                # something bad wrong
                msg = str(strerror)
            except ValueError as err:
                msg = str(err)
            except:
                msg = "Unknown error."
            else:
                done = True

            if not done:
                pressed = QMessageBox.critical(self, 'Error opening database',
                                               msg + info, QMessageBox.No |
                                               QMessageBox.Yes |
                                               QMessageBox.Cancel)
                if pressed == QMessageBox.Yes:
                    # file dialog
                    new_path = str(QFileDialog.getOpenFileName(self,
                                   "Select new JSON file",
                                   self.path_to_json_db))
                    self.path_to_json_db = new_path
                    done = False
                elif pressed == QMessageBox.No:
                    self.global_save_info = {}
                    done = True
                elif pressed == QMessageBox.Cancel:
                    done = True
                    self.global_save_info = {}
                    self.path_to_json_db = './temp_crash_json'
                    self.main_window.close()

    def saveSettings(self):
        self.saveImageInfo()
        self.settings.beginGroup('imagebrowser')
        self.settings.setValue('current_directory', self.current_directory)
        self.settings.setValue('path_to_dark_file', self.path_to_dark_file)
        self.settings.setValue('path_to_json_db', self.path_to_json_db)
        self.settings.endGroup()
        json_file_as_string = json.dumps(self.global_save_info, indent=4,
                                         separators=(',', ': '))
        with open(self.path_to_json_db, 'w') as f:
            f.write(json_file_as_string)

    def openDirectoryDialog(self):
        """Opens a dialog to select and new directory and returns path to
        selected directory."""
        return str(QFileDialog.getExistingDirectory(self, "Open Directory",
                   self.current_directory, QFileDialog.ShowDirsOnly))

    def handleOpenDirectoryAction(self):
        """Called when the user clicks the Open Directory button."""

        new_directory = self.openDirectoryDialog()

        if new_directory is not '' and new_directory != self.current_directory:
            self.watcher.removePath(self.current_directory)
            self.setCurrentDirectory(new_directory)
            self.updateFileList(new_dir=True)
            self.watcher.addPath(self.current_directory)

    def handleDarkFileAction(self):
        """Called when the user clicks the Dark File menu option."""
        new_path_to_dark_file = str(QFileDialog.getOpenFileName(self,
                                    "Select dark file",
                                    self.path_to_dark_file))

        if new_path_to_dark_file != '':
            self.path_to_dark_file = new_path_to_dark_file

    def handleRefreshAction(self):
        self.updateFileList(new_dir=False)

    def handleCleanAction(self):
        progress = QProgressDialog('Reading Reference images', 'Abort',
                                   0, 4.0*self.image_list.n_images, self)
        progress.setWindowModality(Qt.WindowModal)
        progress.setMinimumDuration(1)

        if self.readAllRefImages(progress):
            return
        if self.generateBasis(progress):
            return
        if self.readAllAbsImages(progress):
            return
        if self.generateCleanRefs(progress):
            return

        progress.setValue(4.0*self.image_list.n_images)
        self.populateAndEmitImageInfo()

    def readAllRefImages(self, progress):
        progress.setLabelText('Reading Reference Images')
        self.ref_images = []
        for path_to_ref in self.image_list.reference_files:
            if progress.wasCanceled():
                return 1
            progress.setValue(progress.value() + 1)
            im = clt.normalize(clt.readImageFile(path_to_ref))
            self.ref_images.append(im)

    def generateBasis(self, progress):
        progress.setLabelText('Generating basis vectors')
        self.basis = []
        for b in clt.generateBasis(self.ref_images):
            progress.setValue(progress.value() + 1)
            if progress.wasCanceled():
                return 1
            self.basis.append(b)

    def readAllAbsImages(self, progress):
        progress.setLabelText('Reading absorption images')
        self.abs_images = []
        for path_to_abs in self.image_list.absorption_files:
            progress.setValue(progress.value() + 1)
            if progress.wasCanceled():
                return 1
            im = clt.readImageFile(path_to_abs)
            self.abs_images.append(im)

    def generateCleanRefs(self, progress):
        progress.setLabelText('Generating clean reference images')
        self.clean_ref_images = []

        abs_shape = self.abs_images[0].shape
        # TODO: insert code to get actual mask
        mask = self.getROIMask(abs_shape)
        self.is_cleaned = False
        for im in clt.generateCleanRefs(self.abs_images, self.basis, mask):
            progress.setValue(progress.value() + 1)
            if progress.wasCanceled():
                return 1
            self.clean_ref_images.append(im)
        else:
            self.is_cleaned = True

    def handleUseCleanedAction(self, state):
        if self.is_cleaned is False and state == 2:
            self.handleCleanAction()
        self.populateAndEmitImageInfo()

    def handleUseRoiWhileCleaningAction(self, state):
        self.use_roi_while_cleaning = bool(state)

    def handleImageTypeChanged(self, new_state_string):
        self.populateAndEmitImageInfo()

    def odMinMaxStateChanged(self, new_state):
        print(new_state)

    def correctSaturationStateChanged(self, new_state):
        print(new_state)

    def handleWatcherDirectoryChanged(self, newDir):
        try:
            # see if updating the list would generate any errors
            clt.ImageList(self.current_directory)
        except clt.ImageListError:
            # if they do, then we probably are in the middle of a refresh
            # process, do nothing.
            return
        else:
            self.updateFileList(new_dir=False)

    def getODMinMax(self):
        """Return a tuple with min and max OD values read from the UI.
        returns None if odMinMax check button is not checked."""
        if self.odMinMaxCheck.checkState() == 0:
            return None
        else:
            return (self.odMinSpin.value(), self.odMaxSpin.value())

    def getSaturationParms(self):
        if self.correctSaturationCheckBox.checkState() == 0:
            return None
        else:
            gamma = 6.0666  # MHz
            return (self.satPixCountsSpin.value(), 2.0*self.detuningSpin.value()/gamma)

    def getODSaturationParms(self):
        if self.correctODSaturationCheckBox.checkState() == 0:
            return None
        else:
            return float(self.odSatSpin.value())


    def handleRoiChanged(self, new_roi):
        """Slot: Changes ROI used for cleaning images."""
        self.cleaning_roi = new_roi

    def handleROIHChanged(self, new_roi):
        self.roi_h = new_roi

    def handleROIVChanged(self, new_roi):
        self.roi_v = new_roi

    def getROIMask(self, abs_shape):
        mask = np.ones(abs_shape)
        if self.use_roi_while_cleaning:
            roi = self.cleaning_roi[0]  # 0th component is roi list
            mask[roi[0]:roi[2], roi[1]:roi[3]] = 0.0
        return mask

    def purgeNonExistentEntries(self):
        """Scan JSON database for files in current directory. If database has
        entries for which there are no files, then delete those entries."""
        for key in self.global_save_info.keys():
            if path.dirname(key) == self.current_directory:
                if not path.isfile(key):
                    # remove entry if this file does not exis
                    del self.global_save_info[key]
                    print('deleting: ' + key)

    def handleSaveAnalysis(self):
        save_dialog = SaveDialog(self.settings, self.global_save_info, self.image_list)
        save_dialog.exec_()

    def handleMakeMovie(self):
        print('handle')
        image_list = []
        for index in range(self.image_list.n_images):
            d = {}
            d['abs_image'] = clt.readImageFile(self.image_list.absorption_files[index])
            d['ref_image'] = clt.readImageFile(self.image_list.reference_files[index])
            d['dark_image'] = clt.readImageFile(self.path_to_dark_file)

            if self.is_cleaned and self.useCleanedCheck.checkState() == 2:
                ref_image = self.clean_ref_images[index]
            else:
                ref_image = d['ref_image']
            d['div_image'] = clt.dividedImage(d['abs_image'], ref_image,
                                              d['dark_image'],
                                              od_minmax=self.getODMinMax(),
                                              correct_od_saturation=self.getODSaturationParms(),
                                              correct_saturation=self.getSaturationParms())
            d['image_type'] = self.getImageType()

            image_in_roi = getSubImage(d['div_image'], self.cleaning_roi)
            image_list.append(image_in_roi)

        fig = plt.figure()
        ax = fig.add_subplot(111)
        ax.set_aspect('equal')
        ax.get_xaxis().set_visible(False)
        ax.get_yaxis().set_visible(False)

        im = ax.imshow(image_list[0], cmap='gray', interpolation='nearest')
        im.set_clim([0, 1])
        fig.set_size_inches([5, 5])

        plt.tight_layout()

        def update_img(n):
            im.set_data(image_list[n])
            return im

        #legend(loc=0)
        ani = animation.FuncAnimation(fig, update_img, len(image_list),
                                      interval=30)
        #writer = animation.writers['gif'](fps=10)

        ani.save('demo.gif')

    def handlePluginClicked(self, plugin_name):
        for p in plugin_list:
            if p.name == plugin_name:
                print("found")
                plugin_dialog = p(self.settings, self.makePluginDataPackage())
                plugin_dialog.exec_()

    def makePluginDataPackage(self):
        """Returns a dict with all the data a plugin would need."""
        data_dict = {}
        data_dict['roi_int'] = self.cleaning_roi
        data_dict['roi_h'] = self.roi_h
        data_dict['roi_v'] = self.roi_v

        abs_images = [clt.readImageFile(p) for p in
                      self.image_list.absorption_files]
        ref_images = [clt.readImageFile(p) for p in
                      self.image_list.reference_files]
        dark_image = clt.readImageFile(self.path_to_dark_file)

        if self.is_cleaned and self.useCleanedCheck.checkState() == 2:
            use_refs = self.clean_ref_images
        else:
            use_refs = ref_images

        sat_od_parms = self.getODSaturationParms()
        corr_sat_parms = self.getSaturationParms()
        div_images = [clt.dividedImage(ai, ri, dark_image,
                                       od_minmax=self.getODMinMax(),
                                       correct_od_saturation=sat_od_parms,
                                       correct_saturation=corr_sat_parms)
                      for ai, ri in zip(abs_images, use_refs)]
        data_dict['abs_images'] = abs_images
        data_dict['ref_images'] = use_refs
        data_dict['dark_image'] = dark_image
        data_dict['div_images'] = div_images
        return data_dict
コード例 #42
0
ファイル: projectwidget.py プロジェクト: GEO-IASS/Roam
    def __init__(self, parent=None):
        super(ProjectWidget, self).__init__(parent)
        self.setupUi(self)
        self.project = None
        self.mapisloaded = False
        self.bar = None

        self.canvas.setCanvasColor(Qt.white)
        self.canvas.enableAntiAliasing(True)
        self.canvas.setWheelAction(QgsMapCanvas.WheelZoomToMouseCursor)
        self.canvas.mapRenderer().setLabelingEngine(QgsPalLabeling())

        self.fieldsmodel = QgsFieldModel()
        self.widgetmodel = WidgetsModel()
        self.possiblewidgetsmodel = QStandardItemModel()

        self.formlayersmodel = QgsLayerModel(watchregistry=False)
        self.formlayers = CaptureLayerFilter()
        self.formlayers.setSourceModel(self.formlayersmodel)

        self.selectlayermodel = CaptureLayersModel(watchregistry=False)
        self.selectlayerfilter = LayerTypeFilter()
        self.selectlayerfilter.setSourceModel(self.selectlayermodel)
        self.selectlayermodel.dataChanged.connect(self.selectlayerschanged)

        self.layerCombo.setModel(self.formlayers)
        self.widgetCombo.setModel(self.possiblewidgetsmodel)
        self.selectLayers.setModel(self.selectlayerfilter)
        self.selectLayers_2.setModel(self.selectlayerfilter)
        self.fieldList.setModel(self.fieldsmodel)

        self.widgetlist.setModel(self.widgetmodel)
        self.widgetlist.selectionModel().currentChanged.connect(self.updatecurrentwidget)
        self.widgetmodel.rowsRemoved.connect(self.setwidgetconfigvisiable)
        self.widgetmodel.rowsInserted.connect(self.setwidgetconfigvisiable)
        self.widgetmodel.modelReset.connect(self.setwidgetconfigvisiable)

        self.titleText.textChanged.connect(self.updatetitle)

        QgsProject.instance().readProject.connect(self._readproject)

        self.loadwidgettypes()

        self.addWidgetButton.pressed.connect(self.newwidget)
        self.removeWidgetButton.pressed.connect(self.removewidget)

        self.roamVersionLabel.setText("You are running IntraMaps Roam version {}".format(roam.__version__))

        self.openProjectFolderButton.pressed.connect(self.openprojectfolder)
        self.openinQGISButton.pressed.connect(self.openinqgis)

        self.filewatcher = QFileSystemWatcher()
        self.filewatcher.fileChanged.connect(self.qgisprojectupdated)

        self.formfolderLabel.linkActivated.connect(self.openformfolder)
        self.projectupdatedlabel.linkActivated.connect(self.reloadproject)
        self.projectupdatedlabel.hide()
        self.formtab.currentChanged.connect(self.formtabchanged)

        self.expressionButton.clicked.connect(self.opendefaultexpression)

        self.fieldList.currentIndexChanged.connect(self.updatewidgetname)
        self.fieldwarninglabel.hide()

        for item, data in readonlyvalues:
            self.readonlyCombo.addItem(item, data)

        self.setpage(4)
        self.form = None

        self.projectlocations.currentIndexChanged[str].connect(self.projectlocationchanged.emit)
コード例 #43
0
class ProjectWidget(Ui_Form, QWidget):
    SampleWidgetRole = Qt.UserRole + 1
    projectsaved = pyqtSignal()
    projectupdated = pyqtSignal()
    projectloaded = pyqtSignal(object)
    selectlayersupdated = pyqtSignal(list)

    def __init__(self, parent=None):
        super(ProjectWidget, self).__init__(parent)
        self.setupUi(self)
        self.project = None
        self.mapisloaded = False
        self.bar = None
        self.roamapp = None

        menu = QMenu()
        self.canvas.setCanvasColor(Qt.white)

        self.canvas.enableAntiAliasing(True)
        self.canvas.setWheelAction(QgsMapCanvas.WheelZoomToMouseCursor)
        self.canvas.mapRenderer().setLabelingEngine(QgsPalLabeling())

        # self.roamVersionLabel.setText("You are running IntraMaps Roam version {}".format(roam.__version__))

        self.openProjectFolderButton.pressed.connect(self.openprojectfolder)
        self.openinQGISButton.pressed.connect(self.openinqgis)
        self.depolyProjectButton.pressed.connect(self.deploy_project)
        self.depolyInstallProjectButton.pressed.connect(
            functools.partial(self.deploy_project, True))

        self.filewatcher = QFileSystemWatcher()
        self.filewatcher.fileChanged.connect(self.qgisprojectupdated)

        self.projectupdatedlabel.linkActivated.connect(self.reloadproject)
        self.projectupdatedlabel.hide()

        # self.setpage(4)
        self.currentnode = None
        self.form = None

        qgislocation = r'C:\OSGeo4W\bin\qgis.bat'
        qgislocation = roam.config.settings.setdefault('configmanager', {}) \
            .setdefault('qgislocation', qgislocation)

        self.qgispathEdit.setText(qgislocation)
        self.qgispathEdit.textChanged.connect(self.save_qgis_path)
        self.filePickerButton.pressed.connect(self.set_qgis_path)

    def set_qgis_path(self):
        path = QFileDialog.getOpenFileName(self,
                                           "Select QGIS install file",
                                           filter="(*.bat)")
        if not path:
            return
        self.qgispathEdit.setText(path)
        self.save_qgis_path(path)

    def save_qgis_path(self, path):
        roam.config.settings['configmanager'] = {'qgislocation': path}
        roam.config.save()

    def setpage(self, page, node):
        self.currentnode = node

        self.write_config_currentwidget()

        self.stackedWidget.setCurrentIndex(page)
        if self.project:
            print self.project.dump_settings()

        widget = self.stackedWidget.currentWidget()
        if hasattr(widget, "set_project"):
            widget.set_project(self.project, self.currentnode)

    def write_config_currentwidget(self):
        widget = self.stackedWidget.currentWidget()
        if hasattr(widget, "write_config"):
            widget.write_config()

    def deploy_project(self, with_data=False):
        if self.roamapp.sourcerun:
            base = os.path.join(self.roamapp.apppath, "..")
        else:
            base = self.roamapp.apppath

        default = os.path.join(base, "roam_serv")
        path = roam.config.settings.get("publish", {}).get("path", '')
        if not path:
            path = default

        path = os.path.join(path, "projects")

        if not os.path.exists(path):
            os.makedirs(path)

        self._saveproject()
        options = {}

        bundle.bundle_project(self.project,
                              path,
                              options,
                              as_install=with_data)

    def setaboutinfo(self):
        self.versionLabel.setText(roam.__version__)
        self.qgisapiLabel.setText(str(QGis.QGIS_VERSION))

    def checkcapturelayers(self):
        haslayers = self.project.hascapturelayers()
        self.formslayerlabel.setVisible(not haslayers)
        return haslayers

    def selectlayerschanged(self, *args):
        self.formlayers.setSelectLayers(self.project.selectlayers)
        self.checkcapturelayers()
        self.selectlayersupdated.emit(self.project.selectlayers)

    def reloadproject(self, *args):
        self.setproject(self.project)
        self.projectupdated.emit()

    def qgisprojectupdated(self, path):
        self.projectupdatedlabel.show()
        self.projectupdatedlabel.setText(
            "The QGIS project has been updated. <a href='reload'> "
            "Click to reload</a>. <b style=\"color:red\">Unsaved data will be lost</b>"
        )

    def openinqgis(self):
        projectfile = self.project.projectfile
        qgislocation = r'C:\OSGeo4W\bin\qgis.bat'
        qgislocation = roam.config.settings.setdefault('configmanager', {}) \
            .setdefault('qgislocation', qgislocation)

        try:
            openqgis(projectfile, qgislocation)
        except OSError:
            self.bar.pushMessage("Looks like I couldn't find QGIS",
                                 "Check qgislocation in roam.config",
                                 QgsMessageBar.WARNING)

    def openprojectfolder(self):
        folder = self.project.folder
        openfolder(folder)

    def setproject(self, project, loadqgis=True):
        """
        Set the widgets active project.
        """
        self.mapisloaded = False
        self.filewatcher.removePaths(self.filewatcher.files())
        self.projectupdatedlabel.hide()
        self._closeqgisproject()

        if project.valid:
            self.startsettings = copy.deepcopy(project.settings)
            self.project = project
            self.projectlabel.setText(project.name)
            self.loadqgisproject(project, self.project.projectfile)
            self.filewatcher.addPath(self.project.projectfile)
            self.projectloaded.emit(self.project)

    def loadqgisproject(self, project, projectfile):
        QDir.setCurrent(os.path.dirname(project.projectfile))
        fileinfo = QFileInfo(project.projectfile)
        self.projectLocationLabel.setText("Project File: {}".format(
            os.path.basename(project.projectfile)))
        QgsProject.instance().read(fileinfo)

    def _closeqgisproject(self):
        if self.canvas.isDrawing():
            return

        self.canvas.freeze(True)
        QgsMapLayerRegistry.instance().removeAllMapLayers()
        self.canvas.freeze(False)

    def loadmap(self):
        if self.mapisloaded:
            return

        # This is a dirty hack to work around the timer that is in QgsMapCanvas in 2.2.
        # Refresh will stop the canvas timer
        # Repaint will redraw the widget.
        # loadmap is only called once per project load so it's safe to do this here.
        self.canvas.refresh()
        self.canvas.repaint()

        parser = roam.projectparser.ProjectParser.fromFile(
            self.project.projectfile)
        canvasnode = parser.canvasnode
        self.canvas.mapRenderer().readXML(canvasnode)
        self.canvaslayers = parser.canvaslayers()
        self.canvas.setLayerSet(self.canvaslayers)
        self.canvas.updateScale()
        self.canvas.refresh()

        self.mapisloaded = True

    def _saveproject(self):
        """
        Save the project config to disk.
        """
        self.write_config_currentwidget()
        # self.project.dump_settings()
        self.project.save(update_version=True)
        self.projectsaved.emit()
コード例 #44
0
ファイル: projectwidget.py プロジェクト: xCherry/Roam
class ProjectWidget(Ui_Form, QWidget):
    SampleWidgetRole = Qt.UserRole + 1
    projectsaved = pyqtSignal()
    projectupdated = pyqtSignal()
    projectloaded = pyqtSignal(object)
    selectlayersupdated = pyqtSignal(list)

    def __init__(self, parent=None):
        super(ProjectWidget, self).__init__(parent)
        self.setupUi(self)
        self.project = None
        self.mapisloaded = False
        self.bar = None

        self.canvas.setCanvasColor(Qt.white)
        self.canvas.enableAntiAliasing(True)
        self.canvas.setWheelAction(QgsMapCanvas.WheelZoomToMouseCursor)
        self.canvas.mapRenderer().setLabelingEngine(QgsPalLabeling())

        self.fieldsmodel = QgsFieldModel()
        self.widgetmodel = WidgetsModel()
        self.possiblewidgetsmodel = QStandardItemModel()

        self.formlayersmodel = QgsLayerModel(watchregistry=False)
        self.formlayers = CaptureLayerFilter()
        self.formlayers.setSourceModel(self.formlayersmodel)

        self.selectlayermodel = CaptureLayersModel(watchregistry=False)
        self.selectlayerfilter = LayerTypeFilter()
        self.selectlayerfilter.setSourceModel(self.selectlayermodel)
        self.selectlayermodel.dataChanged.connect(self.selectlayerschanged)

        self.layerCombo.setModel(self.formlayers)
        self.widgetCombo.setModel(self.possiblewidgetsmodel)
        self.selectLayers.setModel(self.selectlayerfilter)
        self.selectLayers_2.setModel(self.selectlayerfilter)
        self.fieldList.setModel(self.fieldsmodel)

        self.widgetlist.setModel(self.widgetmodel)
        self.widgetlist.selectionModel().currentChanged.connect(self.updatecurrentwidget)
        self.widgetmodel.rowsRemoved.connect(self.setwidgetconfigvisiable)
        self.widgetmodel.rowsInserted.connect(self.setwidgetconfigvisiable)
        self.widgetmodel.modelReset.connect(self.setwidgetconfigvisiable)

        self.titleText.textChanged.connect(self.updatetitle)

        QgsProject.instance().readProject.connect(self._readproject)

        self.loadwidgettypes()

        self.addWidgetButton.pressed.connect(self.newwidget)
        self.removeWidgetButton.pressed.connect(self.removewidget)

        self.roamVersionLabel.setText("You are running IntraMaps Roam version {}".format(roam.__version__))

        self.openProjectFolderButton.pressed.connect(self.openprojectfolder)
        self.openinQGISButton.pressed.connect(self.openinqgis)

        self.filewatcher = QFileSystemWatcher()
        self.filewatcher.fileChanged.connect(self.qgisprojectupdated)

        self.formfolderLabel.linkActivated.connect(self.openformfolder)
        self.projectupdatedlabel.linkActivated.connect(self.reloadproject)
        self.projectupdatedlabel.hide()
        self.formtab.currentChanged.connect(self.formtabchanged)

        self.expressionButton.clicked.connect(self.opendefaultexpression)

        self.fieldList.currentIndexChanged.connect(self.updatewidgetname)
        self.fieldwarninglabel.hide()

        for item, data in readonlyvalues:
            self.readonlyCombo.addItem(item, data)

        self.setpage(4)
        self.form = None

    def setaboutinfo(self):
        self.versionLabel.setText(roam.__version__)
        self.qgisapiLabel.setText(str(QGis.QGIS_VERSION))

    def checkcapturelayers(self):
        haslayers = self.project.hascapturelayers()
        self.formslayerlabel.setVisible(not haslayers)
        return haslayers

    def opendefaultexpression(self):
        layer = self.currentform.QGISLayer
        dlg = QgsExpressionBuilderDialog(layer, "Create default value expression", self)
        text = self.defaultvalueText.text().strip('[%').strip('%]').strip()
        dlg.setExpressionText(text)
        if dlg.exec_():
            self.defaultvalueText.setText('[% {} %]'.format(dlg.expressionText()))

    def openformfolder(self, url):
        openfolder(url)

    def selectlayerschanged(self, *args):
        self.formlayers.setSelectLayers(self.project.selectlayers)
        self.checkcapturelayers()
        self.selectlayersupdated.emit(self.project.selectlayers)

    def formtabchanged(self, index):
        # preview
        if index == 1:
            self.form.settings['widgets'] = list(self.widgetmodel.widgets())
            self.setformpreview(self.form)


    def setpage(self, page):
        self.stackedWidget.setCurrentIndex(page)

    def reloadproject(self, *args):
        self.setproject(self.project)

    def qgisprojectupdated(self, path):
        self.projectupdatedlabel.show()
        self.projectupdatedlabel.setText("The QGIS project has been updated. <a href='reload'> "
                                         "Click to reload</a>. <b style=\"color:red\">Unsaved data will be lost</b>")

    def openinqgis(self):
        projectfile = self.project.projectfile
        qgislocation = r'C:\OSGeo4W\bin\qgis.bat'
        qgislocation = roam.config.settings.setdefault('configmanager', {}) \
                                        .setdefault('qgislocation', qgislocation)

        try:
            openqgis(projectfile, qgislocation)
        except WindowsError:
            self.bar.pushMessage("Looks like I couldn't find QGIS",
                               "Check qgislocation in roam.config", QgsMessageBar.WARNING)

    def openprojectfolder(self):
        folder = self.project.folder
        openfolder(folder)

    def setwidgetconfigvisiable(self, *args):
        haswidgets = self.widgetmodel.rowCount() > 0
        self.widgetframe.setEnabled(haswidgets)

    def removewidget(self):
        """
        Remove the selected widget from the widgets list
        """
        widget, index = self.currentuserwidget
        if index.isValid():
            self.widgetmodel.removeRow(index.row(), index.parent())

    def newwidget(self):
        """
        Create a new widget.  The default is a list.
        """
        widget = {}
        widget['widget'] = 'Text'
        # Grab the first field.
        widget['field'] = self.fieldsmodel.index(0, 0).data(QgsFieldModel.FieldNameRole)
        currentindex = self.widgetlist.currentIndex()
        currentitem = self.widgetmodel.itemFromIndex(currentindex)
        if currentitem and currentitem.iscontainor():
            parent = currentindex
        else:
            parent = currentindex.parent()
        index = self.widgetmodel.addwidget(widget, parent)
        self.widgetlist.setCurrentIndex(index)

    def loadwidgettypes(self):
        self.widgetCombo.blockSignals(True)
        for widgettype in roam.editorwidgets.core.supportedwidgets():
            try:
                configclass = configmanager.editorwidgets.widgetconfigs[widgettype]
            except KeyError:
                continue

            configwidget = configclass()
            item = QStandardItem(widgettype)
            item.setData(configwidget, Qt.UserRole)
            item.setData(widgettype, Qt.UserRole + 1)
            item.setIcon(QIcon(widgeticon(widgettype)))
            self.widgetCombo.model().appendRow(item)
            self.widgetstack.addWidget(configwidget)
        self.widgetCombo.blockSignals(False)

    def usedfields(self):
        """
        Return the list of fields that have been used by the the current form's widgets
        """
        for widget in self.currentform.widgets:
            yield widget['field']

    @property
    def currentform(self):
        """
        Return the current selected form.
        """
        return self.form

    @property
    def currentuserwidget(self):
        """
        Return the selected user widget.
        """
        index = self.widgetlist.currentIndex()
        return index.data(Qt.UserRole), index

    @property
    def currentwidgetconfig(self):
        """
        Return the selected widget in the widget combo.
        """
        index = self.widgetCombo.currentIndex()
        index = self.possiblewidgetsmodel.index(index, 0)
        return index.data(Qt.UserRole), index, index.data(Qt.UserRole + 1)

    def updatewidgetname(self, index):
        # Only change the edit text on name field if it's not already set to something other then the
        # field name.
        field = self.fieldsmodel.index(index, 0).data(QgsFieldModel.FieldNameRole)
        currenttext = self.nameText.text()
        foundfield = self.fieldsmodel.findfield(currenttext)
        if foundfield:
            self.nameText.setText(field)

    def _save_widgetfield(self, index):
        """
        Save the selected field for the current widget.

        Shows a error if the field is already used but will allow
        the user to still set it in the case of extra logic for that field
        in the forms Python logic.
        """
        widget, index = self.currentuserwidget
        row = self.fieldList.currentIndex()
        field = self.fieldsmodel.index(row, 0).data(QgsFieldModel.FieldNameRole)
        showwarning = field in self.usedfields()
        self.fieldwarninglabel.setVisible(showwarning)
        widget['field'] = field
        self.widgetmodel.setData(index, widget, Qt.UserRole)

    def _save_selectedwidget(self, index):
        configwidget, index, widgettype = self.currentwidgetconfig
        widget, index = self.currentuserwidget
        if not widget:
            return

        widget['widget'] = widgettype
        widget['required'] = self.requiredCheck.isChecked()
        widget['config'] = configwidget.getconfig()
        widget['name'] = self.nameText.text()
        widget['read-only-rules'] = [self.readonlyCombo.itemData(self.readonlyCombo.currentIndex())]
        widget['hidden'] = self.hiddenCheck.isChecked()

        self.widgetmodel.setData(index, widget, Qt.UserRole)

    def _save_default(self):
        widget, index = self.currentuserwidget
        default = self.defaultvalueText.text()
        widget['default'] = default
        self.widgetmodel.setData(index, widget, Qt.UserRole)

    def _save_selectionlayers(self, index, layer, value):
        config = self.project.settings

        self.selectlayermodel.dataChanged.emit(index, index)

    def _save_formtype(self, index):
        formtype = self.formtypeCombo.currentText()
        form = self.currentform
        form.settings['type'] = formtype

    def _save_formname(self, text):
        """
        Save the form label to the settings file.
        """
        try:
            form = self.currentform
            if form is None:
                return
            form.settings['label'] = text
            self.projectupdated.emit()
        except IndexError:
            return

    def _save_layer(self, index):
        """
        Save the selected layer to the settings file.
        """
        index = self.formlayers.index(index, 0)
        layer = index.data(Qt.UserRole)
        if not layer:
            return

        form = self.currentform
        if form is None:
            return

        form.settings['layer'] = layer.name()
        self.updatefields(layer)

    def setsplash(self, splash):
        pixmap = QPixmap(splash)
        w = self.splashlabel.width()
        h = self.splashlabel.height()
        self.splashlabel.setPixmap(pixmap.scaled(w,h, Qt.KeepAspectRatio))

    def setproject(self, project, loadqgis=True):
        """
        Set the widgets active project.
        """
        self.disconnectsignals()
        self.mapisloaded = False
        self.filewatcher.removePaths(self.filewatcher.files())
        self.projectupdatedlabel.hide()
        self._closeqgisproject()

        if project.valid:
            self.startsettings = copy.deepcopy(project.settings)
            self.project = project
            self.projectlabel.setText(project.name)
            self.versionText.setText(project.version)
            self.selectlayermodel.config = project.settings
            self.formlayers.setSelectLayers(self.project.selectlayers)
            self.setsplash(project.splash)
            self.loadqgisproject(project, self.project.projectfile)
            self.filewatcher.addPath(self.project.projectfile)
            self.projectloaded.emit(self.project)

    def loadqgisproject(self, project, projectfile):
        QDir.setCurrent(os.path.dirname(project.projectfile))
        fileinfo = QFileInfo(project.projectfile)
        QgsProject.instance().read(fileinfo)

    def _closeqgisproject(self):
        if self.canvas.isDrawing():
            return

        self.canvas.freeze(True)
        self.formlayersmodel.removeall()
        self.selectlayermodel.removeall()
        QgsMapLayerRegistry.instance().removeAllMapLayers()
        self.canvas.freeze(False)

    def loadmap(self):
        if self.mapisloaded:
            return

        # This is a dirty hack to work around the timer that is in QgsMapCanvas in 2.2.
        # Refresh will stop the canvas timer
        # Repaint will redraw the widget.
        # loadmap is only called once per project load so it's safe to do this here.
        self.canvas.refresh()
        self.canvas.repaint()

        parser = roam.projectparser.ProjectParser.fromFile(self.project.projectfile)
        canvasnode = parser.canvasnode
        self.canvas.mapRenderer().readXML(canvasnode)
        self.canvaslayers = parser.canvaslayers()
        self.canvas.setLayerSet(self.canvaslayers)
        self.canvas.updateScale()
        self.canvas.refresh()

        self.mapisloaded = True

    def _readproject(self, doc):
        self.formlayersmodel.refresh()
        self.selectlayermodel.refresh()
        self._updateforproject(self.project)

    def _updateforproject(self, project):
        self.titleText.setText(project.name)
        self.descriptionText.setPlainText(project.description)

    def swapwidgetconfig(self, index):
        widgetconfig, _, _ = self.currentwidgetconfig
        defaultvalue = widgetconfig.defaultvalue
        self.defaultvalueText.setText(defaultvalue)

        self.updatewidgetconfig({})

    def updatetitle(self, text):
        self.project.settings['title'] = text
        self.projectlabel.setText(text)
        self.projectupdated.emit()

    def updatewidgetconfig(self, config):
        widgetconfig, index, widgettype = self.currentwidgetconfig
        self.setconfigwidget(widgetconfig, config)

    def setformpreview(self, form):
        def removewidget():
            item = self.frame_2.layout().itemAt(0)
            if item and item.widget():
                item.widget().setParent(None)

        removewidget()

        featureform = FeatureForm.from_form(form, form.settings, None, {})

        self.frame_2.layout().addWidget(featureform)

    def connectsignals(self):
        self.formLabelText.textChanged.connect(self._save_formname)
        self.layerCombo.currentIndexChanged.connect(self._save_layer)
        self.formtypeCombo.currentIndexChanged.connect(self._save_formtype)

        #widget settings
        self.fieldList.currentIndexChanged.connect(self._save_widgetfield)
        self.requiredCheck.toggled.connect(self._save_selectedwidget)
        self.defaultvalueText.textChanged.connect(self._save_default)
        self.widgetCombo.currentIndexChanged.connect(self._save_selectedwidget)
        self.widgetCombo.currentIndexChanged.connect(self.swapwidgetconfig)
        self.nameText.textChanged.connect(self._save_selectedwidget)
        self.readonlyCombo.currentIndexChanged.connect(self._save_selectedwidget)
        self.hiddenCheck.toggled.connect(self._save_selectedwidget)

    def disconnectsignals(self):
        try:
            self.formLabelText.textChanged.disconnect(self._save_formname)
            self.layerCombo.currentIndexChanged.disconnect(self._save_layer)
            self.formtypeCombo.currentIndexChanged.disconnect(self._save_formtype)

            #widget settings
            self.fieldList.currentIndexChanged.disconnect(self._save_widgetfield)
            self.requiredCheck.toggled.disconnect(self._save_selectedwidget)
            self.defaultvalueText.textChanged.disconnect(self._save_default)
            self.widgetCombo.currentIndexChanged.disconnect(self._save_selectedwidget)
            self.widgetCombo.currentIndexChanged.disconnect(self.swapwidgetconfig)
            self.nameText.textChanged.disconnect(self._save_selectedwidget)
            self.readonlyCombo.currentIndexChanged.disconnect(self._save_selectedwidget)
            self.hiddenCheck.toggled.disconnect(self._save_selectedwidget)
        except TypeError:
            pass

    def setform(self, form):
        """
        Update the UI with the currently selected form.
        """

        def getfirstlayer():
            index = self.formlayers.index(0,0)
            layer = index.data(Qt.UserRole)
            layer = layer.name()
            return layer

        def loadwidgets(widget):
            """
            Load the widgets into widgets model
            """
            self.widgetmodel.clear()
            self.widgetmodel.loadwidgets(form.widgets)

        def findlayer(layername):
            index = self.formlayersmodel.findlayer(layername)
            index = self.formlayers.mapFromSource(index)
            layer = index.data(Qt.UserRole)
            return index, layer


        self.disconnectsignals()

        self.form = form

        settings = form.settings
        label = form.label
        layername = settings.setdefault('layer', getfirstlayer())
        layerindex, layer = findlayer(layername)
        if not layer or not layerindex.isValid():
            return

        formtype = settings.setdefault('type', 'auto')
        widgets = settings.setdefault('widgets', [])

        self.formLabelText.setText(label)
        folderurl = "<a href='{path}'>{name}</a>".format(path=form.folder, name=os.path.basename(form.folder))
        self.formfolderLabel.setText(folderurl)
        self.layerCombo.setCurrentIndex(layerindex.row())
        self.updatefields(layer)

        index = self.formtypeCombo.findText(formtype)
        if index == -1:
            self.formtypeCombo.insertItem(0, formtype)
            self.formtypeCombo.setCurrentIndex(0)
        else:
            self.formtypeCombo.setCurrentIndex(index)

        loadwidgets(widgets)

        # Set the first widget
        index = self.widgetmodel.index(0, 0)
        if index.isValid():
            self.widgetlist.setCurrentIndex(index)
            self.updatecurrentwidget(index, None)

        self.connectsignals()

    def updatefields(self, layer):
        """
        Update the UI with the fields for the selected layer.
        """
        self.fieldsmodel.setLayer(layer)

    def setconfigwidget(self, configwidget, config):
        """
        Set the active config widget.
        """

        try:
            configwidget.widgetdirty.disconnect(self._save_selectedwidget)
        except TypeError:
            pass

        #self.descriptionLabel.setText(configwidget.description)
        self.widgetstack.setCurrentWidget(configwidget)
        configwidget.setconfig(config)

        configwidget.widgetdirty.connect(self._save_selectedwidget)

    def updatecurrentwidget(self, index, _):
        """
        Update the UI with the config for the current selected widget.
        """
        if not index.isValid():
            return

        widget = index.data(Qt.UserRole)
        widgettype = widget['widget']
        field = widget['field']
        required = widget.setdefault('required', False)
        name = widget.setdefault('name', field)
        default = widget.setdefault('default', '')
        readonly = widget.setdefault('read-only-rules', [])
        hidden = widget.setdefault('hidden', False)

        try:
            data = readonly[0]
        except:
            data = 'never'

        self.readonlyCombo.blockSignals(True)
        index = self.readonlyCombo.findData(data)
        self.readonlyCombo.setCurrentIndex(index)
        self.readonlyCombo.blockSignals(False)

        self.defaultvalueText.blockSignals(True)
        if not isinstance(default, dict):
            self.defaultvalueText.setText(default)
            self.defaultvalueText.setEnabled(True)
            self.expressionButton.setEnabled(True)
        else:
            # TODO Handle the more advanced default values.
            self.defaultvalueText.setText("Advanced default set in config")
            self.defaultvalueText.setEnabled(False)
            self.expressionButton.setEnabled(False)
        self.defaultvalueText.blockSignals(False)

        self.nameText.blockSignals(True)
        self.nameText.setText(name)
        self.nameText.blockSignals(False)

        self.requiredCheck.blockSignals(True)
        self.requiredCheck.setChecked(required)
        self.requiredCheck.blockSignals(False)

        self.hiddenCheck.blockSignals(True)
        self.hiddenCheck.setChecked(hidden)
        self.hiddenCheck.blockSignals(False)

        if not field is None:
            self.fieldList.blockSignals(True)
            index = self.fieldList.findData(field.lower(), QgsFieldModel.FieldNameRole)
            if index > -1:
                self.fieldList.setCurrentIndex(index)
            else:
                self.fieldList.setEditText(field)
            self.fieldList.blockSignals(False)

        index = self.widgetCombo.findText(widgettype)
        self.widgetCombo.blockSignals(True)
        if index > -1:
            self.widgetCombo.setCurrentIndex(index)
        self.widgetCombo.blockSignals(False)

        self.updatewidgetconfig(config=widget.setdefault('config', {}))

    def _saveproject(self):
        """
        Save the project config to disk.
        """
        title = self.titleText.text()
        description = self.descriptionText.toPlainText()
        version = str(self.versionText.text())

        settings = self.project.settings
        settings['title'] = title
        settings['description'] = description
        settings['version'] = version

        form = self.currentform
        if form:
            form.settings['widgets'] = list(self.widgetmodel.widgets())
            logger.debug(form.settings)

        self.project.save()
        self.projectsaved.emit()
コード例 #45
0
ファイル: projectwidget.py プロジェクト: xCherry/Roam
    def __init__(self, parent=None):
        super(ProjectWidget, self).__init__(parent)
        self.setupUi(self)
        self.project = None
        self.mapisloaded = False
        self.bar = None

        self.canvas.setCanvasColor(Qt.white)
        self.canvas.enableAntiAliasing(True)
        self.canvas.setWheelAction(QgsMapCanvas.WheelZoomToMouseCursor)
        self.canvas.mapRenderer().setLabelingEngine(QgsPalLabeling())

        self.fieldsmodel = QgsFieldModel()
        self.widgetmodel = WidgetsModel()
        self.possiblewidgetsmodel = QStandardItemModel()

        self.formlayersmodel = QgsLayerModel(watchregistry=False)
        self.formlayers = CaptureLayerFilter()
        self.formlayers.setSourceModel(self.formlayersmodel)

        self.selectlayermodel = CaptureLayersModel(watchregistry=False)
        self.selectlayerfilter = LayerTypeFilter()
        self.selectlayerfilter.setSourceModel(self.selectlayermodel)
        self.selectlayermodel.dataChanged.connect(self.selectlayerschanged)

        self.layerCombo.setModel(self.formlayers)
        self.widgetCombo.setModel(self.possiblewidgetsmodel)
        self.selectLayers.setModel(self.selectlayerfilter)
        self.selectLayers_2.setModel(self.selectlayerfilter)
        self.fieldList.setModel(self.fieldsmodel)

        self.widgetlist.setModel(self.widgetmodel)
        self.widgetlist.selectionModel().currentChanged.connect(self.updatecurrentwidget)
        self.widgetmodel.rowsRemoved.connect(self.setwidgetconfigvisiable)
        self.widgetmodel.rowsInserted.connect(self.setwidgetconfigvisiable)
        self.widgetmodel.modelReset.connect(self.setwidgetconfigvisiable)

        self.titleText.textChanged.connect(self.updatetitle)

        QgsProject.instance().readProject.connect(self._readproject)

        self.loadwidgettypes()

        self.addWidgetButton.pressed.connect(self.newwidget)
        self.removeWidgetButton.pressed.connect(self.removewidget)

        self.roamVersionLabel.setText("You are running IntraMaps Roam version {}".format(roam.__version__))

        self.openProjectFolderButton.pressed.connect(self.openprojectfolder)
        self.openinQGISButton.pressed.connect(self.openinqgis)

        self.filewatcher = QFileSystemWatcher()
        self.filewatcher.fileChanged.connect(self.qgisprojectupdated)

        self.formfolderLabel.linkActivated.connect(self.openformfolder)
        self.projectupdatedlabel.linkActivated.connect(self.reloadproject)
        self.projectupdatedlabel.hide()
        self.formtab.currentChanged.connect(self.formtabchanged)

        self.expressionButton.clicked.connect(self.opendefaultexpression)

        self.fieldList.currentIndexChanged.connect(self.updatewidgetname)
        self.fieldwarninglabel.hide()

        for item, data in readonlyvalues:
            self.readonlyCombo.addItem(item, data)

        self.setpage(4)
        self.form = None
コード例 #46
0
ファイル: shp_excel_sync.py プロジェクト: signedav/shpsync
 def activateFileWatcher(self):
     self.filewatcher = QFileSystemWatcher([self.excelPath])
     self.filewatcher.fileChanged.connect(self.excel_changed)
コード例 #47
0
ファイル: text_editor.py プロジェクト: davtoh/RRtools
class Edytor(QMainWindow, Ui_edytor):
    fpath = ""

    def __init__(self):
        super(Edytor,self).__init__()
        self.setupUi(self)
        # Create watcher
        self.watcher = QFileSystemWatcher(self)

        # Register slots
        self.button_close.clicked.connect(self.close)
        self.button_open.clicked.connect(self.file_open)
        self.button_save.clicked.connect(self.file_save)
        self.editor_window.textChanged.connect(self.text_changed)
        self.watcher.fileChanged.connect(self.file_changed)

    @pyqtSlot()
    def file_open(self, fpath=""):
        if self.ask_discard():
            return

        fpath = fpath or QFileDialog.getOpenFileName(self, "Open file...")
        if isfile(fpath):
            # Switch watcher files
            if self.fpath:
                self.watcher.removePath(self.fpath)
            self.watcher.addPath(fpath)

            with open(fpath) as f:
                text = f.read()
            self.editor_window.setText(text)
            # Disable afterwards since `setText` triggers "textChanged" signal
            self.button_save.setEnabled(False)

            # Finally save the path
            self.fpath = fpath

    @pyqtSlot()
    def file_save(self):
        if isfile(self.fpath):
            # Do not trigger fileChanged when saving ourselves
            self.watcher.removePath(self.fpath)

            text = self.editor_window.toPlainText()
            with open(self.fpath, 'w') as f:
                f.write(text)

            self.button_save.setEnabled(False)
            self.watcher.addPath(self.fpath)

    @pyqtSlot()
    def text_changed(self):
        if self.fpath:
            self.button_save.setEnabled(True)

    @pyqtSlot(str)
    def file_changed(self, path):
        res = QMessageBox.question(
            self, "%s - File has been changed" % self.objectName(),
            "The opened document has been modified by another program.\n"
            + "Do you want to reload the file?",
            QMessageBox.Yes | QMessageBox.No
            | (QMessageBox.Save if self.button_save.isEnabled() else 0),
            QMessageBox.Yes
        )
        if res == QMessageBox.Yes:
            self.file_open(self.fpath)
        elif res == QMessageBox.Save:
            self.file_save()

    def ask_discard(self):
        if not self.button_save.isEnabled():
            return

        res = QMessageBox.question(
            self, "%s - Unsaved changes" % self.objectName(),
            "The document has been modified\n"
            + "Do you want to save your changes?",
            QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel,
            QMessageBox.Save
        )
        print(res)
        if res == QMessageBox.Save:
            self.file_save()

        return res == QMessageBox.Cancel

    def closeEvent(self, event):
        # For some reason this is called twice when clicking the "Close" button SOMETIMES
        if self.ask_discard():
            event.ignore()
        else:
            event.accept()
コード例 #48
0
 def _default__watcher(self):
     _watcher = QFileSystemWatcher()
     _watcher.directoryChanged.connect(self.on_directory_changed)
     return _watcher
コード例 #49
0
ファイル: document.py プロジェクト: vi/enki
class _FileWatcher(QObject):
    """File watcher.

    QFileSystemWatcher notifies client about any change (file access mode, modification date, etc.)
    But, we need signal, only after file contents had been changed
    """
    modified = pyqtSignal(bool)
    removed = pyqtSignal(bool)

    def __init__(self, path):
        QObject.__init__(self)
        self._contents = None
        self._watcher = QFileSystemWatcher()
        self._timer = None
        self._path = path

        self._lastEmittedModifiedStatus = None
        self._lastEmittedRemovedStatus = None

        self.setPath(path)
        self.enable()


    def __del__(self):
        self._stopTimer()

    def enable(self):
        """Enable signals from the watcher
        """
        self._watcher.fileChanged.connect(self._onFileChanged)

    def disable(self):
        """Disable signals from the watcher
        """
        self._watcher.fileChanged.disconnect(self._onFileChanged)
        self._stopTimer()

    def setContents(self, contents):
        """Set file contents. Watcher uses it to compare old and new contents of the file.
        """
        self._contents = contents
        # Qt File watcher may work incorrectly, if file was not existing, when it started
        if not self._watcher.files():
            self.setPath(self._path)
        self._lastEmittedModifiedStatus = None
        self._lastEmittedRemovedStatus = None

    def setPath(self, path):
        """Path had been changed or file had been created. Set new path
        """
        if self._watcher.files():
            self._watcher.removePaths(self._watcher.files())
        if path is not None and os.path.isfile(path):
            self._watcher.addPath(path)
        self._path = path
        self._lastEmittedModifiedStatus = None
        self._lastEmittedRemovedStatus = None

    def _emitModifiedStatus(self):
        """Emit self.modified signal with right status
        """
        isModified = self._contents != self._safeRead(self._path)
        if isModified != self._lastEmittedModifiedStatus:
            self.modified.emit(isModified)
            self._lastEmittedModifiedStatus = isModified

    def _emitRemovedStatus(self, isRemoved):
        """Emit 'removed', if status changed"""
        if isRemoved != self._lastEmittedRemovedStatus:
            self._lastEmittedRemovedStatus = isRemoved
            self.removed.emit(isRemoved)

    def _onFileChanged(self):
        """File changed. Emit own signal, if contents changed
        """
        if os.path.exists(self._path):
            self._emitModifiedStatus()
        else:
            self._emitRemovedStatus(True)

        # Sometimes QFileSystemWatcher emits only 1 signal for 2 modifications
        # Check once more later
        self._startTimer()

    def _startTimer(self):
        """Init a timer.
        It is used for monitoring file after deletion.
        Git removes file, than restores it.
        """
        if self._timer is None:
            self._timer = QTimer()
            self._timer.setInterval(500)
            self._timer.timeout.connect(self._onCheckIfDeletedTimer)
        self._timer.start()

    def _stopTimer(self):
        """Stop timer, if exists
        """
        if self._timer is not None:
            self._timer.stop()

    def _onCheckIfDeletedTimer(self):
        """Check, if file has been restored
        """
        if os.path.exists(self._path):
            self.setPath(self._path)  # restart Qt file watcher after file has been restored
            self._stopTimer()
            self._emitRemovedStatus(False)
            self._emitModifiedStatus()

    def _safeRead(self, path):
        """Read file. Ignore exceptions
        """
        try:
            with open(path, 'rb') as file:
                return file.read()
        except (OSError, IOError):
            return None
コード例 #50
0
ファイル: shp_excel_sync.py プロジェクト: opengisch/shpsync
class Syncer(QObject):

    def __init__(self, settings):
        QObject.__init__(self)
        self.s = settings
        self.filewatcher = None
        self.excelName = settings.excelName  # the layer name
        self.excelSheetName = settings.excelSheetName
        self.excelKeyName = settings.excelKeyName
        self.excelFkIdx = field_idx_from_name(
            self.excelName, self.excelKeyName)
        self.excelPath = layer_from_name(self.excelName).publicSource()
        self.excelKeyName = field_name_from_idx(
            self.excelName, self.excelFkIdx)
        # shpfile layer
        self.shpName = settings.shpName
        self.shpKeyName = settings.shpKeyName
        self.shpKeyIdx = field_idx_from_name(self.shpName, self.shpKeyName)
        self.skipLines = settings.skipLines
        layer_from_name(self.shpName).setFeatureFormSuppress(QgsVectorLayer.SuppressOn if settings.hideDialog else QgsVectorLayer.SuppressOff)

        self.join()
        self.clear_edit_state()
        self.initialSync()

    def join(self):
        # join the shp layer to the excel layer, non cached
        # TODO: Ignore if already joined?
        shpLayer = layer_from_name(self.shpName)
        jinfo = QgsVectorJoinInfo()
        jinfo.joinFieldName = self.excelKeyName
        jinfo.targetFieldName = self.shpKeyName
        jinfo.joinLayerId = layer_from_name(self.excelName).id()
        jinfo.memoryCache = False
        jinfo.prefix = ''
        for jinfo2 in shpLayer.vectorJoins():
            if jinfo2 == jinfo:
                info("Join already exists. Will not create it again")
                return
        info("Adding join between master and slave layers")
        shpLayer.addJoin(jinfo)

    def reload_excel(self):
        path = self.excelPath
        layer = layer_from_name(self.excelName)
        fsize = os.stat(self.excelPath).st_size
        info("fsize " + str(fsize))
        if fsize == 0:
            info("File empty. Won't reload yet")
            return
        layer.dataProvider().forceReload()
        show_message_bar("Excel reloaded from disk.")

    def excel_changed(self):
        info("Excel changed on disk - need to sync")
        self.reload_excel()
        self.update_shp_from_excel()

    def get_max_id(self):
    
        layer = layer_from_name(self.shpName)
        if layer.dataProvider().featureCount() == 0:
            return 0
        maxVal = layer.maximumValue(self.shpKeyIdx)
        if maxVal == None:
            return 0
        else:
            return maxVal

    def renameIds(self, fidToId):
        layer = layer_from_name(self.shpName)
        layer.startEditing()
        feats = query_layer_for_fids(self.shpName, fidToId.keys())
        for f in feats:
            res = layer.changeAttributeValue(
                f.id(), self.shpKeyIdx, fidToId[f.id()])
        layer.commitChanges()

    def added_geom(self, layerId, feats):
        info("added feats " + str(feats))
        layer = layer_from_name(self.shpName)
        maxFk = self.get_max_id()
        for i, _ in enumerate(feats):
            _id = maxFk + i + 1
            feats[i].setAttribute(self.shpKeyName, _id)

        self.shpAdd = feats

    def removed_geom_precommit(self, fids):
        #info("Removed fids"+str(fids))
        fks_to_remove = get_fk_set(
            self.shpName, self.shpKeyName, skipFirst=0, fids=fids, useProvider=True)
        self.shpRemove = self.shpRemove.union(fks_to_remove)
        info("feat ids to remove" + str(self.shpRemove))

    def changed_geom(self, layerId, geoms):
        fids = geoms.keys()
        feats = query_layer_for_fids(self.shpName, fids)
        fks_to_change = get_fk_set(
            self.shpName, self.shpKeyName, skipFirst=0, fids=fids)
        self.shpChange = {k: v for (k, v) in zip(fks_to_change, feats)}
        # info("changed"+str(shpChange))

    def get_ignore_indices(self):
        return [field_idx_from_name(self.excelName, field) for field in self.s.expressions.keys()]

    def write_feature_to_excel(self, sheet, idx, feat):
        sheet.write(idx, self.excelFkIdx, feat[self.shpKeyName])
        for (fieldName, exp) in self.s.expressions.iteritems():
            fieldIdx = field_idx_from_name(self.excelName, fieldName)
            exp = QgsExpression(exp)
            sheet.write(idx, fieldIdx, exp.evaluate(feat))

    def write_rowvals_to_excel(self, sheet, idx, vals, ignore=None):
        if ignore is None:
            ignore = []
        for i, v in enumerate(vals):
            if i not in ignore:
                sheet.write(idx, i, v)

    def update_excel_programmatically(self):

        status_msgs = []

        rb = open_workbook(self.excelPath, formatting_info=True)
        r_sheet = rb.sheet_by_name(self.excelSheetName)  # read only copy
        wb = xlwt.Workbook()
        w_sheet = wb.add_sheet(self.excelSheetName, cell_overwrite_ok=True)
        write_idx = 0

        for row_index in range(r_sheet.nrows):
            if row_index < self.skipLines:  # copy header and/or dummy lines
                vals = r_sheet.row_values(row_index)
                self.write_rowvals_to_excel(w_sheet, write_idx, vals)
                write_idx += 1
                continue
            # print(r_sheet.cell(row_index,1).value)
            fk = r_sheet.cell(row_index, self.excelFkIdx).value
            if fk in self.shpRemove:
                status_msgs.append("Removing feature with id {}".format(fk))
                continue
            if fk in self.shpChange.keys():
                status_msgs.append(
                    "Syncing geometry change to feature with id {}".format(fk))
                shpf = self.shpChange[fk]
                self.write_feature_to_excel(w_sheet, write_idx, shpf)
                vals = r_sheet.row_values(row_index)
                self.write_rowvals_to_excel(w_sheet, write_idx, vals,
                                            ignore=self.get_ignore_indices())
            else:  # else just copy the row
                vals = r_sheet.row_values(row_index)
                self.write_rowvals_to_excel(w_sheet, write_idx, vals)

            write_idx += 1

        fidToId = {}
        for shpf in self.shpAdd:
            status_msgs.append(
                "Adding new feature with id {}".format(shpf.attribute(self.shpKeyName)))
            fidToId[shpf.id()] = shpf.attribute(self.shpKeyName)
            self.write_feature_to_excel(w_sheet, write_idx, shpf)
            write_idx += 1

        info('\n'.join(status_msgs))
        wb.save(self.excelPath)
        if status_msgs:
            show_message_bar(status_msgs)
        else:
            show_message_bar("No changes to shapefile to sync.")
        return fidToId

    def clear_edit_state(self):
        info("Clearing edit state")
        self.shpAdd = []
        self.shpChange = {}
        self.shpRemove = Set([])

    def update_excel_from_shp(self):
        info("Will now update excel from edited shapefile")
        info("changing:" + str(self.shpChange))
        info("adding:" + str(self.shpAdd))
        info("removing" + str(self.shpRemove))
        self.deactivateFileWatcher()  # so that we don't sync back and forth
        fidToId = self.update_excel_programmatically()
        # need to alter the ids(not fids) of the new features after, because
        # editing the features after they've been commited doesn't work
        if fidToId:
            self.deactivateShpConnections()
            self.renameIds(fidToId)
            self.activateShpConnections()
        self.reload_excel()
        self.activateFileWatcher()
        self.clear_edit_state()

    def updateShpLayer(self, fksToRemove):
        if not fksToRemove:
            return

        prompt_msg = "Attempt to synchronize between Excel and Shapefile. Shapefile has features with ids: ({}) that don't appear in the Excel. Delete those features from the shapefile? ".format(
            ','.join([str(fk) for fk in fksToRemove]))
        reply = QtGui.QMessageBox.question(iface.mainWindow(), 'Message',
                                           prompt_msg, QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)

        if reply == QtGui.QMessageBox.Yes:
            layer = layer_from_name(self.shpName)
            feats = [f for f in layer.getFeatures()]
            layer.startEditing()
            for f in feats:
                if f.attribute(self.shpKeyName) in fksToRemove:
                    layer.deleteFeature(f.id())
            layer.commitChanges()
        else:
            return

    def update_shp_from_excel(self):
        excelFks = Set(
            get_fk_set(self.excelName, self.excelKeyName, skipFirst=self.skipLines))
        shpFks = Set(get_fk_set(self.shpName, self.shpKeyName, skipFirst=0))
        # TODO also special warning if shp layer is in edit mode
        info("Keys in excel" + str(excelFks))
        info("Keys in shp" + str(shpFks))
        if shpFks == excelFks:
            info("Excel and Shp layer have the same rows. No update necessary")
            return
        inShpButNotInExcel = shpFks - excelFks
        inExcelButNotInShp = excelFks - shpFks
        if inExcelButNotInShp:
            warn("There are rows in the excel file with no matching geometry {}.".format(
                inExcelButNotInShp))
            # FIXME: if those are added later then they will be added twice..
            # However, having an autoincrement id suggests features would be
            # added first from shp only?

        if inShpButNotInExcel:
            self.updateShpLayer(inShpButNotInExcel)

    def activateFileWatcher(self):
        self.filewatcher = QFileSystemWatcher([self.excelPath])
        self.filewatcher.fileChanged.connect(self.excel_changed)

    def deactivateFileWatcher(self):
        self.filewatcher.fileChanged.disconnect(self.excel_changed)
        self.filewatcher.removePath(self.excelPath)

    def activateShpConnections(self):
        shpLayer = layer_from_name(self.shpName)
        shpLayer.committedFeaturesAdded.connect(self.added_geom)
        shpLayer.featuresDeleted.connect(self.removed_geom_precommit)
        shpLayer.committedGeometriesChanges.connect(self.changed_geom)
        shpLayer.editingStopped.connect(self.update_excel_from_shp)
        shpLayer.beforeRollBack.connect(self.clear_edit_state)

    def deactivateShpConnections(self):
        shpLayer = layer_from_name(self.shpName)
        shpLayer.committedFeaturesAdded.disconnect(self.added_geom)
        # shpLayer.featureAdded.disconnect(added_geom_precommit)
        shpLayer.featuresDeleted.disconnect(self.removed_geom_precommit)
        shpLayer.committedGeometriesChanges.disconnect(self.changed_geom)
        shpLayer.editingStopped.disconnect(self.update_excel_from_shp)
        shpLayer.beforeRollBack.disconnect(self.clear_edit_state)

    def initialSync(self):
        info("Initial Syncing excel to shp")
        self.update_shp_from_excel()
        self.activateFileWatcher()
        self.activateShpConnections()

    def __del__(self):
        self.deactivateFileWatcher()
        self.deactivateShpConnections()
コード例 #51
0
ファイル: projectwidget.py プロジェクト: hbatista/Roam
class ProjectWidget(Ui_Form, QWidget):
    SampleWidgetRole = Qt.UserRole + 1
    projectsaved = pyqtSignal()
    projectupdated = pyqtSignal(object)
    projectloaded = pyqtSignal(object)
    selectlayersupdated = pyqtSignal(list)

    def __init__(self, parent=None):
        super(ProjectWidget, self).__init__(parent)
        self.setupUi(self)
        self.project = None
        self.bar = None
        self.roamapp = None

        menu = QMenu()

        # self.roamVersionLabel.setText("You are running IntraMaps Roam version {}".format(roam.__version__))

        self.openProjectFolderButton.pressed.connect(self.openprojectfolder)
        self.openinQGISButton.pressed.connect(self.openinqgis)
        self.depolyProjectButton.pressed.connect(self.deploy_project)
        self.depolyInstallProjectButton.pressed.connect(
            functools.partial(self.deploy_project, True))

        self.filewatcher = QFileSystemWatcher()
        self.filewatcher.fileChanged.connect(self.qgisprojectupdated)

        self.projectupdatedlabel.linkActivated.connect(self.reloadproject)
        self.projectupdatedlabel.hide()

        # self.setpage(4)
        self.currentnode = None
        self.form = None

        qgislocation = r'C:\OSGeo4W\bin\qgis.bat'
        qgislocation = roam.config.settings.setdefault('configmanager', {}) \
            .setdefault('qgislocation', qgislocation)

        self.qgispathEdit.setText(qgislocation)
        self.qgispathEdit.textChanged.connect(self.save_qgis_path)
        self.filePickerButton.pressed.connect(self.set_qgis_path)

        self.connect_page_events()

    def connect_page_events(self):
        """
        Connect the events from all the pages back to here
        """
        for index in range(self.stackedWidget.count()):
            widget = self.stackedWidget.widget(index)
            if hasattr(widget, "raiseMessage"):
                widget.raiseMessage.connect(self.bar.pushMessage)

    def set_qgis_path(self):
        """
        Set the location of the QGIS install.  We need the path to be able to create Roam
        projects
        """
        path = QFileDialog.getOpenFileName(self,
                                           "Select QGIS install file",
                                           filter="(*.bat)")
        if not path:
            return
        self.qgispathEdit.setText(path)
        self.save_qgis_path(path)

    def save_qgis_path(self, path):
        """
        Save the QGIS path back to the Roam config.
        """
        roam.config.settings['configmanager'] = {'qgislocation': path}
        roam.config.save()

    def setpage(self, page, node):
        """
        Set the current page in the config manager.  We pass the project into the current
        page so that it knows what the project is.
        """
        self.currentnode = node

        self.write_config_currentwidget()

        self.stackedWidget.setCurrentIndex(page)

        widget = self.stackedWidget.currentWidget()
        if hasattr(widget, "set_project"):
            widget.set_project(self.project, self.currentnode)

    def write_config_currentwidget(self):
        """
        Call the write config command on the current widget.
        """
        widget = self.stackedWidget.currentWidget()
        if hasattr(widget, "write_config"):
            widget.write_config()

    def deploy_project(self, with_data=False):
        """
        Run the step to deploy a project. Projects are deplyed as a bundled zip of the project folder.
        """
        if self.roamapp.sourcerun:
            base = os.path.join(self.roamapp.apppath, "..")
        else:
            base = self.roamapp.apppath

        default = os.path.join(base, "roam_serv")
        path = roam.config.settings.get("publish", {}).get("path", '')
        if not path:
            path = default

        path = os.path.join(path, "projects")

        if not os.path.exists(path):
            os.makedirs(path)

        self._saveproject()
        options = {}

        bundle.bundle_project(self.project,
                              path,
                              options,
                              as_install=with_data)

    def setaboutinfo(self):
        """
        Set the current about info on the widget
        """
        self.versionLabel.setText(roam.__version__)
        self.qgisapiLabel.setText(unicode(QGis.QGIS_VERSION))

    def selectlayerschanged(self, *args):
        """
        Run the updates when the selection layers have changed
        """
        self.formlayers.setSelectLayers(self.project.selectlayers)
        self.selectlayersupdated.emit(self.project.selectlayers)

    def reloadproject(self, *args):
        """
        Reload the project. At the moment this will drop any unsaved changes to the config.
        Note: Should look at making sure it doesn't do that because it's not really needed.
        """
        self.projectupdated.emit(self.project)
        # self.setproject(self.project)

    def qgisprojectupdated(self, path):
        """
        Show a message when the QGIS project file has been updated.
        """
        self.projectupdatedlabel.show()
        self.projectupdatedlabel.setText(
            "The QGIS project has been updated. <a href='reload'> "
            "Click to reload</a>. <b style=\"color:red\">Unsaved data will be lost</b>"
        )

    def openinqgis(self):
        """
        Open a QGIS session for the user to config the project layers.
        """
        try:
            openqgis(self.project.projectfile)
        except OSError:
            self.bar.pushMessage("Looks like I couldn't find QGIS",
                                 "Check qgislocation in roam.config",
                                 QgsMessageBar.WARNING)

    def openprojectfolder(self):
        """
        Open the project folder in the file manager for the OS.
        """
        folder = self.project.folder
        openfolder(folder)

    def setproject(self, project, loadqgis=True):
        """
        Set the widgets active project.
        """
        self.filewatcher.removePaths(self.filewatcher.files())
        self.projectupdatedlabel.hide()
        self._closeqgisproject()

        if project.valid:
            self.startsettings = copy.deepcopy(project.settings)
            self.project = project
            self.projectlabel.setText(project.name)
            self.loadqgisproject(project, self.project.projectfile)
            self.filewatcher.addPath(self.project.projectfile)
            self.projectloaded.emit(self.project)

    def loadqgisproject(self, project, projectfile):
        print("Load QGIS Project!!")
        QDir.setCurrent(os.path.dirname(project.projectfile))
        fileinfo = QFileInfo(project.projectfile)
        # No idea why we have to set this each time.  Maybe QGIS deletes it for
        # some reason.
        self.badLayerHandler = BadLayerHandler(callback=self.missing_layers)
        QgsProject.instance().setBadLayerHandler(self.badLayerHandler)
        QgsProject.instance().read(fileinfo)

    def missing_layers(self, missinglayers):
        """
        Handle any and show any missing layers.
        """
        self.project.missing_layers = missinglayers

    def _closeqgisproject(self):
        """
        Close the current QGIS project and clean up after..
        """
        QGIS.close_project()

    def _saveproject(self):
        """
        Save the project config to disk.
        """
        self.write_config_currentwidget()
        # self.project.dump_settings()
        self.project.save(update_version=True)
        self.filewatcher.removePaths(self.filewatcher.files())
        QgsProject.instance().write()
        self.filewatcher.addPath(self.project.projectfile)
        self.projectsaved.emit()
コード例 #52
0
ファイル: shp_excel_sync.py プロジェクト: opengisch/shpsync
 def activateFileWatcher(self):
     self.filewatcher = QFileSystemWatcher([self.excelPath])
     self.filewatcher.fileChanged.connect(self.excel_changed)
コード例 #53
0
class PreferencesWindow(BaseWindow):
    def __init__(self, *args, **kwargs):
        super(PreferencesWindow, self).__init__(layoutCls=QVBoxLayout,
                                                *args,
                                                **kwargs)
        self.setWindowTitle("Settings")
        self.setWindowIcon(QIcon(SETTINGS['icon']))
        self._add_steam_box()
        self._add_dota_box()
        self._add_additional_prefs()
        self._add_log_box()

        self._add_log_watcher()
        Settings().signals.changed.connect(self.update_path)

    def _add_log_watcher(self):
        self.watcher = QFileSystemWatcher()
        self.watcher.addPath(abspath(log.file_name))
        self.watcher.fileChanged.connect(self.update_log)

    def show(self):
        self.update_log(abspath(log.file_name))
        return super(PreferencesWindow, self).show()

    def update_path(self, setting_key, new_value):
        if setting_key == "dota_path":
            self.dota_path.setText(new_value)
        elif setting_key == "steam_path":
            self.steam_path.setText(new_value)

    def _add_steam_box(self):
        box = QGroupBox("Steam Location")
        box.setLayout(QHBoxLayout(box))

        self.steam_path = QLineEdit(box)
        self.steam_path.setReadOnly(True)
        self.steam_path.setText(Settings().get("steam_path"))

        change_btn = QPushButton("Change...", box)
        change_btn.clicked.connect(self.change_steam_path)

        box.layout().addWidget(self.steam_path)
        box.layout().addWidget(change_btn)

        self.layout().addWidget(box)

    def _add_dota_box(self):
        box = QGroupBox("Dota Location")
        box.setLayout(QHBoxLayout(box))

        self.dota_path = QLineEdit(box)
        self.dota_path.setReadOnly(True)
        self.dota_path.setText(Settings().get("dota_path"))

        change_btn = QPushButton("Change...", box)
        change_btn.clicked.connect(self.change_dota_path)

        box.layout().addWidget(self.dota_path)
        box.layout().addWidget(change_btn)

        self.layout().addWidget(box)

    def change_steam_path(self):
        self._change_path("steam_path", is_steam_path_valid)

    def change_dota_path(self):
        self._change_path("dota_path", is_dota_path_valid)

    def _change_path(self, path_key, is_valid):
        new_folder = str(
            QFileDialog.getExistingDirectory(
                parent=self,
                caption="Select new path",
                directory=Settings().get(path_key)))
        if new_folder and exists(new_folder):
            if is_valid(new_folder):
                Settings().set(path_key, new_folder)
            else:
                from d2mp.ui import Message
                Message.critical(
                    "Path is not valid",
                    "Path was not saved in settings.\nPlease select a directory with the right executable in it!"
                )

    def _add_additional_prefs(self):
        box = QGroupBox("Additional Preferences")
        box.setLayout(QHBoxLayout(box))

        log_btn = QPushButton("View Log", box)
        log_btn.clicked.connect(self.open_log_file)
        reset_btn = QPushButton("Reset Settings", box)
        reset_btn.clicked.connect(Settings().reset)

        box.layout().addWidget(log_btn)
        box.layout().addWidget(reset_btn)

        self.layout().addWidget(box)

    def _add_log_box(self):
        box = QGroupBox("Application log")
        box.setLayout(QHBoxLayout(box))

        self.log_area = QTextBrowser(box)
        self.log_area.setLineWrapMode(QTextEdit.NoWrap)

        box.layout().addWidget(self.log_area)
        self.layout().addWidget(box)

    def open_log_file(self):
        log.INFO("TODO: open file in standard editor")
        print(abspath(log.file_name))

    def update_log(self, log_file):
        content = ""
        for line in open(log_file):
            if "========= new programm start =========" in line:
                content = ""
            else:
                content += line[37:]
        if content:
            self.log_area.setText(content)
コード例 #54
0
 def _add_log_watcher(self):
     self.watcher = QFileSystemWatcher()
     self.watcher.addPath(abspath(log.file_name))
     self.watcher.fileChanged.connect(self.update_log)
コード例 #55
0
ファイル: windows.py プロジェクト: BloodyD/D2ModdinPyClient
 def _add_log_watcher(self):
     self.watcher = QFileSystemWatcher()
     self.watcher.addPath(abspath(log.file_name))
     self.watcher.fileChanged.connect(self.update_log)
コード例 #56
0
class ScanPage(QWizardPage):
    scanError = pyqtSignal()  # name
    scanSuccess = pyqtSignal()
    path = "qtui/ui/page3_scan.ui"

    def __init__(self, project, parentW=None):
        super(ScanPage, self).__init__()
        self.ui = uic.loadUi(join(os.environ['AUTOEXAM_FOLDER'], self.path),
                             self)
        self.project = project
        self.scan_thread = None
        self.ui.treeWidget.currentItemChanged.connect(self.change_tree_item)
        self.ui.openCameraButton.clicked.connect(self.open_camera)
        self.question_item_to_question = {}

        self.exams = []
        self.order = None
        self.results = None
        self.parentWizard = parentW
        self.scanError.connect(self.on_scan_error)
        self.scanSuccess.connect(self.on_scan_success)
        self.scanning = False

    def initializePage(self):
        super(ScanPage, self).initializePage()
        # api.add_scan_event_subscriber(self)

        self.open_camera()

        if os.path.exists(ORDER_FILE_PATH):
            self.order = scanresults.parse(ORDER_FILE_PATH)

        self.watcher = QFileSystemWatcher()
        self.watcher.fileChanged.connect(self.on_scan_file_change)

        if os.path.exists(TESTS_RESULTS_FILE_PATH):
            self.results = scanresults.parse(TESTS_RESULTS_FILE_PATH)
            self.update_question_tree_widget()
        else:
            with open(TESTS_RESULTS_FILE_PATH, 'w') as f:
                f.write('{}')
            self.results = scanresults.parse(TESTS_RESULTS_FILE_PATH)

        # TODO: Check why this doesn't always work
        self.watcher.addPath(TESTS_RESULTS_FILE_PATH)
        self.last_load_time = time.time()

    def update_question_tree_widget(self):
        tree = self.ui.treeWidget
        tree.clear()

        for i in range(len(self.order)):
            incomplete_test = False
            exam_item = QTreeWidgetItem(tree, ['Exam %d' % i])
            for j in range(len(self.order[i].questions)):
                question_item = QTreeWidgetItem(exam_item,
                                                ['Question %d' % (j + 1)])
                if i in self.results:
                    question_item.question = self.project.questions[
                        self.order[i].questions[j].id - 1]
                else:
                    incomplete_test = True
            if incomplete_test:
                exam_item.setBackground(0, QBrush(Qt.lightGray))

        first_exam_item = tree.topLevelItem(0)
        first_exam_item.setExpanded(True)
        tree.setCurrentItem(tree.itemBelow(first_exam_item))

    def validatePage(self):

        if self.scanning:
            self.show_modal_message(
                'Please close the scanner window first by pressing \'q\'')
            return False
        # TODO: Warning validation here!!!
        if self.results is not None:
            scanresults.dump(self.results,
                             TESTS_RESULTS_FILE_PATH,
                             overwrite=False)
            self.parentWizard.results = self.results
            return True
        else:
            self.show_modal_message('There are still no results to save')
            return False

    def cleanupPage(self):
        super(ScanPage, self).cleanupPage()
        # api.remove_scan_event_subscriber(self)

        # TODO: Do proper shutdown
        # self.scan_thread.__stop()

    # def on_scan_event(self, report):
    #     if report.success:
    #         print 'successful report: ', report
    #         self.process_report(report)
    #     else:
    #         print 'failed report: ', report

    def on_scan_file_change(self, filename):
        if time.time() - self.last_load_time > 2:
            try:
                print('Reloading results...')
                self.results = scanresults.parse(TESTS_RESULTS_FILE_PATH)
                self.update_question_tree_widget()
                self.last_load_time = time.time()
                print('Results reloaded')
            except:
                print('Could not load results.')
        else:
            # print('Ignoring repetitive filewatcher event (this is normal)')
            pass

    # def process_report(self, report):
    #     current = self.ui.treeWidget.topLevelItem(report.test.id)
    #
    #     if current:
    #         if len(report.test.warnings) == 0:
    #             current.setForeground(0, ok_color)
    #         elif len(report.test.warnings) > 0:
    #             current.setForeground(0, warn_color)

    def change_tree_item(self):
        currentItem = self.ui.treeWidget.currentItem()
        if currentItem is not None:
            self.cleanupPanel()
            self.current_item = currentItem
            if currentItem.parent() is not None:  # i.e. it is a question
                self.update_question_panel_with_question()
            else:
                self.update_question_panel_with_exam()

    def update_question_panel_with_question(self):
        current_exam_item = self.current_item.parent()
        exam_no = self.ui.treeWidget.indexOfTopLevelItem(current_exam_item)
        question_no = current_exam_item.indexOfChild(self.current_item)
        question_info = self.project.questions[
            self.order[exam_no].questions[question_no].id - 1]

        self.ui.questionTextLabel.setText(question_info.text)

        # self.ui.questionDataLayout.addWidget(QLabel(question_info.text))

        order_info = self.order[exam_no].questions[question_no].order

        for answer_no in order_info:
            answer = question_info.answers[answer_no]
            answer_text = answer.text
            answer_text += ' (x)' if answer.valid else ''
            question_answer_check = QCheckBox(answer_text)
            question_answer_check.setChecked(
                self.is_answer_checked(exam_no, question_no, answer_no))
            question_answer_check.stateChanged.connect(
                self.update_current_question_state)
            self.ui.questionDataLayout.addWidget(question_answer_check)

    def update_question_panel_with_exam(self):
        current_exam_item = self.current_item
        exam_no = self.ui.treeWidget.indexOfTopLevelItem(current_exam_item)

        if self.results is not None:
            if exam_no in self.results:
                question_text_label = QLabel('TODO: Put here the warnings...')
            else:
                question_text_label = QLabel('This exam has not been scanned!')
        else:
            print('results null! please check!')

        self.ui.questionDataLayout.addWidget(question_text_label)

    def is_answer_checked(self, exam_no, question_no, answer_no):
        # print 'is_answer_checked'
        # print(exam_no,question_no,answer_no)

        try:
            results_data = self.results
            exam_data = results_data[exam_no]

            question_data = exam_data.questions[question_no]
            return answer_no in question_data.answers
        except:
            # print('answer not scanned exception')
            return False

    def update_current_question_state(self, state):
        current_exam_item = self.current_item.parent()

        exam_no = self.ui.treeWidget.indexOfTopLevelItem(current_exam_item)
        question_no = current_exam_item.indexOfChild(self.current_item)

        results_data = self.results

        if exam_no in results_data:
            question_data = results_data[exam_no].questions[question_no]

            order_data = self.order[exam_no].questions[question_no].order
            self.synchronize_answers_with_model(order_data, question_data)

        else:
            # If we get here, we're trying to manually enter info for an
            # exam that has not been scanned yet.
            # We should create an entry in results_data similar
            confirm_edit = QMessageBox.question(
                None, "Manual input?",
                "Do you want to manually enter this test's results?",
                QMessageBox.Yes | QMessageBox.No)
            regen = confirm_edit == QMessageBox.Yes
            if confirm_edit:
                self.results[exam_no] = self.order[exam_no]
                question_data = results_data[exam_no].questions[question_no]
                order_data = self.order[exam_no].questions[question_no].order
                self.synchronize_answers_with_model(order_data, question_data)

                current_exam_item.setBackground(0, QBrush(Qt.white))

    def synchronize_answers_with_model(self, order_data, question_data):
        for i in range(len(order_data)):
            checked = self.ui.questionDataLayout.itemAt(i).widget().isChecked()
            question_idx = order_data[i]
            if checked and question_idx not in question_data.answers:
                question_data.answers.append(question_idx)
            elif not checked and question_idx in question_data.answers:
                question_data.answers.remove(question_idx)

    def cleanupPage(self):
        self.watcher.fileChanged.disconnect(self.on_scan_file_change)
        del self.watcher

    def cleanupPanel(self):
        for i in reversed(range(self.ui.questionDataLayout.count())):
            elem = self.ui.questionDataLayout.itemAt(i)
            if not elem:
                break
            elem.widget().deleteLater()

    def start_scan(self):
        class _args:
            outfile = TESTS_RESULTS_FILE_PATH
            cameras = [self.ui.cameraIndexSpin.value()
                       ]  #TODO: UN-WIRE THIS !!!!
            folder = IMAGES_FOLDER
            time = None
            autowrite = True
            poll = None
            debug = False

        self.scanning = True

        ok = api.scan(_args())  # TODO: Fill dictionary properly
        if ok:
            self.scanSuccess.emit()
        else:
            self.scanError.emit()

        self.scanning = False

    def open_camera(self):
        self.ui.openCameraButton.setEnabled(False)

        self.scan_thread = Thread(target=self.start_scan)
        self.scan_thread.setDaemon(True)
        self.scan_thread.start()
        # self.start_scan()

    def on_scan_error(self):
        # self.parentWizard.back()
        self.show_modal_message("There was an error in the scanning process.\
        Please, check if the right camera is selected and try again.")
        self.ui.openCameraButton.setEnabled(True)

    def show_modal_message(self, msg):
        """
        Shows a modal MessageBox displaying the argument string
        """
        msgBox = QMessageBox()
        msgBox.setText(msg)
        msgBox.setModal(True)
        msgBox.setIcon(QMessageBox.Warning)
        msgBox.exec_()

    def on_scan_success(self):
        """
        Reloads results one last time in case the filewatcher doesn't work
        """

        # Do another dump first to store manually entered results
        scanresults.dump(self.results, TESTS_RESULTS_FILE_PATH)

        # Reload merged results
        self.results = scanresults.parse(TESTS_RESULTS_FILE_PATH)

        # Update UI
        self.update_question_tree_widget()

        # Reenable the button in case someone needs to scan again
        self.ui.openCameraButton.setEnabled(True)

        # Msg for debugging purposes
        print 'All OK with the scanning!'