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()
def __init__(self, parent, url): QDialog.__init__(self, parent) self.resize(800, 600) l = QVBoxLayout() self.te = QTextBrowser(self) self.te.sourceChanged.connect(self.onSourceChanged) self.te.setOpenExternalLinks(True) if not url.startswith("http"): pwd = os.path.dirname(__file__) locale = QSettings().value("locale/userLocale")[0:2] file = "{}/doc/{}/{}".format(pwd, locale, url) if not os.path.isfile(file): file = "{}/doc/en/{}".format(pwd, url) self.te.setSource(QUrl.fromLocalFile(file)) else: self.te.setSource(QUrl(url)) btn = QDialogButtonBox(QDialogButtonBox.Ok, Qt.Horizontal, self) btn.clicked.connect(self.close) l.addWidget(self.te) l.addWidget(btn) self.setLayout(l)
def __init__(self): QtWidgets.QDialog.__init__(self) self.setMinimumWidth(600) self.setMinimumHeight(450) self.helpFile = os.path.join(os.path.dirname(__file__), 'README.html') self.setWindowTitle('VectorBender') txt = QTextBrowser() txt.setReadOnly(True) txt.setSearchPaths([os.path.dirname(__file__)]) txt.setOpenExternalLinks(True) txt.setText(open(self.helpFile, 'r').read()) cls = QPushButton('Close') cls.pressed.connect(self.accept) lay = QVBoxLayout() lay.addWidget(txt) lay.addWidget(cls) self.setLayout(lay)
class LogPanel(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) self.txtStdout = QTextBrowser() self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.txtStdout.setLayout(QGridLayout()) self.txtStdout.layout().setContentsMargins(0, 0, 0, 0) self.txtStdout.layout().addWidget(self.bar, 0, 0, Qt.AlignTop) layout = QGridLayout() layout.addWidget(self.txtStdout) self.setLayout(layout) def print_info(self, text, text_color=LogColor.COLOR_INFO): self.txtStdout.setTextColor(QColor(text_color)) self.txtStdout.append(text) def on_stderr(self, text): color_log_text(text, self.txtStdout) def show_message(self, level, message): if level == Qgis.Warning: self.bar.pushMessage(message, Qgis.Info, 10) elif level == Qgis.Critical: self.bar.pushMessage(message, Qgis.Warning, 10)
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 setupUi(self): self.resize(800, 600) self.setWindowTitle("Authorship") layout = QVBoxLayout() splitter = QSplitter(self) splitter.setOrientation(Qt.Vertical) self.table = QTableWidget(splitter) self.table.setColumnCount(3) self.table.setShowGrid(False) self.table.verticalHeader().hide() self.table.setHorizontalHeaderLabels(["Attribute", "Author", "Value"]) self.table.setRowCount(len(self.blamedata)) self.table.setSelectionBehavior(QAbstractItemView.SelectRows) self.table.setSelectionMode(QAbstractItemView.SingleSelection); self.table.selectionModel().selectionChanged.connect(self.selectionChanged) for i, name in enumerate(self.blamedata.keys()): values = self.blamedata[name] self.table.setItem(i, 0, QTableWidgetItem(name)); self.table.setItem(i, 1, QTableWidgetItem(values[1].authorname)); self.table.setItem(i, 2, QTableWidgetItem(values[0])); self.table.resizeRowsToContents() self.table.horizontalHeader().setMinimumSectionSize(250) self.table.horizontalHeader().setStretchLastSection(True) self.text = QTextBrowser(splitter) layout.addWidget(splitter) self.setLayout(layout) QMetaObject.connectSlotsByName(self)
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()
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 __init__(self): QtWidgets.QDialog.__init__(self) self.setMinimumWidth(600) self.setMinimumHeight(450) self.helpFile = os.path.join(os.path.dirname(__file__),'README.html') self.setWindowTitle('VectorBender') txt = QTextBrowser() txt.setReadOnly(True) txt.setSearchPaths([os.path.dirname(__file__)]) txt.setOpenExternalLinks(True) txt.setText( open(self.helpFile, 'r').read() ) cls = QPushButton('Close') cls.pressed.connect(self.accept) lay = QVBoxLayout() lay.addWidget(txt) lay.addWidget(cls) self.setLayout(lay)
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 __init__(self, parent=None): QTextBrowser.__init__(self, parent) self.setOpenLinks(False) self.item = None self.dirty = False self._clear() self._showPluginInfo() self.anchorClicked.connect(self._linkClicked)
def _show_terms(self, _): if self._terms_browser is None: self._terms_browser = QTextBrowser() self._terms_browser.setReadOnly(True) self._terms_browser.setOpenExternalLinks(True) self._terms_browser.setMinimumSize(600, 700) # TODO: Template terms.html first section, per subscription level # Collect subscription info from self.p_client.user self._terms_browser.setSource( QUrl('qrc:/plugins/planet_explorer/terms.html')) self._terms_browser.setWindowModality(Qt.ApplicationModal) self._terms_browser.show()
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_()
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 __init__(self, parent=None): QWidget.__init__(self, parent) self.txtStdout = QTextBrowser() self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.txtStdout.setLayout(QGridLayout()) self.txtStdout.layout().setContentsMargins(0, 0, 0, 0) self.txtStdout.layout().addWidget(self.bar, 0, 0, Qt.AlignTop) layout = QGridLayout() layout.addWidget(self.txtStdout) self.setLayout(layout)
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 __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 setupUi(self, GHydraulicsResultDialog): GHydraulicsResultDialog.setObjectName(_fromUtf8("GHydraulicsResultDialog")) GHydraulicsResultDialog.resize(640, 480) self.buttonBox = QDialogButtonBox(GHydraulicsResultDialog) self.buttonBox.setGeometry(QtCore.QRect(10, 440, 620, 32)) self.buttonBox.setOrientation(QtCore.Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Ok) self.buttonBox.setObjectName(_fromUtf8("buttonBox")) self.tabWidget = QTabWidget(GHydraulicsResultDialog) self.tabWidget.setGeometry(QtCore.QRect(10, 10, 620, 390)) self.tabWidget.setObjectName(_fromUtf8("tabWidget")) self.tabOutput = QWidget() self.tabOutput.setObjectName(_fromUtf8("tabOutput")) self.textOutput = QTextBrowser(self.tabOutput) self.textOutput.setGeometry(QtCore.QRect(10, 10, 600, 340)) sizePolicy = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.textOutput.sizePolicy().hasHeightForWidth()) self.textOutput.setSizePolicy(sizePolicy) self.textOutput.setObjectName(_fromUtf8("textOutput")) self.tabWidget.addTab(self.tabOutput, _fromUtf8("")) self.tabReport = QWidget() self.tabReport.setObjectName(_fromUtf8("tabReport")) self.textReport = QTextBrowser(self.tabReport) self.textReport.setGeometry(QtCore.QRect(10, 10, 600, 340)) sizePolicy = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.textReport.sizePolicy().hasHeightForWidth()) self.textReport.setSizePolicy(sizePolicy) self.textReport.setObjectName(_fromUtf8("textReport")) self.tabWidget.addTab(self.tabReport, _fromUtf8("")) self.comboStep = QComboBox(GHydraulicsResultDialog) self.comboStep.setGeometry(QtCore.QRect(150, 410, 80, 27)) self.comboStep.setObjectName(_fromUtf8("comboStep")) self.labelStep = QLabel(GHydraulicsResultDialog) self.labelStep.setGeometry(QtCore.QRect(10, 415, 120, 17)) self.labelStep.setObjectName(_fromUtf8("labelStep")) self.retranslateUi(GHydraulicsResultDialog) self.tabWidget.setCurrentIndex(0) #QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), GHydraulicsResultDialog.accept) self.buttonBox.accepted.connect(GHydraulicsResultDialog.accept) #QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), GHydraulicsResultDialog.reject) self.buttonBox.rejected.connect(GHydraulicsResultDialog.reject) QtCore.QMetaObject.connectSlotsByName(GHydraulicsResultDialog)
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)
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 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
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))
class BlameDialog(QDialog): def __init__(self, repo, path): QDialog.__init__(self, None, Qt.WindowSystemMenuHint | Qt.WindowTitleHint) versions = repo.log(path = path, limit = 1) if not versions: raise GeoGigException("The selected feature is not versioned yet") self.blamedata = repo.blame(path) self.repo = repo self.commitText = {} self.setupUi() def setupUi(self): self.resize(800, 600) self.setWindowTitle("Authorship") layout = QVBoxLayout() splitter = QSplitter(self) splitter.setOrientation(Qt.Vertical) self.table = QTableWidget(splitter) self.table.setColumnCount(3) self.table.setShowGrid(False) self.table.verticalHeader().hide() self.table.setHorizontalHeaderLabels(["Attribute", "Author", "Value"]) self.table.setRowCount(len(self.blamedata)) self.table.setSelectionBehavior(QAbstractItemView.SelectRows) self.table.setSelectionMode(QAbstractItemView.SingleSelection); self.table.selectionModel().selectionChanged.connect(self.selectionChanged) for i, name in enumerate(self.blamedata.keys()): values = self.blamedata[name] self.table.setItem(i, 0, QTableWidgetItem(name)); self.table.setItem(i, 1, QTableWidgetItem(values[1].authorname)); self.table.setItem(i, 2, QTableWidgetItem(values[0])); self.table.resizeRowsToContents() self.table.horizontalHeader().setMinimumSectionSize(250) self.table.horizontalHeader().setStretchLastSection(True) self.text = QTextBrowser(splitter) layout.addWidget(splitter) self.setLayout(layout) QMetaObject.connectSlotsByName(self) def selectionChanged(self): idx = self.table.currentRow() commit = self.blamedata[self.table.item(idx, 0).text()][1] self.text.setText(str(commit))
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)
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)
def initGui(self): self.setWindowTitle('QConsolidate3') self.buttonBox = QDialogButtonBox(QDialogButtonBox.Close | QDialogButtonBox.Help) self.label = QLabel("QConsolidate3") self.label.setStyleSheet("font-weight: bold") self.lblLogo = QLabel() self.lblVersion = QLabel() self.textBrowser = QTextBrowser() self.h_layout = QHBoxLayout() self.h_layout.addWidget(self.lblLogo) self.h_layout.addWidget(self.label) self.v_layout = QVBoxLayout() self.v_layout.addLayout(self.h_layout) self.v_layout.addWidget(self.lblVersion) self.v_layout.addWidget(self.textBrowser) self.v_layout.addWidget(self.buttonBox) self.setLayout(self.v_layout)
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 __init__(self, version): super(AboutDialog, self).__init__() dialog_layout = QVBoxLayout() htmlText = """ <h3>{} - release {}</h3> Created by M. Alberti ([email protected]). <br /><br /><a href="https://github.com/mauroalberti/qgSurf">https://github.com/mauroalberti/qgSurf</a> <br /><br />Processing of geological data. <br /><br />Licensed under the terms of GNU GPL 3. """.format(plugin_nm, version) aboutQTextBrowser = QTextBrowser(self) aboutQTextBrowser.insertHtml(htmlText) aboutQTextBrowser.setMinimumSize(400, 200) dialog_layout.addWidget(aboutQTextBrowser) self.setLayout(dialog_layout) self.setWindowTitle('{} about'.format(plugin_nm))
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()))
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 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 PlanetExplorerDockWidget(BASE, WIDGET): BASE: QDockWidget _auth_man: QgsAuthManager msgBar: QgsMessageBar stckdWidgetViews: QStackedWidget stckdWidgetResourceType: QStackedWidget leUser: QLineEdit lePass: QLineEdit leMosaicName: QLineEdit chkBxSaveCreds: QCheckBox lblSignUp: QLabel lblTermsOfService: QLabel lblForgotPass: QLabel cmbBoxItemGroupType: QComboBox btnSearch: QToolButton grpBoxMainFilters: QgsCollapsibleGroupBox grpBoxSeries: QgsCollapsibleGroupBox _main_filters: PlanetMainFilters grpBoxFilters: QgsCollapsibleGroupBox stckdWidgetFilters: QStackedWidget frameResults: QFrame tabWidgetResults: QTabWidget btnOrder: QToolButton btnCog: QToolButton btnInfo: QToolButton btnUser: QToolButton _user_act: QWidgetAction _terms_browser: QTextBrowser closingPlugin = pyqtSignal() def __init__(self, parent=None, iface=None, visible=False): super(PlanetExplorerDockWidget, 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://doc.qt.io/qt-5/designer-using-a-ui-file.html # #widgets-and-dialogs-with-auto-connect self.setupUi(self) self.setVisible(visible) self._iface = iface # noinspection PyArgumentList self._auth_man = QgsApplication.authManager() self.p_client = None self.api_key = None self._save_creds = bool( pluginSetting(SAVE_CREDS_KEY, namespace=SETTINGS_NAMESPACE, typ='bool')) self.leUser.addAction( QIcon(':/plugins/planet_explorer/envelope-gray.svg'), QLineEdit.LeadingPosition) self.lblSignUp.linkActivated[str].connect( lambda: self._open_link_with_browser(SIGNUP_URL)) self.lblTermsOfService.linkActivated[str].connect( lambda: self._open_link_with_browser(TOS_URL)) self.lblForgotPass.linkActivated[str].connect( lambda: self._open_link_with_browser(FORGOT_PASS_URL)) self.btn_ok = self.buttonBoxLogin.button(QDialogButtonBox.Ok) self.btn_ok.setText('Sign In') self.btn_api_key = self.buttonBoxLogin.button(QDialogButtonBox.Abort) """:type: QPushButton""" self.btn_api_key.setText('Use API key') self.btn_api_key.hide() self.buttonBoxLogin.accepted.connect(self.login) self.buttonBoxLogin.rejected.connect(self.api_key_login) self._setup_group_type_selector() self.cmbBoxItemGroupType.currentIndexChanged[int].connect( self._item_group_changed) self._toggle_search_highlight(True) self.btnSearch.clicked[bool].connect(self.perform_search) # Collected sources/filters, upon search request self._sources = None self._sort_order = None self._filters = None self._request = None # Set up the mosaics widget self._setup_mosaics_panel() # Set up AOI, date-range and text filters self._setup_main_filters() # Non-main, per-item-group control widget filters self._filter_widget_registry = {} self._setup_filter_widgets() # Set default group type and filter widget self.cmbBoxItemGroupType.setCurrentIndex(0) self.stckdWidgetFilters.setCurrentIndex(0) # Set up tabbed widget self.tabWidgetResults.tabCloseRequested[int].connect( self.tab_close_requested) # Set up lower button bar self.btnOrder.clicked.connect(self.order_checked) self._setup_cog_button() # noinspection PyTypeChecker self._user_act = None # noinspection PyTypeChecker self._terms_browser = None self._setup_info_button() self.msg_log = QgsMessageLog() # Local QgsMessageBar self.msgBar.hide() self.frameResults.setStyleSheet(RESULTS_BKGRD_PE) self._checked_queue_set_count = 0 self._checked_queue_set = set() self._checked_item_type_nodes = {} # noinspection PyUnusedLocal def showEvent(self, event): if self.logged_in(): self.stckdWidgetViews.setCurrentIndex(1) else: self._setup_client() def _setup_client(self): # Init api client self.p_client = PlanetClient.getInstance() self.p_client.register_area_km_func(area_from_geojsons) self.p_client.loginChanged[bool].connect(self.login_changed) # Retrieve any login/key settings self.switch_to_login_panel() if not self.logged_in(): self.api_key = API_KEY_DEFAULT self._set_credential_fields() # self.btn_api_key.setEnabled(bool(self.api_key)) self.chkBxSaveCreds.stateChanged.connect( self.save_credentials_changed) self._setup_user_button() # Skip login panel if an API key was retrieved/accepted by client # self.login_changed() def logged_in(self): return self.p_client is not None and self.p_client.has_api_key() @pyqtSlot() def api_key_login(self): if self.api_key: self.login(api_key=self.api_key) # Now switch panels self.login_changed() @pyqtSlot() def login(self, api_key=None): if self.logged_in(): return # Do login, push any error to message bar try: # Don't switch panels just yet self.p_client.blockSignals(True) self.p_client.log_in(self.leUser.text(), self.lePass.text(), api_key=api_key) self.p_client.blockSignals(False) except LoginException as e: self.show_message('Login failed!', show_more=str(e.__cause__), level=Qgis.Warning) # Stay on login panel if error return # Login OK self.api_key = self.p_client.api_key() user = self.p_client.user() if is_segments_write_key_valid(): analytics.identify( user["email"], { "email": user["email"], "apiKey": user["api_key"], "organizationId": user["organization_id"], "programId": user["program_id"] }) analytics.track(user["email"], "Log in to Explorer") if is_sentry_dsn_valid(): with sentry_sdk.configure_scope() as scope: scope.user = {"email": user["email"]} # Store settings if self.chkBxSaveCreds.isChecked(): self._store_auth_creds() # For debugging specs = f'logged_in={self.logged_in()}\n\n' \ f'api_key = {self.p_client.api_key()}\n\n' \ f'user: {self.p_client.user()}\n\n' log.debug(f'Login successful:\n{specs}') # Now switch panels self.p_client.loginChanged.emit(self.p_client.has_api_key()) #self.login_changed() @pyqtSlot() def logout(self): if not self.logged_in(): return # Do logout (switches to Login panel) self.p_client.log_out() # self.btn_api_key.setEnabled(bool(self.api_key)) log.debug('User logged out') @pyqtSlot() def login_changed(self): user_name = 'User' if self.logged_in(): p_user = self.p_client.user() if p_user and 'user_name' in p_user: user_name = p_user['user_name'] self.lePass.setText("") self.leUser.setText("") self.switch_to_browse_panel() else: self._set_credential_fields() self.switch_to_login_panel() self._user_act.defaultWidget().setText(f"<b>{user_name}</b>") @pyqtSlot() def switch_to_login_panel(self): self.stckdWidgetViews.setCurrentIndex(0) @pyqtSlot() def switch_to_browse_panel(self): self.stckdWidgetViews.setCurrentIndex(1) def switch_to_daily_images_panel(self): self.stckdWidgetResourceType.setCurrentIndex(0) def switch_to_mosaic_series_panel(self): self.stckdWidgetResourceType.setCurrentIndex(1) def switch_to_single_mosaics_panel(self): self.stckdWidgetResourceType.setCurrentIndex(2) @pyqtSlot(int) def _item_group_changed(self, indx): self.stckdWidgetResourceType.setCurrentIndex(indx) resource_type = self.cmbBoxItemGroupType.currentData() self.btnSearch.setEnabled(resource_type != RESOURCE_MOSAIC_SERIES) self.btnOrder.setVisible(resource_type == RESOURCE_DAILY) self.btnCog.setVisible(resource_type == RESOURCE_DAILY) if resource_type == RESOURCE_MOSAIC_SERIES: self.treeMosaicSeries.populate() elif resource_type == RESOURCE_SINGLE_MOSAICS: self.listSingleMosaics.populate_with_first_page() @pyqtSlot(bool) def _toggle_search_highlight(self, on=True): if on: self.btnSearch.setStyleSheet(SEARCH_HIGHLIGHT) self.btnSearch.setIcon( QIcon(':/plugins/planet_explorer/search_p.svg')) else: self.btnSearch.setStyleSheet('') self.btnSearch.setIcon( QIcon(':/plugins/planet_explorer/search.svg')) @pyqtSlot() def _update_checked_queue_set(self): tab_queues = [] for i in range(self.tabWidgetResults.count()): # noinspection PyTypeChecker wdgt: PlanetSearchResultsWidget = self.tabWidgetResults.widget(i) tab_queues.append(wdgt.checked_queue()) # unique item_type:item_id key grouping set new_queue_set = set().union(*tab_queues) # When using with {'item_type': set(nodes)} # new_queue_set = {} # tab_keys = set().union(*tab_queues) # for tk in tab_keys: # new_queue_set[tk] = set() # # for tq in tab_queues: # for tk in tq.keys(): # new_queue_set[tk] = new_queue_set[tk].union(tq[tk]) self._checked_queue_set = new_queue_set self._update_checked_queue_set_count() @pyqtSlot() def _update_checked_queue_set_count(self): # self._checked_queue_set_count = \ # sum([len(n) for n in self._checked_queue_set.values()]) self._checked_queue_set_count = len(self._checked_queue_set) self.btnOrder.setText( f'Order ({self._checked_queue_set_count} unique)') # noinspection PyUnusedLocal @pyqtSlot() def _collect_sources_filters(self): main_filters = self._main_filters.filters() if not main_filters: main_filters = [] # main_filters_json = self._main_filters.filters_as_json() group_filters: PlanetFilterMixin = \ self._filter_widget(self.cmbBoxItemGroupType.currentIndex()) self._sources = group_filters.sources() self._sort_order = group_filters.sort_order() item_filters = group_filters.filters() if not item_filters: item_filters = [] # item_filters_json = item_filters.filters_as_json() all_filters = main_filters + item_filters # Merge main and item filters self._filters = and_filter(*all_filters) # TODO: Validate filters # noinspection PyUnusedLocal @pyqtSlot(bool) def perform_search(self, clicked=True): log.debug('Search initiated') # Remove highlight on search button self._toggle_search_highlight(False) resource_type = self.cmbBoxItemGroupType.currentData() if resource_type == RESOURCE_DAILY: self._collect_sources_filters() if not self._main_filters.leAOI.text(): self.show_message('No area of interest (AOI) defined', level=Qgis.Warning, duration=10) return # TODO: Also validate GeoJSON prior to performing search # TODO: replace hardcoded item type with dynamic item types search_request = build_search_request(self._filters, self._sources) self._request = search_request if is_segments_write_key_valid(): analytics.track(self.p_client.user()["email"], "Daily images search executed", {"query": search_request}) # self.msg_log.logMessage( # f"Request:\n" \ # f"<pre>{json.dumps(self._request, indent=2)}</pre>", # LOG_NAME) # Create new results tab, in results tab viewer, passing in request wdgt = PlanetSearchResultsWidget( parent=self.tabWidgetResults, iface=self._iface, api_key=self.api_key, request_type=resource_type, request=search_request, sort_order=self._sort_order, ) wdgt.checkedCountChanged.connect(self._update_checked_queue_set) wdgt.setAOIRequested.connect(self.set_aoi_from_request) wdgt.setSearchParamsRequested.connect( self.set_search_params_from_request) wdgt.zoomToAOIRequested.connect( self._prepare_for_zoom_to_search_aoi) self.frameResults.setStyleSheet(RESULTS_BKGRD_WHITE) self.tabWidgetResults.setUpdatesEnabled(False) self.tabWidgetResults.addTab(wdgt, 'Daily') self.tabWidgetResults.setUpdatesEnabled(True) self.tabWidgetResults.setCurrentWidget(wdgt) # search_results = self.p_client.quick_search(search_request) if resource_type == RESOURCE_SINGLE_MOSAICS: search_text = self.leMosaicName.text() if is_segments_write_key_valid(): analytics.track(self.p_client.user()["email"], "Mosaics search executed", {"text": search_text}) self.listSingleMosaics.populate(search_text) @pyqtSlot(dict, tuple) def set_search_params_from_request(self, request, sort_order): for filter_widget in self._filter_widget_registry.values(): filter_widget.set_from_request(request) filter_widget.set_sort_order(sort_order) self._main_filters.set_from_request(request) @pyqtSlot(dict) def set_aoi_from_request(self, request): self._main_filters.set_from_request(request) @pyqtSlot() def _prepare_for_zoom_to_search_aoi(self): active = self.tabWidgetResults.currentIndex() for i in range(self.tabWidgetResults.count()): if i != active: wdgt = self.tabWidgetResults.widget(i) wdgt.clear_aoi_box() wdgt = self.tabWidgetResults.widget(active) self._main_filters.hide_aoi_if_matches_geom(wdgt.aoi_geom()) @pyqtSlot() def _prepare_for_zoom_to_main_aoi(self): wdgt = self.tabWidgetResults.widget( self.tabWidgetResults.currentIndex()) if wdgt: wdgt.hide_aoi_if_matches_geom(self._main_filters.aoi_geom()) @pyqtSlot(int) def tab_close_requested(self, indx): wdgt: Optional[PlanetSearchResultsWidget] = \ self.tabWidgetResults.widget(indx) if wdgt and hasattr(wdgt, 'clean_up'): wdgt.clean_up() self.tabWidgetResults.removeTab(indx) self._update_checked_queue_set() if self.tabWidgetResults.count() == 0: self.frameResults.setStyleSheet(RESULTS_BKGRD_PE) def _collect_checked_nodes(self): tab_queues = [] for i in range(self.tabWidgetResults.count()): # noinspection PyTypeChecker wdgt: PlanetSearchResultsWidget = self.tabWidgetResults.widget(i) tab_queues.append(wdgt.checked_queue()) # Per-tab checked_queue() are a 1-to-1 dict of {'item_type:id': node} # An item_type:id may be checked in trees across multiple tabs. # Use a ChainMap view to resolve dupes and for faster iteration; # because, although the nodes in each tree's model may be different # (e.g. index), the actual metadata and thumbnail are the same. # This means the earliest found item_type:id will be used regardless # of the which tabs it is checked in. tab_queue_chainmap = ChainMap(*tab_queues) # _checked_queue_set is a set of unique, checked item_type:item_id keys # A dict of {'item_type': [nodes]} self._checked_item_type_nodes.clear() for chkd_it_id in sorted(self._checked_queue_set, reverse=True): if ':' not in chkd_it_id: log.debug(f'Item type:id is not valid') continue it_type = chkd_it_id.split(':')[0] if it_type not in self._checked_item_type_nodes: self._checked_item_type_nodes[it_type] = [] if chkd_it_id in tab_queue_chainmap: self._checked_item_type_nodes[it_type].append( tab_queue_chainmap[chkd_it_id]) else: # This should not happen log.debug('Item type:id in checked queue, but NOT in any tab') # Now sort each item_type's node list by date acquired, descending, # even though tabs may have been sorted acquired|published, asc|desc for item_type in self._checked_item_type_nodes: self._checked_item_type_nodes[item_type].sort( key=attrgetter('_acquired'), reverse=True) # When using with {'item_type': set(nodes)} if LOG_VERBOSE: for it_id in self._checked_item_type_nodes: # Possibly super verbose output... nl = '\n' i_types = \ [n.item_id() for n in self._checked_item_type_nodes[it_id]] log.debug(f'\n - {it_id}: ' f'{len(self._checked_item_type_nodes[it_id])}\n' f' - {"{0} - ".format(nl).join(i_types)}') @pyqtSlot() def show_orders_monitor_dialog(self): dlg = PlanetOrdersMonitorDialog(p_client=self.p_client, parent=self) #dlg.setMinimumWidth(700) dlg.setMinimumHeight(750) dlg.exec_() @pyqtSlot() def order_checked(self): log.debug('Order initiated') self._collect_checked_nodes() if not self._checked_item_type_nodes: self.show_message(f'No checked items to order', level=Qgis.Warning, duration=10) return tool_resources = {} if self._main_filters.leAOI.text(): tool_resources['aoi'] = self._main_filters.leAOI.text() else: tool_resources['aoi'] = None dlg = PlanetOrdersDialog( self._checked_item_type_nodes, p_client=self.p_client, tool_resources=tool_resources, parent=self, iface=self._iface, ) dlg.setMinimumWidth(700) dlg.setMinimumHeight(750) dlg.exec_() @pyqtSlot() def add_preview_layer(self): # TODO: Once checked IDs are avaiable log.debug('Preview layer added to map') @pyqtSlot() def copy_checked_ids(self): if not self._checked_queue_set: self.show_message('No checked IDs to copy', level=Qgis.Warning, duration=10) return sorted_checked = sorted(self._checked_queue_set) cb = QgsApplication.clipboard() cb.setText(','.join(sorted_checked)) self.show_message('Checked IDs copied to clipboard') @pyqtSlot() def copy_curl(self): # TODO: Once checked IDs are avaiable self.show_message('cURL command copied to clipboard') @pyqtSlot() def copy_api_key(self): cb = QgsApplication.clipboard() cb.setText(self.p_client.api_key()) self.show_message('API key copied to clipboard') def _setup_mosaics_panel(self): self.treeMosaicSeries = MosaicSeriesTreeWidget(self) self.grpBoxSeries.layout().addWidget(self.treeMosaicSeries) self.listSingleMosaics = MosaicsListWidget(self) self.grpBoxSingleMosaics.layout().addWidget(self.listSingleMosaics) self.leMosaicName.textChanged.connect(self._filters_have_changed) def _setup_group_type_selector(self): self.cmbBoxItemGroupType.clear() for i in range(len(ITEM_GROUPS)): self.cmbBoxItemGroupType.insertItem( i, ITEM_GROUPS[i]['display_name'], userData=ITEM_GROUPS[i]['resource_type']) def _setup_main_filters(self): """Main filters: AOI visual extent, date range and text""" self._main_filters = PlanetMainFilters(parent=self.grpBoxMainFilters, plugin=self, iface=self._iface) self.grpBoxMainFilters.layout().addWidget(self._main_filters) self._main_filters.filtersChanged.connect(self._filters_have_changed) self._main_filters.zoomToAOIRequested.connect( self._prepare_for_zoom_to_main_aoi) def _setup_filter_widgets(self): """Filters related to item groups""" for i in range(len(ITEM_GROUPS)): wdgt = ITEM_GROUPS[i]['filter_widget'] if wdgt is not None: self._filter_widget_registry[i] = \ wdgt( parent=self.stckdWidgetFilters, plugin=self ) self._filter_widget(i).filtersChanged.connect( self._filters_have_changed) self.stckdWidgetFilters.addWidget(self._filter_widget(i)) def _filter_widget(self, indx): if indx in self._filter_widget_registry: return self._filter_widget_registry[indx] else: log.debug('Item group type filter widget not found') def _setup_cog_button(self): cog_menu = QMenu(self) # add_menu_section_action('Previews', cog_menu) # # add_prev_act = QAction('Add preview layer with checked', # cog_menu) # add_prev_act.triggered[bool].connect(self.add_preview_layer) # cog_menu.addAction(add_prev_act) add_menu_section_action('API', cog_menu) copy_menu = cog_menu.addMenu('Copy to clipboard') ids_act = QAction('Checked item IDs', cog_menu) ids_act.triggered[bool].connect(self.copy_checked_ids) copy_menu.addAction(ids_act) # curl_act = QAction('cURL command', cog_menu) # curl_act.triggered[bool].connect(self.copy_curl) # copy_menu.addAction(curl_act) api_act = QAction('API key', cog_menu) api_act.triggered[bool].connect(self.copy_api_key) copy_menu.addAction(api_act) self.btnCog.setMenu(cog_menu) # Also show menu on click, to keep disclosure triangle visible self.btnCog.clicked.connect(self.btnCog.showMenu) def _setup_info_button(self): info_menu = QMenu(self) self._p_sec_act = add_menu_section_action('Planet', info_menu) p_com_act = QAction(QIcon(EXT_LINK), 'planet.com', info_menu) p_com_act.triggered[bool].connect( lambda: self._open_link_with_browser(PLANET_COM)) info_menu.addAction(p_com_act) p_explorer_act = QAction(QIcon(EXT_LINK), 'Planet Explorer web app', info_menu) p_explorer_act.triggered[bool].connect( lambda: self._open_link_with_browser(PLANET_EXPLORER)) info_menu.addAction(p_explorer_act) p_sat_act = QAction(QIcon(EXT_LINK), 'Satellite specs PDF', info_menu) p_sat_act.triggered[bool].connect( lambda: self._open_link_with_browser(SAT_SPECS_PDF)) info_menu.addAction(p_sat_act) p_support_act = QAction(QIcon(EXT_LINK), 'Support Community', info_menu) p_support_act.triggered[bool].connect( lambda: self._open_link_with_browser(PLANET_SUPPORT_COMMUNITY)) info_menu.addAction(p_support_act) self._info_act = add_menu_section_action('Documentation', info_menu) terms_act = QAction('Terms', info_menu) terms_act.triggered[bool].connect(self._show_terms) info_menu.addAction(terms_act) self.btnInfo.setMenu(info_menu) # Also show menu on click, to keep disclosure triangle visible self.btnInfo.clicked.connect(self.btnInfo.showMenu) def _setup_user_button(self): user_menu = QMenu(self) # user_menu.aboutToShow.connect(self.p_client.update_user_quota) self._user_act = add_menu_section_action('User', user_menu) acct_act = QAction(QIcon(EXT_LINK), 'Account', user_menu) acct_act.triggered[bool].connect( lambda: self._open_link_with_browser(ACCOUNT_URL)) user_menu.addAction(acct_act) # quota_menu = user_menu.addMenu('Quota (sqkm)') # quota_menu.addAction( # f'Enabled: {str(self.p_client.user_quota_enabled())}') # quota_menu.addAction( # f'Size: {str(self.p_client.user_quota_size())}') # quota_menu.addAction( # f'Used: {str(self.p_client.user_quota_used())}') # quota_menu.addAction( # f'Remaining: {str(self.p_client.user_quota_remaining())}') # quota_act.setMenu(quota_menu) # user_menu.addAction(quota_act) logout_act = QAction('Logout', user_menu) logout_act.triggered[bool].connect(self.logout) user_menu.addAction(logout_act) add_menu_section_action('Orders', user_menu) monitor_orders_act = QAction('Monitor orders', user_menu) monitor_orders_act.triggered[bool].connect( self.show_orders_monitor_dialog) user_menu.addAction(monitor_orders_act) open_orders_folder_act = QAction('Open orders folder', user_menu) open_orders_folder_act.triggered[bool].connect( open_orders_download_folder) user_menu.addAction(open_orders_folder_act) self.btnUser.setMenu(user_menu) # Also show menu on click, to keep disclosure triangle visible self.btnUser.clicked.connect(self.btnUser.showMenu) @pyqtSlot() def _filters_have_changed(self): """ Main slot for when any filter value has changed. Planet API searches should not be initiated automatically on filter changes (i.e. here), but when the user clicks the search button. :return: """ self._toggle_search_highlight(True) log.debug('Filters have changed') # TODO: Fix signal-triggered collection of filters # self._collect_sources_filters() @pyqtSlot('QString', str, 'PyQt_PyObject', 'PyQt_PyObject') def _passthru_message(self, msg, level, duration, show_more): if level == 'Warning': qgis_level = Qgis.Warning elif level == 'Critical': qgis_level = Qgis.Critical elif level == 'Success': qgis_level = Qgis.Success else: # default qgis_level = Qgis.Info self.show_message(msg, level=qgis_level, duration=duration, show_more=show_more) def show_message(self, message, level=Qgis.Info, duration=None, show_more=None): """Skips bold title, i.e. sets first param (below) to empty string""" if duration is None: duration = self._iface.messageTimeout() if show_more is not None: self.msgBar.pushMessage('', message, show_more, level, duration) else: self.msgBar.pushMessage('', message, level, duration) @pyqtSlot(int) def save_credentials_changed(self, state): if state == 0: self._remove_auth_creds() self._save_creds = state > 0 setPluginSetting(SAVE_CREDS_KEY, self._save_creds, namespace=SETTINGS_NAMESPACE) def _store_auth_creds(self): auth_creds_str = AUTH_STRING.format(user=self.leUser.text(), password=self.lePass.text(), api_key=self.p_client.api_key(), sep=AUTH_SEP) self._auth_man.storeAuthSetting(AUTH_CREDS_KEY, auth_creds_str, True) def _retrieve_auth_creds(self): auth_creds_str = self._auth_man.authSetting(AUTH_CREDS_KEY, defaultValue='', decrypt=True) creds = auth_creds_str.split(AUTH_SEP) return { 'user': creds[0] if len(creds) > 0 else None, 'password': creds[1] if len(creds) > 1 else None, 'api_key': creds[2] if len(creds) > 2 else None } def _set_credential_fields(self): self.lePass.setPasswordVisibility(False) if not self._save_creds: self.chkBxSaveCreds.setChecked(False) else: self.chkBxSaveCreds.setChecked(True) auth_creds = self._retrieve_auth_creds() self.leUser.setText(auth_creds['user']) self.lePass.setText(auth_creds['password']) self.api_key = auth_creds['api_key'] def _remove_auth_creds(self): if not self._auth_man.removeAuthSetting(AUTH_CREDS_KEY): self.show_message('Credentials setting removal failed', level=Qgis.Warning, duration=10) # noinspection PyUnusedLocal @pyqtSlot(bool) def _show_terms(self, _): if self._terms_browser is None: self._terms_browser = QTextBrowser() self._terms_browser.setReadOnly(True) self._terms_browser.setOpenExternalLinks(True) self._terms_browser.setMinimumSize(600, 700) # TODO: Template terms.html first section, per subscription level # Collect subscription info from self.p_client.user self._terms_browser.setSource( QUrl('qrc:/plugins/planet_explorer/terms.html')) self._terms_browser.setWindowModality(Qt.ApplicationModal) self._terms_browser.show() @pyqtSlot(str) def _open_link_with_browser(self, url): QDesktopServices.openUrl(QUrl(url)) def clean_up(self): self._main_filters.clean_up() for i in range(self.tabWidgetResults.count()): wdgt = self.tabWidgetResults.widget(i) if wdgt and hasattr(wdgt, 'clean_up'): wdgt.clean_up() def closeEvent(self, event): self.clean_up() self.closingPlugin.emit() event.accept()
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 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.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()
def __init__(self, iface, parent=None): super(MainDialog, self).__init__(parent) QDialog.__init__(self) self.setupUi(self) self.iface = iface self.previewUrl = None self.layer_search_combo = None self.layer_filter_select = None self.exporter_combo = None self.feedback = FeedbackDialog(self) self.feedback.setModal(True) stgs = QSettings() self.restoreGeometry( stgs.value("qgis2web/MainDialogGeometry", QByteArray(), type=QByteArray)) self.verticalLayout_2.addStretch() self.horizontalLayout_6.addStretch() if stgs.value("qgis2web/previewOnStartup", Qt.Checked) == Qt.Checked: self.previewOnStartup.setCheckState(Qt.Checked) else: self.previewOnStartup.setCheckState(Qt.Unchecked) if stgs.value("qgis2web/closeFeedbackOnSuccess", Qt.Checked) == Qt.Checked: self.closeFeedbackOnSuccess.setCheckState(Qt.Checked) else: self.closeFeedbackOnSuccess.setCheckState(Qt.Unchecked) self.previewFeatureLimit.setText( stgs.value("qgis2web/previewFeatureLimit", "1000")) self.appearanceParams.setSelectionMode( QAbstractItemView.SingleSelection) self.preview = None if webkit_available: widget = QWebView() self.preview = widget try: # if os.environ["TRAVIS"]: self.preview.setPage(WebPage()) except Exception: print("Failed to set custom webpage") webview = self.preview.page() webview.setNetworkAccessManager(QgsNetworkAccessManager.instance()) self.preview.settings().setAttribute( QWebSettings.DeveloperExtrasEnabled, True) self.preview.settings().setAttribute( QWebSettings.DnsPrefetchEnabled, True) else: widget = QTextBrowser() widget.setText( self.tr('Preview is not available since QtWebKit ' 'dependency is missing on your system')) self.right_layout.insertWidget(0, widget) self.populateConfigParams(self) self.populate_layers_and_groups(self) self.populateLayerSearch() self.populateAttrFilter() writer = WRITER_REGISTRY.createWriterFromProject() self.setStateToWriter(writer) self.exporter = EXPORTER_REGISTRY.createFromProject() self.exporter_combo.setCurrentIndex( self.exporter_combo.findText(self.exporter.name())) self.exporter_combo.currentIndexChanged.connect( self.exporterTypeChanged) self.toggleOptions() if webkit_available: if self.previewOnStartup.checkState() == Qt.Checked: self.autoUpdatePreview() self.buttonPreview.clicked.connect(self.previewMap) else: self.buttonPreview.setDisabled(True) QgsProject.instance().cleared.connect(self.reject) self.layersTree.model().dataChanged.connect(self.populateLayerSearch) self.layersTree.model().dataChanged.connect(self.populateAttrFilter) self.ol3.clicked.connect(self.changeFormat) self.leaflet.clicked.connect(self.changeFormat) self.mapbox.clicked.connect(self.changeFormat) self.buttonExport.clicked.connect(self.saveMap) helpText = os.path.join(os.path.dirname(os.path.realpath(__file__)), "helpFile.md") self.helpField.setSource(QUrl.fromLocalFile(helpText)) if webkit_available: self.devConsole = QWebInspector(self.preview) self.devConsole.setFixedHeight(0) self.devConsole.setObjectName("devConsole") self.devConsole.setPage(self.preview.page()) self.devConsole.hide() self.right_layout.insertWidget(1, self.devConsole) self.filter = devToggleFilter() self.filter.devToggle.connect(self.showHideDevConsole) self.installEventFilter(self.filter) self.setModal(False)
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()