class LoadThings(QUndoCommand): def __init__(self, widget, thing): super(LoadThings, self).__init__() self.widget = widget self.createdThing = thing self.item = QTreeWidgetItem() self.item.setText(0, thing.name) typeName = type(thing).__name__ for i in range(self.widget.ui.treeWidget.topLevelItemCount()): group = self.widget.ui.treeWidget.topLevelItem(i) if group.text(0) == typeName: self.group = group break else: # group not found self.group = QTreeWidgetItem() self.group.setText(0, typeName) def redo(self): if self.widget.ui.treeWidget.indexOfTopLevelItem(self.group) == -1: self.widget.ui.treeWidget.addTopLevelItem(self.group) self.group.addChild(self.item) self.group.setExpanded(True) self.widget.ui.treeWidget.setCurrentItem(self.item) def undo(self): self.group.takeChild(self.group.childCount()-1) if self.group.childCount() == 0: parentIndex = self.widget.ui.treeWidget.indexOfTopLevelItem(self.group) self.widget.ui.treeWidget.takeTopLevelItem(parentIndex)
def filter(self, filterString: str, item: QTreeWidgetItem) -> bool: visible = (filterString == "") columnCount = item.columnCount() for i in range(columnCount): if not visible: break text = item.text(i) if HostOsInfo.isMacHost(): # accept e.g. Cmd+E in the filter. the text shows special fancy characters for Cmd if i == columnCount - 1: key = QKeySequence.fromString(text, QKeySequence.NativeText) if not key.isEmpty(): text = key.toString(QKeySequence.PortableText) text.replace("Ctrl", "Cmd") text.replace("Meta", "Ctrl") text.replace("Alt", "Opt") if filterString.upper() in text.upper(): # case insensitive visible = True childCount = item.childCount() if childCount > 0: # force visibility if this item matches leafFilterString = "" if visible else filterString for i in range(childCount): citem = item.child(i) # QTreeWidgetItem if not filter(leafFilterString, citem): visible = True item.setHidden(not visible) return not visible
def _loadDir(self, base_path, tree): for element in os.listdir(base_path): path = os.path.join(base_path, element) if (not os.path.isdir(path)) and (not path.endswith(".csv")): continue if os.path.isdir(path): parent_itm = QTreeWidgetItem(tree, [element]) self._loadDir(path, parent_itm) if parent_itm.childCount() == 0: parent = parent_itm.parent() root = parent_itm.treeWidget().invisibleRootItem() (parent or root).removeChild(parent_itm) else: parent_itm.setIcon( 0, QIcon( "/usr/share/icons/ubuntu-mono-light/places/16/folder-home.svg" )) # parent_itm.setExpanded(True) else: if Graph.getGraphDesc(path) is None: continue # item = GraphFileTreeWidgetItem(tree, element) item = QTreeWidgetItem(tree, [element]) item.setData(0, Qt.UserRole, path) item.setCheckState(0, Qt.Unchecked)
def __setupModelData(self): dsList = DataSourcesList().data_sources.values() groupInfoList = GroupsList().groups groupsItems = [] groups = [] for ds in dsList: if ds.group in groups: group_item = groupsItems[groups.index(ds.group)] else: group_item = QTreeWidgetItem() group_item.setData(self.COLUMN_GROUP_DS, Qt.DisplayRole, ds.group) group_item.setData(self.COLUMN_VISIBILITY, Qt.DisplayRole, "") group_item.setData(self.COLUMN_SOURCE, Qt.DisplayRole, ds.category) group_item.setCheckState(self.COLUMN_VISIBILITY, Qt.Unchecked) groupInfo = groupInfoList.get(ds.group) if groupInfo is not None: group_item.setIcon(self.COLUMN_GROUP_DS, QIcon(groupInfo.icon)) else: group_item.setData( self.COLUMN_GROUP_DS, Qt.DisplayRole, ds.group + " (%s!)" % self.tr("group not found")) group_item.setData(self.COLUMN_GROUP_DS, Qt.UserRole, groupInfo) groups.append(ds.group) groupsItems.append(group_item) self.rootItem.addChild(group_item) ds_item = QTreeWidgetItem() ds_item.setData(self.COLUMN_GROUP_DS, Qt.DisplayRole, ds.alias) ds_item.setIcon(self.COLUMN_GROUP_DS, QIcon(ds.icon_path)) ds_item.setData(self.COLUMN_GROUP_DS, Qt.UserRole, ds) ds_item.setData(self.COLUMN_VISIBILITY, Qt.DisplayRole, "") ds_item.setData(self.COLUMN_SOURCE, Qt.DisplayRole, ds.category) ds_check_state = Qt.Checked if ds.id in PluginSettings.get_hide_ds_id_list(): ds_check_state = Qt.Unchecked ds_item.setCheckState(self.COLUMN_VISIBILITY, ds_check_state) if group_item.childCount() != 0 and group_item.checkState( 1) != ds_check_state: group_item.setCheckState(self.COLUMN_VISIBILITY, Qt.PartiallyChecked) else: group_item.setCheckState(self.COLUMN_VISIBILITY, ds_check_state) group_item.addChild(ds_item)
def addOverlaysToTreeWidget(self, overlayDict, forbiddenOverlays, preSelectedOverlays, singleOverlaySelection): self.singleOverlaySelection = singleOverlaySelection testItem = QTreeWidgetItem("a") for keys in overlayDict.keys(): if overlayDict[keys] in forbiddenOverlays: continue else: boolStat = False split = keys.split("/") for i in range(len(split)): if len(split) == 1: newItemsChild = OverlayTreeWidgetItem( overlayDict[keys], keys) self.addTopLevelItem(newItemsChild) boolStat = False if overlayDict[keys] in preSelectedOverlays: newItemsChild.setCheckState(0, Qt.Checked) else: newItemsChild.setCheckState(0, Qt.Unchecked) elif i + 1 == len(split) and len(split) > 1: newItemsChild = OverlayTreeWidgetItem( overlayDict[keys], keys) testItem.addChild(newItemsChild) if overlayDict[keys] in preSelectedOverlays: newItemsChild.setCheckState(0, Qt.Checked) else: newItemsChild.setCheckState(0, Qt.Unchecked) elif self.topLevelItemCount() == 0 and i + 1 < len(split): newItem = QTreeWidgetItem([split[i]]) self.addTopLevelItem(newItem) testItem = newItem boolStat = True elif self.topLevelItemCount() != 0 and i + 1 < len(split): if boolStat == False: for n in range(self.topLevelItemCount()): if self.topLevelItem(n).text(0) == split[i]: testItem = self.topLevelItem(n) boolStat = True break elif n + 1 == self.topLevelItemCount(): newItem = QTreeWidgetItem([split[i]]) self.addTopLevelItem(newItem) testItem = newItem boolStat = True elif testItem.childCount() == 0: newItem = QTreeWidgetItem([split[i]]) testItem.addChild(newItem) testItem = newItem boolStat = True else: for x in range(testItem.childCount()): if testItem.child(x).text(0) == split[i]: testItem = testItem.child(x) boolStat = True break elif x + 1 == testItem.childCount(): newItem = QTreeWidgetItem([split[i]]) testItem.addChild(newItem) testItem = newItem boolStat = True
class RestoreDialog(widgets.dialog.Dialog): def __init__(self, parent=None): super(RestoreDialog, self).__init__(parent) self.messageLabel().setWordWrap(True) userguide.addButton(self.buttonBox(), "snippets") self.tree = QTreeWidget(headerHidden=True, rootIsDecorated=False) self.setMainWidget(self.tree) self.deletedItem = QTreeWidgetItem(self.tree) self.deletedItem.setFlags(Qt.ItemIsUserCheckable) self.changedItem = QTreeWidgetItem(self.tree) self.changedItem.setFlags(Qt.ItemIsUserCheckable) self.tree.itemChanged.connect(self.slotItemChanged) app.translateUI(self) app.languageChanged.connect(self.populate) self.accepted.connect(self.updateSnippets) qutil.saveDialogSize(self, "snippettool/restoredialog/size") def translateUI(self): self.setWindowTitle( app.caption(_("dialog title", "Restore Built-in Snippets"))) self.setMessage( _("This dialog allows you to recover built-in snippets that have " "been changed or deleted. Check the snippets you want to recover " "and click the button \"Restore Checked Snippets.\"")) self.button("ok").setText(_("Restore Checked Snippets")) self.deletedItem.setText(0, _("Deleted Snippets")) self.changedItem.setText(0, _("Changed Snippets")) def populate(self): """Puts the deleted/changed snippets in the tree.""" self.deletedItem.takeChildren() self.deletedItem.setExpanded(True) self.deletedItem.setCheckState(0, Qt.Unchecked) self.changedItem.takeChildren() self.changedItem.setExpanded(True) self.changedItem.setCheckState(0, Qt.Unchecked) builtins = list(builtin.builtin_snippets) builtins.sort(key=snippets.title) names = frozenset(snippets.names()) for name in builtins: if name in names: if snippets.isoriginal(name): continue parent = self.changedItem else: parent = self.deletedItem item = QTreeWidgetItem(parent) item.name = name item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) item.setCheckState(0, Qt.Unchecked) item.setText(0, snippets.title(name)) self.deletedItem.setDisabled(self.deletedItem.childCount() == 0) self.changedItem.setDisabled(self.changedItem.childCount() == 0) self.checkOkButton() def slotItemChanged(self, item): if item in (self.deletedItem, self.changedItem): for i in range(item.childCount()): item.child(i).setCheckState(0, item.checkState(0)) self.checkOkButton() def checkedSnippets(self): """Yields the names of the checked snippets.""" for parent in (self.deletedItem, self.changedItem): for i in range(parent.childCount()): child = parent.child(i) if child.checkState(0) == Qt.Checked: yield child.name def updateSnippets(self): """Restores the checked snippets.""" collection = self.parent().parent().snippetActions for name in self.checkedSnippets(): collection.restoreDefaultShortcuts(name) model.model().saveSnippet(name, None, None) def checkOkButton(self): """Enables the OK button if there are selected snippets.""" self.button("ok").setEnabled(any(self.checkedSnippets()))
def data(self, profile_data): """Set data for the widget. :param profile_data: profile data. :type profile_data: dict It will replace the previous data. """ default_profile = generate_default_profile() self.clear() for hazard in sorted(default_profile.keys()): classifications = default_profile[hazard] hazard_widget_item = QTreeWidgetItem() hazard_widget_item.setData(0, Qt.UserRole, hazard) hazard_widget_item.setText(0, get_name(hazard)) for classification in sorted(classifications.keys()): # Filter out classification that doesn't support population. # TODO(IS): This is not the best place to put the filtering. # It's more suitable in the generate_default_profile method # in safe/definitions/utilities. classification_definition = definition(classification) supported_exposures = classification_definition.get( 'exposures', []) # Empty list means support all exposure if supported_exposures != []: if exposure_population not in supported_exposures: continue classes = classifications[classification] classification_widget_item = QTreeWidgetItem() classification_widget_item.setData(0, Qt.UserRole, classification) classification_widget_item.setText(0, get_name(classification)) hazard_widget_item.addChild(classification_widget_item) for the_class, the_value in classes.items(): the_class_widget_item = QTreeWidgetItem() the_class_widget_item.setData(0, Qt.UserRole, the_class) the_class_widget_item.setText( 0, get_class_name(the_class, classification)) classification_widget_item.addChild(the_class_widget_item) # Adding widget must be happened after addChild affected_check_box = QCheckBox(self) # Set from profile_data if exist, else get default profile_value = profile_data.get(hazard, {}).get( classification, {}).get(the_class, the_value) affected_check_box.setChecked(profile_value['affected']) self.setItemWidget(the_class_widget_item, 1, affected_check_box) displacement_rate_spinbox = PercentageSpinBox(self) displacement_rate_spinbox.setValue( profile_value['displacement_rate']) displacement_rate_spinbox.setEnabled( profile_value['affected']) self.setItemWidget(the_class_widget_item, 2, displacement_rate_spinbox) # Behaviour when the check box is checked # noinspection PyUnresolvedReferences affected_check_box.stateChanged.connect( displacement_rate_spinbox.setEnabled) if hazard_widget_item.childCount() > 0: self.widget_items.append(hazard_widget_item) self.addTopLevelItems(self.widget_items) self.expandAll()
class GetScriptsAndModelsDialog(BASE, WIDGET): HELP_TEXT = QCoreApplication.translate( "GetScriptsAndModelsDialog", "<h3> Processing resources manager </h3>" "<p>Check/uncheck algorithms in the tree to select the ones that you " "want to install or remove</p>" "<p>Algorithms are divided in 3 groups:</p>" "<ul><li><b>Installed:</b> Algorithms already in your system, with " "the latest version available</li>" "<li><b>Updatable:</b> Algorithms already in your system, but with " "a newer version available in the server</li>" "<li><b>Not installed:</b> Algorithms not installed in your " "system</li></ul>", ) MODELS = 0 SCRIPTS = 1 RSCRIPTS = 2 def __init__(self, resourceType): super(GetScriptsAndModelsDialog, self).__init__(iface.mainWindow()) self.setupUi(self) self.resourceType = resourceType if self.resourceType == self.MODELS: self.folder = ModelerUtils.modelsFolder() self.urlBase = "https://raw.githubusercontent.com/qgis/QGIS-Processing/master/models/" self.icon = QIcon(os.path.join(pluginPath, "images", "model.png")) elif self.resourceType == self.SCRIPTS: self.folder = ScriptUtils.scriptsFolder() self.urlBase = "https://raw.githubusercontent.com/qgis/QGIS-Processing/master/scripts/" self.icon = QIcon(os.path.join(pluginPath, "images", "script.png")) else: self.folder = RUtils.RScriptsFolder() self.urlBase = "https://raw.githubusercontent.com/qgis/QGIS-Processing/master/rscripts/" self.icon = QIcon(os.path.join(pluginPath, "images", "r.png")) self.lastSelectedItem = None self.updateToolbox = False self.populateTree() self.buttonBox.accepted.connect(self.okPressed) self.buttonBox.rejected.connect(self.cancelPressed) self.tree.currentItemChanged.connect(self.currentItemChanged) def populateTree(self): self.uptodateItem = QTreeWidgetItem() self.uptodateItem.setText(0, self.tr("Installed")) self.toupdateItem = QTreeWidgetItem() self.toupdateItem.setText(0, self.tr("Updatable")) self.notinstalledItem = QTreeWidgetItem() self.notinstalledItem.setText(0, self.tr("Not installed")) self.toupdateItem.setIcon(0, self.icon) self.uptodateItem.setIcon(0, self.icon) self.notinstalledItem.setIcon(0, self.icon) resources = readUrl(self.urlBase + "list.txt").splitlines() resources = [r.split(",") for r in resources] self.resources = {f: (v, n) for f, v, n in resources} for filename, version, name in resources: treeBranch = self.getTreeBranchForState(filename, float(version)) item = TreeItem(filename, name, self.icon) treeBranch.addChild(item) if treeBranch != self.notinstalledItem: item.setCheckState(0, Qt.Checked) self.tree.addTopLevelItem(self.toupdateItem) self.tree.addTopLevelItem(self.notinstalledItem) self.tree.addTopLevelItem(self.uptodateItem) self.webView.setHtml(self.HELP_TEXT) def currentItemChanged(self, item, prev): if isinstance(item, TreeItem): try: url = self.urlBase + item.filename.replace(" ", "%20") + ".help" helpContent = readUrl(url) descriptions = json.loads(helpContent) html = "<h2>%s</h2>" % item.name html += self.tr("<p><b>Description:</b> %s</p>") % getDescription(ALG_DESC, descriptions) html += self.tr("<p><b>Created by:</b> %s") % getDescription(ALG_CREATOR, descriptions) html += self.tr("<p><b>Version:</b> %s") % getDescription(ALG_VERSION, descriptions) except HTTPError as e: html = self.tr("<h2>No detailed description available for this script</h2>") self.webView.setHtml(html) else: self.webView.setHtml(self.HELP_TEXT) def getTreeBranchForState(self, filename, version): if not os.path.exists(os.path.join(self.folder, filename)): return self.notinstalledItem else: helpFile = os.path.join(self.folder, filename + ".help") try: with open(helpFile) as f: helpContent = json.load(f) currentVersion = float(helpContent[Help2Html.ALG_VERSION]) except Exception: currentVersion = 0 if version > currentVersion: return self.toupdateItem else: return self.uptodateItem def cancelPressed(self): self.close() def okPressed(self): toDownload = [] for i in xrange(self.toupdateItem.childCount()): item = self.toupdateItem.child(i) if item.checkState(0) == Qt.Checked: toDownload.append(item.filename) for i in xrange(self.notinstalledItem.childCount()): item = self.notinstalledItem.child(i) if item.checkState(0) == Qt.Checked: toDownload.append(item.filename) if toDownload: self.progressBar.setMaximum(len(toDownload)) for i, filename in enumerate(toDownload): QCoreApplication.processEvents() url = self.urlBase + filename.replace(" ", "%20") try: code = readUrl(url) path = os.path.join(self.folder, filename) with open(path, "w") as f: f.write(code) except HTTPError: QMessageBox.critical( iface.mainWindow(), self.tr("Connection problem"), self.tr("Could not download file: %s") % filename, ) return url += ".help" try: html = readUrl(url) except HTTPError: html = '{"ALG_VERSION" : %s}' % self.resources[filename][0] path = os.path.join(self.folder, filename + ".help") with open(path, "w") as f: f.write(html) self.progressBar.setValue(i + 1) toDelete = [] for i in xrange(self.uptodateItem.childCount()): item = self.uptodateItem.child(i) if item.checkState(0) == Qt.Unchecked: toDelete.append(item.filename) for filename in toDelete: path = os.path.join(self.folder, filename) os.remove(path) self.updateToolbox = len(toDownload) + len(toDelete) > 0 self.close()
class MainDialog(QDialog, Ui_MainDialog): """The main dialog of QGIS2Web plugin.""" items = {} def __init__(self, iface): QDialog.__init__(self) self.setupUi(self) self.iface = iface self.previewUrl = None self.layer_search_combo = None self.exporter_combo = None self.feedback = FeedbackDialog(self) self.feedback.setModal(True) stgs = QSettings() self.restoreGeometry(stgs.value("qgis2web/MainDialogGeometry", QByteArray(), type=QByteArray)) 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.paramsTreeOL.setSelectionMode(QAbstractItemView.SingleSelection) self.preview = None if webkit_available: widget = QWebView() self.preview = widget webview = self.preview.page() webview.setNetworkAccessManager(QgsNetworkAccessManager.instance()) self.preview.settings().setAttribute( QWebSettings.DeveloperExtrasEnabled, 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.populateBasemaps() 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) self.layersTree.model().dataChanged.connect(self.populateLayerSearch) self.ol3.clicked.connect(self.changeFormat) self.leaflet.clicked.connect(self.changeFormat) self.buttonExport.clicked.connect(self.saveMap) readme = os.path.join(os.path.dirname(os.path.realpath(__file__)), "README.md") helpText = os.path.join(os.path.dirname(os.path.realpath(__file__)), "helpFile.md") lines = open(readme, 'r').readlines() with open(helpText, 'w') as helpFile: for ct, line in enumerate(lines): if ct > 4: helpFile.write(line) helpFile.close() self.helpField.setSource(QUrl.fromLocalFile(helpText)) if webkit_available: self.devConsole = QWebInspector(self.verticalLayoutWidget_2) self.devConsole.setFixedHeight(0) self.devConsole.setObjectName("devConsole") self.devConsole.setPage(self.preview.page()) self.right_layout.insertWidget(1, self.devConsole) self.filter = devToggleFilter() self.installEventFilter(self.filter) self.setModal(False) def changeFormat(self): self.autoUpdatePreview() self.toggleOptions() def exporterTypeChanged(self): new_exporter_name = self.exporter_combo.currentText() try: self.exporter = [ e for e in EXPORTER_REGISTRY.getExporters() if e.name() == new_exporter_name][0]() except: pass def currentMapFormat(self): """ Returns the currently selected map writer type """ return self.getWriterFactory().type() def getWriterFactory(self): """ Returns a factory to create the currently selected map writer """ if self.mapFormat.checkedButton() == self.ol3: return OpenLayersWriter elif self.mapFormat.checkedButton() == self.leaflet: return LeafletWriter def createWriter(self): """ Creates a writer object reflecting the current settings in the dialog """ writer = self.getWriterFactory()() (writer.layers, writer.groups, writer.popup, writer.visible, writer.json, writer.cluster) = self.getLayersAndGroups() writer.params = self.getParameters() return writer def showErrorMessage(self, error): """ Shows an error message in the preview window """ html = "<html>" html += "<head></head>" html += "<style>body {font-family: sans-serif;}</style>" html += "<body><h1>Error</h1>" html += "<p>qgis2web produced an error:</p><code>" html += error html += "</code></body></html>" if self.preview: self.preview.setHtml(html) def showFeedbackMessage(self, title, message): """ Shows a feedback message in the preview window """ html = "<html>" html += "<head></head>" html += "<style>body {font-family: sans-serif;}</style>" html += "<body><h1>{}</h1>".format(title) html += "<p>{}</p>".format(message) html += "</body></html>" if self.preview: self.preview.setHtml(html) def toggleOptions(self): currentWriter = self.getWriterFactory() for param, value in specificParams.iteritems(): treeParam = self.paramsTreeOL.findItems(param, (Qt.MatchExactly | Qt.MatchRecursive))[0] if currentWriter == OpenLayersWriter: if value == "OL3": treeParam.setDisabled(False) else: treeParam.setDisabled(True) else: if value == "OL3": treeParam.setDisabled(True) else: treeParam.setDisabled(False) for option, value in specificOptions.iteritems(): treeOptions = self.layersTree.findItems(option, (Qt.MatchExactly | Qt.MatchRecursive)) for treeOption in treeOptions: if currentWriter == OpenLayersWriter: if value == "OL3": treeOption.setDisabled(False) else: treeOption.setDisabled(True) else: if value == "OL3": treeOption.setDisabled(True) else: treeOption.setDisabled(False) def createPreview(self): writer = self.createWriter() return writer.write(self.iface, dest_folder=utils.tempFolder()).index_file def shouldAutoPreview(self): """ Returns a tuple, with a bool for whether the preview should automatically be generated, and a string for explanations as to why the preview cannot be automatically generated """ writer = self.createWriter() total_features = 0 for layer in writer.layers: if isinstance(layer, QgsVectorLayer): total_features += layer.featureCount() if total_features > int(self.previewFeatureLimit.text()): # Too many features => too slow! return (False, self.tr('<p>A large number of features are ' 'present in the map. Generating the ' 'preview may take some time.</p>' '<p>Click Update Preview to generate the ' 'preview anyway.</p>')) return (True, None) def autoUpdatePreview(self): """ Triggered when a preview will be automatically generated, i.e. not as a result of the user manually clicking the Update Preview button. """ (auto_preview, message) = self.shouldAutoPreview() if not auto_preview: self.showFeedbackMessage(self.tr('Preview Map'), message) else: self.previewMap() def previewMap(self): try: preview_file = self.createPreview() self.loadPreviewFile(preview_file) except Exception as e: self.showErrorMessage( traceback.format_exc().replace("\n", "<br />")) QgsMessageLog.logMessage(traceback.format_exc(), "qgis2web", level=QgsMessageLog.CRITICAL) def saveMap(self): writer = self.createWriter() write_folder = self.exporter.exportDirectory() if not write_folder: return self.feedback.reset() self.feedback.show() results = writer.write(self.iface, dest_folder=write_folder, feedback=self.feedback) self.feedback.showFeedback('Success') if self.closeFeedbackOnSuccess.checkState() == Qt.Checked: self.feedback.close() result = self.exporter.postProcess(results, feedback=self.feedback) if result and (not os.environ.get('CI') and not os.environ.get('TRAVIS')): webbrowser.open_new_tab(self.exporter.destinationUrl()) def populate_layers_and_groups(self, dlg): """Populate layers on QGIS into our layers and group tree view.""" root_node = QgsProject.instance().layerTreeRoot() tree_groups = [] tree_layers = root_node.findLayers() self.layers_item = QTreeWidgetItem() self.layers_item.setText(0, "Layers and Groups") self.layersTree.setColumnCount(3) for tree_layer in tree_layers: layer = tree_layer.layer() if layer.type() != QgsMapLayer.PluginLayer: try: if layer.type() == QgsMapLayer.VectorLayer: testDump = layer.rendererV2().dump() layer_parent = tree_layer.parent() if layer_parent.parent() is None: item = TreeLayerItem(self.iface, layer, self.layersTree, dlg) self.layers_item.addChild(item) else: if layer_parent not in tree_groups: tree_groups.append(layer_parent) except: QgsMessageLog.logMessage(traceback.format_exc(), "qgis2web", level=QgsMessageLog.CRITICAL) for tree_group in tree_groups: group_name = tree_group.name() group_layers = [ tree_layer.layer() for tree_layer in tree_group.findLayers()] item = TreeGroupItem(group_name, group_layers, self.layersTree) self.layers_item.addChild(item) self.layersTree.addTopLevelItem(self.layers_item) self.layersTree.expandAll() self.layersTree.resizeColumnToContents(0) self.layersTree.resizeColumnToContents(1) for i in xrange(self.layers_item.childCount()): item = self.layers_item.child(i) if item.checkState(0) != Qt.Checked: item.setExpanded(False) def populateLayerSearch(self): self.layer_search_combo.clear() self.layer_search_combo.addItem("None") (layers, groups, popup, visible, json, cluster) = self.getLayersAndGroups() for count, layer in enumerate(layers): if layer.type() == layer.VectorLayer: options = [] fields = layer.pendingFields() for f in fields: fieldIndex = fields.indexFromName(unicode(f.name())) try: formCnf = layer.editFormConfig() editorWidget = formCnf.widgetType(fieldIndex) except: editorWidget = layer.editorWidgetV2(fieldIndex) if editorWidget == QgsVectorLayer.Hidden \ or editorWidget == 'Hidden': continue options.append(unicode(f.name())) for option in options: displayStr = unicode(layer.name() + ": " + option) self.layer_search_combo.insertItem(0, displayStr) sln = utils.safeName(layer.name()) self.layer_search_combo.setItemData( self.layer_search_combo.findText(displayStr), sln + unicode(count)) def configureExporter(self): self.exporter.configure() def populateConfigParams(self, dlg): """ Populates the dialog with option items and widgets """ self.items = defaultdict(dict) tree = dlg.paramsTreeOL configure_export_action = QAction('...', self) configure_export_action.triggered.connect(self.configureExporter) params = getParams(configure_exporter_action=configure_export_action) for group, settings in params.iteritems(): item = QTreeWidgetItem() item.setText(0, group) for param, value in settings.iteritems(): subitem = self.createOptionItem(tree_widget=tree, parent_item=item, parameter=param, default_value=value) item.addChild(subitem) self.items[group][param] = subitem self.paramsTreeOL.addTopLevelItem(item) item.sortChildren(0, Qt.AscendingOrder) self.paramsTreeOL.expandAll() self.paramsTreeOL.resizeColumnToContents(0) self.paramsTreeOL.resizeColumnToContents(1) self.layer_search_combo.removeItem(1) def createOptionItem(self, tree_widget, parent_item, parameter, default_value): """create the tree item corresponding to an option parameter""" action = None if isinstance(default_value, dict): action = default_value['action'] default_value = default_value['option'] subitem = TreeSettingItem(parent_item, tree_widget, parameter, default_value, action) if parameter == 'Layer search': self.layer_search_combo = subitem.combo elif parameter == 'Exporter': self.exporter_combo = subitem.combo return subitem def setStateToWriter(self, writer): """ Sets the dialog state to match the specified writer """ self.selectMapFormat(writer) self.setStateToParams(writer.params) self.setStateForBasemaps(writer.params["Appearance"]["Base layer"]) def setStateToParams(self, params): """ Sets the dialog state to match the specified parameters """ for group, settings in self.items.iteritems(): for param, item in settings.iteritems(): value = params[group][param] item.setValue(value) def setStateForBasemaps(self, basemaps): """ Sets the dialog state to match the specified basemaps """ for i in range(self.basemaps.count()): self.basemaps.item(i).setSelected(False) for basemap in basemaps: try: self.basemaps.findItems(basemap, (Qt.MatchExactly))[0].setSelected(True) except: pass def populateBasemaps(self): """ Adds entries for all known basemaps to the dialog """ multiSelect = QAbstractItemView.ExtendedSelection self.basemaps.setSelectionMode(multiSelect) attrFields = [] for i in range(len(baselayers)): for key in baselayers[i]: attrFields.append(key) self.basemaps.addItems(attrFields) def selectMapFormat(self, writer): """ Updates dialog state to match the specified writer format """ self.ol3.setChecked(isinstance(writer, OpenLayersWriter)) self.leaflet.setChecked(isinstance(writer, LeafletWriter)) def loadPreviewFile(self, file): """ Loads a web based preview from a local file path """ self.previewUrl = QUrl.fromLocalFile(file) if self.preview: self.preview.settings().clearMemoryCaches() self.preview.setUrl(self.previewUrl) def getParameters(self): parameters = defaultdict(dict) for group, settings in self.items.iteritems(): for param, item in settings.iteritems(): parameters[group][param] = item.value() if param == "Layer search": parameters["Appearance"]["Search layer"] = ( self.layer_search_combo.itemData( self.layer_search_combo.currentIndex())) basemaps = [i.text() for i in self.basemaps.selectedItems()] parameters["Appearance"]["Base layer"] = basemaps return parameters def saveParameters(self): """ Saves current dialog state to project """ WRITER_REGISTRY.saveWriterToProject(self.createWriter()) EXPORTER_REGISTRY.writeToProject(self.exporter) def getLayersAndGroups(self): layers = [] groups = {} popup = [] visible = [] json = [] cluster = [] for i in xrange(self.layers_item.childCount()): item = self.layers_item.child(i) if isinstance(item, TreeLayerItem): if item.checkState(0) == Qt.Checked: layers.append(item.layer) popup.append(item.popup) visible.append(item.visible) json.append(item.json) cluster.append(item.cluster) else: group = item.name groupLayers = [] if item.checkState(0) != Qt.Checked: continue for layer in item.layers: groupLayers.append(layer) layers.append(layer) popup.append(utils.NO_POPUP) if item.visible: visible.append(True) else: visible.append(False) if hasattr(item, "json") and item.json: json.append(True) else: json.append(False) if hasattr(item, "cluster") and item.cluster: cluster.append(True) else: cluster.append(False) groups[group] = groupLayers[::-1] return (layers[::-1], groups, popup[::-1], visible[::-1], json[::-1], cluster[::-1]) def closeEvent(self, event): self.saveParameters() (layers, groups, popup, visible, json, cluster) = self.getLayersAndGroups() for layer, pop, vis in zip(layers, popup, visible): attrDict = {} for attr in pop: attrDict['attr'] = pop[attr] layer.setCustomProperty("qgis2web/popup/" + attr, pop[attr]) layer.setCustomProperty("qgis2web/Visible", vis) QSettings().setValue( "qgis2web/MainDialogGeometry", self.saveGeometry()) QSettings().setValue("qgis2web/previewOnStartup", self.previewOnStartup.checkState()) QSettings().setValue("qgis2web/closeFeedbackOnSuccess", self.closeFeedbackOnSuccess.checkState()) QSettings().setValue("qgis2web/previewFeatureLimit", self.previewFeatureLimit.text()) event.accept()
def __init__(self, dialog): super(Shortcuts, self).__init__(dialog) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) self.setLayout(layout) self.scheme = SchemeSelector(self) layout.addWidget(self.scheme) self.tree = QTreeWidget(self) self.tree.setHeaderLabels([_("Command"), _("Shortcut")]) self.tree.setRootIsDecorated(False) self.tree.setColumnCount(2) self.tree.setAllColumnsShowFocus(True) self.tree.setAnimated(True) layout.addWidget(self.tree) self.edit = QPushButton( icons.get("preferences-desktop-keyboard-shortcuts"), '') layout.addWidget(self.edit) # signals self.scheme.currentChanged.connect(self.slotSchemeChanged) self.scheme.changed.connect(self.changed) self.tree.currentItemChanged.connect(self.slotCurrentItemChanged) self.tree.itemDoubleClicked.connect(self.editCurrentItem) self.edit.clicked.connect(self.editCurrentItem) # make a dict of all actions with the actions as key and the names as # value, with the collection prepended (for loading/saving) win = dialog.parent() allactions = {} for collection in actioncollectionmanager.manager( win).actionCollections(): for name, action in collection.actions().items(): allactions[action] = (collection, name) # keep a list of actions not in the menu structure left = list(allactions.keys()) def add_actions(menuitem, actions): """Add actions to a QTreeWidgetItem.""" for a in actions: if a.menu(): item = build_menu_item(a) if item.childCount(): menuitem.addChild(item) elif a in left: left.remove(a) menuitem.addChild(ShortcutItem(a, *allactions[a])) menuitem.setFlags(Qt.ItemIsEnabled) # disable selection def build_menu_item(action): """Return a QTreeWidgetItem with children for all the actions in the submenu.""" menuitem = QTreeWidgetItem() text = qutil.removeAccelerator(action.text()) menuitem.setText(0, _("Menu {name}").format(name=text)) add_actions(menuitem, action.menu().actions()) return menuitem # present the actions nicely ordered as in the menus for a in win.menuBar().actions(): menuitem = build_menu_item(a) if menuitem.childCount(): self.tree.addTopLevelItem(menuitem) # sort leftover actions left.sort(key=lambda i: i.text()) # show actions that are left, grouped by collection titlegroups = {} for a in left[:]: # copy collection, name = allactions[a] if collection.title(): titlegroups.setdefault(collection.title(), []).append(a) left.remove(a) for title in sorted(titlegroups): item = QTreeWidgetItem(["{0}:".format(title)]) for a in titlegroups[title]: item.addChild(ShortcutItem(a, *allactions[a])) self.tree.addTopLevelItem(item) item.setFlags(Qt.ItemIsEnabled) # disable selection # show other actions that were not in the menus item = QTreeWidgetItem([_("Other commands:")]) for a in left: if a.text() and not a.menu(): item.addChild(ShortcutItem(a, *allactions[a])) if item.childCount(): self.tree.addTopLevelItem(item) item.setFlags(Qt.ItemIsEnabled) # disable selection self.tree.expandAll() item = self.tree.topLevelItem(0).child(0) if _lastaction: # find the previously selected item for i in self.items(): if i.name == _lastaction: item = i break self.tree.setCurrentItem(item) self.tree.resizeColumnToContents(0)
def refresh(self): """ Refreshing search results panel """ title = "'%s' - " % self.search_text if self.results is None: text = _('Search canceled') else: nb_files = len(self.results) if nb_files == 0: text = _('String not found') else: text_matches = _('matches in') text_files = _('file') if nb_files > 1: text_files += 's' text = "%d %s %d %s" % (self.nb, text_matches, nb_files, text_files) if self.error_flag: text += ' (' + self.error_flag + ')' elif self.results is not None and not self.completed: text += ' (' + _('interrupted') + ')' self.set_title(title+text) self.clear() self.data = {} if not self.results: # First search interrupted *or* No result return # Directory set dir_set = set() for filename in sorted(self.results.keys()): dirname = osp.abspath(osp.dirname(filename)) dir_set.add(dirname) # Root path root_path_list = None _common = get_common_path(list(dir_set)) if _common is not None: root_path_list = [_common] else: _common = get_common_path(self.pathlist) if _common is not None: root_path_list = [_common] else: root_path_list = self.pathlist if not root_path_list: return for _root_path in root_path_list: dir_set.add(_root_path) # Populating tree: directories def create_dir_item(dirname, parent): if dirname not in root_path_list: displayed_name = osp.basename(dirname) else: displayed_name = dirname item = QTreeWidgetItem(parent, [displayed_name], QTreeWidgetItem.Type) item.setIcon(0, get_std_icon('DirClosedIcon')) return item dirs = {} for dirname in sorted(list(dir_set)): if dirname in root_path_list: parent = self else: parent_dirname = abspardir(dirname) parent = dirs.get(parent_dirname) if parent is None: # This is related to directories which contain found # results only in some of their children directories if osp.commonprefix([dirname]+root_path_list): # create new root path pass items_to_create = [] while dirs.get(parent_dirname) is None: items_to_create.append(parent_dirname) parent_dirname = abspardir(parent_dirname) items_to_create.reverse() for item_dir in items_to_create: item_parent = dirs[abspardir(item_dir)] dirs[item_dir] = create_dir_item(item_dir, item_parent) parent_dirname = abspardir(dirname) parent = dirs[parent_dirname] dirs[dirname] = create_dir_item(dirname, parent) self.root_items = [dirs[_root_path] for _root_path in root_path_list] # Populating tree: files for filename in sorted(self.results.keys()): parent_item = dirs[osp.dirname(filename)] file_item = QTreeWidgetItem(parent_item, [osp.basename(filename)], QTreeWidgetItem.Type) file_item.setIcon(0, get_filetype_icon(filename)) colno_dict = {} fname_res = [] for lineno, colno, line in self.results[filename]: if lineno not in colno_dict: fname_res.append((lineno, colno, line)) colno_dict[lineno] = colno_dict.get(lineno, [])+[str(colno)] for lineno, colno, line in fname_res: colno_str = ",".join(colno_dict[lineno]) item = QTreeWidgetItem(file_item, ["%d (%s): %s" % (lineno, colno_str, line.rstrip())], QTreeWidgetItem.Type) item.setIcon(0, get_icon('arrow.png')) self.data[item] = (filename, lineno) # Removing empty directories top_level_items = [self.topLevelItem(index) for index in range(self.topLevelItemCount())] for item in top_level_items: if not item.childCount(): self.takeTopLevelItem(self.indexOfTopLevelItem(item))
class RestoreDialog(widgets.dialog.Dialog): def __init__(self, parent=None): super(RestoreDialog, self).__init__(parent) self.messageLabel().setWordWrap(True) userguide.addButton(self.buttonBox(), "snippets") self.tree = QTreeWidget(headerHidden=True, rootIsDecorated=False) self.setMainWidget(self.tree) self.deletedItem = QTreeWidgetItem(self.tree) self.deletedItem.setFlags(Qt.ItemIsUserCheckable) self.changedItem = QTreeWidgetItem(self.tree) self.changedItem.setFlags(Qt.ItemIsUserCheckable) self.tree.itemChanged.connect(self.slotItemChanged) app.translateUI(self) app.languageChanged.connect(self.populate) self.accepted.connect(self.updateSnippets) qutil.saveDialogSize(self, "snippettool/restoredialog/size") def translateUI(self): self.setWindowTitle( app.caption(_("dialog title", "Restore Built-in Snippets"))) self.setMessage(_( "This dialog allows you to recover built-in snippets that have " "been changed or deleted. Check the snippets you want to recover " "and click the button \"Restore Checked Snippets.\"")) self.button("ok").setText(_("Restore Checked Snippets")) self.deletedItem.setText(0, _("Deleted Snippets")) self.changedItem.setText(0, _("Changed Snippets")) def populate(self): """Puts the deleted/changed snippets in the tree.""" self.deletedItem.takeChildren() self.deletedItem.setExpanded(True) self.deletedItem.setCheckState(0, Qt.Unchecked) self.changedItem.takeChildren() self.changedItem.setExpanded(True) self.changedItem.setCheckState(0, Qt.Unchecked) builtins = list(builtin.builtin_snippets) builtins.sort(key = snippets.title) names = frozenset(snippets.names()) for name in builtins: if name in names: if snippets.isoriginal(name): continue parent = self.changedItem else: parent = self.deletedItem item = QTreeWidgetItem(parent) item.name = name item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) item.setCheckState(0, Qt.Unchecked) item.setText(0, snippets.title(name)) self.deletedItem.setDisabled(self.deletedItem.childCount() == 0) self.changedItem.setDisabled(self.changedItem.childCount() == 0) self.checkOkButton() def slotItemChanged(self, item): if item in (self.deletedItem, self.changedItem): for i in range(item.childCount()): item.child(i).setCheckState(0, item.checkState(0)) self.checkOkButton() def checkedSnippets(self): """Yields the names of the checked snippets.""" for parent in (self.deletedItem, self.changedItem): for i in range(parent.childCount()): child = parent.child(i) if child.checkState(0) == Qt.Checked: yield child.name def updateSnippets(self): """Restores the checked snippets.""" collection = self.parent().parent().snippetActions for name in self.checkedSnippets(): collection.restoreDefaultShortcuts(name) model.model().saveSnippet(name, None, None) def checkOkButton(self): """Enables the OK button if there are selected snippets.""" self.button("ok").setEnabled(any(self.checkedSnippets()))
def on_addUpdatePushButton_clicked(self): """ Creates a new reclassification button ready to be used """ #checking if the button name is defined if self.buttonNameLineEdit.text() == '': QMessageBox.critical(self, self.tr('Critical!'), self.tr('Enter a button name!')) return if not self.validateShortcut(self.buttonNameLineEdit.text()): QMessageBox.critical(self, self.tr('Critical!'), self.tr('Shortcut already set to another tool!')) return # invisible root item rootItem = self.treeWidget.invisibleRootItem() # class row in the classListWidget classRow = self.tableComboBox.currentText() schemaName, tableName = self.abstractDb.getTableSchema(classRow) if self.abstractDb.db.driverName() == 'QSQLITE': category = schemaName + '_' + tableName.split('_')[0] else: if self.edgvVersion == 'Non_EDGV': category = schemaName else: category = schemaName + '.' + tableName.split('_')[0] # creating items in tree buttonInTree = False leafChildInTree = False leafInTree = False for i in range(rootItem.childCount()): leaf = rootItem.child(i) if leaf.text(0) == category: leafInTree = True item = leaf for j in range(leaf.childCount()): leafChild = leaf.child(j) if leafChild.text(0) == self.tableComboBox.currentText(): leafChildInTree = True item = leafChild for k in range(leafChild.childCount()): leafGrandson = leafChild.child(k) if leafGrandson.text(0) == self.buttonNameLineEdit.text(): buttonItem = leafGrandson buttonItem.setText(0, self.buttonNameLineEdit.text()) buttonInTree = True break if not leafInTree: item = QTreeWidgetItem(rootItem) item.setText(0, category) if not leafChildInTree: item = QTreeWidgetItem(item) item.setText(0, classRow) if not buttonInTree: # item that will be used to create the button buttonItem = QTreeWidgetItem(item) buttonItem.setText(0, self.buttonNameLineEdit.text()) if self.abstractDb.db.driverName() == 'QSQLITE': self.qmlPath = os.path.join(self.qmlDir, tableName+'.qml') fullTableName = schemaName+'_'+tableName else: fullTableName = schemaName+'.'+tableName qmlDict = self.buildQmlDict(fullTableName) #add optional parameters to self.buttonPropDict if fullTableName not in self.buttonPropDict.keys(): self.buttonPropDict[fullTableName] = dict() #parameter dict from buttonPropWidget has the following format: #{'buttonColor':--color of the button--, 'buttonToolTip'--button toolTip--, 'buttonGroupTag':--group tag of the button--} self.buttonPropDict[fullTableName][self.buttonNameLineEdit.text()] = self.buttonPropWidget.getParameterDict() # accessing the attribute name and widget (QComboBox or QListWidget depending on data type) for i in range(self.attributeTableWidget.rowCount()): attribute = self.attributeTableWidget.item(i, 0).text() # this guy is a QComboBox or a QListWidget widgetItem = self.attributeTableWidget.cellWidget(i, 1) if attribute in qmlDict.keys(): if isinstance(qmlDict[attribute], dict): if widgetItem.currentText() in qmlDict[attribute].keys(): value = qmlDict[attribute][widgetItem.currentText()] if isinstance(qmlDict[attribute], tuple): (table, filterKeys) = qmlDict[attribute] valueRelation = self.makeValueRelationDict(table, filterKeys) values = [] for i in range(widgetItem.count()): if widgetItem.item(i).checkState() == Qt.Checked: key = widgetItem.item(i).text() values.append(valueRelation[key]) value = '{%s}' % ','.join(map(str, values)) else: value = widgetItem.text() #sweep tree for attribute attrFound = False for k in range(buttonItem.childCount()): attrItem = buttonItem.child(k) if attribute == attrItem.text(0): attrFound = True attributeItem = attrItem break if not attrFound: attributeItem = QTreeWidgetItem(buttonItem) attributeItem.setText(0, attribute) attributeItem.setText(1, value) for j in [2,3]: itemCell = self.attributeTableWidget.cellWidget(i, j) if itemCell: if itemCell.isEnabled(): itemText = itemCell.currentText() attributeItem.setText(j, self.optionalDict[itemText])
def fillListBox(self, f25, f50, f100, f250): self.cartasList.clear() item25 = QTreeWidgetItem(['1:25.000 (' + str(len(f25)) + ')', '']) item50 = QTreeWidgetItem(['1:50.000 (' + str(len(f50)) + ')', '']) item100 = QTreeWidgetItem(['1:100.000 (' + str(len(f100)) + ')', '']) item250 = QTreeWidgetItem(['1:250.000 (' + str(len(f250)) + ')', '']) itemNotFound = QTreeWidgetItem([u'Não existentes', '']) self.cartasList.addTopLevelItems( [item25, item50, item100, item250, itemNotFound]) for c in f25.keys(): if f25[c] != '': if f25[c][0] != '-': item = QTreeWidgetItem([c, f25[c]]) item25.addChild(item) else: item = QTreeWidgetItem([c, '']) itemNotFound.addChild(item) else: item = QTreeWidgetItem([c, '']) itemNotFound.addChild(item) item25.setExpanded(True) for c in f50.keys(): if f50[c] != '': if f50[c][0] != '-': item = QTreeWidgetItem([c, f50[c]]) item50.addChild(item) else: item = QTreeWidgetItem([c, '']) itemNotFound.addChild(item) else: item = QTreeWidgetItem([c, '']) itemNotFound.addChild(item) item50.setExpanded(True) for c in f100.keys(): if f100[c] != '': if f100[c][0] != '-': item = QTreeWidgetItem([c, f100[c]]) item100.addChild(item) else: item = QTreeWidgetItem([c, '']) itemNotFound.addChild(item) else: item = QTreeWidgetItem([c, '']) itemNotFound.addChild(item) item100.setExpanded(True) for c in f250.keys(): if f250[c] != '': if f250[c][0] != '-': item = QTreeWidgetItem([c, f250[c]]) item250.addChild(item) else: item = QTreeWidgetItem([c, '']) itemNotFound.addChild(item) else: item = QTreeWidgetItem([c, '']) itemNotFound.addChild(item) item250.setExpanded(True) itemNotFound.setExpanded(True) if itemNotFound.childCount() == 0: self.cartasList.invisibleRootItem().removeChild(itemNotFound) else: itemNotFound.setText( 0, itemNotFound.text(0) + ' (' + str(itemNotFound.childCount()) + ')') self.cartasList.header().setResizeMode( QtGui.QHeaderView.ResizeToContents)
class DeviceDialog(QDialog, Ui_DeviceDialog): """ Function and Event handling class for the Ui_DeviceDialog. """ qtcb_enumerate = pyqtSignal(str, str, 'char', type((0,)), type((0,)), int, int) qtcb_connected = pyqtSignal(int) def __init__(self, parent): QDialog.__init__(self, parent, get_modeless_dialog_flags()) self._logger_window = parent self.qtcb_enumerate.connect(self.cb_enumerate) self.qtcb_connected.connect(self.cb_connected) self.host = None self.port = None self.secret = None self.ipcon = IPConnection() self.ipcon.register_callback(IPConnection.CALLBACK_CONNECTED, self.qtcb_connected.emit) self.ipcon.register_callback(IPConnection.CALLBACK_ENUMERATE, self.qtcb_enumerate.emit) self.setupUi(self) self.btn_add_device.clicked.connect(self.btn_add_device_clicked) self.btn_refresh.clicked.connect(self.btn_refresh_clicked) self.btn_close.clicked.connect(self.btn_close_clicked) self.tree_widget.itemActivated.connect(self.add_item) self.connected_uids = [] self.available_item = QTreeWidgetItem(['No devices available']) self.supported_item = QTreeWidgetItem(['Supported devices']) self.tree_widget.addTopLevelItem(self.available_item) self.tree_widget.addTopLevelItem(self.supported_item) for device_name in device_specs: self.supported_item.addChild(QTreeWidgetItem([device_name])) self.supported_item.sortChildren(0, Qt.AscendingOrder) self.supported_item.setExpanded(True) def cb_connected(self, connect_reason): self.tree_widget.clearSelection() self.available_item.takeChildren() self.available_item.setExpanded(True) self.available_item.setText(0, 'No devices available at {0}:{1}'.format(self.host, self.port)) self.connected_uids = [] if self.secret != None: self.ipcon.set_auto_reconnect(False) # don't auto-reconnect on authentication error try: self.ipcon.authenticate(self.secret) except: try: self.ipcon.disconnect() except: pass if connect_reason == IPConnection.CONNECT_REASON_AUTO_RECONNECT: extra = ' after auto-reconnect' else: extra = '' self.available_item.setText(0, 'Could not authenticate' + extra) return self.ipcon.set_auto_reconnect(True) try: self.ipcon.enumerate() except: pass def cb_enumerate(self, uid, connected_uid, position, hardware_version, firmware_version, device_identifier, enumeration_type): if enumeration_type in [IPConnection.ENUMERATION_TYPE_AVAILABLE, IPConnection.ENUMERATION_TYPE_CONNECTED]: if uid not in self.connected_uids: try: display_name = device_factory.get_device_display_name(device_identifier) except KeyError: return # unknown device identifier if display_name in device_specs: self.connected_uids.append(uid) self.available_item.addChild(QTreeWidgetItem(['{0} [{1}]'.format(display_name, uid)])) self.available_item.setText(0, 'Devices available at {0}:{1}'.format(self.host, self.port)) self.available_item.sortChildren(0, Qt.AscendingOrder) else: if uid in self.connected_uids: self.connected_uids.remove(uid) for i in range(self.available_item.childCount()): child = self.available_item.child(i) if '[{0}]'.format(uid) in child.text(0): self.available_item.takeChild(i) break if self.available_item.childCount() == 0: self.available_item.setText(0, 'No devices available at {0}:{1}'.format(self.host, self.port)) def btn_add_device_clicked(self): for item in self.tree_widget.selectedItems(): if item == self.available_item or item == self.supported_item: continue self._logger_window.add_device_to_tree(self.create_device_config(item.text(0))) def btn_refresh_clicked(self): try: self.ipcon.disconnect() except: pass self.tree_widget.clearSelection() self.available_item.takeChildren() self.available_item.setExpanded(True) self.connected_uids = [] self.host = self._logger_window.combo_host.currentText() self.port = self._logger_window.spin_port.value() if self._logger_window.check_authentication.isChecked(): try: self.secret = self._logger_window.edit_secret.text().encode('ascii') except: self.secret = None else: self.secret = None try: self.ipcon.connect(self.host, self.port) self.available_item.setText(0, 'No devices available at {0}:{1}'.format(self.host, self.port)) except: self.available_item.setText(0, 'Could not connect to {0}:{1}'.format(self.host, self.port)) def btn_close_clicked(self): self.close() def add_item(self, item): if item == self.available_item or item == self.supported_item: return self._logger_window.add_device_to_tree(self.create_device_config(item.text(0))) def create_device_config(self, item_text): name, uid = Utilities.parse_device_name(item_text) # FIXME device_spec = device_specs[name] if uid == None: # FIXME uid = '' device = { 'host': 'default', 'name': name, 'uid': uid, 'values': {}, 'options': {} } for value_spec in device_spec['values']: device['values'][value_spec['name']] = {'interval': 0} if value_spec['subvalues'] != None: device['values'][value_spec['name']]['subvalues'] = {} for subvalue_name in value_spec['subvalues']: device['values'][value_spec['name']]['subvalues'][subvalue_name] = True if device_spec['options'] != None: for option_spec in device_spec['options']: device['options'][option_spec['name']] = {'value': option_spec['default']} return device
class DSManagerModel(QAbstractItemModel): __metaclass__ = QSingleton COLUMN_GROUP_DS = 0 COLUMN_VISIBILITY = 1 COLUMN_SOURCE = 2 # instance = None # @classmethod # def getInstance(cls): # if cls.instance def __init__(self, parent=None): super(DSManagerModel, self).__init__(parent) self.columnNames = [] self.columnNames.insert(self.COLUMN_GROUP_DS, self.tr("Group/DS")) self.columnNames.insert(self.COLUMN_VISIBILITY, self.tr("Visible")) self.columnNames.insert(self.COLUMN_SOURCE, self.tr("Source")) self.rootItem = QTreeWidgetItem(self.columnNames) self.__setupModelData() def resetModel(self): self.beginResetModel() self.__clear() self.__setupModelData() self.endResetModel() self.modelReset.emit() def __clear(self): for groupIndex in range(self.rootItem.childCount() - 1, -1, -1): groupItem = self.rootItem.child(groupIndex) for dsIndex in range(groupItem.childCount() - 1, -1, -1): dsItem = groupItem.child(dsIndex) groupItem.removeChild(dsItem) self.rootItem.removeChild(groupItem) def __setupModelData(self): dsList = DataSourcesList().data_sources.values() groupInfoList = GroupsList().groups groupsItems = [] groups = [] for ds in dsList: if ds.group in groups: group_item = groupsItems[groups.index(ds.group)] else: group_item = QTreeWidgetItem() group_item.setData(self.COLUMN_GROUP_DS, Qt.DisplayRole, ds.group) group_item.setData(self.COLUMN_VISIBILITY, Qt.DisplayRole, "") group_item.setData(self.COLUMN_SOURCE, Qt.DisplayRole, ds.category) group_item.setCheckState(self.COLUMN_VISIBILITY, Qt.Unchecked) groupInfo = groupInfoList.get(ds.group) if groupInfo is not None: group_item.setIcon(self.COLUMN_GROUP_DS, QIcon(groupInfo.icon)) else: group_item.setData( self.COLUMN_GROUP_DS, Qt.DisplayRole, ds.group + " (%s!)" % self.tr("group not found")) group_item.setData(self.COLUMN_GROUP_DS, Qt.UserRole, groupInfo) groups.append(ds.group) groupsItems.append(group_item) self.rootItem.addChild(group_item) ds_item = QTreeWidgetItem() ds_item.setData(self.COLUMN_GROUP_DS, Qt.DisplayRole, ds.alias) ds_item.setIcon(self.COLUMN_GROUP_DS, QIcon(ds.icon_path)) ds_item.setData(self.COLUMN_GROUP_DS, Qt.UserRole, ds) ds_item.setData(self.COLUMN_VISIBILITY, Qt.DisplayRole, "") ds_item.setData(self.COLUMN_SOURCE, Qt.DisplayRole, ds.category) ds_check_state = Qt.Checked if ds.id in PluginSettings.get_hide_ds_id_list(): ds_check_state = Qt.Unchecked ds_item.setCheckState(self.COLUMN_VISIBILITY, ds_check_state) if group_item.childCount() != 0 and group_item.checkState( 1) != ds_check_state: group_item.setCheckState(self.COLUMN_VISIBILITY, Qt.PartiallyChecked) else: group_item.setCheckState(self.COLUMN_VISIBILITY, ds_check_state) group_item.addChild(ds_item) def setData(self, index, value, role): if not index.isValid(): return False else: item = index.internalPointer() if role == Qt.CheckStateRole: item.setData(self.COLUMN_VISIBILITY, role, value) self.dataChanged.emit(index, index) self.updateChecks(index, value) return True def updateChecks(self, index, checkState): if self.hasChildren(index): for row in range(0, self.rowCount(index)): childItem = index.internalPointer().child(row) childItem.setCheckState(index.column(), checkState) self.dataChanged.emit(self.index(0, index.column(), index), self.index(row, index.column(), index)) else: parentIndex = self.parent(index) parentItem = parentIndex.internalPointer() diff = False for row in range(0, self.rowCount(parentIndex)): childItem = parentItem.child(row) if childItem.checkState(index.column()) != checkState: diff = True break if diff: parentItem.setCheckState(index.column(), Qt.PartiallyChecked) else: parentItem.setCheckState(index.column(), checkState) self.dataChanged.emit(parentIndex, parentIndex) def columnCount(self, parent): if parent.isValid(): return parent.internalPointer().columnCount() else: return self.rootItem.columnCount() def data(self, index, role): if not index.isValid(): return None if role not in [ Qt.DisplayRole, Qt.CheckStateRole, Qt.DecorationRole, Qt.UserRole ]: return None item = index.internalPointer() return item.data(index.column(), role) def flags(self, index): if not index.isValid(): item = self.rootItem else: item = index.internalPointer() return item.flags() def headerData(self, section, orientation, role): if orientation == Qt.Horizontal and role == Qt.DisplayRole: return self.rootItem.data(section, Qt.DisplayRole) return None def index(self, row, column, parent): if not self.hasIndex(row, column, parent): return QModelIndex() if not parent.isValid(): parentItem = self.rootItem else: parentItem = parent.internalPointer() childItem = parentItem.child(row) if childItem: return self.createIndex(row, column, childItem) else: return QModelIndex() def parent(self, index): if not index.isValid(): return QModelIndex() childItem = index.internalPointer() parentItem = childItem.parent() if parentItem == self.rootItem: return QModelIndex() return self.createIndex(parentItem.parent().indexOfChild(parentItem), index.column(), parentItem) def rowCount(self, parent): if not parent.isValid(): parentItem = self.rootItem else: parentItem = parent.internalPointer() return parentItem.childCount() def sort(self, column, order=Qt.AscendingOrder): self.layoutAboutToBeChanged.emit() if column == self.COLUMN_VISIBILITY: role = Qt.CheckStateRole else: role = Qt.DisplayRole if order == Qt.AscendingOrder: compareFunc = lambda a, b: True if cmp(a, b) < 0 else False else: compareFunc = lambda a, b: True if cmp(a, b) > 0 else False for groupIndexI in range(0, self.rootItem.childCount()): for groupIndexJ in range(0, groupIndexI): groupItemI = self.rootItem.child(groupIndexI) groupItemJ = self.rootItem.child(groupIndexJ) if compareFunc(groupItemI.data(column, role), groupItemJ.data(column, role)): self.rootItem.insertChild( groupIndexJ, self.rootItem.takeChild(groupIndexI)) break self.layoutChanged.emit() def checkAll(self): for row in range(0, self.rootItem.childCount()): groupItem = self.rootItem.child(row) groupIndex = self.createIndex(row, self.COLUMN_VISIBILITY, groupItem) self.setData(groupIndex, Qt.Checked, Qt.CheckStateRole) def uncheckAll(self): for row in range(0, self.rootItem.childCount()): groupItem = self.rootItem.child(row) groupIndex = self.createIndex(row, self.COLUMN_VISIBILITY, groupItem) self.setData(groupIndex, Qt.Unchecked, Qt.CheckStateRole) def saveSettings(self): hideDSidList = [] for groupIndex in range(0, self.rootItem.childCount()): groupItem = self.rootItem.child(groupIndex) for dsIndex in range(0, groupItem.childCount()): dsItem = groupItem.child(dsIndex) if dsItem.checkState(self.COLUMN_VISIBILITY) == Qt.Unchecked: hideDSidList.append( dsItem.data(self.COLUMN_GROUP_DS, Qt.UserRole).id) PluginSettings.set_hide_ds_id_list(hideDSidList) def isGroup(self, index): childItem = index.internalPointer() parentItem = childItem.parent() if parentItem == self.rootItem: return True return False
class GetScriptsAndModelsDialog(BASE, WIDGET): HELP_TEXT = QCoreApplication.translate('GetScriptsAndModelsDialog', '<h3> Processing resources manager </h3>' '<p>Check/uncheck algorithms in the tree to select the ones that you ' 'want to install or remove</p>' '<p>Algorithms are divided in 3 groups:</p>' '<ul><li><b>Installed:</b> Algorithms already in your system, with ' 'the latest version available</li>' '<li><b>Updatable:</b> Algorithms already in your system, but with ' 'a newer version available in the server</li>' '<li><b>Not installed:</b> Algorithms not installed in your ' 'system</li></ul>') MODELS = 0 SCRIPTS = 1 RSCRIPTS = 2 tr_disambiguation = {0: 'GetModelsAction', 1: 'GetScriptsAction', 2: 'GetRScriptsAction'} def __init__(self, resourceType): super(GetScriptsAndModelsDialog, self).__init__(iface.mainWindow()) self.setupUi(self) self.manager = QgsNetworkAccessManager.instance() self.resourceType = resourceType if self.resourceType == self.MODELS: self.folder = ModelerUtils.modelsFolder() self.urlBase = 'https://raw.githubusercontent.com/qgis/QGIS-Processing/master/models/' self.icon = QIcon(os.path.join(pluginPath, 'images', 'model.png')) elif self.resourceType == self.SCRIPTS: self.folder = ScriptUtils.scriptsFolder() self.urlBase = 'https://raw.githubusercontent.com/qgis/QGIS-Processing/master/scripts/' self.icon = QIcon(os.path.join(pluginPath, 'images', 'script.png')) else: self.folder = RUtils.RScriptsFolder() self.urlBase = 'https://raw.githubusercontent.com/qgis/QGIS-Processing/master/rscripts/' self.icon = QIcon(os.path.join(pluginPath, 'images', 'r.png')) self.lastSelectedItem = None self.updateToolbox = False self.populateTree() self.buttonBox.accepted.connect(self.okPressed) self.buttonBox.rejected.connect(self.cancelPressed) self.tree.currentItemChanged.connect(self.currentItemChanged) def popupError(self, error=None, url=None): """Popups an Error message bar for network errors.""" disambiguation = self.tr_disambiguation[self.resourceType] widget = iface.messageBar().createMessage(self.tr('Connection problem', disambiguation), self.tr('Could not connect to scripts/models repository', disambiguation)) if error and url: QgsMessageLog.logMessage(self.tr(u"Network error code: {} on URL: {}").format(error, url), self.tr(u"Processing"), QgsMessageLog.CRITICAL) button = QPushButton(QCoreApplication.translate("Python", "View message log"), pressed=show_message_log) widget.layout().addWidget(button) iface.messageBar().pushWidget(widget, level=QgsMessageBar.CRITICAL, duration=5) def grabHTTP(self, url, loadFunction, arguments=None): """Grab distant content via QGIS internal classes and QtNetwork.""" QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) request = QUrl(url) reply = self.manager.get(QNetworkRequest(request)) if arguments: reply.finished.connect(partial(loadFunction, reply, arguments)) else: reply.finished.connect(partial(loadFunction, reply)) while not reply.isFinished(): QCoreApplication.processEvents() def populateTree(self): self.uptodateItem = QTreeWidgetItem() self.uptodateItem.setText(0, self.tr('Installed')) self.toupdateItem = QTreeWidgetItem() self.toupdateItem.setText(0, self.tr('Updatable')) self.notinstalledItem = QTreeWidgetItem() self.notinstalledItem.setText(0, self.tr('Not installed')) self.toupdateItem.setIcon(0, self.icon) self.uptodateItem.setIcon(0, self.icon) self.notinstalledItem.setIcon(0, self.icon) self.grabHTTP(self.urlBase + 'list.txt', self.treeLoaded) def treeLoaded(self, reply): """ update the tree of scripts/models whenever HTTP request is finished """ QApplication.restoreOverrideCursor() if reply.error() != QNetworkReply.NoError: self.popupError(reply.error(), reply.request().url().toString()) else: resources = unicode(reply.readAll()).splitlines() resources = [r.split(',') for r in resources] self.resources = {f: (v, n) for f, v, n in resources} for filename, version, name in sorted(resources, key=lambda kv: kv[2].lower()): treeBranch = self.getTreeBranchForState(filename, float(version)) item = TreeItem(filename, name, self.icon) treeBranch.addChild(item) if treeBranch != self.notinstalledItem: item.setCheckState(0, Qt.Checked) reply.deleteLater() self.tree.addTopLevelItem(self.toupdateItem) self.tree.addTopLevelItem(self.notinstalledItem) self.tree.addTopLevelItem(self.uptodateItem) self.webView.setHtml(self.HELP_TEXT) def setHelp(self, reply, item): """Change the webview HTML content""" QApplication.restoreOverrideCursor() if reply.error() != QNetworkReply.NoError: html = self.tr('<h2>No detailed description available for this script</h2>') else: content = unicode(reply.readAll()) descriptions = json.loads(content) html = '<h2>%s</h2>' % item.name html += self.tr('<p><b>Description:</b> %s</p>') % getDescription(ALG_DESC, descriptions) html += self.tr('<p><b>Created by:</b> %s') % getDescription(ALG_CREATOR, descriptions) html += self.tr('<p><b>Version:</b> %s') % getDescription(ALG_VERSION, descriptions) reply.deleteLater() self.webView.setHtml(html) def currentItemChanged(self, item, prev): if isinstance(item, TreeItem): url = self.urlBase + item.filename.replace(' ', '%20') + '.help' self.grabHTTP(url, self.setHelp, item) else: self.webView.setHtml(self.HELP_TEXT) def getTreeBranchForState(self, filename, version): if not os.path.exists(os.path.join(self.folder, filename)): return self.notinstalledItem else: helpFile = os.path.join(self.folder, filename + '.help') try: with open(helpFile) as f: helpContent = json.load(f) currentVersion = float(helpContent[Help2Html.ALG_VERSION]) except Exception: currentVersion = 0 if version > currentVersion: return self.toupdateItem else: return self.uptodateItem def cancelPressed(self): super(GetScriptsAndModelsDialog, self).reject() def storeFile(self, reply, filename): """store a script/model that has been downloaded""" QApplication.restoreOverrideCursor() if reply.error() != QNetworkReply.NoError: if os.path.splitext(filename)[1].lower() == '.help': content = '{"ALG_VERSION" : %s}' % self.resources[filename[:-5]][0] else: self.popupError(reply.error(), reply.request().url().toString()) content = None else: content = reply.readAll() reply.deleteLater() if content: path = os.path.join(self.folder, filename) with open(path, 'w') as f: f.write(content) self.progressBar.setValue(self.progressBar.value() + 1) def okPressed(self): toDownload = [] for i in xrange(self.toupdateItem.childCount()): item = self.toupdateItem.child(i) if item.checkState(0) == Qt.Checked: toDownload.append(item.filename) for i in xrange(self.notinstalledItem.childCount()): item = self.notinstalledItem.child(i) if item.checkState(0) == Qt.Checked: toDownload.append(item.filename) if toDownload: self.progressBar.setMaximum(len(toDownload) * 2) for i, filename in enumerate(toDownload): QCoreApplication.processEvents() url = self.urlBase + filename.replace(' ', '%20') self.grabHTTP(url, self.storeFile, filename) url += '.help' self.grabHTTP(url, self.storeFile, filename + '.help') toDelete = [] for i in xrange(self.uptodateItem.childCount()): item = self.uptodateItem.child(i) if item.checkState(0) == Qt.Unchecked: toDelete.append(item.filename) # Remove py and help files if they exist for filename in toDelete: for pathname in (filename, filename + u".help"): path = os.path.join(self.folder, pathname) if os.path.exists(path): os.remove(path) self.updateToolbox = len(toDownload) + len(toDelete) > 0 super(GetScriptsAndModelsDialog, self).accept()
def addOverlaysToTreeWidget(self, overlayDict, forbiddenOverlays, preSelectedOverlays, singleOverlaySelection): self.singleOverlaySelection = singleOverlaySelection testItem = QTreeWidgetItem("a") for keys in overlayDict.keys(): if overlayDict[keys] in forbiddenOverlays: continue else: boolStat = False split = keys.split("/") for i in range(len(split)): if len(split) == 1: newItemsChild = OverlayTreeWidgetItem(overlayDict[keys], keys) self.addTopLevelItem(newItemsChild) boolStat = False if overlayDict[keys] in preSelectedOverlays: newItemsChild.setCheckState(0, Qt.Checked) else: newItemsChild.setCheckState(0, Qt.Unchecked) elif i+1 == len(split) and len(split) > 1: newItemsChild = OverlayTreeWidgetItem(overlayDict[keys], keys) testItem.addChild(newItemsChild) if overlayDict[keys] in preSelectedOverlays: newItemsChild.setCheckState(0, Qt.Checked) else: newItemsChild.setCheckState(0, Qt.Unchecked) elif self.topLevelItemCount() == 0 and i+1 < len(split): newItem = QTreeWidgetItem([split[i]]) self.addTopLevelItem(newItem) testItem = newItem boolStat = True elif self.topLevelItemCount() != 0 and i+1 < len(split): if boolStat == False: for n in range(self.topLevelItemCount()): if self.topLevelItem(n).text(0) == split[i]: testItem = self.topLevelItem(n) boolStat = True break elif n+1 == self.topLevelItemCount(): newItem = QTreeWidgetItem([split[i]]) self.addTopLevelItem(newItem) testItem = newItem boolStat = True elif testItem.childCount() == 0: newItem = QTreeWidgetItem([split[i]]) testItem.addChild(newItem) testItem = newItem boolStat = True else: for x in range(testItem.childCount()): if testItem.child(x).text(0) == split[i]: testItem = testItem.child(x) boolStat = True break elif x+1 == testItem.childCount(): newItem = QTreeWidgetItem([split[i]]) testItem.addChild(newItem) testItem = newItem boolStat = True
class DeviceDialog(QDialog, Ui_DeviceDialog): """ Function and Event handling class for the Ui_DeviceDialog. """ qtcb_enumerate = pyqtSignal(str, str, 'char', type((0, )), type((0, )), int, int) qtcb_connected = pyqtSignal(int) def __init__(self, parent): QDialog.__init__(self, parent, get_modeless_dialog_flags()) self._logger_window = parent self.qtcb_enumerate.connect(self.cb_enumerate) self.qtcb_connected.connect(self.cb_connected) self.host = None self.port = None self.secret = None self.ipcon = IPConnection() self.ipcon.register_callback(IPConnection.CALLBACK_CONNECTED, self.qtcb_connected.emit) self.ipcon.register_callback(IPConnection.CALLBACK_ENUMERATE, self.qtcb_enumerate.emit) self.setupUi(self) self.btn_add_device.clicked.connect(self.btn_add_device_clicked) self.btn_refresh.clicked.connect(self.btn_refresh_clicked) self.btn_close.clicked.connect(self.btn_close_clicked) self.tree_widget.itemActivated.connect(self.add_item) self.connected_uids = [] self.available_item = QTreeWidgetItem(['No devices available']) self.supported_item = QTreeWidgetItem(['Supported devices']) self.tree_widget.addTopLevelItem(self.available_item) self.tree_widget.addTopLevelItem(self.supported_item) for device_name in device_specs: self.supported_item.addChild(QTreeWidgetItem([device_name])) self.supported_item.sortChildren(0, Qt.AscendingOrder) self.supported_item.setExpanded(True) def cb_connected(self, connect_reason): self.tree_widget.clearSelection() self.available_item.takeChildren() self.available_item.setExpanded(True) self.available_item.setText( 0, 'No devices available at {0}:{1}'.format(self.host, self.port)) self.connected_uids = [] if self.secret != None: self.ipcon.set_auto_reconnect( False) # don't auto-reconnect on authentication error try: self.ipcon.authenticate(self.secret) except: try: self.ipcon.disconnect() except: pass if connect_reason == IPConnection.CONNECT_REASON_AUTO_RECONNECT: extra = ' after auto-reconnect' else: extra = '' self.available_item.setText(0, 'Could not authenticate' + extra) return self.ipcon.set_auto_reconnect(True) try: self.ipcon.enumerate() except: pass def cb_enumerate(self, uid, connected_uid, position, hardware_version, firmware_version, device_identifier, enumeration_type): if enumeration_type in [IPConnection.ENUMERATION_TYPE_AVAILABLE, IPConnection.ENUMERATION_TYPE_CONNECTED] and \ uid not in self.connected_uids: try: display_name = device_factory.get_device_display_name( device_identifier) except KeyError: return # unknown device identifier if display_name in device_specs: self.connected_uids.append(uid) self.available_item.addChild( QTreeWidgetItem(['{0} [{1}]'.format(display_name, uid)])) self.available_item.setText( 0, 'Devices available at {0}:{1}'.format( self.host, self.port)) self.available_item.sortChildren(0, Qt.AscendingOrder) else: if uid in self.connected_uids: self.connected_uids.remove(uid) for i in range(self.available_item.childCount()): child = self.available_item.child(i) if '[{0}]'.format(uid) in child.text(0): self.available_item.takeChild(i) break if self.available_item.childCount() == 0: self.available_item.setText( 0, 'No devices available at {0}:{1}'.format( self.host, self.port)) def btn_add_device_clicked(self): for item in self.tree_widget.selectedItems(): if item == self.available_item or item == self.supported_item: continue self._logger_window.add_device_to_tree( self.create_device_config(item.text(0))) def btn_refresh_clicked(self): try: self.ipcon.disconnect() except: pass self.tree_widget.clearSelection() self.available_item.takeChildren() self.available_item.setExpanded(True) self.connected_uids = [] self.host = self._logger_window.combo_host.currentText() self.port = self._logger_window.spin_port.value() if self._logger_window.check_authentication.isChecked(): try: self.secret = self._logger_window.edit_secret.text().encode( 'ascii') except: self.secret = None else: self.secret = None try: self.ipcon.connect(self.host, self.port) self.available_item.setText( 0, 'No devices available at {0}:{1}'.format(self.host, self.port)) except: self.available_item.setText( 0, 'Could not connect to {0}:{1}'.format(self.host, self.port)) def btn_close_clicked(self): self.close() def add_item(self, item): if item == self.available_item or item == self.supported_item: return self._logger_window.add_device_to_tree( self.create_device_config(item.text(0))) def create_device_config(self, item_text): name, uid = Utilities.parse_device_name(item_text) # FIXME device_spec = device_specs[name] if uid == None: # FIXME uid = '' device = { 'host': 'default', 'name': name, 'uid': uid, 'values': {}, 'options': {} } for value_spec in device_spec['values']: device['values'][value_spec['name']] = {'interval': 0} if value_spec['subvalues'] != None: device['values'][value_spec['name']]['subvalues'] = {} for subvalue_name in value_spec['subvalues']: device['values'][ value_spec['name']]['subvalues'][subvalue_name] = True if device_spec['options'] != None: for option_spec in device_spec['options']: device['options'][option_spec['name']] = { 'value': option_spec['default'] } return device
class GetScriptsAndModelsDialog(BASE, WIDGET): HELP_TEXT = QCoreApplication.translate( 'GetScriptsAndModelsDialog', '<h3> Processing resources manager </h3>' '<p>Check/uncheck algorithms in the tree to select the ones that you ' 'want to install or remove</p>' '<p>Algorithms are divided in 3 groups:</p>' '<ul><li><b>Installed:</b> Algorithms already in your system, with ' 'the latest version available</li>' '<li><b>Updatable:</b> Algorithms already in your system, but with ' 'a newer version available in the server</li>' '<li><b>Not installed:</b> Algorithms not installed in your ' 'system</li></ul>') MODELS = 0 SCRIPTS = 1 RSCRIPTS = 2 tr_disambiguation = { 0: 'GetModelsAction', 1: 'GetScriptsAction', 2: 'GetRScriptsAction' } def __init__(self, resourceType): super(GetScriptsAndModelsDialog, self).__init__(iface.mainWindow()) self.setupUi(self) self.manager = QgsNetworkAccessManager.instance() self.resourceType = resourceType if self.resourceType == self.MODELS: self.folder = ModelerUtils.modelsFolder() self.urlBase = 'https://raw.githubusercontent.com/qgis/QGIS-Processing/master/models/' self.icon = QIcon(os.path.join(pluginPath, 'images', 'model.png')) elif self.resourceType == self.SCRIPTS: self.folder = ScriptUtils.scriptsFolder() self.urlBase = 'https://raw.githubusercontent.com/qgis/QGIS-Processing/master/scripts/' self.icon = QIcon(os.path.join(pluginPath, 'images', 'script.png')) else: self.folder = RUtils.RScriptsFolder() self.urlBase = 'https://raw.githubusercontent.com/qgis/QGIS-Processing/master/rscripts/' self.icon = QIcon(os.path.join(pluginPath, 'images', 'r.png')) self.lastSelectedItem = None self.updateToolbox = False self.populateTree() self.buttonBox.accepted.connect(self.okPressed) self.buttonBox.rejected.connect(self.cancelPressed) self.tree.currentItemChanged.connect(self.currentItemChanged) def popupError(self, error=None, url=None): """Popups an Error message bar for network errors.""" disambiguation = self.tr_disambiguation[self.resourceType] widget = iface.messageBar().createMessage( self.tr('Connection problem', disambiguation), self.tr('Could not connect to scripts/models repository', disambiguation)) if error and url: QgsMessageLog.logMessage( self.tr(u"Network error code: {} on URL: {}").format( error, url), self.tr(u"Processing"), QgsMessageLog.CRITICAL) button = QPushButton(QCoreApplication.translate( "Python", "View message log"), pressed=show_message_log) widget.layout().addWidget(button) iface.messageBar().pushWidget(widget, level=QgsMessageBar.CRITICAL, duration=5) def grabHTTP(self, url, loadFunction, arguments=None): """Grab distant content via QGIS internal classes and QtNetwork.""" QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) request = QUrl(url) reply = self.manager.get(QNetworkRequest(request)) if arguments: reply.finished.connect(partial(loadFunction, reply, arguments)) else: reply.finished.connect(partial(loadFunction, reply)) while not reply.isFinished(): QCoreApplication.processEvents() def populateTree(self): self.uptodateItem = QTreeWidgetItem() self.uptodateItem.setText(0, self.tr('Installed')) self.toupdateItem = QTreeWidgetItem() self.toupdateItem.setText(0, self.tr('Updatable')) self.notinstalledItem = QTreeWidgetItem() self.notinstalledItem.setText(0, self.tr('Not installed')) self.toupdateItem.setIcon(0, self.icon) self.uptodateItem.setIcon(0, self.icon) self.notinstalledItem.setIcon(0, self.icon) self.grabHTTP(self.urlBase + 'list.txt', self.treeLoaded) def treeLoaded(self, reply): """ update the tree of scripts/models whenever HTTP request is finished """ QApplication.restoreOverrideCursor() if reply.error() != QNetworkReply.NoError: self.popupError(reply.error(), reply.request().url().toString()) else: resources = unicode(reply.readAll()).splitlines() resources = [r.split(',') for r in resources] self.resources = {f: (v, n) for f, v, n in resources} for filename, version, name in sorted( resources, key=lambda kv: kv[2].lower()): treeBranch = self.getTreeBranchForState( filename, float(version)) item = TreeItem(filename, name, self.icon) treeBranch.addChild(item) if treeBranch != self.notinstalledItem: item.setCheckState(0, Qt.Checked) reply.deleteLater() self.tree.addTopLevelItem(self.toupdateItem) self.tree.addTopLevelItem(self.notinstalledItem) self.tree.addTopLevelItem(self.uptodateItem) self.webView.setHtml(self.HELP_TEXT) def setHelp(self, reply, item): """Change the webview HTML content""" QApplication.restoreOverrideCursor() if reply.error() != QNetworkReply.NoError: html = self.tr( '<h2>No detailed description available for this script</h2>') else: content = unicode(reply.readAll()) descriptions = json.loads(content) html = '<h2>%s</h2>' % item.name html += self.tr('<p><b>Description:</b> %s</p>') % getDescription( ALG_DESC, descriptions) html += self.tr('<p><b>Created by:</b> %s') % getDescription( ALG_CREATOR, descriptions) html += self.tr('<p><b>Version:</b> %s') % getDescription( ALG_VERSION, descriptions) reply.deleteLater() self.webView.setHtml(html) def currentItemChanged(self, item, prev): if isinstance(item, TreeItem): url = self.urlBase + item.filename.replace(' ', '%20') + '.help' self.grabHTTP(url, self.setHelp, item) else: self.webView.setHtml(self.HELP_TEXT) def getTreeBranchForState(self, filename, version): if not os.path.exists(os.path.join(self.folder, filename)): return self.notinstalledItem else: helpFile = os.path.join(self.folder, filename + '.help') try: with open(helpFile) as f: helpContent = json.load(f) currentVersion = float(helpContent[Help2Html.ALG_VERSION]) except Exception: currentVersion = 0 if version > currentVersion: return self.toupdateItem else: return self.uptodateItem def cancelPressed(self): super(GetScriptsAndModelsDialog, self).reject() def storeFile(self, reply, filename): """store a script/model that has been downloaded""" QApplication.restoreOverrideCursor() if reply.error() != QNetworkReply.NoError: if os.path.splitext(filename)[1].lower() == '.help': content = '{"ALG_VERSION" : %s}' % self.resources[ filename[:-5]][0] else: self.popupError(reply.error(), reply.request().url().toString()) content = None else: content = reply.readAll() reply.deleteLater() if content: path = os.path.join(self.folder, filename) with open(path, 'w') as f: f.write(content) self.progressBar.setValue(self.progressBar.value() + 1) def okPressed(self): toDownload = [] for i in xrange(self.toupdateItem.childCount()): item = self.toupdateItem.child(i) if item.checkState(0) == Qt.Checked: toDownload.append(item.filename) for i in xrange(self.notinstalledItem.childCount()): item = self.notinstalledItem.child(i) if item.checkState(0) == Qt.Checked: toDownload.append(item.filename) if toDownload: self.progressBar.setMaximum(len(toDownload) * 2) for i, filename in enumerate(toDownload): QCoreApplication.processEvents() url = self.urlBase + filename.replace(' ', '%20') self.grabHTTP(url, self.storeFile, filename) url += '.help' self.grabHTTP(url, self.storeFile, filename + '.help') toDelete = [] for i in xrange(self.uptodateItem.childCount()): item = self.uptodateItem.child(i) if item.checkState(0) == Qt.Unchecked: toDelete.append(item.filename) # Remove py and help files if they exist for filename in toDelete: for pathname in (filename, filename + u".help"): path = os.path.join(self.folder, pathname) if os.path.exists(path): os.remove(path) self.updateToolbox = len(toDownload) + len(toDelete) > 0 super(GetScriptsAndModelsDialog, self).accept()
def __init__(self, dialog): super(Shortcuts, self).__init__(dialog) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) self.setLayout(layout) self.scheme = SchemeSelector(self) layout.addWidget(self.scheme) self.tree = QTreeWidget(self) self.tree.setHeaderLabels([_("Command"), _("Shortcut")]) self.tree.setRootIsDecorated(False) self.tree.setColumnCount(2) self.tree.setAllColumnsShowFocus(True) self.tree.setAnimated(True) layout.addWidget(self.tree) self.edit = QPushButton(icons.get("preferences-desktop-keyboard-shortcuts"), '') layout.addWidget(self.edit) # signals self.scheme.currentChanged.connect(self.slotSchemeChanged) self.scheme.changed.connect(self.changed) self.tree.currentItemChanged.connect(self.slotCurrentItemChanged) self.tree.itemDoubleClicked.connect(self.editCurrentItem) self.edit.clicked.connect(self.editCurrentItem) # make a dict of all actions with the actions as key and the names as # value, with the collection prepended (for loading/saving) win = dialog.parent() allactions = {} for collection in actioncollectionmanager.manager(win).actionCollections(): for name, action in collection.actions().items(): allactions[action] = (collection, name) # keep a list of actions not in the menu structure left = allactions.keys() def add_actions(menuitem, actions): """Add actions to a QTreeWidgetItem.""" for a in actions: if a.menu(): item = build_menu_item(a) if item.childCount(): menuitem.addChild(item) elif a in left: left.remove(a) menuitem.addChild(ShortcutItem(a, *allactions[a])) menuitem.setFlags(Qt.ItemIsEnabled) # disable selection def build_menu_item(action): """Return a QTreeWidgetItem with children for all the actions in the submenu.""" menuitem = QTreeWidgetItem() text = qutil.removeAccelelator(action.text()) menuitem.setText(0, _("Menu {name}").format(name=text)) add_actions(menuitem, action.menu().actions()) return menuitem # present the actions nicely ordered as in the menus for a in win.menuBar().actions(): menuitem = build_menu_item(a) if menuitem.childCount(): self.tree.addTopLevelItem(menuitem) # sort leftover actions left.sort(key=lambda i: i.text()) # show actions that are left, grouped by collection titlegroups = {} for a in left[:]: # copy collection, name = allactions[a] if collection.title(): titlegroups.setdefault(collection.title(), []).append(a) left.remove(a) for title in sorted(titlegroups): item = QTreeWidgetItem(["{0}:".format(title)]) for a in titlegroups[title]: item.addChild(ShortcutItem(a, *allactions[a])) self.tree.addTopLevelItem(item) item.setFlags(Qt.ItemIsEnabled) # disable selection # show other actions that were not in the menus item = QTreeWidgetItem([_("Other commands:")]) for a in left: if a.text() and not a.menu(): item.addChild(ShortcutItem(a, *allactions[a])) if item.childCount(): self.tree.addTopLevelItem(item) item.setFlags(Qt.ItemIsEnabled) # disable selection self.tree.expandAll() item = self.tree.topLevelItem(0).child(0) if _lastaction: # find the previously selected item for i in self.items(): if i.name == _lastaction: item = i break self.tree.setCurrentItem(item) self.tree.resizeColumnToContents(0)
class GetScriptsAndModelsDialog(BASE, WIDGET): HELP_TEXT = QCoreApplication.translate( 'GetScriptsAndModelsDialog', '<h3> Processing resources manager </h3>' '<p>Check/uncheck algorithms in the tree to select the ones that you ' 'want to install or remove</p>' '<p>Algorithms are divided in 3 groups:</p>' '<ul><li><b>Installed:</b> Algorithms already in your system, with ' 'the latest version available</li>' '<li><b>Updatable:</b> Algorithms already in your system, but with ' 'a newer version available in the server</li>' '<li><b>Not installed:</b> Algorithms not installed in your ' 'system</li></ul>') MODELS = 0 SCRIPTS = 1 RSCRIPTS = 2 def __init__(self, resourceType): super(GetScriptsAndModelsDialog, self).__init__(iface.mainWindow()) self.setupUi(self) self.resourceType = resourceType if self.resourceType == self.MODELS: self.folder = ModelerUtils.modelsFolder() self.urlBase = 'https://raw.githubusercontent.com/qgis/QGIS-Processing/master/models/' self.icon = QIcon(os.path.join(pluginPath, 'images', 'model.png')) elif self.resourceType == self.SCRIPTS: self.folder = ScriptUtils.scriptsFolder() self.urlBase = 'https://raw.githubusercontent.com/qgis/QGIS-Processing/master/scripts/' self.icon = QIcon(os.path.join(pluginPath, 'images', 'script.png')) else: self.folder = RUtils.RScriptsFolder() self.urlBase = 'https://raw.githubusercontent.com/qgis/QGIS-Processing/master/rscripts/' self.icon = QIcon(os.path.join(pluginPath, 'images', 'r.png')) self.lastSelectedItem = None self.updateToolbox = False self.populateTree() self.buttonBox.accepted.connect(self.okPressed) self.buttonBox.rejected.connect(self.cancelPressed) self.tree.currentItemChanged.connect(self.currentItemChanged) def populateTree(self): self.uptodateItem = QTreeWidgetItem() self.uptodateItem.setText(0, self.tr('Installed')) self.toupdateItem = QTreeWidgetItem() self.toupdateItem.setText(0, self.tr('Updatable')) self.notinstalledItem = QTreeWidgetItem() self.notinstalledItem.setText(0, self.tr('Not installed')) self.toupdateItem.setIcon(0, self.icon) self.uptodateItem.setIcon(0, self.icon) self.notinstalledItem.setIcon(0, self.icon) resources = readUrl(self.urlBase + 'list.txt').splitlines() resources = [r.split(',') for r in resources] self.resources = {f: (v, n) for f, v, n in resources} for filename, version, name in sorted(resources, key=lambda kv: kv[2].lower()): treeBranch = self.getTreeBranchForState(filename, float(version)) item = TreeItem(filename, name, self.icon) treeBranch.addChild(item) if treeBranch != self.notinstalledItem: item.setCheckState(0, Qt.Checked) self.tree.addTopLevelItem(self.toupdateItem) self.tree.addTopLevelItem(self.notinstalledItem) self.tree.addTopLevelItem(self.uptodateItem) self.webView.setHtml(self.HELP_TEXT) def currentItemChanged(self, item, prev): if isinstance(item, TreeItem): try: url = self.urlBase + item.filename.replace(' ', '%20') + '.help' helpContent = readUrl(url) descriptions = json.loads(helpContent) html = '<h2>%s</h2>' % item.name html += self.tr('<p><b>Description:</b> %s</p>' ) % getDescription(ALG_DESC, descriptions) html += self.tr('<p><b>Created by:</b> %s') % getDescription( ALG_CREATOR, descriptions) html += self.tr('<p><b>Version:</b> %s') % getDescription( ALG_VERSION, descriptions) except HTTPError as e: html = self.tr( '<h2>No detailed description available for this script</h2>' ) self.webView.setHtml(html) else: self.webView.setHtml(self.HELP_TEXT) def getTreeBranchForState(self, filename, version): if not os.path.exists(os.path.join(self.folder, filename)): return self.notinstalledItem else: helpFile = os.path.join(self.folder, filename + '.help') try: with open(helpFile) as f: helpContent = json.load(f) currentVersion = float(helpContent[Help2Html.ALG_VERSION]) except Exception: currentVersion = 0 if version > currentVersion: return self.toupdateItem else: return self.uptodateItem def cancelPressed(self): self.close() def okPressed(self): toDownload = [] for i in xrange(self.toupdateItem.childCount()): item = self.toupdateItem.child(i) if item.checkState(0) == Qt.Checked: toDownload.append(item.filename) for i in xrange(self.notinstalledItem.childCount()): item = self.notinstalledItem.child(i) if item.checkState(0) == Qt.Checked: toDownload.append(item.filename) if toDownload: self.progressBar.setMaximum(len(toDownload)) for i, filename in enumerate(toDownload): QCoreApplication.processEvents() url = self.urlBase + filename.replace(' ', '%20') try: code = readUrl(url) path = os.path.join(self.folder, filename) with open(path, 'w') as f: f.write(code) except HTTPError: QMessageBox.critical( iface.mainWindow(), self.tr('Connection problem'), self.tr('Could not download file: %s') % filename) return url += '.help' try: html = readUrl(url) except HTTPError: html = '{"ALG_VERSION" : %s}' % self.resources[filename][0] path = os.path.join(self.folder, filename + '.help') with open(path, 'w') as f: f.write(html) self.progressBar.setValue(i + 1) toDelete = [] for i in xrange(self.uptodateItem.childCount()): item = self.uptodateItem.child(i) if item.checkState(0) == Qt.Unchecked: toDelete.append(item.filename) for filename in toDelete: path = os.path.join(self.folder, filename) os.remove(path) self.updateToolbox = len(toDownload) + len(toDelete) > 0 self.close()