def update_history_view(self): """Update the history view.""" historic_folder = query_historic() files = os.listdir(historic_folder) self.dialog.list_historic.clear() for file in files[::-1]: file_path = join(historic_folder, file) with open(file_path, encoding='utf8') as json_file: data = json.load(json_file, object_hook=as_enum) name = data['file_name'] item = QListWidgetItem(self.dialog.list_historic) self.dialog.list_historic.addItem(item) group = QFrame() group.setFrameStyle(QFrame.StyledPanel) group.setStyleSheet('QFrame { margin: 3px; }') group.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) hbox = QHBoxLayout() vbox = QVBoxLayout() label_name = QLabel(name) label_name.setStyleSheet('font-weight: bold;') label_name.setWordWrap(True) vbox.addWidget(label_name) for label in data['description']: if not label: label = tr('No description') real_label = QLabel(label) real_label.setWordWrap(True) vbox.addWidget(real_label) hbox.addItem(vbox) button_run = QPushButton() button_save = QPushButton() button_run.setIcon(QIcon(QgsApplication.iconPath("mActionStart.svg"))) button_save.setIcon(QIcon(QgsApplication.iconPath("mActionFileSave.svg"))) button_run.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) button_save.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) button_run.setToolTip(tr('Run the query')) button_save.setToolTip(tr('Save this query in a new preset')) hbox.addWidget(button_run) hbox.addWidget(button_save) group.setLayout(hbox) # Actions on click run = partial(self.run_saved_query, data) button_run.clicked.connect(run) save = partial(self.save_history_preset, data) button_save.clicked.connect(save) item.setSizeHint(group.minimumSizeHint()) self.dialog.list_historic.setItemWidget(item, group)
def __init__(self, layer): super().__init__() self.layer = layer # Is legend a png file? self.my_img = os.path.splitext(layer.source())[0] + '.legend.png' if not os.path.exists(self.my_img): # No, is it a jpg? self.my_img = os.path.splitext(layer.source())[0] + '.legend.jpg' if not os.path.exists(self.my_img): # No: is this raster using a common legend? pwd = os.getcwd() compath = os.path.split(layer.source())[0] os.chdir(compath) englob = glob.glob("*.legendcommon.*") if len(englob) > 0: # Yes self.my_img = os.path.join(compath, self.getMy_Img()) else: # No: abort os.chdir(pwd) return # os.chdir(pwd) im = Image.open(self.my_img) w, h = im.size self.setAutoFillBackground(False) self.my_pix = QPixmap(self.my_img) self.imgleg = QPushButton() self.imgleg.setIcon(QIcon(self.my_pix)) self.imgleg.setCheckable(False) self.imgleg.setFlat(True) if w >= h: self.imgleg.setIconSize(QSize(200, int(200 * h / w))) else: self.imgleg.setIconSize(QSize(int(200 * w / h), 200)) self.imgleg.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) layout = QHBoxLayout() spacer = QSpacerItem(1, 0, QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) layout.addWidget(self.imgleg) layout.addItem(spacer) self.setLayout(layout) if self.layer.type() == QgsMapLayer.RasterLayer: self.imgleg.released.connect(self.showLegend)
def setup_default_preset(self): """Setup the display of presets""" preset_folder = resources_path('map_preset') folders = os.listdir(preset_folder) for folder_name in folders: file_path = join(preset_folder, folder_name, folder_name + '.json') with open(file_path, encoding='utf8') as json_file: data = json.load(json_file, object_hook=as_enum) item = QListWidgetItem(self.dialog.list_default_mp) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) self.dialog.list_default_mp.addItem(item) widget = QFrame() widget.setFrameStyle(QFrame.StyledPanel) widget.setStyleSheet('QFrame { margin: 3px; };') widget.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) hbox = QHBoxLayout() vbox = QVBoxLayout() picture = QLabel() icon_path = resources_path('map_preset', folder_name, folder_name + '_icon.png') if not os.path.isfile(icon_path): icon_path = resources_path('icons', 'QuickOSM.svg') icon = QPixmap(icon_path) icon.scaled(QSize(150, 250), Qt.KeepAspectRatio) picture.setPixmap(icon) picture.setStyleSheet( 'max-height: 150px; max-width: 250px; margin-right: 50px;') hbox.addWidget(picture) title = QLabel(data['file_name']) title.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) title.setStyleSheet('font: bold 20px; margin-bottom: 25px;') vbox.addWidget(title) for label in data['description']: if not label: label = tr('No description') real_label = QLabel(label) real_label.setWordWrap(True) vbox.addWidget(real_label) hbox.addItem(vbox) widget.setLayout(hbox) item.setSizeHint(widget.minimumSizeHint()) self.dialog.list_default_mp.setItemWidget(item, widget)
def __init__(self, layer): super().__init__() self.layer = layer self.setAutoFillBackground(False) self.checkbox = QCheckBox(self.tr("Show Labels")) layout = QHBoxLayout() spacer = QSpacerItem(1, 0, QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) layout.addWidget(self.checkbox) layout.addItem(spacer) self.setLayout(layout) # init from layer if self.layer.type() == QgsMapLayer.VectorLayer: self.checkbox.toggled.connect(self.toggled) self.checkbox.setChecked(self.layer.labelsEnabled())
def buildPoleHeader(self): headerRow = QHBoxLayout() spacerItemA = QSpacerItem(60, 20, QSizePolicy.Fixed, QSizePolicy.Minimum) spacerItemE = QSpacerItem(60, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) headername = QLabel(self.tr('Stuetzenbezeichnung')) headername.setMinimumSize(QSize(180, 30)) headerDist = QLabel(self.tr('Hori.distanz')) headerDist.setMinimumSize(QSize(95, 30)) headerHeight = QLabel(self.tr('Hoehe')) headerHeight.setMinimumSize(QSize(85, 30)) headerRow.addItem(spacerItemA) headerRow.addWidget(headername) headerRow.addWidget(headerDist) headerRow.addWidget(headerHeight) headerRow.addItem(spacerItemE) self.outerLayout.addLayout(headerRow)
def draw(self, layout: QLayout, edit: bool = False): ''' draw parameter in given layout Parameters ---------- layout : QBoxLayout layout to append the drawn parameter to edit : bool, optional edit mode displaying the label and input of parameter if True, else label and (uneditable) value, by default False ''' if edit and not self.input: return self.row = QHBoxLayout() label = QLabel(self.label) spacer = QFrame() spacer_layout = QHBoxLayout() spacer_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding)) spacer.setLayout(spacer_layout) # dotted line in preview if not edit: spacer.setFrameShape(QFrame.StyledPanel) spacer.setStyleSheet('border-width: 1px; border-style: none; ' 'border-bottom-style: dotted;' 'border-color: grey;') if isinstance(layout, QGridLayout): n_rows = layout.rowCount() layout.addWidget(label, n_rows, 0) layout.addWidget(spacer, n_rows, 1) layout.addLayout(self.row, n_rows, 2) else: self.row.addWidget(label) self.row.addWidget(spacer) layout.addLayout(self.row) if edit: self.input.draw(self.row, unit=self.unit) else: self.row.addWidget(self._value_label) if self.unit: unit_label = QLabel(self.unit) self.row.addWidget(unit_label)
class ProgressDialog(QDialog): """ Progress dialog shows progress bar for algorithm. """ def __init__(self, iface): QDialog.__init__(self, iface.mainWindow()) self.workerThread = None self.state = False self.outputLoc = None self.resultStatus = None self.reRun = False self.savedProj = None # Build GUI Elements self.setWindowTitle("SEILAPLAN wird ausgeführt") self.resize(500, 100) self.container = QVBoxLayout() self.progressBar = QProgressBar(self) self.progressBar.setMinimumWidth(500) self.statusLabel = QLabel(self) self.hbox = QHBoxLayout() self.cancelButton = QDialogButtonBox() self.closeButton = QDialogButtonBox() self.resultLabel = ClickLabel(self) self.resultLabel.setMaximumWidth(500) self.resultLabel.setSizePolicy( QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding)) self.resultLabel.setWordWrap(True) self.rerunButton = QPushButton("Berechnungen wiederholen") self.rerunButton.setVisible(False) spacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.cancelButton.setStandardButtons(QDialogButtonBox.Cancel) self.cancelButton.clicked.connect(self.onAbort) self.closeButton.setStandardButtons(QDialogButtonBox.Close) self.closeButton.clicked.connect(self.onClose) self.hbox.addWidget(self.rerunButton) self.hbox.addItem(spacer) self.hbox.addWidget(self.cancelButton) self.hbox.setAlignment(self.cancelButton, Qt.AlignHCenter) self.hbox.addWidget(self.closeButton) self.hbox.setAlignment(self.closeButton, Qt.AlignHCenter) self.closeButton.hide() self.container.addWidget(self.progressBar) self.container.addWidget(self.statusLabel) self.container.addWidget(self.resultLabel) self.container.addLayout(self.hbox) self.container.setSizeConstraint(QLayout.SetFixedSize) self.setLayout(self.container) def setThread(self, workerThread): self.workerThread = workerThread self.connectProgressSignals() def connectProgressSignals(self): # Connet signals of thread self.workerThread.sig_jobEnded.connect(self.jobEnded) self.workerThread.sig_jobError.connect(self.onError) self.workerThread.sig_value.connect(self.valueFromThread) self.workerThread.sig_range.connect(self.rangeFromThread) self.workerThread.sig_text.connect(self.textFromThread) self.workerThread.sig_result.connect(self.resultFromThread) self.rerunButton.clicked.connect(self.onRerun) def run(self): # Show modal dialog window (QGIS is still responsive) self.show() # start event loop self.exec_() def jobEnded(self, success): self.setWindowTitle("SEILAPLAN") if success: self.statusLabel.setText("Berechnungen abgeschlossen.") self.progressBar.setValue(self.progressBar.maximum()) self.setFinalMessage() else: # If there was an abort by the user self.statusLabel.setText("Berechnungen abgebrochen.") self.progressBar.setValue(self.progressBar.minimum()) self.finallyDo() self.rerunButton.setVisible(True) def valueFromThread(self, value): self.progressBar.setValue(value) def rangeFromThread(self, range_vals): self.progressBar.setRange(range_vals[0], range_vals[1]) def maxFromThread(self, max): self.progressBar.setValue(self.progressBar.maximum()) def textFromThread(self, value): self.statusLabel.setText(value) def resultFromThread(self, result): [self.outputLoc, self.resultStatus] = result def setFinalMessage(self): self.resultLabel.clicked.connect(self.onResultClicked) self.resultLabel.blockSignals(True) linkToFolder = ('<html><head/><body><p></p><p><a href=' '"file:////{0}"><span style="text-decoration: ' 'underline; color:#0000ff;">{0}</span></a></p>' '</body></html>'.format(self.outputLoc)) # Optimization successful if self.resultStatus == 1: self.resultLabel.setText(textOK + linkToFolder) self.resultLabel.blockSignals(False) # Cable takes off of support elif self.resultStatus == 2: self.resultLabel.setText(textSeil + linkToFolder) self.resultLabel.blockSignals(False) # Optimization partially successful elif self.resultStatus == 3: self.resultLabel.setText(textHalf + linkToFolder) self.resultLabel.blockSignals(False) # Optimization not successful elif self.resultStatus == 4: self.resultLabel.setText(textBad) self.setLayout(self.container) def onResultClicked(self): # Open a folder window if sys.platform == 'darwin': # MAC subprocess.call(["open", "-R", self.outputLoc]) elif sys.platform.startswith('linux'): # LINUX subprocess.Popen(["xdg-open", self.outputLoc]) elif 'win32' in sys.platform: # WINDOWS from subprocess import CalledProcessError try: subprocess.check_call(['explorer', self.outputLoc]) except CalledProcessError: pass def onAbort(self): self.setWindowTitle("SEILAPLAN") self.statusLabel.setText("Laufender Prozess wird abgebrochen...") self.workerThread.cancel() # Terminates process cleanly def onError(self, exception_string): self.setWindowTitle("SEILAPLAN: Berechnung fehlgeschlagen") self.statusLabel.setText("Ein Fehler ist aufgetreten:") self.resultLabel.setText(exception_string) self.progressBar.setValue(self.progressBar.minimum()) self.finallyDo() def onRerun(self): self.reRun = True self.onClose() def finallyDo(self): self.cancelButton.hide() self.closeButton.show() def onClose(self): self.close()
class Ui_DistroMap(object): def setupUi(self, DistroMap): DistroMap.setObjectName("DistroMap") DistroMap.resize(439, 657) self.gridLayout_3 = QGridLayout(DistroMap) self.gridLayout_3.setObjectName("gridLayout_3") self.scrollArea = QScrollArea(DistroMap) self.scrollArea.setWidgetResizable(True) self.scrollArea.setObjectName("scrollArea") self.scrollAreaWidgetContents = QWidget() self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 419, 573)) self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents") self.gridLayout_6 = QGridLayout(self.scrollAreaWidgetContents) self.gridLayout_6.setObjectName("gridLayout_6") self.verticalLayout = QVBoxLayout() self.verticalLayout.setObjectName("verticalLayout") self.label_5 = QLabel(self.scrollAreaWidgetContents) self.label_5.setObjectName("label_5") self.verticalLayout.addWidget(self.label_5) self.comboLocalities = QComboBox(self.scrollAreaWidgetContents) self.comboLocalities.setObjectName("comboLocalities") self.verticalLayout.addWidget(self.comboLocalities) self.gridLayout_6.addLayout(self.verticalLayout, 1, 0, 1, 1) self.horizontalLayout_6 = QHBoxLayout() self.horizontalLayout_6.setObjectName("horizontalLayout_6") self.verticalLayout_13 = QVBoxLayout() self.verticalLayout_13.setObjectName("verticalLayout_13") self.label_19 = QLabel(self.scrollAreaWidgetContents) self.label_19.setObjectName("label_19") self.verticalLayout_13.addWidget(self.label_19) self.horizontalLayout_3 = QHBoxLayout() self.horizontalLayout_3.setObjectName("horizontalLayout_3") self.spnOutWidth = QSpinBox(self.scrollAreaWidgetContents) self.spnOutWidth.setMaximum(999999) self.spnOutWidth.setProperty("value", 325) self.spnOutWidth.setObjectName("spnOutWidth") self.horizontalLayout_3.addWidget(self.spnOutWidth) self.label_20 = QLabel(self.scrollAreaWidgetContents) self.label_20.setAlignment(Qt.AlignCenter) self.label_20.setObjectName("label_20") self.horizontalLayout_3.addWidget(self.label_20) self.spnOutHeight = QSpinBox(self.scrollAreaWidgetContents) self.spnOutHeight.setMaximum(999999) self.spnOutHeight.setProperty("value", 299) self.spnOutHeight.setObjectName("spnOutHeight") self.horizontalLayout_3.addWidget(self.spnOutHeight) self.verticalLayout_13.addLayout(self.horizontalLayout_3) self.horizontalLayout_6.addLayout(self.verticalLayout_13) self.horizontalLayout_5 = QHBoxLayout() self.horizontalLayout_5.setObjectName("horizontalLayout_5") self.verticalLayout_14 = QVBoxLayout() self.verticalLayout_14.setObjectName("verticalLayout_14") self.label_21 = QLabel(self.scrollAreaWidgetContents) sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.label_21.sizePolicy().hasHeightForWidth()) self.label_21.setSizePolicy(sizePolicy) self.label_21.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.label_21.setObjectName("label_21") self.verticalLayout_14.addWidget(self.label_21) self.horizontalLayout_4 = QHBoxLayout() self.horizontalLayout_4.setObjectName("horizontalLayout_4") spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout_4.addItem(spacerItem) self.btnColour = QPushButton(self.scrollAreaWidgetContents) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.btnColour.sizePolicy().hasHeightForWidth()) self.btnColour.setSizePolicy(sizePolicy) self.btnColour.setObjectName("btnColour") self.horizontalLayout_4.addWidget(self.btnColour) self.verticalLayout_14.addLayout(self.horizontalLayout_4) self.horizontalLayout_5.addLayout(self.verticalLayout_14) self.frmColour = QFrame(self.scrollAreaWidgetContents) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.frmColour.sizePolicy().hasHeightForWidth()) self.frmColour.setSizePolicy(sizePolicy) self.frmColour.setMinimumSize(QSize(45, 45)) self.frmColour.setSizeIncrement(QSize(1, 1)) self.frmColour.setBaseSize(QSize(0, 0)) self.frmColour.setFrameShape(QFrame.StyledPanel) self.frmColour.setFrameShadow(QFrame.Raised) self.frmColour.setObjectName("frmColour") self.horizontalLayout_5.addWidget(self.frmColour) self.horizontalLayout_6.addLayout(self.horizontalLayout_5) self.gridLayout_6.addLayout(self.horizontalLayout_6, 4, 0, 1, 1) self.verticalLayout_2 = QVBoxLayout() self.verticalLayout_2.setObjectName("verticalLayout_2") self.label_6 = QLabel(self.scrollAreaWidgetContents) self.label_6.setObjectName("label_6") self.verticalLayout_2.addWidget(self.label_6) self.comboTaxonField = QComboBox(self.scrollAreaWidgetContents) self.comboTaxonField.setObjectName("comboTaxonField") self.verticalLayout_2.addWidget(self.comboTaxonField) self.gridLayout_6.addLayout(self.verticalLayout_2, 2, 0, 1, 1) self.verticalLayout_5 = QVBoxLayout() self.verticalLayout_5.setObjectName("verticalLayout_5") self.label_9 = QLabel(self.scrollAreaWidgetContents) self.label_9.setObjectName("label_9") self.verticalLayout_5.addWidget(self.label_9) self.horizontalLayout = QHBoxLayout() self.horizontalLayout.setObjectName("horizontalLayout") self.leOutDir = QLineEdit(self.scrollAreaWidgetContents) self.leOutDir.setPlaceholderText("") self.leOutDir.setObjectName("leOutDir") self.horizontalLayout.addWidget(self.leOutDir) self.btnBrowse = QPushButton(self.scrollAreaWidgetContents) self.btnBrowse.setObjectName("btnBrowse") self.horizontalLayout.addWidget(self.btnBrowse) self.verticalLayout_5.addLayout(self.horizontalLayout) self.gridLayout_6.addLayout(self.verticalLayout_5, 5, 0, 1, 1) self.verticalLayout_6 = QVBoxLayout() self.verticalLayout_6.setObjectName("verticalLayout_6") self.label = QLabel(self.scrollAreaWidgetContents) self.label.setObjectName("label") self.verticalLayout_6.addWidget(self.label) self.gridLayout = QGridLayout() self.gridLayout.setObjectName("gridLayout") self.label_2 = QLabel(self.scrollAreaWidgetContents) self.label_2.setObjectName("label_2") self.gridLayout.addWidget(self.label_2, 0, 0, 1, 1) self.comboSecondary = QComboBox(self.scrollAreaWidgetContents) self.comboSecondary.setObjectName("comboSecondary") self.gridLayout.addWidget(self.comboSecondary, 1, 1, 1, 1) self.comboSurface = QComboBox(self.scrollAreaWidgetContents) self.comboSurface.setObjectName("comboSurface") self.gridLayout.addWidget(self.comboSurface, 2, 1, 1, 1) self.label_3 = QLabel(self.scrollAreaWidgetContents) self.label_3.setObjectName("label_3") self.gridLayout.addWidget(self.label_3, 1, 0, 1, 1) self.label_4 = QLabel(self.scrollAreaWidgetContents) self.label_4.setObjectName("label_4") self.gridLayout.addWidget(self.label_4, 2, 0, 1, 1) self.comboBase = QComboBox(self.scrollAreaWidgetContents) self.comboBase.setObjectName("comboBase") self.gridLayout.addWidget(self.comboBase, 0, 1, 1, 1) self.gridLayout.setColumnStretch(0, 1) self.gridLayout.setColumnStretch(1, 3) self.verticalLayout_6.addLayout(self.gridLayout) self.gridLayout_6.addLayout(self.verticalLayout_6, 0, 0, 1, 1) self.verticalLayout_3 = QVBoxLayout() self.verticalLayout_3.setObjectName("verticalLayout_3") self.label_7 = QLabel(self.scrollAreaWidgetContents) self.label_7.setObjectName("label_7") self.verticalLayout_3.addWidget(self.label_7) self.comboGrid = QComboBox(self.scrollAreaWidgetContents) self.comboGrid.setObjectName("comboGrid") self.verticalLayout_3.addWidget(self.comboGrid) self.verticalLayout_4 = QVBoxLayout() self.verticalLayout_4.setObjectName("verticalLayout_4") self.label_8 = QLabel(self.scrollAreaWidgetContents) self.label_8.setObjectName("label_8") self.verticalLayout_4.addWidget(self.label_8) self.gridLayout_2 = QGridLayout() self.gridLayout_2.setObjectName("gridLayout_2") self.leMaxY = QLineEdit(self.scrollAreaWidgetContents) self.leMaxY.setObjectName("leMaxY") self.gridLayout_2.addWidget(self.leMaxY, 0, 1, 1, 1) self.leMinX = QLineEdit(self.scrollAreaWidgetContents) self.leMinX.setObjectName("leMinX") self.gridLayout_2.addWidget(self.leMinX, 1, 0, 1, 1) self.leMaxX = QLineEdit(self.scrollAreaWidgetContents) self.leMaxX.setObjectName("leMaxX") self.gridLayout_2.addWidget(self.leMaxX, 1, 2, 1, 1) self.leMinY = QLineEdit(self.scrollAreaWidgetContents) self.leMinY.setObjectName("leMinY") self.gridLayout_2.addWidget(self.leMinY, 2, 1, 1, 1) self.btnExtent = QPushButton(self.scrollAreaWidgetContents) self.btnExtent.setObjectName("btnExtent") self.gridLayout_2.addWidget(self.btnExtent, 1, 1, 1, 1) self.verticalLayout_4.addLayout(self.gridLayout_2) self.verticalLayout_3.addLayout(self.verticalLayout_4) self.gridLayout_6.addLayout(self.verticalLayout_3, 3, 0, 1, 1) self.scrollArea.setWidget(self.scrollAreaWidgetContents) self.gridLayout_3.addWidget(self.scrollArea, 0, 0, 1, 1) self.buttonBox = QDialogButtonBox(DistroMap) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Ok) self.buttonBox.setObjectName("buttonBox") self.gridLayout_3.addWidget(self.buttonBox, 2, 0, 1, 1) self.progressBar = QProgressBar(DistroMap) self.progressBar.setProperty("value", 0) self.progressBar.setObjectName("progressBar") self.gridLayout_3.addWidget(self.progressBar, 1, 0, 1, 1) self.retranslateUi(DistroMap) self.buttonBox.rejected.connect(DistroMap.reject) QMetaObject.connectSlotsByName(DistroMap) def retranslateUi(self, DistroMap): DistroMap.setWindowTitle(QApplication.translate("DistroMap", "Distribution Map Generator", None)) self.label_5.setText(QApplication.translate("DistroMap", "Point localities layer", None)) self.label_19.setText(QApplication.translate("DistroMap", "Output resolution", None)) self.label_20.setText(QApplication.translate("DistroMap", "x", None)) self.label_21.setText(QApplication.translate("DistroMap", "Map background", None)) self.btnColour.setText(QApplication.translate("DistroMap", "Change", None)) self.label_6.setText(QApplication.translate("DistroMap", "Taxon identifier field", None)) self.label_9.setText(QApplication.translate("DistroMap", "Output directory", None)) self.btnBrowse.setText(QApplication.translate("DistroMap", "Browse...", None)) self.label.setText(QApplication.translate("DistroMap", "Background layers:", None)) self.label_2.setText(QApplication.translate("DistroMap", "Base", None)) self.label_3.setText(QApplication.translate("DistroMap", "Secondary", None)) self.label_4.setText(QApplication.translate("DistroMap", "Surface", None)) self.label_7.setText(QApplication.translate("DistroMap", "Grid layer", None)) self.label_8.setText(QApplication.translate("DistroMap", "Output extent:", None)) self.leMaxY.setText(QApplication.translate("DistroMap", "-21.00", None)) self.leMinX.setText(QApplication.translate("DistroMap", "14.75", None)) self.leMaxX.setText(QApplication.translate("DistroMap", "34.00", None)) self.leMinY.setText(QApplication.translate("DistroMap", "-36.00", None)) self.btnExtent.setText(QApplication.translate("DistroMap", "Use current", None))
class DisplayAequilibraEFormatsDialog(QtWidgets.QDialog, FORM_CLASS): def __init__(self, iface): QtWidgets.QDialog.__init__(self) self.iface = iface self.setupUi(self) self.error = None self.error = None self.data_path, self.data_type = GetOutputFileName( self, 'AequilibraE custom formats', ["Aequilibrae dataset(*.aed)", "Aequilibrae matrix(*.aem)"], '.aed', standard_path()) if self.data_type is None: self.error = 'Path provided is not a valid dataset' self.exit_with_error() self.data_type = self.data_type.upper() if self.data_type == 'AED': self.data_to_show = AequilibraEData() elif self.data_type == 'AEM': self.data_to_show = AequilibraeMatrix() try: self.data_to_show.load(self.data_path) except: self.error = 'Could not load dataset' self.exit_with_error() # Elements that will be used during the displaying self._layout = QVBoxLayout() self.table = QTableView() self._layout.addWidget(self.table) # Settings for displaying self.show_layout = QHBoxLayout() # Thousand separator self.thousand_separator = QCheckBox() self.thousand_separator.setChecked(True) self.thousand_separator.setText('Thousands separator') self.thousand_separator.toggled.connect(self.format_showing) self.show_layout.addWidget(self.thousand_separator) self.spacer = QSpacerItem(5, 0, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.show_layout.addItem(self.spacer) # Decimals txt = QLabel() txt.setText('Decimal places') self.show_layout.addWidget(txt) self.decimals = QSpinBox() self.decimals.valueChanged.connect(self.format_showing) self.decimals.setMinimum(0) self.decimals.setValue(4) self.decimals.setMaximum(10) self.show_layout.addWidget(self.decimals) self._layout.addItem(self.show_layout) # differentiates between matrix and dataset if self.data_type == 'AEM': self.data_to_show.computational_view([self.data_to_show.names[0]]) # Matrices need cores and indices to be set as well self.mat_layout = QHBoxLayout() self.mat_list = QComboBox() for n in self.data_to_show.names: self.mat_list.addItem(n) self.mat_list.currentIndexChanged.connect(self.change_matrix_cores) self.mat_layout.addWidget(self.mat_list) self.idx_list = QComboBox() for i in self.data_to_show.index_names: self.idx_list.addItem(i) self.idx_list.currentIndexChanged.connect(self.change_matrix_cores) self.mat_layout.addWidget(self.idx_list) self._layout.addItem(self.mat_layout) self.change_matrix_cores() self.but_export = QPushButton() self.but_export.setText('Export') self.but_export.clicked.connect(self.export) self.but_close = QPushButton() self.but_close.clicked.connect(self.exit_procedure) self.but_close.setText('Close') self.but_layout = QHBoxLayout() self.but_layout.addWidget(self.but_export) self.but_layout.addWidget(self.but_close) self._layout.addItem(self.but_layout) # We chose to use QTableView. However, if we want to allow the user to edit the dataset # The we need to allow them to switch to the slower QTableWidget # Code below # self.table = QTableWidget(self.data_to_show.entries, self.data_to_show.num_fields) # self.table.setHorizontalHeaderLabels(self.data_to_show.fields) # self.table.setObjectName('data_viewer') # # self.table.setVerticalHeaderLabels([str(x) for x in self.data_to_show.index[:]]) # self.table.clearContents() # # for i in range(self.data_to_show.entries): # for j, f in enumerate(self.data_to_show.fields): # item1 = QTableWidgetItem(str(self.data_to_show.data[f][i])) # item1.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) # self.table.setItem(i, j, item1) self.resize(700, 500) self.setLayout(self._layout) self.format_showing() def format_showing(self): decimals = self.decimals.value() separator = self.thousand_separator.isChecked() if isinstance(self.data_to_show, AequilibraeMatrix): m = NumpyModel(self.data_to_show, separator, decimals) else: m = DatabaseModel(self.data_to_show, separator, decimals) self.table.clearSpans() self.table.setModel(m) def change_matrix_cores(self): self.data_to_show.computational_view([self.mat_list.currentText()]) self.data_to_show.set_index(self.data_to_show.index_names[0]) self.format_showing() def export(self): new_name, file_type = GetOutputFileName( self, self.data_type, ["Comma-separated file(*.csv)"], ".csv", self.data_path) if new_name is not None: self.data_to_show.export(new_name) def exit_with_error(self): qgis.utils.iface.messageBar().pushMessage("Error:", self.error, level=1) self.exit_procedure() def exit_procedure(self): self.close()
def fill_tree_with_element(widget, treeItem, elt, ns_imap={}, custom_viewers={}, ns_map={}): """ :param widget: the QTreeWidget :param treeItem: a QTreeWidgetItem to fill :param elt: the XML node :param ns_imap: an "inverse" namespace map { uri : prefix } :param custom_viewers: a dict giving a custom viewer plugin (QWidget) for some elements {tag : constructor} :param ns_map: a namespace map { prefix : uri } """ is_root = treeItem == widget.invisibleRootItem() # tag ns, tag = split_tag(elt.tag) if ns and ns_imap.get(ns): treeItem.setText(0, ns_imap[ns] + ":" + tag) else: treeItem.setText(0, tag) f = treeItem.font(0) f.setBold(True) treeItem.setFont(0, f) # custom viewer if elt.tag in custom_viewers: custom_viewer_widget, filter = custom_viewers[elt.tag] if filter is None or elt.find(filter, ns_map) is not None: btn = QToolButton(widget) btn.setIcon(custom_viewer_widget.icon()) btn.setIconSize(QSize(32, 32)) def show_viewer(btn): widget.w = custom_viewer_widget.init_from_xml(elt) widget.w.setWindowModality(Qt.WindowModal) widget.w.show() btn.clicked.connect(show_viewer) w = QWidget(widget) l = QHBoxLayout() l.addWidget(btn) l.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding)) w.setLayout(l) if is_root: # insert an item child = QTreeWidgetItem() treeItem.addChild(child) widget.setItemWidget(child, 0, w) else: widget.setItemWidget(treeItem, 1, w) # attributes for k, v in elt.attrib.items(): child = QTreeWidgetItem() treeItem.addChild(child) if "}" in k: i = k.index("}") ns = k[1:i] # get ns prefix from ns uri p = ns_imap.get(ns) if p is not None: n = p + ":" + k[i + 1:] else: n = k[i + 1:] else: n = no_prefix(k) child.setText(0, "@" + n) if n == "xlink:href" and v.startswith("http"): html = QLabel(widget) html.setOpenExternalLinks(True) html.setTextFormat(Qt.RichText) html.setText('<a href="{}">{}</a>'.format(v, v)) child.setData(1, Qt.UserRole, v) widget.setItemWidget(child, 1, html) else: child.setText(1, v) # text if elt.text: treeItem.setText(1, elt.text) # children for xmlChild in elt: child = QTreeWidgetItem() treeItem.addChild(child) fill_tree_with_element(widget, child, xmlChild, ns_imap, custom_viewers, ns_map)
class GraphDockWidget(QDockWidget): """Main Dock Widget for showing 3Di results in Graphs""" closingWidget = pyqtSignal(int) def __init__( self, iface, parent_widget=None, parent_class=None, nr=0, ts_datasources=None, root_tool=None, ): """Constructor""" super().__init__(parent_widget) self.iface = iface self.parent_class = parent_class self.nr = nr self.ts_datasources = ts_datasources self.root_tool = root_tool self.setup_ui(self) parameter_config = self._get_active_parameter_config() # add graph widgets self.q_graph_widget = GraphWidget( self, self.ts_datasources, parameter_config["q"], "Q graph", QgsWkbTypes.LineString, ) self.h_graph_widget = GraphWidget( self, self.ts_datasources, parameter_config["h"], "H graph", QgsWkbTypes.Point, ) self.graphTabWidget.addTab(self.q_graph_widget, self.q_graph_widget.name) self.graphTabWidget.addTab(self.h_graph_widget, self.h_graph_widget.name) # add listeners self.addSelectedObjectButton.clicked.connect(self.add_objects) # init current layer state and add listener self.selected_layer_changed(self.iface.mapCanvas().currentLayer) self.iface.currentLayerChanged.connect(self.selected_layer_changed) self.root_tool.timeslider_widget.datasource_changed.connect( self.on_active_ts_datasource_change) def on_close(self): """ unloading widget and remove all required stuff :return: """ self.addSelectedObjectButton.clicked.disconnect(self.add_objects) self.iface.currentLayerChanged.disconnect(self.selected_layer_changed) self.root_tool.timeslider_widget.datasource_changed.disconnect( self.on_active_ts_datasource_change) # self.q_graph_widget.close() # self.h_graph_widget.close() def closeEvent(self, event): """ overwrite of QDockWidget class to emit signal :param event: QEvent """ self.on_close() self.closingWidget.emit(self.nr) event.accept() def _get_active_parameter_config(self): active_ts_datasource = self.root_tool.timeslider_widget.active_ts_datasource if active_ts_datasource is not None: # TODO: just taking the first datasource, not sure if correct: threedi_result = active_ts_datasource.threedi_result() available_subgrid_vars = threedi_result.available_subgrid_map_vars available_agg_vars = threedi_result.available_aggregation_vars if not available_agg_vars: messagebar_message("Warning", "No aggregation netCDF was found.", level=1, duration=5) parameter_config = generate_parameter_config( available_subgrid_vars, available_agg_vars) else: parameter_config = {"q": {}, "h": {}} return parameter_config def on_active_ts_datasource_change(self): parameter_config = self._get_active_parameter_config() self.q_graph_widget.set_parameter_list(parameter_config["q"]) self.h_graph_widget.set_parameter_list(parameter_config["h"]) def selected_layer_changed(self, active_layer): tdi_layer = False # get active layer from canvas, otherwise .dataProvider doesn't work canvas = self.iface.mapCanvas() current_layer = canvas.currentLayer() if current_layer: provider = current_layer.dataProvider() valid_object_type = normalized_object_type(current_layer.name()) if provider.name() in VALID_PROVIDERS and valid_object_type: tdi_layer = True elif current_layer.name() in ("flowlines", "nodes"): tdi_layer = True # activate button if 3Di layers found self.addSelectedObjectButton.setEnabled(tdi_layer) def add_objects(self): canvas = self.iface.mapCanvas() current_layer = canvas.currentLayer() if not current_layer: # todo: feedback select layer first return provider = current_layer.dataProvider() if provider.name() not in VALID_PROVIDERS: return if current_layer.name() not in list(LAYER_QH_TYPE_MAPPING.keys()): if current_layer.name() not in ("flowlines", "nodes"): # todo: feedback layer not supported return selected_features = current_layer.selectedFeatures() if current_layer.name() == "flowlines": self.q_graph_widget.add_objects(current_layer, selected_features) self.graphTabWidget.setCurrentIndex( self.graphTabWidget.indexOf(self.q_graph_widget)) return elif current_layer.name() == "nodes": self.h_graph_widget.add_objects(current_layer, selected_features) self.graphTabWidget.setCurrentIndex( self.graphTabWidget.indexOf(self.h_graph_widget)) return if LAYER_QH_TYPE_MAPPING[current_layer.name()] == "q": self.q_graph_widget.add_objects(current_layer, selected_features) self.graphTabWidget.setCurrentIndex( self.graphTabWidget.indexOf(self.q_graph_widget)) else: self.h_graph_widget.add_objects(current_layer, selected_features) self.graphTabWidget.setCurrentIndex( self.graphTabWidget.indexOf(self.h_graph_widget)) def on_btnstate(self, state): """Toggle ``absolute`` state of the GraphPlots""" checked = state == Qt.Checked self.q_graph_widget.graph_plot.absolute = ( self.h_graph_widget.graph_plot.absolute) = checked def setup_ui(self, dock_widget): """ initiate main Qt building blocks of interface :param dock_widget: QDockWidget instance """ dock_widget.setObjectName("dock_widget") dock_widget.setAttribute(Qt.WA_DeleteOnClose) self.dockWidgetContent = QWidget(self) self.dockWidgetContent.setObjectName("dockWidgetContent") self.mainVLayout = QVBoxLayout(self.dockWidgetContent) self.dockWidgetContent.setLayout(self.mainVLayout) # add button to add objects to graphs self.buttonBarHLayout = QHBoxLayout(self) self.addSelectedObjectButton = QPushButton(self.dockWidgetContent) self.addSelectedObjectButton.setObjectName("addSelectedObjectButton") self.checkbox = QCheckBox("Absolute", parent=self.dockWidgetContent) self.checkbox.setChecked(False) self.checkbox.stateChanged.connect(self.on_btnstate) self.buttonBarHLayout.addWidget(self.addSelectedObjectButton) self.buttonBarHLayout.addWidget(self.checkbox) spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.buttonBarHLayout.addItem(spacerItem) self.mainVLayout.addItem(self.buttonBarHLayout) # add tabWidget for graphWidgets self.graphTabWidget = QTabWidget(self.dockWidgetContent) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(6) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.graphTabWidget.sizePolicy().hasHeightForWidth()) self.graphTabWidget.setSizePolicy(sizePolicy) self.graphTabWidget.setObjectName("graphTabWidget") self.mainVLayout.addWidget(self.graphTabWidget) # add dockwidget dock_widget.setWidget(self.dockWidgetContent) self.retranslate_ui(dock_widget) QMetaObject.connectSlotsByName(dock_widget) def retranslate_ui(self, DockWidget): DockWidget.setWindowTitle("3Di result plots %i" % self.nr) self.addSelectedObjectButton.setText("Add")
class QgisStepsBar(QWidget): def __init__(self, steps): super().__init__() self.steps = steps self.widgets = {} self.label_width = len(max(self.steps, key=len)) * 5 self.label_spacing_width = self.label_width / 15 self.bar_height = 15 self.dot_width = 20 self._build_ui() self.current_index = 0 self._update() def _build_ui(self): self.layout_main = QVBoxLayout() self.setLayout(self.layout_main) self.layout_bar = QHBoxLayout() self.layout_bar.addSpacing(self.label_width / 2 - (self.dot_width / 2)) self.layout_main.addLayout(self.layout_bar) self._create_bar() self.layout_bar.addSpacing(self.label_width / 2 - (self.dot_width / 2)) self.layout_labels = QHBoxLayout() self.layout_main.addLayout(self.layout_labels) self._create_labels() def _create_bar(self): for i in range(len(self.steps)): self.widgets[i] = [] if i != 0: line = QFrame() line.setFrameShape(QFrame.HLine) line.setLineWidth(3) line.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) line.setFixedHeight(self.bar_height) self.layout_bar.addWidget(line) self.widgets[i].append(line) dot = QLabel("•") dot.font_size = self.bar_height * 2.6 dot.setFixedWidth(self.dot_width) dot.setFixedHeight(self.bar_height) dot.setAlignment(Qt.AlignCenter) self.layout_bar.addWidget(dot) self.widgets[i].append(dot) def _create_labels(self): for i in range(len(self.steps)): if i != 0: spacer = QSpacerItem( self.label_spacing_width, 0, QSizePolicy.Expanding, QSizePolicy.Minimum, ) self.layout_labels.addItem(spacer) label = QLabel(self.steps[i]) label.font_size = 11 label.setWordWrap(True) label.setAlignment(Qt.AlignCenter) label.setFixedWidth(self.label_width) self.layout_labels.addWidget(label) self.widgets[i].append(label) def _update(self): for key in self.widgets: if key <= self.current_index: color = "#00AC94" # greenish else: color = "#B7A99A" # greyish for widget in self.widgets[key]: try: widget.setStyleSheet("font-size:{}pt; color:{};".format( widget.font_size, color)) except AttributeError: widget.setStyleSheet("color:{};".format(color)) def increment(self): if self.current_index != len(self.steps) - 1: self.current_index += 1 self._update() def decrement(self): if self.current_index != 0: self.current_index -= 1 self._update()
def update_personal_preset_view(self): """Update the presets displayed.""" preset_folder = query_preset() files = filter( lambda folder: os.path.isdir(join(preset_folder, folder)), os.listdir(preset_folder)) self.dialog.list_personal_preset_mp.clear() for file in files: file_path = join(preset_folder, file, file + '.json') with open(file_path, encoding='utf8') as json_file: data = json.load(json_file, object_hook=as_enum) name = data['file_name'] item = QListWidgetItem(self.dialog.list_personal_preset_mp) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) self.dialog.list_personal_preset_mp.addItem(item) preset = QFrame() preset.setObjectName('FramePreset') preset.setFrameStyle(QFrame.StyledPanel) preset.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) hbox = QHBoxLayout() vbox = QVBoxLayout() label_name = QLabel(name) label_name.setStyleSheet('font-weight: bold;') label_name.setWordWrap(True) vbox.addWidget(label_name) for label in data['description']: if not label: label = tr('No description') real_label = QLabel(label) real_label.setWordWrap(True) vbox.addWidget(real_label) hbox.addItem(vbox) button_edit = QPushButton() button_remove = QPushButton() button_edit.setIcon( QIcon(QgsApplication.iconPath("mActionToggleEditing.svg"))) button_remove.setIcon( QIcon(QgsApplication.iconPath('symbologyRemove.svg'))) button_edit.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) button_remove.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) button_edit.setToolTip(tr('Edit the preset')) button_remove.setToolTip(tr('Delete the preset')) hbox.addWidget(button_edit) hbox.addWidget(button_remove) if data['advanced']: self.listAdvanced.append(True) preset.setStyleSheet('#FramePreset { margin: 3px;' ' border: 3px solid ' + self.advanced_selected + ';' ' border-width: 1px 1px 1px 4px;}') else: self.listAdvanced.append(False) preset.setStyleSheet('#FramePreset { margin: 3px;' ' border: 3px solid ' + self.basic_selected + ';' ' border-width: 1px 1px 1px 4px;}') preset.setLayout(hbox) # Actions on click remove = partial(self.verification_remove_preset, item, name) button_remove.clicked.connect(remove) edit = partial(self.edit_preset, data) button_edit.clicked.connect(edit) item.setSizeHint(preset.minimumSizeHint()) self.dialog.list_personal_preset_mp.setItemWidget(item, preset) self.listAdvanced.append(False)
def __init__(self, parent, interface, drawTool, projectHandler): """ :type drawTool: gui.mapMarker.MapMarkerTool :type projectHandler: projectHandler.ProjectConfHandler """ QDialog.__init__(self, parent) self.iface = interface self.projectHandler = projectHandler self.drawTool = drawTool self.setWindowTitle(self.tr('Gelaendelinie')) self.setWindowModality(Qt.WindowModal) self.profile = None # Array with properties fixed poles self.poleData = [] # Array with sections without poles self.noPoleSection = [] # Profile data self.xdata = None self.zdata = None self.profileMin = 0 self.profileMax = None # Plot self.sc = ProfilePlot(self) # Pan/Zoom Tools for diagram tbar = MyNavigationToolbar(self.sc, self) tbar.pan() self.sc.setToolbar(tbar) # Layout main_widget = QWidget(self) self.container = QVBoxLayout(main_widget) self.outerLayout = QVBoxLayout() # GUI fields stueTitle = QLabel('<b>' + self.tr('Stuetzenoptimierung einschraenken') + '</b>') hbox = QHBoxLayout() line1 = QFrame() line1.setFrameShape(QFrame.HLine) line1.setFrameShadow(QFrame.Sunken) # Create labels and buttons self.fixStueAdd = QPushButton(self.tr('Fixe Stuetze definieren')) self.noStueAdd = QPushButton(self.tr('Abschnitt ohne Stuetzen definieren')) self.noStueDel = QPushButton() icon = QIcon() icon.addPixmap( QPixmap(':/plugins/SeilaplanPlugin/gui/icons/icon_bin.png'), QIcon.Normal, QIcon.Off) self.noStueDel.setIcon(icon) self.noStueDel.setIconSize(QSize(16, 16)) self.fixStueAdd.setToolTip(self.tr('Tooltip Fixe Stuetzen')) self.noStueAdd.setToolTip(self.tr('Tooltip Abschnitte ohne Stuetzen')) self.noStueDel.setToolTip(self.tr('Tooltip Abschnitte loeschen')) spacerItem1 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) hbox.addWidget(self.fixStueAdd) hbox.addItem(spacerItem1) hbox.addWidget(self.noStueAdd) hbox.addWidget(self.noStueDel) hbox.setAlignment(self.noStueAdd, Qt.AlignRight) btnBoxSpacer = QSpacerItem(40, 40, QSizePolicy.Fixed, QSizePolicy.Fixed) self.buttonBox = QDialogButtonBox(main_widget) self.buttonBox.setStandardButtons(QDialogButtonBox.Ok) # Build up Gui self.container.addWidget(self.sc) self.container.addWidget(tbar, alignment=Qt.AlignHCenter | Qt.AlignTop) self.container.addWidget(line1) self.container.addWidget(stueTitle) self.container.addLayout(hbox) self.container.addLayout(self.outerLayout) self.container.addItem(btnBoxSpacer) self.container.addWidget(self.buttonBox) # Connect signals self.fixStueAdd.clicked.connect(self.sc.acitvateCrosshairPole) self.noStueAdd.clicked.connect(self.sc.activateCrosshairSection) self.noStueDel.clicked.connect(self.deleteSections) self.buttonBox.accepted.connect(self.Apply) self.setLayout(self.container) # Gui's functionality for fixed pole gui fields self.buildPoleHeader() self.poleLayout = CustomPoleWidget(self, self.outerLayout, self.poleData) self.poleLayout.sig_updatePole.connect(self.updatePole) self.poleLayout.sig_deletePole.connect(self.deletePole)
def show(self, *args, title: str = 'Parameter einstellen', scrollable: bool = False): ''' render parameters and elements in parent Parameters ---------- args : optional arguments for appending parameter layout to parent (like x, y if parent is grid layout) title : str, optional title of the parameter dialog, defaults to 'Parameter einstellen' scrollable : bool, optional a scrollbar will be added to both preview and dialog if True, recommended if there are a lot of parameters, defaults to not scrollable ''' if self.parent is None: raise Exception("can't render Params object with no parent set") # Debug: function to automatically write a help file with all params # with empty texts, should be removed in production if (settings.DEBUG and getattr(self, 'help_file', None) and not os.path.exists(self.help_file)): if not os.path.exists(self.HELP_PATH): os.mkdir(self.HELP_PATH) with open(self.help_file, 'w') as json_file: json.dump(self.help_dict, json_file, indent=4) self.dialog = ParamsDialog(parent=None, help_text=self.help_dict['beschreibung'], title=title) self.parent.addLayout(self.layout, *args) if scrollable: frame = QFrame() scroll_area = QScrollArea() layout = QVBoxLayout() layout.setSpacing(5) frame.setLayout(layout) scroll_area.setWidget(frame) scroll_area.setWidgetResizable(True) scroll_area.setFixedHeight(400) self.layout.addWidget(scroll_area) else: layout = self.layout for element in self._elements: if isinstance(element, QLayoutItem): layout.addItem(element) # overview elif not getattr(element, 'hide_in_overview', None): element.draw(layout) self.dialog.draw(element) if not self.editable: return row = QHBoxLayout() button = QPushButton(self.button_label) icon = QIcon(os.path.join(settings.IMAGE_PATH, 'iconset_mob', '20190619_iconset_mob_edit_1.png')) button.setIcon(icon) tool_tip = self.help_dict.get('tooltip', None) button.setToolTip(tool_tip) row.addItem( QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum)) row.addWidget(button) self.layout.addItem( QSpacerItem(10, 10, QSizePolicy.Fixed, QSizePolicy.Minimum)) self.layout.addLayout(row) button.clicked.connect(self.show_dialog)
class ProgressDialog(QDialog): """ Progress dialog shows progress bar for algorithm. """ def __init__(self, iface): QDialog.__init__(self, iface.mainWindow()) self.workerThread = None self.state = False self.resultStatus = None self.doReRun = False self.wasCanceled = False self.wasSuccessful = False self.savedProj = None self.result = None self.messageTxt = { 'msg_optimierung': self.tr('Berechnung der optimalen Stuetzenpositionen...'), 'msg_seillinie': self.tr('Berechnung der optimale Seillinie...') } # Build GUI Elements self.setWindowTitle(self.tr("SEILAPLAN wird ausgefuehrt")) self.resize(500, 100) self.container = QVBoxLayout() self.progressBar = QProgressBar(self) self.progressBar.setMinimumWidth(500) self.statusLabel = QLabel(self) self.hbox = QHBoxLayout() self.cancelButton = QDialogButtonBox() self.closeButton = QDialogButtonBox() self.resultLabel = QLabel(self) self.resultLabel.setMaximumWidth(500) self.resultLabel.setSizePolicy( QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding)) self.resultLabel.setWordWrap(True) spacer1 = QSpacerItem(20, 20, QSizePolicy.Fixed, QSizePolicy.Fixed) self.rerunButton = QPushButton(self.tr("zurueck zum Startfenster")) self.rerunButton.setVisible(False) spacer2 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.cancelButton.setStandardButtons(QDialogButtonBox.Cancel) self.cancelButton.button(QDialogButtonBox.Cancel).setText(self.tr("Abbrechen")) self.cancelButton.clicked.connect(self.onAbort) self.closeButton.setStandardButtons(QDialogButtonBox.Close) self.closeButton.button(QDialogButtonBox.Close).setText(self.tr("Schliessen")) self.closeButton.clicked.connect(self.onClose) self.hbox.addWidget(self.rerunButton) self.hbox.addItem(spacer2) self.hbox.addWidget(self.cancelButton) self.hbox.setAlignment(self.cancelButton, Qt.AlignHCenter) self.hbox.addWidget(self.closeButton) self.hbox.setAlignment(self.closeButton, Qt.AlignHCenter) self.closeButton.hide() self.container.addWidget(self.progressBar) self.container.addWidget(self.statusLabel) self.container.addWidget(self.resultLabel) self.container.addItem(spacer1) self.container.addLayout(self.hbox) self.container.setSizeConstraint(QLayout.SetFixedSize) self.setLayout(self.container) # noinspection PyMethodMayBeStatic def tr(self, message, **kwargs): """Get the translation for a string using Qt translation API. We implement this ourselves since we do not inherit QObject. :param message: String for translation. :type message: str, QString :returns: Translated version of message. :rtype: QString Parameters ---------- **kwargs """ # noinspection PyTypeChecker,PyArgumentList,PyCallByClass return QCoreApplication.translate(type(self).__name__, message) def setThread(self, workerThread): self.workerThread = workerThread self.connectThreadSignals() def connectThreadSignals(self): # Connect signals of thread self.workerThread.sig_jobEnded.connect(self.jobEnded) self.workerThread.sig_jobError.connect(self.onError) self.workerThread.sig_value.connect(self.valueFromThread) self.workerThread.sig_range.connect(self.rangeFromThread) self.workerThread.sig_text.connect(self.textFromThread) self.workerThread.sig_result.connect(self.resultFromThread) self.rerunButton.clicked.connect(self.onRerun) def run(self): # Show modal dialog window (QGIS is still responsive) self.show() # start event loop self.exec() def jobEnded(self, success): self.setWindowTitle("SEILAPLAN") if success: self.progressBar.setValue(self.progressBar.maximum()) self.wasSuccessful = True # Close progress dialog so that adjustment window can be opened self.close() else: # If there was an abort by the user self.statusLabel.setText(self.tr("Berechnungen abgebrochen.")) self.progressBar.setValue(self.progressBar.minimum()) self.finallyDo() def valueFromThread(self, value): self.progressBar.setValue(int(value)) def rangeFromThread(self, range_vals): self.progressBar.setRange(int(round(range_vals[0])), int(round(range_vals[1]))) def maxFromThread(self, max): self.progressBar.setValue(self.progressBar.maximum()) def textFromThread(self, message): self.statusLabel.setText(self.messageTxt[message]) def resultFromThread(self, resultStatus): self.resultStatus = resultStatus # resultStatus: # 1 = Optimization successful # 2 = Cable takes off from support # 3 = Optimization partially successful def onAbort(self): self.setWindowTitle('SEILAPLAN') self.statusLabel.setText(self.tr( 'Laufender Prozess wird abgebrochen...')) self.workerThread.cancel() # Terminates process cleanly self.wasCanceled = True def onError(self, exception_string): self.setWindowTitle(self.tr('SEILAPLAN: Berechnung fehlgeschlagen')) self.statusLabel.setText(self.tr('Ein Fehler ist aufgetreten:')) self.resultLabel.setText(self.tr(exception_string)) self.resultLabel.setHidden(False) self.progressBar.setValue(self.progressBar.minimum()) self.setLayout(self.container) self.finallyDo() def onRerun(self): self.doReRun = True self.onClose() def finallyDo(self): self.rerunButton.setVisible(True) self.cancelButton.hide() self.closeButton.show() def onClose(self): self.close()
class GraphWidget(QWidget): def __init__( self, parent=None, ts_datasources=None, parameter_config=[], name="", geometry_type=QgsWkbTypes.Point, ): super().__init__(parent) self.name = name self.ts_datasources = ts_datasources self.parent = parent self.geometry_type = geometry_type self.setup_ui() self.model = LocationTimeseriesModel( ts_datasources=self.ts_datasources) self.graph_plot.set_location_model(self.model) self.graph_plot.set_ds_model(self.ts_datasources) self.location_timeseries_table.setModel(self.model) # set listeners self.parameter_combo_box.currentIndexChanged.connect( self.parameter_change) self.remove_timeseries_button.clicked.connect( self.remove_objects_table) # init parameter selection self.set_parameter_list(parameter_config) if self.geometry_type == QgsWkbTypes.Point: self.marker = QgsVertexMarker(self.parent.iface.mapCanvas()) else: self.marker = QgsRubberBand(self.parent.iface.mapCanvas()) self.marker.setColor(Qt.red) self.marker.setWidth(2) def set_parameter_list(self, parameter_config): # reset nr_old_parameters = self.parameter_combo_box.count() self.parameters = dict([(p["name"], p) for p in parameter_config]) self.parameter_combo_box.insertItems( 0, [p["name"] for p in parameter_config]) # todo: find best matching parameter based on previous selection if nr_old_parameters > 0: self.parameter_combo_box.setCurrentIndex(0) nr_parameters_tot = self.parameter_combo_box.count() for i in reversed( list( range(nr_parameters_tot - nr_old_parameters, nr_parameters_tot))): self.parameter_combo_box.removeItem(i) # self.graph_plot.set_parameter(self.current_parameter) def on_close(self): """ unloading widget and remove all required stuff :return: """ self.parameter_combo_box.currentIndexChanged.disconnect( self.parameter_change) self.remove_timeseries_button.clicked.disconnect( self.remove_objects_table) def closeEvent(self, event): """ overwrite of QDockWidget class to emit signal :param event: QEvent """ self.on_close() event.accept() def highlight_feature(self, obj_id, obj_type): pass # todo: selection generated errors and crash of Qgis. Implement method # with QgsRubberband and/ or QgsVertexMarker transform = QgsCoordinateTransform( QgsCoordinateReferenceSystem(4326), QgsProject.instance().crs(), QgsProject.instance(), ) layers = self.parent.iface.mapCanvas().layers() for lyr in layers: # Clear other layers # lyr.removeSelection() if lyr.name() == obj_type: # query layer for object filt = u'"id" = {0}'.format(obj_id) request = QgsFeatureRequest().setFilterExpression(filt) features = lyr.getFeatures(request) for feature in features: if self.geometry_type == QgsWkbTypes.Point: geom = feature.geometry() geom.transform(transform) self.marker.setCenter(geom.asPoint()) self.marker.setVisible(True) else: self.marker.setToGeometry(feature.geometry(), lyr) def unhighlight_all_features(self): """Remove the highlights from all layers""" if self.geometry_type == QgsWkbTypes.Point: self.marker.setVisible(False) else: self.marker.reset() pass # todo: selection generated errors and crash of Qgis. Implement method # with QgsRubberband and/ or QgsVertexMarker def setup_ui(self): """ Create Qt widgets and elements """ self.setObjectName(self.name) self.hLayout = QHBoxLayout(self) self.hLayout.setObjectName("hLayout") # add graphplot self.graph_plot = GraphPlot(self) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(1) sizePolicy.setHeightForWidth( self.graph_plot.sizePolicy().hasHeightForWidth()) self.graph_plot.setSizePolicy(sizePolicy) self.graph_plot.setMinimumSize(QSize(250, 250)) self.hLayout.addWidget(self.graph_plot) # add layout for timeseries table and other controls self.vLayoutTable = QVBoxLayout(self) self.hLayout.addLayout(self.vLayoutTable) # add combobox for parameter selection self.parameter_combo_box = QComboBox(self) self.vLayoutTable.addWidget(self.parameter_combo_box) # add timeseries table self.location_timeseries_table = LocationTimeseriesTable(self) self.location_timeseries_table.hoverEnterRow.connect( self.highlight_feature) self.location_timeseries_table.hoverExitAllRows.connect( self.unhighlight_all_features) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.location_timeseries_table.sizePolicy().hasHeightForWidth()) self.location_timeseries_table.setSizePolicy(sizePolicy) self.location_timeseries_table.setMinimumSize(QSize(250, 0)) self.vLayoutTable.addWidget(self.location_timeseries_table) # add buttons below table self.hLayoutButtons = QHBoxLayout(self) self.vLayoutTable.addLayout(self.hLayoutButtons) self.remove_timeseries_button = QPushButton(self) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.remove_timeseries_button.sizePolicy().hasHeightForWidth()) self.remove_timeseries_button.setSizePolicy(sizePolicy) self.remove_timeseries_button.setObjectName("remove_timeseries_button") self.hLayoutButtons.addWidget(self.remove_timeseries_button) self.hLayoutButtons.addItem( QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)) self.retranslateUi() def retranslateUi(self): """ set translated widget text """ self.remove_timeseries_button.setText("Delete") def parameter_change(self, nr): """ set current selected parameter and trigger refresh of graphs :param nr: nr of selected option of combobox :return: """ self.current_parameter = self.parameters[ self.parameter_combo_box.currentText()] self.graph_plot.set_parameter(self.current_parameter) def get_feature_index(self, layer, feature): """ get the id of the selected id feature :param layer: selected Qgis layer to be added :param feature: selected Qgis feature to be added :return: idx (integer) We can't do ``feature.id()``, so we have to pick something that we have agreed on. For now we have hardcoded the 'id' field as the default, but that doesn't mean it's always the case in the future when more layers are added! """ idx = feature.id() if layer.dataProvider().name() in PROVIDERS_WITHOUT_PRIMARY_KEY: idx = feature["id"] return idx def get_object_name(self, layer, feature): """ get the object_name (display_name / type) of the selected id feature :param layer: selected Qgis layer to be added :param feature: selected Qgis feature to be added :return: object_name (string) To get a object_name we use the following logic: - get the '*display_name*' column if available; - if not: get the 'type' column if available; - if not: object_name = 'N/A' """ object_name = None for column_nr, field in enumerate(layer.fields()): if "display_name" in field.name(): object_name = feature[column_nr] if object_name is None: for column_nr, field in enumerate(layer.fields()): if field.name() == "type": object_name = feature[column_nr] break else: object_name = "N/A" logger.warning( "Layer has no 'display_name', it's probably a result " "layer, but putting a placeholder object name just " "for safety.") return object_name def get_new_items(self, layer, features, filename, existing_items): """ get a list of new items (that have been selected by user) to be added to graph (if they do not already exist in the graph items :param layer: selected Qgis layer to be added :param features: selected Qgis features to be added :param filename: selected Qgis features to be added :param existing_items: selected Qgis features to be added :return: new_items (list) """ new_items = [] for feature in features: new_idx = self.get_feature_index(layer, feature) new_object_name = self.get_object_name(layer, feature) # check if object not already exist if (layer.name() + "_" + str(new_idx)) not in existing_items: item = { "object_type": layer.name(), "object_id": new_idx, "object_name": new_object_name, "file_path": filename, } new_items.append(item) return new_items def add_objects(self, layer, features): """ :param layer: layer of features :param features: Qgis layer features to be added :return: boolean: new objects are added """ # Get the active database as URI, conn_info is something like: # u"dbname='/home/jackieleng/git/threedi-turtle/var/models/ # DS_152_1D_totaal_bergingsbak/results/ # DS_152_1D_totaal_bergingsbak_result.sqlite'" if layer.name() not in ("flowlines", "nodes", "pumplines"): msg = """Please select results from either the 'flowlines', 'nodes' or 'pumplines' layer.""" messagebar_message("Info", msg, level=0, duration=5) return conn_info = QgsDataSourceUri( layer.dataProvider().dataSourceUri()).connectionInfo() try: filename = conn_info.split("'")[1] except IndexError: raise RuntimeError( "Active database (%s) doesn't look like an sqlite filename" % conn_info) # get attribute information from selected layers existing_items = [ "%s_%s" % (item.object_type.value, str(item.object_id.value)) for item in self.model.rows ] items = self.get_new_items(layer, features, filename, existing_items) if len(items) > 20: msg = ("%i new objects selected. Adding those to the plot can " "take a while. Do you want to continue?" % len(items)) reply = QMessageBox.question(self, "Add objects", msg, QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.No: return False self.model.insertRows(items) msg = "%i new objects added to plot " % len(items) skipped_items = len(features) - len(items) if skipped_items > 0: msg += "(skipped %s already present objects)" % skipped_items statusbar_message(msg) return True def remove_objects_table(self): """ removes selected objects from table :return: """ selection_model = self.location_timeseries_table.selectionModel() # get unique rows in selected fields rows = set( [index.row() for index in selection_model.selectedIndexes()]) for row in reversed(sorted(rows)): self.model.removeRows(row, 1)