class DataFrameModel(QAbstractTableModel): """Podstawowy model tabeli zasilany przez pandas dataframe.""" DtypeRole = Qt.UserRole + 1000 ValueRole = Qt.UserRole + 1001 def __init__(self, df=pd.DataFrame(), tv=None, col_names=[], parent=None): super(DataFrameModel, self).__init__(parent) self._dataframe = df self.col_names = col_names self.tv = tv # Referencja do tableview self.tv.setModel(self) self.tv.selectionModel().selectionChanged.connect( lambda: self.layoutChanged.emit()) self.tv.horizontalHeader().setSortIndicatorShown(False) self.sort_col = -1 self.sort_ord = 1 def col_names(self, df, col_names): """Nadanie nazw kolumn tableview'u.""" df.columns = col_names return df def sort_reset(self): """Wyłącza sortowanie po kolumnie.""" self.sort_col = -1 self.sort_ord = 1 def setDataFrame(self, dataframe): self.beginResetModel() self._dataframe = dataframe.copy() self.endResetModel() def dataFrame(self): return self._dataframe dataFrame = pyqtProperty(pd.DataFrame, fget=dataFrame, fset=setDataFrame) @pyqtSlot(int, Qt.Orientation, result=str) def headerData(self, section: int, orientation: Qt.Orientation, role: int = Qt.DisplayRole): if role == Qt.DisplayRole: if orientation == Qt.Horizontal: if self.col_names: try: return self.col_names[section] # type: ignore except: pass return self._dataframe.columns[section] else: return str(self._dataframe.index[section]) return QVariant() # if role == Qt.DecorationRole and orientation == Qt.Horizontal: # self.tv.setSortIndicatorShown(False) def rowCount(self, parent=QModelIndex()): if parent.isValid(): return 0 return len(self._dataframe.index) def columnCount(self, parent=QModelIndex()): if parent.isValid(): return 0 return self._dataframe.columns.size def data(self, index, role=Qt.DisplayRole): if not index.isValid() or not (0 <= index.row() < self.rowCount() \ and 0 <= index.column() < self.columnCount()): return QVariant() row = self._dataframe.index[index.row()] col = self._dataframe.columns[index.column()] dt = self._dataframe[col].dtype try: val = self._dataframe.iloc[row][col] except: return QVariant() # if role == Qt.DisplayRole: # # # Get the raw value # # if isinstance(val, float) and (index.column() == 2 or index.column() == 3): # # return "%.2f" % val # # if isinstance(val, float) and (index.column() == 4 or index.column() == 5): # # return "%.1f" % val # # if isinstance(val, float) & index.column() == 6: # # return "%.0f" % val # return str(val) if role == DataFrameModel.ValueRole: return val if role == DataFrameModel.DtypeRole: return dt return QVariant() def roleNames(self): roles = { Qt.DisplayRole: b'display', DataFrameModel.DtypeRole: b'dtype', DataFrameModel.ValueRole: b'value' } return roles
class GdalToolsInOutSelector(QWidget, Ui_GdalToolsInOutSelector): FILE = 0x1 LAYER = 0x2 MULTIFILE = 0x4 # NOT IMPLEMENTED YET FILE_LAYER = 0x1 | 0x2 FILES = 0x1 | 0x4 # NOT IMPLEMENTED YET FILES_LAYER = 0x3 | 0x4 # NOT IMPLEMENTED YET selectClicked = pyqtSignal() filenameChanged = pyqtSignal() layerChanged = pyqtSignal() def __init__(self, parent=None, type=None): QWidget.__init__(self, parent) self.setupUi(self) self.setFocusPolicy(Qt.StrongFocus) self.combo.setInsertPolicy(QComboBox.NoInsert) self.clear() self.typ = None if type is None: self.resetType() else: self.setType(type) self.selectBtn.clicked.connect(self.selectClicked) self.fileEdit.textChanged.connect(self.textChanged) self.combo.editTextChanged.connect(self.textChanged) self.combo.currentIndexChanged.connect(self.indexChanged) def clear(self): self.filenames = [] self.fileEdit.clear() self.clearComboState() self.combo.clear() def textChanged(self): if self.getType() & self.MULTIFILE: self.filenames = self.fileEdit.text().split(",") if self.getType() & self.LAYER: index = self.combo.currentIndex() if index >= 0: text = self.combo.currentText() if text != self.combo.itemText(index): return self.setFilename(text) self.filenameChanged.emit() def indexChanged(self): self.layerChanged.emit() self.filenameChanged.emit() def setType(self, type): if type == self.typ: return if type & self.MULTIFILE: # MULTITYPE IS NOT IMPLEMENTED YET type = type & ~self.MULTIFILE self.typ = type self.selectBtn.setVisible(self.getType() & self.FILE) self.combo.setVisible(self.getType() & self.LAYER) self.fileEdit.setVisible(not (self.getType() & self.LAYER)) self.combo.setEditable(self.getType() & self.FILE) if self.getType() & self.FILE: self.setFocusProxy(self.selectBtn) else: self.setFocusProxy(self.combo) # send signals to refresh connected widgets self.filenameChanged.emit() self.layerChanged.emit() def getType(self): return self.typ def resetType(self): self.setType(self.FILE_LAYER) selectorType = pyqtProperty("int", getType, setType, resetType) def setFilename(self, fn=None): self.blockSignals(True) prevFn, prevLayer = self.filename(), self.layer() if isinstance(fn, QgsMapLayer): fn = fn.source() elif isinstance(fn, str) or isinstance(fn, str): fn = str(fn) # TODO test elif isinstance(fn, list): if len(fn) > 0: if self.getType() & self.MULTIFILE: self.filenames = fn #fn = "".join( fn, "," ) fn = ",".join(fn) else: fn = '' else: fn = '' if not (self.getType() & self.LAYER): self.fileEdit.setText(fn) else: self.combo.setCurrentIndex(-1) self.combo.setEditText(fn) self.blockSignals(False) if self.filename() != prevFn: self.filenameChanged.emit() if self.layer() != prevLayer: self.layerChanged.emit() def setLayer(self, layer=None): if not (self.getType() & self.LAYER): return self.setFilename(layer) self.blockSignals(True) prevFn, prevLayer = self.filename(), self.layer() if isinstance(layer, QgsMapLayer): if self.combo.findData(layer.id()) >= 0: index = self.combo.findData(layer.id()) self.combo.setCurrentIndex(index) else: self.combo.setCurrentIndex(-1) self.combo.setEditText(layer.source()) elif isinstance(layer, int) and layer >= 0 and layer < self.combo.count(): self.combo.setCurrentIndex(layer) else: self.combo.clearEditText() self.combo.setCurrentIndex(-1) self.blockSignals(False) if self.filename() != prevFn: self.filenameChanged.emit() if self.layer() != prevLayer: self.layerChanged.emit() def setLayers(self, layers=None): if layers is None or not hasattr(layers, '__iter__') or len(layers) <= 0: self.combo.clear() return self.blockSignals(True) prevFn, prevLayer = self.filename(), self.layer() self.saveComboState() self.combo.clear() for l in layers: self.combo.addItem(l.name(), l.id()) self.restoreComboState() self.blockSignals(False) if self.filename() != prevFn: self.filenameChanged.emit() if self.layer() != prevLayer: self.layerChanged.emit() def clearComboState(self): self.prevState = None def saveComboState(self): index = self.combo.currentIndex() text = self.combo.currentText() layerID = self.combo.itemData(index) if index >= 0 else "" self.prevState = (index, text, layerID) def restoreComboState(self): if self.prevState is None: return index, text, layerID = self.prevState if index < 0: if text == '' and self.combo.count() > 0: index = 0 elif self.combo.findData(layerID) < 0: index = -1 text = "" else: index = self.combo.findData(layerID) self.combo.setCurrentIndex(index) if index >= 0: text = self.combo.itemText(index) self.combo.setEditText(text) def layer(self): if self.getType() != self.FILE and self.combo.currentIndex() >= 0: layerID = self.combo.itemData(self.combo.currentIndex()) return QgsMapLayerRegistry.instance().mapLayer(layerID) return None def filename(self): if not (self.getType() & self.LAYER): if self.getType() & self.MULTIFILE: return self.filenames return self.fileEdit.text() if self.combo.currentIndex() < 0: if self.getType() & self.MULTIFILE: return self.filenames return self.combo.currentText() layer = self.layer() if layer is not None: return layer.source() return ''
class CompassWidget(QWidget): angleChanged = pyqtSignal(float) angle2Changed = pyqtSignal(float) def __init__(self, parent=None): QWidget.__init__(self, parent) self._angle = -9999.9 self._angle2 = -9999.9 self._margins = 10 self._pointText = { 0: "N", 45: "45", 90: "90", 135: "135", 180: "S", 225: "225", 270: "270", 315: "315" } def paintEvent(self, event): painter = QPainter() painter.begin(self) painter.setRenderHint(QPainter.Antialiasing) painter.fillRect(event.rect(), self.palette().brush(QPalette.Window)) self.drawMarkings(painter) self.drawNeedle(painter) self.drawNeedle2(painter) painter.end() def drawMarkings(self, painter): painter.save() painter.translate(self.width() / 2, self.height() / 2) scale = min((self.width() - self._margins) / 120.0, (self.height() - self._margins) / 120.0) painter.scale(scale, scale) font = QFont(self.font()) font.setPixelSize(10) metrics = QFontMetricsF(font) painter.setFont(font) painter.setPen(self.palette().color(QPalette.Shadow)) i = 0 while i < 360: if i % 45 == 0: painter.drawLine(0, -40, 0, -50) painter.drawText(int(-metrics.width(self._pointText[i]) / 2), -52, self._pointText[i]) else: painter.drawLine(0, -45, 0, -50) painter.rotate(15) i += 15 painter.restore() def drawNeedle(self, painter): if self._angle < -9999: return painter.save() painter.translate(self.width() / 2, self.height() / 2) painter.rotate(self._angle) scale = min((self.width() - self._margins) / 120.0, (self.height() - self._margins) / 120.0) painter.scale(scale, scale) painter.setPen(QPen(Qt.NoPen)) # painter.setBrush(self.palette().brush(QPalette.Shadow)) # # painter.drawPolygon( # QPolygon([QPoint(-10, 0), QPoint(0, -45), QPoint(10, 0), # QPoint(0, 45), QPoint(-10, 0)]) # ) painter.setBrush(self.palette().brush(QPalette.Highlight)) painter.drawPolygon( QPolygon([ QPoint(-5, -25), QPoint(0, -45), QPoint(5, -25), QPoint(0, -30), QPoint(-5, -25) ])) painter.restore() def drawNeedle2(self, painter): if self._angle2 < -9999: return painter.save() painter.translate(self.width() / 2, self.height() / 2) painter.rotate(self._angle2) scale = min((self.width() - self._margins) / 120.0, (self.height() - self._margins) / 120.0) painter.scale(scale, scale) painter.setPen(QPen(Qt.NoPen)) # painter.setBrush(self.palette().brush(QPalette.Dark)) # # painter.drawPolygon( # QPolygon([QPoint(-7, 0), QPoint(0, -25), QPoint(7, 0), # QPoint(0, 25), QPoint(-7, 0)]) # ) painter.setBrush(self.palette().brush(QPalette.Foreground)) painter.drawPolygon( QPolygon([ QPoint(-5, -10), QPoint(0, -25), QPoint(5, -10), QPoint(0, -13), QPoint(-5, -10) ])) painter.restore() def sizeHint(self): return QSize(150, 150) def angle(self): return self._angle def angle2(self): return self._angle2 @pyqtSlot(float) def setAngle(self, angle): if angle != self._angle: self._angle = angle self.angleChanged.emit(angle) self.update() angle = pyqtProperty(float, angle, setAngle) @pyqtSlot(float) def setAngle2(self, angle): if angle != self._angle2: self._angle2 = angle self.angle2Changed.emit(angle) self.update() angle2 = pyqtProperty(float, angle2, setAngle2) def reset(self, no=None): if no == 1: self._angle = -9999.9 elif no == 2: self._angle2 = -9999.9 else: self._angle = -9999.9 self._angle2 = -9999.9 self.update()