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 __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 )
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 tr_disambiguation = {0: 'GetModelsAction', 1: 'GetScriptsAction'} def __init__(self, resourceType): super(GetScriptsAndModelsDialog, self).__init__(iface.mainWindow()) self.setupUi(self) if hasattr(self.leFilter, 'setPlaceholderText'): self.leFilter.setPlaceholderText(self.tr('Search...')) self.manager = QgsNetworkAccessManager.instance() repoUrl = ProcessingConfig.getSetting( ProcessingConfig.MODELS_SCRIPTS_REPO) self.resourceType = resourceType if self.resourceType == self.MODELS: self.folder = ModelerUtils.modelsFolders()[0] self.urlBase = '{}/models/'.format(repoUrl) self.icon = QgsApplication.getThemeIcon("/processingModel.svg") elif self.resourceType == self.SCRIPTS: self.folder = ScriptUtils.scriptsFolders()[0] self.urlBase = '{}/scripts/'.format(repoUrl) self.icon = QgsApplication.getThemeIcon("/processingScript.svg") self.lastSelectedItem = None self.updateProvider = False self.data = None self.populateTree() self.buttonBox.accepted.connect(self.okPressed) self.buttonBox.rejected.connect(self.cancelPressed) self.tree.currentItemChanged.connect(self.currentItemChanged) self.leFilter.textChanged.connect(self.fillTree) 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(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.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 = bytes(reply.readAll()).decode('utf8').splitlines() resources = [r.split(',', 2) for r in resources] self.resources = {f: (v, n) for f, v, n in resources} reply.deleteLater() self.fillTree() def fillTree(self): self.tree.clear() 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) text = str(self.leFilter.text()) for i in sorted(list(self.resources.keys()), key=lambda kv: kv[2].lower()): filename = i version = self.resources[filename][0] name = self.resources[filename][1] treeBranch = self.getTreeBranchForState(filename, float(version)) if text == '' or text.lower() in filename.lower(): 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) if text != '': self.tree.expandAll() self.txtHelp.setHtml(self.HELP_TEXT) def setHelp(self, reply, item): """Change the HTML content""" QApplication.restoreOverrideCursor() if reply.error() != QNetworkReply.NoError: html = self.tr( '<h2>No detailed description available for this script</h2>') else: content = bytes(reply.readAll()).decode('utf8') try: descriptions = json.loads(content) except json.decoder.JSONDecodeError: html = self.tr( '<h2>JSON Decoding Error - could not load help</h2>') except Exception: html = self.tr( '<h2>Unspecified Error - could not load help</h2>') html = '<h2>%s</h2>' % item.name html += self.tr('<p><b>Description:</b> {0}</p>').format( getDescription(ALG_DESC, descriptions)) html += self.tr('<p><b>Created by:</b> {0}').format( getDescription(ALG_CREATOR, descriptions)) html += self.tr('<p><b>Version:</b> {0}').format( getDescription(ALG_VERSION, descriptions)) reply.deleteLater() self.txtHelp.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.txtHelp.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 = bytes(reply.readAll()).decode('utf8') 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 range(self.toupdateItem.childCount()): item = self.toupdateItem.child(i) if item.checkState(0) == Qt.Checked: toDownload.append(item.filename) for i in range(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 range(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.updateProvider = len(toDownload) + len(toDelete) > 0 super(GetScriptsAndModelsDialog, self).accept()
class MainDialog(QDialog, FORM_CLASS): """The main dialog of QGIS2Web plugin.""" items = {} 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) @pyqtSlot(bool) def showHideDevConsole(self, visible): self.devConsole.setVisible(visible) 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 Exception: 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 elif self.mapFormat.checkedButton() == self.mapbox: return MapboxWriter 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.interactive, writer.json, writer.cluster, writer.getFeatureInfo) = 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.items(): treeParam = self.appearanceParams.findItems( param, Qt.MatchExactly | Qt.MatchRecursive)[0] if currentWriter == OpenLayersWriter: if value == "OL3": treeParam.setDisabled(False) if treeParam.combo: treeParam.combo.setEnabled(True) else: treeParam.setDisabled(True) if treeParam.combo: treeParam.combo.setEnabled(False) else: if value == "OL3": treeParam.setDisabled(True) if treeParam.combo: treeParam.combo.setEnabled(False) else: treeParam.setDisabled(False) if treeParam.combo: treeParam.combo.setEnabled(True) for option, value in specificOptions.items(): 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): preview_file = self.createPreview() self.loadPreviewFile(preview_file) 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 and (layer.type() != QgsMapLayer.VectorLayer or layer.wkbType() != QgsWkbTypes.NoGeometry) and layer.customProperty("ol_layer_type") is None): try: # if layer.type() == QgsMapLayer.VectorLayer: # testDump = layer.renderer().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 Exception: QgsMessageLog.logMessage(traceback.format_exc(), "qgis2web", level=Qgis.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 range(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, interactive, json, cluster, getFeatureInfo) = self.getLayersAndGroups() for count, layer in enumerate(layers): if layer.type() == layer.VectorLayer: options = [] fields = layer.fields() for f in fields: fieldIndex = fields.indexFromName(f.name()) editorWidget = layer.editorWidgetSetup(fieldIndex).type() if editorWidget == 'Hidden': continue options.append(f.name()) for option in options: displayStr = 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 + "_" + str(count)) def populateAttrFilter(self): self.layer_filter_select.clear() (layers, groups, popup, visible, interactive, json, cluster, getFeatureInfo) = self.getLayersAndGroups() options = [] for count, layer in enumerate(layers): if layer.type() == layer.VectorLayer: fields = layer.fields() for f in fields: fieldIndex = fields.indexFromName(f.name()) editorWidget = layer.editorWidgetSetup(fieldIndex).type() if editorWidget == 'Hidden': continue if utils.boilType(f.typeName()) in [ "int", "str", "real", "date", "bool", "time", "datetime" ]: options.append([ f.name() + ": " + utils.boilType(f.typeName()), layer.name() ]) preCleanOptions = {} for entry in options: if entry[0] not in list(preCleanOptions.keys()): preCleanOptions[entry[0]] = ": " + entry[1] else: preCleanOptions[entry[0]] = "| ".join( [preCleanOptions[entry[0]], entry[1]]) options = [] for key, value in preCleanOptions.items(): options.append(key + value) cleanOptions = list(set(options)) for option in cleanOptions: self.layer_filter_select.insertItem(0, option) def configureExporter(self): self.exporter.configure() def populateConfigParams(self, dlg): """ Populates the dialog with option items and widgets """ self.items = defaultdict(dict) tree = dlg.appearanceParams 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.items(): if group != "Data export": item = QTreeWidgetItem() item.setText(0, group) for param, value in settings.items(): subitem = self.createOptionItem(tree_widget=tree, parent_item=item, parameter=param, default_value=value) item.addChild(subitem) self.items[group][param] = subitem self.appearanceParams.addTopLevelItem(item) item.sortChildren(0, Qt.AscendingOrder) self.appearanceParams.expandAll() self.appearanceParams.resizeColumnToContents(0) self.appearanceParams.resizeColumnToContents(1) self.layer_search_combo.removeItem(1) self.layer_filter_select.takeItem(1) # configure export params in separate tab exportTree = dlg.exportParams for group, settings in params.items(): if group == "Data export": item = QTreeWidgetItem() item.setText(0, group) for param, value in settings.items(): subitem = self.createOptionItem(tree_widget=exportTree, parent_item=item, parameter=param, default_value=value) item.addChild(subitem) self.items[group][param] = subitem self.exportParams.addTopLevelItem(item) item.sortChildren(0, Qt.AscendingOrder) self.exportParams.expandAll() self.exportParams.resizeColumnToContents(0) self.exportParams.resizeColumnToContents(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 if parameter == 'Attribute filter': self.layer_filter_select = subitem.list 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) def setStateToParams(self, params): """ Sets the dialog state to match the specified parameters """ for group, settings in self.items.items(): for param, item in settings.items(): value = params[group][param] item.setValue(value) 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)) self.mapbox.setChecked(isinstance(writer, MapboxWriter)) 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.items(): for param, item in settings.items(): if param in ('Widget Icon', 'Widget Background'): parameters[group][param] = item._value.color().name() else: parameters[group][param] = item.value() if param == "Layer search": parameters["Appearance"]["Search layer"] = ( self.layer_search_combo.itemData( self.layer_search_combo.currentIndex())) if param == "Attribute filter": parameters["Appearance"]["Attribute filter"] = ( self.layer_filter_select.selectedItems()) 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 = [] interactive = [] json = [] cluster = [] getFeatureInfo = [] for i in range(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) interactive.append(item.interactive) json.append(item.json) cluster.append(item.cluster) getFeatureInfo.append(item.getFeatureInfo) 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({}) if item.visible: visible.append(True) else: visible.append(False) if item.interactive: interactive.append(True) else: interactive.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) if hasattr(item, "getFeatureInfo") and item.getFeatureInfo: getFeatureInfo.append(True) else: getFeatureInfo.append(False) groups[group] = groupLayers[::-1] return (layers[::-1], groups, popup[::-1], visible[::-1], interactive[::-1], json[::-1], cluster[::-1], getFeatureInfo[::-1]) def reject(self): self.saveParameters() (layers, groups, popup, visible, interactive, json, cluster, getFeatureInfo) = self.getLayersAndGroups() try: for layer, pop, vis, int in zip(layers, popup, visible, interactive): attrDict = {} for attr in pop: attrDict['attr'] = pop[attr] layer.setCustomProperty("qgis2web/popup/" + attr, pop[attr]) layer.setCustomProperty("qgis2web/Visible", vis) layer.setCustomProperty("qgis2web/Interactive", int) except Exception: pass 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()) QDialog.close(self) def closeEvent(self, event): try: if self.devConsole or self.devConsole.isVisible() and self.preview: del self.devConsole del self.preview self.reject() event.accept() except Exception: pass
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() repoUrl = ProcessingConfig.getSetting(ProcessingConfig.MODELS_SCRIPTS_REPO) self.resourceType = resourceType if self.resourceType == self.MODELS: self.folder = ModelerUtils.modelsFolders()[0] self.urlBase = '{}/models/'.format(repoUrl) self.icon = QIcon(os.path.join(pluginPath, 'images', 'model.png')) elif self.resourceType == self.SCRIPTS: self.folder = ScriptUtils.scriptsFolders()[0] self.urlBase = '{}/scripts/'.format(repoUrl) self.icon = QIcon(os.path.join(pluginPath, 'images', 'script.png')) else: self.folder = RUtils.RScriptsFolders()[0] self.urlBase = '{}/rscripts/'.format(repoUrl) self.icon = QIcon(os.path.join(pluginPath, 'images', 'r.svg')) self.lastSelectedItem = None self.updateProvider = 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)) 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.txtHelp.setHtml(self.HELP_TEXT) def setHelp(self, reply, item): """Change the 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.txtHelp.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.txtHelp.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.updateProvider = len(toDownload) + len(toDelete) > 0 super(GetScriptsAndModelsDialog, self).accept()
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 list(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 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 compareFunc = lambda a, b: a < b # need to check else: # compareFunc = lambda a, b: True if cmp(a, b) > 0 else False compareFunc = lambda a, b: a >= b # need to check 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
def __init__(self): super(TestSelector, self).__init__() self.setupUi(self) self.tests = None self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().insertWidget(1, self.bar) allTests = defaultdict(list) for test in tests.tests: allTests[test.group].append(test) for group, groupTests in iteritems(allTests): groupItem = QTreeWidgetItem() groupItem.setText(0, group) groupItem.setFlags(groupItem.flags() | Qt.ItemIsTristate) unitItem = QTreeWidgetItem() unitItem.setText(0, "Fully automated tests") unitItem.setFlags(unitItem.flags() | Qt.ItemIsTristate) manualItem = QTreeWidgetItem() manualItem.setText(0, "Manual and semi-automated tests") manualItem.setFlags(manualItem.flags() | Qt.ItemIsTristate) unitTestsByCategories = defaultdict(list) manualTestsByCategories = defaultdict(list) for test in groupTests: if isinstance(test, UnitTestWrapper): unitTestsByCategories[test.category].append(test) else: manualTestsByCategories[test.category].append(test) for testsList, parentItem in [(unitTestsByCategories, unitItem), (manualTestsByCategories, manualItem) ]: for cat, catTests in iteritems(testsList): categoryItem = QTreeWidgetItem() categoryItem.setText(0, cat) categoryItem.setFlags(manualItem.flags() | Qt.ItemIsTristate) for test in catTests: testItem = QTreeWidgetItem() testItem.setFlags(testItem.flags() | Qt.ItemIsUserCheckable) testItem.setCheckState(0, Qt.Unchecked) testItem.test = test testItem.setText(0, test.name) categoryItem.addChild(testItem) parentItem.addChild(categoryItem) if manualItem.childCount(): groupItem.addChild(manualItem) if unitItem.childCount(): groupItem.addChild(unitItem) self.testsTree.addTopLevelItem(groupItem) groupItem.setExpanded(True) self.buttonBox.button( QDialogButtonBox.Ok).setText("Run selected tests") self.buttonBox.accepted.connect(self.okPressed) self.buttonBox.rejected.connect(self.cancelPressed) self.selectAllLabel.linkActivated.connect( lambda: self.checkTests(lambda t: Qt.Checked)) self.unselectAllLabel.linkActivated.connect( lambda: self.checkTests(lambda t: Qt.Unchecked)) def _onlyManual(t): if isinstance(t, UnitTestWrapper): return Qt.Unchecked else: return Qt.Checked self.onlyManualLabel.linkActivated.connect( lambda: self.checkTests(_onlyManual)) def _onlyUnit(t): if isinstance(t, UnitTestWrapper): return Qt.Checked else: return Qt.Unchecked self.onlyUnitLabel.linkActivated.connect( lambda: self.checkTests(_onlyUnit)) self.exportButton.clicked.connect(self.export)
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 compareFunc = lambda a, b: a < b # need to check else: # compareFunc = lambda a, b: True if cmp(a, b) > 0 else False compareFunc = lambda a, b: a >= b # need to check 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
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 list(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()
def __init__(self): super(TestSelector, self).__init__() self.setupUi(self) self.tests = None self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().insertWidget(1, self.bar) allTests = defaultdict(list) for test in tests.tests: allTests[test.group].append(test) for group, groupTests in iteritems(allTests): groupItem = QTreeWidgetItem() groupItem.setText(0, group) groupItem.setFlags(groupItem.flags() | Qt.ItemIsTristate) unitItem = QTreeWidgetItem() unitItem.setText(0, "Fully automated tests") unitItem.setFlags(unitItem.flags() | Qt.ItemIsTristate) manualItem = QTreeWidgetItem() manualItem.setText(0, "Manual and semi-automated tests") manualItem.setFlags(manualItem.flags() | Qt.ItemIsTristate) for test in groupTests: testItem = QTreeWidgetItem() testItem.setFlags(testItem.flags() | Qt.ItemIsUserCheckable) testItem.setCheckState(0, Qt.Unchecked) testItem.test = test testItem.setText(0, test.name) if isinstance(test, UnitTestWrapper): unitItem.addChild(testItem) else: manualItem.addChild(testItem) if manualItem.childCount(): groupItem.addChild(manualItem) if unitItem.childCount(): groupItem.addChild(unitItem) self.testsTree.addTopLevelItem(groupItem) groupItem.setExpanded(True) self.buttonBox.button(QDialogButtonBox.Ok).setText("Run selected tests") self.buttonBox.accepted.connect(self.okPressed) self.buttonBox.rejected.connect(self.cancelPressed) self.selectAllLabel.linkActivated.connect(lambda: self.checkTests(lambda t: Qt.Checked)) self.unselectAllLabel.linkActivated.connect(lambda: self.checkTests(lambda t: Qt.Unchecked)) def _onlyManual(t): if isinstance(t, UnitTestWrapper): return Qt.Unchecked else: return Qt.Checked self.onlyManualLabel.linkActivated.connect(lambda: self.checkTests(_onlyManual)) def _onlyUnit(t): if isinstance(t, UnitTestWrapper): return Qt.Checked else: return Qt.Unchecked self.onlyUnitLabel.linkActivated.connect(lambda: self.checkTests(_onlyUnit)) self.exportButton.clicked.connect(self.export)
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 list(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 list(qmlDict.keys()): if isinstance(qmlDict[attribute], dict): if widgetItem.currentText() in list(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: if isinstance(widgetItem, DsgCustomComboBox): value = widgetItem.currentText() 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 __init__(self): super(TestSelector, self).__init__() self.setupUi(self) self.tests = None self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().insertWidget(1, self.bar) allTests = defaultdict(list) for test in tests.tests: allTests[test.group].append(test) for group, groupTests in iteritems(allTests): groupItem = QTreeWidgetItem() groupItem.setText(0, group) groupItem.setFlags(groupItem.flags() | Qt.ItemIsTristate); unitItem = QTreeWidgetItem() unitItem.setText(0, "Fully automated tests") unitItem.setFlags(unitItem.flags() | Qt.ItemIsTristate); manualItem = QTreeWidgetItem() manualItem.setText(0, "Manual and semi-automated tests") manualItem.setFlags(manualItem.flags() | Qt.ItemIsTristate); unitTestsByCategories = defaultdict(list) manualTestsByCategories = defaultdict(list) for test in groupTests: if isinstance(test, UnitTestWrapper): unitTestsByCategories[test.category].append(test) else: manualTestsByCategories[test.category].append(test) for testsList, parentItem in [(unitTestsByCategories, unitItem), (manualTestsByCategories, manualItem)]: for cat, catTests in iteritems(testsList): categoryItem = QTreeWidgetItem() categoryItem.setText(0, cat) categoryItem.setFlags(manualItem.flags() | Qt.ItemIsTristate); for test in catTests: testItem = QTreeWidgetItem() testItem.setFlags(testItem.flags() | Qt.ItemIsUserCheckable); testItem.setCheckState(0, Qt.Unchecked); testItem.test = test testItem.setText(0, test.name) categoryItem.addChild(testItem) parentItem.addChild(categoryItem) if manualItem.childCount(): groupItem.addChild(manualItem) if unitItem.childCount(): groupItem.addChild(unitItem) self.testsTree.addTopLevelItem(groupItem) groupItem.setExpanded(True) self.buttonBox.button(QDialogButtonBox.Ok).setText("Run selected tests") self.buttonBox.accepted.connect(self.okPressed) self.buttonBox.rejected.connect(self.cancelPressed) self.selectAllLabel.linkActivated.connect(lambda: self.checkTests(lambda t: Qt.Checked)) self.unselectAllLabel.linkActivated.connect(lambda: self.checkTests(lambda t: Qt.Unchecked)) def _onlyManual(t): if isinstance(t, UnitTestWrapper): return Qt.Unchecked else: return Qt.Checked self.onlyManualLabel.linkActivated.connect(lambda: self.checkTests(_onlyManual)) def _onlyUnit(t): if isinstance(t, UnitTestWrapper): return Qt.Checked else: return Qt.Unchecked self.onlyUnitLabel.linkActivated.connect(lambda: self.checkTests(_onlyUnit)) filepath = os.path.expanduser("~/.testerplugin/failed.txt") if os.path.exists(filepath): with open(filepath) as f: failed = json.load(f) else: failed = [] def _onlyLastFailures(t): if t.group in failed and t.name in failed[t.group]: return Qt.Checked else: return Qt.Unchecked self.onlyLastFailuresLabel.linkActivated.connect(lambda: self.checkTests(_onlyLastFailures)) self.exportButton.clicked.connect(self.export)
def __init__(self): super(TestSelector, self).__init__() self.setupUi(self) self.tests = None self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().insertWidget(1, self.bar) allTests = defaultdict(list) for test in tests.tests: allTests[test.group].append(test) for group, groupTests in allTests.items(): groupItem = QTreeWidgetItem() groupItem.setText(0, group) groupItem.setFlags(groupItem.flags() | Qt.ItemIsTristate) unitItem = QTreeWidgetItem() unitItem.setText(0, 'Fully Automated Tests') unitItem.setFlags(unitItem.flags() | Qt.ItemIsTristate) manualItem = QTreeWidgetItem() manualItem.setText(0, 'Manual and Semi-Automated Tests') manualItem.setFlags(manualItem.flags() | Qt.ItemIsTristate) unitTestsByCategories = defaultdict(list) manualTestsByCategories = defaultdict(list) for test in groupTests: if isinstance(test, UnitTestWrapper): unitTestsByCategories[test.category].append(test) else: manualTestsByCategories[test.category].append(test) for testsList, parentItem in [(unitTestsByCategories, unitItem), (manualTestsByCategories, manualItem) ]: for cat, catTests in testsList.items(): categoryItem = QTreeWidgetItem() categoryItem.setText(0, cat) categoryItem.setFlags(manualItem.flags() | Qt.ItemIsTristate) for test in catTests: testItem = QTreeWidgetItem() testItem.setFlags(testItem.flags() | Qt.ItemIsUserCheckable) testItem.setCheckState(0, Qt.Unchecked) testItem.test = test testItem.setText(0, test.name) categoryItem.addChild(testItem) parentItem.addChild(categoryItem) if manualItem.childCount(): groupItem.addChild(manualItem) if unitItem.childCount(): groupItem.addChild(unitItem) self.testsTree.addTopLevelItem(groupItem) groupItem.setExpanded(True) self.testsTree.itemChanged.connect(self.toggleRunButton) self.buttonBox.button( QDialogButtonBox.Ok).setText('Run Selected Tests') self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False) self.buttonBox.accepted.connect(self.okPressed) self.buttonBox.rejected.connect(self.cancelPressed) self.selectAllLabel.linkActivated.connect( lambda: self.checkTests(lambda t: Qt.Checked)) self.unselectAllLabel.linkActivated.connect( lambda: self.checkTests(lambda t: Qt.Unchecked)) def _onlyManual(t): if isinstance(t, UnitTestWrapper): return Qt.Unchecked else: return Qt.Checked self.onlyManualLabel.linkActivated.connect( lambda: self.checkTests(_onlyManual)) def _onlyUnit(t): if isinstance(t, UnitTestWrapper): return Qt.Checked else: return Qt.Unchecked self.onlyUnitLabel.linkActivated.connect( lambda: self.checkTests(_onlyUnit)) filepath = os.path.expanduser('~/.testerplugin/failed.txt') if os.path.exists(filepath): with open(filepath) as f: failed = json.load(f) else: failed = [] def _onlyLastFailures(t): if t.group in failed and t.name in failed[t.group]: return Qt.Checked else: return Qt.Unchecked self.onlyLastFailuresLabel.linkActivated.connect( lambda: self.checkTests(_onlyLastFailures)) self.exportButton.clicked.connect(self.export)