class LessonFinishedDialog(QDialog): def __init__(self, lesson): super(LessonFinishedDialog, self).__init__(iface.mainWindow()) self.reopen = False self.lesson = lesson self.setWindowTitle("Lesson finished") self.verticalLayout = QVBoxLayout() self.verticalLayout.setSpacing(10) self.verticalLayout.setMargin(10) txt = "<p>Congratulations! You have correctly finished this lesson.</p>" if lesson.nextLessons: txt += "<p>We recommend you the following lessons to continue:</p><ul>" for i, nextLesson in enumerate(lesson.nextLessons): txt+="<li><a href='%i'>%s</a>" % (i, nextLesson[1]) txt += "</ul><p>If you don't want to run more lessons, just <a href='exit'>close this dialog.</a></p>" txt += "<p>If you want to run another lesson, click <a href='reopen'>here</a> to reopen the lesson selector</p>" self.text = QTextBrowser() self.text.anchorClicked.connect(self.linkClicked) self.text.setHtml(txt) self.text.setOpenLinks(False) self.verticalLayout.addWidget(self.text) self.setLayout(self.verticalLayout) self.resize(400, 300) self.nextLesson = None def linkClicked(self, url): if url.path() not in ["exit", "reopen"]: self.nextLesson = lessonFromName(*self.lesson.nextLessons[int(url.path())]) if url.path() =="reopen": self.reopen = True self.close()
class SessionFinishedDialog(QDialog): def __init__(self, session): super(SessionFinishedDialog, self).__init__(iface.mainWindow()) self.reopen = False self.session = session self.setWindowTitle("Session finished") self.verticalLayout = QVBoxLayout() self.verticalLayout.setSpacing(10) self.verticalLayout.setMargin(10) txt = "<p>Congratulations! You have correctly finished this session.</p>" if session.nextSessions: txt += "<p>We recommend you the following sessions to continue:</p><ul>" for i, nextSession in enumerate(session.nextSessions): txt += "<li><a href='%i'>%s</a>" % (i, nextSession[1]) txt += "</ul><p>If you don't want to run more sessions, just <a href='exit'>close this dialog.</a></p>" txt += "<p>If you want to run another session, click <a href='reopen'>here</a> to reopen the session selector</p>" self.text = QTextBrowser() self.text.anchorClicked.connect(self.linkClicked) self.text.setHtml(txt) self.text.setOpenLinks(False) self.verticalLayout.addWidget(self.text) self.setLayout(self.verticalLayout) self.resize(400, 300) self.nextSession = None def linkClicked(self, url): if url.path() not in ["exit", "reopen"]: self.nextSession = sessionFromName( *self.session.nextSessions[int(url.path())]) if url.path() == "reopen": self.reopen = True self.close()
def __init__(self, pt): super().__init__(iface.mainWindow()) self.pt = pt layout = QVBoxLayout() textbrowser = QTextBrowser() textbrowser.setOpenLinks(False) textbrowser.setOpenExternalLinks(False) textbrowser.anchorClicked.connect(self._link_clicked) url = ( "https://learn.planet.com/sample-skysat.html?utm_source=defense-and-intelligence&" "amp;utm_medium=website&amp;utm_campaign=skysat-sample-imagery&amp;" "utm_content=skysat-sample-imagery") text = f"""<p><strong>Complete your high resolution imagery order</strong></p> <p><br/>Your custom high resolution imagery order can be completed using Planet’s Tasking Dashboard. The dashboard allows you to place an order to task our SkySat satellite and get high-resolution imagery for your area and time of interest.</p> <p>If you have not yet purchased the ability to order high-resolution imagery, you may download samples<a href="{url}"> here</a> and contact our sales team <a href="https://www.planet.com/contact-sales/"> here</a>.</p> <p> </p> <p"><a href="dashboard">Take me to the Tasking Dashboard</a> </p>""" textbrowser.setHtml(text) layout.addWidget(textbrowser) self.setLayout(layout) self.setFixedSize(600, 400)
def tabChanged(self, tabIdx): THRESHOLD = 1500 if tabIdx != 2: # the full changed view return if self.fullHistory is not None: return if not self.fullDiffSummary: return if self.fullDiffSummaryTotal > THRESHOLD: text = QTextBrowser() text.setHtml( "<br><br><br><center><font size=+3><b>Too many changes to show - {:,} features changed</b></font>" .format(self.fullDiffSummaryTotal)) layout = self.tabWidget.widget(2).layout() self.clearLayout(layout) #layout.setMargin(0) layout.addWidget(text) self.fullHistory = layout #self.tabWidget.widget(2).setLayout(layout) return # need to set it up layout = self.tabWidget.widget(2).layout() self.clearLayout(layout) #layout.setMargin(0) pr = self.prs[self.comboPr.currentText()] prid = pr["id"] total, diffsummary = self.server.diffSummaryPR(self.user, self.repo, prid) if total is None: text = QTextBrowser() text.setHtml( "<br><br><br><center><font size=+3><b>PR is in Conflict - Please Synchronize</b></font>" .format(self.fullDiffSummaryTotal)) layout = self.tabWidget.widget(2).layout() #layout.setMargin(0) self.clearLayout(layout) layout.addWidget(text) self.fullHistory = layout #self.tabWidget.widget(2).setLayout(layout) return layers = [l["path"] for l in diffsummary.values()] diffs = { layer: execute(lambda: list( self.server.diffPR(self.user, self.repo, layer, prid)[1])) for layer in layers } fullDiffView = DiffViewerWidget(diffs) fullDiffView.selectFirstChangedFeature() layout.addWidget(fullDiffView) self.fullHistory = layout
class Info(QDialog): info = [] @classmethod def showInfo(cls, plugin, html, gmlid, parent): info = Info(plugin, html, gmlid, parent) info.setAttribute(Qt.WA_DeleteOnClose) info.setModal(False) cls.info.append(info) info.show() def __init__(self, plugin, html, gmlid, parent): QDialog.__init__(self, parent) self.resize(QSize(740, 580)) self.setWindowTitle(u"Flurstücksnachweis") self.plugin = plugin self.gmlid = gmlid self.tbEigentuemer = QTextBrowser(self) self.tbEigentuemer.setHtml(html) self.tbEigentuemer.setContextMenuPolicy(Qt.NoContextMenu) layout = QVBoxLayout(self) layout.addWidget(self.tbEigentuemer) self.setLayout(layout) self.restoreGeometry(QSettings("norBIT", "norGIS-ALKIS-Erweiterung").value("infogeom", QByteArray(), type=QByteArray)) self.move(self.pos() + QPoint(16, 16) * len(self.info)) def print_(self): printer = QPrinter() dlg = QPrintDialog(printer) if dlg.exec_() == QDialog.Accepted: self.tbEigentuemer.print_(printer) def contextMenuEvent(self, e): menu = QMenu(self) action = QAction("Drucken", self) action.triggered.connect(self.print_) menu.addAction(action) menu.exec_(e.globalPos()) def closeEvent(self, e): QSettings("norBIT", "norGIS-ALKIS-Erweiterung").setValue("infogeom", self.saveGeometry()) self.info.remove(self) self.plugin.clearHighlight() QDialog.closeEvent(self, e) def event(self, e): if e.type() == QEvent.WindowActivate: self.plugin.highlight(where="gml_id='{}'".format(self.gmlid)) return QDialog.event(self, e)
class Info(QDialog): info = [] @classmethod def showInfo(cls, plugin, html, gmlid, parent): info = Info(plugin, html, gmlid, parent) info.setAttribute(Qt.WA_DeleteOnClose) info.setModal(False) cls.info.append(info) info.show() def __init__(self, plugin, html, gmlid, parent): QDialog.__init__(self, parent) self.resize(QSize(740, 580)) self.setWindowTitle(u"Flurstücksnachweis") self.plugin = plugin self.gmlid = gmlid self.tbEigentuemer = QTextBrowser(self) self.tbEigentuemer.setHtml(html) self.tbEigentuemer.setContextMenuPolicy(Qt.NoContextMenu) layout = QVBoxLayout(self) layout.addWidget(self.tbEigentuemer) self.setLayout(layout) self.restoreGeometry(QSettings("norBIT", "norGIS-ALKIS-Erweiterung").value("infogeom", QByteArray(), type=QByteArray)) self.move(self.pos() + QPoint(16, 16) * (len(self.info) - 1)) def print_(self): printer = QPrinter() dlg = QPrintDialog(printer) if dlg.exec_() == QDialog.Accepted: self.tbEigentuemer.print_(printer) def contextMenuEvent(self, e): menu = QMenu(self) action = QAction("Drucken", self) action.triggered.connect(self.print_) menu.addAction(action) menu.exec_(e.globalPos()) def closeEvent(self, e): QSettings("norBIT", "norGIS-ALKIS-Erweiterung").setValue("infogeom", self.saveGeometry()) QDialog.closeEvent(self, e) self.info.remove(self) def event(self, e): if e.type() == QEvent.WindowActivate: self.plugin.highlight(where="gml_id='{}'".format(self.gmlid)) return QDialog.event(self, e)
class HtmlDialog(QDialog): def __init__(self, title, content, parent=None): super(HtmlDialog, self).__init__(parent) self.setWindowTitle(title) self.verticalLayout = QVBoxLayout() self.verticalLayout.setSpacing(10) self.verticalLayout.setMargin(10) self.text = QTextBrowser() self.text.setHtml(content) self.verticalLayout.addWidget(self.text) self.setLayout(self.verticalLayout) self.resize(400, 400)
def _on_tb_btn_clicked(message, tb_text): vbox = QVBoxLayout() dlg = QDialog() dlg.setWindowTitle('Traceback') text_browser = QTextBrowser() unformatted_msg = message formatted_msg = highlight(tb_text, PythonLexer(), HtmlFormatter(full=True)) text_browser.setHtml(unformatted_msg + formatted_msg) vbox.addWidget(text_browser) dlg.setLayout(vbox) dlg.setMinimumSize(700, 500) dlg.exec_()
class RedistrictingDockWidget(QgsDockWidget): """ Dock widget for display of redistricting statistics and operations """ def __init__(self, _iface: QgisInterface = None): super().__init__() if _iface is not None: self.iface = _iface else: self.iface = iface dock_contents = QWidget() grid = QGridLayout(dock_contents) grid.setContentsMargins(0, 0, 0, 0) self._dock_toolbar = QToolBar(dock_contents) self._dock_toolbar.setFloatable(False) grid.addWidget(self._dock_toolbar, 0, 0, 1, 1) self._dock_toolbar.setIconSize(self.iface.iconSize(True)) self.frame = QTextBrowser() self.frame.setOpenLinks(False) self.frame.anchorClicked.connect(self.anchor_clicked) grid.addWidget(self.frame, 1, 0, 1, 1) self.setWidget(dock_contents) def dock_toolbar(self): """ Returns the dock toolbar """ return self._dock_toolbar def show_message(self, html): """ Shows a HTML formatted message in the dock, replacing its current contents :param html: HTML to show """ self.frame.setHtml(html) self.setUserVisible(True) def anchor_clicked(self, link: QUrl): """ Called on clicking an anchor link in the dock frame :param link: link clicked """ pass # pylint: disable=unnecessary-pass
def setHtml(self, html): # convert special tags :) html = str(html).replace( '<warning>', '<img src=":/db_manager/warning"> ') # add default style html = u""" <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <style type="text/css"> .section { margin-top: 25px; } table.header th { background-color: #dddddd; } table.header td { background-color: #f5f5f5; } table.header th, table.header td { padding: 0px 10px; } table td { padding-right: 20px; } .underline { text-decoration:underline; } </style> </head> <body> %s <br> </body> </html> """ % html # print ">>>>>\n", html, "\n<<<<<<" return QTextBrowser.setHtml(self, html)
def setHtml(self, html): # convert special tags :) html = unicode(html).replace('<warning>', '<img src=":/db_manager/warning"> ') # add default style html = u""" <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <style type="text/css"> .section { margin-top: 25px; } table.header th { background-color: #dddddd; } table.header td { background-color: #f5f5f5; } table.header th, table.header td { padding: 0px 10px; } table td { padding-right: 20px; } .underline { text-decoration:underline; } </style> </head> <body> %s <br> </body> </html> """ % html # print ">>>>>\n", html, "\n<<<<<<" return QTextBrowser.setHtml(self, html)
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 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.name) 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: 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.name) 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 = QScrollArea() 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): if self._algName is None: dependent = [] else: dependent = self.model.getDependentAlgorithms(self._algName) opts = [] for alg in list(self.model.algs.values()): if alg.name not in dependent: opts.append(alg) return opts def getDependenciesPanel(self): return MultipleInputPanel([alg.description for alg in self.getAvailableDependencies()]) 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.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.name, out.name)) else: values.append(ValueFromOutput(alg.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("'%s' from algorithm '%s'") % (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() 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.commandLineName()) 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() for selected in selectedOptions: alg.dependencies.append(availableDependencies[selected].name) 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 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.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.name) 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)') label = QLabel(desc) self.labels[param.name] = label widget = self.getWidgetFromParameter(param) self.valueItems[param.name] = widget if param.name in 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.setLayout(self.verticalLayout) self.setPreviousValues() self.setWindowTitle(self._alg.name) 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 = QScrollArea() 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.reply = QgsNetworkAccessManager.instance().get( QNetworkRequest(algHelp)) self.reply.finished.connect(self.requestFinished) except: self.txtHelp.setHtml( self.tr('<h2>No help available for this algorithm</h2>')) self.tabWidget.addTab(self.txtHelp, 'Help') 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) 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 = unicode(reply.readAll()) reply.deleteLater() self.txtHelp.setHtml(html) def getAvailableDependencies(self): if self._algName is None: dependent = [] else: dependent = self.model.getDependentAlgorithms(self._algName) opts = [] for alg in self.model.algs.values(): if alg.name not in dependent: opts.append(alg) return opts def getDependenciesPanel(self): return MultipleInputPanel( [alg.algorithm.name for alg in self.getAvailableDependencies()]) 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): values = [] inputs = self.model.inputs for i in inputs.values(): param = i.param if isinstance(param, paramType): values.append(ValueFromInput(param.name)) if outType is None: return values if self._algName is None: dependent = [] else: dependent = self.model.getDependentAlgorithms(self._algName) for alg in self.model.algs.values(): if alg.name not in dependent: for out in alg.algorithm.outputs: if isinstance(out, outType): values.append(ValueFromOutput(alg.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("'%s' from algorithm '%s'") % ( alg.algorithm.getOutputFromName( value.output).description, alg.description) def getWidgetFromParameter(self, param): if isinstance(param, ParameterRaster): item = QComboBox() layers = self.getAvailableValuesOfType(ParameterRaster, OutputRaster) if param.optional: item.addItem(self.NOT_SELECTED, None) for layer in layers: item.addItem(self.resolveValueDescription(layer), layer) elif isinstance(param, ParameterVector): item = QComboBox() layers = self.getAvailableValuesOfType(ParameterVector, OutputVector) if param.optional: item.addItem(self.NOT_SELECTED, None) for layer in layers: item.addItem(self.resolveValueDescription(layer), layer) elif isinstance(param, ParameterTable): item = QComboBox() tables = self.getAvailableValuesOfType(ParameterTable, OutputTable) layers = self.getAvailableValuesOfType(ParameterVector, OutputVector) if param.optional: item.addItem(self.NOT_SELECTED, None) for table in tables: item.addItem(self.resolveValueDescription(table), table) for layer in layers: item.addItem(self.resolveValueDescription(layer), layer) elif isinstance(param, ParameterBoolean): item = QComboBox() item.addItem('Yes') item.addItem('No') bools = self.getAvailableValuesOfType(ParameterBoolean, None) for b in bools: item.addItem(self.resolveValueDescription(b), b) if param.default: item.setCurrentIndex(0) else: item.setCurrentIndex(1) elif isinstance(param, ParameterSelection): item = QComboBox() item.addItems(param.options) item.setCurrentIndex(param.default or 0) elif isinstance(param, ParameterFixedTable): item = FixedTablePanel(param) elif isinstance(param, ParameterRange): item = RangePanel(param) elif isinstance(param, ParameterMultipleInput): if param.datatype == ParameterMultipleInput.TYPE_VECTOR_ANY: options = self.getAvailableValuesOfType( ParameterVector, OutputVector) else: options = self.getAvailableValuesOfType( ParameterRaster, OutputRaster) opts = [] for opt in options: opts.append(self.resolveValueDescription(opt)) item = MultipleInputPanel(opts) elif isinstance(param, ParameterString): strings = self.getAvailableValuesOfType(ParameterString, OutputString) options = [(self.resolveValueDescription(s), s) for s in strings] if param.multiline: item = MultilineTextPanel(options) item.setText(unicode(param.default or "")) else: item = QComboBox() item.setEditable(True) for desc, val in options: item.addItem(desc, val) item.setEditText(unicode(param.default or "")) elif isinstance(param, ParameterTableField): item = QComboBox() item.setEditable(True) fields = self.getAvailableValuesOfType(ParameterTableField, None) for f in fields: item.addItem(self.resolveValueDescription(f), f) elif isinstance(param, ParameterTableMultipleField): item = QComboBox() item.setEditable(True) fields = self.getAvailableValuesOfType(ParameterTableMultipleField, None) for f in fields: item.addItem(self.resolveValueDescription(f), f) elif isinstance(param, ParameterNumber): item = QComboBox() item.setEditable(True) numbers = self.getAvailableValuesOfType(ParameterNumber, OutputNumber) for n in numbers: item.addItem(self.resolveValueDescription(n), n) item.setEditText(unicode(param.default)) elif isinstance(param, ParameterCrs): item = CrsSelectionPanel(param.default) elif isinstance(param, ParameterExtent): item = QComboBox() item.setEditable(True) extents = self.getAvailableValuesOfType(ParameterExtent, OutputExtent) if self.canUseAutoExtent(): item.addItem(self.USE_MIN_COVERING_EXTENT, None) for ex in extents: item.addItem(self.resolveValueDescription(ex), ex) if not self.canUseAutoExtent(): item.setEditText(unicode(param.default)) elif isinstance(param, ParameterPoint): item = QComboBox() item.setEditable(True) points = self.getAvailableValuesOfType(ParameterPoint) for p in points: item.addItem(self.resolveValueDescription(p), p) item.setEditText(unicode(param.default)) elif isinstance(param, ParameterFile): item = QComboBox() item.setEditable(True) files = self.getAvailableValuesOfType(ParameterFile, OutputFile) for f in files: item.addItem(self.resolveValueDescription(f), f) elif isinstance(param, ParameterGeometryPredicate): item = GeometryPredicateSelectionPanel(param.enabledPredicates) else: item = QLineEdit() try: item.setText(unicode(param.default)) except: pass return item def canUseAutoExtent(self): for param in self._alg.parameters: if isinstance( param, (ParameterRaster, ParameterVector, ParameterMultipleInput)): return True return False def setTableContent(self): params = self._alg.parameters outputs = self._alg.outputs visibleParams = [p for p in params if not p.hidden] visibleOutputs = [p for o in outputs if not o.hidden] self.tableWidget.setRowCount(len(visibleParams) + len(visibleOutputs)) for i, param in visibleParams: item = QTableWidgetItem(param.description) item.setFlags(Qt.ItemIsEnabled) self.tableWidget.setItem(i, 0, item) item = self.getWidgetFromParameter(param) self.valueItems[param.name] = item self.tableWidget.setCellWidget(i, 1, item) self.tableWidget.setRowHeight(i, 22) for i, output in visibleOutputs: item = QTableWidgetItem(output.description + '<' + output.__module__.split('.')[-1] + '>') item.setFlags(Qt.ItemIsEnabled) self.tableWidget.setItem(i, 0, item) item = QLineEdit() if hasattr(item, 'setPlaceholderText'): item.setPlaceholderText(ModelerParametersDialog.ENTER_NAME) self.valueItems[output.name] = item self.tableWidget.setCellWidget(i, 1, item) self.tableWidget.setRowHeight(i, 22) def setComboBoxValue(self, combo, value, param): if isinstance(value, list): value = value[0] items = [combo.itemData(i) for i in range(combo.count())] try: idx = items.index(value) combo.setCurrentIndex(idx) return except ValueError: pass if combo.isEditable(): if value is not None: combo.setEditText(unicode(value)) elif isinstance(param, ParameterSelection): combo.setCurrentIndex(int(value)) elif isinstance(param, ParameterBoolean): if value: combo.setCurrentIndex(0) else: combo.setCurrentIndex(1) 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 widget = self.valueItems[param.name] if param.name in alg.params: value = alg.params[param.name] else: value = param.default if isinstance( param, (ParameterRaster, ParameterVector, ParameterTable, ParameterTableField, ParameterSelection, ParameterNumber, ParameterBoolean, ParameterExtent, ParameterFile, ParameterPoint)): self.setComboBoxValue(widget, value, param) elif isinstance(param, ParameterString): if param.multiline: widget.setValue(value) else: self.setComboBoxValue(widget, value, param) elif isinstance(param, ParameterCrs): widget.setAuthId(value) elif isinstance(param, ParameterFixedTable): pass # TODO! elif isinstance(param, ParameterMultipleInput): if param.datatype == ParameterMultipleInput.TYPE_VECTOR_ANY: options = self.getAvailableValuesOfType( ParameterVector, OutputVector) else: options = self.getAvailableValuesOfType( ParameterRaster, OutputRaster) selected = [] for i, opt in enumerate(options): if opt in value: selected.append(i) widget.setSelectedItems(selected) elif isinstance(param, ParameterGeometryPredicate): widget.setValue(value) for name, out in alg.outputs.iteritems(): widget = self.valueItems[name].setText(out.description) selected = [] dependencies = self.getAvailableDependencies() 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.commandLineName()) 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.valueItems[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 = unicode(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() for selected in selectedOptions: alg.dependencies.append(availableDependencies[selected].name) return alg def setParamValueLayerOrTable(self, alg, param, widget): idx = widget.currentIndex() if idx < 0: return False else: value = widget.itemData(widget.currentIndex()) alg.params[param.name] = value return True def setParamTableFieldValue(self, alg, param, widget): idx = widget.findText(widget.currentText()) if idx < 0: s = unicode(widget.currentText()).strip() if s == '': if param.optional: alg.params[param.name] = None return True else: return False else: alg.params[param.name] = s return True else: alg.params[param.name] = widget.itemData(widget.currentIndex()) return True def setParamStringValue(self, alg, param, widget): if param.multiline: value = widget.getValue() option = widget.getOption() if option == MultilineTextPanel.USE_TEXT: if value == '': if param.optional: alg.params[param.name] = None return True else: return False else: alg.params[param.name] = value else: alg.params[param.name] = value else: idx = widget.findText(widget.currentText()) if idx < 0: value = widget.currentText().strip() if value == '': if param.optional: alg.params[param.name] = None return True else: return False else: alg.params[param.name] = value else: alg.params[param.name] = widget.itemData(widget.currentIndex()) return True def setParamFileValue(self, alg, param, widget): idx = widget.findText(widget.currentText()) if idx < 0: value = widget.currentText() else: value = widget.itemData(widget.currentIndex()) alg.params[param.name] = value return True def setParamNumberValue(self, alg, param, widget): idx = widget.findText(widget.currentText()) if idx < 0: s = widget.currentText().strip() if s: try: value = float(s) except: return False elif param.optional: value = None else: return False else: value = widget.itemData(widget.currentIndex()) alg.params[param.name] = value return True def setParamExtentValue(self, alg, param, widget): idx = widget.findText(widget.currentText()) if idx < 0: s = unicode(widget.currentText()).strip() if s: try: tokens = s.split(',') if len(tokens) != 4: return False for token in tokens: float(token) except: return False elif param.optional: s = None else: return False alg.params[param.name] = [s] else: value = widget.itemData(widget.currentIndex()) alg.params[param.name] = value return True def setParamPointValue(self, alg, param, widget): idx = widget.findText(widget.currentText()) if idx < 0: s = unicode(widget.currentText()).strip() if s: try: tokens = s.split(',') if len(tokens) != 2: return False for token in tokens: float(token) except: return False elif param.optional: s = None else: return False alg.params[param.name] = [s] else: value = widget.itemData(widget.currentIndex()) alg.params[param.name] = value return True def setParamValue(self, alg, param, widget): if isinstance(param, (ParameterRaster, ParameterVector, ParameterTable)): return self.setParamValueLayerOrTable(alg, param, widget) elif isinstance(param, ParameterBoolean): if widget.currentIndex() < 2: value = widget.currentIndex() == 0 else: value = widget.itemData(widget.currentIndex()) alg.params[param.name] = value return True elif isinstance(param, ParameterString): return self.setParamStringValue(alg, param, widget) elif isinstance(param, ParameterNumber): return self.setParamNumberValue(alg, param, widget) elif isinstance(param, ParameterExtent): return self.setParamExtentValue(alg, param, widget) elif isinstance(param, ParameterPoint): return self.setParamPointValue(alg, param, widget) elif isinstance(param, ParameterFile): return self.setParamFileValue(alg, param, widget) elif isinstance(param, ParameterSelection): alg.params[param.name] = widget.currentIndex() return True elif isinstance(param, ParameterRange): alg.params[param.name] = widget.getValue() return True elif isinstance(param, ParameterCrs): authid = widget.getValue() if authid is None and not param.optional: return False alg.params[param.name] = authid return True elif isinstance(param, ParameterFixedTable): table = widget.table if not bool(table) and not param.optional: return False alg.params[param.name] = ParameterFixedTable.tableToString(table) return True elif isinstance(param, (ParameterTableField, ParameterTableMultipleField)): return self.setParamTableFieldValue(alg, param, widget) elif isinstance(param, ParameterMultipleInput): if param.datatype == ParameterMultipleInput.TYPE_VECTOR_ANY: options = self.getAvailableValuesOfType( ParameterVector, OutputVector) else: options = self.getAvailableValuesOfType( ParameterRaster, OutputRaster) values = [options[i] for i in widget.selectedoptions] if len(values) == 0 and not param.optional: return False alg.params[param.name] = values return True elif isinstance(param, ParameterGeometryPredicate): alg.params[param.name] = widget.value() return True else: alg.params[param.name] = unicode(widget.text()) return True def okPressed(self): self.alg = self.createAlgorithm() if self.alg is not None: self.close() def cancelPressed(self): self.alg = None self.close()
class HistoryDiffViewerWidget(QWidget): def __init__(self, dialog, server, user, repo, graph, layer=None, initialSimplify=False): self.graph = graph self.dialog = dialog self.server = server self.user = user self.repo = repo self.layer = layer self.afterLayer = None self.beforeLayer = None self.extraLayers = [] # layers for the "Map" tab QWidget.__init__(self, iface.mainWindow()) self.setWindowFlags(Qt.Window) self.simplifyLog = initialSimplify self.initGui() self.tabWidget.setVisible(False) self.setLabelText("Select a commit to show its content") self.label.setVisible(False) if self.graph.commits: self.history.setCurrentItem(self.history.topLevelItem(0)) self.itemChanged(self.history.topLevelItem(0), None) self.history.currentItemChanged.connect(self.itemChanged) def setShowPopup(self, show): self.history.showPopup = show def initGui(self): layout = QVBoxLayout() splitter = QSplitter() splitter.setOrientation(Qt.Vertical) self.history = HistoryTree(self.dialog) self.history.updateContent(self.server, self.user, self.repo, self.graph, self.layer) self.historyWithFilter = HistoryTreeWrapper(self.history) if self.simplifyLog: self.historyWithFilter.simplify(True) splitter.addWidget(self.historyWithFilter) self.tabWidget = QTabWidget() self.tabCanvas = QWidget() tabLayout = QVBoxLayout() tabLayout.setMargin(0) self.canvas = QgsMapCanvas(self.tabCanvas) self.canvas.setCanvasColor(Qt.white) self.panTool = QgsMapToolPan(self.canvas) self.canvas.setMapTool(self.panTool) tabLayout.addWidget(self.canvas) self.labelNoChanges = QLabel("This commit doesn't change any geometry") self.labelNoChanges.setAlignment(Qt.AlignCenter) self.labelNoChanges.setVisible(False) tabLayout.addWidget(self.labelNoChanges) self.tabCanvas.setLayout(tabLayout) self.summaryTextBrowser = QTextBrowser() self.summaryTextBrowser.setOpenLinks(False) self.summaryTextBrowser.anchorClicked.connect(self.summaryTextBrowserAnchorClicked) self.tabWidget.addTab(self.summaryTextBrowser, "Commit Summary") self.tabWidget.addTab(self.tabCanvas, "Map") tabLayout = QVBoxLayout() tabLayout.setMargin(0) self.tabDiffViewer = QWidget() self.diffViewer = DiffViewerWidget({}) tabLayout.addWidget(self.diffViewer) self.tabDiffViewer.setLayout(tabLayout) self.tabWidget.addTab(self.tabDiffViewer, "Attributes") splitter.addWidget(self.tabWidget) self.label = QTextBrowser() self.label.setVisible(False) splitter.addWidget(self.label) self.tabWidget.setCurrentWidget(self.tabDiffViewer) layout.addWidget(splitter) self.setLayout(layout) exportDiffButton = QPushButton("Export this commit's DIFF for all layers") exportDiffButton.clicked.connect(self.exportDiffAllLayers) layout.addWidget(exportDiffButton) self.label.setMinimumHeight(self.tabWidget.height()) self.setWindowTitle("Repository history") def summaryTextBrowserAnchorClicked(self,url): url = url.url() #convert to string item = self.history.currentItem() if item is None: return commitid = item.commit.commitid cmd,layerName = url.split(".",1) if cmd == "addLive": execute(lambda: self.history.exportVersion(layerName,commitid,True)) elif cmd == "addGeoPKG": self.history.exportVersion(layerName,commitid,False) elif cmd == "exportDiff": execute(lambda: self.history.exportDiff(item, None,layer=layerName)) def exportDiffAllLayers(self): item = self.history.currentItem() if item is not None: self.history.exportDiff(item, None) def setLabelText(self,text): self.label.setHtml("<br><br><br><center><b>{}</b></center>".format(text)) def setContent(self, server, user, repo, graph, layer = None): self.server = server self.user = user self.repo = repo self.layer = layer self.graph = graph self.historyWithFilter.updateContent(server, user, repo, graph, layer) if self.history.graph.commits: self.history.setCurrentItem(self.history.topLevelItem(0)) def itemChanged(self, current, previous, THRESHOLD = 1500): item = self.history.currentItem() if item is not None: commit = self.graph.getById(item.ref) if commit is None: self.tabWidget.setVisible(False) self.setLabelText("Select a commit to show its content") self.label.setVisible(True) return commit2 = commit.commitid + "~1" if not item.commit.hasParents(): commit2 = "0000000000000000" total,details = self.server.diffSummary(self.user, self.repo, commit2,commit.commitid) tooLargeDiff = total > THRESHOLD if tooLargeDiff: html = "<br><br><center><b><font size=+3>Commit <font size=-0.1><tt>{}</tt></font> DIFF is too large to be shown</b></font><br>".format(commit.commitid[:8]) else: html = "<br><br><center><b><font size=+3>Commit <font size=-0.1><tt>{}</tt></font> Summary</b></font><br>".format(commit.commitid[:8]) html += "<table>" html += "<tr><Td style='padding:5px'><b>Layer Name</b></td><td style='padding:5px'><b>Additions</b></td><td style='padding:5px'><b>Deletions</b></td><td style='padding:5px'><b>Modifications</b></td><td></td><td></td><td></td></tr>" for detail in details.values(): html += "<tr><td style='padding:5px'>{}</td><td style='padding:5px'><center>{:,}</center></td><td style='padding:5px'><center>{:,}</center></td><td style='padding:5px'><center>{:,}</center></td><td style='padding:5px'>{}</td><td style='padding:5px'>{}</td><td style='padding:5px'>{}</td></tr>".format( detail["path"], int(detail["featuresAdded"]), int(detail["featuresRemoved"]),int(detail["featuresChanged"]), "<a href='addLive.{}'>Add Live</a>".format(detail["path"]), "<a href='addGeoPKG.{}'>Add GeoPKG</a>".format(detail["path"]), "<a href='exportDiff.{}'>Export Diff</a>".format(detail["path"]) ) html += "<tr></tr>" html += "<tr><td colspan=4>There is a total of {:,} features changed</td></tr>".format(total) html += "</table>" # html += "<br><br>There is a total of {:,} features changed".format(total) self.summaryTextBrowser.setHtml(html) self.label.setVisible(False) self.tabWidget.setVisible(True) self.tabWidget.setTabEnabled(1,not tooLargeDiff) self.tabWidget.setTabEnabled(2,not tooLargeDiff) if not tooLargeDiff: self.setDiffContent(commit, commit2) else: self.tabWidget.setVisible(False) self.setLabelText("Select a commit to show its content") self.label.setVisible(True) def setDiffContent(self, commit, commit2): if self.layer is None: layers = set(self.server.layers(self.user, self.repo, commit.commitid)) layers2 = set(self.server.layers(self.user, self.repo, commit2)) layers = layers.union(layers2) else: layers = [self.layer] diffs = {layer: execute(lambda: self.server.diff(self.user, self.repo, layer, commit.commitid, commit2)) for layer in layers} diffs = {key:value for (key,value) in diffs.items() if len(value) !=0} layers = [l for l in diffs.keys()] self.diffViewer.setChanges(diffs) self.canvas.setLayers([]) self.removeMapLayers() extent = QgsRectangle() for layer in layers: if not diffs[layer]: continue beforeLayer, afterLayer = execute(lambda: self._getLayers(diffs[layer])) if afterLayer is not None: resourcesPath = os.path.join(os.path.dirname(__file__), os.pardir, "resources") oldStylePath = os.path.join(resourcesPath, "{}_before.qml".format( QgsWkbTypes.geometryDisplayString(beforeLayer.geometryType()))) newStylePath = os.path.join(resourcesPath, "{}_after.qml".format( QgsWkbTypes.geometryDisplayString(afterLayer.geometryType()))) beforeLayer.loadNamedStyle(oldStylePath) afterLayer.loadNamedStyle(newStylePath) QgsProject.instance().addMapLayer(beforeLayer, False) QgsProject.instance().addMapLayer(afterLayer, False) extent.combineExtentWith(beforeLayer.extent()) extent.combineExtentWith(afterLayer.extent()) self.extraLayers.append(beforeLayer) self.extraLayers.append(afterLayer) # make extent a bit bit (10%) bigger # this gives some margin around the dataset (not cut-off at edges) if not extent.isEmpty(): widthDelta = extent.width() * 0.05 heightDelta = extent.height() * 0.05 extent = QgsRectangle(extent.xMinimum() - widthDelta, extent.yMinimum() - heightDelta, extent.xMaximum() + widthDelta, extent.yMaximum() + heightDelta) layers = self.extraLayers hasChanges = False for layer in layers: if layer is not None and layer.featureCount() > 0: hasChanges = True break self.canvas.setLayers(layers) self.canvas.setExtent(extent) self.canvas.refresh() self.canvas.setVisible(hasChanges) self.labelNoChanges.setVisible(not hasChanges) def _getLayers(self, changes): ADDED, MODIFIED, REMOVED, = 0, 1, 2 def _feature(g, changeType): feat = QgsFeature() if g is not None: feat.setGeometry(g) feat.setAttributes([changeType]) return feat if changes: f = changes[0] new = f["new"] old = f["old"] reference = new or old geomtype = QgsWkbTypes.displayString(reference.geometry().wkbType()) oldLayer = loadLayerNoCrsDialog(geomtype + "?crs=epsg:4326&field=geogig.changeType:integer", "old", "memory") newLayer = loadLayerNoCrsDialog(geomtype + "?crs=epsg:4326&field=geogig.changeType:integer", "new", "memory") oldFeatures = [] newFeatures = [] for f in changes: new = f["new"] old = f["old"] newGeom = new.geometry() if new is not None else None oldGeom = old.geometry() if old is not None else None if oldGeom is None: feature = _feature(newGeom, ADDED) newFeatures.append(feature) elif newGeom is None: feature = _feature(oldGeom, REMOVED) oldFeatures.append(feature) elif oldGeom.asWkt() != newGeom.asWkt(): feature = _feature(oldGeom, MODIFIED) oldFeatures.append(feature) feature = _feature(newGeom, MODIFIED) newFeatures.append(feature) else: feature = _feature(newGeom, MODIFIED) newFeatures.append(feature) oldLayer.dataProvider().addFeatures(oldFeatures) newLayer.dataProvider().addFeatures(newFeatures) else: oldLayer = None newLayer = None return oldLayer, newLayer def removeMapLayers(self): for layer in self.extraLayers: if layer is not None: QgsProject.instance().removeMapLayer(layer.id()) self.extraLayers = []
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.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.name) 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)') label = QLabel(desc) self.labels[param.name] = label widget = self.getWidgetFromParameter(param) 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.setLayout(self.verticalLayout) self.setPreviousValues() self.setWindowTitle(self._alg.name) 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 = QScrollArea() 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.reply = QgsNetworkAccessManager.instance().get(QNetworkRequest(algHelp)) self.reply.finished.connect(self.requestFinished) except: self.txtHelp.setHtml(self.tr('<h2>No help available for this algorithm</h2>')) self.tabWidget.addTab(self.txtHelp, 'Help') 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) 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): if self._algName is None: dependent = [] else: dependent = self.model.getDependentAlgorithms(self._algName) opts = [] for alg in list(self.model.algs.values()): if alg.name not in dependent: opts.append(alg) return opts def getDependenciesPanel(self): return MultipleInputPanel([alg.algorithm.name for alg in self.getAvailableDependencies()]) 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): values = [] inputs = self.model.inputs for i in list(inputs.values()): param = i.param if isinstance(param, paramType): if dataType is not None and param.datatype in dataType: values.append(ValueFromInput(param.name)) else: values.append(ValueFromInput(param.name)) 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.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.name, out.name)) else: values.append(ValueFromOutput(alg.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("'%s' from algorithm '%s'") % (alg.algorithm.getOutputFromName(value.output).description, alg.description) def getWidgetFromParameter(self, param): if isinstance(param, ParameterRaster): item = QComboBox() layers = self.getAvailableValuesOfType(ParameterRaster, OutputRaster) if param.optional: item.addItem(self.NOT_SELECTED, None) for layer in layers: item.addItem(self.resolveValueDescription(layer), layer) elif isinstance(param, ParameterVector): item = QComboBox() layers = self.getAvailableValuesOfType(ParameterVector, OutputVector) if param.optional: item.addItem(self.NOT_SELECTED, None) for layer in layers: item.addItem(self.resolveValueDescription(layer), layer) elif isinstance(param, ParameterTable): item = QComboBox() tables = self.getAvailableValuesOfType(ParameterTable, OutputTable) layers = self.getAvailableValuesOfType(ParameterVector, OutputVector) if param.optional: item.addItem(self.NOT_SELECTED, None) for table in tables: item.addItem(self.resolveValueDescription(table), table) for layer in layers: item.addItem(self.resolveValueDescription(layer), layer) elif isinstance(param, ParameterBoolean): item = QComboBox() item.addItem('Yes') item.addItem('No') bools = self.getAvailableValuesOfType(ParameterBoolean, None) for b in bools: item.addItem(self.resolveValueDescription(b), b) if param.default: item.setCurrentIndex(0) else: item.setCurrentIndex(1) elif isinstance(param, ParameterSelection): item = QComboBox() item.addItems(param.options) item.setCurrentIndex(param.default or 0) elif isinstance(param, ParameterFixedTable): item = FixedTablePanel(param) elif isinstance(param, ParameterRange): item = RangePanel(param) elif isinstance(param, ParameterMultipleInput): if param.datatype == dataobjects.TYPE_VECTOR_ANY: options = self.getAvailableValuesOfType(ParameterVector, OutputVector) elif param.datatype == dataobjects.TYPE_VECTOR_POINT: options = self.getAvailableValuesOfType(ParameterVector, OutputVector, [dataobjects.TYPE_VECTOR_POINT, dataobjects.TYPE_VECTOR_ANY]) elif param.datatype == dataobjects.TYPE_VECTOR_LINE: options = self.getAvailableValuesOfType(ParameterVector, OutputVector, [dataobjects.TYPE_VECTOR_LINE, dataobjects.TYPE_VECTOR_ANY]) elif param.datatype == dataobjects.TYPE_VECTOR_POLYGON: options = self.getAvailableValuesOfType(ParameterVector, OutputVector, [dataobjects.TYPE_VECTOR_POLYGON, dataobjects.TYPE_VECTOR_ANY]) elif param.datatype == dataobjects.TYPE_RASTER: options = self.getAvailableValuesOfType(ParameterRaster, OutputRaster) else: options = self.getAvailableValuesOfType(ParameterFile, OutputFile) opts = [] for opt in options: opts.append(self.resolveValueDescription(opt)) item = MultipleInputPanel(opts) elif isinstance(param, ParameterString): strings = self.getAvailableValuesOfType(ParameterString, OutputString) options = [(self.resolveValueDescription(s), s) for s in strings] if param.multiline: item = MultilineTextPanel(options) item.setText(str(param.default or "")) else: item = QComboBox() item.setEditable(True) for desc, val in options: item.addItem(desc, val) item.setEditText(str(param.default or "")) elif isinstance(param, ParameterTableField): item = QComboBox() item.setEditable(True) fields = self.getAvailableValuesOfType(ParameterTableField, None) for f in fields: item.addItem(self.resolveValueDescription(f), f) elif isinstance(param, ParameterTableMultipleField): item = QComboBox() item.setEditable(True) fields = self.getAvailableValuesOfType(ParameterTableMultipleField, None) for f in fields: item.addItem(self.resolveValueDescription(f), f) elif isinstance(param, ParameterNumber): item = QComboBox() item.setEditable(True) numbers = self.getAvailableValuesOfType(ParameterNumber, OutputNumber) for n in numbers: item.addItem(self.resolveValueDescription(n), n) item.setEditText(str(param.default)) elif isinstance(param, ParameterCrs): item = QComboBox() values = self.getAvailableValuesOfType(ParameterCrs, OutputCrs) for v in values: item.addItem(self.resolveValueDescription(v), v) elif isinstance(param, ParameterExtent): item = QComboBox() item.setEditable(True) extents = self.getAvailableValuesOfType(ParameterExtent, OutputExtent) if self.canUseAutoExtent(): item.addItem(self.USE_MIN_COVERING_EXTENT, None) for ex in extents: item.addItem(self.resolveValueDescription(ex), ex) if not self.canUseAutoExtent(): item.setEditText(str(param.default)) elif isinstance(param, ParameterPoint): item = QComboBox() item.setEditable(True) points = self.getAvailableValuesOfType(ParameterPoint) for p in points: item.addItem(self.resolveValueDescription(p), p) item.setEditText(str(param.default)) elif isinstance(param, ParameterFile): item = QComboBox() item.setEditable(True) files = self.getAvailableValuesOfType(ParameterFile, OutputFile) for f in files: item.addItem(self.resolveValueDescription(f), f) elif isinstance(param, ParameterGeometryPredicate): item = GeometryPredicateSelectionPanel(param.enabledPredicates) else: item = QLineEdit() try: item.setText(str(param.default)) except: pass return item def canUseAutoExtent(self): for param in self._alg.parameters: if isinstance(param, (ParameterRaster, ParameterVector, ParameterMultipleInput)): return True return False def setTableContent(self): params = self._alg.parameters outputs = self._alg.outputs visibleParams = [p for p in params if not p.hidden] visibleOutputs = [p for o in outputs if not o.hidden] self.tableWidget.setRowCount(len(visibleParams) + len(visibleOutputs)) for i, param in visibleParams: item = QTableWidgetItem(param.description) item.setFlags(Qt.ItemIsEnabled) self.tableWidget.setItem(i, 0, item) item = self.getWidgetFromParameter(param) self.valueItems[param.name] = item self.tableWidget.setCellWidget(i, 1, item) self.tableWidget.setRowHeight(i, 22) for i, output in visibleOutputs: item = QTableWidgetItem(output.description + '<' + output.__module__.split('.')[-1] + '>') item.setFlags(Qt.ItemIsEnabled) self.tableWidget.setItem(i, 0, item) item = QLineEdit() if hasattr(item, 'setPlaceholderText'): item.setPlaceholderText(ModelerParametersDialog.ENTER_NAME) self.valueItems[output.name] = item self.tableWidget.setCellWidget(i, 1, item) self.tableWidget.setRowHeight(i, 22) def setComboBoxValue(self, combo, value, param): if isinstance(value, list): value = value[0] items = [combo.itemData(i) for i in range(combo.count())] try: idx = items.index(value) combo.setCurrentIndex(idx) return except ValueError: pass if combo.isEditable(): if value is not None: combo.setEditText(str(value)) elif isinstance(param, ParameterSelection): combo.setCurrentIndex(int(value)) elif isinstance(param, ParameterBoolean): if value: combo.setCurrentIndex(0) else: combo.setCurrentIndex(1) 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 widget = self.valueItems[param.name] if param.name in alg.params: value = alg.params[param.name] else: value = param.default if isinstance(param, ( ParameterRaster, ParameterVector, ParameterTable, ParameterTableField, ParameterSelection, ParameterNumber, ParameterBoolean, ParameterExtent, ParameterFile, ParameterPoint, ParameterCrs )): self.setComboBoxValue(widget, value, param) elif isinstance(param, ParameterString): if param.multiline: widget.setValue(value) else: self.setComboBoxValue(widget, value, param) elif isinstance(param, ParameterFixedTable): pass # TODO! elif isinstance(param, ParameterMultipleInput): if param.datatype == dataobjects.TYPE_VECTOR_ANY: options = self.getAvailableValuesOfType(ParameterVector, OutputVector) elif param.datatype == dataobjects.TYPE_VECTOR_POINT: options = self.getAvailableValuesOfType(ParameterVector, OutputVector, [dataobjects.TYPE_VECTOR_POINT, dataobjects.TYPE_VECTOR_ANY]) elif param.datatype == dataobjects.TYPE_VECTOR_LINE: options = self.getAvailableValuesOfType(ParameterVector, OutputVector, [dataobjects.TYPE_VECTOR_LINE, dataobjects.TYPE_VECTOR_ANY]) elif param.datatype == dataobjects.TYPE_VECTOR_POLYGON: options = self.getAvailableValuesOfType(ParameterVector, OutputVector, [dataobjects.TYPE_VECTOR_POLYGON, dataobjects.TYPE_VECTOR_ANY]) elif param.datatype == dataobjects.TYPE_RASTER: options = self.getAvailableValuesOfType(ParameterRaster, OutputRaster) else: options = self.getAvailableValuesOfType(ParameterFile, OutputFile) selected = [] for i, opt in enumerate(options): if opt in value: selected.append(i) widget.setSelectedItems(selected) elif isinstance(param, ParameterGeometryPredicate): widget.setValue(value) for name, out in alg.outputs.items(): widget = self.valueItems[name].setText(out.description) selected = [] dependencies = self.getAvailableDependencies() 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.commandLineName()) 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.valueItems[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() for selected in selectedOptions: alg.dependencies.append(availableDependencies[selected].name) return alg def setParamValueLayerOrTable(self, alg, param, widget): idx = widget.currentIndex() if idx < 0: return False else: value = widget.itemData(widget.currentIndex()) alg.params[param.name] = value return True def setParamTableFieldValue(self, alg, param, widget): idx = widget.findText(widget.currentText()) if idx < 0: s = str(widget.currentText()).strip() if s == '': if param.optional: alg.params[param.name] = None return True else: return False else: alg.params[param.name] = s return True else: alg.params[param.name] = widget.itemData(widget.currentIndex()) return True def setParamStringValue(self, alg, param, widget): if param.multiline: value = widget.getValue() option = widget.getOption() if option == MultilineTextPanel.USE_TEXT: if value == '': if param.optional: alg.params[param.name] = None return True else: return False else: alg.params[param.name] = value else: alg.params[param.name] = value else: idx = widget.findText(widget.currentText()) if idx < 0: value = widget.currentText().strip() if value == '': if param.optional: alg.params[param.name] = None return True else: return False else: alg.params[param.name] = value else: alg.params[param.name] = widget.itemData(widget.currentIndex()) return True def setParamFileValue(self, alg, param, widget): idx = widget.findText(widget.currentText()) if idx < 0: value = widget.currentText() else: value = widget.itemData(widget.currentIndex()) alg.params[param.name] = value return True def setParamNumberValue(self, alg, param, widget): idx = widget.findText(widget.currentText()) if idx < 0: s = widget.currentText().strip() if s: try: value = float(s) except: return False elif param.optional: value = None else: return False else: value = widget.itemData(widget.currentIndex()) alg.params[param.name] = value return True def setParamExtentValue(self, alg, param, widget): idx = widget.findText(widget.currentText()) if idx < 0: s = str(widget.currentText()).strip() if s: try: tokens = s.split(',') if len(tokens) != 4: return False for token in tokens: float(token) except: return False elif param.optional: s = None else: return False alg.params[param.name] = [s] else: value = widget.itemData(widget.currentIndex()) alg.params[param.name] = value return True def setParamPointValue(self, alg, param, widget): idx = widget.findText(widget.currentText()) if idx < 0: s = str(widget.currentText()).strip() if s: try: tokens = s.split(',') if len(tokens) != 2: return False for token in tokens: float(token) except: return False elif param.optional: s = None else: return False alg.params[param.name] = [s] else: value = widget.itemData(widget.currentIndex()) alg.params[param.name] = value return True def setParamCrsValue(self, alg, param, widget): idx = widget.currentIndex() if idx < 0: return False else: value = widget.itemData(widget.currentIndex()) alg.params[param.name] = value return True def setParamValue(self, alg, param, widget): if isinstance(param, (ParameterRaster, ParameterVector, ParameterTable)): return self.setParamValueLayerOrTable(alg, param, widget) elif isinstance(param, ParameterBoolean): if widget.currentIndex() < 2: value = widget.currentIndex() == 0 else: value = widget.itemData(widget.currentIndex()) alg.params[param.name] = value return True elif isinstance(param, ParameterString): return self.setParamStringValue(alg, param, widget) elif isinstance(param, ParameterNumber): return self.setParamNumberValue(alg, param, widget) elif isinstance(param, ParameterExtent): return self.setParamExtentValue(alg, param, widget) elif isinstance(param, ParameterPoint): return self.setParamPointValue(alg, param, widget) elif isinstance(param, ParameterFile): return self.setParamFileValue(alg, param, widget) elif isinstance(param, ParameterSelection): alg.params[param.name] = widget.currentIndex() return True elif isinstance(param, ParameterRange): alg.params[param.name] = widget.getValue() return True elif isinstance(param, ParameterCrs): return self.setParamCrsValue(alg, param, widget) elif isinstance(param, ParameterFixedTable): table = widget.table if not bool(table) and not param.optional: return False alg.params[param.name] = ParameterFixedTable.tableToString(table) return True elif isinstance(param, (ParameterTableField, ParameterTableMultipleField)): return self.setParamTableFieldValue(alg, param, widget) elif isinstance(param, ParameterMultipleInput): if param.datatype == dataobjects.TYPE_VECTOR_ANY: options = self.getAvailableValuesOfType(ParameterVector, OutputVector) elif param.datatype == dataobjects.TYPE_VECTOR_POINT: options = self.getAvailableValuesOfType(ParameterVector, OutputVector, [dataobjects.TYPE_VECTOR_POINT, dataobjects.TYPE_VECTOR_ANY]) elif param.datatype == dataobjects.TYPE_VECTOR_LINE: options = self.getAvailableValuesOfType(ParameterVector, OutputVector, [dataobjects.TYPE_VECTOR_LINE, dataobjects.TYPE_VECTOR_ANY]) elif param.datatype == dataobjects.TYPE_VECTOR_POLYGON: options = self.getAvailableValuesOfType(ParameterVector, OutputVector, [dataobjects.TYPE_VECTOR_POLYGON, dataobjects.TYPE_VECTOR_ANY]) elif param.datatype == dataobjects.TYPE_RASTER: options = self.getAvailableValuesOfType(ParameterRaster, OutputRaster) else: options = self.getAvailableValuesOfType(ParameterFile, OutputFile) values = [options[i] for i in widget.selectedoptions] if len(values) == 0 and not param.optional: return False alg.params[param.name] = values return True elif isinstance(param, ParameterGeometryPredicate): alg.params[param.name] = widget.value() return True else: alg.params[param.name] = str(widget.text()) return True def okPressed(self): self.alg = self.createAlgorithm() if self.alg is not None: self.close() def cancelPressed(self): self.alg = None self.close()
class SelectedPopulationDockWidget(QgsDockWidget): """ Dock widget for display of population of selected meshblocks """ def __init__(self, _iface: QgisInterface = None, meshblock_layer: QgsVectorLayer = None): super().__init__() self.setWindowTitle(self.tr('Selected Meshblock Population')) self.meshblock_layer = meshblock_layer if _iface is not None: self.iface = _iface else: self.iface = iface dock_contents = QWidget() grid = QGridLayout(dock_contents) grid.setContentsMargins(0, 0, 0, 0) self.frame = QTextBrowser() self.frame.setOpenLinks(False) self.frame.anchorClicked.connect(self.anchor_clicked) grid.addWidget(self.frame, 1, 0, 1, 1) self.setWidget(dock_contents) self.meshblock_layer.selectionChanged.connect(self.selection_changed) self.task = None self.district_registry = None self.target_electorate = None self.quota = 0 def reset(self): """ Clears the current results shown in the dock """ self.target_electorate = None self.frame.setHtml('') def update(self): """ Refreshes the stats shown in the dock """ self.selection_changed() def set_task(self, task: str): """ Sets the current task to use when showing populations """ self.task = task if self.district_registry: self.quota = self.district_registry.get_quota_for_district_type( self.task) self.target_electorate = None self.selection_changed() def set_district_registry(self, registry): """ Sets the associated district registry """ self.district_registry = registry if self.task: self.quota = self.district_registry.get_quota_for_district_type( self.task) self.selection_changed() def selection_changed(self): """ Triggered when the selection in the meshblock layer changes """ if not self.task or not self.district_registry: return request = QgsFeatureRequest().setFilterFids( self.meshblock_layer.selectedFeatureIds()).setFlags( QgsFeatureRequest.NoGeometry) counts = defaultdict(int) for f in self.meshblock_layer.getFeatures(request): electorate = f['staged_electorate'] if self.task == 'GN': pop = f['offline_pop_gn'] elif self.task == 'GS': pop = f['offline_pop_gs'] else: pop = f['offline_pop_m'] counts[electorate] += pop html = """<h3>Target Electorate: <a href="#">{}</a></h3><p>""".format( self.district_registry.get_district_title(self.target_electorate)) request = QgsFeatureRequest() request.setFilterExpression( QgsExpression.createFieldEqualityExpression('type', self.task)) request.setFlags(QgsFeatureRequest.NoGeometry) request.setSubsetOfAttributes( ['electorate_id', 'estimated_pop', 'stats_nz_pop'], self.district_registry.source_layer.fields()) original_populations = {} for f in self.district_registry.source_layer.getFeatures(request): estimated_pop = f['stats_nz_pop'] if estimated_pop is None or estimated_pop == NULL: # otherwise just use existing estimated pop as starting point estimated_pop = f['estimated_pop'] original_populations[f['electorate_id']] = estimated_pop overall = 0 for electorate, pop in counts.items(): if self.target_electorate: if electorate != self.target_electorate: overall += pop # use stats nz pop as initial estimate, if available estimated_pop = original_populations[electorate] estimated_pop -= pop variance = LinzElectoralDistrictRegistry.get_variation_from_quota_percent( self.quota, estimated_pop) html += """\n{}: <span style="font-weight:bold">-{}</span> (after: {}, {}{}%)<br>""".format( self.district_registry.get_district_title(electorate), pop, int(estimated_pop), '+' if variance > 0 else '', variance) else: html += """\n{}: <span style="font-weight:bold">{}</span><br>""".format( self.district_registry.get_district_title(electorate), pop) if self.target_electorate: estimated_pop = original_populations[self.target_electorate] estimated_pop += overall variance = LinzElectoralDistrictRegistry.get_variation_from_quota_percent( self.quota, estimated_pop) html += """\n{}: <span style="font-weight:bold">+{}</span> (after: {}, {}{}%)<br>""".format( self.district_registry.get_district_title( self.target_electorate), overall, int(estimated_pop), '+' if variance > 0 else '', variance) html += '</p>' self.frame.setHtml(html) def anchor_clicked(self): """ Allows choice of "target" electorate """ dlg = DistrictPicker(district_registry=self.district_registry, parent=self.iface.mainWindow()) if dlg.selected_district is None: return self.target_electorate = dlg.selected_district self.selection_changed()