add a search bar that could locate an element in one of the QTreeViews
-
I have several tree views in a scroll area. When I search for a word I want that it directs me to this word. So I want a search that automatically scrolls to the item I'm looking for, even if it's further down.
this is my code :
from PyQt5.QtWidgets import * from PyQt5.QtCore import * from PyQt5.QtGui import * from table_view import * from odl_parser import ODLParser class StartWindow(QDialog): def __init__(self, parent=None): super().__init__(parent) self.setWindowTitle('Open ODL File or Folder') self.resize(600, 400) main_layout = QHBoxLayout(self) self.image_label = QLabel(self) self.image_label.setPixmap(QPixmap('ACLViewer.jpg').scaled(300, 300, Qt.KeepAspectRatio)) main_layout.addWidget(self.image_label) buttons_layout = QVBoxLayout() self.choose_file_button = QPushButton('Choose File', self) self.choose_file_button.clicked.connect(self.choose_file) buttons_layout.addWidget(self.choose_file_button) self.choose_folder_button = QPushButton('Choose Folder', self) self.choose_folder_button.clicked.connect(self.choose_folder) buttons_layout.addWidget(self.choose_folder_button) main_layout.addLayout(buttons_layout) self.first_tree_configured = False def choose_file(self): file_path, _ = QFileDialog.getOpenFileName(self, "Open ODL File", "", "ODL Files (*.odl)") if file_path: self.open_table_view(file_path) def choose_folder(self): folder_path = QFileDialog.getExistingDirectory(self, "Open Folder Containing ODL Files") if folder_path: self.open_folder_view(folder_path) def open_table_view(self, file_path): parser = ODLParser(file_path) window = Table(parser) window.setWindowTitle('DM Parsing - ' + file_path) window.show() def open_folder_view(self, folder_path): folder_window = QDialog(self) folder_window.setWindowTitle('ODL Files Tree View') folder_window.resize(800, 600) layout = QVBoxLayout(folder_window) self.group_combobox = QComboBox() self.group_combobox.setStyleSheet(""" border: 1px solid gray; border-radius: 3px; padding: 1px 18px 1px 3px; min-width: 6em; """) self.group_combobox.setMaximumWidth(340) layout.addWidget(self.group_combobox) self.tables = [] self.save_button = QPushButton("Save", folder_window) self.save_button.setStyleSheet(""" border: 2px solid #8f8f91; border-radius: 6px; background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #f6f7fa, stop: 1 #dadbde); min-width: 80px; """) #self.save_button.clicked.connect(self.save_acl_changes) self.reset_button = QPushButton("Reset", folder_window) self.reset_button.setStyleSheet(""" border: 2px solid #8f8f91; border-radius: 6px; background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #f6f7fa, stop: 1 #dadbde); min-width: 80px; """) self.reset_button.clicked.connect(self.reset_acl_changes) buttons_layout = QHBoxLayout() buttons_layout.addWidget(self.group_combobox) buttons_layout.addWidget(self.save_button) buttons_layout.addWidget(self.reset_button) self.search_bar = QLineEdit() self.search_bar.setStyleSheet(""" border: 2px solid gray; border-radius: 5px; padding: 0 8px; background: lightblue; selection-background-color: gray; """) self.search_bar.setPlaceholderText("Search...") layout.addWidget(self.search_bar) self.search_bar.textChanged.connect(self.**search_tree**) layout.addLayout(buttons_layout) scroll_area = QScrollArea(folder_window) scroll_area.setWidgetResizable(True) scroll_widget = QWidget() scroll_layout = QVBoxLayout(scroll_widget) import os processed_files = set() all_groups = set() for root, dirs, files in os.walk(folder_path): for filename in files: if ('acl' in filename.lower() or 'acls' in filename.lower()) and filename not in processed_files: file_path = os.path.join(root, filename) parser = ODLParser(file_path) file_groups, _ = get_headers_and_rights(parser.data_model) all_groups.update(file_groups) tree_view = self.create_tree_view(parser) scroll_layout.addWidget(tree_view) processed_files.add(filename) self.group_combobox.addItems(sorted(all_groups)) self.group_combobox.setCurrentIndex(0) self.group_combobox.currentTextChanged.connect(self.on_group_combobox_changed) QTimer.singleShot(0, lambda: self.on_group_combobox_changed(self.group_combobox.currentText())) scroll_area.setWidget(scroll_widget) layout.addWidget(scroll_area) folder_window.exec_() def reset_acl_changes(self): selected_group = self.group_combobox.currentText() for table in self.tables: table.reset_acl_changes(selected_group) table.tree.expandAll() def **search_tree**(self, text): for table in self.tables: found_items = table.tree.model().findItems(text, Qt.MatchContains | Qt.MatchRecursive) for item in found_items: index = table.tree.model().indexFromItem(item) table.tree.expand(index) table.tree.scrollTo(index) table.tree.setCurrentIndex(index) def on_group_combobox_changed(self, selected_group): for table in self.tables: table.update_access_rights(selected_group) table.tree.expandAll() def create_tree_view(self, parser): window = Table(parser) tree_view = window.tree window.is_first_tree = not self.first_tree_configured if not self.first_tree_configured: self.configure_tree_view(tree_view) self.first_tree_configured = True else: self.configure_tree_view2(tree_view) tree_view.expandAll() height = 0 for i in range(tree_view.model().rowCount()): index = tree_view.model().index(i, 0) height += tree_view.rowHeight(index) * self.count_visible_nodes(index) height += tree_view.header().height() tree_view.setFixedHeight(height) self.tables.append(window) return tree_view def configure_tree_view(self, tree_view): tree_view.setColumnWidth(0, 430) tree_view.setColumnWidth(1, 100) tree_view.header().setStretchLastSection(True) def configure_tree_view2(self, tree_view): self.configure_tree_view(tree_view) tree_view.header().hide() def count_visible_nodes(self, index, model=None): if not index.isValid(): return 0 if model is None: model = index.model() count = 1 if index.model().hasChildren(index): for row in range(model.rowCount(index)): child_index = model.index(row, 0, index) count += self.count_visible_nodes(child_index, model) return count
I've tried the search_tree function but it didn't direct me to the word I'm looking for.
Can any one help me ?
-
@JonB I have other treeviews above, the word I gave you exists in the last treeview, that's why I want to make a function that shows me the place of the word that I searched
@sof4Rou
I don't understand. If you are talking about scrolling within one treeview which contains a word your code should work and the item is shown in that treeview in your screenshot. If you are talking about needing to scroll the multiple treeviews to get to one containing the word that is a totally different scroll on a different object and I don't know if that is what you mean. If that is the case you need to scroll your desired widget into view in whatever the enclosing scroll area is.QScrollArea::ensureWidgetVisible(QWidget *childWidget, int xmargin = 50, int ymargin = 50), is that what you asking about?
-
I have several tree views in a scroll area. When I search for a word I want that it directs me to this word. So I want a search that automatically scrolls to the item I'm looking for, even if it's further down.
this is my code :
from PyQt5.QtWidgets import * from PyQt5.QtCore import * from PyQt5.QtGui import * from table_view import * from odl_parser import ODLParser class StartWindow(QDialog): def __init__(self, parent=None): super().__init__(parent) self.setWindowTitle('Open ODL File or Folder') self.resize(600, 400) main_layout = QHBoxLayout(self) self.image_label = QLabel(self) self.image_label.setPixmap(QPixmap('ACLViewer.jpg').scaled(300, 300, Qt.KeepAspectRatio)) main_layout.addWidget(self.image_label) buttons_layout = QVBoxLayout() self.choose_file_button = QPushButton('Choose File', self) self.choose_file_button.clicked.connect(self.choose_file) buttons_layout.addWidget(self.choose_file_button) self.choose_folder_button = QPushButton('Choose Folder', self) self.choose_folder_button.clicked.connect(self.choose_folder) buttons_layout.addWidget(self.choose_folder_button) main_layout.addLayout(buttons_layout) self.first_tree_configured = False def choose_file(self): file_path, _ = QFileDialog.getOpenFileName(self, "Open ODL File", "", "ODL Files (*.odl)") if file_path: self.open_table_view(file_path) def choose_folder(self): folder_path = QFileDialog.getExistingDirectory(self, "Open Folder Containing ODL Files") if folder_path: self.open_folder_view(folder_path) def open_table_view(self, file_path): parser = ODLParser(file_path) window = Table(parser) window.setWindowTitle('DM Parsing - ' + file_path) window.show() def open_folder_view(self, folder_path): folder_window = QDialog(self) folder_window.setWindowTitle('ODL Files Tree View') folder_window.resize(800, 600) layout = QVBoxLayout(folder_window) self.group_combobox = QComboBox() self.group_combobox.setStyleSheet(""" border: 1px solid gray; border-radius: 3px; padding: 1px 18px 1px 3px; min-width: 6em; """) self.group_combobox.setMaximumWidth(340) layout.addWidget(self.group_combobox) self.tables = [] self.save_button = QPushButton("Save", folder_window) self.save_button.setStyleSheet(""" border: 2px solid #8f8f91; border-radius: 6px; background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #f6f7fa, stop: 1 #dadbde); min-width: 80px; """) #self.save_button.clicked.connect(self.save_acl_changes) self.reset_button = QPushButton("Reset", folder_window) self.reset_button.setStyleSheet(""" border: 2px solid #8f8f91; border-radius: 6px; background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #f6f7fa, stop: 1 #dadbde); min-width: 80px; """) self.reset_button.clicked.connect(self.reset_acl_changes) buttons_layout = QHBoxLayout() buttons_layout.addWidget(self.group_combobox) buttons_layout.addWidget(self.save_button) buttons_layout.addWidget(self.reset_button) self.search_bar = QLineEdit() self.search_bar.setStyleSheet(""" border: 2px solid gray; border-radius: 5px; padding: 0 8px; background: lightblue; selection-background-color: gray; """) self.search_bar.setPlaceholderText("Search...") layout.addWidget(self.search_bar) self.search_bar.textChanged.connect(self.**search_tree**) layout.addLayout(buttons_layout) scroll_area = QScrollArea(folder_window) scroll_area.setWidgetResizable(True) scroll_widget = QWidget() scroll_layout = QVBoxLayout(scroll_widget) import os processed_files = set() all_groups = set() for root, dirs, files in os.walk(folder_path): for filename in files: if ('acl' in filename.lower() or 'acls' in filename.lower()) and filename not in processed_files: file_path = os.path.join(root, filename) parser = ODLParser(file_path) file_groups, _ = get_headers_and_rights(parser.data_model) all_groups.update(file_groups) tree_view = self.create_tree_view(parser) scroll_layout.addWidget(tree_view) processed_files.add(filename) self.group_combobox.addItems(sorted(all_groups)) self.group_combobox.setCurrentIndex(0) self.group_combobox.currentTextChanged.connect(self.on_group_combobox_changed) QTimer.singleShot(0, lambda: self.on_group_combobox_changed(self.group_combobox.currentText())) scroll_area.setWidget(scroll_widget) layout.addWidget(scroll_area) folder_window.exec_() def reset_acl_changes(self): selected_group = self.group_combobox.currentText() for table in self.tables: table.reset_acl_changes(selected_group) table.tree.expandAll() def **search_tree**(self, text): for table in self.tables: found_items = table.tree.model().findItems(text, Qt.MatchContains | Qt.MatchRecursive) for item in found_items: index = table.tree.model().indexFromItem(item) table.tree.expand(index) table.tree.scrollTo(index) table.tree.setCurrentIndex(index) def on_group_combobox_changed(self, selected_group): for table in self.tables: table.update_access_rights(selected_group) table.tree.expandAll() def create_tree_view(self, parser): window = Table(parser) tree_view = window.tree window.is_first_tree = not self.first_tree_configured if not self.first_tree_configured: self.configure_tree_view(tree_view) self.first_tree_configured = True else: self.configure_tree_view2(tree_view) tree_view.expandAll() height = 0 for i in range(tree_view.model().rowCount()): index = tree_view.model().index(i, 0) height += tree_view.rowHeight(index) * self.count_visible_nodes(index) height += tree_view.header().height() tree_view.setFixedHeight(height) self.tables.append(window) return tree_view def configure_tree_view(self, tree_view): tree_view.setColumnWidth(0, 430) tree_view.setColumnWidth(1, 100) tree_view.header().setStretchLastSection(True) def configure_tree_view2(self, tree_view): self.configure_tree_view(tree_view) tree_view.header().hide() def count_visible_nodes(self, index, model=None): if not index.isValid(): return 0 if model is None: model = index.model() count = 1 if index.model().hasChildren(index): for row in range(model.rowCount(index)): child_index = model.index(row, 0, index) count += self.count_visible_nodes(child_index, model) return count
I've tried the search_tree function but it didn't direct me to the word I'm looking for.
Can any one help me ?
@sof4Rou said in add a search bar that could locate an element in one of the QTreeViews:
but it didn't direct me to the word I'm looking for.
What did it do? Anything? Nothing? Were any matching items found? Did it not scroll to the last occurrence of the string?
If you don't get an answer I suggest you provide a minimal (i.e. much, much smaller than this), self-contained sample.
-
@sof4Rou said in add a search bar that could locate an element in one of the QTreeViews:
but it didn't direct me to the word I'm looking for.
What did it do? Anything? Nothing? Were any matching items found? Did it not scroll to the last occurrence of the string?
If you don't get an answer I suggest you provide a minimal (i.e. much, much smaller than this), self-contained sample.
-
@sof4Rou said in add a search bar that could locate an element in one of the QTreeViews:
but it didn't direct me to the word I'm looking for.
What did it do? Anything? Nothing? Were any matching items found? Did it not scroll to the last occurrence of the string?
If you don't get an answer I suggest you provide a minimal (i.e. much, much smaller than this), self-contained sample.
-
@JonB
for example here, when I search for the item "sah" , the scroll area does not go down and show me the word@sof4Rou
That word is at the top of the treeview, so I don't see there is anything to "scroll to", and your screenshot looks fine, it is showing you the word.In any case: get rid of all your code. Create a single
QTreeView
with a model. The only part of your code you are asking about istable.tree.expand(index) table.tree.scrollTo(index) table.tree.setCurrentIndex(index)
So test that behaviour on increasing row number in
index
to make sure it scrolls as you want. Then add any "searching" back in. -
@sof4Rou
That word is at the top of the treeview, so I don't see there is anything to "scroll to", and your screenshot looks fine, it is showing you the word.In any case: get rid of all your code. Create a single
QTreeView
with a model. The only part of your code you are asking about istable.tree.expand(index) table.tree.scrollTo(index) table.tree.setCurrentIndex(index)
So test that behaviour on increasing row number in
index
to make sure it scrolls as you want. Then add any "searching" back in. -
@JonB I have other treeviews above, the word I gave you exists in the last treeview, that's why I want to make a function that shows me the place of the word that I searched
@sof4Rou
I don't understand. If you are talking about scrolling within one treeview which contains a word your code should work and the item is shown in that treeview in your screenshot. If you are talking about needing to scroll the multiple treeviews to get to one containing the word that is a totally different scroll on a different object and I don't know if that is what you mean. If that is the case you need to scroll your desired widget into view in whatever the enclosing scroll area is.QScrollArea::ensureWidgetVisible(QWidget *childWidget, int xmargin = 50, int ymargin = 50), is that what you asking about?
-
S SGaist moved this topic from General and Desktop on
-
-
@sof4Rou
I don't understand. If you are talking about scrolling within one treeview which contains a word your code should work and the item is shown in that treeview in your screenshot. If you are talking about needing to scroll the multiple treeviews to get to one containing the word that is a totally different scroll on a different object and I don't know if that is what you mean. If that is the case you need to scroll your desired widget into view in whatever the enclosing scroll area is.QScrollArea::ensureWidgetVisible(QWidget *childWidget, int xmargin = 50, int ymargin = 50), is that what you asking about?