class RequestsOperations(QWidget): def __init__(self, parent): super().__init__(parent) self.initUI() self.__ops = [] def initUI(self): self.layout = QFormLayout() self.layout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow) self.layout.setLabelAlignment(Qt.AlignLeft) self.layout.setFormAlignment(Qt.AlignLeft | Qt.AlignTop) twoListsOfSets = QWidget() twoListsOfSets.setLayout(QHBoxLayout()) twoListsOfSets.layout().setContentsMargins(5, 10, 5, 5) twoListsOfSets.layout().setSpacing(0) effect = QGraphicsDropShadowEffect() effect.setBlurRadius(10) effect.setColor(QColor(0, 0, 0, 160)) effect.setOffset(0.0) self.requestList = QListView() self.requestList.setSpacing(3) self.requestList.setAutoFillBackground(True) self.requestList.setGraphicsEffect(effect) self.requestList.setFrameStyle(QFrame.NoFrame) self.requestList.viewport().setAutoFillBackground(False) self.requestList.setFlow(QListView.LeftToRight) self.requestList.setWrapping(True) self.requestList.setResizeMode(QListView.Adjust) self.requestList.setUniformItemSizes(True) self.requestsModel = QStandardItemModel() self.requestList.setModel(self.requestsModel) effect = QGraphicsDropShadowEffect() effect.setBlurRadius(10) effect.setColor(QColor(0, 0, 0, 160)) effect.setOffset(0.0) self.requestList2 = QListView() self.requestList2.setSpacing(3) self.requestList2.setAutoFillBackground(True) self.requestList2.setGraphicsEffect(effect) self.requestList2.setFrameStyle(QFrame.NoFrame) self.requestList2.viewport().setAutoFillBackground(False) self.requestList2.setFlow(QListView.LeftToRight) self.requestList2.setWrapping(True) self.requestList2.setResizeMode(QListView.Adjust) self.requestList2.setUniformItemSizes(True) self.requestsModel2 = QStandardItemModel() self.requestList2.setModel(self.requestsModel2) twoListsOfSets.layout().addWidget(self.requestList) twoListsOfSets.layout().addWidget(self.requestList2) self.layout.addRow("SETS", twoListsOfSets) self.layout.addRow(HorizontalLine(self)) self.operationSelection = QGroupBox() self.operationSelection.setFlat(True) self.operationSelection.setLayout(QVBoxLayout()) self.buttonIntersection = QRadioButton("Intersection") self.operationSelection.layout().addWidget(self.buttonIntersection) self.buttonIntersection.clicked.connect( self.__disableSecondRequestList) self.buttonIntersection.click() self.buttonUnion = QRadioButton("Union") self.operationSelection.layout().addWidget(self.buttonUnion) self.buttonUnion.clicked.connect(self.__disableSecondRequestList) self.buttonDiff = QRadioButton("Difference") self.operationSelection.layout().addWidget(self.buttonDiff) self.buttonDiff.clicked.connect(self.__enableSecondRequestList) self.layout.addRow("OPERATION", self.operationSelection) self.buttonApplyWidget = QWidget() self.buttonApplyWidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) self.buttonApplyLayout = QHBoxLayout() self.buttonApplyLayout.setContentsMargins(0, 0, 0, 0) self.buttonApplyWidget.setLayout(self.buttonApplyLayout) self.buttonApply = QPushButton("Apply") self.buttonApply.clicked.connect(self.__applyOp) self.operationSelection.layout().addWidget(self.buttonApply) self.buttonApplyLayout.addWidget(self.buttonApply, alignment=Qt.AlignRight) self.layout.addRow("", self.buttonApplyWidget) self.layout.addRow(HorizontalLine(self)) self.layout.addRow("RESULTS", None) self.resultingSets = QTableView() self.resultingSets.horizontalHeader().setSectionResizeMode( QHeaderView.Stretch) self.resultingSets.verticalHeader().setSectionResizeMode( QHeaderView.ResizeToContents) self.resultingSets.setModel(OperationsTableModel()) self.layout.addRow(self.resultingSets) self.layout.addRow(HorizontalLine(self)) self.outputSetSelection = QComboBox() self.outputSetSelection.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed) self.layout.addRow("OUTPUT SET", self.outputSetSelection) self.setLayout(self.layout) def outputSet(self): return self.outputSetSelection.currentText() def setOutputSet(self, outputSetName): self.outputSetSelection.setCurrentText(outputSetName) @property def ops(self): return copy.deepcopy(self.__ops) def __applyOp(self): includedSets = [ self.requestsModel.item(i).text() for i in range(self.requestsModel.rowCount()) if self.requestsModel.item(i).data(Qt.CheckStateRole) == QVariant( Qt.Checked) ] if self.buttonUnion.isChecked(): if len(includedSets) > 1: opName = SetNameManagement.getUniqueSetName() self.addOp(OverpassUnion(opName), includedSets) logging.info("Union created.") else: logging.error("The union must have at least two sets.") elif self.buttonIntersection.isChecked(): if len(includedSets) > 1: opName = SetNameManagement.getUniqueSetName() self.addOp(OverpassIntersection(opName), includedSets) logging.info("Intersection created.") else: logging.error("The intersection must have at least two sets.") elif self.buttonDiff.isChecked(): excludedSets = [ self.requestsModel2.item(i).text() for i in range(self.requestsModel2.rowCount()) if self.requestsModel2.item(i).data(Qt.CheckStateRole) == QVariant(Qt.Checked) ] if len(includedSets) == 1 and len(excludedSets) > 0: opName = SetNameManagement.getUniqueSetName() self.addOp(OverpassDiff(includedSets[0], opName), excludedSets) logging.info("Difference created.") else: logging.error( "The difference must have only one set selected in the first list and at least one in the other." ) logging.debug("LINE") def addOp(self, op, sets=None): SetNameManagement.assign(op.name) self.__ops.append(op) if sets is not None: op.addSets(sets) self.resultingSets.model().addOp(op.name, op) self.addRequest(op.name) self.cleanRequestList() def __enableSecondRequestList(self): self.requestList2.show() def __disableSecondRequestList(self): self.requestList2.hide() def addRequest(self, name): self.requestsModel.beginInsertRows(QModelIndex(), self.requestsModel.rowCount(), self.requestsModel.rowCount()) item = QStandardItem(name) item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) item.setData(QVariant(Qt.Unchecked), Qt.CheckStateRole) self.requestsModel.appendRow(item) self.requestsModel.endInsertRows() self.requestsModel2.beginInsertRows(QModelIndex(), self.requestsModel2.rowCount(), self.requestsModel2.rowCount()) item = QStandardItem(name) item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) item.setData(QVariant(Qt.Unchecked), Qt.CheckStateRole) self.requestsModel2.appendRow(item) self.requestsModel2.endInsertRows() self.outputSetSelection.addItem(name) def removeSetAndDependencies(self, setName): removeList = [setName] for set in removeList: logging.info("Removing set '{}'.".format(set)) removeList.extend( [i for i in self.__removeSet(set) if i not in removeList]) logging.debug("LINE") def __removeSet(self, setName): dependencies = [] for op in self.__ops: op.removeSet(setName) if not op.isValid(): dependencies.append(op.name) for i in range(self.requestsModel.rowCount()): if self.requestsModel.item(i).text() == setName: self.requestsModel.beginRemoveRows(QModelIndex(), i, i) self.requestsModel.removeRow(i) self.requestsModel.endInsertRows() self.requestsModel2.beginRemoveRows(QModelIndex(), i, i) self.requestsModel2.removeRow(i) self.requestsModel2.endInsertRows() self.outputSetSelection.removeItem(i) break for op in self.__ops: if op.name == setName: self.resultingSets.model().removeOp(setName) self.__ops.remove(op) break SetNameManagement.releaseName(setName) return dependencies def reset(self): while len(self.ops) > 0: self.removeSetAndDependencies(self.ops[0].name) def cleanRequestList(self): for i in range(self.requestsModel.rowCount()): self.requestsModel.item(i).setData(QVariant(Qt.Unchecked), Qt.CheckStateRole) self.requestsModel2.item(i).setData(QVariant(Qt.Unchecked), Qt.CheckStateRole) def keyPressEvent(self, event): if event.key() == Qt.Key_Backspace and self.resultingSets.hasFocus(): advice = "Are you sure?\nAll sets containing this one will be deleted if they are no longer valid" reply = QMessageBox.question(self, "Remove request operation", advice) if reply == QMessageBox.Yes: select = self.resultingSets.selectionModel() while len(select.selectedRows()) > 0: self.removeSetAndDependencies( self.resultingSets.model().getOpByIndex( select.selectedRows()[0].row())) event.accept()
class DisambiguationWidget(QWidget): def __init__(self, getRequestFunction, setFiltersFunction, parent=None): super().__init__(parent) self.getRequestFunction = getRequestFunction self.setFiltersFunction = setFiltersFunction # LAYOUT self.layout = QFormLayout() self.layout.setContentsMargins(10, 10, 10, 10) self.layout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow) self.layout.setLabelAlignment(Qt.AlignLeft) self.layout.setFormAlignment(Qt.AlignLeft | Qt.AlignTop) # TYPE self.onlyDisconnectedCB = QCheckBox() self.onlyDisconnectedCB.setText("Only disconnected ways") self.columnSelection = QListView() self.columnSelection.setSpacing(3) self.columnSelection.setAutoFillBackground(True) self.columnSelection.setFrameStyle(QFrame.NoFrame) self.columnSelection.viewport().setAutoFillBackground(False) self.columnSelection.setFlow(QListView.LeftToRight) self.columnSelection.setWrapping(True) self.columnSelection.setResizeMode(QListView.Adjust) self.columnSelectionModel = QStandardItemModel() self.columnSelection.setModel(self.columnSelectionModel) self.applyButton = QPushButton("Apply") self.applyButton.clicked.connect(self.showTable) self.tableView = QTableView() self.tableView.doubleClicked.connect( lambda signal: self.setFiltersFunction( self.setSelection.currentText(), self.tableView.model().getDictDataFromCell(signal))) horizontalHeader = self.tableView.horizontalHeader() horizontalHeader.setSectionResizeMode(QHeaderView.ResizeToContents) horizontalHeader.setStretchLastSection(True) verticalHeader = self.tableView.verticalHeader() verticalHeader.sectionDoubleClicked.connect( lambda i: self.setFiltersFunction( self.setSelection.currentText(), self.tableView.model().getDictData(i))) self.tableView.setMinimumHeight(300) self.tableButtons = QWidget() tableButtonsLayout = QHBoxLayout() tableButtonsLayout.setAlignment(Qt.AlignRight) self.tableButtons.setLayout(tableButtonsLayout) tableButtonsLayout.setSpacing(0) tableButtonsLayout.setContentsMargins(0, 0, 0, 0) buttonMore = IconButton( QIcon(os.path.join(picturesDir, "showMore.png")), self.tableButtons.windowHandle(), self.tableButtons.height()) buttonMore.setToolTip("Show more") buttonMore.setFlat(True) buttonMore.clicked.connect(self.showMore) tableButtonsLayout.addWidget(buttonMore) buttonLess = IconButton( QIcon(os.path.join(picturesDir, "showLess.png")), self.tableButtons.windowHandle(), self.tableButtons.height()) buttonLess.setToolTip("Show less") buttonLess.setFlat(True) buttonLess.clicked.connect(self.showLess) tableButtonsLayout.addWidget(buttonLess) self.setSelection = QComboBox() self.setSelection.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum) self.layout.addRow("SET", self.setSelection) self.layout.addRow("TYPE", self.onlyDisconnectedCB) self.layout.addRow("KEYS", self.columnSelection) self.layout.addRow(self.applyButton) self.layout.addRow(self.tableView) self.layout.addRow(self.tableButtons) self.setLayout(self.layout) def showMore(self): if self.tableView.model() is not None: self.tableView.model().showMore() def showLess(self): if self.tableView.model() is not None: self.tableView.model().showLess() def addFilterFromCell(self, signal): key = self.tableView.model().headerData(signal.column(), Qt.Horizontal, Qt.DisplayRole) value = self.tableView.model().itemData(signal).get(0) return self.setFiltersFunction( self.setSelection.currentText(), ([OverpassFilter(key, TagComparison.EQUAL, value, False, True) ], [])) def showTable(self): request = self.getRequestFunction(self.setSelection.currentText()) if request is not None: query = OverpassQuery(request.name) query.addRequest(request) try: writeXMLResponse(query.getQL(), tableDir) except OverpassRequestException as e: logging.error(str(e)) return except OSError: logging.error( "There was a problem creating the file with the request response." ) return except RuntimeError as e: logging.error(str(e)) return except Exception: logging.error(traceback.format_exc()) return jsonResponse = ox.overpass_json_from_file(tableDir) if len(jsonResponse["elements"]) == 0: logging.warning("There are no elements to show in the table.") logging.debug("LINE") else: self.disconnectedWaysTable = DisconnectedWaysTable( jsonResponse) self.similarWaysTable = SimilarWaysTable(jsonResponse) self.showHideOnlyDisconnected() self.columnSelectionModel.clear() for key in self.similarWaysTable.getAllColumns(): self.columnSelectionModel.beginInsertRows( QModelIndex(), self.columnSelectionModel.rowCount(), self.columnSelectionModel.rowCount()) item = QStandardItem(key) self.columnSelectionModel.itemChanged.connect( self.updateColumns) item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) item.setData( QVariant(Qt.Checked if key in self.similarWaysTable. getSelectedColumns() else Qt.Unchecked), Qt.CheckStateRole) self.columnSelectionModel.appendRow(item) self.columnSelectionModel.endInsertRows() self.disconnectedWaysTable.updateColumns( self.similarWaysTable.getSelectedColumns()) self.onlyDisconnectedCB.stateChanged.connect( self.showHideOnlyDisconnected) logging.info("Showing table.") logging.debug("LINE") else: logging.warning( "There is no requests. It is not possible to show the table.") def updateColumns(self): self.disconnectedWaysTable.updateColumns(self.getSelectedKeys()) self.similarWaysTable.updateColumns(self.getSelectedKeys()) def getSelectedKeys(self): return [ self.columnSelectionModel.item(i).text() for i in range(self.columnSelectionModel.rowCount()) if self.columnSelectionModel.item(i).data(Qt.CheckStateRole) == QVariant(Qt.Checked) ] def getSelectedRowNetworkx(self): if self.tableView.model() is None: logging.warning("The table has not been created yet.") logging.debug("LINE") else: indexes = self.tableView.selectionModel().selectedRows() return self.tableView.model().getRowJson(indexes) def getHtmlFromSelectedRow(self): selectedRows = self.getSelectedRowNetworkx() if selectedRows: return buildHTMLWithNetworkx(selectedRows) else: raise RuntimeError("No row is selected") def showHideOnlyDisconnected(self): if self.onlyDisconnectedCB.isChecked(): self.tableView.setModel(self.disconnectedWaysTable) else: self.tableView.setModel(self.similarWaysTable) def showTableSelection(self): try: self.changePage( buildHTMLWithNetworkx(self.getSelectedRowNetworkx())) except (OverpassRequestException, OsmnxException) as e: logging.error(str(e)) logging.warning( "Before open NETEDIT you must run a query with the row filters applied." ) except ox.EmptyOverpassResponse: logging.error("There are no elements with the given row.") except OSError: logging.error( "There was a problem creating the file with the row selection." ) except Exception: logging.error(traceback.format_exc()) logging.debug("LINE") def addSet(self, setName): self.applyButton.setEnabled(True) self.setSelection.addItem(setName) def removeSet(self, setName): for i in range(self.setSelection.count()): if self.setSelection.itemText(i) == setName: self.setSelection.removeItem(i) break