def unmodalWidget(objectName, repeatTimes=10, repeatInterval=500, step=0): """Look for a widget in the QGIS hierarchy to set it as not modal. If the widget is not found try agail after a "repeatInterval" and repeat no more that "repeatTimes" """ if not objectName: return l = QgsApplication.instance().topLevelWidgets() for d in l: for dd in d.findChildren(QDialog): if dd.objectName() != objectName: continue dd.setWindowModality(False) return if repeatTimes == step: return # if here => not found QTimer.singleShot( repeatInterval, lambda: unmodalWidget(objectName, repeatTimes, repeatInterval, step + 1))
def test_delete_feature(self): """ Check if a feature can be deleted properly """ self.createWrapper(self.vl_a, '"name"=\'Erich Gamma\'') self.assertEqual(self.table_view.model().rowCount(), 1) self.assertEqual(1, len([f for f in self.vl_b.getFeatures()])) fid = next(self.vl_b.getFeatures(QgsFeatureRequest().setFilterExpression('"name"=\'Design Patterns. Elements of Reusable Object-Oriented Software\''))).id() self.widget.featureSelectionManager().select([fid]) btn = self.widget.findChild(QToolButton, 'mDeleteFeatureButton') def clickOk(): # Click the "Delete features" button on the confirmation message # box widget = self.widget.findChild(QMessageBox) buttonBox = widget.findChild(QDialogButtonBox) deleteButton = next((b for b in buttonBox.buttons() if buttonBox.buttonRole(b) == QDialogButtonBox.AcceptRole)) deleteButton.click() QTimer.singleShot(1, clickOk) btn.click() # This is the important check that the feature is deleted self.assertEqual(0, len([f for f in self.vl_b.getFeatures()])) # This is actually more checking that the database on delete action is properly set on the relation self.assertEqual(0, len([f for f in self.vl_link.getFeatures()])) self.assertEqual(self.table_view.model().rowCount(), 0)
def unmodalWidget(objectName, repeatTimes=10, repeatInterval=500, step=0): """Look for a widget in the QGIS hierarchy to set it as not modal. If the widget is not found try agail after a "repeatInterval" and repeat no more that "repeatTimes" """ if not objectName: return l = QgsApplication.instance().topLevelWidgets() for d in l: for dd in d.findChildren(QDialog): if dd.objectName() != objectName: continue dd.setWindowModality(False) return if repeatTimes == step: return # if here => not found QTimer.singleShot(repeatInterval, lambda: unmodalWidget(objectName, repeatTimes, repeatInterval, step + 1))
def test_model_stop(self): """Test that when a model is deleted fetching query rows is also interrupted""" md = QgsProviderRegistry.instance().providerMetadata('postgres') conn = md.createConnection(self.uri, {}) res = conn.execSql('SELECT * FROM qgis_test.random_big_data') self.model = QgsQueryResultModel(res) def model_deleter(): del (self.model) self.running = True def loop_exiter(): self.running = False QTimer.singleShot(1, model_deleter) QTimer.singleShot(2, loop_exiter) while self.running: QCoreApplication.processEvents() self.assertTrue(res.fetchedRowCount() > 0 and res.fetchedRowCount() < self.NUM_RECORDS)
def _dropEvent(event): def alg_dropped(algorithm_id, pos): alg = QgsApplication.processingRegistry().createAlgorithmById( algorithm_id) if alg is not None: self._addAlgorithm(alg, pos) else: assert False, algorithm_id def input_dropped(id, pos): if id in [ param.id() for param in QgsApplication.instance(). processingRegistry().parameterTypes() ]: self.addInputOfType(itemId, pos) if event.mimeData().hasFormat( 'application/x-vnd.qgis.qgis.algorithmid'): data = event.mimeData().data( 'application/x-vnd.qgis.qgis.algorithmid') stream = QDataStream(data, QIODevice.ReadOnly) algorithm_id = stream.readQString() QTimer.singleShot( 0, lambda id=algorithm_id, pos=self.view.mapToScene(event.pos( )): alg_dropped(id, pos)) event.accept() elif event.mimeData().hasText(): itemId = event.mimeData().text() QTimer.singleShot(0, lambda id=itemId, pos=self.view.mapToScene( event.pos()): input_dropped(id, pos)) event.accept() else: event.ignore()
def wrapper(self): if hasattr(self, "plugin_dock"): plugin_dock = getattr(self, "plugin_dock") else: plugin_dock = self threedi_api = getattr(plugin_dock, "threedi_api", None) if threedi_api is None: plugin_dock.communication.bar_info( "Action reserved for logged in users. Logging-in...") log_in_dialog = LogInDialog(plugin_dock) log_in_dialog.show() QTimer.singleShot(10, log_in_dialog.log_in_threedi) log_in_dialog.exec_() if log_in_dialog.LOGGED_IN: plugin_dock.threedi_api = log_in_dialog.threedi_api plugin_dock.current_user = log_in_dialog.user plugin_dock.current_user_full_name = log_in_dialog.user_full_name plugin_dock.organisations = log_in_dialog.organisations plugin_dock.initialize_authorized_view() else: plugin_dock.communication.bar_warn( "Logging-in canceled. Action aborted!") return return fn(self)
def test_model_stop(self): """Test that when a model is deleted fetching query rows is also interrupted""" def model_deleter(): del self.model def loop_exiter(): self.running = False md = QgsProviderRegistry.instance().providerMetadata('postgres') conn = md.createConnection(self.uri, {}) res = conn.execSql('SELECT * FROM qgis_test.random_big_data') self.model = QgsQueryResultModel(res) self.running = True QTimer.singleShot(15, model_deleter) QTimer.singleShot(600, loop_exiter) while self.running: try: self.model.fetchMore(QModelIndex()) except: pass QCoreApplication.processEvents() row_count = res.fetchedRowCount() self.assertGreater(row_count, 0) self.assertLess(row_count, self.NUM_RECORDS)
def animate(self): if self.animating: if self.nextStep(): QTimer.singleShot(500, self.animate) else: self.buttonPlay.setChecked(False) self.animating = False
def keyReleaseEvent(self, event): if event.key() in [ Qt.Key_Up, Qt.Key_Down, Qt.Key_Right, Qt.Key_Left, Qt.Key_PageUp, Qt.Key_PageDown ]: QTimer.singleShot(10, self.render_widget.parent_view.canvas_changed)
def show_console(): """ called from QGIS to open the console """ global _console if _console is None: parent = iface.mainWindow() if iface else None _console = PythonConsole(parent) _console.show() # force show even if it was restored as hidden # set focus to the console so the user can start typing # defer the set focus event so it works also whether the console not visible yet QTimer.singleShot(0, _console.activate) else: _console.setVisible(not _console.isVisible()) # set focus to the console so the user can start typing if _console.isVisible(): _console.activate() # Shows help on first launch of the console settings = QgsSettings() if settings.value('pythonConsole/contextHelpOnFirstLaunch', True, type=bool): QgsHelp.openHelp( "../pyqgis_developer_cookbook/intro.html#python-console") settings.setValue('pythonConsole/contextHelpOnFirstLaunch', False) return _console
def project_saved(self): if PlanetClient.getInstance().has_api_key(): def resave(): path = QgsProject.instance().absoluteFilePath() if path.lower().endswith(".qgs"): with open(path) as f: s = f.read() with open(path, "w") as f: f.write(s.replace(PlanetClient.getInstance().api_key(), "")) else: tmpfilename = path + ".temp" qgsfilename = os.path.splitext(os.path.basename(path))[0] + ".qgs" with zipfile.ZipFile(path, 'r') as zin: with zipfile.ZipFile(tmpfilename, 'w') as zout: zout.comment = zin.comment for item in zin.infolist(): if not item.filename.lower().endswith(".qgs"): zout.writestr(item, zin.read(item.filename)) else: s = zin.read(item.filename).decode("utf-8") s = s.replace(PlanetClient.getInstance().api_key(), "") qgsfilename = item.filename os.remove(path) os.rename(tmpfilename, path) with zipfile.ZipFile(path, mode='a', compression=zipfile.ZIP_DEFLATED) as zf: zf.writestr(qgsfilename, s) QTimer.singleShot(100, resave)
def testStoreMissingAuth(self): """ Test file storing with missing authentication """ f = self.getNewFile(b"New content") storedContent = self.storage.store(f.name, self.url + "/" + os.path.basename(f.name)) self.assertTrue(storedContent) self.assertEqual(storedContent.status(), Qgis.ContentStatus.NotStarted) spyStored = QSignalSpy(storedContent.stored) spyCanceled = QSignalSpy(storedContent.canceled) loop = QEventLoop() storedContent.errorOccurred.connect(loop.quit) QTimer.singleShot(1, lambda: storedContent.store()) loop.exec() self.assertEqual(storedContent.status(), Qgis.ContentStatus.Failed) self.assertTrue(storedContent.errorString()) self.assertFalse(storedContent.url()) QCoreApplication.processEvents() self.assertEqual(len(spyStored), 0) self.assertEqual(len(spyCanceled), 0)
def checkTask(self): if isProgressCanceled(): self.ok = True self.canceled = True closeProgressBar() self.taskIsFinished.emit() return self.response = self.connector.getHttp("tasks/{}".format( str(self.taskId))) if self.response["status"] in ["COMPLETE"]: self.ok = True closeProgressBar() self.taskIsFinished.emit() elif self.response["status"] in ["FAILED", "ABORTED"]: self.ok = False closeProgressBar() self.taskIsFinished.emit() else: try: progressAmount = str(self.response["progress"]["progress"]) if self.maxvalue: try: setProgressValue(float(progressAmount)) except: text = "%s [%s]" % (self.text, progressAmount) setProgressText(text) else: text = "%s [%s]" % (self.text, progressAmount) setProgressText(text) except KeyError: pass QTimer.singleShot(500, self.checkTask)
def editing_toggled(self, enabled: bool): """ Called when editing mode is toggled """ QTimer.singleShot( 0, partial(self.enable_actions_for_layer, self.iface.activeLayer(), enabled))
def canvasPressEvent(self, event): self.update_pixel_value_to_widget(event) # restart point tool self.clean() self.render_widget.canvas.unsetMapTool(self) # delay some ms before restore maptool QTimer.singleShot( 180, lambda: self.render_widget.canvas.setMapTool( self.render_widget.pan_zoom_tool))
def showEvent(self, event): """ Notifies if there are not entity configuration objects defined. :param event: Window event :type event: QShowEvent """ QTimer.singleShot(500, self.check_entity_config) return QDialog.showEvent(self, event)
def dispatch_parallel(self, delay=0.1, delay_offset=0.001, n_parallel=1): for i in range(n_parallel): if not self.count_active() < self.n_parallel: return n_active = self._reserve() print_qgis("dispatch con", n_active) if n_active == 1: print_qgis("dispatch con emit") self._emit_progress_start() d = delay * i + delay_offset QTimer.singleShot(d, self._dispatch)
def test_full_failure(self): """Test failing request""" # need to import here so that there's already an initialized QGIS app from quick_api.gui.quick_api_dialog import QuickApiDialog from quick_api.core.maptool import PointTool # first set up a project CRS = QgsCoordinateReferenceSystem.fromEpsgId(3857) project = QgsProject.instance() project.setCrs(CRS) CANVAS.setExtent(QgsRectangle(258889, 7430342, 509995, 7661955)) CANVAS.setDestinationCrs(CRS) # Create and open the dialog dlg = QuickApiDialog(IFACE) dlg.open() self.assertTrue(dlg.isVisible()) # Click the map button which should hide the dialog map_button: QPushButton = dlg.map_button QTest.mouseClick(map_button, Qt.LeftButton) self.assertFalse(dlg.isVisible()) self.assertIsInstance(CANVAS.mapTool(), PointTool) # Click in the map canvas, which should return the clicked coord, # make the dialog visible again map_releases = QgsMapMouseEvent( CANVAS, QEvent.MouseButtonRelease, QPoint(0, 0), # Relative to the canvas' dimensions Qt.LeftButton, Qt.LeftButton, Qt.NoModifier, ) dlg.point_tool.canvasReleaseEvent(map_releases) self.assertRegex(dlg.lineedit_xy.text(), r"^(\d+\.\d+.+\d+\.\d+)$") self.assertTrue(dlg.isVisible()) # Clicking the OK button should result in a QMessageBox.critical dialog def handle_msgbox(): msgbox: QMessageBox = QApplication.activeWindow() self.assertIsInstance(msgbox, QMessageBox) self.assertIn("Unable to geocode", msgbox.text()) QTest.mouseClick(msgbox.button(QMessageBox.Ok), Qt.LeftButton) # Time the MsgBox test to 7000 ms after clicking # the OK button (Nominatim rate limiting for ~6 secs..) QTimer.singleShot(7000, handle_msgbox) QTest.mouseClick(dlg.button_box.button(QDialogButtonBox.Ok), Qt.LeftButton) # No layers produced layers = project.mapLayers(validOnly=True) self.assertEqual(len(layers), 0)
def showEvent(self, event): """ (Re)load map layers in the viewer and main canvas. :param event: Window event :type event: QShowEvent """ self.setEnabled(True) if QTimer is not None: QTimer.singleShot(200, self.init_mirror_map) return QMainWindow.showEvent(self, event)
def checkTask(self): r = requests.get(self.url, stream=True) r.raise_for_status() self.response = r.json() if self.response["task"]["status"] == "FINISHED": self.ok = True self.taskIsFinished.emit() elif self.response["task"]["status"] == "FAILED": self.ok = False self.taskIsFinished.emit() else: QTimer.singleShot(500, self.checkTask)
def connectDevice(self): result = False if self.host is None: result = self.iodevice.bind(self.port) else: ha = QHostAddress(self.host) result = self.iodevice.bind(ha, self.port) if result is False: if self.reconnect > 0: QTimer.singleShot(self.reconnect, self.onReconnectTimer) else: self.deviceConnected.emit(True)
def on_log_in(self): """Handle logging-in.""" log_in_dialog = LogInDialog(self) log_in_dialog.show() QTimer.singleShot(10, log_in_dialog.log_in_threedi) log_in_dialog.exec_() if log_in_dialog.LOGGED_IN: self.threedi_api = log_in_dialog.threedi_api self.current_user = log_in_dialog.user self.current_user_full_name = log_in_dialog.user_full_name self.organisations = log_in_dialog.organisations self.initialize_authorized_view()
def testStoreWithoutFileName(self): """ Test file storing and fetching """ f = self.getNewFile(b"New content") # store storedContent = self.storage.store(f.name, self.url + "/", self.auth_config.id()) self.assertTrue(storedContent) self.assertEqual(storedContent.status(), Qgis.ContentStatus.NotStarted) spyErrorOccurred = QSignalSpy(storedContent.errorOccurred) spyProgressChanged = QSignalSpy(storedContent.progressChanged) loop = QEventLoop() storedContent.stored.connect(loop.quit) storedContent.errorOccurred.connect(loop.quit) QTimer.singleShot(1, lambda: storedContent.store()) loop.exec() self.assertEqual(len(spyErrorOccurred), 0) self.assertFalse(storedContent.errorString()) self.assertEqual(storedContent.url(), self.url + "/" + os.path.basename(f.name)) self.assertEqual(storedContent.status(), Qgis.ContentStatus.Finished) self.assertTrue(len(spyProgressChanged) > 0) self.assertEqual(spyProgressChanged[-1][0], 100) # fetch fetchedContent = self.storage.fetch( self.url + "/" + os.path.basename(f.name), self.auth_config.id()) self.assertTrue(fetchedContent) self.assertEqual(fetchedContent.status(), Qgis.ContentStatus.NotStarted) spyErrorOccurred = QSignalSpy(fetchedContent.errorOccurred) loop = QEventLoop() fetchedContent.fetched.connect(loop.quit) fetchedContent.errorOccurred.connect(loop.quit) QTimer.singleShot(1, lambda: fetchedContent.fetch()) loop.exec() self.assertEqual(len(spyErrorOccurred), 0) self.assertEqual(fetchedContent.status(), Qgis.ContentStatus.Finished) self.assertFalse(fetchedContent.errorString()) self.assertTrue(fetchedContent.filePath()) self.checkContent(fetchedContent.filePath(), b"New content") self.assertEqual( os.path.splitext(fetchedContent.filePath())[1], '.txt')
def freeze_set(self, val, from_resize=False, delay=False): """Zarządza blokadą odświeżania dockwidget'u.""" if val and self.freeze: # Blokada jest już włączona return if not val and not self.freeze: # Blokada jest już wyłączona return if val and not self.freeze: # Zablokowanie odświeżania dockwidget'u: if from_resize and not self.resizing: # Wejście w tryb zmiany rozmiaru dockwidget'u: self.resizing = True if not from_resize and not self.changing: # Wejście w tryb zmiany zawartości paneli: self.changing = True # Włączenie blokady: self.freeze = True if delay: QTimer.singleShot(300, self.freeze_start) else: self.freeze_start() elif not val and self.changing and self.freeze: QTimer.singleShot(300, self.changing_stop) elif not val and not self.changing and not self.resizing: if delay: QTimer.singleShot(300, self.freeze_end) else: QTimer.singleShot(300, self.freeze_end)
def set_user_input_widget(self, widget): """ Sets the user input widget """ # because of a qgis bug, we need to delay this call until the previous widget has been completely deleted # see fix in https://github.com/qgis/QGIS/pull/39658 def _deferred_set_user_input_widget(_widget): self.iface.addUserInputWidget(_widget) _widget.setFocus(Qt.TabFocusReason) # add the user input widget only after the end of the current event loop QTimer.singleShot(1, partial(_deferred_set_user_input_widget, widget))
def focus(self): """Adjust to the tile extent in all view widgets in main dialog""" # focus to extent with a bit of buffer from ThRasE.gui.main_dialog import ThRasEDialog buffer = (self.ymax - self.ymin) * 0.01 extent_with_buffer = QgsRectangle(self.xmin-buffer, self.ymin-buffer, self.xmax+buffer, self.ymax+buffer) [view_widget.render_widget.update_canvas_to(extent_with_buffer) for view_widget in ThRasEDialog.view_widgets if view_widget.is_active] self.show() from ThRasE.thrase import ThRasE if not ThRasE.dialog.currentTileKeepVisible.isChecked(): QTimer.singleShot(1200, self.hide)
def draw_point(point, rubber_band=None, color=QColor(255, 0, 0, 100), width=3, duration_time=None, is_new=False): """ :param duration_time: integer milliseconds ex: 3000 for 3 seconds """ rubber_band.reset(0) rubber_band.setIconSize(10) rubber_band.setColor(color) rubber_band.setWidth(width) rubber_band.addPoint(point) # wait to simulate a flashing effect if duration_time is not None: QTimer.singleShot(duration_time, rubber_band.reset)
def connectDevice(self): if not self.serialPort: return self.iodevice.setPortName(self.serialPort) self.iodevice.setBaudRate(self.baudrate) self.iodevice.setDataBits(self.databits) self.iodevice.setParity(self.parity) self.iodevice.setStopBits(self.stopbits) self.iodevice.setFlowControl(self.flowControl) if not self.iodevice.open(QIODevice.ReadOnly): if self.reconnect > 0: QTimer.singleShot(self.reconnect, self.onReconnectTimer) else: self.deviceConnected.emit(True)
def draw_polyline(points, rubber_band, color=QColor(255, 0, 0, 100), width=5, duration_time=None): """ Draw 'line' over canvas following list of points :param duration_time: integer milliseconds ex: 3000 for 3 seconds """ rubber_band.setIconSize(20) polyline = QgsGeometry.fromPolylineXY(points) rubber_band.setToGeometry(polyline, None) rubber_band.setColor(color) rubber_band.setWidth(width) rubber_band.show() # wait to simulate a flashing effect if duration_time is not None: QTimer.singleShot(duration_time, rubber_band.reset)
def restoreGui(self): """Reset the GUI to its initial state.""" QTimer.singleShot(1000, lambda: self.dlg.pageBar.setValue(0)) # QTimer.singleShot(1000, lambda: self.dlg.updateBar.setValue(0)) self.dlg.printinglabel.setText('') # Reset standardbuttons and their functions and labels self.dlg.buttonBox.rejected.disconnect(self.stopProcessing) self.dlg.buttonBox.rejected.connect(self.dlg.reject) self.dlg.btnCancel.hide() self.dlg.btnClose.show() QApplication.restoreOverrideCursor() self.dlg.exportButton.setEnabled(True) self.arret = False
def restoreGui(self): """Reset the GUI to its initial state.""" QTimer.singleShot(1000, lambda: self.dlg.pageBar.setValue(0)) self.dlg.printinglabel.setText('') self.dlg.printinglabel.hide() # Reset standardbuttons and their functions and labels self.dlg.buttonBox.rejected.disconnect(self.stopProcessing) self.dlg.buttonBox.rejected.connect(self.dlg.reject) self.dlg.btnCancel.hide() self.dlg.btnClose.show() QApplication.restoreOverrideCursor() self.dlg.exportButton.setEnabled(True) self.arret = False
def project_saved(self): if PlanetClient.getInstance().has_api_key(): def resave(): try: path = QgsProject.instance().absoluteFilePath() if path.lower().endswith(".qgs"): with open(path, encoding='utf-8') as f: s = f.read() with open(path, "w", encoding='utf-8') as f: f.write( s.replace(PlanetClient.getInstance().api_key(), "")) else: tmpfilename = path + ".temp" qgsfilename = os.path.splitext( os.path.basename(path))[0] + ".qgs" with zipfile.ZipFile(path, 'r') as zin: with zipfile.ZipFile(tmpfilename, 'w') as zout: zout.comment = zin.comment for item in zin.infolist(): if not item.filename.lower().endswith( ".qgs"): zout.writestr(item, zin.read(item.filename)) else: s = zin.read( item.filename).decode("utf-8") s = s.replace( PlanetClient.getInstance().api_key( ), "") qgsfilename = item.filename os.remove(path) os.rename(tmpfilename, path) with zipfile.ZipFile( path, mode='a', compression=zipfile.ZIP_DEFLATED) as zf: zf.writestr(qgsfilename, s) except Exception: QMessageBox.warning( self.iface.mainWindow( "Error saving project", "There was an error while removing API keys from QGIS project file.\n" "The project that you have just saved might contain Planet API keys in plain text." )) QTimer.singleShot(100, resave)
def show_console(): """ called from QGIS to open the console """ global _console if _console is None: parent = iface.mainWindow() if iface else None _console = PythonConsole(parent) _console.show() # force show even if it was restored as hidden # set focus to the console so the user can start typing # defer the set focus event so it works also whether the console not visible yet QTimer.singleShot(0, _console.activate) else: _console.setVisible(not _console.isVisible()) # set focus to the console so the user can start typing if _console.isVisible(): _console.activate() return _console
def highlight(self, point): currExt = self.canvas.extent() leftPt = QgsPoint(currExt.xMinimum(), point.y()) rightPt = QgsPoint(currExt.xMaximum(), point.y()) topPt = QgsPoint(point.x(), currExt.yMaximum()) bottomPt = QgsPoint(point.x(), currExt.yMinimum()) horizLine = QgsGeometry.fromPolyline( [ leftPt , rightPt ] ) vertLine = QgsGeometry.fromPolyline( [ topPt , bottomPt ] ) self.crossRb.reset(QgsWkbTypes.LineGeometry) self.crossRb.addGeometry(horizLine, None) self.crossRb.addGeometry(vertLine, None) QTimer.singleShot(700, self.resetRubberbands)
def loadPreview(self, item): if item == self.item and not self.dirty: return if item is None: return self._clear() if isinstance(item, Table) and item.type in [Table.VectorType, Table.RasterType]: # update the preview, but first let the manager chance to show the canvas def runPrev(): return self._loadTablePreview(item) QTimer.singleShot(50, runPrev) else: return self.item = item self.item.aboutToChange.connect(self.setDirty)
def show_console(): """ called from QGIS to open the console """ global _console if _console is None: parent = iface.mainWindow() if iface else None _console = PythonConsole(parent) _console.show() # force show even if it was restored as hidden # set focus to the console so the user can start typing # defer the set focus event so it works also whether the console not visible yet QTimer.singleShot(0, _console.activate) else: _console.setVisible(not _console.isVisible()) # set focus to the console so the user can start typing if _console.isVisible(): _console.activate() ## Shows help on first launch of the console settings = QSettings() if settings.value('pythonConsole/contextHelpOnFirstLaunch', True, type=bool): QgsContextHelp.run("PythonConsole") settings.setValue('pythonConsole/contextHelpOnFirstLaunch', False) return _console
def _dropEvent(event): def alg_dropped(algorithm_id, pos): alg = QgsApplication.processingRegistry().createAlgorithmById(algorithm_id) if alg is not None: self._addAlgorithm(alg, pos) else: assert False, algorithm_id def input_dropped(id, pos): if id in [param.id() for param in QgsApplication.instance().processingRegistry().parameterTypes()]: self.addInputOfType(itemId, pos) if event.mimeData().hasFormat('application/x-vnd.qgis.qgis.algorithmid'): data = event.mimeData().data('application/x-vnd.qgis.qgis.algorithmid') stream = QDataStream(data, QIODevice.ReadOnly) algorithm_id = stream.readQString() QTimer.singleShot(0, lambda id=algorithm_id, pos=self.view.mapToScene(event.pos()): alg_dropped(id, pos)) event.accept() elif event.mimeData().hasText(): itemId = event.mimeData().text() QTimer.singleShot(0, lambda id=itemId, pos=self.view.mapToScene(event.pos()): input_dropped(id, pos)) event.accept() else: event.ignore()
def waitAfterRenderComplete(self, painter=None): """When the map canvas signals renderComplete, wait defined millisec until next animation step""" if self.saveAnimation: # make animation/export run as fast as possible self.playAnimation(painter) else: QTimer.singleShot(self.animationFrameLength, self.playAnimation)