Searching a TreeView - python

I am working on a project and am using a treeview. I have done lots of searching and all ive found to my answer is to itterate through the whole treeview but not even how to do it, so my question is how do i search a treeview for an item that contains an input string. The idea will be to have an entry box and have users type something in there, when they press search items that contain what the user has input is shown. I'm not sure if i could do this in the treeview or if it will have to go into a listview. I'm on windows 7 pyqt5 python 3.5
self.treeView = QtWidgets.QTreeView(self.centralWidget)
self.treeView.setSortingEnabled(True)
self.treeView.setObjectName("treeView")
self.horizontalLayout_4.addWidget(self.treeView)
self.file_model=QtWidgets.QFileSystemModel()
self.file_model.setRootPath('C:\My Stuff\Movies')
self.treeView.setModel(self.file_model)
self.treeView.setRootIndex(self.file_model.index('C:\My Stuff\Movies'))
self.treeView.setHeaderHidden(True)
self.treeView.hideColumn(1)
self.treeView.hideColumn(2)
self.treeView.hideColumn(3)

This answer is an outline of the solution.
You may find the code I wrote for SCM Workbench useful for reference:
https://github.com/barry-scott/scm-workbench/blob/master/Source/Scm/wb_scm_table_model.py
In my app the function indexFromBookmark() I think is close to what you
want.
To start you need the root of the tree. You get that item with self.invisibleRootItem().
You can ask two interesting things of the item. Its name from item.text() and its children by calling item.child( row ) where the row starts from 0.
When the item of interest is found you can turn the item into an index using indexFromItem(). You need an index to set the selection in the tree for example.
With file names I guess you split on '\' and each items text() is the path part.

Related

QtreeWidget python read the state of the checked boxes

First sorry if I am missing anything.and sorry about the format, new to stackoverflow
I am trying to read the flag state from a QtreeWidget.
I have tried a lot of things and nothing seam to work.
I am dynamical creating the tree as follows
Part=str(result2[row2][0])
qty=str(offset_B)+str(result2[row2][1])
instock=str(offset_B)+str(result2[row2][2])
B = QTreeWidgetItem(A, [Part,qty,instock])
B.setForeground(0,QtGui.QBrush(QtGui.QColor(color_item)))
B.setForeground(1,QtGui.QBrush(QtGui.QColor(color_item)))
B.setForeground(2,QtGui.QBrush(QtGui.QColor(color_item)))
B.setFlags(Qt.ItemIsTristate)
B.setCheckState(0, Qt.Unchecked)
I have a button Generate Po's and when I click it I want to iterate through the items and grab the text value of the checked Items.
sample
so it should return a list of some sort with all the text field.
I can do the list I just need to understand how to grab the "State" of the button.
I hope this is clear enough.

Python - Deleting a line from a file (To-Do List program that uses entries, different from other posts)

I have a problem with my code. I am trying to delete a specific line from a file. I am making a To-Do List program in Tkinter, and I am using a Label as the to-do list. I have two buttons, 'Add Item' and 'Delete Item'. I also have an entry box, and the buttons take the string from the entry using the .get() method. The delete button is not working because I cannot find a way to delete a line from a file that the program is using to store the list. I have looked over many other posts about the same problem, but mine is different. Whenever I run the program, and I click delete item after I fill out the text box, it deletes ALL items from the file, but I only want it to delete one item. The problem is NOT the one that #JetMashKangaroo had in this post: How to delete a line from a file in Python.
Here is the snippet of code:
def dele():
global ItemName
global Display
global List
ToDoDel = ItemName.get()
new_f = List.readlines()
List.seek(0)
for line in new_f:
if ToDoDel not in line:
List.write(line)
List.truncate()
Display['text'] = List.readlines()
ItemName is the entry box. Display is the label that displays the To-Do list. List is the variable below:
List = open('***/***/To-Do_List.txt','r+')
The program works perfectly, but I cannot add this delete function because it deletes all the text from the file. the function dele is called when the button 'Delete Item' is pressed. Help would be greatly appreciated.
The most likely reason you're running into a problem is that you are attempting to modify the list while also iterating over it. Here's an example post of someone else who ran into a similar issue.
My suggestion is that you keep track of which indexes to modify within your loop, then remove them after the loop has completed.

Retrieving cell data from a selected cell in a tablewidget

