class VfsDirWidget(QWidget): def __init__(self, vfs_view, *args, **kwargs): QWidget.__init__(self, *args, **kwargs) self.vnode_2click_selected = None # Getting the Model self.source_model = VfsDirModel() # Creating a QTableView self.view = QTreeView() self.view.doubleClicked.connect(self.double_clicked) self.view.clicked.connect(self.clicked) self.view.setSelectionBehavior(QAbstractItemView.SelectRows) self.view.setSelectionMode(QAbstractItemView.ExtendedSelection) font = self.view.font() font.setPointSize(8) self.view.setFont(font) self.view.setModel(self.source_model) # # QTableView Headers self.header = self.view.header() self.header.setSectionResizeMode(QHeaderView.ResizeToContents) self.header.setStretchLastSection(True) size = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) size.setHorizontalStretch(1) self.view.setSizePolicy(size) self.main_layout = QHBoxLayout() self.main_layout.addWidget(self.view) self.setLayout(self.main_layout) self.source_model.vfs_view_set(vfs_view) def vfs_view_get(self): return self.source_model.vfs_view_get() def clicked(self, index): if index.isValid(): if self.source_model.vfs_view is not None: items = self.view.selectedIndexes() items = list(set([idx.internalPointer() for idx in items])) items = [ idx.v_path() for idx in items if isinstance(idx, VfsDirLeaf) or isinstance(idx, VfsDirBranch) ] self.source_model.vfs_view.paths_set(items) def double_clicked(self, index): if index.isValid(): tnode = index.internalPointer() if isinstance( tnode, VfsDirLeaf) and self.vnode_2click_selected is not None: self.vnode_2click_selected(tnode.uids_hard)
class MyWidget(QtWidgets.QWidget): @Slot() def run_report(self): dialog = ReportNameDialog() if dialog.exec_(): metadata_fields = {} item_model = self.list.model() for i in range(item_model.rowCount()): qmodel_index = item_model.index(i, 0) index_name = item_model.item(i, 0).text() if item_model.itemData(qmodel_index).get(10) == 2: metadata_fields[index_name] = "" if hasattr(item_model.item(i, 1), "text"): index_value = item_model.item(i, 1).text() if index_name == DOCUMENT_TYPE: if index_value == TYPE_ASSET: index_value = "IO" if index_value == TYPE_FOLDER: index_value = "SO" if index_value == TYPE_ANY: index_value = "" metadata_fields[index_name] = index_value self.progress = QProgressDialog( "Creating Report\n\nPlease Wait...", None, 0, 100) self.progress.setModal(True) self.progress.setWindowTitle("Report") self.progress.setAutoClose(True) self.progress.setAutoReset(True) self.callback = CallBack() worker = Worker(self.client, self.search_value.text(), dialog.report(), metadata_fields, self.callback, dialog.auto_report()) self.callback.change_value.connect(self.progress.setValue) self.callback.max_value.connect(self.progress.setMaximum) self.callback.reset_dialog.connect(self.progress.reset) self.threadpool.start(worker) self.progress.show() def __init__(self): super().__init__() self.threadpool = QThreadPool() self.threadpool.setMaxThreadCount(1) self.setWindowTitle("Preservica Solr Reporting") self.windowModality() self.progress = None self.callback = None self.search_label = QtWidgets.QLabel( "Main Search Term (% returns everything)") self.search_value = QtWidgets.QLineEdit("%") self.help_label = QtWidgets.QLabel( "Select from the list of indexed fields below to " "add columns to the output spreadsheet\n\n" "Indexes can have an optional filter term. Filters " "are only applied to selected fields") self.list = QTreeView() self.list.setSelectionBehavior(QAbstractItemView.SelectRows) model = QStandardItemModel() model.setHorizontalHeaderLabels(['Index Name', 'Index Filter Term']) self.list.setModel(model) self.list.setUniformRowHeights(True) self.list.setAlternatingRowColors(True) self.list.setColumnWidth(0, 350) self.list.setColumnWidth(1, 250) self.list.setItemDelegateForColumn( 1, ComboDelegate(self.list, DOCUMENT_TYPE, model)) if not os.path.isfile("credentials.properties"): dialog = PasswordDialog() if dialog.exec_(): self.client = ContentAPI(dialog.username(), dialog.password(), dialog.tenant(), dialog.server()) else: raise SystemExit else: self.client = ContentAPI() for index_name in self.client.indexed_fields(): if index_name == "xip.full_text": continue index = QStandardItem(index_name) index.setCheckable(True) index.setEditable(False) model.appendRow([index]) self.run_report_button = QtWidgets.QPushButton("Run Report") self.run_report_button.released.connect(self.run_report) self.list.setModel(model) self.layout = QtWidgets.QVBoxLayout() self.layout.addWidget(self.search_label) self.layout.addWidget(self.search_value) self.layout.addWidget(self.help_label) self.layout.addWidget(self.list) self.layout.addWidget(self.run_report_button) self.setLayout(self.layout)
class SearchReplaceDialog(QDialog): """Search & Replace window """ def __init__(self, parent, initial_query=None): """Initialize the search window """ super(SearchReplaceDialog, self).__init__(parent) self.parent = parent self.prefs = parent.prefs self.items_checked = 0 self.search_button = QPushButton('Search') self.search_text = MySearchField(self.search_button) self.search_text.setPlaceholderText("Enter search query here") self.search_button.clicked.connect(self.submit_search) input_layout = QHBoxLayout() input_layout.addWidget(self.search_text) input_layout.addWidget(self.search_button) self.results_tree = QTreeView() self.results_tree.setRootIsDecorated(False) self.results_tree.setAlternatingRowColors(True) self.results_tree.setAllColumnsShowFocus(True) self.results_tree.setSelectionBehavior(QAbstractItemView.SelectRows) self.results_tree.setSelectionMode(QAbstractItemView.SingleSelection) self.results_tree.doubleClicked.connect(self.go_to_object) self.whole_field_checkbox = QCheckBox("Whole Field Only", self) self.advanced_search_checkbox = QCheckBox("Advanced Search", self) self.advanced_search_checkbox.stateChanged.connect( self.advanced_search_checked) self.ignore_geometry_checkbox = QCheckBox("Ignore Geometry", self) self.go_button = QPushButton('Go') self.go_button.clicked.connect(self.go_to_object) checks_layout = QHBoxLayout() checks_layout.addWidget(self.whole_field_checkbox) checks_layout.addWidget(self.advanced_search_checkbox) checks_layout.addWidget(self.ignore_geometry_checkbox) checks_layout.addStretch() checks_layout.addWidget(self.go_button) self.query_label = QLabel("Query:") self.query_label.setEnabled(False) self.query_text = QLineEdit() self.query_text.setEnabled(True) self.query_text.setReadOnly(True) self.query_text.setFrame(False) self.query_text.setStyleSheet("""QLineEdit { background-color: LightGray; color: white; } """) query_layout = QHBoxLayout() query_layout.addWidget(self.query_label) query_layout.addWidget(self.query_text) self.select_label = QLabel("Select:") self.select_all_button = QPushButton("All") self.select_none_button = QPushButton("None") self.select_invert_button = QPushButton("Invert") self.delete_button = QPushButton("Delete Objects") self.select_all_button.clicked.connect(self.select_all_clicked) self.select_none_button.clicked.connect(self.select_none_clicked) self.select_invert_button.clicked.connect(self.select_invert_clicked) self.delete_button.clicked.connect(self.delete_button_clicked) self.delete_button.setEnabled(False) selection_layout = QHBoxLayout() selection_layout.addWidget(self.select_label) selection_layout.addWidget(self.select_all_button) selection_layout.addWidget(self.select_none_button) selection_layout.addWidget(self.select_invert_button) selection_layout.addStretch() selection_layout.addWidget(self.delete_button) self.replace_with_text = QLineEdit() self.replace_with_label = QLabel("Replace With:") self.replace_button = QPushButton("Replace") self.replace_button.clicked.connect(self.replace_button_clicked) self.replace_button.setEnabled(False) replace_layout = QHBoxLayout() replace_layout.addWidget(self.replace_with_label) replace_layout.addWidget(self.replace_with_text) replace_layout.addWidget(self.replace_button) layout = QVBoxLayout() layout.addLayout(input_layout) layout.addLayout(checks_layout) layout.addLayout(query_layout) layout.addWidget(self.results_tree) layout.addLayout(selection_layout) layout.addLayout(replace_layout) self.resize(650, 450) self.setLayout(layout) self.setWindowTitle("IDF+ Search & Replace") self.search_text.setFocus() self.setTabOrder(self.search_text, self.search_button) self.setTabOrder(self.search_button, self.whole_field_checkbox) self.setTabOrder(self.whole_field_checkbox, self.advanced_search_checkbox) self.setTabOrder(self.advanced_search_checkbox, self.select_all_button) self.setTabOrder(self.select_all_button, self.select_none_button) self.setTabOrder(self.select_none_button, self.select_invert_button) self.setTabOrder(self.select_invert_button, self.replace_with_text) self.setTabOrder(self.replace_with_text, self.replace_button) self.setTabOrder(self.replace_button, self.search_text) self.results_tree.setModel(self.create_results_model([])) self.results_tree.setColumnHidden(2, True) if initial_query is not None: self.search_text.setText(initial_query) self.search_button.click() def create_results_model(self, results): def add_result_row(row_model, value, obj_class, uuid): row_model.insertRow(0) row_model.setData(model.index(0, 0), value) row_model.setData(model.index(0, 1), obj_class) row_model.setData(model.index(0, 2), uuid) item_0 = model.itemFromIndex(model.index(0, 0)) item_0.setCheckState(Qt.Unchecked) item_0.setFlags(item_0.flags() | Qt.ItemIsUserCheckable) item_0.setEditable(False) item_1 = model.itemFromIndex(model.index(0, 1)) item_1.setEditable(False) model = QStandardItemModel(0, 3, self) model.setHeaderData(0, Qt.Horizontal, "Value") model.setHeaderData(1, Qt.Horizontal, "Class") model.setHeaderData(2, Qt.Horizontal, "UUID") for hit in results: add_result_row(model, hit['value'], hit['obj_class_display'], hit['uuid']) return model def submit_search(self): """Submits a search based on the current query """ user_query = self.search_text.text() idf = self.parent.idf if not user_query or len(user_query) < 2 or not idf: return [], "" results, my_query = idf.search( user_query, self.whole_field_checkbox.isChecked(), self.advanced_search_checkbox.isChecked(), self.ignore_geometry_checkbox.isChecked()) self.query_text.setText(str(my_query)) self.results_tree.setModel(self.create_results_model(results)) self.results_tree.model().itemChanged.connect(self.item_checked) # self.results_tree.setColumnHidden(2, True) self.results_tree.resizeColumnToContents(0) self.results_tree.resizeColumnToContents(1) self.results_tree.setSortingEnabled(True) def item_checked(self, item): if item.checkState() == Qt.Checked: self.items_checked += 1 else: self.items_checked -= 1 if self.items_checked > 0: self.delete_button.setEnabled(True) self.replace_button.setEnabled(True) else: self.delete_button.setEnabled(False) self.replace_button.setEnabled(False) def select_all_clicked(self): model = self.results_tree.model() result_count = model.rowCount() for i in range(result_count): model.itemFromIndex(model.index(i, 0)).setCheckState(Qt.Checked) def select_none_clicked(self): model = self.results_tree.model() result_count = model.rowCount() for i in range(result_count): model.itemFromIndex(model.index(i, 0)).setCheckState(Qt.Unchecked) def select_invert_clicked(self): model = self.results_tree.model() result_count = model.rowCount() for i in range(result_count): item = model.itemFromIndex(model.index(i, 0)) if item.checkState() == Qt.Checked: new_state = Qt.Unchecked else: new_state = Qt.Checked item.setCheckState(new_state) def delete_button_clicked(self): model = self.results_tree.model() result_count = model.rowCount() if result_count <= 0 or self.items_checked <= 0: return question = "Are you sure you want to perform this deletion?\n" \ "Undo is currently NOT supported for this operation." response = self.confirm_action(question) if response is not True: return for i in range(result_count): item_0 = model.itemFromIndex(model.index(i, 0)) item_2 = model.itemFromIndex(model.index(i, 2)) if item_0.checkState() != Qt.Checked: continue field = self.parent.idf.field_by_uuid(item_2.text()) obj = field._outer obj_class = self.parent.idf.idf_objects(obj.obj_class) try: index = obj_class.index(obj) self.parent.idf.remove_objects(obj.obj_class, index, index + 1) except ValueError: pass # already deleted self.parent.set_dirty(True) self.submit_search() self.parent.load_table_view(self.parent.current_obj_class) QMessageBox.information(self, "Delete Action", "Deletion Complete!") def advanced_search_checked(self): if self.advanced_search_checkbox.isChecked(): self.whole_field_checkbox.setEnabled(False) self.whole_field_checkbox.setChecked(True) self.ignore_geometry_checkbox.setEnabled(False) self.ignore_geometry_checkbox.setChecked(False) else: self.whole_field_checkbox.setEnabled(True) self.whole_field_checkbox.setChecked(False) self.ignore_geometry_checkbox.setEnabled(True) self.ignore_geometry_checkbox.setChecked(False) def replace_button_clicked(self): search_text = self.search_text.text() replace_with_text = self.replace_with_text.text() if not search_text: return model = self.results_tree.model() result_count = model.rowCount() if result_count <= 0 or self.items_checked <= 0: return question = "Are you sure you want to perform this replacement?\n" \ "Undo is currently NOT supported for this operation." response = self.confirm_action(question) if response is not True: return for i in range(result_count): item_0 = model.itemFromIndex(model.index(i, 0)) item_2 = model.itemFromIndex(model.index(i, 2)) if item_0.checkState() != Qt.Checked: continue field = self.parent.idf.field_by_uuid(item_2.text()) if self.whole_field_checkbox.isChecked( ) or self.advanced_search_checkbox.isChecked(): field.value = replace_with_text else: regex = re.compile(re.escape(search_text), re.IGNORECASE) field.value = regex.sub(replace_with_text, field.value) self.parent.set_dirty(True) self.submit_search() self.parent.load_table_view(self.parent.current_obj_class) QMessageBox.information(self, "Replacement", "Replacement Complete!") def confirm_action(self, question): """Confirm user wants to perform action """ flags = QMessageBox.StandardButton.Yes flags |= QMessageBox.StandardButton.No response = QMessageBox.question(self, "Are you sure?", question, flags) if response == QMessageBox.Yes: return True elif QMessageBox.No: return False else: return False def go_to_object(self, index=None): if index is None: selected = self.results_tree.selectedIndexes() if not selected: return index = selected[0] model = self.results_tree.model() item = model.itemFromIndex(model.index(index.row(), 2)) field = self.parent.idf.field_by_uuid(item.text()) self.parent.activateWindow() self.parent.jump_to_field(field)