class SaveQueryDialog(QDialog, Ui_ui_save_query): # Signal new query signal_new_query_successful = pyqtSignal( name='signal_new_query_successful') def __init__( self, parent=None, query=None, white_list_values=None, output_geometry_types=None): """ SaveQueryDialog constructor @param query:query to save @type query: str @param white_list_values: doc of layers with columns @type white_list_values: dic @param output_geometry_types: list of layers @type output_geometry_types: list """ super(SaveQueryDialog, self).__init__(parent) QDialog.__init__(self) self.setupUi(self) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().addWidget(self.bar) self.whiteListValues = white_list_values self.outputGeomTypes = output_geometry_types self.query = query def accept(self): """ On accept, we call the FileQueryWriter """ category = self.lineEdit_category.text() name = self.lineEdit_name.text() # Get folder .qgis2/QuickOSM/queries on linux for instance folder = get_user_query_folder() ini_file = FileQueryWriter( path=folder, name=name, category=category, query=self.query, whiteListValues=self.whiteListValues, outputGeomTypes=self.outputGeomTypes) try: ini_file.save() self.signal_new_query_successful.emit() self.hide() except QuickOsmException, e: self.bar.pushMessage(e.msg, level=e.level, duration=e.duration) except Exception, e: self.display_exception(e)
class MyDialog(QDialog): def __init__(self): QDialog.__init__(self) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.setLayout(QGridLayout()) self.layout().setContentsMargins(0, 0, 0, 0) self.buttonbox = QDialogButtonBox(QDialogButtonBox.Ok) self.buttonbox.accepted.connect(self.run) self.layout().addWidget(self.buttonbox, 0, 0, 2, 1) self.layout().addWidget(self.bar, 0, 0, 1, 1) def run(self): self.bar.pushMessage("Hello", "World", level=QgsMessageBar.INFO)
class EditorTab(QWidget): def __init__(self, parent, parentConsole, filename, *args): QWidget.__init__(self, parent=None, *args) self.tw = parent self.pc = parentConsole self.path = None self.fileExcuteList = {} self.fileExcuteList = dict() self.newEditor = Editor(self) if filename: self.path = filename if os.path.exists(filename): self.loadFile(filename, False) # Creates layout for message bar self.layout = QGridLayout(self.newEditor) self.layout.setContentsMargins(0, 0, 0, 0) spacerItem = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) self.layout.addItem(spacerItem, 1, 0, 1, 1) # messageBar instance self.infoBar = QgsMessageBar() sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.infoBar.setSizePolicy(sizePolicy) self.layout.addWidget(self.infoBar, 0, 0, 1, 1) self.tabLayout = QGridLayout(self) self.tabLayout.setContentsMargins(0, 0, 0, 0) self.tabLayout.addWidget(self.newEditor) self.keyFilter = KeyFilter(parent, self) self.setEventFilter(self.keyFilter) def loadFile(self, filename, modified): try: fn = open(unicode(filename), "rb") except IOError, error: IOErrorTr = QCoreApplication.translate('PythonConsole', 'The file <b>%1</b> could not be opened. Error: %2') \ .arg(filename).arg(error.strerror) print IOErrorTr QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) txt = fn.read() fn.close() self.newEditor.setText(txt) QApplication.restoreOverrideCursor() self.newEditor.setModified(modified) self.newEditor.mtime = os.stat(filename).st_mtime self.newEditor.recolor()
class QgisServerCheckerDialog(QtGui.QDialog, FORM_CLASS): def __init__(self, parent=None): """Constructor.""" super(QgisServerCheckerDialog, self).__init__(parent) # Set up the user interface from Designer. # After setupUI you can access any designer object by doing # self.<objectname>, and you can use autoconnect slots - see # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html # #widgets-and-dialogs-with-auto-connect self.setupUi(self) self.bar = QgsMessageBar() self.bar.setSizePolicy( QSizePolicy.Minimum, QSizePolicy.Fixed ) self.layout().insertWidget(0, self.bar)
def __init__(self, codeList, parent=None): """Constructor.""" super(LoadByClass, self).__init__(parent) # Set up the user interface from Designer. # After setupUI you can access any designer object by doing # self.<objectname>, and you can use autoconnect slots - see # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html # #widgets-and-dialogs-with-auto-connect self.setupUi(self) self.selectedClasses = [] self.bar = QgsMessageBar() self.setLayout(QtGui.QGridLayout(self)) self.layout().setContentsMargins(0,0,0,0) self.layout().setAlignment(QtCore.Qt.AlignTop) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) self.bar.setSizePolicy(sizePolicy) self.layout().addWidget(self.bar, 0,0,1,1) #Objects Connections QtCore.QObject.connect(self.widget, QtCore.SIGNAL(("connectionChanged()")), self.listClassesFromDatabase) QtCore.QObject.connect(self.widget, QtCore.SIGNAL(("problemOccurred()")), self.pushMessage) QtCore.QObject.connect(self.pushButtonCancel, QtCore.SIGNAL(("clicked()")), self.cancel) QtCore.QObject.connect(self.selectAllCheck, QtCore.SIGNAL(("stateChanged(int)")), self.selectAll) QtCore.QObject.connect(self.pushButtonOk, QtCore.SIGNAL(("clicked()")), self.okSelected) self.widget.tabWidget.currentChanged.connect(self.restoreInitialState) self.codeList = codeList self.layerFactory = LayerFactory()
def toggle_select_features_widget(title, text, button_text, layer, new_feature_ids, old_feature_ids): """ Create a widget for QgsMessageBar to switch between two sets. :param title: The title :type title: str :param text: The text message :type text: str :param button_text: The text on the toggle button :type button_text: str :param layer: The QgsVectorLayer where the selection is applied :type layer: QgsVectorLayer :param new_feature_ids: The list to select if use_new is true :type new_feature_ids: QgsFeatureIds :param old_feature_ids: The list to select if use_new is false :type old_feature_ids: QgsFeatureIds """ widget = QgsMessageBar.createMessage(title, text) button = QToolButton(widget) button.setCheckable(True) button.setText(button_text) button.toggled.connect( lambda on, layer=layer, new_feature_ids=new_feature_ids, old_feature_ids=old_feature_ids: toggle_select_features(layer, on, new_feature_ids, old_feature_ids)) widget.layout().addWidget(button) return widget
def __init__(self): QDialog.__init__(self) self.setupUi(self) self.settings = MySettings() SettingDialog.__init__(self, self.settings) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().addWidget(self.bar, 0, 0, 1, 2) self.proj = QgsProject.instance() allowedClasses, hasAllowedClasses = self.proj.readListEntry("teamqgis", "allowedClasses") if hasAllowedClasses: self.addEditableItems(allowedClasses) self.addClassLineEdit.textEdited.connect(self.addClassLineEdit_textEdited) self.addClassLineEdit.textChanged.connect(self.addClassLineEdit_textChanged) self.classesListWidget.itemSelectionChanged.connect(self.classesListWidget_selectionChanged) classesListWidgetModel = self.classesListWidget.model() classesListWidgetModel.rowsRemoved.connect(self.classesListWidgetModel_dataChanged) classesListWidgetModel.rowsInserted.connect(self.classesListWidgetModel_dataChanged) classesListWidgetModel.dataChanged.connect(self.classesListWidgetModel_dataChanged) classesListWidgetModel.layoutChanged.connect(self.classesListWidgetModel_dataChanged)
def setupUi(self): self.setMinimumWidth(500) self.setMinimumHeight(400) self.resize(640, 450) self.verticalLayout = QVBoxLayout(self) self.verticalLayout.setSpacing(2) self.verticalLayout.setMargin(0) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.verticalLayout.addWidget(self.bar) self.tree = QTreeWidget(self) self.tree.setAlternatingRowColors(True) self.verticalLayout.addWidget(self.tree) self.horizontalLayout = QHBoxLayout(self) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Ok) self.horizontalLayout.addWidget(self.buttonBox) self.verticalLayout.addLayout(self.horizontalLayout) self.setWindowTitle("Configuration options") self.tree.headerItem().setText(0, "Setting") self.tree.headerItem().setText(1, "Value") self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject)
def __init__( self, parent=None, query=None, white_list_values=None, output_geometry_types=None): """ SaveQueryDialog constructor @param query:query to save @type query: str @param white_list_values: doc of layers with columns @type white_list_values: dic @param output_geometry_types: list of layers @type output_geometry_types: list """ super(SaveQueryDialog, self).__init__(parent) QDialog.__init__(self) self.setupUi(self) self.message_bar = QgsMessageBar() self.message_bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().addWidget(self.message_bar) self.white_list_values = white_list_values self.output_geometry_types = output_geometry_types self.query = query
def __init__(self, parent=None): """Constructor.""" super(CriaSpatialiteDialog, self).__init__(parent) # Set up the user interface from Designer. # After setupUI you can access any designer object by doing # self.<objectname>, and you can use autoconnect slots - see # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html # #widgets-and-dialogs-with-auto-connect self.setupUi(self) self.filepath = "" self.carregado = False self.coordSysDefinido = False self.epsgCriaSpatialite = 0 self.srsCriaSpatialite = '' self.sqliteFileName = '' self.bar = QgsMessageBar() self.setLayout(QtGui.QGridLayout(self)) self.layout().setContentsMargins(0,0,0,0) self.layout().setAlignment(QtCore.Qt.AlignTop) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) self.bar.setSizePolicy(sizePolicy) self.layout().addWidget(self.bar, 0,0,1,1) QtCore.QObject.connect(self.pushButtonBuscarPastaDestinoCriaSpatialite, QtCore.SIGNAL(("clicked()")), self.definePastaDestino) QtCore.QObject.connect(self.pushButtonBuscarSistCoordCriaSpatialite, QtCore.SIGNAL(("clicked()")), self.setaSistCoordCriaSpatialite) QtCore.QObject.connect(self.pushButtonOkCriaSpatialite, QtCore.SIGNAL(("clicked()")), self.okselecionadoCriaSpatialite)
def __init__(self, parent, parentConsole, filename, *args): QWidget.__init__(self, parent=None, *args) self.tw = parent self.pc = parentConsole self.path = None self.fileExcuteList = {} self.fileExcuteList = dict() self.newEditor = Editor(self) if filename: self.path = filename if os.path.exists(filename): self.loadFile(filename, False) # Creates layout for message bar self.layout = QGridLayout(self.newEditor) self.layout.setContentsMargins(0, 0, 0, 0) spacerItem = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) self.layout.addItem(spacerItem, 1, 0, 1, 1) # messageBar instance self.infoBar = QgsMessageBar() sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.infoBar.setSizePolicy(sizePolicy) self.layout.addWidget(self.infoBar, 0, 0, 1, 1) self.tabLayout = QGridLayout(self) self.tabLayout.setContentsMargins(0, 0, 0, 0) self.tabLayout.addWidget(self.newEditor) self.keyFilter = KeyFilter(parent, self) self.setEventFilter(self.keyFilter)
def __init__(self, parent, parentConsole, filename, *args): QWidget.__init__(self, parent=None, *args) self.mw = parent self.pc = parentConsole self.path = None self.fileExcuteList = {} self.fileExcuteList = dict() self.newEditor = Editor(self) self.newEditor.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.newEditor.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.newEditor.modificationChanged.connect(self.modified) if filename: self.newEditor.setText(open(unicode(filename), "r").read()) self.newEditor.setModified(False) self.path = filename # Creates layout for message bar self.layout = QGridLayout(self.newEditor) self.layout.setContentsMargins(0, 0, 0, 0) spacerItem = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) self.layout.addItem(spacerItem, 1, 0, 1, 1) # messageBar instance self.infoBar = QgsMessageBar() sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.infoBar.setSizePolicy(sizePolicy) self.layout.addWidget(self.infoBar, 0, 0, 1, 1) self.tabLayout = QGridLayout(self) self.tabLayout.setContentsMargins(0, 0, 0, 0) self.tabLayout.addWidget(self.newEditor) self.keyFilter = KeyFilter(parent, self) self.setEventFilter(self.keyFilter)
def __init__(self, parent=None): super(ShellOutputScintilla, self).__init__(parent) self.parent = parent self.shell = self.parent.shell self.settings = QgsSettings() # Creates layout for message bar self.layout = QGridLayout(self) self.layout.setContentsMargins(0, 0, 0, 0) spacerItem = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) self.layout.addItem(spacerItem, 1, 0, 1, 1) # messageBar instance self.infoBar = QgsMessageBar() sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.infoBar.setSizePolicy(sizePolicy) self.layout.addWidget(self.infoBar, 0, 0, 1, 1) # Enable non-ascii chars for editor self.setUtf8(True) sys.stdout = writeOut(self, sys.stdout) sys.stderr = writeOut(self, sys.stderr, "_traceback") self.insertInitText() self.refreshSettingsOutput() self.setReadOnly(True) # Set the default font font = QFontDatabase.systemFont(QFontDatabase.FixedFont) self.setFont(font) self.setMarginsFont(font) # Margin 0 is used for line numbers self.setMarginWidth(0, 0) self.setMarginWidth(1, 0) self.setMarginWidth(2, 0) #fm = QFontMetrics(font) self.setMarginsFont(font) self.setMarginWidth(1, "00000") self.setMarginLineNumbers(1, True) self.setMarginsForegroundColor(QColor("#3E3EE3")) self.setMarginsBackgroundColor(QColor("#f9f9f9")) self.setCaretLineVisible(True) self.setCaretWidth(0) self.setMinimumHeight(120) self.setWrapMode(QsciScintilla.WrapCharacter) self.SendScintilla(QsciScintilla.SCI_SETHSCROLLBAR, 0) self.runScut = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_E), self) self.runScut.setContext(Qt.WidgetShortcut) self.runScut.activated.connect(self.enteredSelected) # Reimplemented copy action to prevent paste prompt (>>>,...) in command view self.copyShortcut = QShortcut(QKeySequence.Copy, self) self.copyShortcut.activated.connect(self.copy) self.selectAllShortcut = QShortcut(QKeySequence.SelectAll, self) self.selectAllShortcut.activated.connect(self.selectAll)
class GdalAlgorithmDialog(AlgorithmDialog): def __init__(self, alg): AlgorithmDialogBase.__init__(self, alg) self.alg = alg self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().insertWidget(0, self.bar) self.setMainWidget(GdalParametersPanel(self, alg)) self.runAsBatchButton = QPushButton(QCoreApplication.translate("AlgorithmDialog", "Run as Batch Process…")) self.runAsBatchButton.clicked.connect(self.runAsBatch) self.buttonBox.addButton(self.runAsBatchButton, QDialogButtonBox.ResetRole) # reset role to ensure left alignment self.mainWidget.parametersHaveChanged()
def __init__(self): QDialog.__init__(self) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.setLayout(QGridLayout()) self.layout().setContentsMargins(0, 0, 0, 0) self.buttonbox = QDialogButtonBox(QDialogButtonBox.Ok) self.buttonbox.accepted.connect(self.run) self.layout().addWidget(self.buttonbox, 0, 0, 2, 1) self.layout().addWidget(self.bar, 0, 0, 1, 1)
def activate(self): """ Map tool is activated """ QgsMapTool.activate(self) self.canvas.setCursor(QCursor(Qt.CrossCursor)) msgtitle = self.tr('Digitizing Drainage Channel') msg = self.tr('Digitize start and end point. Rightclick to abort.') self.messageBarItem = QgsMessageBar.createMessage(msgtitle, msg) self.iface.messageBar().pushItem(self.messageBarItem)
def accept(self): self.tblStatistics.setRowCount(0) layer = self.cmbLayer.currentLayer() if self.chkSelectedOnly.isChecked() and layer.selectedFeatureCount() == 0: QgsMessageBar.pushWarning(self.tr("No selection"), self.tr("There is no selection in the input layer. Uncheck " "corresponding option or select some features before " "running analysis")) return self.calculator.setLayer(layer) self.calculator.setField(self.cmbField.currentField()) self.calculator.setSelectedOnly(self.chkSelectedOnly.isChecked()) self.btnOk.setEnabled(False) self.btnClose.setEnabled(False) self.thread.start()
def _initGui(self): """setup the user interface""" self.ui = Ui_geopunt4Qgis() self.ui.setupUi(self) #get settings self.s = QtCore.QSettings() self.loadSettings() #setup geometryHelper object self.gh = gh.geometryHelper(self.iface) #create graphicsLayer self.graphicsLayer = [] #populate gemeenteBox gemeentes = json.load( open(os.path.join(os.path.dirname(__file__), "data/gemeentenVL.json")) ) gemeenteNamen = [str( n["Naam"]) for n in gemeentes] self.ui.gemeenteBox.addItems( gemeenteNamen ) self.ui.gemeenteBox.setEditText(QtCore.QCoreApplication.translate( "geopunt4QgisAdresDialog", "gemeente")) self.ui.gemeenteBox.setStyleSheet('QComboBox {color: #808080}') self.ui.gemeenteBox.setFocus() self.completer = QtGui.QCompleter( self ) self.completerModel = QtGui.QStringListModel( self ) self.ui.gemeenteBox.setCompleter( self.completer ) self.completer.setModel( self.completerModel ) self.completer.setCaseSensitivity(False) self.completerModel.setStringList( gemeenteNamen ) #setup a message bar self.bar = QgsMessageBar() self.bar.setSizePolicy( QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed ) self.ui.verticalLayout.addWidget(self.bar) self.ui.buttonBox.addButton( QtGui.QPushButton("Sluiten"), QtGui.QDialogButtonBox.RejectRole ) for btn in self.ui.buttonBox.buttons(): btn.setAutoDefault(0) #event handlers if self.adresSearchOnEnter: self.ui.zoekText.returnPressed.connect(self.onZoekActivated) else: self.ui.zoekText.textEdited.connect(self.onZoekActivated) self.ui.gemeenteBox.currentIndexChanged.connect(self.onZoekActivated) self.ui.resultLijst.itemDoubleClicked.connect(self.onItemActivated) self.ui.resultLijst.itemClicked.connect(self.onItemClick) self.ui.ZoomKnop.clicked.connect(self.onZoomKnopClick) self.ui.Add2mapKnop.clicked.connect(self.onAdd2mapKnopClick) self.ui.buttonBox.helpRequested.connect(self.openHelp) self.finished.connect(self.clean )
def _initGui(self): """setup the user interface""" self.ui = Ui_elevationDlg() self.ui.setupUi(self) #get settings self.s = QSettings() self.loadSettings() self.gh = geometryHelper( self.iface ) self.eh = elevationHelper( self.iface, self.startDir) #setup a message bar self.bar = QgsMessageBar() self.bar.setSizePolicy( QSizePolicy.Minimum, QSizePolicy.Fixed ) self.ui.verticalLayout.addWidget(self.bar) self.ui.buttonBox.addButton(QPushButton("Sluiten"), QDialogButtonBox.RejectRole ) for btn in self.ui.buttonBox.buttons(): btn.setAutoDefault(0) ##graph global vars self.Rubberline = None self.profile = None self.pt = None self.ax = None self.ano = None self.anoLbl = None self.counter = 0 self.xscaleUnit = (1, "m") # a figure instance to plot on self.figure = Figure() #create the Canvas widget and toolbar and set graphWgt as parent self.canvas = FigureCanvas(self.figure) self.toolbar = NavigationToolbar(self.canvas, self) ### #self.ui.toolbar.layout().insertWidget(0, self.toolbar) self.ui.graphWgt.layout().addWidget(self.canvas) self.createCanvasToolbar() #events self.ui.drawBtn.clicked.connect(self.drawBtnClicked) self.figure.canvas.mpl_connect('motion_notify_event', self.showGraphMotion) self.ui.saveLineBtn.clicked.connect(self.saveLineClicked) self.ui.savePntBtn.clicked.connect(self.savePntClicked) self.ui.addDHMbtn.clicked.connect(self.addDHMasWMS) self.ui.refreshBtn.clicked.connect( self.onRefresh ) self.ui.buttonBox.helpRequested.connect(self.openHelp) self.rejected.connect(self.clean )
def showMessageBar(self, title, text, level=QgsMessageBar.INFO): if self.bar is None: self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) ui = self.ui margins = ui.gridLayout.getContentsMargins() vl = ui.gridLayout.takeAt(0) ui.gridLayout.setContentsMargins(0,0,0,0) ui.gridLayout.addWidget(self.bar, 0, 0) ui.gridLayout.addItem(vl, 1, 0) ui.verticalLayout.setContentsMargins(margins[0], margins[1] / 2, margins[2], margins[3]) self.bar.pushMessage(title, text, level=level)
def _initGui(self): 'Set up the user interface from Designer.' self.ui = Ui_geopunt4QgisPoiDlg() self.ui.setupUi(self) #get settings self.s = QSettings() self.loadSettings() #setup geopunt and geometryHelper objects self.gh = geometryHelper(self.iface) self.ph = poiHelper( self.iface) #create the graphicsLayer self.graphicsLayer = [] #setup a message bar self.bar = QgsMessageBar() self.bar.setSizePolicy( QSizePolicy.Minimum, QSizePolicy.Fixed ) self.ui.verticalLayout.addWidget(self.bar) self.ui.buttonBox.addButton( QPushButton("Sluiten"), QDialogButtonBox.RejectRole ) for btn in self.ui.buttonBox.buttons(): btn.setAutoDefault(0) #table ui self.ui.resultLijst.hideColumn(0) # filters self.firstShow = True self.poiTypes = {} self.poiCategories = {} self.poiThemes = {} #actions self.ui.resultLijst.addAction( self.ui.actionZoomtoSelection ) self.ui.actionZoomtoSelection.triggered.connect( self.onZoomSelClicked) self.ui.resultLijst.addAction( self.ui.actionAddTSeltoMap ) self.ui.actionAddTSeltoMap.triggered.connect( self.onAddSelClicked) #event handlers self.ui.zoekKnop.clicked.connect(self.onZoekActivated) self.ui.zoomSelKnop.clicked.connect(self.onZoomSelClicked) self.ui.resultLijst.itemDoubleClicked.connect(self.onZoomSelClicked ) self.ui.resultLijst.itemSelectionChanged.connect(self.onSelectionChanged) self.ui.addToMapKnop.clicked.connect(self.onAddSelClicked) self.ui.addMinModelBtn.clicked.connect( self.addMinModel ) self.ui.poiText.textChanged.connect( self.searchTxtChanged ) self.ui.buttonBox.helpRequested.connect(self.openHelp) self.finished.connect(self.clean )
def __init__(self, codeList, parent=None): """Constructor.""" super(LoadByCategory, self).__init__(parent) # Set up the user interface from Designer. # After setupUI you can access any designer object by doing # self.<objectname>, and you can use autoconnect slots - see # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html # #widgets-and-dialogs-with-auto-connect self.setupUi(self) self.categories = [] self.selectedClasses = [] self.point = [] self.line = [] self.polygon = [] self.pointWithElement = [] self.lineWithElement = [] self.polygonWithElement = [] self.parentTreeNode = None self.checkBoxPoint.setCheckState(0) self.checkBoxLine.setCheckState(0) self.checkBoxPolygon.setCheckState(0) self.checkBoxAll.setCheckState(0) self.bar = QgsMessageBar() self.setLayout(QtGui.QGridLayout(self)) self.layout().setContentsMargins(0,0,0,0) self.layout().setAlignment(QtCore.Qt.AlignTop) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) self.bar.setSizePolicy(sizePolicy) self.layout().addWidget(self.bar, 0,0,1,1) #Objects Connections self.widget.connectionChanged.connect(self.listCategoriesFromDatabase) self.widget.problemOccurred.connect(self.pushMessage) self.pushButtonCancel.clicked.connect(self.cancel) self.pushButtonOk.clicked.connect(self.okSelected) self.pushButtonSelectAll.clicked.connect(self.selectAll) self.pushButtonDeselectAll.clicked.connect(self.deselectAll) self.pushButtonSelectOne.clicked.connect(self.selectOne) self.pushButtonDeselectOne.clicked.connect(self.deselectOne) self.checkBoxAll.stateChanged.connect(self.setAllGroup) self.widget.tabWidget.currentChanged.connect(self.restoreInitialState) self.codeList = codeList self.layerFactory = LayerFactory()
def __init__(self, alg): AlgorithmDialogBase.__init__(self, alg) self.alg = alg self.setWindowTitle(self.tr('Batch Processing - %s') % self.alg.name) self.setMainWidget(BatchPanel(self, self.alg)) self.textShortHelp.setVisible(False) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().insertWidget(0, self.bar)
def __init__(self, alg): AlgorithmDialogBase.__init__(self, alg) self.alg = alg self.setMainWidget(self.getParametersPanel(alg, self)) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().insertWidget(0, self.bar) self.runAsBatchButton = QPushButton(self.tr("Run as Batch Process…")) self.runAsBatchButton.clicked.connect(self.runAsBatch) self.buttonBox.addButton(self.runAsBatchButton, QDialogButtonBox.ResetRole) # reset role to ensure left alignment
def _initGui(self): self.ui = Ui_vmmQryDlg() self.ui.setupUi(self) self.setup() self.gh = geometryHelper(self.iface) #setup a message bar self.bar = QgsMessageBar() self.bar.setSizePolicy( QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed ) self.ui.verticalLayout.addWidget(self.bar) #events self.ui.addLayerBtn.clicked.connect(self.addLayerClick) self.ui.button_box.helpRequested.connect(self.help)
class GdalAlgorithmDialog(AlgorithmDialog): def __init__(self, alg): AlgorithmDialogBase.__init__(self, alg) self.alg = alg self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().insertWidget(0, self.bar) self.setMainWidget(GdalParametersPanel(self, alg)) cornerWidget = QWidget() layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 5) self.tabWidget.setStyleSheet("QTabBar::tab { height: 30px; }") runAsBatchButton = QPushButton(self.tr("Run as batch process...")) runAsBatchButton.clicked.connect(self.runAsBatch) layout.addWidget(runAsBatchButton) cornerWidget.setLayout(layout) self.tabWidget.setCornerWidget(cornerWidget) self.mainWidget.parametersHaveChanged()
def _initGui(self): """setup the user interface""" self.ui = Ui_geopunt4QgisDataCatalogDlg() self.ui.setupUi(self) #get settings self.s = QtCore.QSettings() self.loadSettings() self.gh = gh.geometryHelper( self.iface ) #setup a message bar self.bar = QgsMessageBar() self.bar.setSizePolicy( QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed ) self.ui.verticalLayout.addWidget(self.bar) self.ui.buttonBox.addButton( QtGui.QPushButton("Sluiten"), QtGui.QDialogButtonBox.RejectRole ) for btn in self.ui.buttonBox.buttons(): btn.setAutoDefault(0) #vars self.firstShow = True self.wms = None self.wfs = None self.dl = None self.zoek = '' self.bronnen = None self.model = QtGui.QStandardItemModel( self ) self.proxyModel = QtGui.QSortFilterProxyModel(self) self.proxyModel.setSourceModel(self.model) self.ui.resultView.setModel( self.proxyModel ) self.completer = QtGui.QCompleter( self ) self.completerModel = QtGui.QStringListModel( self) self.ui.zoekTxt.setCompleter( self.completer ) self.completer.setModel( self.completerModel ) #eventhandlers self.ui.zoekBtn.clicked.connect(self.onZoekClicked) self.ui.addWMSbtn.clicked.connect(self.addWMS) self.ui.addWFSbtn.clicked.connect(self.addWFS) self.ui.DLbtn.clicked.connect(lambda: self.openUrl(self.dl)) self.ui.resultView.clicked.connect(self.resultViewClicked) self.ui.modelFilterCbx.currentIndexChanged.connect(self.modelFilterCbxIndexChanged) self.ui.filterWgt.setHidden(1) self.ui.buttonBox.helpRequested.connect(self.openHelp) self.finished.connect(self.clean)
def _initGui(self): """setup the user interface""" self.ui = Ui_dataCatalogDlg() self.ui.setupUi(self) #get settings self.s = settings() self.gh = gh.geometryHelper( self.iface ) #setup a message bar self.bar = QgsMessageBar() self.bar.setSizePolicy( QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed ) self.ui.verticalLayout.addWidget(self.bar) #vars self.firstShow = True self.wms = None self.wfs = None self.wmts = None self.wcs = None self.dl = None self.zoek = '' #datamodel self.model = QtGui.QStandardItemModel(self) self.proxyModel = QtGui.QSortFilterProxyModel(self) self.proxyModel.setSourceModel(self.model) self.ui.resultView.setModel( self.proxyModel ) #completer self.completer = QtGui.QCompleter( self ) self.completerModel = QtGui.QStringListModel(self) self.ui.zoekTxt.setCompleter(self.completer ) self.completer.setModel(self.completerModel ) self.md = metadata.MDReader(timeout=self.s.timeout, proxyUrl=self.s.proxyUrl) #eventhandlers self.ui.zoekBtn.clicked.connect(self.onZoekClicked) self.ui.addWMSbtn.clicked.connect(self.addWMS) self.ui.addWFSbtn.clicked.connect(self.addWFS) self.ui.addWMTSbtn.clicked.connect(self.addWMTS) self.ui.addWCSbtn.clicked.connect(self.addWCS) self.ui.DLbtn.clicked.connect(lambda: self.openUrl(self.dl)) self.ui.resultView.clicked.connect(self.resultViewClicked) self.ui.modelFilterCbx.currentIndexChanged.connect(self.modelFilterCbxIndexChanged) self.finished.connect(self.clean)
def __init__(self, iface, parent=None): ''' Constructor ''' super(LayerDialog, self).__init__(parent) self.setupUi(self) self.bar = QgsMessageBar(self) self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().addWidget(self.bar) self.iface = iface settings = QSettings() settings.beginGroup('/SpatiaLite/connections') self.mDatabaseComboBox.clear() for k in settings.childGroups(): text = settings.value(k + '/sqlitepath', '###unknown###') self.mDatabaseComboBox.addItem(text) settings.endGroup() self.mOkButton = self.buttonBox.button(QDialogButtonBox.Ok)
def __init__(self, alg): AlgorithmDialogBase.__init__(self, alg) self.alg = alg self.setMainWidget(self.getParametersPanel(alg, self)) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().insertWidget(0, self.bar) self.cornerWidget = QWidget() layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 5) self.runAsBatchButton = QPushButton(self.tr("Run as batch process...")) self.runAsBatchButton.clicked.connect(self.runAsBatch) layout.addWidget(self.runAsBatchButton) self.cornerWidget.setLayout(layout) self.tabWidget.setCornerWidget(self.cornerWidget)
class AssociateExtAddressWizard(QWizard, WIZARD_UI): def __init__(self, iface, db, qgis_utils, parent=None): QWizard.__init__(self, parent) self.setupUi(self) self.iface = iface self.log = QgsApplication.messageLog() self._db = db self.qgis_utils = qgis_utils self.canvas = self.iface.mapCanvas() self.maptool = self.canvas.mapTool() self.maptool_identify = None self.help_strings = HelpStrings() self.translatable_config_strings = TranslatableConfigStrings() self._extaddress_layer = None self._plot_layer = None self._building_layer = None self._building_unit_layer = None self._current_layer = None self._feature_tid = None self.restore_settings() self.rad_to_plot.toggled.connect(self.adjust_page_1_controls) self.rad_to_building.toggled.connect(self.adjust_page_1_controls) self.rad_to_building_unit.toggled.connect(self.adjust_page_1_controls) self.adjust_page_1_controls() self.button(QWizard.NextButton).clicked.connect(self.prepare_selection) self.button(QWizard.FinishButton).clicked.connect(self.finished_dialog) self.button(QWizard.HelpButton).clicked.connect(self.show_help) self.mMapLayerComboBox.setFilters(QgsMapLayerProxyModel.PolygonLayer) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.setLayout(QGridLayout()) self.layout().addWidget(self.bar, 0, 0, Qt.AlignTop) def adjust_page_1_controls(self): self.cbo_mapping.clear() self.cbo_mapping.addItem("") self.cbo_mapping.addItems( self.qgis_utils.get_field_mappings_file_names(EXTADDRESS_TABLE)) if self.rad_refactor.isChecked(): self.lbl_refactor_source.setEnabled(True) self.mMapLayerComboBox.setEnabled(True) self.lbl_field_mapping.setEnabled(True) self.cbo_mapping.setEnabled(True) disable_next_wizard(self) FinishButton_text = QCoreApplication.translate( "AssociateExtAddressWizard", "Import") self.txt_help_page_1.setHtml( self.help_strings.get_refactor_help_string( EXTADDRESS_TABLE, True)) self.wizardPage1.setFinalPage(True) self.wizardPage1.setButtonText( QWizard.FinishButton, QCoreApplication.translate("AssociateExtAddressWizard", FinishButton_text)) elif self.rad_to_plot.isChecked(): self.lbl_refactor_source.setEnabled(False) self.mMapLayerComboBox.setEnabled(False) self.lbl_field_mapping.setEnabled(False) self.cbo_mapping.setEnabled(False) self.wizardPage1.setFinalPage(False) enable_next_wizard(self) FinishButton_text = QCoreApplication.translate( "AssociateExtAddressWizard", "Associate Plot ExtAddress") self.txt_help_page_1.setHtml( self.help_strings. WIZ_ASSOCIATE_EXTADDRESS_CADASTRE_PAGE_1_OPTION_1) elif self.rad_to_building.isChecked(): self.lbl_refactor_source.setEnabled(False) self.mMapLayerComboBox.setEnabled(False) self.lbl_field_mapping.setEnabled(False) self.cbo_mapping.setEnabled(False) self.wizardPage1.setFinalPage(False) enable_next_wizard(self) FinishButton_text = QCoreApplication.translate( "AssociateExtAddressWizard", "Associate Building ExtAddress") self.txt_help_page_1.setHtml( self.help_strings. WIZ_ASSOCIATE_EXTADDRESS_CADASTRE_PAGE_1_OPTION_2) else: #self.rad_to_building_unit.isChecked(): self.lbl_refactor_source.setEnabled(False) self.mMapLayerComboBox.setEnabled(False) self.lbl_field_mapping.setEnabled(False) self.cbo_mapping.setEnabled(False) self.wizardPage1.setFinalPage(False) enable_next_wizard(self) FinishButton_text = QCoreApplication.translate( "AssociateExtAddressWizard", "Associate Building Unit ExtAddress") self.txt_help_page_1.setHtml( self.help_strings. WIZ_ASSOCIATE_EXTADDRESS_CADASTRE_PAGE_1_OPTION_3) self.wizardPage2.setButtonText( QWizard.FinishButton, QCoreApplication.translate('AssociateExtAddressWizard', FinishButton_text)) def prepare_selection(self): self.button(self.FinishButton).setDisabled(True) if self.rad_to_plot.isChecked(): self.btn_select.setText( QCoreApplication.translate("AssociateExtAddressWizard", "Select Plot")) self.txt_help_page_2.setHtml( self.help_strings. WIZ_ASSOCIATE_EXTADDRESS_CADASTRE_PAGE_2_OPTION_1) # Load layers res_layers = self.qgis_utils.get_layers(self._db, { EXTADDRESS_TABLE: { 'name': EXTADDRESS_TABLE, 'geometry': QgsWkbTypes.PointGeometry }, PLOT_TABLE: { 'name': PLOT_TABLE, 'geometry': QgsWkbTypes.PolygonGeometry } }, load=True) self._extaddress_layer = res_layers[EXTADDRESS_TABLE] self._plot_layer = res_layers[PLOT_TABLE] self._current_layer = self._plot_layer elif self.rad_to_building.isChecked(): self.btn_select.setText( QCoreApplication.translate("AssociateExtAddressWizard", "Select Building")) self.txt_help_page_2.setHtml( self.help_strings. WIZ_ASSOCIATE_EXTADDRESS_CADASTRE_PAGE_2_OPTION_2) # Load layers res_layers = self.qgis_utils.get_layers(self._db, { EXTADDRESS_TABLE: { 'name': EXTADDRESS_TABLE, 'geometry': QgsWkbTypes.PointGeometry }, BUILDING_TABLE: { 'name': BUILDING_TABLE, 'geometry': QgsWkbTypes.PolygonGeometry } }, load=True) self._extaddress_layer = res_layers[EXTADDRESS_TABLE] self._building_layer = res_layers[BUILDING_TABLE] self._current_layer = self._building_layer else: #self.rad_to_building_unit.isChecked(): self.btn_select.setText( QCoreApplication.translate("AssociateExtAddressWizard", "Select Building Unit")) self.txt_help_page_2.setHtml( self.help_strings. WIZ_ASSOCIATE_EXTADDRESS_CADASTRE_PAGE_2_OPTION_3) # Load layers res_layers = self.qgis_utils.get_layers(self._db, { EXTADDRESS_TABLE: { 'name': EXTADDRESS_TABLE, 'geometry': QgsWkbTypes.PointGeometry }, BUILDING_UNIT_TABLE: { 'name': BUILDING_UNIT_TABLE, 'geometry': QgsWkbTypes.PolygonGeometry } }, load=True) self._extaddress_layer = res_layers[EXTADDRESS_TABLE] self._building_unit_layer = res_layers[BUILDING_UNIT_TABLE] self._current_layer = self._building_unit_layer self.iface.setActiveLayer(self._current_layer) self.check_selected_features() self.btn_select.clicked.connect(self.select_feature) self.btn_select_by_expression.clicked.connect( self.select_feature_by_expression) def check_selected_features(self): self.bar.clearWidgets() if self._current_layer.selectedFeatureCount() == 1: self.lbl_selected.setText( QCoreApplication.translate("AssociateExtAddressWizard", "1 Feature Selected")) self.button(self.FinishButton).setDisabled(False) self._feature_tid = self._current_layer.selectedFeatures( )[0][ID_FIELD] self.canvas.zoomToSelected(self._current_layer) elif self._current_layer.selectedFeatureCount() > 1: self.show_message( QCoreApplication.translate("AssociateExtAddressWizard", "Please select just one feature"), Qgis.Warning) self.lbl_selected.setText( QCoreApplication.translate( "AssociateExtAddressWizard", "{} Feature(s) Selected".format( self._current_layer.selectedFeatureCount()))) self.button(self.FinishButton).setDisabled(True) else: self.lbl_selected.setText( QCoreApplication.translate("AssociateExtAddressWizard", "0 Features Selected")) self.button(self.FinishButton).setDisabled(True) def select_feature_by_expression(self): Dlg_expression_selection = QgsExpressionSelectionDialog( self._current_layer) self._current_layer.selectionChanged.connect( self.check_selected_features) Dlg_expression_selection.exec() self._current_layer.selectionChanged.disconnect( self.check_selected_features) def select_feature(self): self.setVisible(False) # Make wizard disappear # Create maptool self.maptool_identify = QgsMapToolIdentifyFeature(self.canvas) self.maptool_identify.setLayer(self._current_layer) cursor = QCursor() cursor.setShape(Qt.CrossCursor) self.maptool_identify.setCursor(cursor) self.canvas.setMapTool(self.maptool_identify) self.maptool_identify.featureIdentified.connect(self.get_feature_id) # TODO: Take into account that a user can select another tool def get_feature_id(self, feature): self.setVisible(True) # Make wizard appear if feature: self.lbl_selected.setText( QCoreApplication.translate("AssociateExtAddressWizard", "1 Feature Selected")) self._current_layer.selectByIds([feature.id()]) self.canvas.setMapTool(self.maptool) self.check_selected_features() self.maptool_identify.featureIdentified.disconnect(self.get_feature_id) self.log.logMessage( "Spatial Unit's featureIdentified SIGNAL disconnected", PLUGIN_NAME, Qgis.Info) def finished_dialog(self): self.save_settings() if self.rad_refactor.isChecked(): if self.mMapLayerComboBox.currentLayer() is not None: field_mapping = self.cbo_mapping.currentText() res_etl_model = self.qgis_utils.show_etl_model( self._db, self.mMapLayerComboBox.currentLayer(), EXTADDRESS_TABLE, field_mapping=field_mapping) if res_etl_model: if field_mapping: self.qgis_utils.delete_old_field_mapping(field_mapping) self.qgis_utils.save_field_mapping(EXTADDRESS_TABLE) else: self.iface.messageBar().pushMessage( 'Asistente LADM_COL', QCoreApplication.translate( "AssociateExtAddressWizard", "Select a source layer to set the field mapping to '{}'." ).format(EXTADDRESS_TABLE), Qgis.Warning) else: self.prepare_extaddress_creation() def prepare_extaddress_creation(self): # Don't suppress (i.e., show) feature form form_config = self._extaddress_layer.editFormConfig() form_config.setSuppress(QgsEditFormConfig.SuppressOff) self._extaddress_layer.setEditFormConfig(form_config) self.edit_extaddress() def edit_extaddress(self): if self._current_layer.selectedFeatureCount() == 1: # Open Form self.iface.layerTreeView().setCurrentLayer(self._extaddress_layer) self._extaddress_layer.startEditing() self.iface.actionAddFeature().trigger() # Create connections to react when a feature is added to buffer and # when it gets stored into the DB self._extaddress_layer.featureAdded.connect( self.call_extaddress_commit) else: self.iface.messageBar().pushMessage( "Asistente LADM_COL", QCoreApplication.translate("AssociateExtAddressWizard", "Please select a feature"), Qgis.Warning) def call_extaddress_commit(self, fid): plot_field_idx = self._extaddress_layer.getFeature(fid).fieldNameIndex( EXTADDRESS_PLOT_FIELD) building_field_idx = self._extaddress_layer.getFeature( fid).fieldNameIndex(EXTADDRESS_BUILDING_FIELD) building_unit_field_idx = self._extaddress_layer.getFeature( fid).fieldNameIndex(EXTADDRESS_BUILDING_UNIT_FIELD) if self._current_layer.name() == PLOT_TABLE: self._extaddress_layer.changeAttributeValue( fid, plot_field_idx, self._feature_tid) elif self._current_layer.name() == BUILDING_TABLE: self._extaddress_layer.changeAttributeValue( fid, building_field_idx, self._feature_tid) else: #self._current_layer.name() == BUILDING_UNIT_TABLE: self._extaddress_layer.changeAttributeValue( fid, building_unit_field_idx, self._feature_tid) self._extaddress_layer.featureAdded.disconnect( self.call_extaddress_commit) self.log.logMessage("Extaddres's featureAdded SIGNAL disconnected", PLUGIN_NAME, Qgis.Info) res = self._extaddress_layer.commitChanges() self._current_layer.removeSelection() def show_message(self, message, level): self.bar.pushMessage(message, level, 0) def save_settings(self): settings = QSettings() load_data_type = 'refactor' if self.rad_to_plot.isChecked(): load_data_type = 'to_plot' elif self.rad_to_building.isChecked(): load_data_type = 'to_building' else: #self.rad_to_building_unit.isChecked(): load_data_type = 'to_building_unit' settings.setValue( 'Asistente-LADM_COL/wizards/ext_address_load_data_type', load_data_type) def restore_settings(self): settings = QSettings() load_data_type = settings.value( 'Asistente-LADM_COL/wizards/ext_address_load_data_type', 'to_plot') if load_data_type == 'refactor': self.rad_refactor.setChecked(True) elif load_data_type == 'to_plot': self.rad_to_plot.setChecked(True) elif load_data_type == 'to_building': self.rad_to_building.setChecked(True) else: #load_data_type == 'to_building_unit': self.rad_to_building_unit.setChecked(True) def show_help(self): self.qgis_utils.show_help("associate_ext_address")
def setupUi(self): self.checkBoxes = {} self.showAdvanced = False self.wrappers = {} self.valueItems = {} self.dependentItems = {} self.algorithmItem = None self.resize(650, 450) self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok | QDialogButtonBox.Help) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.verticalLayout = QVBoxLayout() self.verticalLayout.setSpacing(5) self.verticalLayout.setMargin(20) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.verticalLayout.addWidget(self.bar) hLayout = QHBoxLayout() hLayout.setSpacing(5) hLayout.setMargin(0) descriptionLabel = QLabel(self.tr("Description")) self.descriptionBox = QLineEdit() self.descriptionBox.setText(self._alg.displayName()) hLayout.addWidget(descriptionLabel) hLayout.addWidget(self.descriptionBox) self.verticalLayout.addLayout(hLayout) line = QFrame() line.setFrameShape(QFrame.HLine) line.setFrameShadow(QFrame.Sunken) self.verticalLayout.addWidget(line) self.algorithmItem = QgsGui.instance().processingGuiRegistry().algorithmConfigurationWidget(self._alg) if self.configuration: self.algorithmItem.setConfiguration(self.configuration) self.verticalLayout.addWidget(self.algorithmItem) widget_context = QgsProcessingParameterWidgetContext() if iface is not None: widget_context.setMapCanvas(iface.mapCanvas()) widget_context.setModel(self.model) widget_context.setModelChildAlgorithmId(self.childId) for param in self._alg.parameterDefinitions(): if param.flags() & QgsProcessingParameterDefinition.FlagAdvanced: self.advancedButton = QPushButton() self.advancedButton.setText(self.tr('Show advanced parameters')) self.advancedButton.clicked.connect( self.showAdvancedParametersClicked) advancedButtonHLayout = QHBoxLayout() advancedButtonHLayout.addWidget(self.advancedButton) advancedButtonHLayout.addStretch() self.verticalLayout.addLayout(advancedButtonHLayout) break for param in self._alg.parameterDefinitions(): if param.isDestination() or param.flags() & QgsProcessingParameterDefinition.FlagHidden: continue wrapper = WidgetWrapperFactory.create_wrapper(param, self) self.wrappers[param.name()] = wrapper if issubclass(wrapper.__class__, QgsProcessingModelerParameterWidget): wrapper.setWidgetContext(widget_context) wrapper.registerProcessingContextGenerator(self.context_generator) widget = wrapper else: widget = wrapper.widget if widget is not None: self.valueItems[param.name()] = widget if issubclass(wrapper.__class__, QgsProcessingModelerParameterWidget): label = wrapper.createLabel() else: tooltip = param.description() widget.setToolTip(tooltip) label = wrapper.label self.widget_labels[param.name()] = label if param.flags() & QgsProcessingParameterDefinition.FlagAdvanced: label.setVisible(self.showAdvanced) widget.setVisible(self.showAdvanced) self.verticalLayout.addWidget(label) self.verticalLayout.addWidget(widget) for dest in self._alg.destinationParameterDefinitions(): if dest.flags() & QgsProcessingParameterDefinition.FlagHidden: continue if isinstance(dest, (QgsProcessingParameterRasterDestination, QgsProcessingParameterVectorDestination, QgsProcessingParameterFeatureSink, QgsProcessingParameterFileDestination, QgsProcessingParameterFolderDestination)): label = QLabel(dest.description()) item = QgsFilterLineEdit() if hasattr(item, 'setPlaceholderText'): item.setPlaceholderText(self.tr('[Enter name if this is a final result]')) self.verticalLayout.addWidget(label) self.verticalLayout.addWidget(item) self.valueItems[dest.name()] = item label = QLabel(' ') self.verticalLayout.addWidget(label) label = QLabel(self.tr('Parent algorithms')) self.dependenciesPanel = self.getDependenciesPanel() self.verticalLayout.addWidget(label) self.verticalLayout.addWidget(self.dependenciesPanel) self.verticalLayout.addStretch(1000) self.setPreviousValues() self.setWindowTitle(self._alg.displayName()) self.verticalLayout2 = QVBoxLayout() self.verticalLayout2.setSpacing(2) self.verticalLayout2.setMargin(0) self.paramPanel = QWidget() self.paramPanel.setLayout(self.verticalLayout) self.scrollArea = QgsScrollArea() self.scrollArea.setWidget(self.paramPanel) self.scrollArea.setWidgetResizable(True) self.verticalLayout2.addWidget(self.scrollArea) self.verticalLayout2.addWidget(self.buttonBox) self.setLayout(self.verticalLayout2) self.buttonBox.accepted.connect(self.okPressed) self.buttonBox.rejected.connect(self.cancelPressed) self.buttonBox.helpRequested.connect(self.openHelp) QMetaObject.connectSlotsByName(self)
class AlgorithmDialog(AlgorithmDialogBase): def __init__(self, alg): AlgorithmDialogBase.__init__(self, alg) self.alg = alg self.setMainWidget(self.getParametersPanel(alg, self)) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().insertWidget(0, self.bar) self.runAsBatchButton = QPushButton( QCoreApplication.translate("AlgorithmDialog", "Run as Batch Process…")) self.runAsBatchButton.clicked.connect(self.runAsBatch) self.buttonBox.addButton( self.runAsBatchButton, QDialogButtonBox.ResetRole) # reset role to ensure left alignment def getParametersPanel(self, alg, parent): return ParametersPanel(parent, alg) def runAsBatch(self): self.close() dlg = BatchAlgorithmDialog(self.alg) dlg.show() dlg.exec_() def getParamValues(self): parameters = {} if not hasattr(self, 'mainWidget') or self.mainWidget is None: return parameters for param in self.alg.parameterDefinitions(): if param.flags() & QgsProcessingParameterDefinition.FlagHidden: continue if not param.isDestination(): wrapper = self.mainWidget.wrappers[param.name()] value = None if wrapper.widget: value = wrapper.value() parameters[param.name()] = value if not param.checkValueIsAcceptable(value): raise AlgorithmDialogBase.InvalidParameterValue( param, wrapper.widget) else: dest_project = None if not param.flags() & QgsProcessingParameterDefinition.FlagHidden and \ isinstance(param, (QgsProcessingParameterRasterDestination, QgsProcessingParameterFeatureSink, QgsProcessingParameterVectorDestination)): if self.mainWidget.checkBoxes[param.name()].isChecked(): dest_project = QgsProject.instance() value = self.mainWidget.outputWidgets[param.name()].getValue() if value and isinstance(value, QgsProcessingOutputLayerDefinition): value.destinationProject = dest_project if value: parameters[param.name()] = value return parameters def checkExtentCRS(self): unmatchingCRS = False hasExtent = False context = dataobjects.createContext() projectCRS = iface.mapCanvas().mapSettings().destinationCrs() layers = QgsProcessingUtils.compatibleLayers(QgsProject.instance()) for param in self.alg.parameterDefinitions(): if isinstance( param, (ParameterRaster, ParameterVector, ParameterMultipleInput)): if param.value: if isinstance(param, ParameterMultipleInput): inputlayers = param.value.split(';') else: inputlayers = [param.value] for inputlayer in inputlayers: for layer in layers: if layer.source() == inputlayer: if layer.crs() != projectCRS: unmatchingCRS = True p = QgsProcessingUtils.mapLayerFromString( inputlayer, context) if p is not None: if p.crs() != projectCRS: unmatchingCRS = True if isinstance(param, ParameterExtent): if param.skip_crs_check: continue value = self.mainWidget.wrappers[ param.name()].widget.leText.text().strip() if value: hasExtent = True return hasExtent and unmatchingCRS def accept(self): super(AlgorithmDialog, self)._saveGeometry() feedback = self.createFeedback() context = dataobjects.createContext(feedback) checkCRS = ProcessingConfig.getSetting( ProcessingConfig.WARN_UNMATCHING_CRS) try: parameters = self.getParamValues() if checkCRS and not self.alg.validateInputCrs(parameters, context): reply = QMessageBox.question( self, self.tr("Unmatching CRS's"), self.tr('Layers do not all use the same CRS. This can ' 'cause unexpected results.\nDo you want to ' 'continue?'), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.No: return checkExtentCRS = ProcessingConfig.getSetting( ProcessingConfig.WARN_UNMATCHING_EXTENT_CRS) # TODO if False and checkExtentCRS and self.checkExtentCRS(): reply = QMessageBox.question( self, self.tr("Extent CRS"), self. tr('Extent parameters must use the same CRS as the input layers.\n' 'Your input layers do not have the same extent as the project, ' 'so the extent might be in a wrong CRS if you have selected it from the canvas.\n' 'Do you want to continue?'), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.No: return ok, msg = self.alg.checkParameterValues(parameters, context) if msg: QMessageBox.warning(self, self.tr('Unable to execute algorithm'), msg) return self.btnRun.setEnabled(False) self.btnClose.setEnabled(False) buttons = self.mainWidget.iterateButtons self.iterateParam = None for i in range(len(list(buttons.values()))): button = list(buttons.values())[i] if button.isChecked(): self.iterateParam = list(buttons.keys())[i] break self.progressBar.setMaximum(0) self.lblProgress.setText(self.tr('Processing algorithm...')) # Make sure the Log tab is visible before executing the algorithm try: self.tabWidget.setCurrentIndex(1) self.repaint() except: pass self.setInfo( self.tr('<b>Algorithm \'{0}\' starting...</b>').format( self.alg.displayName()), escape_html=False) feedback.pushInfo(self.tr('Input parameters:')) display_params = [] for k, v in parameters.items(): display_params.append("'" + k + "' : " + self.alg.parameterDefinition( k).valueAsPythonString(v, context)) feedback.pushCommandInfo('{ ' + ', '.join(display_params) + ' }') feedback.pushInfo('') start_time = time.time() if self.iterateParam: self.buttonCancel.setEnabled( self.alg.flags() & QgsProcessingAlgorithm.FlagCanCancel) if executeIterating(self.alg, parameters, self.iterateParam, context, feedback): feedback.pushInfo( self.tr( 'Execution completed in {0:0.2f} seconds'.format( time.time() - start_time))) self.buttonCancel.setEnabled(False) self.finish(True, parameters, context, feedback) else: self.buttonCancel.setEnabled(False) self.resetGUI() else: command = self.alg.asPythonCommand(parameters, context) if command: ProcessingLog.addToLog(command) self.buttonCancel.setEnabled( self.alg.flags() & QgsProcessingAlgorithm.FlagCanCancel) def on_complete(ok, results): if ok: feedback.pushInfo( self.tr('Execution completed in {0:0.2f} seconds'. format(time.time() - start_time))) feedback.pushInfo(self.tr('Results:')) feedback.pushCommandInfo(pformat(results)) else: feedback.reportError( self.tr('Execution failed after {0:0.2f} seconds'. format(time.time() - start_time))) feedback.pushInfo('') self.buttonCancel.setEnabled(False) self.finish(ok, results, context, feedback) task = QgsProcessingAlgRunnerTask(self.alg, parameters, context, feedback) task.executed.connect(on_complete) QgsApplication.taskManager().addTask(task) except AlgorithmDialogBase.InvalidParameterValue as e: try: self.buttonBox.accepted.connect( lambda e=e: e.widget.setPalette(QPalette())) palette = e.widget.palette() palette.setColor(QPalette.Base, QColor(255, 255, 0)) e.widget.setPalette(palette) except: pass self.bar.clearWidgets() self.bar.pushMessage( "", self.tr("Wrong or missing parameter value: {0}").format( e.parameter.description()), level=QgsMessageBar.WARNING, duration=5) def finish(self, successful, result, context, feedback): keepOpen = not successful or ProcessingConfig.getSetting( ProcessingConfig.KEEP_DIALOG_OPEN) if self.iterateParam is None: # add html results to results dock for out in self.alg.outputDefinitions(): if isinstance(out, QgsProcessingOutputHtml) and out.name( ) in result and result[out.name()]: resultsList.addResult(icon=self.alg.icon(), name=out.description(), result=result[out.name()]) if not handleAlgorithmResults(self.alg, context, feedback, not keepOpen): self.resetGUI() return self.executed = True self.setInfo(self.tr('Algorithm \'{0}\' finished').format( self.alg.displayName()), escape_html=False) if not keepOpen: self.close() else: self.resetGUI() if self.alg.hasHtmlOutputs(): self.setInfo(self.tr( 'HTML output has been generated by this algorithm.' '\nOpen the results dialog to check it.'), escape_html=False)
class CreateGroupPartySurvey(QDialog, DIALOG_UI): WIZARD_NAME = "CreateGroupPartySurveyWizard" WIZARD_TOOL_NAME = QCoreApplication.translate(WIZARD_NAME, "Create group party") def __init__(self, iface, db, parent=None): QDialog.__init__(self, parent) self.setupUi(self) self.iface = iface self._db = db self.logger = Logger() self.app = AppInterface() self.names = self._db.names self.help_strings = HelpStrings() self.data = {} # {t_id: [display_text, denominator, numerator]} self.current_selected_parties = [] # [t_ids] self.parties_to_group = {} # {t_id: [denominator, numerator]} self._layers = { self.names.LC_GROUP_PARTY_T: None, self.names.LC_PARTY_T: None, self.names.MEMBERS_T: None, self.names.FRACTION_S: None, self.names.COL_GROUP_PARTY_TYPE_D: None } # Fill combo of types col_group_party_type_table = self.app.core.get_layer(self._db, self.names.COL_GROUP_PARTY_TYPE_D, True) if not col_group_party_type_table: return for feature in col_group_party_type_table.getFeatures(): self.cbo_group_type.addItem(feature[self.names.DISPLAY_NAME_F], feature[self.names.T_ID_F]) self.txt_search_party.setText("") self.btn_select.setEnabled(False) self.btn_deselect.setEnabled(False) self.tbl_selected_parties.setColumnCount(3) self.tbl_selected_parties.setColumnWidth(0, 140) self.tbl_selected_parties.setColumnWidth(1, 90) self.tbl_selected_parties.setColumnWidth(2, 90) self.tbl_selected_parties.sortItems(0, Qt.AscendingOrder) self.txt_search_party.textEdited.connect(self.search) self.lst_all_parties.itemSelectionChanged.connect(self.selection_changed_all) self.tbl_selected_parties.itemSelectionChanged.connect(self.selection_changed_selected) self.tbl_selected_parties.cellChanged.connect(self.valueEdited) self.btn_select_all.clicked.connect(self.select_all) self.btn_deselect_all.clicked.connect(self.deselect_all) self.btn_select.clicked.connect(self.select) self.btn_deselect.clicked.connect(self.deselect) self.buttonBox.helpRequested.connect(self.show_help) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().addWidget(self.bar, 0, 0, Qt.AlignTop) self.rejected.connect(self.close_wizard) def closeEvent(self, e): # It's necessary to prevent message bar alert pass def required_layers_are_available(self): layers_are_available = self.app.core.required_layers_are_available(self._db, self._layers, self.WIZARD_TOOL_NAME) return layers_are_available def load_parties_data(self): expression = QgsExpression(self._layers[self.names.LC_PARTY_T].displayExpression()) context = QgsExpressionContext() data = dict() for feature in self._layers[self.names.LC_PARTY_T].getFeatures(): context.setFeature(feature) expression.prepare(context) value = expression.evaluate(context) data[feature[self.names.T_ID_F]] = [value if value != NULL else None, 0, 0] self.set_parties_data(data) def set_parties_data(self, parties_data): """ Initialize parties data. :param parties_data: Dictionary {t_id: [display_text, denominator, numerator]} :type parties_data: dict """ self.data = parties_data self.update_lists() def search(self, text): self.update_lists(True) def selection_changed_all(self): self.btn_select.setEnabled(len(self.lst_all_parties.selectedItems())) def selection_changed_selected(self): self.btn_deselect.setEnabled(len(self.tbl_selected_parties.selectedItems())) def select_all(self): """ SLOT. Select all parties listed from left list widget. """ items_ids = [] for index in range(self.lst_all_parties.count()): items_ids.append(self.lst_all_parties.item(index).data(Qt.UserRole)) self.add_parties_to_selected(items_ids) def deselect_all(self): """ SLOT. Remove all parties from left list widget. """ items_ids = [] for index in range(self.tbl_selected_parties.rowCount()): items_ids.append(self.tbl_selected_parties.item(index, 0).data(Qt.UserRole)) self.remove_parties_from_selected(items_ids) def select(self): """ SLOT. Select all parties highlighted in left list widget. """ self.add_parties_to_selected([item.data(Qt.UserRole) for item in self.lst_all_parties.selectedItems()]) def deselect(self): """ SLOT. Remove all parties highlighted in right list widget. """ self.remove_parties_from_selected([item.data(Qt.UserRole) for item in self.tbl_selected_parties.selectedItems() if item.column() == 0]) def add_parties_to_selected(self, parties_ids): self.current_selected_parties.extend(parties_ids) self.update_lists() def remove_parties_from_selected(self, parties_ids): for party_id in parties_ids: self.current_selected_parties.remove(party_id) if party_id in self.parties_to_group: del self.parties_to_group[party_id] self.update_lists() def update_lists(self, only_update_all_list=False): """ Update left list widget and optionally the right one. :param only_update_all_list: Only update left list widget. :type only_update_all_list: bool """ # All parties self.lst_all_parties.clear() if self.txt_search_party.text(): tmp_parties = {i:d for i,d in self.data.items() if self.txt_search_party.text().lower() in d[0].lower()} else: tmp_parties = copy.deepcopy(self.data) # Copy all! for party_id in self.current_selected_parties: if party_id in tmp_parties: del tmp_parties[party_id] for i,d in tmp_parties.items(): item = QListWidgetItem(d[0]) item.setData(Qt.UserRole, i) self.lst_all_parties.addItem(item) if not only_update_all_list: # Selected parties self.tbl_selected_parties.clearContents() self.tbl_selected_parties.setRowCount(len(self.current_selected_parties)) self.tbl_selected_parties.setColumnCount(3) self.tbl_selected_parties.setSortingEnabled(False) for row, party_id in enumerate(self.current_selected_parties): item = QTableWidgetItem(self.data[party_id][0]) item.setFlags(item.flags() & ~Qt.ItemIsEditable) item.setData(Qt.UserRole, party_id) self.tbl_selected_parties.setItem(row, 0, item) value_denominator = self.parties_to_group[party_id][0] if party_id in self.parties_to_group else self.data[party_id][1] self.tbl_selected_parties.setItem(row, 1, QTableWidgetItem(str(value_denominator))) value_numerator = self.parties_to_group[party_id][1] if party_id in self.parties_to_group else self.data[party_id][2] self.tbl_selected_parties.setItem(row, 2, QTableWidgetItem(str(value_numerator))) self.tbl_selected_parties.setSortingEnabled(True) def valueEdited(self, row, column): """ SLOT. Update either the denominator or the numerator for given row. :param row: Edited row :type row: int :param column: Edited column :type column: int """ if column != 0: party_id = self.tbl_selected_parties.item(row, 0).data(Qt.UserRole) value_denominator = self.tbl_selected_parties.item(row, 1).text() # While creating a row and the second column is created, the third # one doesn't exist, so use the value already stored for that case value_numerator = self.parties_to_group[party_id][1] if party_id in self.parties_to_group else 0 if self.tbl_selected_parties.item(row, 2) is not None: value_numerator = self.tbl_selected_parties.item(row, 2).text() self.parties_to_group[party_id] = [value_denominator, value_numerator] def accept(self): """ Overwrite the dialog's `accept <https://doc.qt.io/qt-5/qdialog.html#accept>`_ SLOT to store selected parties and numerator-denominator before closing the dialog. """ self.parties_to_group = {} for index in range(self.tbl_selected_parties.rowCount()): k = self.tbl_selected_parties.item(index, 0).data(Qt.UserRole) try: v_n = int(self.tbl_selected_parties.item(index, 1).text()) except ValueError as e: self.show_message(QCoreApplication.translate("WizardTranslations", "There are some invalid values in the numerator column. Fix them before continuing..."), Qgis.Warning) return try: v_d = int(self.tbl_selected_parties.item(index, 2).text()) except ValueError as e: self.show_message(QCoreApplication.translate("WizardTranslations", "There are some invalid values in the denominator column. Fix them before continuing..."), Qgis.Warning) return self.parties_to_group[k] = [v_n, v_d] name = self.txt_group_name.text() group_party_type = self.cbo_group_type.itemData(self.cbo_group_type.currentIndex()) dict_params = { self.names.COL_PARTY_T_NAME_F: name, self.names.COL_GROUP_PARTY_T_TYPE_F: group_party_type, 'porcentajes': self.parties_to_group } res, msg = self.validate_group_party(dict_params) if not res: self.show_message(msg, Qgis.Warning) return self.save_group_party(self._db, [dict_params]) def validate_group_party(self, params): name = params[self.names.COL_PARTY_T_NAME_F] group_party_type = params[self.names.COL_GROUP_PARTY_T_TYPE_F] porcentajes = params['porcentajes'] if not porcentajes: return (False, QCoreApplication.translate("CreateGroupParty", "You need to select some parties to create a group.")) elif len(porcentajes) == 1: return (False, QCoreApplication.translate("CreateGroupParty", "There is just one party, you need to add at least two parties to a group.")) there_percents = False fraction = Fraction() for t, nd in porcentajes.items(): if porcentajes[t] != [0,0]: there_percents = True break if there_percents: for t, nd in porcentajes.items(): if porcentajes[t][1] == 0: return (False, QCoreApplication.translate("CreateGroupParty", "There are denominators equal to zero. You need to change those values.")) elif porcentajes[t][1] < porcentajes[t][0]: return (False, QCoreApplication.translate("CreateGroupParty", "The denominator cannot be less than the numerator.")) else: fraction = Fraction(porcentajes[t][0], porcentajes[t][1]) + fraction if fraction != 1.0: return (False, QCoreApplication.translate("CreateGroupParty", "The sum of the fractions must be equal to one.")) return (True, QCoreApplication.translate("CreateGroupParty", "Validation passed!")) def show_message(self, message, level): self.bar.clearWidgets() # Remove previous messages before showing a new one self.bar.pushMessage(message, level, 10) def save_group_party(self, db, params): """ Save group party data into associated tables: self.names.LC_GROUP_PARTY_T, self.names.MEMBERS_T and self.names.FRACTION_S. params: List of dicts, where each dict is an independent group party: { self.names.COL_PARTY_T_NAME_F: '', self.names.COL_GROUP_PARTY_T_TYPE_F: '', 'porcentajes': { 't_id_miembro': [20, 100], # numerador/denominador 't_id_miembro2': [40, 100] } } """ # Disconnect from previous runs self.disconnect_signals() for group in params: # Create connections to react when a group party is stored to the DB self._layers[self.names.LC_GROUP_PARTY_T].committedFeaturesAdded.connect(partial(self.finish_group_party_saving, group['porcentajes'])) # First save the group party new_feature = QgsVectorLayerUtils().createFeature(self._layers[self.names.LC_GROUP_PARTY_T]) new_feature.setAttribute(self.names.COL_GROUP_PARTY_T_TYPE_F, group[self.names.COL_GROUP_PARTY_T_TYPE_F]) new_feature.setAttribute(self.names.COL_PARTY_T_NAME_F, group[self.names.COL_PARTY_T_NAME_F]) # TODO: Remove when local id and namespace are defined #new_feature.setAttribute(self.names.OID_T_LOCAL_ID_F, 1) #new_feature.setAttribute(self.names.OID_T_NAMESPACE_F, self.names.LC_GROUP_PARTY_T) # TODO: Gui should allow users to enter namespace, local_id and date values #new_feature.setAttribute("p_espacio_de_nombres", self.names.LC_GROUP_PARTY_T) #new_feature.setAttribute("p_local_id", '0') #new_feature.setAttribute("comienzo_vida_util_version", 'now()') self.logger.info(__name__, "Saving Group Party: {}".format(group)) with edit(self._layers[self.names.LC_GROUP_PARTY_T]): self._layers[self.names.LC_GROUP_PARTY_T].addFeature(new_feature) def finish_group_party_saving(self, members, layer_id, features): try: self._layers[self.names.LC_GROUP_PARTY_T].committedFeaturesAdded.disconnect() except TypeError as e: pass message = QCoreApplication.translate("WizardTranslations", "'{}' tool has been closed because an error occurred while trying to save the data.").format(self.WIZARD_TOOL_NAME) if len(features) != 1: message = QCoreApplication.translate("WizardTranslations", "'{}' tool has been closed. We should have got only one group party... We cannot do anything with {} group parties").format(self.WIZARD_TOOL_NAME, len(features)) self.logger.warning(__name__, "We should have got only one group party... We cannot do anything with {} group parties".format(len(features))) else: fid = features[0].id() if not self._layers[self.names.LC_GROUP_PARTY_T].getFeature(fid).isValid(): self.logger.warning(__name__, "Feature not found in table Group Party...") else: group_party_id = self._layers[self.names.LC_GROUP_PARTY_T].getFeature(fid)[self.names.T_ID_F] # Now save members party_ids = list() for party_id, fraction in members.items(): # Create connections to react when a group party is stored to the DB self._layers[self.names.MEMBERS_T].committedFeaturesAdded.connect(partial(self.finish_member_saving, fraction)) new_feature = QgsVectorLayerUtils().createFeature(self._layers[self.names.MEMBERS_T]) new_feature.setAttribute(self.names.MEMBERS_T_GROUP_PARTY_F, group_party_id) new_feature.setAttribute(self.names.MEMBERS_T_PARTY_F, party_id) self.logger.info(__name__, "Saving group party's member ({}: {}).".format(group_party_id, party_id)) with edit(self._layers[self.names.MEMBERS_T]): self._layers[self.names.MEMBERS_T].addFeature(new_feature) party_ids.append(party_id) if len(party_ids): message = QCoreApplication.translate("WizardTranslations", "The new group party (t_id={}) was successfully created and associated with its corresponding party(ies) (t_id={})!").format(group_party_id, ", ".join([str(b) for b in party_ids])) else: message = QCoreApplication.translate("WizardTranslations", "The new group party (t_id={}) was successfully created but this one wasn't associated with a party(ies)").format(group_party_id) self.close_wizard(message) def finish_member_saving(self, fraction, layer_id, features): try: self._layers[self.names.MEMBERS_T].committedFeaturesAdded.disconnect() except TypeError as e: pass if len(features) != 1: self.logger.warning(__name__, "We should have got only one member... We cannot do anything with {} members".format(len(features))) else: fid = features[0].id() if not self._layers[self.names.MEMBERS_T].getFeature(fid).isValid(): self.logger.warning(__name__, "Feature not found in table Members...") else: member_id = self._layers[self.names.MEMBERS_T].getFeature(fid)[self.names.T_ID_F] if fraction == [0, 0]: return # And finally save fractions new_feature = QgsVectorLayerUtils().createFeature(self._layers[self.names.FRACTION_S]) new_feature.setAttribute(self.names.FRACTION_S_MEMBER_F, member_id) new_feature.setAttribute(self.names.FRACTION_S_NUMERATOR_F, fraction[0]) new_feature.setAttribute(self.names.FRACTION_S_DENOMINATOR_F, fraction[1]) with edit(self._layers[self.names.FRACTION_S]): self.logger.info(__name__, "Saving member's fraction ({}: {}).".format(member_id, fraction)) self._layers[self.names.FRACTION_S].addFeature(new_feature) def close_wizard(self, message=None, show_message=True): if message is None: message = QCoreApplication.translate("WizardTranslations", "'{}' tool has been closed.").format(self.WIZARD_TOOL_NAME) if show_message: self.logger.info_msg(__name__, message) self.disconnect_signals() self.close() def disconnect_signals(self): try: self._layers[self.names.LC_GROUP_PARTY_T].committedFeaturesAdded.disconnect() except TypeError as e: pass try: self._layers[self.names.MEMBERS_T].committedFeaturesAdded.disconnect() except TypeError as e: pass def show_help(self): show_plugin_help("group_party")
class Qgis2threejsDialog(QDialog): STYLE_MAX_COUNT = 3 def __init__(self, iface): QDialog.__init__(self, iface.mainWindow()) self.iface = iface self.apiChanged22 = False # not QgsApplication.prefixPath().startswith("C:/OSGeo4W") # QGis.QGIS_VERSION_INT >= 20200 # Set up the user interface from Designer. self.ui = ui = Ui_Qgis2threejsDialog() ui.setupUi(self) self.setWindowFlags(self.windowFlags() | Qt.WindowMinimizeButtonHint) ui.lineEdit_OutputFilename.setPlaceholderText("[Temporary file]") ui.pushButton_Run.clicked.connect(self.run) ui.pushButton_Close.clicked.connect(self.reject) # DEM tab ui.toolButton_switchFocusMode.setVisible(False) ui.toolButton_PointTool.setVisible(False) ui.progressBar.setVisible(False) self.switchFocusMode(True) ui.toolButton_Browse.clicked.connect(self.browseClicked) ui.radioButton_Simple.toggled.connect(self.samplingModeChanged) ui.horizontalSlider_Resolution.valueChanged.connect( self.calculateResolution) ui.spinBox_Height.valueChanged.connect(self.updateQuads) ui.toolButton_switchFocusMode.clicked.connect( self.switchFocusModeClicked) ui.toolButton_PointTool.clicked.connect(self.startPointSelection) # Vector tab ui.treeWidget_VectorLayers.setHeaderLabel("Vector layers") self.initVectorStyleWidgets() ui.treeWidget_VectorLayers.currentItemChanged.connect( self.currentVectorLayerChanged) ui.treeWidget_VectorLayers.itemChanged.connect( self.vectorLayerItemChanged) ui.comboBox_ObjectType.currentIndexChanged.connect( self.objectTypeSelectionChanged) self.bar = None self.localBrowsingMode = True self.rb_quads = self.rb_point = None self.currentVectorLayer = None self.vectorPropertiesDict = {} self.objectTypeManager = ObjectTypeManager() # set map tool self.previousMapTool = None self.mapTool = RectangleMapTool(iface.mapCanvas()) self.connect(self.mapTool, SIGNAL("rectangleCreated()"), self.rectangleSelected) # self.mapTool = PointMapTool(iface.mapCanvas()) # QObject.connect(self.mapTool, SIGNAL("pointSelected()"), self.pointSelected) iface.mapCanvas().mapToolSet.connect(self.mapToolSet) self.startPointSelection() def exec_(self): ui = self.ui messages = [] # show message if crs unit is degrees mapSettings = self.iface.mapCanvas().mapSettings( ) if self.apiChanged22 else self.iface.mapCanvas().mapRenderer() if mapSettings.destinationCrs().mapUnits() in [QGis.Degrees]: self.showMessageBar("The unit of current CRS is degrees", "Terrain may not appear well.") # show message if there are no dem layer no_demlayer = ui.comboBox_DEMLayer.count() == 0 ui.pushButton_Run.setEnabled(not no_demlayer) if no_demlayer: self.showMessageBar( "No DEM layer", "Load 1-band raster layer with GDAL provider.", QgsMessageBar.WARNING) return QDialog.exec_(self) def showMessageBar(self, title, text, level=QgsMessageBar.INFO): if self.bar is None: self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) ui = self.ui margins = ui.gridLayout.getContentsMargins() vl = ui.gridLayout.takeAt(0) ui.gridLayout.setContentsMargins(0, 0, 0, 0) ui.gridLayout.addWidget(self.bar, 0, 0) ui.gridLayout.addItem(vl, 1, 0) ui.verticalLayout.setContentsMargins(margins[0], margins[1] / 2, margins[2], margins[3]) self.bar.pushMessage(title, text, level=level) def initDEMLayerList(self, layerId=None): # list 1 band raster layers self.ui.comboBox_DEMLayer.clear() for id, layer in QgsMapLayerRegistry().instance().mapLayers().items(): if layer.type() == QgsMapLayer.RasterLayer and layer.providerType( ) == "gdal" and layer.bandCount() == 1: self.ui.comboBox_DEMLayer.addItem(layer.name(), id) # select the last selected layer if layerId is not None: index = self.ui.comboBox_DEMLayer.findData(layerId) if index != -1: self.ui.comboBox_DEMLayer.setCurrentIndex(index) return index return -1 def initVectorLayerTree(self, vectorPropertiesDict): self.vectorPropertiesDict = vectorPropertiesDict tree = self.ui.treeWidget_VectorLayers tree.clear() # add vector layers into tree widget self.treeTopItems = topItems = { QGis.Point: QTreeWidgetItem(tree, ["Point"]), QGis.Line: QTreeWidgetItem(tree, ["Line"]), QGis.Polygon: QTreeWidgetItem(tree, ["Polygon"]) } self.vlItems = {} for layer in self.iface.legendInterface().layers(): if layer.type() != QgsMapLayer.VectorLayer: continue geometry_type = layer.geometryType() if geometry_type in [QGis.Point, QGis.Line, QGis.Polygon]: self.vlItems[layer.id()] = item = QTreeWidgetItem( topItems[geometry_type], [layer.name()]) if layer.id() in self.vectorPropertiesDict: isVisible = self.vectorPropertiesDict[ layer.id()]["visible"] else: isVisible = False #self.iface.legendInterface().isLayerVisible(layer) check_state = Qt.Checked if isVisible else Qt.Unchecked item.setData(0, Qt.CheckStateRole, check_state) item.setData(0, Qt.UserRole, layer.id()) #item.setDisabled(True) #item.setData(0, Qt.CheckStateRole, Qt.Unchecked) for item in topItems.values(): tree.expandItem(item) self.setVectorStylesEnabled(False) def initVectorStyleWidgets(self): self.colorWidget = StyleWidget(StyleWidget.COLOR) self.ui.verticalLayout_Styles.addWidget(self.colorWidget) self.heightWidget = StyleWidget(StyleWidget.HEIGHT) self.ui.verticalLayout_zCoordinate.addWidget(self.heightWidget) self.styleWidgets = [] for i in range(self.STYLE_MAX_COUNT): widget = StyleWidget() widget.setVisible(False) self.ui.verticalLayout_Styles.addWidget(widget) self.styleWidgets.append(widget) def currentVectorLayerChanged(self, currentItem, previousItem): # save properties of previous item if previousItem is not None: layerid = previousItem.data(0, Qt.UserRole) if layerid is not None: self.saveVectorProperties(layerid) layerid = currentItem.data(0, Qt.UserRole) if layerid is None: self.currentVectorLayer = None return self.currentVectorLayer = layer = QgsMapLayerRegistry().instance( ).mapLayer(layerid) if layer is None: return for i in range(self.STYLE_MAX_COUNT): self.styleWidgets[i].hide() obj_types = self.objectTypeManager.objectTypeNames( layer.geometryType()) ui = self.ui ui.comboBox_ObjectType.blockSignals(True) ui.comboBox_ObjectType.clear() ui.comboBox_ObjectType.addItems(obj_types) ui.comboBox_ObjectType.blockSignals(False) # set up property widgets self.objectTypeSelectionChanged() if layerid in self.vectorPropertiesDict: # restore properties self.restoreVectorProperties(layerid) self.setVectorStylesEnabled( currentItem.data(0, Qt.CheckStateRole) == Qt.Checked) def vectorLayerItemChanged(self, item, column): # update style form enablement currentItem = self.ui.treeWidget_VectorLayers.currentItem() if currentItem: self.setVectorStylesEnabled( currentItem.data(0, Qt.CheckStateRole) == Qt.Checked) def objectTypeSelectionChanged(self, idx=None): layer = self.currentVectorLayer try: ve = float(ui.lineEdit_zFactor.text()) except: ve = 1 mapTo3d = MapTo3D(self.iface.mapCanvas(), verticalExaggeration=ve) self.objectTypeManager.setupForm( self, mapTo3d, layer, layer.geometryType(), self.ui.comboBox_ObjectType.currentIndex()) def numericFields(self, layer): # get attributes of a sample feature and create numeric field name list numeric_fields = [] f = QgsFeature() layer.getFeatures().nextFeature(f) for field in f.fields(): isNumeric = False try: float(f.attribute(field.name())) isNumeric = True except: pass if isNumeric: numeric_fields.append(field.name()) return numeric_fields def setVectorStylesEnabled(self, enabled): self.ui.comboBox_ObjectType.setEnabled(enabled) self.ui.label_ObjectType.setEnabled(enabled) self.colorWidget.setEnabled(enabled) self.heightWidget.setEnabled(enabled) for i in range(self.STYLE_MAX_COUNT): self.styleWidgets[i].setEnabled(enabled) def saveVectorProperties(self, layerid): properties = {} layer = QgsMapLayerRegistry().instance().mapLayer(layerid) itemIndex = self.ui.comboBox_ObjectType.currentIndex() properties["itemindex"] = itemIndex properties["typeitem"] = self.objectTypeManager.objectTypeItem( layer.geometryType(), itemIndex) properties["visible"] = self.vlItems[ self.currentVectorLayer.id()].data(0, Qt.CheckStateRole) == Qt.Checked properties["color"] = self.colorWidget.values() properties["height"] = self.heightWidget.values() for i in range(self.STYLE_MAX_COUNT): if self.styleWidgets[i].isVisible(): properties[i] = self.styleWidgets[i].values() self.vectorPropertiesDict[layerid] = properties def restoreVectorProperties(self, layerid): properties = self.vectorPropertiesDict[layerid] self.ui.comboBox_ObjectType.setCurrentIndex(properties["itemindex"]) self.colorWidget.setValues(properties["color"]) self.heightWidget.setValues(properties["height"]) for i in range(self.STYLE_MAX_COUNT): if i in properties: self.styleWidgets[i].setValues(properties[i]) def calculateResolution(self, v=None): extent = self.iface.mapCanvas().extent() renderer = self.iface.mapCanvas().mapRenderer() size = 100 * self.ui.horizontalSlider_Resolution.value() self.ui.label_Resolution.setText("about {0} x {0} px".format(size)) # calculate resolution and size width, height = renderer.width(), renderer.height() s = (size * size / float(width * height))**0.5 if s < 1: width = int(width * s) height = int(height * s) xres = extent.width() / width yres = extent.height() / height self.ui.lineEdit_HRes.setText(str(xres)) self.ui.lineEdit_VRes.setText(str(yres)) self.ui.lineEdit_Width.setText(str(width + 1)) self.ui.lineEdit_Height.setText(str(height + 1)) def progress(self, percentage): self.ui.progressBar.setValue(percentage) self.ui.progressBar.setVisible(percentage != 100) def run(self): ui = self.ui filename = ui.lineEdit_OutputFilename.text() # ""=Temporary file if filename != "" and QFileInfo( filename).exists() and QMessageBox.question( None, "Qgis2threejs", "Output file already exists. Overwrite it?", QMessageBox.Ok | QMessageBox.Cancel) != QMessageBox.Ok: return self.endPointSelection() item = ui.treeWidget_VectorLayers.currentItem() if item: self.saveVectorProperties(item.data(0, Qt.UserRole)) ui.pushButton_Run.setEnabled(False) self.progress(0) canvas = self.iface.mapCanvas() htmlfilename = ui.lineEdit_OutputFilename.text() demlayerid = ui.comboBox_DEMLayer.itemData( ui.comboBox_DEMLayer.currentIndex()) mapTo3d = MapTo3D(canvas, verticalExaggeration=float( ui.lineEdit_zFactor.text())) if self.ui.radioButton_Simple.isChecked(): dem_width = int(ui.lineEdit_Width.text()) dem_height = int(ui.lineEdit_Height.text()) context = OutputContext(mapTo3d, canvas, demlayerid, self.vectorPropertiesDict, self.objectTypeManager, self.localBrowsingMode, dem_width, dem_height) htmlfilename = runSimple(htmlfilename, context, self.progress) else: context = OutputContext(mapTo3d, canvas, demlayerid, self.vectorPropertiesDict, self.objectTypeManager, self.localBrowsingMode) htmlfilename = runAdvanced(htmlfilename, context, self, self.progress) self.progress(100) ui.pushButton_Run.setEnabled(True) if htmlfilename is None: return self.clearRubberBands() if not tools.openHTMLFile(htmlfilename): return QDialog.accept(self) def reject(self): self.endPointSelection() self.clearRubberBands() QDialog.reject(self) def startPointSelection(self): canvas = self.iface.mapCanvas() self.previousMapTool = canvas.mapTool() canvas.setMapTool(self.mapTool) self.ui.toolButton_PointTool.setVisible(False) def endPointSelection(self): self.mapTool.reset() self.iface.mapCanvas().setMapTool(self.previousMapTool) def rectangleSelected(self): ui = self.ui ui.radioButton_Advanced.setChecked(True) rect = self.mapTool.rectangle() toRect = rect.width() and rect.height() self.switchFocusMode(toRect) ui.lineEdit_xmin.setText(str(rect.xMinimum())) ui.lineEdit_ymin.setText(str(rect.yMinimum())) ui.lineEdit_xmax.setText(str(rect.xMaximum())) ui.lineEdit_ymax.setText(str(rect.yMaximum())) quadtree = QuadTree(self.iface.mapCanvas().extent()) quadtree.buildTreeByRect(rect, self.ui.spinBox_Height.value()) self.createRubberBands(quadtree.quads(), rect.center()) self.setWindowState(self.windowState() & ~Qt.WindowMinimized | Qt.WindowActive) def pointSelected(self): # set values of controls self.ui.lineEdit_CenterX.setText(str(self.mapTool.point.x())) self.ui.lineEdit_CenterY.setText(str(self.mapTool.point.y())) self.ui.radioButton_Advanced.setChecked(True) quadtree = QuadTree(self.iface.mapCanvas().extent(), self.mapTool.point, self.ui.spinBox_Height.value()) self.createRubberBands(quadtree.quads(), self.mapTool.point) self.setWindowState(self.windowState() & ~Qt.WindowMinimized | Qt.WindowActive) def mapToolSet(self, mapTool): if mapTool != self.mapTool: self.ui.toolButton_PointTool.setVisible(True) def createQuadTree(self): ui = self.ui try: c = map(float, [ ui.lineEdit_xmin.text(), ui.lineEdit_ymin.text(), ui.lineEdit_xmax.text(), ui.lineEdit_ymax.text() ]) except: return None quadtree = QuadTree(self.iface.mapCanvas().extent()) quadtree.buildTreeByRect(QgsRectangle(c[0], c[1], c[2], c[3]), ui.spinBox_Height.value()) return quadtree def createRubberBands(self, quads, point=None): self.clearRubberBands() # create quads with rubber band self.rb_quads = QgsRubberBand(self.iface.mapCanvas(), QGis.Line) self.rb_quads.setColor(Qt.blue) self.rb_quads.setWidth(1) for quad in quads: points = [] extent = quad.extent points.append(QgsPoint(extent.xMinimum(), extent.yMinimum())) points.append(QgsPoint(extent.xMinimum(), extent.yMaximum())) points.append(QgsPoint(extent.xMaximum(), extent.yMaximum())) points.append(QgsPoint(extent.xMaximum(), extent.yMinimum())) self.rb_quads.addGeometry(QgsGeometry.fromPolygon([points]), None) self.log(extent.toString()) self.log("Quad count: %d" % len(quads)) # create a point with rubber band if point: self.rb_point = QgsRubberBand(self.iface.mapCanvas(), QGis.Point) self.rb_point.setColor(Qt.red) self.rb_point.addPoint(point) def clearRubberBands(self): # clear quads and point if self.rb_quads: self.iface.mapCanvas().scene().removeItem(self.rb_quads) self.rb_quads = None if self.rb_point: self.iface.mapCanvas().scene().removeItem(self.rb_point) self.rb_point = None def browseClicked(self): directory = self.ui.lineEdit_OutputFilename.text() if directory == "": directory = QDir.homePath() filename = QFileDialog.getSaveFileName( self, self.tr("Output filename"), directory, "HTML file (*.html *.htm)", options=QFileDialog.DontConfirmOverwrite) if filename != "": self.ui.lineEdit_OutputFilename.setText(filename) def samplingModeChanged(self): ui = self.ui isSimpleMode = ui.radioButton_Simple.isChecked() simple_widgets = [ ui.horizontalSlider_Resolution, ui.lineEdit_Width, ui.lineEdit_Height, ui.lineEdit_HRes, ui.lineEdit_VRes ] for w in simple_widgets: w.setEnabled(isSimpleMode) isAdvancedMode = not isSimpleMode advanced_widgets = [ ui.spinBox_Height, ui.lineEdit_xmin, ui.lineEdit_ymin, ui.lineEdit_xmax, ui.lineEdit_ymax, ui.toolButton_switchFocusMode ] for w in advanced_widgets: w.setEnabled(isAdvancedMode) def updateQuads(self, v=None): quadtree = self.createQuadTree() if quadtree: self.createRubberBands(quadtree.quads(), quadtree.focusRect.center()) else: self.clearRubberBands() def switchFocusModeClicked(self): self.switchFocusMode(not self.ui.label_xmin.isVisible()) def switchFocusMode(self, toRect): ui = self.ui toPoint = not toRect ui.label_xmin.setVisible(toRect) ui.label_ymin.setVisible(toRect) ui.lineEdit_xmin.setVisible(toRect) ui.lineEdit_ymin.setVisible(toRect) suffix = "max" if toRect else "" ui.label_xmax.setText("x" + suffix) ui.label_ymax.setText("y" + suffix) mode = "point" if toRect else "rectangle" ui.toolButton_switchFocusMode.setText("To " + mode + " selection") selection = "area" if toRect else "point" action = "Stroke a rectangle" if toRect else "Click" ui.label_Focus.setText( "Focus {0} ({1} on map canvas to set values)".format( selection, action)) def log(self, msg): if debug_mode: qDebug(msg)
class BatchAlgorithmDialog(AlgorithmDialogBase): def __init__(self, alg): AlgorithmDialogBase.__init__(self, alg) self.alg = alg self.setWindowTitle(self.tr('Batch Processing - %s') % self.alg.name) self.setMainWidget(BatchPanel(self, self.alg)) self.textShortHelp.setVisible(False) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().insertWidget(0, self.bar) def accept(self): self.algs = [] self.load = [] self.canceled = False for row in range(self.mainWidget.tblParameters.rowCount()): alg = self.alg.getCopy() col = 0 for param in alg.parameters: if param.hidden: continue wrapper = self.mainWidget.wrappers[row][col] if not self.mainWidget.setParamValue(param, wrapper, alg): self.bar.pushMessage( "", self.tr( 'Wrong or missing parameter value: %s (row %d)') % (param.description, row + 1), level=QgsMessageBar.WARNING, duration=5) self.algs = None return col += 1 for out in alg.outputs: if out.hidden: continue widget = self.mainWidget.tblParameters.cellWidget(row, col) text = widget.getValue() if text.strip() != '': out.value = text col += 1 else: self.bar.pushMessage( "", self.tr('Wrong or missing output value: %s (row %d)') % (out.description, row + 1), level=QgsMessageBar.WARNING, duration=5) self.algs = None return self.algs.append(alg) if self.alg.getVisibleOutputsCount(): widget = self.mainWidget.tblParameters.cellWidget(row, col) self.load.append(widget.currentIndex() == 0) else: self.load.append(False) QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) self.mainWidget.setEnabled(False) self.progressBar.setMaximum(len(self.algs)) # Make sure the Log tab is visible before executing the algorithm try: self.tabWidget.setCurrentIndex(1) self.repaint() except: pass for count, alg in enumerate(self.algs): self.setText( self.tr('\nProcessing algorithm %d/%d...') % (count + 1, len(self.algs))) self.setInfo(self.tr('<b>Algorithm %s starting...</b>' % alg.name)) if runalg(alg, self) and not self.canceled: if self.load[count]: handleAlgorithmResults(alg, self, False) self.setInfo( self.tr('Algorithm %s correctly executed...') % alg.name) else: QApplication.restoreOverrideCursor() return self.finish() def finish(self): for count, alg in enumerate(self.algs): self.loadHTMLResults(alg, count) self.createSummaryTable() QApplication.restoreOverrideCursor() self.mainWidget.setEnabled(True) QMessageBox.information(self, self.tr('Batch processing'), self.tr('Batch processing completed')) def loadHTMLResults(self, alg, num): for out in alg.outputs: if out.hidden or not out.open: continue if isinstance(out, OutputHTML): ProcessingResults.addResult( '{} [{}]'.format(out.description, num), out.value) def createSummaryTable(self): createTable = False for out in self.algs[0].outputs: if isinstance(out, (OutputNumber, OutputString)): createTable = True break if not createTable: return outputFile = getTempFilename('html') with codecs.open(outputFile, 'w', encoding='utf-8') as f: for alg in self.algs: f.write('<hr>\n') for out in alg.outputs: if isinstance(out, (OutputNumber, OutputString)): f.write('<p>{}: {}</p>\n'.format( out.description, out.value)) f.write('<hr>\n') ProcessingResults.addResult('{} [summary]'.format(self.algs[0].name), outputFile)
class ModelerDialog(BASE, WIDGET): CANVAS_SIZE = 4000 update_model = pyqtSignal() def __init__(self, alg=None): super(ModelerDialog, self).__init__(None) self.setupUi(self) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.centralWidget().layout().insertWidget(0, self.bar) try: self.setDockOptions(self.dockOptions() | QMainWindow.GroupedDragging) except: pass self.addDockWidget(Qt.LeftDockWidgetArea, self.propertiesDock) self.addDockWidget(Qt.LeftDockWidgetArea, self.inputsDock) self.addDockWidget(Qt.LeftDockWidgetArea, self.algorithmsDock) self.tabifyDockWidget(self.inputsDock, self.algorithmsDock) self.inputsDock.raise_() self.zoom = 1 self.setWindowFlags(Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint | Qt.WindowCloseButtonHint) settings = QgsSettings() self.restoreState( settings.value("/Processing/stateModeler", QByteArray())) self.restoreGeometry( settings.value("/Processing/geometryModeler", QByteArray())) self.scene = ModelerScene(self) self.scene.setSceneRect( QRectF(0, 0, self.CANVAS_SIZE, self.CANVAS_SIZE)) self.view.setScene(self.scene) self.view.setAcceptDrops(True) self.view.ensureVisible(0, 0, 10, 10) def _dragEnterEvent(event): if event.mimeData().hasText(): event.acceptProposedAction() else: event.ignore() def _dropEvent(event): if event.mimeData().hasText(): text = event.mimeData().text() if text in ModelerParameterDefinitionDialog.paramTypes: self.addInputOfType(text, event.pos()) else: alg = QgsApplication.processingRegistry().algorithmById( text) if alg is not None: self._addAlgorithm(alg.getCopy(), event.pos()) event.accept() else: event.ignore() def _dragMoveEvent(event): if event.mimeData().hasText(): event.accept() else: event.ignore() def _wheelEvent(event): self.view.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) settings = QgsSettings() factor = settings.value('/qgis/zoom_favor', 2.0) if (event.modifiers() == Qt.ControlModifier): factor = 1.0 + (factor - 1.0) / 20.0 if event.angleDelta().y() < 0: factor = 1 / factor self.view.scale(factor, factor) self.repaintModel() def _enterEvent(e): QGraphicsView.enterEvent(self.view, e) self.view.viewport().setCursor(Qt.ArrowCursor) def _mouseReleaseEvent(e): QGraphicsView.mouseReleaseEvent(self.view, e) self.view.viewport().setCursor(Qt.ArrowCursor) def _mousePressEvent(e): if e.button() == Qt.MidButton: self.previousMousePos = e.pos() else: QGraphicsView.mousePressEvent(self.view, e) def _mouseMoveEvent(e): if e.buttons() == Qt.MidButton: offset = self.previousMousePos - e.pos() self.previousMousePos = e.pos() self.view.verticalScrollBar().setValue( self.view.verticalScrollBar().value() + offset.y()) self.view.horizontalScrollBar().setValue( self.view.horizontalScrollBar().value() + offset.x()) else: QGraphicsView.mouseMoveEvent(self.view, e) self.view.setDragMode(QGraphicsView.ScrollHandDrag) self.view.dragEnterEvent = _dragEnterEvent self.view.dropEvent = _dropEvent self.view.dragMoveEvent = _dragMoveEvent self.view.wheelEvent = _wheelEvent self.view.enterEvent = _enterEvent self.view.mousePressEvent = _mousePressEvent self.view.mouseMoveEvent = _mouseMoveEvent def _mimeDataInput(items): mimeData = QMimeData() text = items[0].text(0) mimeData.setText(text) return mimeData self.inputsTree.mimeData = _mimeDataInput self.inputsTree.setDragDropMode(QTreeWidget.DragOnly) self.inputsTree.setDropIndicatorShown(True) def _mimeDataAlgorithm(items): item = items[0] if isinstance(item, TreeAlgorithmItem): mimeData = QMimeData() mimeData.setText(item.alg.id()) return mimeData self.algorithmTree.mimeData = _mimeDataAlgorithm self.algorithmTree.setDragDropMode(QTreeWidget.DragOnly) self.algorithmTree.setDropIndicatorShown(True) if hasattr(self.searchBox, 'setPlaceholderText'): self.searchBox.setPlaceholderText(self.tr('Search...')) if hasattr(self.textName, 'setPlaceholderText'): self.textName.setPlaceholderText(self.tr('Enter model name here')) if hasattr(self.textGroup, 'setPlaceholderText'): self.textGroup.setPlaceholderText(self.tr('Enter group name here')) # Connect signals and slots self.inputsTree.doubleClicked.connect(self.addInput) self.searchBox.textChanged.connect(self.fillAlgorithmTree) self.algorithmTree.doubleClicked.connect(self.addAlgorithm) # Ctrl+= should also trigger a zoom in action ctrlEquals = QShortcut(QKeySequence("Ctrl+="), self) ctrlEquals.activated.connect(self.zoomIn) try: iconSize = int(settings.value("iconsize", 24)) except: iconSize = 24 self.mToolbar.setIconSize(QSize(iconSize, iconSize)) self.mActionOpen.triggered.connect(self.openModel) self.mActionSave.triggered.connect(self.save) self.mActionSaveAs.triggered.connect(self.saveAs) self.mActionZoomIn.triggered.connect(self.zoomIn) self.mActionZoomOut.triggered.connect(self.zoomOut) self.mActionZoomActual.triggered.connect(self.zoomActual) self.mActionZoomToItems.triggered.connect(self.zoomToItems) self.mActionExportImage.triggered.connect(self.exportAsImage) self.mActionExportPdf.triggered.connect(self.exportAsPdf) self.mActionExportSvg.triggered.connect(self.exportAsSvg) self.mActionExportPython.triggered.connect(self.exportAsPython) self.mActionEditHelp.triggered.connect(self.editHelp) self.mActionRun.triggered.connect(self.runModel) if alg is not None: self.alg = alg self.textGroup.setText(alg._group) self.textName.setText(alg.displayName()) self.repaintModel() else: self.alg = ModelerAlgorithm() self.alg.modelerdialog = self self.fillInputsTree() self.fillAlgorithmTree() self.view.centerOn(0, 0) self.alg.setModelerView(self) self.help = None self.hasChanged = False def closeEvent(self, evt): settings = QgsSettings() settings.setValue("/Processing/stateModeler", self.saveState()) settings.setValue("/Processing/geometryModeler", self.saveGeometry()) if self.hasChanged: ret = QMessageBox.question( self, self.tr('Save?'), self. tr('There are unsaved changes in this model, do you want to keep those?' ), QMessageBox.Save | QMessageBox.Cancel | QMessageBox.Discard, QMessageBox.Cancel) if ret == QMessageBox.Save: self.saveModel(False) evt.accept() elif ret == QMessageBox.Discard: evt.accept() else: evt.ignore() else: evt.accept() def editHelp(self): alg = self.alg.getCopy() dlg = HelpEditionDialog(alg) dlg.exec_() if dlg.descriptions: self.alg.helpContent = dlg.descriptions self.hasChanged = True def runModel(self): if len(self.alg.algs) == 0: self.bar.pushMessage( "", "Model doesn't contain any algorithm and/or parameter and can't be executed", level=QgsMessageBar.WARNING, duration=5) return # hack - remove when above getCopy is removed provider = self.alg.provider() alg = self.alg.getCopy() # hack pt 2 alg.setProvider(provider) dlg = AlgorithmDialog(alg) dlg.exec_() def save(self): self.saveModel(False) def saveAs(self): self.saveModel(True) def zoomIn(self): self.view.setTransformationAnchor(QGraphicsView.NoAnchor) point = self.view.mapToScene( QPoint(self.view.viewport().width() / 2, self.view.viewport().height() / 2)) settings = QgsSettings() factor = settings.value('/qgis/zoom_favor', 2.0) self.view.scale(factor, factor) self.view.centerOn(point) self.repaintModel() def zoomOut(self): self.view.setTransformationAnchor(QGraphicsView.NoAnchor) point = self.view.mapToScene( QPoint(self.view.viewport().width() / 2, self.view.viewport().height() / 2)) settings = QgsSettings() factor = settings.value('/qgis/zoom_favor', 2.0) factor = 1 / factor self.view.scale(factor, factor) self.view.centerOn(point) self.repaintModel() def zoomActual(self): point = self.view.mapToScene( QPoint(self.view.viewport().width() / 2, self.view.viewport().height() / 2)) self.view.resetTransform() self.view.centerOn(point) def zoomToItems(self): totalRect = self.scene.itemsBoundingRect() totalRect.adjust(-10, -10, 10, 10) self.view.fitInView(totalRect, Qt.KeepAspectRatio) def exportAsImage(self): self.repaintModel(controls=False) filename, fileFilter = QFileDialog.getSaveFileName( self, self.tr('Save Model As Image'), '', self.tr('PNG files (*.png *.PNG)')) if not filename: return if not filename.lower().endswith('.png'): filename += '.png' totalRect = self.scene.itemsBoundingRect() totalRect.adjust(-10, -10, 10, 10) imgRect = QRectF(0, 0, totalRect.width(), totalRect.height()) img = QImage(totalRect.width(), totalRect.height(), QImage.Format_ARGB32_Premultiplied) img.fill(Qt.white) painter = QPainter() painter.setRenderHint(QPainter.Antialiasing) painter.begin(img) self.scene.render(painter, imgRect, totalRect) painter.end() img.save(filename) self.bar.pushMessage("", "Model was correctly exported as image", level=QgsMessageBar.SUCCESS, duration=5) self.repaintModel(controls=True) def exportAsPdf(self): self.repaintModel(controls=False) filename, fileFilter = QFileDialog.getSaveFileName( self, self.tr('Save Model As PDF'), '', self.tr('PDF files (*.pdf *.PDF)')) if not filename: return if not filename.lower().endswith('.pdf'): filename += '.pdf' totalRect = self.scene.itemsBoundingRect() totalRect.adjust(-10, -10, 10, 10) printerRect = QRectF(0, 0, totalRect.width(), totalRect.height()) printer = QPrinter() printer.setOutputFormat(QPrinter.PdfFormat) printer.setOutputFileName(filename) printer.setPaperSize(QSizeF(printerRect.width(), printerRect.height()), QPrinter.DevicePixel) printer.setFullPage(True) painter = QPainter(printer) self.scene.render(painter, printerRect, totalRect) painter.end() self.bar.pushMessage("", "Model was correctly exported as PDF", level=QgsMessageBar.SUCCESS, duration=5) self.repaintModel(controls=True) def exportAsSvg(self): self.repaintModel(controls=False) filename, fileFilter = QFileDialog.getSaveFileName( self, self.tr('Save Model As SVG'), '', self.tr('SVG files (*.svg *.SVG)')) if not filename: return if not filename.lower().endswith('.svg'): filename += '.svg' totalRect = self.scene.itemsBoundingRect() totalRect.adjust(-10, -10, 10, 10) svgRect = QRectF(0, 0, totalRect.width(), totalRect.height()) svg = QSvgGenerator() svg.setFileName(filename) svg.setSize(QSize(totalRect.width(), totalRect.height())) svg.setViewBox(svgRect) svg.setTitle(self.alg.displayName()) painter = QPainter(svg) self.scene.render(painter, svgRect, totalRect) painter.end() self.bar.pushMessage("", "Model was correctly exported as SVG", level=QgsMessageBar.SUCCESS, duration=5) self.repaintModel(controls=True) def exportAsPython(self): filename, filter = QFileDialog.getSaveFileName( self, self.tr('Save Model As Python Script'), '', self.tr('Python files (*.py *.PY)')) if not filename: return if not filename.lower().endswith('.py'): filename += '.py' text = self.alg.toPython() with codecs.open(filename, 'w', encoding='utf-8') as fout: fout.write(text) self.bar.pushMessage("", "Model was correctly exported as python script", level=QgsMessageBar.SUCCESS, duration=5) def saveModel(self, saveAs): if str(self.textGroup.text()).strip() == '' \ or str(self.textName.text()).strip() == '': QMessageBox.warning( self, self.tr('Warning'), self.tr('Please enter group and model names before saving')) return self.alg._name = str(self.textName.text()) self.alg._group = str(self.textGroup.text()) if self.alg.descriptionFile is not None and not saveAs: filename = self.alg.descriptionFile else: filename, filter = QFileDialog.getSaveFileName( self, self.tr('Save Model'), ModelerUtils.modelsFolders()[0], self.tr('Processing models (*.model)')) if filename: if not filename.endswith('.model'): filename += '.model' self.alg.descriptionFile = filename if filename: text = self.alg.toJson() try: with codecs.open(filename, 'w', encoding='utf-8') as fout: fout.write(text) except: if saveAs: QMessageBox.warning( self, self.tr('I/O error'), self.tr('Unable to save edits. Reason:\n {0}').format( str(sys.exc_info()[1]))) else: QMessageBox.warning( self, self.tr("Can't save model"), self.tr("This model can't be saved in its " "original location (probably you do not " "have permission to do it). Please, use " "the 'Save as...' option.")) return self.update_model.emit() self.bar.pushMessage("", "Model was correctly saved", level=QgsMessageBar.SUCCESS, duration=5) self.hasChanged = False def openModel(self): filename, selected_filter = QFileDialog.getOpenFileName( self, self.tr('Open Model'), ModelerUtils.modelsFolders()[0], self.tr('Processing models (*.model *.MODEL)')) if filename: try: alg = ModelerAlgorithm.fromFile(filename) self.alg = alg self.alg.setModelerView(self) self.textGroup.setText(alg._group) self.textName.setText(alg._name) self.repaintModel() self.view.centerOn(0, 0) self.hasChanged = False except WrongModelException as e: QgsMessageLog.logMessage( self.tr('Could not load model {0}\n{1}').format( filename, e.msg), self.tr('Processing'), QgsMessageLog.CRITICAL) QMessageBox.critical( self, self.tr('Could not open model'), self.tr('The selected model could not be loaded.\n' 'See the log for more information.')) except Exception as e: QgsMessageLog.logMessage( self.tr('Could not load model {0}\n{1}').format( filename, e.args[0]), self.tr('Processing'), QgsMessageLog.CRITICAL) QMessageBox.critical( self, self.tr('Could not open model'), self.tr('The selected model could not be loaded.\n' 'See the log for more information.')) def repaintModel(self, controls=True): self.scene = ModelerScene() self.scene.setSceneRect( QRectF(0, 0, ModelerAlgorithm.CANVAS_SIZE, ModelerAlgorithm.CANVAS_SIZE)) self.scene.paintModel(self.alg, controls) self.view.setScene(self.scene) def addInput(self): item = self.inputsTree.currentItem() paramType = str(item.text(0)) self.addInputOfType(paramType) def addInputOfType(self, paramType, pos=None): if paramType in ModelerParameterDefinitionDialog.paramTypes: dlg = ModelerParameterDefinitionDialog(self.alg, paramType) dlg.exec_() if dlg.param is not None: if pos is None: pos = self.getPositionForParameterItem() if isinstance(pos, QPoint): pos = QPointF(pos) self.alg.addParameter(ModelerParameter(dlg.param, pos)) self.repaintModel() # self.view.ensureVisible(self.scene.getLastParameterItem()) self.hasChanged = True def getPositionForParameterItem(self): MARGIN = 20 BOX_WIDTH = 200 BOX_HEIGHT = 80 if self.alg.inputs: maxX = max([i.pos.x() for i in list(self.alg.inputs.values())]) newX = min(MARGIN + BOX_WIDTH + maxX, self.CANVAS_SIZE - BOX_WIDTH) else: newX = MARGIN + BOX_WIDTH / 2 return QPointF(newX, MARGIN + BOX_HEIGHT / 2) def fillInputsTree(self): icon = QIcon(os.path.join(pluginPath, 'images', 'input.svg')) parametersItem = QTreeWidgetItem() parametersItem.setText(0, self.tr('Parameters')) for paramType in ModelerParameterDefinitionDialog.paramTypes: paramItem = QTreeWidgetItem() paramItem.setText(0, paramType) paramItem.setIcon(0, icon) paramItem.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled) parametersItem.addChild(paramItem) self.inputsTree.addTopLevelItem(parametersItem) parametersItem.setExpanded(True) def addAlgorithm(self): item = self.algorithmTree.currentItem() if isinstance(item, TreeAlgorithmItem): alg = QgsApplication.processingRegistry().algorithmById( item.alg.id()) self._addAlgorithm(alg.getCopy()) def _addAlgorithm(self, alg, pos=None): dlg = alg.getCustomModelerParametersDialog(self.alg) if not dlg: dlg = ModelerParametersDialog(alg, self.alg) dlg.exec_() if dlg.alg is not None: if pos is None: dlg.alg.pos = self.getPositionForAlgorithmItem() else: dlg.alg.pos = pos if isinstance(dlg.alg.pos, QPoint): dlg.alg.pos = QPointF(pos) from processing.modeler.ModelerGraphicItem import ModelerGraphicItem for i, out in enumerate(dlg.alg.outputs): dlg.alg.outputs[out].pos = dlg.alg.pos + QPointF( ModelerGraphicItem.BOX_WIDTH, (i + 1.5) * ModelerGraphicItem.BOX_HEIGHT) self.alg.addAlgorithm(dlg.alg) self.repaintModel() self.hasChanged = True def getPositionForAlgorithmItem(self): MARGIN = 20 BOX_WIDTH = 200 BOX_HEIGHT = 80 if self.alg.algs: maxX = max([alg.pos.x() for alg in list(self.alg.algs.values())]) maxY = max([alg.pos.y() for alg in list(self.alg.algs.values())]) newX = min(MARGIN + BOX_WIDTH + maxX, self.CANVAS_SIZE - BOX_WIDTH) newY = min(MARGIN + BOX_HEIGHT + maxY, self.CANVAS_SIZE - BOX_HEIGHT) else: newX = MARGIN + BOX_WIDTH / 2 newY = MARGIN * 2 + BOX_HEIGHT + BOX_HEIGHT / 2 return QPointF(newX, newY) def fillAlgorithmTree(self): self.fillAlgorithmTreeUsingProviders() self.algorithmTree.sortItems(0, Qt.AscendingOrder) text = str(self.searchBox.text()) if text != '': self.algorithmTree.expandAll() def fillAlgorithmTreeUsingProviders(self): self.algorithmTree.clear() text = str(self.searchBox.text()) search_strings = text.split(' ') for provider in QgsApplication.processingRegistry().providers(): if not provider.isActive(): continue groups = {} # Add algorithms for alg in provider.algorithms(): if alg.flags() & QgsProcessingAlgorithm.FlagHideFromModeler: continue if alg.id() == self.alg.id(): continue item_text = [alg.displayName().lower()] item_text.extend(alg.tags()) show = not search_strings or all( any(part in t for t in item_text) for part in search_strings) if show: if alg.group() in groups: groupItem = groups[alg.group()] else: groupItem = QTreeWidgetItem() name = alg.group() groupItem.setText(0, name) groupItem.setToolTip(0, name) groups[alg.group()] = groupItem algItem = TreeAlgorithmItem(alg) groupItem.addChild(algItem) if len(groups) > 0: providerItem = QTreeWidgetItem() providerItem.setText(0, provider.name()) providerItem.setToolTip(0, provider.name()) providerItem.setIcon(0, provider.icon()) for groupItem in list(groups.values()): providerItem.addChild(groupItem) self.algorithmTree.addTopLevelItem(providerItem) providerItem.setExpanded(text != '') for groupItem in list(groups.values()): if text != '': groupItem.setExpanded(True) self.algorithmTree.sortItems(0, Qt.AscendingOrder)
def __init__(self, alg=None): super(ModelerDialog, self).__init__(None) self.setupUi(self) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.centralWidget().layout().insertWidget(0, self.bar) try: self.setDockOptions(self.dockOptions() | QMainWindow.GroupedDragging) except: pass self.addDockWidget(Qt.LeftDockWidgetArea, self.propertiesDock) self.addDockWidget(Qt.LeftDockWidgetArea, self.inputsDock) self.addDockWidget(Qt.LeftDockWidgetArea, self.algorithmsDock) self.tabifyDockWidget(self.inputsDock, self.algorithmsDock) self.inputsDock.raise_() self.zoom = 1 self.setWindowFlags(Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint | Qt.WindowCloseButtonHint) settings = QgsSettings() self.restoreState( settings.value("/Processing/stateModeler", QByteArray())) self.restoreGeometry( settings.value("/Processing/geometryModeler", QByteArray())) self.scene = ModelerScene(self) self.scene.setSceneRect( QRectF(0, 0, self.CANVAS_SIZE, self.CANVAS_SIZE)) self.view.setScene(self.scene) self.view.setAcceptDrops(True) self.view.ensureVisible(0, 0, 10, 10) def _dragEnterEvent(event): if event.mimeData().hasText(): event.acceptProposedAction() else: event.ignore() def _dropEvent(event): if event.mimeData().hasText(): text = event.mimeData().text() if text in ModelerParameterDefinitionDialog.paramTypes: self.addInputOfType(text, event.pos()) else: alg = QgsApplication.processingRegistry().algorithmById( text) if alg is not None: self._addAlgorithm(alg.getCopy(), event.pos()) event.accept() else: event.ignore() def _dragMoveEvent(event): if event.mimeData().hasText(): event.accept() else: event.ignore() def _wheelEvent(event): self.view.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) settings = QgsSettings() factor = settings.value('/qgis/zoom_favor', 2.0) if (event.modifiers() == Qt.ControlModifier): factor = 1.0 + (factor - 1.0) / 20.0 if event.angleDelta().y() < 0: factor = 1 / factor self.view.scale(factor, factor) self.repaintModel() def _enterEvent(e): QGraphicsView.enterEvent(self.view, e) self.view.viewport().setCursor(Qt.ArrowCursor) def _mouseReleaseEvent(e): QGraphicsView.mouseReleaseEvent(self.view, e) self.view.viewport().setCursor(Qt.ArrowCursor) def _mousePressEvent(e): if e.button() == Qt.MidButton: self.previousMousePos = e.pos() else: QGraphicsView.mousePressEvent(self.view, e) def _mouseMoveEvent(e): if e.buttons() == Qt.MidButton: offset = self.previousMousePos - e.pos() self.previousMousePos = e.pos() self.view.verticalScrollBar().setValue( self.view.verticalScrollBar().value() + offset.y()) self.view.horizontalScrollBar().setValue( self.view.horizontalScrollBar().value() + offset.x()) else: QGraphicsView.mouseMoveEvent(self.view, e) self.view.setDragMode(QGraphicsView.ScrollHandDrag) self.view.dragEnterEvent = _dragEnterEvent self.view.dropEvent = _dropEvent self.view.dragMoveEvent = _dragMoveEvent self.view.wheelEvent = _wheelEvent self.view.enterEvent = _enterEvent self.view.mousePressEvent = _mousePressEvent self.view.mouseMoveEvent = _mouseMoveEvent def _mimeDataInput(items): mimeData = QMimeData() text = items[0].text(0) mimeData.setText(text) return mimeData self.inputsTree.mimeData = _mimeDataInput self.inputsTree.setDragDropMode(QTreeWidget.DragOnly) self.inputsTree.setDropIndicatorShown(True) def _mimeDataAlgorithm(items): item = items[0] if isinstance(item, TreeAlgorithmItem): mimeData = QMimeData() mimeData.setText(item.alg.id()) return mimeData self.algorithmTree.mimeData = _mimeDataAlgorithm self.algorithmTree.setDragDropMode(QTreeWidget.DragOnly) self.algorithmTree.setDropIndicatorShown(True) if hasattr(self.searchBox, 'setPlaceholderText'): self.searchBox.setPlaceholderText(self.tr('Search...')) if hasattr(self.textName, 'setPlaceholderText'): self.textName.setPlaceholderText(self.tr('Enter model name here')) if hasattr(self.textGroup, 'setPlaceholderText'): self.textGroup.setPlaceholderText(self.tr('Enter group name here')) # Connect signals and slots self.inputsTree.doubleClicked.connect(self.addInput) self.searchBox.textChanged.connect(self.fillAlgorithmTree) self.algorithmTree.doubleClicked.connect(self.addAlgorithm) # Ctrl+= should also trigger a zoom in action ctrlEquals = QShortcut(QKeySequence("Ctrl+="), self) ctrlEquals.activated.connect(self.zoomIn) try: iconSize = int(settings.value("iconsize", 24)) except: iconSize = 24 self.mToolbar.setIconSize(QSize(iconSize, iconSize)) self.mActionOpen.triggered.connect(self.openModel) self.mActionSave.triggered.connect(self.save) self.mActionSaveAs.triggered.connect(self.saveAs) self.mActionZoomIn.triggered.connect(self.zoomIn) self.mActionZoomOut.triggered.connect(self.zoomOut) self.mActionZoomActual.triggered.connect(self.zoomActual) self.mActionZoomToItems.triggered.connect(self.zoomToItems) self.mActionExportImage.triggered.connect(self.exportAsImage) self.mActionExportPdf.triggered.connect(self.exportAsPdf) self.mActionExportSvg.triggered.connect(self.exportAsSvg) self.mActionExportPython.triggered.connect(self.exportAsPython) self.mActionEditHelp.triggered.connect(self.editHelp) self.mActionRun.triggered.connect(self.runModel) if alg is not None: self.alg = alg self.textGroup.setText(alg._group) self.textName.setText(alg.displayName()) self.repaintModel() else: self.alg = ModelerAlgorithm() self.alg.modelerdialog = self self.fillInputsTree() self.fillAlgorithmTree() self.view.centerOn(0, 0) self.alg.setModelerView(self) self.help = None self.hasChanged = False
def __init__(self, model=None): super().__init__(None) self.setAttribute(Qt.WA_DeleteOnClose) self.setupUi(self) # LOTS of bug reports when we include the dock creation in the UI file # see e.g. #16428, #19068 # So just roll it all by hand......! self.propertiesDock = QgsDockWidget(self) self.propertiesDock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.propertiesDock.setObjectName("propertiesDock") propertiesDockContents = QWidget() self.verticalDockLayout_1 = QVBoxLayout(propertiesDockContents) self.verticalDockLayout_1.setContentsMargins(0, 0, 0, 0) self.verticalDockLayout_1.setSpacing(0) self.scrollArea_1 = QgsScrollArea(propertiesDockContents) sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.scrollArea_1.sizePolicy().hasHeightForWidth()) self.scrollArea_1.setSizePolicy(sizePolicy) self.scrollArea_1.setFocusPolicy(Qt.WheelFocus) self.scrollArea_1.setFrameShape(QFrame.NoFrame) self.scrollArea_1.setFrameShadow(QFrame.Plain) self.scrollArea_1.setWidgetResizable(True) self.scrollAreaWidgetContents_1 = QWidget() self.gridLayout = QGridLayout(self.scrollAreaWidgetContents_1) self.gridLayout.setContentsMargins(6, 6, 6, 6) self.gridLayout.setSpacing(4) self.label_1 = QLabel(self.scrollAreaWidgetContents_1) self.gridLayout.addWidget(self.label_1, 0, 0, 1, 1) self.textName = QLineEdit(self.scrollAreaWidgetContents_1) self.gridLayout.addWidget(self.textName, 0, 1, 1, 1) self.label_2 = QLabel(self.scrollAreaWidgetContents_1) self.gridLayout.addWidget(self.label_2, 1, 0, 1, 1) self.textGroup = QLineEdit(self.scrollAreaWidgetContents_1) self.gridLayout.addWidget(self.textGroup, 1, 1, 1, 1) self.label_1.setText(self.tr("Name")) self.textName.setToolTip(self.tr("Enter model name here")) self.label_2.setText(self.tr("Group")) self.textGroup.setToolTip(self.tr("Enter group name here")) self.scrollArea_1.setWidget(self.scrollAreaWidgetContents_1) self.verticalDockLayout_1.addWidget(self.scrollArea_1) self.propertiesDock.setWidget(propertiesDockContents) self.addDockWidget(Qt.DockWidgetArea(1), self.propertiesDock) self.propertiesDock.setWindowTitle(self.tr("Model properties")) self.inputsDock = QgsDockWidget(self) self.inputsDock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.inputsDock.setObjectName("inputsDock") self.inputsDockContents = QWidget() self.verticalLayout_3 = QVBoxLayout(self.inputsDockContents) self.verticalLayout_3.setContentsMargins(0, 0, 0, 0) self.scrollArea_2 = QgsScrollArea(self.inputsDockContents) sizePolicy.setHeightForWidth( self.scrollArea_2.sizePolicy().hasHeightForWidth()) self.scrollArea_2.setSizePolicy(sizePolicy) self.scrollArea_2.setFocusPolicy(Qt.WheelFocus) self.scrollArea_2.setFrameShape(QFrame.NoFrame) self.scrollArea_2.setFrameShadow(QFrame.Plain) self.scrollArea_2.setWidgetResizable(True) self.scrollAreaWidgetContents_2 = QWidget() self.verticalLayout = QVBoxLayout(self.scrollAreaWidgetContents_2) self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.verticalLayout.setSpacing(0) self.inputsTree = QTreeWidget(self.scrollAreaWidgetContents_2) self.inputsTree.setAlternatingRowColors(True) self.inputsTree.header().setVisible(False) self.verticalLayout.addWidget(self.inputsTree) self.scrollArea_2.setWidget(self.scrollAreaWidgetContents_2) self.verticalLayout_3.addWidget(self.scrollArea_2) self.inputsDock.setWidget(self.inputsDockContents) self.addDockWidget(Qt.DockWidgetArea(1), self.inputsDock) self.inputsDock.setWindowTitle(self.tr("Inputs")) self.algorithmsDock = QgsDockWidget(self) self.algorithmsDock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.algorithmsDock.setObjectName("algorithmsDock") self.algorithmsDockContents = QWidget() self.verticalLayout_4 = QVBoxLayout(self.algorithmsDockContents) self.verticalLayout_4.setContentsMargins(0, 0, 0, 0) self.scrollArea_3 = QgsScrollArea(self.algorithmsDockContents) sizePolicy.setHeightForWidth( self.scrollArea_3.sizePolicy().hasHeightForWidth()) self.scrollArea_3.setSizePolicy(sizePolicy) self.scrollArea_3.setFocusPolicy(Qt.WheelFocus) self.scrollArea_3.setFrameShape(QFrame.NoFrame) self.scrollArea_3.setFrameShadow(QFrame.Plain) self.scrollArea_3.setWidgetResizable(True) self.scrollAreaWidgetContents_3 = QWidget() self.verticalLayout_2 = QVBoxLayout(self.scrollAreaWidgetContents_3) self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) self.verticalLayout_2.setSpacing(4) self.searchBox = QgsFilterLineEdit(self.scrollAreaWidgetContents_3) self.verticalLayout_2.addWidget(self.searchBox) self.algorithmTree = QgsProcessingToolboxTreeView( None, QgsApplication.processingRegistry()) self.algorithmTree.setAlternatingRowColors(True) self.algorithmTree.header().setVisible(False) self.verticalLayout_2.addWidget(self.algorithmTree) self.scrollArea_3.setWidget(self.scrollAreaWidgetContents_3) self.verticalLayout_4.addWidget(self.scrollArea_3) self.algorithmsDock.setWidget(self.algorithmsDockContents) self.addDockWidget(Qt.DockWidgetArea(1), self.algorithmsDock) self.algorithmsDock.setWindowTitle(self.tr("Algorithms")) self.searchBox.setToolTip( self.tr("Enter algorithm name to filter list")) self.searchBox.setShowSearchIcon(True) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.centralWidget().layout().insertWidget(0, self.bar) try: self.setDockOptions(self.dockOptions() | QMainWindow.GroupedDragging) except: pass if iface is not None: self.mToolbar.setIconSize(iface.iconSize()) self.setStyleSheet(iface.mainWindow().styleSheet()) self.mActionOpen.setIcon( QgsApplication.getThemeIcon('/mActionFileOpen.svg')) self.mActionSave.setIcon( QgsApplication.getThemeIcon('/mActionFileSave.svg')) self.mActionSaveAs.setIcon( QgsApplication.getThemeIcon('/mActionFileSaveAs.svg')) self.mActionSaveInProject.setIcon( QgsApplication.getThemeIcon('/mAddToProject.svg')) self.mActionZoomActual.setIcon( QgsApplication.getThemeIcon('/mActionZoomActual.svg')) self.mActionZoomIn.setIcon( QgsApplication.getThemeIcon('/mActionZoomIn.svg')) self.mActionZoomOut.setIcon( QgsApplication.getThemeIcon('/mActionZoomOut.svg')) self.mActionExportImage.setIcon( QgsApplication.getThemeIcon('/mActionSaveMapAsImage.svg')) self.mActionZoomToItems.setIcon( QgsApplication.getThemeIcon('/mActionZoomFullExtent.svg')) self.mActionExportPdf.setIcon( QgsApplication.getThemeIcon('/mActionSaveAsPDF.svg')) self.mActionExportSvg.setIcon( QgsApplication.getThemeIcon('/mActionSaveAsSVG.svg')) #self.mActionExportPython.setIcon( # QgsApplication.getThemeIcon('/mActionSaveAsPython.svg')) self.mActionEditHelp.setIcon( QgsApplication.getThemeIcon('/mActionEditHelpContent.svg')) self.mActionRun.setIcon( QgsApplication.getThemeIcon('/mActionStart.svg')) self.addDockWidget(Qt.LeftDockWidgetArea, self.propertiesDock) self.addDockWidget(Qt.LeftDockWidgetArea, self.inputsDock) self.addDockWidget(Qt.LeftDockWidgetArea, self.algorithmsDock) self.tabifyDockWidget(self.inputsDock, self.algorithmsDock) self.inputsDock.raise_() self.zoom = 1 self.setWindowFlags(Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint | Qt.WindowCloseButtonHint) settings = QgsSettings() self.restoreState( settings.value("/Processing/stateModeler", QByteArray())) self.restoreGeometry( settings.value("/Processing/geometryModeler", QByteArray())) self.scene = ModelerScene(self, dialog=self) self.scene.setSceneRect( QRectF(0, 0, self.CANVAS_SIZE, self.CANVAS_SIZE)) self.view.setScene(self.scene) self.view.setAcceptDrops(True) self.view.ensureVisible(0, 0, 10, 10) def _dragEnterEvent(event): if event.mimeData().hasText() or event.mimeData().hasFormat( 'application/x-vnd.qgis.qgis.algorithmid'): event.acceptProposedAction() else: event.ignore() def _dropEvent(event): 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() alg = QgsApplication.processingRegistry().createAlgorithmById( algorithm_id) if alg is not None: self._addAlgorithm(alg, event.pos()) else: assert False, algorithm_id elif event.mimeData().hasText(): itemId = event.mimeData().text() if itemId in [ param.id() for param in QgsApplication.instance(). processingRegistry().parameterTypes() ]: self.addInputOfType(itemId, event.pos()) event.accept() else: event.ignore() def _dragMoveEvent(event): if event.mimeData().hasText() or event.mimeData().hasFormat( 'application/x-vnd.qgis.qgis.algorithmid'): event.accept() else: event.ignore() def _wheelEvent(event): self.view.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) settings = QgsSettings() factor = settings.value('/qgis/zoom_favor', 2.0) # "Normal" mouse has an angle delta of 120, precision mouses provide data # faster, in smaller steps factor = 1.0 + (factor - 1.0) / 120.0 * abs(event.angleDelta().y()) if (event.modifiers() == Qt.ControlModifier): factor = 1.0 + (factor - 1.0) / 20.0 if event.angleDelta().y() < 0: factor = 1 / factor self.view.scale(factor, factor) def _enterEvent(e): QGraphicsView.enterEvent(self.view, e) self.view.viewport().setCursor(Qt.ArrowCursor) def _mouseReleaseEvent(e): QGraphicsView.mouseReleaseEvent(self.view, e) self.view.viewport().setCursor(Qt.ArrowCursor) def _mousePressEvent(e): if e.button() == Qt.MidButton: self.previousMousePos = e.pos() else: QGraphicsView.mousePressEvent(self.view, e) def _mouseMoveEvent(e): if e.buttons() == Qt.MidButton: offset = self.previousMousePos - e.pos() self.previousMousePos = e.pos() self.view.verticalScrollBar().setValue( self.view.verticalScrollBar().value() + offset.y()) self.view.horizontalScrollBar().setValue( self.view.horizontalScrollBar().value() + offset.x()) else: QGraphicsView.mouseMoveEvent(self.view, e) self.view.setDragMode(QGraphicsView.ScrollHandDrag) self.view.dragEnterEvent = _dragEnterEvent self.view.dropEvent = _dropEvent self.view.dragMoveEvent = _dragMoveEvent self.view.wheelEvent = _wheelEvent self.view.enterEvent = _enterEvent self.view.mousePressEvent = _mousePressEvent self.view.mouseMoveEvent = _mouseMoveEvent def _mimeDataInput(items): mimeData = QMimeData() text = items[0].data(0, Qt.UserRole) mimeData.setText(text) return mimeData self.inputsTree.mimeData = _mimeDataInput self.inputsTree.setDragDropMode(QTreeWidget.DragOnly) self.inputsTree.setDropIndicatorShown(True) self.algorithms_model = ModelerToolboxModel( self, QgsApplication.processingRegistry()) self.algorithmTree.setToolboxProxyModel(self.algorithms_model) self.algorithmTree.setDragDropMode(QTreeWidget.DragOnly) self.algorithmTree.setDropIndicatorShown(True) self.algorithmTree.setFilters( QgsProcessingToolboxProxyModel.FilterModeler) if hasattr(self.searchBox, 'setPlaceholderText'): self.searchBox.setPlaceholderText( QCoreApplication.translate('ModelerDialog', 'Search…')) if hasattr(self.textName, 'setPlaceholderText'): self.textName.setPlaceholderText(self.tr('Enter model name here')) if hasattr(self.textGroup, 'setPlaceholderText'): self.textGroup.setPlaceholderText(self.tr('Enter group name here')) # Connect signals and slots self.inputsTree.doubleClicked.connect(self.addInput) self.searchBox.textChanged.connect(self.algorithmTree.setFilterString) self.algorithmTree.doubleClicked.connect(self.addAlgorithm) # Ctrl+= should also trigger a zoom in action ctrlEquals = QShortcut(QKeySequence("Ctrl+="), self) ctrlEquals.activated.connect(self.zoomIn) self.mActionOpen.triggered.connect(self.openModel) self.mActionSave.triggered.connect(self.save) self.mActionSaveAs.triggered.connect(self.saveAs) self.mActionSaveInProject.triggered.connect(self.saveInProject) self.mActionZoomIn.triggered.connect(self.zoomIn) self.mActionZoomOut.triggered.connect(self.zoomOut) self.mActionZoomActual.triggered.connect(self.zoomActual) self.mActionZoomToItems.triggered.connect(self.zoomToItems) self.mActionExportImage.triggered.connect(self.exportAsImage) self.mActionExportPdf.triggered.connect(self.exportAsPdf) self.mActionExportSvg.triggered.connect(self.exportAsSvg) #self.mActionExportPython.triggered.connect(self.exportAsPython) self.mActionEditHelp.triggered.connect(self.editHelp) self.mActionRun.triggered.connect(self.runModel) if model is not None: self.model = model.create() self.model.setSourceFilePath(model.sourceFilePath()) self.textGroup.setText(self.model.group()) self.textName.setText(self.model.displayName()) self.repaintModel() else: self.model = QgsProcessingModelAlgorithm() self.model.setProvider( QgsApplication.processingRegistry().providerById('model')) self.fillInputsTree() self.view.centerOn(0, 0) self.help = None self.hasChanged = False
class DialogImportData(QDialog, DIALOG_UI): open_dlg_import_schema = pyqtSignal(list) # selected models BUTTON_NAME_IMPORT_DATA = QCoreApplication.translate( "DialogImportData", "Import data") BUTTON_NAME_GO_TO_CREATE_STRUCTURE = QCoreApplication.translate( "DialogImportData", "Go to Create Structure...") def __init__(self, iface, qgis_utils, conn_manager): QDialog.__init__(self) self.setupUi(self) QgsGui.instance().enableAutoGeometryRestore(self) self.iface = iface self.conn_manager = conn_manager self.db = self.conn_manager.get_db_connector_from_source() self.qgis_utils = qgis_utils self.base_configuration = BaseConfiguration() self.ilicache = IliCache(self.base_configuration) self.ilicache.refresh() self._conf_db = ConfigDbSupported() self._params = None self._current_db = None self.xtf_file_browse_button.clicked.connect( make_file_selector( self.xtf_file_line_edit, title=QCoreApplication.translate( "DialogImportData", 'Open Transfer or Catalog File'), file_filter=QCoreApplication.translate( "DialogImportData", 'Transfer File (*.xtf *.itf);;Catalogue File (*.xml *.xls *.xlsx)' ))) self.validators = Validators() self.xtf_file_line_edit.setPlaceholderText( QCoreApplication.translate("DialogImportData", "[Name of the XTF to be imported]")) fileValidator = FileValidator(pattern=['*.xtf', '*.itf', '*.xml']) self.xtf_file_line_edit.setValidator(fileValidator) self.xtf_file_line_edit.textChanged.connect(self.update_import_models) self.xtf_file_line_edit.textChanged.emit( self.xtf_file_line_edit.text()) # db self.connection_setting_button.clicked.connect(self.show_settings) self.connection_setting_button.setText( QCoreApplication.translate("DialogImportData", 'Connection Settings')) # LOG self.log_config.setTitle( QCoreApplication.translate("DialogImportData", "Show log")) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().addWidget(self.bar, 0, 0, Qt.AlignTop) self.buttonBox.accepted.disconnect() self.buttonBox.clicked.connect(self.accepted_import_data) self.buttonBox.clear() self.buttonBox.addButton(QDialogButtonBox.Cancel) self._accept_button = self.buttonBox.addButton( self.BUTTON_NAME_IMPORT_DATA, QDialogButtonBox.AcceptRole) self.buttonBox.addButton(QDialogButtonBox.Help) self.buttonBox.helpRequested.connect(self.show_help) self.update_connection_info() self.restore_configuration() def accepted_import_data(self, button): if self.buttonBox.buttonRole(button) == QDialogButtonBox.AcceptRole: if button.text() == self.BUTTON_NAME_IMPORT_DATA: self.accepted() elif button.text() == self.BUTTON_NAME_GO_TO_CREATE_STRUCTURE: self.close() # Close import data dialog self.open_dlg_import_schema.emit(self.get_ili_models( )) # Emit signal to open import schema dialog def update_connection_info(self): db_description = self.db.get_description_conn_string() if db_description: self.db_connect_label.setText(db_description) self.db_connect_label.setToolTip(self.db.get_display_conn_string()) self._accept_button.setEnabled(True) else: self.db_connect_label.setText( QCoreApplication.translate("DialogImportData", "The database is not defined!")) self.db_connect_label.setToolTip('') self._accept_button.setEnabled(False) def update_import_models(self): message_error = None if not self.xtf_file_line_edit.text().strip(): color = '#ffd356' # Light orange self.import_models_qmodel = QStandardItemModel() self.import_models_list_view.setModel(self.import_models_qmodel) else: if os.path.isfile(self.xtf_file_line_edit.text().strip()): color = '#fff' # White self.import_models_qmodel = QStandardItemModel() models_name = self.find_models_xtf( self.xtf_file_line_edit.text().strip()) for model_name in models_name: if not model_name in DEFAULT_HIDDEN_MODELS: item = QStandardItem(model_name) item.setCheckable(False) item.setEditable(False) self.import_models_qmodel.appendRow(item) if self.import_models_qmodel.rowCount() > 0: self.import_models_list_view.setModel( self.import_models_qmodel) else: message_error = QCoreApplication.translate( "DialogImportData", "No models were found in the XTF. Is it a valid file?") color = '#ffd356' # Light orange self.import_models_qmodel = QStandardItemModel() self.import_models_list_view.setModel( self.import_models_qmodel) else: message_error = QCoreApplication.translate( "DialogImportData", "Please set a valid XTF file") color = '#ffd356' # Light orange self.import_models_qmodel = QStandardItemModel() self.import_models_list_view.setModel( self.import_models_qmodel) self.xtf_file_line_edit.setStyleSheet( 'QLineEdit {{ background-color: {} }}'.format(color)) if message_error: self.txtStdout.setText(message_error) self.show_message(message_error, Qgis.Warning) self.import_models_list_view.setFocus() return def find_models_xtf(self, xtf_path): models_name = list() pattern = re.compile(r'<MODEL[^>]*>(?P<text>[^<]*)</MODEL>') with open(xtf_path, 'r') as f: for txt in pattern.finditer(f.read()): model_tag = str(txt.group(0)) name = re.findall('NAME="(.*?)"', model_tag, re.IGNORECASE) models_name.extend(name) return sorted(models_name) def get_ili_models(self): ili_models = list() for index in range(self.import_models_qmodel.rowCount()): item = self.import_models_qmodel.item(index) ili_models.append(item.text()) return ili_models def show_settings(self): dlg = SettingsDialog(qgis_utils=self.qgis_utils, conn_manager=self.conn_manager) # Connect signals (DBUtils, QgisUtils) dlg.db_connection_changed.connect( self.conn_manager.db_connection_changed) dlg.db_connection_changed.connect( self.qgis_utils.cache_layers_and_relations) dlg.organization_tools_changed.connect( self.qgis_utils.organization_tools_changed) dlg.set_action_type(EnumDbActionType.IMPORT) dlg.tabWidget.setCurrentIndex(SETTINGS_CONNECTION_TAB_INDEX) if dlg.exec_(): self.db = dlg.get_db_connection() self.update_connection_info() def accepted(self): configuration = self.update_configuration() if not os.path.isfile(self.xtf_file_line_edit.text().strip()): message_error = 'Please set a valid XTF file before importing data. XTF file does not exist' self.txtStdout.setText( QCoreApplication.translate("DialogImportData", message_error)) self.show_message(message_error, Qgis.Warning) self.xtf_file_line_edit.setFocus() return if not self.xtf_file_line_edit.validator().validate( configuration.xtffile, 0)[0] == QValidator.Acceptable: message_error = 'Please set a valid XTF before importing data.' self.txtStdout.setText( QCoreApplication.translate("DialogImportData", message_error)) self.show_message(message_error, Qgis.Warning) self.xtf_file_line_edit.setFocus() return if not self.get_ili_models(): message_error = QCoreApplication.translate( "DialogImportData", "The selected XTF file does not have information according to the LADM-COL model to import." ) self.txtStdout.setText(message_error) self.show_message(message_error, Qgis.Warning) self.import_models_list_view.setFocus() return # Get list models in db and xtf ili_models = set([ili_model for ili_model in self.get_ili_models()]) db_models = list() for db_model in self.db.get_models(): model_name_with_dependencies = db_model['modelname'] model_name = model_name_with_dependencies.split('{')[0] db_models.append(model_name) db_models = set(db_models) if not ili_models.issubset(db_models): message_error = "The XTF file to import does not have the same models as the target database schema. " \ "Please create a schema that also includes the following missing modules:\n\n * {}".format(" \n * ".join(sorted(ili_models.difference(db_models)))) self.txtStdout.clear() self.txtStdout.setTextColor(QColor('#000000')) self.txtStdout.setText( QCoreApplication.translate("DialogImportData", message_error)) self.show_message(message_error, Qgis.Warning) self.xtf_file_line_edit.setFocus() # button is removed to define order in GUI for button in self.buttonBox.buttons(): if button.text() == self.BUTTON_NAME_IMPORT_DATA: self.buttonBox.removeButton(button) # Check if button was previously added self.remove_create_structure_button() self.buttonBox.addButton( self.BUTTON_NAME_GO_TO_CREATE_STRUCTURE, QDialogButtonBox.AcceptRole).setStyleSheet("color: #aa2222;") self.buttonBox.addButton(self.BUTTON_NAME_IMPORT_DATA, QDialogButtonBox.AcceptRole) return with OverrideCursor(Qt.WaitCursor): self.progress_bar.show() self.progress_bar.setValue(0) self.disable() self.txtStdout.setTextColor(QColor('#000000')) self.txtStdout.clear() dataImporter = iliimporter.Importer(dataImport=True) item_db = self._conf_db.get_db_items()[self.db.mode] dataImporter.tool = item_db.get_mbaker_db_ili_mode() dataImporter.configuration = configuration self.save_configuration(configuration) dataImporter.stdout.connect(self.print_info) dataImporter.stderr.connect(self.on_stderr) dataImporter.process_started.connect(self.on_process_started) dataImporter.process_finished.connect(self.on_process_finished) self.progress_bar.setValue(25) try: if dataImporter.run() != iliimporter.Importer.SUCCESS: self.enable() self.progress_bar.hide() self.show_message( QCoreApplication.translate( "DialogImportData", "An error occurred when importing the data. For more information see the log..." ), Qgis.Warning) return except JavaNotFoundError: # Set JAVA PATH get_java_path_dlg = GetJavaPathDialog() get_java_path_dlg.setModal(True) if get_java_path_dlg.exec_(): configuration = self.update_configuration() if not get_java_path_from_qgis_model_baker(): message_error_java = QCoreApplication.translate( "DialogImportData", """Java could not be found. You can configure the JAVA_HOME environment variable, restart QGIS and try again.""" ) self.txtStdout.setTextColor(QColor('#000000')) self.txtStdout.clear() self.txtStdout.setText(message_error_java) self.show_message(message_error_java, Qgis.Warning) self.enable() self.progress_bar.hide() return self.buttonBox.clear() self.buttonBox.setEnabled(True) self.buttonBox.addButton(QDialogButtonBox.Close) self.progress_bar.setValue(100) self.show_message( QCoreApplication.translate( "DialogImportData", "Import of the data was successfully completed"), Qgis.Success) def remove_create_structure_button(self): for button in self.buttonBox.buttons(): if button.text() == self.BUTTON_NAME_GO_TO_CREATE_STRUCTURE: self.buttonBox.removeButton(button) def save_configuration(self, configuration): settings = QSettings() settings.setValue( 'Asistente-LADM_COL/QgisModelBaker/ili2pg/xtffile_import', configuration.xtffile) settings.setValue('Asistente-LADM_COL/QgisModelBaker/show_log', not self.log_config.isCollapsed()) def restore_configuration(self): settings = QSettings() self.xtf_file_line_edit.setText( settings.value( 'Asistente-LADM_COL/QgisModelBaker/ili2pg/xtffile_import')) # Show log value_show_log = settings.value( 'Asistente-LADM_COL/QgisModelBaker/show_log', False, type=bool) self.log_config.setCollapsed(not value_show_log) # set model repository # if there is no option by default use online model repository self.use_local_models = settings.value( 'Asistente-LADM_COL/models/custom_model_directories_is_checked', type=bool) if self.use_local_models: self.custom_model_directories = settings.value( 'Asistente-LADM_COL/models/custom_models') if settings.value( 'Asistente-LADM_COL/models/custom_models') else None def update_configuration(self): """ Get the configuration that is updated with the user configuration changes on the dialog. :return: Configuration """ item_db = self._conf_db.get_db_items()[self.db.mode] configuration = ImportDataConfiguration() item_db.set_db_configuration_params(self.db.dict_conn_params, configuration) configuration.xtffile = self.xtf_file_line_edit.text().strip() configuration.delete_data = False configuration.epsg = QSettings().value( 'Asistente-LADM_COL/advanced_settings/epsg', int(DEFAULT_EPSG), int) configuration.inheritance = DEFAULT_INHERITANCE configuration.create_basket_col = CREATE_BASKET_COL configuration.create_import_tid = CREATE_IMPORT_TID configuration.stroke_arcs = STROKE_ARCS java_path = get_java_path_from_qgis_model_baker() if java_path: self.base_configuration.java_path = java_path # Check custom model directories if self.use_local_models: if self.custom_model_directories is None: self.base_configuration.custom_model_directories_enabled = False else: self.base_configuration.custom_model_directories = self.custom_model_directories self.base_configuration.custom_model_directories_enabled = True configuration.base_configuration = self.base_configuration if self.get_ili_models(): configuration.ilimodels = ';'.join(self.get_ili_models()) configuration.disable_validation = not QSettings().value( 'Asistente-LADM_COL/advanced_settings/validate_data_importing_exporting', True, bool) return configuration def print_info(self, text, text_color='#000000', clear=False): self.txtStdout.setTextColor(QColor(text_color)) self.txtStdout.append(text) QCoreApplication.processEvents() def on_stderr(self, text): color_log_text(text, self.txtStdout) self.advance_progress_bar_by_text(text) def on_process_started(self, command): self.disable() self.txtStdout.setTextColor(QColor('#000000')) self.txtStdout.clear() self.txtStdout.setText(command) QCoreApplication.processEvents() def on_process_finished(self, exit_code, result): color = '#004905' if exit_code == 0 else '#aa2222' self.txtStdout.setTextColor(QColor(color)) self.txtStdout.append('Finished ({})'.format(exit_code)) if result == iliimporter.Importer.SUCCESS: self.buttonBox.clear() self.buttonBox.setEnabled(True) self.buttonBox.addButton(QDialogButtonBox.Close) else: self.show_message( QCoreApplication.translate("DialogImportData", "Error when importing data"), Qgis.Warning) self.enable() # Open log if self.log_config.isCollapsed(): self.log_config.setCollapsed(False) def advance_progress_bar_by_text(self, text): if text.strip() == 'Info: compile models...': self.progress_bar.setValue(50) QCoreApplication.processEvents() elif text.strip() == 'Info: create table structure...': self.progress_bar.setValue(55) QCoreApplication.processEvents() elif text.strip() == 'Info: first validation pass...': self.progress_bar.setValue(60) QCoreApplication.processEvents() elif text.strip() == 'Info: second validation pass...': self.progress_bar.setValue(80) QCoreApplication.processEvents() def show_help(self): self.qgis_utils.show_help("import_data") def disable(self): self.db_config.setEnabled(False) self.ili_config.setEnabled(False) self.buttonBox.setEnabled(False) def enable(self): self.db_config.setEnabled(True) self.ili_config.setEnabled(True) self.buttonBox.setEnabled(True) def show_message(self, message, level): self.bar.pushMessage("Asistente LADM_COL", message, level, duration=0)
def setupUi(self): self.labels = {} self.widgets = {} self.checkBoxes = {} self.showAdvanced = False self.wrappers = {} self.valueItems = {} self.dependentItems = {} self.resize(650, 450) self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok | QDialogButtonBox.Help) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.verticalLayout = QVBoxLayout() self.verticalLayout.setSpacing(5) self.verticalLayout.setMargin(20) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.verticalLayout.addWidget(self.bar) hLayout = QHBoxLayout() hLayout.setSpacing(5) hLayout.setMargin(0) descriptionLabel = QLabel(self.tr("Description")) self.descriptionBox = QLineEdit() self.descriptionBox.setText(self._alg.displayName()) hLayout.addWidget(descriptionLabel) hLayout.addWidget(self.descriptionBox) self.verticalLayout.addLayout(hLayout) line = QFrame() line.setFrameShape(QFrame.HLine) line.setFrameShadow(QFrame.Sunken) self.verticalLayout.addWidget(line) for param in self._alg.parameterDefinitions(): if param.flags() & QgsProcessingParameterDefinition.FlagAdvanced: self.advancedButton = QPushButton() self.advancedButton.setText( self.tr('Show advanced parameters')) self.advancedButton.clicked.connect( self.showAdvancedParametersClicked) advancedButtonHLayout = QHBoxLayout() advancedButtonHLayout.addWidget(self.advancedButton) advancedButtonHLayout.addStretch() self.verticalLayout.addLayout(advancedButtonHLayout) break for param in self._alg.parameterDefinitions(): if param.isDestination( ) or param.flags() & QgsProcessingParameterDefinition.FlagHidden: continue desc = param.description() if isinstance(param, QgsProcessingParameterExtent): desc += self.tr('(xmin, xmax, ymin, ymax)') if isinstance(param, QgsProcessingParameterPoint): desc += self.tr('(x, y)') if param.flags() & QgsProcessingParameterDefinition.FlagOptional: desc += self.tr(' [optional]') label = QLabel(desc) self.labels[param.name()] = label wrapper = WidgetWrapperFactory.create_wrapper(param, self) self.wrappers[param.name()] = wrapper widget = wrapper.widget if widget is not None: self.valueItems[param.name()] = widget tooltip = param.description() label.setToolTip(tooltip) widget.setToolTip(tooltip) if param.flags( ) & QgsProcessingParameterDefinition.FlagAdvanced: label.setVisible(self.showAdvanced) widget.setVisible(self.showAdvanced) self.widgets[param.name()] = widget self.verticalLayout.addWidget(label) self.verticalLayout.addWidget(widget) for dest in self._alg.destinationParameterDefinitions(): if dest.flags() & QgsProcessingParameterDefinition.FlagHidden: continue if isinstance(dest, (QgsProcessingParameterRasterDestination, QgsProcessingParameterFeatureSink, QgsProcessingParameterFileDestination, QgsProcessingParameterFolderDestination)): label = QLabel(dest.description()) item = QgsFilterLineEdit() if hasattr(item, 'setPlaceholderText'): item.setPlaceholderText(ModelerParametersDialog.ENTER_NAME) self.verticalLayout.addWidget(label) self.verticalLayout.addWidget(item) self.valueItems[dest.name()] = item label = QLabel(' ') self.verticalLayout.addWidget(label) label = QLabel(self.tr('Parent algorithms')) self.dependenciesPanel = self.getDependenciesPanel() self.verticalLayout.addWidget(label) self.verticalLayout.addWidget(self.dependenciesPanel) self.verticalLayout.addStretch(1000) self.setPreviousValues() self.setWindowTitle(self._alg.displayName()) self.verticalLayout2 = QVBoxLayout() self.verticalLayout2.setSpacing(2) self.verticalLayout2.setMargin(0) self.paramPanel = QWidget() self.paramPanel.setLayout(self.verticalLayout) self.scrollArea = QgsScrollArea() self.scrollArea.setWidget(self.paramPanel) self.scrollArea.setWidgetResizable(True) self.verticalLayout2.addWidget(self.scrollArea) self.verticalLayout2.addWidget(self.buttonBox) self.setLayout(self.verticalLayout2) self.buttonBox.accepted.connect(self.okPressed) self.buttonBox.rejected.connect(self.cancelPressed) self.buttonBox.helpRequested.connect(self.openHelp) QMetaObject.connectSlotsByName(self) for wrapper in list(self.wrappers.values()): wrapper.postInitialize(list(self.wrappers.values()))
class ModelerParametersDialog(QDialog): ENTER_NAME = '[Enter name if this is a final result]' NOT_SELECTED = '[Not selected]' USE_MIN_COVERING_EXTENT = '[Use min covering extent]' def __init__(self, alg, model, algName=None): QDialog.__init__(self) self.setModal(True) # The algorithm to define in this dialog. It is an instance of QgsProcessingModelAlgorithm self._alg = alg # The model this algorithm is going to be added to self.model = model # The name of the algorithm in the model, in case we are editing it and not defining it for the first time self.childId = algName self.setupUi() self.params = None settings = QgsSettings() self.restoreGeometry( settings.value("/Processing/modelParametersDialogGeometry", QByteArray())) def closeEvent(self, event): settings = QgsSettings() settings.setValue("/Processing/modelParametersDialogGeometry", self.saveGeometry()) super(ModelerParametersDialog, self).closeEvent(event) def setupUi(self): self.labels = {} self.widgets = {} self.checkBoxes = {} self.showAdvanced = False self.wrappers = {} self.valueItems = {} self.dependentItems = {} self.resize(650, 450) self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok | QDialogButtonBox.Help) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.verticalLayout = QVBoxLayout() self.verticalLayout.setSpacing(5) self.verticalLayout.setMargin(20) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.verticalLayout.addWidget(self.bar) hLayout = QHBoxLayout() hLayout.setSpacing(5) hLayout.setMargin(0) descriptionLabel = QLabel(self.tr("Description")) self.descriptionBox = QLineEdit() self.descriptionBox.setText(self._alg.displayName()) hLayout.addWidget(descriptionLabel) hLayout.addWidget(self.descriptionBox) self.verticalLayout.addLayout(hLayout) line = QFrame() line.setFrameShape(QFrame.HLine) line.setFrameShadow(QFrame.Sunken) self.verticalLayout.addWidget(line) for param in self._alg.parameterDefinitions(): if param.flags() & QgsProcessingParameterDefinition.FlagAdvanced: self.advancedButton = QPushButton() self.advancedButton.setText( self.tr('Show advanced parameters')) self.advancedButton.clicked.connect( self.showAdvancedParametersClicked) advancedButtonHLayout = QHBoxLayout() advancedButtonHLayout.addWidget(self.advancedButton) advancedButtonHLayout.addStretch() self.verticalLayout.addLayout(advancedButtonHLayout) break for param in self._alg.parameterDefinitions(): if param.isDestination( ) or param.flags() & QgsProcessingParameterDefinition.FlagHidden: continue desc = param.description() if isinstance(param, QgsProcessingParameterExtent): desc += self.tr('(xmin, xmax, ymin, ymax)') if isinstance(param, QgsProcessingParameterPoint): desc += self.tr('(x, y)') if param.flags() & QgsProcessingParameterDefinition.FlagOptional: desc += self.tr(' [optional]') label = QLabel(desc) self.labels[param.name()] = label wrapper = WidgetWrapperFactory.create_wrapper(param, self) self.wrappers[param.name()] = wrapper widget = wrapper.widget if widget is not None: self.valueItems[param.name()] = widget tooltip = param.description() label.setToolTip(tooltip) widget.setToolTip(tooltip) if param.flags( ) & QgsProcessingParameterDefinition.FlagAdvanced: label.setVisible(self.showAdvanced) widget.setVisible(self.showAdvanced) self.widgets[param.name()] = widget self.verticalLayout.addWidget(label) self.verticalLayout.addWidget(widget) for dest in self._alg.destinationParameterDefinitions(): if dest.flags() & QgsProcessingParameterDefinition.FlagHidden: continue if isinstance(dest, (QgsProcessingParameterRasterDestination, QgsProcessingParameterFeatureSink, QgsProcessingParameterFileDestination, QgsProcessingParameterFolderDestination)): label = QLabel(dest.description()) item = QgsFilterLineEdit() if hasattr(item, 'setPlaceholderText'): item.setPlaceholderText(ModelerParametersDialog.ENTER_NAME) self.verticalLayout.addWidget(label) self.verticalLayout.addWidget(item) self.valueItems[dest.name()] = item label = QLabel(' ') self.verticalLayout.addWidget(label) label = QLabel(self.tr('Parent algorithms')) self.dependenciesPanel = self.getDependenciesPanel() self.verticalLayout.addWidget(label) self.verticalLayout.addWidget(self.dependenciesPanel) self.verticalLayout.addStretch(1000) self.setPreviousValues() self.setWindowTitle(self._alg.displayName()) self.verticalLayout2 = QVBoxLayout() self.verticalLayout2.setSpacing(2) self.verticalLayout2.setMargin(0) self.paramPanel = QWidget() self.paramPanel.setLayout(self.verticalLayout) self.scrollArea = QgsScrollArea() self.scrollArea.setWidget(self.paramPanel) self.scrollArea.setWidgetResizable(True) self.verticalLayout2.addWidget(self.scrollArea) self.verticalLayout2.addWidget(self.buttonBox) self.setLayout(self.verticalLayout2) self.buttonBox.accepted.connect(self.okPressed) self.buttonBox.rejected.connect(self.cancelPressed) self.buttonBox.helpRequested.connect(self.openHelp) QMetaObject.connectSlotsByName(self) for wrapper in list(self.wrappers.values()): wrapper.postInitialize(list(self.wrappers.values())) def getAvailableDependencies(self): # spellok if self.childId is None: dependent = [] else: dependent = list(self.model.dependentChildAlgorithms(self.childId)) dependent.append(self.childId) opts = [] for alg in list(self.model.childAlgorithms().values()): if alg.childId() not in dependent: opts.append(alg) return opts def getDependenciesPanel(self): return MultipleInputPanel([ alg.description() for alg in self.getAvailableDependencies() ]) # spellok def showAdvancedParametersClicked(self): self.showAdvanced = not self.showAdvanced if self.showAdvanced: self.advancedButton.setText(self.tr('Hide advanced parameters')) else: self.advancedButton.setText(self.tr('Show advanced parameters')) for param in self._alg.parameterDefinitions(): if param.flags() & QgsProcessingParameterDefinition.FlagAdvanced: self.labels[param.name()].setVisible(self.showAdvanced) self.widgets[param.name()].setVisible(self.showAdvanced) def getAvailableValuesOfType(self, paramType, outTypes=[], dataTypes=[]): # upgrade paramType to list if paramType is None: paramType = [] elif not isinstance(paramType, (tuple, list)): paramType = [paramType] if outTypes is None: outTypes = [] elif not isinstance(outTypes, (tuple, list)): outTypes = [outTypes] return self.model.availableSourcesForChild(self.childId, [ p.typeName() for p in paramType if issubclass(p, QgsProcessingParameterDefinition) ], [ o.typeName() for o in outTypes if issubclass(o, QgsProcessingOutputDefinition) ], dataTypes) def resolveValueDescription(self, value): if isinstance(value, QgsProcessingModelChildParameterSource): if value.source( ) == QgsProcessingModelChildParameterSource.StaticValue: return value.staticValue() elif value.source( ) == QgsProcessingModelChildParameterSource.ModelParameter: return self.model.parameterDefinition( value.parameterName()).description() elif value.source( ) == QgsProcessingModelChildParameterSource.ChildOutput: alg = self.model.childAlgorithm(value.outputChildId()) return self.tr("'{0}' from algorithm '{1}'").format( alg.algorithm().outputDefinition( value.outputName()).description(), alg.description()) return value def setPreviousValues(self): if self.childId is not None: alg = self.model.childAlgorithm(self.childId) self.descriptionBox.setText(alg.description()) for param in alg.algorithm().parameterDefinitions(): if param.isDestination() or param.flags( ) & QgsProcessingParameterDefinition.FlagHidden: continue value = None if param.name() in alg.parameterSources(): value = alg.parameterSources()[param.name()] if isinstance(value, list) and len(value) == 1: value = value[0] elif isinstance(value, list) and len(value) == 0: value = None if value is None: value = param.defaultValue() if isinstance( value, QgsProcessingModelChildParameterSource ) and value.source( ) == QgsProcessingModelChildParameterSource.StaticValue: value = value.staticValue() self.wrappers[param.name()].setValue(value) for name, out in list(alg.modelOutputs().items()): if out.childOutputName() in self.valueItems: self.valueItems[out.childOutputName()].setText(out.name()) selected = [] dependencies = self.getAvailableDependencies() # spellok for idx, dependency in enumerate(dependencies): if dependency.childId() in alg.dependencies(): selected.append(idx) self.dependenciesPanel.setSelectedItems(selected) def createAlgorithm(self): alg = QgsProcessingModelChildAlgorithm(self._alg.id()) if not self.childId: alg.generateChildId(self.model) else: alg.setChildId(self.childId) alg.setDescription(self.descriptionBox.text()) for param in self._alg.parameterDefinitions(): if param.isDestination( ) or param.flags() & QgsProcessingParameterDefinition.FlagHidden: continue try: val = self.wrappers[param.name()].value() except InvalidParameterValue: self.bar.pushMessage( self.tr("Error"), self.tr( "Wrong or missing value for parameter '{}'").format( param.description()), level=QgsMessageBar.WARNING) return None if isinstance(val, QgsProcessingModelChildParameterSource): val = [val] elif not (isinstance(val, list) and all([ isinstance(subval, QgsProcessingModelChildParameterSource) for subval in val ])): val = [ QgsProcessingModelChildParameterSource.fromStaticValue(val) ] for subval in val: if (isinstance(subval, QgsProcessingModelChildParameterSource) and subval.source() == QgsProcessingModelChildParameterSource.StaticValue and not param.checkValueIsAcceptable(subval.staticValue())) \ or (subval is None and not param.flags() & QgsProcessingParameterDefinition.FlagOptional): self.bar.pushMessage( self.tr("Error"), self.tr("Wrong or missing value for parameter '{}'" ).format(param.description()), level=QgsMessageBar.WARNING) return None alg.addParameterSources(param.name(), val) outputs = {} for dest in self._alg.destinationParameterDefinitions(): if not dest.flags() & QgsProcessingParameterDefinition.FlagHidden: name = str(self.valueItems[dest.name()].text()) if name.strip( ) != '' and name != ModelerParametersDialog.ENTER_NAME: output = QgsProcessingModelOutput(name, name) output.setChildId(alg.childId()) output.setChildOutputName(dest.name()) outputs[name] = output alg.setModelOutputs(outputs) selectedOptions = self.dependenciesPanel.selectedoptions availableDependencies = self.getAvailableDependencies() # spellok dep_ids = [] for selected in selectedOptions: dep_ids.append( availableDependencies[selected].childId()) # spellok alg.setDependencies(dep_ids) #try: # self._alg.processBeforeAddingToModeler(alg, self.model) #except: # pass return alg def okPressed(self): alg = self.createAlgorithm() if alg is not None: self.accept() def cancelPressed(self): self.reject() def openHelp(self): algHelp = self._alg.helpUrl() if not algHelp: algHelp = QgsHelp.helpUrl("processing_algs/{}/{}.html{}".format( self._alg.provider().id(), self._alg.groupId(), self._alg.name())).toString() if algHelp not in [None, ""]: webbrowser.open(algHelp)
class ModelerDialog(BASE, WIDGET): ALG_ITEM = 'ALG_ITEM' PROVIDER_ITEM = 'PROVIDER_ITEM' GROUP_ITEM = 'GROUP_ITEM' NAME_ROLE = Qt.UserRole TAG_ROLE = Qt.UserRole + 1 TYPE_ROLE = Qt.UserRole + 2 CANVAS_SIZE = 4000 update_model = pyqtSignal() def __init__(self, model=None): super().__init__(None) self.setAttribute(Qt.WA_DeleteOnClose) self.setupUi(self) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.centralWidget().layout().insertWidget(0, self.bar) try: self.setDockOptions(self.dockOptions() | QMainWindow.GroupedDragging) except: pass self.mToolbar.setIconSize(iface.iconSize()) self.mActionOpen.setIcon( QgsApplication.getThemeIcon('/mActionFileOpen.svg')) self.mActionSave.setIcon( QgsApplication.getThemeIcon('/mActionFileSave.svg')) self.mActionSaveAs.setIcon( QgsApplication.getThemeIcon('/mActionFileSaveAs.svg')) self.mActionZoomActual.setIcon( QgsApplication.getThemeIcon('/mActionZoomActual.svg')) self.mActionZoomIn.setIcon( QgsApplication.getThemeIcon('/mActionZoomIn.svg')) self.mActionZoomOut.setIcon( QgsApplication.getThemeIcon('/mActionZoomOut.svg')) self.mActionExportImage.setIcon( QgsApplication.getThemeIcon('/mActionSaveMapAsImage.svg')) self.mActionZoomToItems.setIcon( QgsApplication.getThemeIcon('/mActionZoomFullExtent.svg')) self.mActionExportPdf.setIcon( QgsApplication.getThemeIcon('/mActionSaveAsPDF.svg')) self.mActionExportSvg.setIcon( QgsApplication.getThemeIcon('/mActionSaveAsSVG.svg')) #self.mActionExportPython.setIcon( # QgsApplication.getThemeIcon('/mActionSaveAsPython.svg')) self.mActionEditHelp.setIcon( QgsApplication.getThemeIcon('/mActionEditHelpContent.svg')) self.mActionRun.setIcon( QgsApplication.getThemeIcon('/mActionStart.svg')) self.addDockWidget(Qt.LeftDockWidgetArea, self.propertiesDock) self.addDockWidget(Qt.LeftDockWidgetArea, self.inputsDock) self.addDockWidget(Qt.LeftDockWidgetArea, self.algorithmsDock) self.tabifyDockWidget(self.inputsDock, self.algorithmsDock) self.inputsDock.raise_() self.zoom = 1 self.setWindowFlags(Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint | Qt.WindowCloseButtonHint) settings = QgsSettings() self.restoreState( settings.value("/Processing/stateModeler", QByteArray())) self.restoreGeometry( settings.value("/Processing/geometryModeler", QByteArray())) self.scene = ModelerScene(self, dialog=self) self.scene.setSceneRect( QRectF(0, 0, self.CANVAS_SIZE, self.CANVAS_SIZE)) self.view.setScene(self.scene) self.view.setAcceptDrops(True) self.view.ensureVisible(0, 0, 10, 10) def _dragEnterEvent(event): if event.mimeData().hasText(): event.acceptProposedAction() else: event.ignore() def _dropEvent(event): if event.mimeData().hasText(): itemId = event.mimeData().text() if itemId in [ param.id() for param in QgsApplication.instance(). processingRegistry().parameterTypes() ]: self.addInputOfType(itemId, event.pos()) else: alg = QgsApplication.processingRegistry( ).createAlgorithmById(itemId) if alg is not None: self._addAlgorithm(alg, event.pos()) event.accept() else: event.ignore() def _dragMoveEvent(event): if event.mimeData().hasText(): event.accept() else: event.ignore() def _wheelEvent(event): self.view.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) settings = QgsSettings() factor = settings.value('/qgis/zoom_favor', 2.0) # "Normal" mouse has an angle delta of 120, precision mouses provide data # faster, in smaller steps factor = 1.0 + (factor - 1.0) / 120.0 * abs(event.angleDelta().y()) if (event.modifiers() == Qt.ControlModifier): factor = 1.0 + (factor - 1.0) / 20.0 if event.angleDelta().y() < 0: factor = 1 / factor self.view.scale(factor, factor) def _enterEvent(e): QGraphicsView.enterEvent(self.view, e) self.view.viewport().setCursor(Qt.ArrowCursor) def _mouseReleaseEvent(e): QGraphicsView.mouseReleaseEvent(self.view, e) self.view.viewport().setCursor(Qt.ArrowCursor) def _mousePressEvent(e): if e.button() == Qt.MidButton: self.previousMousePos = e.pos() else: QGraphicsView.mousePressEvent(self.view, e) def _mouseMoveEvent(e): if e.buttons() == Qt.MidButton: offset = self.previousMousePos - e.pos() self.previousMousePos = e.pos() self.view.verticalScrollBar().setValue( self.view.verticalScrollBar().value() + offset.y()) self.view.horizontalScrollBar().setValue( self.view.horizontalScrollBar().value() + offset.x()) else: QGraphicsView.mouseMoveEvent(self.view, e) self.view.setDragMode(QGraphicsView.ScrollHandDrag) self.view.dragEnterEvent = _dragEnterEvent self.view.dropEvent = _dropEvent self.view.dragMoveEvent = _dragMoveEvent self.view.wheelEvent = _wheelEvent self.view.enterEvent = _enterEvent self.view.mousePressEvent = _mousePressEvent self.view.mouseMoveEvent = _mouseMoveEvent def _mimeDataInput(items): mimeData = QMimeData() text = items[0].data(0, Qt.UserRole) mimeData.setText(text) return mimeData self.inputsTree.mimeData = _mimeDataInput self.inputsTree.setDragDropMode(QTreeWidget.DragOnly) self.inputsTree.setDropIndicatorShown(True) def _mimeDataAlgorithm(items): item = items[0] mimeData = None if isinstance(item, TreeAlgorithmItem): mimeData = QMimeData() mimeData.setText(item.alg.id()) return mimeData self.algorithmTree.mimeData = _mimeDataAlgorithm self.algorithmTree.setDragDropMode(QTreeWidget.DragOnly) self.algorithmTree.setDropIndicatorShown(True) if hasattr(self.searchBox, 'setPlaceholderText'): self.searchBox.setPlaceholderText( QCoreApplication.translate('ModelerDialog', 'Search…')) if hasattr(self.textName, 'setPlaceholderText'): self.textName.setPlaceholderText(self.tr('Enter model name here')) if hasattr(self.textGroup, 'setPlaceholderText'): self.textGroup.setPlaceholderText(self.tr('Enter group name here')) # Connect signals and slots self.inputsTree.doubleClicked.connect(self.addInput) self.searchBox.textChanged.connect(self.textChanged) self.algorithmTree.doubleClicked.connect(self.addAlgorithm) # Ctrl+= should also trigger a zoom in action ctrlEquals = QShortcut(QKeySequence("Ctrl+="), self) ctrlEquals.activated.connect(self.zoomIn) self.mActionOpen.triggered.connect(self.openModel) self.mActionSave.triggered.connect(self.save) self.mActionSaveAs.triggered.connect(self.saveAs) self.mActionZoomIn.triggered.connect(self.zoomIn) self.mActionZoomOut.triggered.connect(self.zoomOut) self.mActionZoomActual.triggered.connect(self.zoomActual) self.mActionZoomToItems.triggered.connect(self.zoomToItems) self.mActionExportImage.triggered.connect(self.exportAsImage) self.mActionExportPdf.triggered.connect(self.exportAsPdf) self.mActionExportSvg.triggered.connect(self.exportAsSvg) #self.mActionExportPython.triggered.connect(self.exportAsPython) self.mActionEditHelp.triggered.connect(self.editHelp) self.mActionRun.triggered.connect(self.runModel) if model is not None: self.model = model.create() self.model.setSourceFilePath(model.sourceFilePath()) self.textGroup.setText(self.model.group()) self.textName.setText(self.model.displayName()) self.repaintModel() else: self.model = QgsProcessingModelAlgorithm() self.model.setProvider( QgsApplication.processingRegistry().providerById('model')) self.fillInputsTree() self.fillTreeUsingProviders() self.view.centerOn(0, 0) self.help = None self.hasChanged = False def closeEvent(self, evt): settings = QgsSettings() settings.setValue("/Processing/stateModeler", self.saveState()) settings.setValue("/Processing/geometryModeler", self.saveGeometry()) if self.hasChanged: ret = QMessageBox.question( self, self.tr('Save Model?'), self. tr('There are unsaved changes in this model. Do you want to keep those?' ), QMessageBox.Save | QMessageBox.Cancel | QMessageBox.Discard, QMessageBox.Cancel) if ret == QMessageBox.Save: self.saveModel(False) evt.accept() elif ret == QMessageBox.Discard: evt.accept() else: evt.ignore() else: evt.accept() def editHelp(self): alg = self.model dlg = HelpEditionDialog(alg) dlg.exec_() if dlg.descriptions: self.model.setHelpContent(dlg.descriptions) self.hasChanged = True def runModel(self): if len(self.model.childAlgorithms()) == 0: self.bar.pushMessage( "", self. tr("Model doesn't contain any algorithm and/or parameter and can't be executed" ), level=Qgis.Warning, duration=5) return dlg = AlgorithmDialog(self.model) dlg.exec_() def save(self): self.saveModel(False) def saveAs(self): self.saveModel(True) def zoomIn(self): self.view.setTransformationAnchor(QGraphicsView.NoAnchor) point = self.view.mapToScene( QPoint(self.view.viewport().width() / 2, self.view.viewport().height() / 2)) settings = QgsSettings() factor = settings.value('/qgis/zoom_favor', 2.0) self.view.scale(factor, factor) self.view.centerOn(point) self.repaintModel() def zoomOut(self): self.view.setTransformationAnchor(QGraphicsView.NoAnchor) point = self.view.mapToScene( QPoint(self.view.viewport().width() / 2, self.view.viewport().height() / 2)) settings = QgsSettings() factor = settings.value('/qgis/zoom_favor', 2.0) factor = 1 / factor self.view.scale(factor, factor) self.view.centerOn(point) self.repaintModel() def zoomActual(self): point = self.view.mapToScene( QPoint(self.view.viewport().width() / 2, self.view.viewport().height() / 2)) self.view.resetTransform() self.view.centerOn(point) def zoomToItems(self): totalRect = self.scene.itemsBoundingRect() totalRect.adjust(-10, -10, 10, 10) self.view.fitInView(totalRect, Qt.KeepAspectRatio) def exportAsImage(self): self.repaintModel(controls=False) filename, fileFilter = QFileDialog.getSaveFileName( self, self.tr('Save Model As Image'), '', self.tr('PNG files (*.png *.PNG)')) if not filename: return if not filename.lower().endswith('.png'): filename += '.png' totalRect = self.scene.itemsBoundingRect() totalRect.adjust(-10, -10, 10, 10) imgRect = QRectF(0, 0, totalRect.width(), totalRect.height()) img = QImage(totalRect.width(), totalRect.height(), QImage.Format_ARGB32_Premultiplied) img.fill(Qt.white) painter = QPainter() painter.setRenderHint(QPainter.Antialiasing) painter.begin(img) self.scene.render(painter, imgRect, totalRect) painter.end() img.save(filename) self.bar.pushMessage("", self.tr("Model was correctly exported as image"), level=Qgis.Success, duration=5) self.repaintModel(controls=True) def exportAsPdf(self): self.repaintModel(controls=False) filename, fileFilter = QFileDialog.getSaveFileName( self, self.tr('Save Model As PDF'), '', self.tr('PDF files (*.pdf *.PDF)')) if not filename: return if not filename.lower().endswith('.pdf'): filename += '.pdf' totalRect = self.scene.itemsBoundingRect() totalRect.adjust(-10, -10, 10, 10) printerRect = QRectF(0, 0, totalRect.width(), totalRect.height()) printer = QPrinter() printer.setOutputFormat(QPrinter.PdfFormat) printer.setOutputFileName(filename) printer.setPaperSize(QSizeF(printerRect.width(), printerRect.height()), QPrinter.DevicePixel) printer.setFullPage(True) painter = QPainter(printer) self.scene.render(painter, printerRect, totalRect) painter.end() self.bar.pushMessage("", self.tr("Model was correctly exported as PDF"), level=Qgis.Success, duration=5) self.repaintModel(controls=True) def exportAsSvg(self): self.repaintModel(controls=False) filename, fileFilter = QFileDialog.getSaveFileName( self, self.tr('Save Model As SVG'), '', self.tr('SVG files (*.svg *.SVG)')) if not filename: return if not filename.lower().endswith('.svg'): filename += '.svg' totalRect = self.scene.itemsBoundingRect() totalRect.adjust(-10, -10, 10, 10) svgRect = QRectF(0, 0, totalRect.width(), totalRect.height()) svg = QSvgGenerator() svg.setFileName(filename) svg.setSize(QSize(totalRect.width(), totalRect.height())) svg.setViewBox(svgRect) svg.setTitle(self.model.displayName()) painter = QPainter(svg) self.scene.render(painter, svgRect, totalRect) painter.end() self.bar.pushMessage("", self.tr("Model was correctly exported as SVG"), level=Qgis.Success, duration=5) self.repaintModel(controls=True) def exportAsPython(self): filename, filter = QFileDialog.getSaveFileName( self, self.tr('Save Model As Python Script'), '', self.tr('Python files (*.py *.PY)')) if not filename: return if not filename.lower().endswith('.py'): filename += '.py' text = self.model.asPythonCode() with codecs.open(filename, 'w', encoding='utf-8') as fout: fout.write(text) self.bar.pushMessage( "", self.tr("Model was correctly exported as python script"), level=Qgis.Success, duration=5) def saveModel(self, saveAs): if str(self.textGroup.text()).strip() == '' \ or str(self.textName.text()).strip() == '': QMessageBox.warning( self, self.tr('Warning'), self.tr('Please enter group and model names before saving')) return self.model.setName(str(self.textName.text())) self.model.setGroup(str(self.textGroup.text())) if self.model.sourceFilePath() and not saveAs: filename = self.model.sourceFilePath() else: filename, filter = QFileDialog.getSaveFileName( self, self.tr('Save Model'), ModelerUtils.modelsFolders()[0], self.tr('Processing models (*.model3)')) if filename: if not filename.endswith('.model3'): filename += '.model3' self.model.setSourceFilePath(filename) if filename: if not self.model.toFile(filename): if saveAs: QMessageBox.warning( self, self.tr('I/O error'), self.tr('Unable to save edits. Reason:\n {0}').format( str(sys.exc_info()[1]))) else: QMessageBox.warning( self, self.tr("Can't save model"), QCoreApplication. translate('QgsPluginInstallerInstallingDialog', ( "This model can't be saved in its original location (probably you do not " "have permission to do it). Please, use the 'Save as…' option." ))) return self.update_model.emit() self.bar.pushMessage("", self.tr("Model was correctly saved"), level=Qgis.Success, duration=5) self.hasChanged = False def openModel(self): filename, selected_filter = QFileDialog.getOpenFileName( self, self.tr('Open Model'), ModelerUtils.modelsFolders()[0], self.tr('Processing models (*.model3 *.MODEL3)')) if filename: self.loadModel(filename) def loadModel(self, filename): alg = QgsProcessingModelAlgorithm() if alg.fromFile(filename): self.model = alg self.model.setProvider( QgsApplication.processingRegistry().providerById('model')) self.textGroup.setText(alg.group()) self.textName.setText(alg.name()) self.repaintModel() self.view.centerOn(0, 0) self.hasChanged = False else: QgsMessageLog.logMessage( self.tr('Could not load model {0}').format(filename), self.tr('Processing'), Qgis.Critical) QMessageBox.critical( self, self.tr('Open Model'), self.tr('The selected model could not be loaded.\n' 'See the log for more information.')) def repaintModel(self, controls=True): self.scene = ModelerScene(self, dialog=self) self.scene.setSceneRect( QRectF(0, 0, self.CANVAS_SIZE, self.CANVAS_SIZE)) self.scene.paintModel(self.model, controls) self.view.setScene(self.scene) def addInput(self): item = self.inputsTree.currentItem() param = item.data(0, Qt.UserRole) self.addInputOfType(param) def addInputOfType(self, paramType, pos=None): dlg = ModelerParameterDefinitionDialog(self.model, paramType) dlg.exec_() if dlg.param is not None: if pos is None: pos = self.getPositionForParameterItem() if isinstance(pos, QPoint): pos = QPointF(pos) component = QgsProcessingModelParameter(dlg.param.name()) component.setDescription(dlg.param.name()) component.setPosition(pos) self.model.addModelParameter(dlg.param, component) self.repaintModel() # self.view.ensureVisible(self.scene.getLastParameterItem()) self.hasChanged = True def getPositionForParameterItem(self): MARGIN = 20 BOX_WIDTH = 200 BOX_HEIGHT = 80 if len(self.model.parameterComponents()) > 0: maxX = max([ i.position().x() for i in list(self.model.parameterComponents().values()) ]) newX = min(MARGIN + BOX_WIDTH + maxX, self.CANVAS_SIZE - BOX_WIDTH) else: newX = MARGIN + BOX_WIDTH / 2 return QPointF(newX, MARGIN + BOX_HEIGHT / 2) def textChanged(self): text = self.searchBox.text().strip(' ').lower() for item in list(self.disabledProviderItems.values()): item.setHidden(True) self._filterItem(self.algorithmTree.invisibleRootItem(), [t for t in text.split(' ') if t]) if text: self.algorithmTree.expandAll() self.disabledWithMatchingAlgs = [] for provider in QgsApplication.processingRegistry().providers(): if not provider.isActive(): for alg in provider.algorithms(): if text in alg.name(): self.disabledWithMatchingAlgs.append(provider.id()) break else: self.algorithmTree.collapseAll() def _filterItem(self, item, text): if (item.childCount() > 0): show = False for i in range(item.childCount()): child = item.child(i) showChild = self._filterItem(child, text) show = (showChild or show) and item not in list( self.disabledProviderItems.values()) item.setHidden(not show) return show elif isinstance(item, (TreeAlgorithmItem, TreeActionItem)): # hide if every part of text is not contained somewhere in either the item text or item user role item_text = [ item.text(0).lower(), item.data(0, ModelerDialog.NAME_ROLE).lower() ] if isinstance(item, TreeAlgorithmItem): item_text.append(item.alg.id()) item_text.extend(item.data(0, ModelerDialog.TAG_ROLE)) hide = bool(text) and not all( any(part in t for t in item_text) for part in text) item.setHidden(hide) return not hide else: item.setHidden(True) return False def fillInputsTree(self): icon = QIcon(os.path.join(pluginPath, 'images', 'input.svg')) parametersItem = QTreeWidgetItem() parametersItem.setText(0, self.tr('Parameters')) sortedParams = sorted( QgsApplication.instance().processingRegistry().parameterTypes(), key=lambda pt: pt.name()) for param in sortedParams: if param.flags() & QgsProcessingParameterType.ExposeToModeler: paramItem = QTreeWidgetItem() paramItem.setText(0, param.name()) paramItem.setData(0, Qt.UserRole, param.id()) paramItem.setIcon(0, icon) paramItem.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled) paramItem.setToolTip(0, param.description()) parametersItem.addChild(paramItem) self.inputsTree.addTopLevelItem(parametersItem) parametersItem.setExpanded(True) def addAlgorithm(self): item = self.algorithmTree.currentItem() if isinstance(item, TreeAlgorithmItem): alg = QgsApplication.processingRegistry().createAlgorithmById( item.alg.id()) self._addAlgorithm(alg) def _addAlgorithm(self, alg, pos=None): dlg = ModelerParametersDialog(alg, self.model) if dlg.exec_(): alg = dlg.createAlgorithm() if pos is None: alg.setPosition(self.getPositionForAlgorithmItem()) else: alg.setPosition(pos) from processing.modeler.ModelerGraphicItem import ModelerGraphicItem for i, out in enumerate(alg.modelOutputs()): alg.modelOutput(out).setPosition( alg.position() + QPointF(ModelerGraphicItem.BOX_WIDTH, (i + 1.5) * ModelerGraphicItem.BOX_HEIGHT)) self.model.addChildAlgorithm(alg) self.repaintModel() self.hasChanged = True def getPositionForAlgorithmItem(self): MARGIN = 20 BOX_WIDTH = 200 BOX_HEIGHT = 80 if self.model.childAlgorithms(): maxX = max([ alg.position().x() for alg in list(self.model.childAlgorithms().values()) ]) maxY = max([ alg.position().y() for alg in list(self.model.childAlgorithms().values()) ]) newX = min(MARGIN + BOX_WIDTH + maxX, self.CANVAS_SIZE - BOX_WIDTH) newY = min(MARGIN + BOX_HEIGHT + maxY, self.CANVAS_SIZE - BOX_HEIGHT) else: newX = MARGIN + BOX_WIDTH / 2 newY = MARGIN * 2 + BOX_HEIGHT + BOX_HEIGHT / 2 return QPointF(newX, newY) def fillTreeUsingProviders(self): self.algorithmTree.clear() self.disabledProviderItems = {} # TODO - replace with proper model for toolbox! # first add qgis/native providers, since they create top level groups for provider in QgsApplication.processingRegistry().providers(): if provider.id() in ('qgis', 'native', '3d'): self.addAlgorithmsFromProvider( provider, self.algorithmTree.invisibleRootItem()) else: continue self.algorithmTree.sortItems(0, Qt.AscendingOrder) for provider in QgsApplication.processingRegistry().providers(): if provider.id() in ('qgis', 'native', '3d'): # already added continue else: providerItem = TreeProviderItem(provider, self.algorithmTree, self) # insert non-native providers at end of tree, alphabetically for i in range( self.algorithmTree.invisibleRootItem().childCount()): child = self.algorithmTree.invisibleRootItem().child(i) if isinstance(child, TreeProviderItem): if child.text(0) > providerItem.text(0): break self.algorithmTree.insertTopLevelItem(i + 1, providerItem) if not provider.isActive(): providerItem.setHidden(True) self.disabledProviderItems[provider.id()] = providerItem def addAlgorithmsFromProvider(self, provider, parent): groups = {} count = 0 algs = provider.algorithms() active = provider.isActive() # Add algorithms for alg in algs: if alg.flags() & QgsProcessingAlgorithm.FlagHideFromModeler: continue groupItem = None if alg.group() in groups: groupItem = groups[alg.group()] else: # check if group already exists for i in range(parent.childCount()): if parent.child(i).text(0) == alg.group(): groupItem = parent.child(i) groups[alg.group()] = groupItem break if not groupItem: groupItem = TreeGroupItem(alg.group()) if not active: groupItem.setInactive() if provider.id() in ('qgis', 'native', '3d'): groupItem.setIcon(0, provider.icon()) groups[alg.group()] = groupItem algItem = TreeAlgorithmItem(alg) if not active: algItem.setForeground(0, Qt.darkGray) groupItem.addChild(algItem) count += 1 text = provider.name() if not provider.id() in ('qgis', 'native', '3d'): if not active: def activateProvider(): self.activateProvider(provider.id()) label = QLabel( text + " <a href='%s'>Activate</a>") label.setStyleSheet( "QLabel {background-color: white; color: grey;}") label.linkActivated.connect(activateProvider) self.algorithmTree.setItemWidget(parent, 0, label) else: parent.setText(0, text) for group, groupItem in sorted(groups.items(), key=operator.itemgetter(1)): parent.addChild(groupItem) if not provider.id() in ('qgis', 'native', '3d'): parent.setHidden(parent.childCount() == 0)
def __init__(self, iface, db, qgis_utils): QDialog.__init__(self) self.setupUi(self) QgsGui.instance().enableAutoGeometryRestore(self) self.iface = iface self.db = db self.qgis_utils = qgis_utils self.base_configuration = BaseConfiguration() self.ilicache = IliCache(self.base_configuration) self.ilicache.refresh() self._conf_db = ConfigDbSupported() self._params = None self._current_db = None self.xtf_file_browse_button.clicked.connect( make_save_file_selector( self.xtf_file_line_edit, title=QCoreApplication.translate("DialogExportData", "Save in XTF Transfer File"), file_filter=QCoreApplication.translate( "DialogExportData", "XTF Transfer File (*.xtf);;Interlis 1 Transfer File (*.itf);;XML (*.xml);;GML (*.gml)" ), extension='.xtf', extensions=['.' + ext for ext in self.ValidExtensions])) self.xtf_file_browse_button.clicked.connect( self.xtf_browser_opened_to_true) self.xtf_browser_was_opened = False self.validators = Validators() fileValidator = FileValidator( pattern=['*.' + ext for ext in self.ValidExtensions], allow_non_existing=True) self.xtf_file_line_edit.setPlaceholderText( QCoreApplication.translate("DialogExportData", "[Name of the XTF to be created]")) self.xtf_file_line_edit.setValidator(fileValidator) self.xtf_file_line_edit.textChanged.connect( self.validators.validate_line_edits) self.xtf_file_line_edit.textChanged.connect( self.xtf_browser_opened_to_false) self.xtf_file_line_edit.textChanged.emit( self.xtf_file_line_edit.text()) self.connection_setting_button.clicked.connect(self.show_settings) self.connection_setting_button.setText( QCoreApplication.translate("DialogExportData", "Connection Settings")) # LOG self.log_config.setTitle( QCoreApplication.translate("DialogExportData", "Show log")) self.log_config.setFlat(True) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().addWidget(self.bar, 0, 0, Qt.AlignTop) self.buttonBox.accepted.disconnect() self.buttonBox.accepted.connect(self.accepted) self.buttonBox.clear() self.buttonBox.addButton(QDialogButtonBox.Cancel) self._accept_button = self.buttonBox.addButton( QCoreApplication.translate("DialogExportData", "Export data"), QDialogButtonBox.AcceptRole) self.buttonBox.addButton(QDialogButtonBox.Help) self.buttonBox.helpRequested.connect(self.show_help) self.update_connection_info() self.update_model_names() self.restore_configuration()
class DialogExportData(QDialog, DIALOG_UI): ValidExtensions = ['xtf', 'itf', 'gml', 'xml'] current_row_schema = 0 def __init__(self, iface, db, qgis_utils): QDialog.__init__(self) self.setupUi(self) QgsGui.instance().enableAutoGeometryRestore(self) self.iface = iface self.db = db self.qgis_utils = qgis_utils self.base_configuration = BaseConfiguration() self.ilicache = IliCache(self.base_configuration) self.ilicache.refresh() self._conf_db = ConfigDbSupported() self._params = None self._current_db = None self.xtf_file_browse_button.clicked.connect( make_save_file_selector( self.xtf_file_line_edit, title=QCoreApplication.translate("DialogExportData", "Save in XTF Transfer File"), file_filter=QCoreApplication.translate( "DialogExportData", "XTF Transfer File (*.xtf);;Interlis 1 Transfer File (*.itf);;XML (*.xml);;GML (*.gml)" ), extension='.xtf', extensions=['.' + ext for ext in self.ValidExtensions])) self.xtf_file_browse_button.clicked.connect( self.xtf_browser_opened_to_true) self.xtf_browser_was_opened = False self.validators = Validators() fileValidator = FileValidator( pattern=['*.' + ext for ext in self.ValidExtensions], allow_non_existing=True) self.xtf_file_line_edit.setPlaceholderText( QCoreApplication.translate("DialogExportData", "[Name of the XTF to be created]")) self.xtf_file_line_edit.setValidator(fileValidator) self.xtf_file_line_edit.textChanged.connect( self.validators.validate_line_edits) self.xtf_file_line_edit.textChanged.connect( self.xtf_browser_opened_to_false) self.xtf_file_line_edit.textChanged.emit( self.xtf_file_line_edit.text()) self.connection_setting_button.clicked.connect(self.show_settings) self.connection_setting_button.setText( QCoreApplication.translate("DialogExportData", "Connection Settings")) # LOG self.log_config.setTitle( QCoreApplication.translate("DialogExportData", "Show log")) self.log_config.setFlat(True) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().addWidget(self.bar, 0, 0, Qt.AlignTop) self.buttonBox.accepted.disconnect() self.buttonBox.accepted.connect(self.accepted) self.buttonBox.clear() self.buttonBox.addButton(QDialogButtonBox.Cancel) self._accept_button = self.buttonBox.addButton( QCoreApplication.translate("DialogExportData", "Export data"), QDialogButtonBox.AcceptRole) self.buttonBox.addButton(QDialogButtonBox.Help) self.buttonBox.helpRequested.connect(self.show_help) self.update_connection_info() self.update_model_names() self.restore_configuration() def update_connection_info(self): db_description = self.db.get_description_conn_string() if db_description: self.db_connect_label.setText(db_description) self.db_connect_label.setToolTip(self.db.get_display_conn_string()) self._accept_button.setEnabled(True) else: self.db_connect_label.setText( QCoreApplication.translate("DialogExportData", "The database is not defined!")) self.db_connect_label.setToolTip('') self._accept_button.setEnabled(False) def update_model_names(self): self.export_models_qmodel = QStandardItemModel() db_models = None db_models = self.db.get_models() if db_models: for db_model in db_models: regex = re.compile(r'(?:\{[^\}]*\}|\s)') for modelname in regex.split(db_model['modelname']): if modelname and modelname not in DEFAULT_HIDDEN_MODELS: item = QStandardItem(modelname.strip()) item.setCheckable(False) item.setEditable(False) self.export_models_qmodel.appendRow(item) self.export_models_list_view.setModel(self.export_models_qmodel) def get_ili_models(self): ili_models = list() for index in range(self.export_models_qmodel.rowCount()): item = self.export_models_qmodel.item(index) ili_models.append(item.text()) return ili_models def show_settings(self): dlg = self.qgis_utils.get_settings_dialog() dlg.set_action_type(EnumDbActionType.EXPORT) dlg.tabWidget.setCurrentIndex(SETTINGS_CONNECTION_TAB_INDEX) if dlg.exec_(): self.db = dlg.get_db_connection() self.update_model_names() self.update_connection_info() def accepted(self): configuration = self.update_configuration() if not self.xtf_file_line_edit.validator().validate( configuration.xtffile, 0)[0] == QValidator.Acceptable: message_error = QCoreApplication.translate( "DialogExportData", "Please set a valid XTF file before exporting data.") self.txtStdout.setText(message_error) self.show_message(message_error, Qgis.Warning) self.xtf_file_line_edit.setFocus() return if not self.get_ili_models(): message_error = QCoreApplication.translate( "DialogExportData", "Please set a valid schema to export. This schema does not have information to export." ) self.txtStdout.setText(message_error) self.show_message(message_error, Qgis.Warning) self.export_models_list_view.setFocus() return if not configuration.iliexportmodels: message_error = QCoreApplication.translate( "DialogExportData", "Please set a model before exporting data.") self.txtStdout.setText(message_error) self.show_message(message_error, Qgis.Warning) self.export_models_list_view.setFocus() return # If xtf browser was opened and the file exists, the user already chose # to overwrite the file if os.path.isfile(self.xtf_file_line_edit.text().strip() ) and not self.xtf_browser_was_opened: self.msg = QMessageBox() self.msg.setIcon(QMessageBox.Warning) self.msg.setText( QCoreApplication.translate( "DialogExportData", "{filename} already exists.\nDo you want to replace it?"). format(filename=os.path.basename( self.xtf_file_line_edit.text().strip()))) self.msg.setWindowTitle( QCoreApplication.translate("DialogExportData", "Save in XTF Transfer File")) self.msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No) msg_box = self.msg.exec_() if msg_box == QMessageBox.No: return with OverrideCursor(Qt.WaitCursor): self.progress_bar.show() self.progress_bar.setValue(0) self.disable() self.txtStdout.setTextColor(QColor('#000000')) self.txtStdout.clear() exporter = iliexporter.Exporter() item_db = self._conf_db.get_db_items()[self.db.mode] exporter.tool_name = item_db.get_model_baker_tool_name() exporter.configuration = configuration self.save_configuration(configuration) exporter.stdout.connect(self.print_info) exporter.stderr.connect(self.on_stderr) exporter.process_started.connect(self.on_process_started) exporter.process_finished.connect(self.on_process_finished) self.progress_bar.setValue(25) try: if exporter.run() != iliexporter.Exporter.SUCCESS: self.enable() self.progress_bar.hide() self.show_message( QCoreApplication.translate( "DialogExportData", "An error occurred when exporting the data. For more information see the log..." ), Qgis.Warning) return except JavaNotFoundError: # Set JAVA PATH get_java_path_dlg = DialogGetJavaPath() get_java_path_dlg.setModal(True) if get_java_path_dlg.exec_(): configuration = self.update_configuration() if not get_java_path_from_qgis_model_baker(): message_error_java = QCoreApplication.translate( "DialogExportData", """Java could not be found. You can configure the JAVA_HOME environment variable, restart QGIS and try again.""" ) self.txtStdout.setTextColor(QColor('#000000')) self.txtStdout.clear() self.txtStdout.setText(message_error_java) self.show_message(message_error_java, Qgis.Warning) self.enable() self.progress_bar.hide() return self.buttonBox.clear() self.buttonBox.setEnabled(True) self.buttonBox.addButton(QDialogButtonBox.Close) self.progress_bar.setValue(100) self.show_message( QCoreApplication.translate( "DialogExportData", "Export of the data was successfully completed."), Qgis.Success) def save_configuration(self, configuration): settings = QSettings() settings.setValue( 'Asistente-LADM_COL/QgisModelBaker/ili2pg/xtffile_export', configuration.xtffile) settings.setValue('Asistente-LADM_COL/QgisModelBaker/show_log', not self.log_config.isCollapsed()) def restore_configuration(self): settings = QSettings() self.xtf_file_line_edit.setText( settings.value( 'Asistente-LADM_COL/QgisModelBaker/ili2pg/xtffile_export')) # Show log value_show_log = settings.value( 'Asistente-LADM_COL/QgisModelBaker/show_log', False, type=bool) self.log_config.setCollapsed(not value_show_log) # set model repository # if there is no option by default use online model repository custom_model_is_checked = settings.value( 'Asistente-LADM_COL/models/custom_model_directories_is_checked', type=bool) if custom_model_is_checked: self.custom_model_directories = settings.value( 'Asistente-LADM_COL/models/custom_models') def update_configuration(self): """ Get the configuration that is updated with the user configuration changes on the dialog. :return: Configuration """ item_db = self._conf_db.get_db_items()[self.db.mode] configuration = ExportConfiguration() item_db.set_db_configuration_params(self.db.dict_conn_params, configuration) configuration.xtffile = self.xtf_file_line_edit.text().strip() java_path = get_java_path_from_qgis_model_baker() if java_path: self.base_configuration.java_path = java_path # Check custom model directories if QSettings().value( 'Asistente-LADM_COL/models/custom_model_directories_is_checked', type=bool): if self.custom_model_directories is None: self.base_configuration.custom_model_directories_enabled = False else: self.base_configuration.custom_model_directories = self.custom_model_directories self.base_configuration.custom_model_directories_enabled = True configuration.base_configuration = self.base_configuration if self.get_ili_models(): configuration.iliexportmodels = ';'.join(self.get_ili_models()) configuration.ilimodels = ';'.join(self.get_ili_models()) return configuration def print_info(self, text, text_color='#000000', clear=False): self.txtStdout.setTextColor(QColor(text_color)) self.txtStdout.append(text) QCoreApplication.processEvents() def on_stderr(self, text): color_log_text(text, self.txtStdout) self.advance_progress_bar_by_text(text) def on_process_started(self, command): self.disable() self.txtStdout.setTextColor(QColor('#000000')) self.txtStdout.clear() self.txtStdout.setText(command) QCoreApplication.processEvents() def on_process_finished(self, exit_code, result): color = '#004905' if exit_code == 0 else '#aa2222' self.txtStdout.setTextColor(QColor(color)) self.txtStdout.append( QCoreApplication.translate("DialogExportData", "Finished ({})").format(exit_code)) if result == iliexporter.Exporter.SUCCESS: self.buttonBox.clear() self.buttonBox.setEnabled(True) self.buttonBox.addButton(QDialogButtonBox.Close) else: self.enable() # Open log if self.log_config.isCollapsed(): self.log_config.setCollapsed(False) def advance_progress_bar_by_text(self, text): if text.strip() == 'Info: compile models...': self.progress_bar.setValue(50) QCoreApplication.processEvents() elif text.strip() == 'Info: process data...': self.progress_bar.setValue(55) QCoreApplication.processEvents() elif text.strip() == 'Info: first validation pass...': self.progress_bar.setValue(70) QCoreApplication.processEvents() elif text.strip() == 'Info: second validation pass...': self.progress_bar.setValue(85) QCoreApplication.processEvents() def show_help(self): self.qgis_utils.show_help("export_data") def disable(self): self.db_config.setEnabled(False) self.ili_config.setEnabled(False) self.buttonBox.setEnabled(False) def enable(self): self.db_config.setEnabled(True) self.ili_config.setEnabled(True) self.buttonBox.setEnabled(True) def show_message(self, message, level): self.bar.pushMessage("Asistente LADM_COL", message, level, duration=0) def xtf_browser_opened_to_true(self): """ Slot. Sets a flag to true to eventually avoid asking a user whether to overwrite a file. """ self.xtf_browser_was_opened = True def xtf_browser_opened_to_false(self): """ Slot. Sets a flag to false to eventually ask a user whether to overwrite a file. """ self.xtf_browser_was_opened = False
class WizardDialog(QDialog, FORM_CLASS): """Dialog implementation class for Wizard""" def __init__(self, parent=None, iface=None): """Constructor for the dialog. .. note:: In QtDesigner the advanced editor's predefined keywords list should be shown in english always, so when adding entries to cboKeyword, be sure to choose :safe_qgis:`Properties<<` and untick the :safe_qgis:`translatable` property. :param parent: Parent widget of this dialog. :type parent: QWidget :param iface: QGIS QGisAppInterface instance. :type iface: QGisAppInterface """ QDialog.__init__(self, parent) self.setupUi(self) self.setWindowTitle('Cadasta') self.iface = iface self.parent_step = None self.message_bar = None self.steps = [] self.set_logo() self.populate_stacked_widget() self.update_step_label() first_step = self.first_step() first_step.set_widgets() self.go_to_step(first_step) # Set tab order for button self.setTabOrder(self.next_button, self.back_button) self.setTabOrder(self.back_button, self.cancel_button) def last_step(self): """Returns the last step of wizard. This method must be implemented in derived classes. :returns: Last step of wizard. :rtype: WizardStep """ raise NotImplementedError("The current wizard class doesn't implement \ the populate_stacked_widget method") def first_step(self): """Returns the first step of wizard. This method must be implemented in derived classes. :returns: First step of wizard. :rtype: WizardStep """ raise NotImplementedError("The current wizard class doesn't implement \ the populate_stacked_widget method") def populate_stacked_widget(self): """Append widgets to stacked widget. This method must be implemented in derived classes. """ raise NotImplementedError("The current wizard class doesn't implement \ the populate_stacked_widget method") def update_step_label(self): """Update step label with current step / total step.""" current_step = self.stackedWidget.currentIndex() total_step = self.stackedWidget.count() self.label_step.setText('%d/%d' % (current_step + 1, total_step)) def set_subtitle(self, subtitle): """Set subtitle of dialog. :param subtitle: Subtitle string :type subtitle: str """ self.label_subtitle.setText(subtitle) def set_logo(self): """Set logo of dialog.""" filename = logo_element() pixmap = QPixmap(filename) self.label_main_icon.setPixmap(pixmap) # =========================== # NAVIGATION # =========================== def go_to_step(self, step): """Set the stacked widget to the given step, set up the buttons, and run all operations that should start immediately after entering the new step. :param step: The step widget to be moved to. :type step: QWidget """ self.stackedWidget.setCurrentWidget(step) self.update_step_label() # Enable the Back button unless it's not the first step or # last step self.back_button.setEnabled( step not in [self.first_step()] or self.parent_step is not None) # Set Next button label if step == self.last_step(): self.next_button.setText(self.tr('Close')) else: self.next_button.setText(self.tr('Next')) def get_current_step(self): """Return current step of the wizard. :returns: Current step of the wizard. :rtype: WizardStep instance """ return self.stackedWidget.currentWidget() def prepare_the_next_step(self, new_step): """Prepare the next tab. To be implemented in derived classes. :param new_step: New tab to be prepared. :type new_step: WizardStep """ pass def prepare_the_previous_step(self): """Prepare the previous tab. """ self.next_button.setEnabled(True) # prevents actions being handled twice # noinspection PyPep8Naming @pyqtSignature('') def on_next_button_released(self): """Handle the Next button release. .. note:: This is an automatic Qt slot executed when the Next button is released. """ current_step = self.get_current_step() valid_status, message = current_step.validate_step() if not valid_status: self.message_bar = QgsMessageBar() self.message_bar.pushWarning( tr('Error'), message ) LOGGER.info(message) return self.steps.append(current_step) # Determine the new step to be switched new_step = current_step.get_next_step() if new_step is not None: # Prepare the next tab self.prepare_the_next_step(new_step) new_step.set_widgets() else: # Wizard complete self.accept() return self.go_to_step(new_step) # prevents actions being handled twice # noinspection PyPep8Naming @pyqtSignature('') def on_back_button_released(self): """Handle the Back button release. .. note:: This is an automatic Qt slot executed when the Back button is released. """ previous_step = self.steps.pop() self.prepare_the_previous_step() self.update_step_label() self.go_to_step(previous_step) # prevents actions being handled twice # noinspection PyPep8Naming @pyqtSignature('') def on_cancel_button_released(self): """Handle the Cancel button release. .. note:: This is an automatic Qt slot executed when the Back button is released. """ self.close()
def __init__(self, iface, parent=None): super(GridExtractDialog, self).__init__(parent) # Set up the user interface from Designer. self.setupUi(self) self.iface = iface self.DISP_TEMP_LAYERS = read_setting(PLUGIN_NAME + '/DISP_TEMP_LAYERS', bool) self.DEBUG = config.get_debug_mode() self.layers_df = None self.pixel_size = ['0', 'm', ''] # Catch and redirect python errors directed at the log messages python error tab. QgsApplication.messageLog().messageReceived.connect(errorCatcher) if not os.path.exists(TEMPDIR): os.mkdir(TEMPDIR) # Setup for validation messagebar on gui----------------------------- self.messageBar = QgsMessageBar( self) # leave this message bar for bailouts self.validationLayout = QtWidgets.QFormLayout( self) # new layout to gui if isinstance(self.layout(), QtWidgets.QFormLayout): # create a validation layout so multiple messages can be added and cleaned up. self.layout().insertRow(0, self.validationLayout) self.layout().insertRow(0, self.messageBar) else: self.layout().insertWidget( 0, self.messageBar) # for use with Vertical/horizontal layout box # GUI Runtime Customisation ----------------------------------------------- self.mcboPointsLayer.setFilters(QgsMapLayerProxyModel.PointLayer) self.mcboPointsLayer.setExcludedProviders(['wms']) self.mcboRasterLayer.setFilters(QgsMapLayerProxyModel.RasterLayer) self.mcboRasterLayer.setExcludedProviders(['wms']) self.setMapLayers() self.setWindowIcon( QtGui.QIcon(':/plugins/pat/icons/icon_gridExtract.svg')) self.chkgrpStatistics.setExclusive(False) self.tabList.setColumnCount(2) self.tabList.setHorizontalHeaderItem(0, QTableWidgetItem("ID")) self.tabList.setHorizontalHeaderItem(1, QTableWidgetItem("0 Raster(s)")) self.tabList.horizontalHeader().setSectionResizeMode( QtWidgets.QHeaderView.Stretch) self.tabList.hideColumn(0) # don't need to display the unique layer ID self.pixel_size = ['0', 'm', ''] self.statsMapping = { 'mean': np.nanmean, 'minimum': np.nanmin, 'maximum': np.nanmax, 'standard deviation': np.nanstd, 'coefficient of variation': raster_ops.nancv, 'pixel count': raster_ops.pixelcount, }
class ModelerParametersDialog(QDialog): ENTER_NAME = '[Enter name if this is a final result]' NOT_SELECTED = '[Not selected]' USE_MIN_COVERING_EXTENT = '[Use min covering extent]' def __init__(self, alg, model, algName=None): QDialog.__init__(self) self.setModal(True) # The algorithm to define in this dialog. It is an instance of GeoAlgorithm self._alg = alg # The resulting algorithm after the user clicks on OK. it is an instance of the container Algorithm class self.alg = None # The model this algorithm is going to be added to self.model = model # The name of the algorithm in the model, in case we are editing it and not defining it for the first time self._algName = algName self.setupUi() self.params = None def setupUi(self): self.labels = {} self.widgets = {} self.checkBoxes = {} self.showAdvanced = False self.wrappers = {} self.valueItems = {} self.dependentItems = {} self.resize(650, 450) self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok) tooltips = self._alg.getParameterDescriptions() self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.verticalLayout = QVBoxLayout() self.verticalLayout.setSpacing(5) self.verticalLayout.setMargin(20) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.verticalLayout.addWidget(self.bar) hLayout = QHBoxLayout() hLayout.setSpacing(5) hLayout.setMargin(0) descriptionLabel = QLabel(self.tr("Description")) self.descriptionBox = QLineEdit() self.descriptionBox.setText(self._alg.displayName()) hLayout.addWidget(descriptionLabel) hLayout.addWidget(self.descriptionBox) self.verticalLayout.addLayout(hLayout) line = QFrame() line.setFrameShape(QFrame.HLine) line.setFrameShadow(QFrame.Sunken) self.verticalLayout.addWidget(line) for param in self._alg.parameters: if param.isAdvanced: self.advancedButton = QPushButton() self.advancedButton.setText( self.tr('Show advanced parameters')) self.advancedButton.clicked.connect( self.showAdvancedParametersClicked) advancedButtonHLayout = QHBoxLayout() advancedButtonHLayout.addWidget(self.advancedButton) advancedButtonHLayout.addStretch() self.verticalLayout.addLayout(advancedButtonHLayout) break for param in self._alg.parameters: if param.hidden: continue desc = param.description if isinstance(param, ParameterExtent): desc += self.tr('(xmin, xmax, ymin, ymax)') if isinstance(param, ParameterPoint): desc += self.tr('(x, y)') if param.optional: desc += self.tr(' [optional]') label = QLabel(desc) self.labels[param.name] = label wrapper = param.wrapper(self) self.wrappers[param.name] = wrapper widget = wrapper.widget if widget is not None: self.valueItems[param.name] = widget if param.name in list(tooltips.keys()): tooltip = tooltips[param.name] else: tooltip = param.description label.setToolTip(tooltip) widget.setToolTip(tooltip) if param.isAdvanced: label.setVisible(self.showAdvanced) widget.setVisible(self.showAdvanced) self.widgets[param.name] = widget self.verticalLayout.addWidget(label) self.verticalLayout.addWidget(widget) for output in self._alg.outputs: if output.hidden: continue if isinstance(output, (OutputRaster, OutputVector, OutputTable, OutputHTML, OutputFile, OutputDirectory)): label = QLabel(output.description + '<' + output.__class__.__name__ + '>') item = QLineEdit() if hasattr(item, 'setPlaceholderText'): item.setPlaceholderText(ModelerParametersDialog.ENTER_NAME) self.verticalLayout.addWidget(label) self.verticalLayout.addWidget(item) self.valueItems[output.name] = item label = QLabel(' ') self.verticalLayout.addWidget(label) label = QLabel(self.tr('Parent algorithms')) self.dependenciesPanel = self.getDependenciesPanel() self.verticalLayout.addWidget(label) self.verticalLayout.addWidget(self.dependenciesPanel) self.verticalLayout.addStretch(1000) self.setPreviousValues() self.setWindowTitle(self._alg.displayName()) self.verticalLayout2 = QVBoxLayout() self.verticalLayout2.setSpacing(2) self.verticalLayout2.setMargin(0) self.tabWidget = QTabWidget() self.tabWidget.setMinimumWidth(300) self.paramPanel = QWidget() self.paramPanel.setLayout(self.verticalLayout) self.scrollArea = QgsScrollArea() self.scrollArea.setWidget(self.paramPanel) self.scrollArea.setWidgetResizable(True) self.tabWidget.addTab(self.scrollArea, self.tr('Parameters')) self.txtHelp = QTextBrowser() html = None isText, algHelp = self._alg.help() if algHelp is not None: algHelp = algHelp if isText else QUrl(algHelp) try: if isText: self.txtHelp.setHtml(algHelp) else: html = self.tr( '<p>Downloading algorithm help... Please wait.</p>') self.txtHelp.setHtml(html) self.tabWidget.addTab(self.txtHelp, 'Help') self.reply = QgsNetworkAccessManager.instance().get( QNetworkRequest(algHelp)) self.reply.finished.connect(self.requestFinished) except: pass self.verticalLayout2.addWidget(self.tabWidget) self.verticalLayout2.addWidget(self.buttonBox) self.setLayout(self.verticalLayout2) self.buttonBox.accepted.connect(self.okPressed) self.buttonBox.rejected.connect(self.cancelPressed) QMetaObject.connectSlotsByName(self) for wrapper in list(self.wrappers.values()): wrapper.postInitialize(list(self.wrappers.values())) def requestFinished(self): """Change the webview HTML content""" reply = self.sender() if reply.error() != QNetworkReply.NoError: html = self.tr( '<h2>No help available for this algorithm</h2><p>{}</p>'. format(reply.errorString())) else: html = str(reply.readAll()) reply.deleteLater() self.txtHelp.setHtml(html) def getAvailableDependencies(self): # spellok if self._algName is None: dependent = [] else: dependent = self.model.getDependentAlgorithms(self._algName) opts = [] for alg in list(self.model.algs.values()): if alg.modeler_name not in dependent: opts.append(alg) return opts def getDependenciesPanel(self): return MultipleInputPanel([ alg.description for alg in self.getAvailableDependencies() ]) # spellok def showAdvancedParametersClicked(self): self.showAdvanced = not self.showAdvanced if self.showAdvanced: self.advancedButton.setText(self.tr('Hide advanced parameters')) else: self.advancedButton.setText(self.tr('Show advanced parameters')) for param in self._alg.parameters: if param.isAdvanced: self.labels[param.name].setVisible(self.showAdvanced) self.widgets[param.name].setVisible(self.showAdvanced) def getAvailableValuesOfType(self, paramType, outType=None, dataType=None): # upgrade paramType to list if type(paramType) is not list: paramType = [paramType] values = [] inputs = self.model.inputs for i in list(inputs.values()): param = i.param for t in paramType: if isinstance(param, t): if dataType is not None: if param.datatype in dataType: values.append(ValueFromInput(param.name)) else: values.append(ValueFromInput(param.name)) break if outType is None: return values if self._algName is None: dependent = [] else: dependent = self.model.getDependentAlgorithms(self._algName) for alg in list(self.model.algs.values()): if alg.modeler_name not in dependent: for out in alg.algorithm.outputs: if isinstance(out, outType): if dataType is not None and out.datatype in dataType: values.append( ValueFromOutput(alg.modeler_name, out.name)) else: values.append( ValueFromOutput(alg.modeler_name, out.name)) return values def resolveValueDescription(self, value): if isinstance(value, ValueFromInput): return self.model.inputs[value.name].param.description else: alg = self.model.algs[value.alg] return self.tr("'{0}' from algorithm '{1}'").format( alg.algorithm.getOutputFromName(value.output).description, alg.description) def setPreviousValues(self): if self._algName is not None: alg = self.model.algs[self._algName] self.descriptionBox.setText(alg.description) for param in alg.algorithm.parameters: if param.hidden: continue if param.name in alg.params: value = alg.params[param.name] else: value = param.default self.wrappers[param.name].setValue(value) for name, out in list(alg.outputs.items()): self.valueItems[name].setText(out.description) selected = [] dependencies = self.getAvailableDependencies() # spellok for idx, dependency in enumerate(dependencies): if dependency.name in alg.dependencies: selected.append(idx) self.dependenciesPanel.setSelectedItems(selected) def createAlgorithm(self): alg = Algorithm(self._alg.id()) alg.setName(self.model) alg.description = self.descriptionBox.text() params = self._alg.parameters outputs = self._alg.outputs for param in params: if param.hidden: continue if not self.setParamValue(alg, param, self.wrappers[param.name]): self.bar.pushMessage( "Error", "Wrong or missing value for parameter '%s'" % param.description, level=QgsMessageBar.WARNING) return None for output in outputs: if not output.hidden: name = str(self.valueItems[output.name].text()) if name.strip( ) != '' and name != ModelerParametersDialog.ENTER_NAME: alg.outputs[output.name] = ModelerOutput(name) selectedOptions = self.dependenciesPanel.selectedoptions availableDependencies = self.getAvailableDependencies() # spellok for selected in selectedOptions: alg.dependencies.append( availableDependencies[selected].name) # spellok self._alg.processBeforeAddingToModeler(alg, self.model) return alg def setParamValue(self, alg, param, wrapper): try: if wrapper.widget: value = wrapper.value() alg.params[param.name] = value return True except InvalidParameterValue: return False def okPressed(self): self.alg = self.createAlgorithm() if self.alg is not None: self.close() def cancelPressed(self): self.alg = None self.close()
class SaveSearchDialog(BASE, WIDGET): def __init__(self, request): super(SaveSearchDialog, self).__init__(iface.mainWindow()) self.request = request self.request_to_save = None self.setupUi(self) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().addWidget(self.bar) self.buttonBox.button(QDialogButtonBox.Save).clicked.connect(self.save) self.buttonBox.button(QDialogButtonBox.Cancel).clicked.connect( self.reject) self.btnCreateFolder.clicked.connect(self.createFolder) self.set_from_request() self.populate_folders() def createFolder(self): name, _ = QInputDialog.getText(self, "Save Search", "Enter folder name") if name and name not in self._folder_names: self._folder_names.append(name) self.populate_folders() def populate_folders(self): self.comboFolder.clear() self.comboFolder.addItems(self._folders()) _folder_names = None def _folders(self): if self._folder_names is None: self._folder_names = [""] client = PlanetClient.getInstance() res = client.get_searches().get() for search in res["searches"]: tokens = search["name"].split("/") if len(tokens) > 1 and tokens[0] not in self._folder_names: self._folder_names.append(tokens[0]) return self._folder_names def set_from_request(self): filters = filters_from_request(self.request, "geometry") if filters: geom = filters[0].get("config") aoi_txt = json.dumps(geom) extent = qgsgeometry_from_geojson(aoi_txt).boundingBox() else: extent = iface.mapCanvas().fullExtent() layout = QVBoxLayout() layout.setMargin(0) self.canvas = QgsMapCanvas() layers = iface.mapCanvas().mapSettings().layers() crs = QgsCoordinateReferenceSystem("EPSG:4326") self.canvas.setLayers(layers) self.canvas.setDestinationCrs(crs) self.canvas.setExtent(extent) layout.addWidget(self.canvas) self.widgetAOI.setLayout(layout) filters = filters_from_request(self.request, "acquired") if filters: gte = filters[0]["config"].get("gte") if gte is not None: self.lblStartDate.setText( QDateTime.fromString(gte, Qt.ISODate).date().toString()) else: self.lblStartDate.setText("---") self.chkExcludeStart.setEnabled(False) lte = filters[0]["config"].get("lte") if lte is not None: self.lblEndDate.setText( QDateTime.fromString(lte, Qt.ISODate).date().toString()) else: self.lblEndDate.setText("---") self.chkExcludeEnd.setEnabled(False) self.txtFilters.setPlainText(filters_as_text_from_request( self.request)) def save(self): name = self.txtName.text() if len(name) == 0: self.bar.pushMessage("", "Invalid name", Qgis.Warning) return folder = self.comboFolder.currentText() if folder: name = f"{folder}/{name}" self.request_to_save = copy.deepcopy(self.request) self.request_to_save["name"] = name filters = filters_from_request(self.request, "acquired") if filters: config = filters[0]["config"] if self.chkExcludeStart.isChecked() and "gte" in config: del config["gte"] if self.chkExcludeEnd.isChecked() and "lte" in config: del config["lte"] self.replace_date_filter(self.request_to_save, config) self.accept() def replace_date_filter(self, request, newfilter): def process_filter(filterdict): if filterdict["type"] in ["AndFilter", "OrFilter"]: for subfilter in filterdict["config"]: process_filter(subfilter) elif filterdict.get("field_name") == "acquired": filterdict["config"] == newfilter process_filter(request["filter"])
class ModelerDialog(BASE, WIDGET): ALG_ITEM = 'ALG_ITEM' PROVIDER_ITEM = 'PROVIDER_ITEM' GROUP_ITEM = 'GROUP_ITEM' NAME_ROLE = Qt.UserRole TAG_ROLE = Qt.UserRole + 1 TYPE_ROLE = Qt.UserRole + 2 CANVAS_SIZE = 4000 update_model = pyqtSignal() def __init__(self, model=None): super().__init__(None) self.setAttribute(Qt.WA_DeleteOnClose) self.setupUi(self) # LOTS of bug reports when we include the dock creation in the UI file # see e.g. #16428, #19068 # So just roll it all by hand......! self.propertiesDock = QgsDockWidget(self) self.propertiesDock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.propertiesDock.setObjectName("propertiesDock") propertiesDockContents = QWidget() self.verticalDockLayout_1 = QVBoxLayout(propertiesDockContents) self.verticalDockLayout_1.setContentsMargins(0, 0, 0, 0) self.verticalDockLayout_1.setSpacing(0) self.scrollArea_1 = QgsScrollArea(propertiesDockContents) sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.scrollArea_1.sizePolicy().hasHeightForWidth()) self.scrollArea_1.setSizePolicy(sizePolicy) self.scrollArea_1.setFocusPolicy(Qt.WheelFocus) self.scrollArea_1.setFrameShape(QFrame.NoFrame) self.scrollArea_1.setFrameShadow(QFrame.Plain) self.scrollArea_1.setWidgetResizable(True) self.scrollAreaWidgetContents_1 = QWidget() self.gridLayout = QGridLayout(self.scrollAreaWidgetContents_1) self.gridLayout.setContentsMargins(6, 6, 6, 6) self.gridLayout.setSpacing(4) self.label_1 = QLabel(self.scrollAreaWidgetContents_1) self.gridLayout.addWidget(self.label_1, 0, 0, 1, 1) self.textName = QLineEdit(self.scrollAreaWidgetContents_1) self.gridLayout.addWidget(self.textName, 0, 1, 1, 1) self.label_2 = QLabel(self.scrollAreaWidgetContents_1) self.gridLayout.addWidget(self.label_2, 1, 0, 1, 1) self.textGroup = QLineEdit(self.scrollAreaWidgetContents_1) self.gridLayout.addWidget(self.textGroup, 1, 1, 1, 1) self.label_1.setText(self.tr("Name")) self.textName.setToolTip(self.tr("Enter model name here")) self.label_2.setText(self.tr("Group")) self.textGroup.setToolTip(self.tr("Enter group name here")) self.scrollArea_1.setWidget(self.scrollAreaWidgetContents_1) self.verticalDockLayout_1.addWidget(self.scrollArea_1) self.propertiesDock.setWidget(propertiesDockContents) self.addDockWidget(Qt.DockWidgetArea(1), self.propertiesDock) self.propertiesDock.setWindowTitle(self.tr("Model properties")) self.inputsDock = QgsDockWidget(self) self.inputsDock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.inputsDock.setObjectName("inputsDock") self.inputsDockContents = QWidget() self.verticalLayout_3 = QVBoxLayout(self.inputsDockContents) self.verticalLayout_3.setContentsMargins(0, 0, 0, 0) self.scrollArea_2 = QgsScrollArea(self.inputsDockContents) sizePolicy.setHeightForWidth( self.scrollArea_2.sizePolicy().hasHeightForWidth()) self.scrollArea_2.setSizePolicy(sizePolicy) self.scrollArea_2.setFocusPolicy(Qt.WheelFocus) self.scrollArea_2.setFrameShape(QFrame.NoFrame) self.scrollArea_2.setFrameShadow(QFrame.Plain) self.scrollArea_2.setWidgetResizable(True) self.scrollAreaWidgetContents_2 = QWidget() self.verticalLayout = QVBoxLayout(self.scrollAreaWidgetContents_2) self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.verticalLayout.setSpacing(0) self.inputsTree = QTreeWidget(self.scrollAreaWidgetContents_2) self.inputsTree.setAlternatingRowColors(True) self.inputsTree.header().setVisible(False) self.verticalLayout.addWidget(self.inputsTree) self.scrollArea_2.setWidget(self.scrollAreaWidgetContents_2) self.verticalLayout_3.addWidget(self.scrollArea_2) self.inputsDock.setWidget(self.inputsDockContents) self.addDockWidget(Qt.DockWidgetArea(1), self.inputsDock) self.inputsDock.setWindowTitle(self.tr("Inputs")) self.algorithmsDock = QgsDockWidget(self) self.algorithmsDock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.algorithmsDock.setObjectName("algorithmsDock") self.algorithmsDockContents = QWidget() self.verticalLayout_4 = QVBoxLayout(self.algorithmsDockContents) self.verticalLayout_4.setContentsMargins(0, 0, 0, 0) self.scrollArea_3 = QgsScrollArea(self.algorithmsDockContents) sizePolicy.setHeightForWidth( self.scrollArea_3.sizePolicy().hasHeightForWidth()) self.scrollArea_3.setSizePolicy(sizePolicy) self.scrollArea_3.setFocusPolicy(Qt.WheelFocus) self.scrollArea_3.setFrameShape(QFrame.NoFrame) self.scrollArea_3.setFrameShadow(QFrame.Plain) self.scrollArea_3.setWidgetResizable(True) self.scrollAreaWidgetContents_3 = QWidget() self.verticalLayout_2 = QVBoxLayout(self.scrollAreaWidgetContents_3) self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) self.verticalLayout_2.setSpacing(4) self.searchBox = QgsFilterLineEdit(self.scrollAreaWidgetContents_3) self.verticalLayout_2.addWidget(self.searchBox) self.algorithmTree = QgsProcessingToolboxTreeView( None, QgsApplication.processingRegistry()) self.algorithmTree.setAlternatingRowColors(True) self.algorithmTree.header().setVisible(False) self.verticalLayout_2.addWidget(self.algorithmTree) self.scrollArea_3.setWidget(self.scrollAreaWidgetContents_3) self.verticalLayout_4.addWidget(self.scrollArea_3) self.algorithmsDock.setWidget(self.algorithmsDockContents) self.addDockWidget(Qt.DockWidgetArea(1), self.algorithmsDock) self.algorithmsDock.setWindowTitle(self.tr("Algorithms")) self.searchBox.setToolTip( self.tr("Enter algorithm name to filter list")) self.searchBox.setShowSearchIcon(True) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.centralWidget().layout().insertWidget(0, self.bar) try: self.setDockOptions(self.dockOptions() | QMainWindow.GroupedDragging) except: pass if iface is not None: self.mToolbar.setIconSize(iface.iconSize()) self.setStyleSheet(iface.mainWindow().styleSheet()) self.mActionOpen.setIcon( QgsApplication.getThemeIcon('/mActionFileOpen.svg')) self.mActionSave.setIcon( QgsApplication.getThemeIcon('/mActionFileSave.svg')) self.mActionSaveAs.setIcon( QgsApplication.getThemeIcon('/mActionFileSaveAs.svg')) self.mActionSaveInProject.setIcon( QgsApplication.getThemeIcon('/mAddToProject.svg')) self.mActionZoomActual.setIcon( QgsApplication.getThemeIcon('/mActionZoomActual.svg')) self.mActionZoomIn.setIcon( QgsApplication.getThemeIcon('/mActionZoomIn.svg')) self.mActionZoomOut.setIcon( QgsApplication.getThemeIcon('/mActionZoomOut.svg')) self.mActionExportImage.setIcon( QgsApplication.getThemeIcon('/mActionSaveMapAsImage.svg')) self.mActionZoomToItems.setIcon( QgsApplication.getThemeIcon('/mActionZoomFullExtent.svg')) self.mActionExportPdf.setIcon( QgsApplication.getThemeIcon('/mActionSaveAsPDF.svg')) self.mActionExportSvg.setIcon( QgsApplication.getThemeIcon('/mActionSaveAsSVG.svg')) #self.mActionExportPython.setIcon( # QgsApplication.getThemeIcon('/mActionSaveAsPython.svg')) self.mActionEditHelp.setIcon( QgsApplication.getThemeIcon('/mActionEditHelpContent.svg')) self.mActionRun.setIcon( QgsApplication.getThemeIcon('/mActionStart.svg')) self.addDockWidget(Qt.LeftDockWidgetArea, self.propertiesDock) self.addDockWidget(Qt.LeftDockWidgetArea, self.inputsDock) self.addDockWidget(Qt.LeftDockWidgetArea, self.algorithmsDock) self.tabifyDockWidget(self.inputsDock, self.algorithmsDock) self.inputsDock.raise_() self.zoom = 1 self.setWindowFlags(Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint | Qt.WindowCloseButtonHint) settings = QgsSettings() self.restoreState( settings.value("/Processing/stateModeler", QByteArray())) self.restoreGeometry( settings.value("/Processing/geometryModeler", QByteArray())) self.scene = ModelerScene(self, dialog=self) self.scene.setSceneRect( QRectF(0, 0, self.CANVAS_SIZE, self.CANVAS_SIZE)) self.view.setScene(self.scene) self.view.setAcceptDrops(True) self.view.ensureVisible(0, 0, 10, 10) def _dragEnterEvent(event): if event.mimeData().hasText() or event.mimeData().hasFormat( 'application/x-vnd.qgis.qgis.algorithmid'): event.acceptProposedAction() else: event.ignore() def _dropEvent(event): 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() alg = QgsApplication.processingRegistry().createAlgorithmById( algorithm_id) if alg is not None: self._addAlgorithm(alg, event.pos()) else: assert False, algorithm_id elif event.mimeData().hasText(): itemId = event.mimeData().text() if itemId in [ param.id() for param in QgsApplication.instance(). processingRegistry().parameterTypes() ]: self.addInputOfType(itemId, event.pos()) event.accept() else: event.ignore() def _dragMoveEvent(event): if event.mimeData().hasText() or event.mimeData().hasFormat( 'application/x-vnd.qgis.qgis.algorithmid'): event.accept() else: event.ignore() def _wheelEvent(event): self.view.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) settings = QgsSettings() factor = settings.value('/qgis/zoom_favor', 2.0) # "Normal" mouse has an angle delta of 120, precision mouses provide data # faster, in smaller steps factor = 1.0 + (factor - 1.0) / 120.0 * abs(event.angleDelta().y()) if (event.modifiers() == Qt.ControlModifier): factor = 1.0 + (factor - 1.0) / 20.0 if event.angleDelta().y() < 0: factor = 1 / factor self.view.scale(factor, factor) def _enterEvent(e): QGraphicsView.enterEvent(self.view, e) self.view.viewport().setCursor(Qt.ArrowCursor) def _mouseReleaseEvent(e): QGraphicsView.mouseReleaseEvent(self.view, e) self.view.viewport().setCursor(Qt.ArrowCursor) def _mousePressEvent(e): if e.button() == Qt.MidButton: self.previousMousePos = e.pos() else: QGraphicsView.mousePressEvent(self.view, e) def _mouseMoveEvent(e): if e.buttons() == Qt.MidButton: offset = self.previousMousePos - e.pos() self.previousMousePos = e.pos() self.view.verticalScrollBar().setValue( self.view.verticalScrollBar().value() + offset.y()) self.view.horizontalScrollBar().setValue( self.view.horizontalScrollBar().value() + offset.x()) else: QGraphicsView.mouseMoveEvent(self.view, e) self.view.setDragMode(QGraphicsView.ScrollHandDrag) self.view.dragEnterEvent = _dragEnterEvent self.view.dropEvent = _dropEvent self.view.dragMoveEvent = _dragMoveEvent self.view.wheelEvent = _wheelEvent self.view.enterEvent = _enterEvent self.view.mousePressEvent = _mousePressEvent self.view.mouseMoveEvent = _mouseMoveEvent def _mimeDataInput(items): mimeData = QMimeData() text = items[0].data(0, Qt.UserRole) mimeData.setText(text) return mimeData self.inputsTree.mimeData = _mimeDataInput self.inputsTree.setDragDropMode(QTreeWidget.DragOnly) self.inputsTree.setDropIndicatorShown(True) self.algorithms_model = ModelerToolboxModel( self, QgsApplication.processingRegistry()) self.algorithmTree.setToolboxProxyModel(self.algorithms_model) self.algorithmTree.setDragDropMode(QTreeWidget.DragOnly) self.algorithmTree.setDropIndicatorShown(True) self.algorithmTree.setFilters( QgsProcessingToolboxProxyModel.FilterModeler) if hasattr(self.searchBox, 'setPlaceholderText'): self.searchBox.setPlaceholderText( QCoreApplication.translate('ModelerDialog', 'Search…')) if hasattr(self.textName, 'setPlaceholderText'): self.textName.setPlaceholderText(self.tr('Enter model name here')) if hasattr(self.textGroup, 'setPlaceholderText'): self.textGroup.setPlaceholderText(self.tr('Enter group name here')) # Connect signals and slots self.inputsTree.doubleClicked.connect(self.addInput) self.searchBox.textChanged.connect(self.algorithmTree.setFilterString) self.algorithmTree.doubleClicked.connect(self.addAlgorithm) # Ctrl+= should also trigger a zoom in action ctrlEquals = QShortcut(QKeySequence("Ctrl+="), self) ctrlEquals.activated.connect(self.zoomIn) self.mActionOpen.triggered.connect(self.openModel) self.mActionSave.triggered.connect(self.save) self.mActionSaveAs.triggered.connect(self.saveAs) self.mActionSaveInProject.triggered.connect(self.saveInProject) self.mActionZoomIn.triggered.connect(self.zoomIn) self.mActionZoomOut.triggered.connect(self.zoomOut) self.mActionZoomActual.triggered.connect(self.zoomActual) self.mActionZoomToItems.triggered.connect(self.zoomToItems) self.mActionExportImage.triggered.connect(self.exportAsImage) self.mActionExportPdf.triggered.connect(self.exportAsPdf) self.mActionExportSvg.triggered.connect(self.exportAsSvg) #self.mActionExportPython.triggered.connect(self.exportAsPython) self.mActionEditHelp.triggered.connect(self.editHelp) self.mActionRun.triggered.connect(self.runModel) if model is not None: self.model = model.create() self.model.setSourceFilePath(model.sourceFilePath()) self.textGroup.setText(self.model.group()) self.textName.setText(self.model.displayName()) self.repaintModel() else: self.model = QgsProcessingModelAlgorithm() self.model.setProvider( QgsApplication.processingRegistry().providerById('model')) self.fillInputsTree() self.view.centerOn(0, 0) self.help = None self.hasChanged = False def closeEvent(self, evt): settings = QgsSettings() settings.setValue("/Processing/stateModeler", self.saveState()) settings.setValue("/Processing/geometryModeler", self.saveGeometry()) if self.hasChanged: ret = QMessageBox.question( self, self.tr('Save Model?'), self. tr('There are unsaved changes in this model. Do you want to keep those?' ), QMessageBox.Save | QMessageBox.Cancel | QMessageBox.Discard, QMessageBox.Cancel) if ret == QMessageBox.Save: self.saveModel(False) evt.accept() elif ret == QMessageBox.Discard: evt.accept() else: evt.ignore() else: evt.accept() def editHelp(self): alg = self.model dlg = HelpEditionDialog(alg) dlg.exec_() if dlg.descriptions: self.model.setHelpContent(dlg.descriptions) self.hasChanged = True def runModel(self): if len(self.model.childAlgorithms()) == 0: self.bar.pushMessage( "", self. tr("Model doesn't contain any algorithm and/or parameter and can't be executed" ), level=Qgis.Warning, duration=5) return dlg = AlgorithmDialog(self.model) dlg.exec_() def save(self): self.saveModel(False) def saveAs(self): self.saveModel(True) def saveInProject(self): if not self.can_save(): return self.model.setName(str(self.textName.text())) self.model.setGroup(str(self.textGroup.text())) self.model.setSourceFilePath(None) project_provider = QgsApplication.processingRegistry().providerById( PROJECT_PROVIDER_ID) project_provider.add_model(self.model) self.update_model.emit() self.bar.pushMessage("", self.tr("Model was saved inside current project"), level=Qgis.Success, duration=5) self.hasChanged = False QgsProject.instance().setDirty(True) def zoomIn(self): self.view.setTransformationAnchor(QGraphicsView.NoAnchor) point = self.view.mapToScene( QPoint(self.view.viewport().width() / 2, self.view.viewport().height() / 2)) settings = QgsSettings() factor = settings.value('/qgis/zoom_favor', 2.0) self.view.scale(factor, factor) self.view.centerOn(point) self.repaintModel() def zoomOut(self): self.view.setTransformationAnchor(QGraphicsView.NoAnchor) point = self.view.mapToScene( QPoint(self.view.viewport().width() / 2, self.view.viewport().height() / 2)) settings = QgsSettings() factor = settings.value('/qgis/zoom_favor', 2.0) factor = 1 / factor self.view.scale(factor, factor) self.view.centerOn(point) self.repaintModel() def zoomActual(self): point = self.view.mapToScene( QPoint(self.view.viewport().width() / 2, self.view.viewport().height() / 2)) self.view.resetTransform() self.view.centerOn(point) def zoomToItems(self): totalRect = self.scene.itemsBoundingRect() totalRect.adjust(-10, -10, 10, 10) self.view.fitInView(totalRect, Qt.KeepAspectRatio) def exportAsImage(self): self.repaintModel(controls=False) filename, fileFilter = QFileDialog.getSaveFileName( self, self.tr('Save Model As Image'), '', self.tr('PNG files (*.png *.PNG)')) if not filename: return if not filename.lower().endswith('.png'): filename += '.png' totalRect = self.scene.itemsBoundingRect() totalRect.adjust(-10, -10, 10, 10) imgRect = QRectF(0, 0, totalRect.width(), totalRect.height()) img = QImage(totalRect.width(), totalRect.height(), QImage.Format_ARGB32_Premultiplied) img.fill(Qt.white) painter = QPainter() painter.setRenderHint(QPainter.Antialiasing) painter.begin(img) self.scene.render(painter, imgRect, totalRect) painter.end() img.save(filename) self.bar.pushMessage("", self.tr("Model was correctly exported as image"), level=Qgis.Success, duration=5) self.repaintModel(controls=True) def exportAsPdf(self): self.repaintModel(controls=False) filename, fileFilter = QFileDialog.getSaveFileName( self, self.tr('Save Model As PDF'), '', self.tr('PDF files (*.pdf *.PDF)')) if not filename: return if not filename.lower().endswith('.pdf'): filename += '.pdf' totalRect = self.scene.itemsBoundingRect() totalRect.adjust(-10, -10, 10, 10) printerRect = QRectF(0, 0, totalRect.width(), totalRect.height()) printer = QPrinter() printer.setOutputFormat(QPrinter.PdfFormat) printer.setOutputFileName(filename) printer.setPaperSize(QSizeF(printerRect.width(), printerRect.height()), QPrinter.DevicePixel) printer.setFullPage(True) painter = QPainter(printer) self.scene.render(painter, printerRect, totalRect) painter.end() self.bar.pushMessage("", self.tr("Model was correctly exported as PDF"), level=Qgis.Success, duration=5) self.repaintModel(controls=True) def exportAsSvg(self): self.repaintModel(controls=False) filename, fileFilter = QFileDialog.getSaveFileName( self, self.tr('Save Model As SVG'), '', self.tr('SVG files (*.svg *.SVG)')) if not filename: return if not filename.lower().endswith('.svg'): filename += '.svg' totalRect = self.scene.itemsBoundingRect() totalRect.adjust(-10, -10, 10, 10) svgRect = QRectF(0, 0, totalRect.width(), totalRect.height()) svg = QSvgGenerator() svg.setFileName(filename) svg.setSize(QSize(totalRect.width(), totalRect.height())) svg.setViewBox(svgRect) svg.setTitle(self.model.displayName()) painter = QPainter(svg) self.scene.render(painter, svgRect, totalRect) painter.end() self.bar.pushMessage("", self.tr("Model was correctly exported as SVG"), level=Qgis.Success, duration=5) self.repaintModel(controls=True) def exportAsPython(self): filename, filter = QFileDialog.getSaveFileName( self, self.tr('Save Model As Python Script'), '', self.tr('Processing scripts (*.py *.PY)')) if not filename: return if not filename.lower().endswith('.py'): filename += '.py' text = self.model.asPythonCode() with codecs.open(filename, 'w', encoding='utf-8') as fout: fout.write(text) self.bar.pushMessage( "", self.tr("Model was correctly exported as python script"), level=Qgis.Success, duration=5) def can_save(self): """ Tests whether a model can be saved, or if it is not yet valid :return: bool """ if str(self.textName.text()).strip() == '': self.bar.pushWarning( "", self.tr('Please a enter model name before saving')) return False return True def saveModel(self, saveAs): if not self.can_save(): return self.model.setName(str(self.textName.text())) self.model.setGroup(str(self.textGroup.text())) if self.model.sourceFilePath() and not saveAs: filename = self.model.sourceFilePath() else: filename, filter = QFileDialog.getSaveFileName( self, self.tr('Save Model'), ModelerUtils.modelsFolders()[0], self.tr('Processing models (*.model3 *.MODEL3)')) if filename: if not filename.endswith('.model3'): filename += '.model3' self.model.setSourceFilePath(filename) if filename: if not self.model.toFile(filename): if saveAs: QMessageBox.warning( self, self.tr('I/O error'), self.tr('Unable to save edits. Reason:\n {0}').format( str(sys.exc_info()[1]))) else: QMessageBox.warning( self, self.tr("Can't save model"), QCoreApplication. translate('QgsPluginInstallerInstallingDialog', ( "This model can't be saved in its original location (probably you do not " "have permission to do it). Please, use the 'Save as…' option." ))) return self.update_model.emit() self.bar.pushMessage("", self.tr("Model was correctly saved"), level=Qgis.Success, duration=5) self.hasChanged = False def openModel(self): filename, selected_filter = QFileDialog.getOpenFileName( self, self.tr('Open Model'), ModelerUtils.modelsFolders()[0], self.tr('Processing models (*.model3 *.MODEL3)')) if filename: self.loadModel(filename) def loadModel(self, filename): alg = QgsProcessingModelAlgorithm() if alg.fromFile(filename): self.model = alg self.model.setProvider( QgsApplication.processingRegistry().providerById('model')) self.textGroup.setText(alg.group()) self.textName.setText(alg.name()) self.repaintModel() self.view.centerOn(0, 0) self.hasChanged = False else: QgsMessageLog.logMessage( self.tr('Could not load model {0}').format(filename), self.tr('Processing'), Qgis.Critical) QMessageBox.critical( self, self.tr('Open Model'), self.tr('The selected model could not be loaded.\n' 'See the log for more information.')) def repaintModel(self, controls=True): self.scene = ModelerScene(self, dialog=self) self.scene.setSceneRect( QRectF(0, 0, self.CANVAS_SIZE, self.CANVAS_SIZE)) self.scene.paintModel(self.model, controls) self.view.setScene(self.scene) def addInput(self): item = self.inputsTree.currentItem() param = item.data(0, Qt.UserRole) self.addInputOfType(param) def addInputOfType(self, paramType, pos=None): dlg = ModelerParameterDefinitionDialog(self.model, paramType) dlg.exec_() if dlg.param is not None: if pos is None: pos = self.getPositionForParameterItem() if isinstance(pos, QPoint): pos = QPointF(pos) component = QgsProcessingModelParameter(dlg.param.name()) component.setDescription(dlg.param.name()) component.setPosition(pos) self.model.addModelParameter(dlg.param, component) self.repaintModel() # self.view.ensureVisible(self.scene.getLastParameterItem()) self.hasChanged = True def getPositionForParameterItem(self): MARGIN = 20 BOX_WIDTH = 200 BOX_HEIGHT = 80 if len(self.model.parameterComponents()) > 0: maxX = max([ i.position().x() for i in list(self.model.parameterComponents().values()) ]) newX = min(MARGIN + BOX_WIDTH + maxX, self.CANVAS_SIZE - BOX_WIDTH) else: newX = MARGIN + BOX_WIDTH / 2 return QPointF(newX, MARGIN + BOX_HEIGHT / 2) def fillInputsTree(self): icon = QIcon(os.path.join(pluginPath, 'images', 'input.svg')) parametersItem = QTreeWidgetItem() parametersItem.setText(0, self.tr('Parameters')) sortedParams = sorted( QgsApplication.instance().processingRegistry().parameterTypes(), key=lambda pt: pt.name()) for param in sortedParams: if param.flags() & QgsProcessingParameterType.ExposeToModeler: paramItem = QTreeWidgetItem() paramItem.setText(0, param.name()) paramItem.setData(0, Qt.UserRole, param.id()) paramItem.setIcon(0, icon) paramItem.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled) paramItem.setToolTip(0, param.description()) parametersItem.addChild(paramItem) self.inputsTree.addTopLevelItem(parametersItem) parametersItem.setExpanded(True) def addAlgorithm(self): algorithm = self.algorithmTree.selectedAlgorithm() if algorithm is not None: alg = QgsApplication.processingRegistry().createAlgorithmById( algorithm.id()) self._addAlgorithm(alg) def _addAlgorithm(self, alg, pos=None): dlg = ModelerParametersDialog(alg, self.model) if dlg.exec_(): alg = dlg.createAlgorithm() if pos is None: alg.setPosition(self.getPositionForAlgorithmItem()) else: alg.setPosition(pos) from processing.modeler.ModelerGraphicItem import ModelerGraphicItem for i, out in enumerate(alg.modelOutputs()): alg.modelOutput(out).setPosition( alg.position() + QPointF(ModelerGraphicItem.BOX_WIDTH, (i + 1.5) * ModelerGraphicItem.BOX_HEIGHT)) self.model.addChildAlgorithm(alg) self.repaintModel() self.hasChanged = True def getPositionForAlgorithmItem(self): MARGIN = 20 BOX_WIDTH = 200 BOX_HEIGHT = 80 if self.model.childAlgorithms(): maxX = max([ alg.position().x() for alg in list(self.model.childAlgorithms().values()) ]) maxY = max([ alg.position().y() for alg in list(self.model.childAlgorithms().values()) ]) newX = min(MARGIN + BOX_WIDTH + maxX, self.CANVAS_SIZE - BOX_WIDTH) newY = min(MARGIN + BOX_HEIGHT + maxY, self.CANVAS_SIZE - BOX_HEIGHT) else: newX = MARGIN + BOX_WIDTH / 2 newY = MARGIN * 2 + BOX_HEIGHT + BOX_HEIGHT / 2 return QPointF(newX, newY)
def __init__(self, parent=None): super(ShellOutputScintilla, self).__init__(parent) self.parent = parent self.shell = self.parent.shell self.settings = QSettings() # Creates layout for message bar self.layout = QGridLayout(self) self.layout.setContentsMargins(0, 0, 0, 0) spacerItem = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) self.layout.addItem(spacerItem, 1, 0, 1, 1) # messageBar instance self.infoBar = QgsMessageBar() sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.infoBar.setSizePolicy(sizePolicy) self.layout.addWidget(self.infoBar, 0, 0, 1, 1) # Enable non-ascii chars for editor self.setUtf8(True) sys.stdout = writeOut(self, sys.stdout) sys.stderr = writeOut(self, sys.stderr, "_traceback") self.insertInitText() self.setLexers() self.setReadOnly(True) # Set the default font font = QFont() font.setFamily('Courier') font.setFixedPitch(True) font.setPointSize(10) self.setFont(font) self.setMarginsFont(font) # Margin 0 is used for line numbers self.setMarginWidth(0, 0) self.setMarginWidth(1, 0) self.setMarginWidth(2, 0) #fm = QFontMetrics(font) self.setMarginsFont(font) self.setMarginWidth(1, "00000") self.setMarginLineNumbers(1, True) self.setMarginsForegroundColor(QColor("#3E3EE3")) self.setMarginsBackgroundColor(QColor("#f9f9f9")) self.setCaretLineVisible(True) self.setCaretLineBackgroundColor(QColor("#fcf3ed")) self.setMinimumHeight(120) self.setWrapMode(QsciScintilla.WrapCharacter) self.SendScintilla(QsciScintilla.SCI_SETHSCROLLBAR, 0) self.runScut = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_E), self) self.runScut.setContext(Qt.WidgetShortcut) self.runScut.activated.connect(self.enteredSelected) # Reimplemeted copy action to prevent paste prompt (>>>,...) in command view self.copyShortcut = QShortcut(QKeySequence.Copy, self) self.copyShortcut.activated.connect(self.copy) self.selectAllShortcut = QShortcut(QKeySequence.SelectAll, self) self.selectAllShortcut.activated.connect(self.selectAll)
class ShellOutputScintilla(QsciScintilla): def __init__(self, parent=None): super(ShellOutputScintilla, self).__init__(parent) self.parent = parent self.shell = self.parent.shell self.settings = QSettings() # Creates layout for message bar self.layout = QGridLayout(self) self.layout.setContentsMargins(0, 0, 0, 0) spacerItem = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) self.layout.addItem(spacerItem, 1, 0, 1, 1) # messageBar instance self.infoBar = QgsMessageBar() sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.infoBar.setSizePolicy(sizePolicy) self.layout.addWidget(self.infoBar, 0, 0, 1, 1) # Enable non-ascii chars for editor self.setUtf8(True) sys.stdout = writeOut(self, sys.stdout) sys.stderr = writeOut(self, sys.stderr, "_traceback") self.insertInitText() self.setLexers() self.setReadOnly(True) # Set the default font font = QFont() font.setFamily('Courier') font.setFixedPitch(True) font.setPointSize(10) self.setFont(font) self.setMarginsFont(font) # Margin 0 is used for line numbers self.setMarginWidth(0, 0) self.setMarginWidth(1, 0) self.setMarginWidth(2, 0) #fm = QFontMetrics(font) self.setMarginsFont(font) self.setMarginWidth(1, "00000") self.setMarginLineNumbers(1, True) self.setMarginsForegroundColor(QColor("#3E3EE3")) self.setMarginsBackgroundColor(QColor("#f9f9f9")) self.setCaretLineVisible(True) self.setCaretLineBackgroundColor(QColor("#fcf3ed")) self.setMinimumHeight(120) self.setWrapMode(QsciScintilla.WrapCharacter) self.SendScintilla(QsciScintilla.SCI_SETHSCROLLBAR, 0) self.runScut = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_E), self) self.runScut.setContext(Qt.WidgetShortcut) self.runScut.activated.connect(self.enteredSelected) # Reimplemeted copy action to prevent paste prompt (>>>,...) in command view self.copyShortcut = QShortcut(QKeySequence.Copy, self) self.copyShortcut.activated.connect(self.copy) self.selectAllShortcut = QShortcut(QKeySequence.SelectAll, self) self.selectAllShortcut.activated.connect(self.selectAll) def insertInitText(self): txtInit = QCoreApplication.translate( "PythonConsole", "Python %1 on %2\n" "## Type help(iface) for more info and list of methods.\n").arg( sys.version, socket.gethostname()) initText = self.setText(txtInit) def refreshLexerProperties(self): self.setLexers() def setLexers(self): self.lexer = QsciLexerPython() loadFont = self.settings.value("pythonConsole/fontfamilytext", "Monospace").toString() fontSize = self.settings.value("pythonConsole/fontsize", 10).toInt()[0] font = QFont(loadFont) font.setFixedPitch(True) font.setPointSize(fontSize) font.setStyleHint(QFont.TypeWriter) font.setStretch(QFont.SemiCondensed) font.setLetterSpacing(QFont.PercentageSpacing, 87.0) font.setBold(False) self.lexer.setDefaultFont(font) self.lexer.setColor(Qt.red, 1) self.lexer.setColor(Qt.darkGreen, 5) self.lexer.setColor(Qt.darkBlue, 15) self.lexer.setFont(font, 1) self.lexer.setFont(font, 2) self.lexer.setFont(font, 3) self.lexer.setFont(font, 4) self.setLexer(self.lexer) def clearConsole(self): self.setText('') self.insertInitText() self.shell.setFocus() def contextMenuEvent(self, e): menu = QMenu(self) iconRun = QgsApplication.getThemeIcon("console/iconRunConsole.png") iconClear = QgsApplication.getThemeIcon("console/iconClearConsole.png") iconHideTool = QgsApplication.getThemeIcon( "console/iconHideToolConsole.png") iconSettings = QgsApplication.getThemeIcon( "console/iconSettingsConsole.png") hideToolBar = menu.addAction( iconHideTool, QCoreApplication.translate("PythonConsole", "Hide/Show Toolbar"), self.hideToolBar) menu.addSeparator() showEditorAction = menu.addAction( QCoreApplication.translate("PythonConsole", "Show Editor"), self.showEditor) menu.addSeparator() runAction = menu.addAction( iconRun, QCoreApplication.translate("PythonConsole", "Enter Selected"), self.enteredSelected, QKeySequence(Qt.CTRL + Qt.Key_E)) clearAction = menu.addAction( iconClear, QCoreApplication.translate("PythonConsole", "Clear console"), self.clearConsole) menu.addSeparator() copyAction = menu.addAction( QCoreApplication.translate("PythonConsole", "Copy"), self.copy, QKeySequence.Copy) menu.addSeparator() selectAllAction = menu.addAction( QCoreApplication.translate("PythonConsole", "Select All"), self.selectAll, QKeySequence.SelectAll) menu.addSeparator() settingsDialog = menu.addAction( iconSettings, QCoreApplication.translate("PythonConsole", "Settings"), self.parent.openSettings) runAction.setEnabled(False) clearAction.setEnabled(False) copyAction.setEnabled(False) selectAllAction.setEnabled(False) showEditorAction.setEnabled(True) if self.hasSelectedText(): runAction.setEnabled(True) copyAction.setEnabled(True) if not self.text(3) == '': selectAllAction.setEnabled(True) clearAction.setEnabled(True) if self.parent.tabEditorWidget.isVisible(): showEditorAction.setEnabled(False) action = menu.exec_(self.mapToGlobal(e.pos())) def hideToolBar(self): tB = self.parent.toolBar tB.hide() if tB.isVisible() else tB.show() self.shell.setFocus() def showEditor(self): Ed = self.parent.splitterObj if not Ed.isVisible(): Ed.show() self.parent.showEditorButton.setChecked(True) self.shell.setFocus() def copy(self): """Copy text to clipboard... or keyboard interrupt""" if self.hasSelectedText(): text = unicode(self.selectedText()) text = text.replace('>>> ', '').replace('... ', '').strip() # removing prompts QApplication.clipboard().setText(text) else: self.emit(SIGNAL("keyboard_interrupt()")) def enteredSelected(self): cmd = self.selectedText() self.shell.insertFromDropPaste(cmd) self.shell.entered() def keyPressEvent(self, e): # empty text indicates possible shortcut key sequence so stay in output txt = e.text() if txt.length() and txt >= " ": self.shell.append(txt) self.shell.move_cursor_to_end() self.shell.setFocus() e.ignore() else: # possible shortcut key sequence, accept it e.accept() def widgetMessageBar(self, iface, text): timeout = iface.messageTimeout() self.infoBar.pushMessage(text, QgsMessageBar.INFO, timeout)
def __init__(self, canvas): """Constructor. :param canvas: """ QObject.__init__(self) self.canvas = canvas self.legend = QgisLegend(canvas) self.message_bar = QgsMessageBar(None) # Set up slots so we can mimic the behaviour of QGIS when layers # are added. LOGGER.debug('Initialising canvas...') # noinspection PyArgumentList QgsMapLayerRegistry.instance().layersAdded.connect(self.addLayers) # noinspection PyArgumentList QgsMapLayerRegistry.instance().layerWasAdded.connect(self.addLayer) # noinspection PyArgumentList QgsMapLayerRegistry.instance().removeAll.connect(self.removeAllLayers) # For processing module self.destCrs = None # For keeping track of which layer is active in the legend. self.active_layer = None # In the next section of code, we are going to do some monkey patching # to make the QGIS processing framework think that this mock QGIS IFACE # instance is the actual one. It will also ensure that the processing # algorithms are nicely loaded and available for use. # noinspection PyUnresolvedReferences from processing.tools import dataobjects # noinspection PyUnresolvedReferences import processing # noinspection PyUnresolvedReferences from processing.core.Processing import Processing # pylint: enable=F0401, E0611 processing.classFactory(self) # We create our own getAlgorithm function below which will will monkey # patch in to the Processing class in QGIS in order to ensure that the # Processing.initialize() call is made before asking for an alg. @staticmethod def mock_getAlgorithm(name): """ Modified version of the original getAlgorithm function. :param name: Name of the algorithm to load. :type name: str :return: An algorithm concrete class. :rtype: QgsAlgorithm ? """ Processing.initialize() # FIXME: Had some weird bug in QGIS 2.18 MacOSX (KyngChaos) try: providers = Processing.algs.values() except: providers = Processing.algs().values() for provider in providers: if name in provider: return provider[name] return None # Now we let the monkey loose! Processing.getAlgorithm = mock_getAlgorithm # We also need to make dataobjects think that this iface is 'the one' # Note. the placement here (after the getAlgorithm monkey patch above) # is significant, so don't move it! dataobjects.iface = self # set up a layer tree bridge so that new added layers appear in legend self.layer_tree_root = QgsProject.instance().layerTreeRoot() self.bridge = QgsLayerTreeMapCanvasBridge(self.layer_tree_root, self.canvas) self.bridge.setCanvasLayers()
class OptionsWidget(WidgetBase, FORM_CLASS): """Options widget.""" authenticated = pyqtSignal() unauthenticated = pyqtSignal() def __init__(self, parent=None, auth_token=None): """Constructor :param parent: parent - widget to use as parent. :type parent: QWidget """ super(OptionsWidget, self).__init__(parent) self.text_test_connection_button = None self.url = None self.auth_token = auth_token self.login_api = None self.organisation_api = Organization() self.set_widgets() def set_widgets(self): """Set all widgets.""" self.text_test_connection_button = self.test_connection_button.text() self.ok_label.setVisible(False) self.save_button.setEnabled(False) self.test_connection_button.clicked.connect(self.login) self.save_button.clicked.connect(self.save_authtoken) self.clear_button.setText(tr('Clear')) self.clear_button.setEnabled(True) self.clear_button.clicked.connect(self.clear_information) self.url_input.setText(get_url_instance()) # If login information exists if not self.auth_token: self.auth_token = get_authtoken() if self.auth_token: self.test_connection_button.setEnabled(False) self.username_input.setText(get_setting('username')) self.username_input.setReadOnly(True) self.password_input.setReadOnly(True) self.username_input.setStyleSheet( "QLineEdit { background-color: '#d9d9d9'; color: '#5b5b5b'; " "selection-background-color: '#969292'; }") self.password_input.setStyleSheet( "QLineEdit { background-color: '#d9d9d9'; color: '#5b5b5b'; " "selection-background-color: '#969292'; }") self.token_status.setText(tr('Auth token is saved.')) else: self.token_status.setText(tr('Auth token is empty.')) def clear_information(self): """Clear login information.""" self.username_input.setReadOnly(False) self.password_input.setReadOnly(False) self.username_input.setStyleSheet("") self.password_input.setStyleSheet("") self.username_input.clear() self.password_input.clear() self.ok_label.clear() delete_authtoken() delete_setting('username') self.test_connection_button.setEnabled(True) self.token_status.setText(tr('Auth token is empty.')) self.unauthenticated.emit() def login(self): """Login function when tools button clicked.""" self.clear_button.setEnabled(False) username = self.username_input.displayText() password = self.password_input.text() self.url = self.url_input.displayText() self.auth_token = None self.save_button.setEnabled(False) self.ok_label.setVisible(False) if not self.url or not username or not password: self.message_bar = QgsMessageBar() self.message_bar.pushWarning( self.tr('Error'), self.tr('URL/Username/password is empty.')) else: self.test_connection_button.setEnabled(False) self.test_connection_button.setText(self.tr('Logging in...')) # call tools API self.login_api = self.call_login_api(self.url, username, password) self.login_api.connect_post(self.login_api.post_data) def call_login_api(self, url, username, password): """Call login api. :param url: platform url :type url: str :param username: username for login :type username: str :param password: password for login :type password: str """ return Login(domain=url, username=username, password=password, on_finished=self.on_finished) def on_finished(self, result): """On finished function when tools request is finished.""" self.ok_label.setVisible(True) self.clear_button.setEnabled(True) if 'auth_token' in result: self.auth_token = result['auth_token'] self.save_button.setEnabled(True) self.ok_label.setText(self.tr('Success')) self.ok_label.setStyleSheet('color:green') else: self.save_button.setEnabled(False) self.ok_label.setText(self.tr('Failed')) self.ok_label.setStyleSheet('color:red') self.test_connection_button.setText(self.text_test_connection_button) self.test_connection_button.setEnabled(True) def save_authtoken(self): """Save received authtoken to setting. Authoken is saved to setting, and close dialog after that. """ if self.auth_token: set_setting('username', self.username_input.displayText()) save_authtoken(self.auth_token) save_url_instance(self.url) self.save_button.setEnabled(False) self.save_organizations() self.username_input.setReadOnly(True) self.password_input.setReadOnly(True) self.username_input.setStyleSheet( "QLineEdit { background-color: '#d9d9d9'; color: '#5b5b5b'; " "selection-background-color: '#969292'; }") self.password_input.setStyleSheet( "QLineEdit { background-color: '#d9d9d9'; color: '#5b5b5b'; " "selection-background-color: '#969292'; }") def save_organizations(self): """Save organizations of user. Organization is saved to setting. If it is success, close dialog after that. """ status, results = self.organisation_api. \ organizations_project_filtered() self.clear_button.setEnabled(True) self.save_button.setEnabled(False) if status: organization = [] for result in results: organization.append(result['slug']) save_user_organizations(organization) self.parent.close() else: self.message_bar = QgsMessageBar() self.message_bar.pushWarning( self.tr('Error'), self.tr('Error when getting user permission.')) self.authenticated.emit()
def setupUi(self): self.labels = {} self.widgets = {} self.checkBoxes = {} self.showAdvanced = False self.wrappers = {} self.valueItems = {} self.dependentItems = {} self.resize(650, 450) self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok) tooltips = self._alg.getParameterDescriptions() self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.verticalLayout = QVBoxLayout() self.verticalLayout.setSpacing(5) self.verticalLayout.setMargin(20) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.verticalLayout.addWidget(self.bar) hLayout = QHBoxLayout() hLayout.setSpacing(5) hLayout.setMargin(0) descriptionLabel = QLabel(self.tr("Description")) self.descriptionBox = QLineEdit() self.descriptionBox.setText(self._alg.displayName()) hLayout.addWidget(descriptionLabel) hLayout.addWidget(self.descriptionBox) self.verticalLayout.addLayout(hLayout) line = QFrame() line.setFrameShape(QFrame.HLine) line.setFrameShadow(QFrame.Sunken) self.verticalLayout.addWidget(line) for param in self._alg.parameters: if param.isAdvanced: self.advancedButton = QPushButton() self.advancedButton.setText( self.tr('Show advanced parameters')) self.advancedButton.clicked.connect( self.showAdvancedParametersClicked) advancedButtonHLayout = QHBoxLayout() advancedButtonHLayout.addWidget(self.advancedButton) advancedButtonHLayout.addStretch() self.verticalLayout.addLayout(advancedButtonHLayout) break for param in self._alg.parameters: if param.hidden: continue desc = param.description if isinstance(param, ParameterExtent): desc += self.tr('(xmin, xmax, ymin, ymax)') if isinstance(param, ParameterPoint): desc += self.tr('(x, y)') if param.optional: desc += self.tr(' [optional]') label = QLabel(desc) self.labels[param.name] = label wrapper = param.wrapper(self) self.wrappers[param.name] = wrapper widget = wrapper.widget if widget is not None: self.valueItems[param.name] = widget if param.name in list(tooltips.keys()): tooltip = tooltips[param.name] else: tooltip = param.description label.setToolTip(tooltip) widget.setToolTip(tooltip) if param.isAdvanced: label.setVisible(self.showAdvanced) widget.setVisible(self.showAdvanced) self.widgets[param.name] = widget self.verticalLayout.addWidget(label) self.verticalLayout.addWidget(widget) for output in self._alg.outputs: if output.hidden: continue if isinstance(output, (OutputRaster, OutputVector, OutputTable, OutputHTML, OutputFile, OutputDirectory)): label = QLabel(output.description + '<' + output.__class__.__name__ + '>') item = QLineEdit() if hasattr(item, 'setPlaceholderText'): item.setPlaceholderText(ModelerParametersDialog.ENTER_NAME) self.verticalLayout.addWidget(label) self.verticalLayout.addWidget(item) self.valueItems[output.name] = item label = QLabel(' ') self.verticalLayout.addWidget(label) label = QLabel(self.tr('Parent algorithms')) self.dependenciesPanel = self.getDependenciesPanel() self.verticalLayout.addWidget(label) self.verticalLayout.addWidget(self.dependenciesPanel) self.verticalLayout.addStretch(1000) self.setPreviousValues() self.setWindowTitle(self._alg.displayName()) self.verticalLayout2 = QVBoxLayout() self.verticalLayout2.setSpacing(2) self.verticalLayout2.setMargin(0) self.tabWidget = QTabWidget() self.tabWidget.setMinimumWidth(300) self.paramPanel = QWidget() self.paramPanel.setLayout(self.verticalLayout) self.scrollArea = QgsScrollArea() self.scrollArea.setWidget(self.paramPanel) self.scrollArea.setWidgetResizable(True) self.tabWidget.addTab(self.scrollArea, self.tr('Parameters')) self.txtHelp = QTextBrowser() html = None isText, algHelp = self._alg.help() if algHelp is not None: algHelp = algHelp if isText else QUrl(algHelp) try: if isText: self.txtHelp.setHtml(algHelp) else: html = self.tr( '<p>Downloading algorithm help... Please wait.</p>') self.txtHelp.setHtml(html) self.tabWidget.addTab(self.txtHelp, 'Help') self.reply = QgsNetworkAccessManager.instance().get( QNetworkRequest(algHelp)) self.reply.finished.connect(self.requestFinished) except: pass self.verticalLayout2.addWidget(self.tabWidget) self.verticalLayout2.addWidget(self.buttonBox) self.setLayout(self.verticalLayout2) self.buttonBox.accepted.connect(self.okPressed) self.buttonBox.rejected.connect(self.cancelPressed) QMetaObject.connectSlotsByName(self) for wrapper in list(self.wrappers.values()): wrapper.postInitialize(list(self.wrappers.values()))
class ShellOutputScintilla(QsciScintilla): def __init__(self, parent=None): super(ShellOutputScintilla, self).__init__(parent) self.parent = parent self.shell = self.parent.shell self.settings = QSettings() # Creates layout for message bar self.layout = QGridLayout(self) self.layout.setContentsMargins(0, 0, 0, 0) spacerItem = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) self.layout.addItem(spacerItem, 1, 0, 1, 1) # messageBar instance self.infoBar = QgsMessageBar() sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.infoBar.setSizePolicy(sizePolicy) self.layout.addWidget(self.infoBar, 0, 0, 1, 1) # Enable non-ascii chars for editor self.setUtf8(True) sys.stdout = writeOut(self, sys.stdout) sys.stderr = writeOut(self, sys.stderr, "_traceback") self.insertInitText() self.refreshSettingsOutput() self.setReadOnly(True) # Set the default font font = QFont() font.setFamily('Courier') font.setFixedPitch(True) font.setPointSize(10) self.setFont(font) self.setMarginsFont(font) # Margin 0 is used for line numbers self.setMarginWidth(0, 0) self.setMarginWidth(1, 0) self.setMarginWidth(2, 0) #fm = QFontMetrics(font) self.setMarginsFont(font) self.setMarginWidth(1, "00000") self.setMarginLineNumbers(1, True) self.setMarginsForegroundColor(QColor("#3E3EE3")) self.setMarginsBackgroundColor(QColor("#f9f9f9")) self.setCaretLineVisible(True) self.setCaretWidth(0) self.setMinimumHeight(120) self.setWrapMode(QsciScintilla.WrapCharacter) self.SendScintilla(QsciScintilla.SCI_SETHSCROLLBAR, 0) self.runScut = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_E), self) self.runScut.setContext(Qt.WidgetShortcut) self.runScut.activated.connect(self.enteredSelected) # Reimplemented copy action to prevent paste prompt (>>>,...) in command view self.copyShortcut = QShortcut(QKeySequence.Copy, self) self.copyShortcut.activated.connect(self.copy) self.selectAllShortcut = QShortcut(QKeySequence.SelectAll, self) self.selectAllShortcut.activated.connect(self.selectAll) def insertInitText(self): txtInit = QCoreApplication.translate("PythonConsole", "Python Console \n" "Use iface to access QGIS API interface or Type help(iface) for more info") ## some translation string for the console header ends without '\n' ## and the first command in console will be appended at the header text. ## The following code add a '\n' at the end of the string if not present. if txtInit.endswith('\n'): self.setText(txtInit) else: self.setText(txtInit + '\n') def refreshSettingsOutput(self): # Set Python lexer self.setLexers() caretLineColor = self.settings.value("pythonConsole/caretLineColor", QColor("#fcf3ed")) cursorColor = self.settings.value("pythonConsole/cursorColor", QColor(Qt.black)) self.setCaretLineBackgroundColor(caretLineColor) self.setCaretForegroundColor(cursorColor) def setLexers(self): self.lexer = QsciLexerPython() loadFont = self.settings.value("pythonConsole/fontfamilytext", "Monospace") fontSize = self.settings.value("pythonConsole/fontsize", 10, type=int) font = QFont(loadFont) font.setFixedPitch(True) font.setPointSize(fontSize) font.setStyleHint(QFont.TypeWriter) font.setStretch(QFont.SemiCondensed) font.setLetterSpacing(QFont.PercentageSpacing, 87.0) font.setBold(False) self.lexer.setDefaultFont(font) self.lexer.setDefaultColor(QColor(self.settings.value("pythonConsole/defaultFontColor", QColor(Qt.black)))) self.lexer.setColor(QColor(self.settings.value("pythonConsole/commentFontColor", QColor(Qt.gray))), 1) self.lexer.setColor(QColor(self.settings.value("pythonConsole/keywordFontColor", QColor(Qt.darkGreen))), 5) self.lexer.setColor(QColor(self.settings.value("pythonConsole/classFontColor", QColor(Qt.blue))), 8) self.lexer.setColor(QColor(self.settings.value("pythonConsole/methodFontColor", QColor(Qt.darkGray))), 9) self.lexer.setColor(QColor(self.settings.value("pythonConsole/decorFontColor", QColor(Qt.darkBlue))), 15) self.lexer.setColor(QColor(self.settings.value("pythonConsole/commentBlockFontColor", QColor(Qt.gray))), 12) self.lexer.setColor(QColor(self.settings.value("pythonConsole/singleQuoteFontColor", QColor(Qt.blue))), 4) self.lexer.setColor(QColor(self.settings.value("pythonConsole/doubleQuoteFontColor", QColor(Qt.blue))), 3) self.lexer.setColor(QColor(self.settings.value("pythonConsole/tripleSingleQuoteFontColor", QColor(Qt.blue))), 6) self.lexer.setColor(QColor(self.settings.value("pythonConsole/tripleDoubleQuoteFontColor", QColor(Qt.blue))), 7) self.lexer.setColor(QColor(Qt.red), 14) self.lexer.setFont(font, 1) self.lexer.setFont(font, 2) self.lexer.setFont(font, 3) self.lexer.setFont(font, 4) for style in range(0, 33): paperColor = QColor(self.settings.value("pythonConsole/paperBackgroundColor", QColor(Qt.white))) self.lexer.setPaper(paperColor, style) self.setLexer(self.lexer) def clearConsole(self): self.setText('') self.insertInitText() self.shell.setFocus() def contextMenuEvent(self, e): menu = QMenu(self) iconRun = QgsApplication.getThemeIcon("console/iconRunConsole.png") iconClear = QgsApplication.getThemeIcon("console/iconClearConsole.png") iconHideTool = QgsApplication.getThemeIcon("console/iconHideToolConsole.png") iconSettings = QgsApplication.getThemeIcon("console/iconSettingsConsole.png") menu.addAction(iconHideTool, QCoreApplication.translate("PythonConsole", "Hide/Show Toolbar"), self.hideToolBar) menu.addSeparator() showEditorAction = menu.addAction( QCoreApplication.translate("PythonConsole", "Show Editor"), self.showEditor) menu.addSeparator() runAction = menu.addAction(iconRun, QCoreApplication.translate("PythonConsole", "Enter Selected"), self.enteredSelected, QKeySequence(Qt.CTRL + Qt.Key_E)) clearAction = menu.addAction(iconClear, QCoreApplication.translate("PythonConsole", "Clear Console"), self.clearConsole) menu.addSeparator() copyAction = menu.addAction( QCoreApplication.translate("PythonConsole", "Copy"), self.copy, QKeySequence.Copy) selectAllAction = menu.addAction( QCoreApplication.translate("PythonConsole", "Select All"), self.selectAll, QKeySequence.SelectAll) menu.addSeparator() menu.addAction(iconSettings, QCoreApplication.translate("PythonConsole", "Options..."), self.parent.openSettings) runAction.setEnabled(False) clearAction.setEnabled(False) copyAction.setEnabled(False) selectAllAction.setEnabled(False) showEditorAction.setEnabled(True) if self.hasSelectedText(): runAction.setEnabled(True) copyAction.setEnabled(True) if not self.text(3) == '': selectAllAction.setEnabled(True) clearAction.setEnabled(True) if self.parent.tabEditorWidget.isVisible(): showEditorAction.setEnabled(False) menu.exec_(self.mapToGlobal(e.pos())) def hideToolBar(self): tB = self.parent.toolBar tB.hide() if tB.isVisible() else tB.show() self.shell.setFocus() def showEditor(self): Ed = self.parent.splitterObj if not Ed.isVisible(): Ed.show() self.parent.showEditorButton.setChecked(True) self.shell.setFocus() def copy(self): """Copy text to clipboard... or keyboard interrupt""" if self.hasSelectedText(): text = self.selectedText() text = text.replace('>>> ', '').replace('... ', '').strip() # removing prompts QApplication.clipboard().setText(text) else: raise KeyboardInterrupt def enteredSelected(self): cmd = self.selectedText() self.shell.insertFromDropPaste(cmd) self.shell.entered() def keyPressEvent(self, e): # empty text indicates possible shortcut key sequence so stay in output txt = e.text() if len(txt) and txt >= " ": self.shell.append(txt) self.shell.move_cursor_to_end() self.shell.setFocus() e.ignore() else: # possible shortcut key sequence, accept it e.accept() def widgetMessageBar(self, iface, text): timeout = iface.messageTimeout() self.infoBar.pushMessage(text, QgsMessageBar.INFO, timeout)
def __init__(self, iface, conn_manager, context, selected_models=list(), link_to_import_data=True, parent=None): QDialog.__init__(self, parent) self.iface = iface self.conn_manager = conn_manager self.selected_models = selected_models self.link_to_import_data = link_to_import_data self.logger = Logger() self.app = AppInterface() self.__ladmcol_models = LADMColModelRegistry() self.java_dependency = JavaDependency() self.java_dependency.download_dependency_completed.connect( self.download_java_complete) self.java_dependency.download_dependency_progress_changed.connect( self.download_java_progress_change) self.db_source = context.get_db_sources()[0] self.db = self.conn_manager.get_db_connector_from_source( self.db_source) self._dbs_supported = ConfigDBsSupported() self._running_tool = False # There may be two cases where we need to emit a db_connection_changed from the Schema Import dialog: # 1) Connection Settings was opened and the DB conn was changed. # 2) Connection Settings was never opened but the Schema Import ran successfully, in a way that new models may # convert a db/schema LADM-COL compliant. self._db_was_changed = False # To postpone calling refresh gui until we close this dialog instead of settings # Similarly, we could call a refresh on layers and relations cache in two cases: # 1) If the SI dialog was called for the COLLECTED source: opening Connection Settings and changing the DB # connection. # 2) Not opening the Connection Settings, but running a successful Schema Import on the COLLECTED DB, which # invalidates the cache as models change. self._schedule_layers_and_relations_refresh = False self.setupUi(self) self.validators = Validators() self.update_import_models() self.previous_item = QListWidgetItem() self.connection_setting_button.clicked.connect(self.show_settings) self.connection_setting_button.setText( QCoreApplication.translate("DialogImportSchema", "Connection Settings")) # CRS Setting self.srs_auth = DEFAULT_SRS_AUTH self.srs_code = DEFAULT_SRS_CODE self.crsSelector.crsChanged.connect(self.crs_changed) # LOG self.log_config.setTitle( QCoreApplication.translate("DialogImportSchema", "Show log")) self.buttonBox.accepted.disconnect() self.buttonBox.clicked.connect(self.accepted_import_schema) self.buttonBox.clear() self.buttonBox.addButton(QDialogButtonBox.Cancel) self._accept_button = self.buttonBox.addButton( self.BUTTON_NAME_CREATE_STRUCTURE, QDialogButtonBox.AcceptRole) self.buttonBox.addButton(QDialogButtonBox.Help) self.buttonBox.helpRequested.connect(self.show_help) self.import_models_list_widget.setDisabled(bool( selected_models)) # If we got models from params, disable panel self.update_connection_info() self.restore_configuration() self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().addWidget(self.bar, 0, 0, Qt.AlignTop)
class geobricks_qgis_plugin_faostat: def __init__(self, iface): self.iface = iface self.layout = QVBoxLayout() self.cbGroups = QComboBox() self.cbDomains = QComboBox() self.cbElements = QComboBox() self.cbItems = QComboBox() self.download_folder = QLineEdit() try: if self.last_download_folder is not None: self.download_folder.setText(self.last_download_folder) except: self.last_download_folder = None self.download_folder_button = QPushButton(self.tr('...')) self.download_folder_button.clicked.connect(self.select_output_file) self.progress = QProgressBar() self.add_to_canvas = QCheckBox(self.tr('Add output layer to canvas')) self.start_download_button = QPushButton(self.tr('Start Download')) self.start_download_button.clicked.connect(self.download_data) self.progress_label = QLabel('<b>' + self.tr('Progress') + '</b>') self.bar = QgsMessageBar() self.plugin_dir = os.path.dirname(__file__) locale = QSettings().value('locale/userLocale')[0:2] locale_path = os.path.join( self.plugin_dir, 'i18n', 'geobricks_qgis_plugin_faostat_{}.qm'.format(locale)) if os.path.exists(locale_path): self.translator = QTranslator() self.translator.load(locale_path) if qVersion() > '4.3.3': QCoreApplication.installTranslator(self.translator) self.dlg = geobricks_qgis_plugin_faostatDialog() self.actions = [] self.menu = self.tr('FAOSTAT Data Downloader') self.toolbar = self.iface.addToolBar('geobricks_qgis_plugin_faostat') self.toolbar.setObjectName('geobricks_qgis_plugin_faostat') self.initialized = False def run(self): # Build UI self.build_ui() # Populate domains groups = get_groups() for group in groups: self.cbGroups.addItem(group['label'], group['code']) # Test message bar self.bar.pushMessage(None, str(len(groups)) + self.tr(' groups added'), level=QgsMessageBar.INFO) def build_ui(self): # Reset layout self.layout = QVBoxLayout() # Groups lbl_0 = QLabel('<b>' + self.tr('Groups') + '</b>') self.cbGroups.addItem(self.tr('Please select a groups...')) self.cbGroups.activated[str].connect(self.on_groups_change) # Domains lbl_1 = QLabel('<b>' + self.tr('Domains') + '</b>') self.cbDomains.addItem( self.tr('Please select a group to populate this combo-box...')) self.cbDomains.activated[str].connect(self.on_domain_change) # Elements lbl_2 = QLabel('<b>' + self.tr('Elements') + '</b>') self.cbElements.addItem( self.tr('Please select a domain to populate this combo-box...')) # Items lbl_3 = QLabel('<b>' + self.tr('Items') + '</b>') self.cbItems.addItem( self.tr('Please select a domain to populate this combo-box...')) # Download Folder lbl_4 = QLabel('<b>' + self.tr('Download Folder') + '</b>') download_folder_widget = QWidget() download_folder_layout = QHBoxLayout() download_folder_widget.setLayout(download_folder_layout) download_folder_layout.addWidget(self.download_folder) download_folder_layout.addWidget(self.download_folder_button) # Progress bar self.progress.setValue(0) # Add to canvas self.add_to_canvas.toggle() # Message bar self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout.addWidget(self.bar) # Add widgets to layout self.layout.addWidget(lbl_0) self.layout.addWidget(self.cbGroups) self.layout.addWidget(lbl_1) self.layout.addWidget(self.cbDomains) self.layout.addWidget(lbl_2) self.layout.addWidget(self.cbElements) self.layout.addWidget(lbl_3) self.layout.addWidget(self.cbItems) self.layout.addWidget(lbl_4) self.layout.addWidget(download_folder_widget) self.layout.addWidget(self.add_to_canvas) self.layout.addWidget(self.start_download_button) self.layout.addWidget(self.progress_label) self.layout.addWidget(self.progress) # Set layout self.dlg.setLayout(self.layout) # Show dialog self.dlg.show() def download_data(self): # Get user selection group_code = self.cbGroups.itemData(self.cbGroups.currentIndex()) domain_code = self.cbDomains.itemData(self.cbDomains.currentIndex()) element_code = self.cbElements.itemData(self.cbElements.currentIndex()) item_code = self.cbItems.itemData(self.cbItems.currentIndex()) download_folder = self.download_folder.text() # Check selection if group_code is None: self.bar.pushMessage(None, self.tr('Please select a group'), level=QgsMessageBar.CRITICAL) elif domain_code is None: self.bar.pushMessage(None, self.tr('Please select a domain'), level=QgsMessageBar.CRITICAL) elif element_code is None: self.bar.pushMessage(None, self.tr('Please select an element'), level=QgsMessageBar.CRITICAL) elif item_code is None: self.bar.pushMessage(None, self.tr('Please select an item'), level=QgsMessageBar.CRITICAL) elif download_folder is None or len(download_folder) == 0: self.bar.pushMessage(None, self.tr('Please select a download folder'), level=QgsMessageBar.CRITICAL) else: # Get data data = get_data(domain_code, element_code, item_code) # Notify the user self.bar.pushMessage(None, self.tr('Downloaded rows: ') + str(len(data)), level=QgsMessageBar.INFO) # Layer name layer_name = self.cbItems.currentText().replace( ' ', '_') + '_' + self.cbElements.currentText().replace( ' ', '_') folder_name = os.path.join(download_folder, group_code, domain_code) if not os.path.exists(folder_name): os.makedirs(folder_name) # Copy template layer output_file = copy_layer(folder_name, layer_name) layer = QgsVectorLayer(output_file, 'layer_name', 'ogr') # Add all the years to the layer feature_idx = 64 year_to_be_shown = 2014 number_of_nulls = 0 for year in range(2014, 1960, -1): progress = (1 + (feature_idx - 64)) * 1.86 self.progress.setValue(progress) self.progress_label.setText('<b>' + self.tr('Progress') + ': ' + '</b> ' + self.tr('Adding Year ') + str(year)) year_data = self.get_year_data(data, year) layer.dataProvider().addAttributes( [QgsField(str(year), QVariant.Double)]) if len(year_data) > 0: layer.startEditing() for feature in layer.getFeatures(): if feature['FAOSTAT'] is not None: feature_code = str(feature['FAOSTAT']) for d in year_data: data_code = str(d['code']) if data_code == feature_code: value = d['value'] layer.changeAttributeValue( feature.id(), (feature_idx), float(value)) tmp_feature = QgsFeature() tmp_feature.setAttributes([float(value)]) layer.dataProvider().addFeatures( [tmp_feature]) if value is None: number_of_nulls += 1 layer.commitChanges() else: year_to_be_shown -= 1 feature_idx += 1 # Add layer to canvas if self.add_to_canvas.isChecked(): renderer = self.create_join_renderer( layer, str(year_to_be_shown), 11, QgsGraduatedSymbolRendererV2.Pretty) l = QgsVectorLayer( output_file, layer_name + '(' + str(year_to_be_shown) + ')', 'ogr') r = renderer.clone() r.setClassAttribute(str(year_to_be_shown)) l.setRendererV2(r) QgsMapLayerRegistry.instance().addMapLayer(l) self.iface.legendInterface().setLayerVisible(l, True) # Close pop-up self.dlg.close() def create_join_renderer(self, layer, field, classes, mode, color='PuBu'): symbol = QgsSymbolV2.defaultSymbol(layer.geometryType()) style = QgsStyleV2().defaultStyle() colorRamp = style.colorRampRef(color) renderer = QgsGraduatedSymbolRendererV2.createRenderer( layer, field, classes, mode, symbol, colorRamp) label_format = self.create_join_label_format(2) renderer.setLabelFormat(label_format) return renderer def create_join_label_format(self, precision): format = QgsRendererRangeV2LabelFormat() template = '%1 - %2' format.setFormat(template) format.setPrecision(precision) format.setTrimTrailingZeroes(True) return format def get_year_data(self, data, year): out = [] for d in data: if d['year'] == str(year): out.append(d) return out def on_groups_change(self, text): # Get selected group code group_code = self.cbGroups.itemData(self.cbGroups.currentIndex()) # Update domains list domains = get_domains(group_code) self.cbDomains.clear() self.cbDomains.addItem(self.tr('Please select a domain')) for domain in domains: self.cbDomains.addItem(domain['label'], domain['code']) def on_domain_change(self, text): # Get selected domain code domain_code = self.cbDomains.itemData(self.cbDomains.currentIndex()) # Check domain code if domain_code is not None: # Update elements list try: elements = get_elements(domain_code) self.cbElements.clear() self.cbElements.addItem(self.tr('Please select an element')) for element in elements: self.cbElements.addItem(element['label'], element['code']) except ValueError: self.bar.pushMessage( None, self. tr('No elements available for this domain. Please select another domain.' ), level=QgsMessageBar.CRITICAL) # Update items list try: items = get_items(domain_code) self.cbItems.clear() self.cbItems.addItem(self.tr('Please select an item')) for item in items: self.cbItems.addItem(item['label'], item['code']) except: self.bar.pushMessage( None, self. tr('No items available for this domain. Please select another domain.' ), level=QgsMessageBar.CRITICAL) else: self.bar.pushMessage( None, self.tr('No domain selected. Please select a domain.'), level=QgsMessageBar.CRITICAL) def tr(self, message): return QCoreApplication.translate('geobricks_qgis_plugin_faostat', message) def add_action(self, icon_path, text, callback, enabled_flag=True, add_to_menu=True, add_to_toolbar=True, status_tip=None, whats_this=None, parent=None): icon = QIcon(icon_path) action = QAction(icon, text, parent) action.triggered.connect(callback) action.setEnabled(enabled_flag) if status_tip is not None: action.setStatusTip(status_tip) if whats_this is not None: action.setWhatsThis(whats_this) if add_to_toolbar: self.toolbar.addAction(action) if add_to_menu: self.iface.addPluginToMenu(self.menu, action) self.actions.append(action) return action def initGui(self): icon_path = ':/plugins/geobricks_qgis_plugin_faostat/icon.png' self.add_action(icon_path, text=self.tr('FAOSTAT Data Downloader'), callback=self.run, parent=self.iface.mainWindow()) def unload(self): for action in self.actions: self.iface.removePluginMenu( self.tr(self.tr('FAOSTAT Data Downloader')), action) self.iface.removeToolBarIcon(action) del self.toolbar def select_output_file(self): filename = QFileDialog.getExistingDirectory(self.dlg, self.tr('Select Folder')) self.last_download_folder = filename self.download_folder.setText(self.last_download_folder)
class AlgorithmDialog(AlgorithmDialogBase): def __init__(self, alg): AlgorithmDialogBase.__init__(self, alg) self.alg = alg self.setMainWidget(alg.getParametersPanel(self)) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().insertWidget(0, self.bar) self.cornerWidget = QWidget() layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 5) self.tabWidget.setStyleSheet("QTabBar::tab { height: 30px; }") self.runAsBatchButton = QPushButton(self.tr("Run as batch process...")) self.runAsBatchButton.clicked.connect(self.runAsBatch) layout.addWidget(self.runAsBatchButton) self.cornerWidget.setLayout(layout) self.tabWidget.setCornerWidget(self.cornerWidget) def runAsBatch(self): self.close() dlg = BatchAlgorithmDialog(self.alg) dlg.show() dlg.exec_() def setParamValues(self): params = self.alg.parameters outputs = self.alg.outputs for param in params: if param.hidden: continue wrapper = self.mainWidget.wrappers[param.name] if not self.setParamValue(param, wrapper): raise AlgorithmDialogBase.InvalidParameterValue( param, wrapper.widget) for output in outputs: if output.hidden: continue output.value = self.mainWidget.outputWidgets[ output.name].getValue() if isinstance(output, (OutputRaster, OutputVector, OutputTable)): output.open = self.mainWidget.checkBoxes[ output.name].isChecked() return True def setParamValue(self, param, wrapper): if wrapper.widget: return param.setValue(wrapper.value()) else: return True def checkExtentCRS(self): unmatchingCRS = False hasExtent = False projectCRS = iface.mapCanvas().mapSettings().destinationCrs() layers = QgsProcessingUtils.compatibleLayers(QgsProject.instance()) for param in self.alg.parameters: if isinstance( param, (ParameterRaster, ParameterVector, ParameterMultipleInput)): if param.value: if isinstance(param, ParameterMultipleInput): inputlayers = param.value.split(';') else: inputlayers = [param.value] for inputlayer in inputlayers: for layer in layers: if layer.source() == inputlayer: if layer.crs() != projectCRS: unmatchingCRS = True p = dataobjects.getLayerFromString(inputlayer) if p is not None: if p.crs() != projectCRS: unmatchingCRS = True if isinstance(param, ParameterExtent): if param.skip_crs_check: continue value = self.mainWidget.wrappers[ param.name].widget.leText.text().strip() if value: hasExtent = True return hasExtent and unmatchingCRS def accept(self): self.settings.setValue("/Processing/dialogBase", self.saveGeometry()) checkCRS = ProcessingConfig.getSetting( ProcessingConfig.WARN_UNMATCHING_CRS) try: self.setParamValues() if checkCRS and not self.alg.checkInputCRS(): reply = QMessageBox.question( self, self.tr("Unmatching CRS's"), self.tr('Layers do not all use the same CRS. This can ' 'cause unexpected results.\nDo you want to ' 'continue?'), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.No: return checkExtentCRS = ProcessingConfig.getSetting( ProcessingConfig.WARN_UNMATCHING_EXTENT_CRS) if checkExtentCRS and self.checkExtentCRS(): reply = QMessageBox.question( self, self.tr("Extent CRS"), self. tr('Extent parameters must use the same CRS as the input layers.\n' 'Your input layers do not have the same extent as the project, ' 'so the extent might be in a wrong CRS if you have selected it from the canvas.\n' 'Do you want to continue?'), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.No: return msg = self.alg._checkParameterValuesBeforeExecuting() if msg: QMessageBox.warning(self, self.tr('Unable to execute algorithm'), msg) return self.btnRun.setEnabled(False) self.btnClose.setEnabled(False) buttons = self.mainWidget.iterateButtons self.iterateParam = None for i in range(len(list(buttons.values()))): button = list(buttons.values())[i] if button.isChecked(): self.iterateParam = list(buttons.keys())[i] break self.progressBar.setMaximum(0) self.lblProgress.setText(self.tr('Processing algorithm...')) # Make sure the Log tab is visible before executing the algorithm try: self.tabWidget.setCurrentIndex(1) self.repaint() except: pass QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) self.setInfo( self.tr('<b>Algorithm {0} starting...</b>').format( self.alg.displayName())) if self.iterateParam: if executeIterating(self.alg, self.iterateParam, self.feedback): self.finish() else: QApplication.restoreOverrideCursor() self.resetGUI() else: command = self.alg.getAsCommand() if command: ProcessingLog.addToLog(ProcessingLog.LOG_ALGORITHM, command) if execute(self.alg, self.feedback): self.finish() else: QApplication.restoreOverrideCursor() self.resetGUI() except AlgorithmDialogBase.InvalidParameterValue as e: try: self.buttonBox.accepted.connect( lambda e=e: e.widget.setPalette(QPalette())) palette = e.widget.palette() palette.setColor(QPalette.Base, QColor(255, 255, 0)) e.widget.setPalette(palette) except: pass self.bar.clearWidgets() self.bar.pushMessage( "", self.tr("Wrong or missing parameter value: {0}").format( e.parameter.description), level=QgsMessageBar.WARNING, duration=5) def finish(self): keepOpen = ProcessingConfig.getSetting( ProcessingConfig.KEEP_DIALOG_OPEN) if self.iterateParam is None: if not handleAlgorithmResults(self.alg, self.feedback, not keepOpen): self.resetGUI() return self.executed = True self.setInfo( self.tr('Algorithm {0} finished').format(self.alg.displayName())) QApplication.restoreOverrideCursor() if not keepOpen: self.close() else: self.resetGUI() if self.alg.getHTMLOutputsCount() > 0: self.setInfo( self.tr('HTML output has been generated by this algorithm.' '\nOpen the results dialog to check it.')) def closeEvent(self, evt): QgsProject.instance().layerWasAdded.disconnect( self.mainWidget.layerRegistryChanged) QgsProject.instance().layersWillBeRemoved.disconnect( self.mainWidget.layerRegistryChanged) super(AlgorithmDialog, self).closeEvent(evt)
def __init__(self, model=None): super().__init__(None) self.setAttribute(Qt.WA_DeleteOnClose) self.setupUi(self) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.centralWidget().layout().insertWidget(0, self.bar) try: self.setDockOptions(self.dockOptions() | QMainWindow.GroupedDragging) except: pass self.mToolbar.setIconSize(iface.iconSize()) self.mActionOpen.setIcon( QgsApplication.getThemeIcon('/mActionFileOpen.svg')) self.mActionSave.setIcon( QgsApplication.getThemeIcon('/mActionFileSave.svg')) self.mActionSaveAs.setIcon( QgsApplication.getThemeIcon('/mActionFileSaveAs.svg')) self.mActionZoomActual.setIcon( QgsApplication.getThemeIcon('/mActionZoomActual.svg')) self.mActionZoomIn.setIcon( QgsApplication.getThemeIcon('/mActionZoomIn.svg')) self.mActionZoomOut.setIcon( QgsApplication.getThemeIcon('/mActionZoomOut.svg')) self.mActionExportImage.setIcon( QgsApplication.getThemeIcon('/mActionSaveMapAsImage.svg')) self.mActionZoomToItems.setIcon( QgsApplication.getThemeIcon('/mActionZoomFullExtent.svg')) self.mActionExportPdf.setIcon( QgsApplication.getThemeIcon('/mActionSaveAsPDF.svg')) self.mActionExportSvg.setIcon( QgsApplication.getThemeIcon('/mActionSaveAsSVG.svg')) #self.mActionExportPython.setIcon( # QgsApplication.getThemeIcon('/mActionSaveAsPython.svg')) self.mActionEditHelp.setIcon( QgsApplication.getThemeIcon('/mActionEditHelpContent.svg')) self.mActionRun.setIcon( QgsApplication.getThemeIcon('/mActionStart.svg')) self.addDockWidget(Qt.LeftDockWidgetArea, self.propertiesDock) self.addDockWidget(Qt.LeftDockWidgetArea, self.inputsDock) self.addDockWidget(Qt.LeftDockWidgetArea, self.algorithmsDock) self.tabifyDockWidget(self.inputsDock, self.algorithmsDock) self.inputsDock.raise_() self.zoom = 1 self.setWindowFlags(Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint | Qt.WindowCloseButtonHint) settings = QgsSettings() self.restoreState( settings.value("/Processing/stateModeler", QByteArray())) self.restoreGeometry( settings.value("/Processing/geometryModeler", QByteArray())) self.scene = ModelerScene(self, dialog=self) self.scene.setSceneRect( QRectF(0, 0, self.CANVAS_SIZE, self.CANVAS_SIZE)) self.view.setScene(self.scene) self.view.setAcceptDrops(True) self.view.ensureVisible(0, 0, 10, 10) def _dragEnterEvent(event): if event.mimeData().hasText(): event.acceptProposedAction() else: event.ignore() def _dropEvent(event): if event.mimeData().hasText(): itemId = event.mimeData().text() if itemId in [ param.id() for param in QgsApplication.instance(). processingRegistry().parameterTypes() ]: self.addInputOfType(itemId, event.pos()) else: alg = QgsApplication.processingRegistry( ).createAlgorithmById(itemId) if alg is not None: self._addAlgorithm(alg, event.pos()) event.accept() else: event.ignore() def _dragMoveEvent(event): if event.mimeData().hasText(): event.accept() else: event.ignore() def _wheelEvent(event): self.view.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) settings = QgsSettings() factor = settings.value('/qgis/zoom_favor', 2.0) # "Normal" mouse has an angle delta of 120, precision mouses provide data # faster, in smaller steps factor = 1.0 + (factor - 1.0) / 120.0 * abs(event.angleDelta().y()) if (event.modifiers() == Qt.ControlModifier): factor = 1.0 + (factor - 1.0) / 20.0 if event.angleDelta().y() < 0: factor = 1 / factor self.view.scale(factor, factor) def _enterEvent(e): QGraphicsView.enterEvent(self.view, e) self.view.viewport().setCursor(Qt.ArrowCursor) def _mouseReleaseEvent(e): QGraphicsView.mouseReleaseEvent(self.view, e) self.view.viewport().setCursor(Qt.ArrowCursor) def _mousePressEvent(e): if e.button() == Qt.MidButton: self.previousMousePos = e.pos() else: QGraphicsView.mousePressEvent(self.view, e) def _mouseMoveEvent(e): if e.buttons() == Qt.MidButton: offset = self.previousMousePos - e.pos() self.previousMousePos = e.pos() self.view.verticalScrollBar().setValue( self.view.verticalScrollBar().value() + offset.y()) self.view.horizontalScrollBar().setValue( self.view.horizontalScrollBar().value() + offset.x()) else: QGraphicsView.mouseMoveEvent(self.view, e) self.view.setDragMode(QGraphicsView.ScrollHandDrag) self.view.dragEnterEvent = _dragEnterEvent self.view.dropEvent = _dropEvent self.view.dragMoveEvent = _dragMoveEvent self.view.wheelEvent = _wheelEvent self.view.enterEvent = _enterEvent self.view.mousePressEvent = _mousePressEvent self.view.mouseMoveEvent = _mouseMoveEvent def _mimeDataInput(items): mimeData = QMimeData() text = items[0].data(0, Qt.UserRole) mimeData.setText(text) return mimeData self.inputsTree.mimeData = _mimeDataInput self.inputsTree.setDragDropMode(QTreeWidget.DragOnly) self.inputsTree.setDropIndicatorShown(True) def _mimeDataAlgorithm(items): item = items[0] mimeData = None if isinstance(item, TreeAlgorithmItem): mimeData = QMimeData() mimeData.setText(item.alg.id()) return mimeData self.algorithmTree.mimeData = _mimeDataAlgorithm self.algorithmTree.setDragDropMode(QTreeWidget.DragOnly) self.algorithmTree.setDropIndicatorShown(True) if hasattr(self.searchBox, 'setPlaceholderText'): self.searchBox.setPlaceholderText( QCoreApplication.translate('ModelerDialog', 'Search…')) if hasattr(self.textName, 'setPlaceholderText'): self.textName.setPlaceholderText(self.tr('Enter model name here')) if hasattr(self.textGroup, 'setPlaceholderText'): self.textGroup.setPlaceholderText(self.tr('Enter group name here')) # Connect signals and slots self.inputsTree.doubleClicked.connect(self.addInput) self.searchBox.textChanged.connect(self.textChanged) self.algorithmTree.doubleClicked.connect(self.addAlgorithm) # Ctrl+= should also trigger a zoom in action ctrlEquals = QShortcut(QKeySequence("Ctrl+="), self) ctrlEquals.activated.connect(self.zoomIn) self.mActionOpen.triggered.connect(self.openModel) self.mActionSave.triggered.connect(self.save) self.mActionSaveAs.triggered.connect(self.saveAs) self.mActionZoomIn.triggered.connect(self.zoomIn) self.mActionZoomOut.triggered.connect(self.zoomOut) self.mActionZoomActual.triggered.connect(self.zoomActual) self.mActionZoomToItems.triggered.connect(self.zoomToItems) self.mActionExportImage.triggered.connect(self.exportAsImage) self.mActionExportPdf.triggered.connect(self.exportAsPdf) self.mActionExportSvg.triggered.connect(self.exportAsSvg) #self.mActionExportPython.triggered.connect(self.exportAsPython) self.mActionEditHelp.triggered.connect(self.editHelp) self.mActionRun.triggered.connect(self.runModel) if model is not None: self.model = model.create() self.model.setSourceFilePath(model.sourceFilePath()) self.textGroup.setText(self.model.group()) self.textName.setText(self.model.displayName()) self.repaintModel() else: self.model = QgsProcessingModelAlgorithm() self.model.setProvider( QgsApplication.processingRegistry().providerById('model')) self.fillInputsTree() self.fillTreeUsingProviders() self.view.centerOn(0, 0) self.help = None self.hasChanged = False