I am making a stock control program and i have hit a problem with getting the value of a selected cell, i know i need to use "QtGui.QTableWidget.currentRow" and "QtGui.QTableWidget.currentColumn" to get the item's position. However i cannot seem to get this to work because when the functions are called nothing has been selected and so it returns -1,-1
Does anyone know how to get it so it runs the "QtGui.QTableWidget.currentRow" and "QtGui.QTableWidget.currentColumn" everytime the user selects a cell?
i think the code i need to get the actual data once i have the co-ords is QtGui.QTableWidget.item ?
This is the code i am using to get the row and column:
row = self.table.currentRow
column = self.table.currentColumn
self.ID = self.table.item(row, column)
when the user clicks a button to add stock the program should then use the product code it will have just got to make the change to the database after getting the quantity added from the user
I am using python 3.2 and pyqt 4
any help would be appreciated
Thank you
Sam
When the QTableWidget sees that someone has clicked one of it's cells, it will emit a cellClicked event - which you need to connect to. Maybe something like
self.table.cellClicked.connect(self.cell_was_clicked)
could be in your setup code,
and the function cell_was_clicked might be something like
def cell_was_clicked(self, row, column):
print("Row %d and Column %d was clicked" % (row, column))
item = self.table.itemAt(row, column)
self.ID = item.text()
I've not used currentRow and currentColumn as you want a response on the click. This function is documented here (sorry, I prefer pyside - it's pretty much the same as PyQT). Note also itemAt instead of just item - as you will get the item at the cell, not it's contents. Use the .text() function of QTableWidgetItem to get at the contents.
Note - this is using 'slots and signals' and in particular the 'new style'. As you're using PyQT4 and Python 3 you should have no trouble with 'new stuff' :-)
You might consider browsing a slots and signals tutorial - that might straighten a few of these abstract concepts out. Good luck!
here is the code that worked for me:
def get_selected_cell_value():
current_row = self.sold_items_details_table.currentRow()
current_column = self.sold_items_details_table.currentColumn()
cell_value = table.item(current_row, current_column).text()

PyGTK: Doubleclick on CellRenderer

In my PyGTK application I currently use 'editable' to make cells editable. But since my cell contents sometimes are really really large I want to ask the user for changes in a new window when he doubleclicks on a cell. But I could not find out how to hook on double-clicks on specific cellrenderers - I don't want to edit the whole row and I also don't want to set this callback for the whole row, only for columns where too long content can occur. How can I do this with CellRendererText() or something similar.
My currently cell-generating code is:
cols[i] = gtk.TreeViewColumn(coltitle)
cells[i] = gtk.CellRendererText()
cols[i].pack_start(cells[i])
cols[i].add_attribute(cells[i], 'text', i)
cols[i].set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
cols[i].set_fixed_width(100)
cells[i].set_property('editable', True)
cells[i].connect('edited', self.edited, (i, ls))
cols[i].set_resizable(True)
mytreeview.append_column(cols[i])
Thanks!
I believe this is not possible directly. However, you can connect to button-press-event on the gtk.TreeView. Then, when event.type equals to gtk.gdk._2BUTTON_PRESS, convert x and y to tree location using gtk.TreeView.get_path_at_pos(). This will return both a tree path indicating the row and gtk.TreeViewColumn object on which the click was made.

Entry with suggestions

I'm building a small PyGTK application and I have an text input field (currently a ComboBoxEntry) which is populated with a few values that the user should be able to choose from.
I think what I want to do is to filter out the matching fields and only show those ones so the user using the keyboard arrows can choose one of the matching ones.
To give some background the predefined values are a bunch of urls and the user should be able to choose from theese or fill in a new one.
Example:
the predefined urls:
http://www.google.com
http://www.google.com/android
http://www.greatstuff.com
http://www.facebook.com
When a user types 'http://www.g'
The three URLs starting with that string is to be shown (in some way) and when typeing 'http://www.goog' the two starting with that is to be shown
Any Ideas?
An Entry with an EntryCompletion seems more appropriate than a ComboBoxEntry. As always, the tutorial is a good start.
It's very easy to set up when the predefined URLs list is small and fixed.
You just need to populate a ListStore:
# simplified example from the tutorial
import gtk
urls = [
'http://www.google.com',
'http://www.google.com/android',
'http://www.greatstuff.com',
'http://www.facebook.com',
]
liststore = gtk.ListStore(str)
for s in urls:
liststore.append([s])
completion = gtk.EntryCompletion()
completion.set_model(liststore)
completion.set_text_column(0)
entry = gtk.Entry()
entry.set_completion(completion)
# boilerplate
window = gtk.Window()
window.add(entry)
window.connect('destroy', lambda w: gtk.main_quit())
window.show_all()
gtk.main()
Users are not likely to bother typing "http://" or even "www.", so you probably want to match any part of the URL (e.g. just "og" works!):
def match_anywhere(completion, entrystr, iter, data):
modelstr = completion.get_model()[iter][0]
return entrystr in modelstr
completion.set_match_func(match_anywhere, None)
This will test every value in the ListStore for a match, so it's not scalable to huge lists (I mean huge; a 1000 works fine).
Be sure to play with the various options of EntryCompletion, to configure the most pleasant behavior.
You may want to look at how Deskbar Applet's Cuemiac does it.
Well, you obviously want to deal with prefixes so you'll probably want to use some sort of trie. Of course, there are issues to deal with. For instance, after a person has typed in a few letters ( or maybe even just one) you will want to either traverse the rest of the branches of the trie to find suggestions, or have suggestions stored in each node. A lot of these sorts of decisions depend on how many possible suggestions you plan on having.

Categories