class DataViewer(QDialog): def __init__(self, parent=None): super(DataViewer, self).__init__(parent) # Main window self.mainWindow = parent self.setWindowTitle("Extract Data") self.setMinimumWidth(400) # layout layout = QVBoxLayout(self) self.setLayout(layout) self.extractLayout = QFormLayout() layout.addLayout(self.extractLayout) # Extract key input self.input_extract = QLineEdit() self.input_extract.setFocus() self.input_extract.textChanged.connect(self.delayPreview) self.extractLayout.addRow("Key to extract:",self.input_extract) # Object ID key input self.input_id = QLineEdit() self.input_id.textChanged.connect(self.delayPreview) self.extractLayout.addRow("Key for Object ID:", self.input_id) # Options optionsLayout = QHBoxLayout() self.extractLayout.addRow(optionsLayout) self.allnodesCheckbox = QCheckBox("Select all nodes") self.allnodesCheckbox.setToolTip(wraptip("Check if you want to extract data for all nodes.")) self.allnodesCheckbox.setChecked(False) optionsLayout.addWidget(self.allnodesCheckbox) self.levelEdit=QSpinBox() self.levelEdit.setMinimum(1) self.levelEdit.setToolTip(wraptip("Based on the selected nodes, only extract data for nodes and subnodes of the specified level (base level is 1)")) self.levelEdit.valueChanged.connect(self.delayPreview) optionsLayout.addWidget(QLabel("Node level")) optionsLayout.addWidget(self.levelEdit) self.objecttypeEdit = QLineEdit("offcut") self.objecttypeEdit.setToolTip(wraptip("Skip nodes with these object types.")) self.objecttypeEdit.textChanged.connect(self.delayPreview) optionsLayout.addWidget(QLabel("Exclude object types")) optionsLayout.addWidget(self.objecttypeEdit) #self.extractLayout.addRow("Exclude object types", self.objecttypeEdit) # Preview toggle previewLayout = QHBoxLayout() layout.addLayout(previewLayout) self.togglePreviewCheckbox = QCheckBox() self.togglePreviewCheckbox .setCheckState(Qt.Checked) self.togglePreviewCheckbox.setToolTip(wraptip("Check to see a dumped preview of the value")) self.togglePreviewCheckbox.stateChanged.connect(self.showPreview) previewLayout.addWidget(self.togglePreviewCheckbox) self.previewTimer = QTimer() self.previewTimer.timeout.connect(self.showPreview) self.previewTimer.setSingleShot(True) self.togglePreviewLabel = QLabel("Preview") previewLayout.addWidget(self.togglePreviewLabel) previewLayout.addStretch() # Data self.dataEdit = QTextEdit(self) self.dataEdit.setReadOnly(True) self.dataEdit.setMinimumHeight(400) layout.addWidget(self.dataEdit) # Buttons buttons = QDialogButtonBox(QDialogButtonBox.Apply | QDialogButtonBox.Close) buttons.button(QDialogButtonBox.Apply).clicked.connect(self.createNodes) buttons.button(QDialogButtonBox.Close).clicked.connect(self.close) layout.addWidget(buttons) def showValue(self, key = ''): self.input_extract.setText(key) #self.input_id.setText(key) self.allnodesCheckbox.setChecked(self.mainWindow.allnodesCheckbox.isChecked()) self.levelEdit.setValue(self.mainWindow.levelEdit.value()) self.objecttypeEdit.setText(self.mainWindow.typesEdit.text()) self.show() self.raise_() @Slot() def delayPreview(self): self.previewTimer.stop() self.previewTimer.start(500) def updateNode(self, current): self.delayPreview() if current.isValid(): level = current.model().getLevel(current) + 1 self.levelEdit.setValue(level) @Slot() def showPreview(self): if self.togglePreviewCheckbox.isChecked(): try: # Get nodes key_nodes = self.input_extract.text() subkey = key_nodes.split('|').pop(0).rsplit('.', 1)[0] key_id = self.input_id.text() #selected = self.mainWindow.tree.selectionModel().selectedRows() objecttypes = self.objecttypeEdit.text().replace(' ', '').split(',') level = self.levelEdit.value() - 1 conditions = {'filter': {'level': level, '!objecttype': objecttypes}} selected = self.mainWindow.tree.selectedIndexesAndChildren(conditions) nodes = [] for item in selected: if not item.isValid(): continue treenode = item.internalPointer() dbnode = treenode.dbnode() if dbnode is not None: name, nodes = extractValue(dbnode.response, key_nodes, dump=False) break # Dump nodes value = [] nodes = [nodes] if not (type(nodes) is list) else nodes for n in nodes: nodedata = json.dumps(n) if isinstance(n, Mapping) else n n = n if isinstance(n, Mapping) else {subkey: n} objectid = extractValue(n, key_id, default=None)[1] if key_id != '' else '' value.append((str(objectid), str(nodedata))) except Exception as e: value = [('',str(e))] value = ['<b>{}</b><p>{}</p><hr>'.format(html.escape(x),html.escape(y)) for x,y in value] value = "\n\n".join(value) self.dataEdit.setHtml(value) self.dataEdit.setVisible(self.togglePreviewCheckbox.isChecked()) if not self.togglePreviewCheckbox.isChecked(): self.adjustSize() self.show() def initProgress(self): self.progressBar = ProgressBar("Extracting data...", self.mainWindow) self.progressTotal = None self.progressLevel = None self.progressUpdate = datetime.now() def updateProgress(self,current, total, level=0): if datetime.now() >= self.progressUpdate: if (self.progressLevel is None) or (level < self.progressLevel): self.progressLevel = level self.progressTotal = total if (level == self.progressLevel) or (total > self.progressTotal): self.progressBar.setMaximum(total) self.progressBar.setValue(current) self.progressUpdate = datetime.now() + timedelta(milliseconds=50) QApplication.processEvents() return not self.progressBar.wasCanceled def finishProgress(self): self.progressBar.close() @Slot() def createNodes(self): key_nodes = self.input_extract.text() key_objectid = self.input_id.text() if key_nodes == '': return False if key_objectid == '': key_objectid = None try: self.initProgress() objecttypes = self.objecttypeEdit.text().replace(' ', '').split(',') level = self.levelEdit.value() - 1 allnodes = self.allnodesCheckbox.isChecked() conditions = {'filter': {'level': level, '!objecttype': objecttypes}, 'selectall': allnodes} selected = self.mainWindow.tree.selectedIndexesAndChildren(conditions, self.updateProgress) for item in selected: if self.progressBar.wasCanceled: break if not item.isValid(): continue treenode = item.internalPointer() treenode.unpackList(key_nodes, key_objectid, delaycommit=True) except Exception as e: self.mainWindow.logmessage(e) finally: self.mainWindow.tree.treemodel.commitNewNodes() self.finishProgress() #self.close() return True
class TransferNodes(QDialog): def __init__(self, parent=None): super(TransferNodes, self).__init__(parent) # Main window self.mainWindow = parent self.setWindowTitle("Add selected nodes as seed nodes") #self.setMinimumWidth(400) # layout layout = QVBoxLayout(self) self.setLayout(layout) self.extractLayout = QFormLayout() layout.addLayout(self.extractLayout) # Options self.allnodesCheckbox = QCheckBox("Select all nodes") self.allnodesCheckbox.setToolTip(wraptip("Check if you want to transfer all nodes.")) self.allnodesCheckbox.setChecked(False) self.extractLayout.addRow("Nodes", self.allnodesCheckbox) self.levelEdit=QSpinBox() self.levelEdit.setMinimum(1) self.levelEdit.setToolTip(wraptip("Based on the selected nodes, only subnodes of the specified level are processed (base level is 1)")) self.extractLayout.addRow("Node level", self.levelEdit) self.objecttypeEdit = QLineEdit("offcut") self.objecttypeEdit.setToolTip(wraptip("Skip nodes with these object types.")) self.extractLayout.addRow("Exclude object types", self.objecttypeEdit) # Buttons buttons = QDialogButtonBox(QDialogButtonBox.Apply | QDialogButtonBox.Close) buttons.button(QDialogButtonBox.Apply).clicked.connect(self.createNodes) buttons.button(QDialogButtonBox.Close).clicked.connect(self.close) layout.addWidget(buttons) def show(self): self.allnodesCheckbox.setChecked(self.mainWindow.allnodesCheckbox.isChecked()) self.levelEdit.setValue(self.mainWindow.levelEdit.value()) self.objecttypeEdit.setText(self.mainWindow.typesEdit.text()) super(TransferNodes, self).show() self.raise_() def updateNode(self, current): if current.isValid(): level = current.model().getLevel(current) + 1 self.levelEdit.setValue(level) def initProgress(self): self.progressBar = ProgressBar("Transferring nodes...", self.mainWindow) self.progressTotal = None self.progressLevel = None self.progressUpdate = datetime.now() def updateProgress(self,current, total, level=0): if datetime.now() >= self.progressUpdate: if (self.progressLevel is None) or (level < self.progressLevel): self.progressLevel = level self.progressTotal = total if (level == self.progressLevel) or (total > self.progressTotal): self.progressBar.setMaximum(total) self.progressBar.setValue(current) self.progressUpdate = datetime.now() + timedelta(milliseconds=50) QApplication.processEvents() return not self.progressBar.wasCanceled def finishProgress(self): self.progressBar.close() @Slot() def createNodes(self): try: self.initProgress() # Get list of seed nodes to avoid duplicates seednodes = Node.query.filter(Node.parent_id == None).add_columns('objectid') seednodes = [node.objectid for node in seednodes] # Iterate nodes objecttypes = self.objecttypeEdit.text().replace(' ', '').split(',') level = self.levelEdit.value() - 1 allnodes = self.allnodesCheckbox.isChecked() conditions = {'filter': {'level': level, '!objecttype': objecttypes}, 'selectall': allnodes} selected = self.mainWindow.tree.selectedIndexesAndChildren(conditions, self.updateProgress) nodes_new = 0 nodes_dupl = 0 for item in selected: if self.progressBar.wasCanceled: break if not item.isValid(): continue treenode = item.internalPointer() objectid = treenode.data.get("objectid") # no duplicates if not objectid in seednodes: seednodes.append(objectid) treenode.copyNode(delaycommit=True) nodes_new += 1 else: nodes_dupl += 1 self.mainWindow.tree.treemodel.commitNewNodes() self.mainWindow.tree.selectLastRow() self.mainWindow.logmessage(f"{nodes_new} nodes added as seed nodes. {nodes_dupl} duplicate nodes skipped.") self.close() except Exception as e: self.mainWindow.logmessage(e) finally: self.mainWindow.tree.treemodel.commitNewNodes() self.finishProgress() #self.close() return True