PDA

View Full Version : How to obtain string from TextCursor whenever it is double clicked



naoyamakino
22nd July 2009, 18:04
Hi there, when user double clicks on QTextCursor in QTextEdit, I am looking for a way to get a string from that QTextCursor.


class ContactsView(QtGui.QTextEdit):
def __init__(self, parent=None):
QtGui.QTextEdit.__init__(self, parent)
#some initialization

def insert(self, name):
cursor = self.textCursor()
path = "image/icons/Messenger_blue32.png"
icon = QtGui.QPixmap(path)
image = icon.toImage()
cursor.insertImage(image)
cursor.insertText(name)
self.setTextCursor(cursor)
self.ensureCursorVisible()
end = "<br />"
fragment = QtGui.QTextDocumentFragment.fromHtml(end)
self.textCursor().insertFragment(fragment)

def mouseDoubleClickEvent(self,event):
cursor = self.cursorForPosition(event.pos())
BlockUnderCursor = 2
cursor.select(BlockUnderCursor)
name = cursor.selectedText()
print name

and when I run this program, I am getting this run time error;


ContactsView.py", line 24, in mouseDoubleClickEvent
print name
UnicodeEncodeError: 'ascii' codec can't encode character u'\ufffc' in position 0: ordinal not in range(128)

I believe I am getting this error because there are more than strings in cursor.
all I am interested is that I want to get a string from TextCursor whenever it is double clicked.
Could anyone give me an advise? any inputs would be very appreciated.
thank you for consideration.

regards
Naoya

wysota
22nd July 2009, 19:55
User is not clicking on QTextCursor. QTextCursor doesn't have a visual representation. In general your code seems correct. The problem is probably that you can't print the QString, you need to do a proper conversion to ascii (try name.toByteArray().constData())

naoyamakino
22nd July 2009, 21:23
Hi wysota, thank you so much for an input. I tried the conversion that you advised. but i got a following error;


ContactsView.py", line 91, in mouseDoubleClickEvent
print str(name).toByteArray().constData()
UnicodeEncodeError: 'ascii' codec can't encode character u'\ufffc' in position 0: ordinal not in range(128)


Do you know why? again, thank you for your time and very appreciate if you could give me an input.

regards
Naoya

wysota
22nd July 2009, 21:31
Hmm... did it even compile? There is no such thing as toByteArray() for QString :)

Should be:

print name.toAscii().constData()
And don't surround name with str(), it will again try to do the conversion on QString which will fail.

naoyamakino
22nd July 2009, 22:04
Hi wysota, yes it now gives me a string

print name.toAscii()
and the output was:

?name@email.com??name2@email.org??name3@email.com? ?name4@email.com?

these are a list of ALL contacts in TextEdit. but what I wanted was I only wanted to get one name which is just double clicked.
I thought
cursor = self.cursorForPosition(event.pos()) gives me a cursor which is right under the pos()...


here is my main window where I call ContactsView

self.contactList = ContactsView.ContactsView(self,self)
#some initialization...
for name in buddyList:#buddyList is a list of contacts
self.contactList.insert(name)#here inserts and displays contacts in contactList

in this list, I want to double click a name and get a string which name is clicked.
Do you have any idea?
thank you so much for your advises and always appreciate all.

best regards
Naoya

wysota
22nd July 2009, 23:01
My idea would be to use QListView instead of QTextEdit :)

And following your idea - you're selecting the whole block under cursor (in human terms - the whole paragraph of the text) whereas you'd probably want to select WordUnderCursor or do parsing of the text yourself if your contacts contain word separator characters.

naoyamakino
23rd July 2009, 07:19
Hi wysota, thank you for the idea. and I am very close!!I switched QTextEdit to QListView and now I can select an item, display with icons;


class ContactsView(QtGui.QListView):
def __init__(self,buddyList, parent=None):
QtGui.QListView.__init__(self, parent)
self.buddyList = buddyList
self.iStandardModel =QtGui.QStandardItemModel(self)
def insert(self, name):
path = "image/icons/Messenger_blue32.png"
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(path), QtGui.QIcon.Normal, QtGui.QIcon.Off)
item = QtGui.QStandardItem(icon,name)
item.setEditable(False)
self.iStandardModel.appendRow(item)
self.setModel(self.iStandardModel)

but I'm facing a same issue; I can't still find a way to get a selected QStandardItem...
there is a isSelectable function but I could not find things like isSelected().

I tried something like this:


self.contactList = ContactsView.ContactsView(self,self)
if(buddyList is not None):
for name in buddyList:
self.contactList.insert(name)
self.connect(self.contactList.selectionModel(),
QtCore.SIGNAL("selectionChanged(QItemSelection, QItemSelection)"),
self.slot)
...
def slot(self, selected, deselected):
print str(selected), "items selected"
but this dose not print any useful information:

<PyQt4.QtGui.QItemSelection object at 0x03A77810> items selected
this prints out which ever I choose an item.

Could you please give me an advise again?
I very much appreciate your kindness and support.

regards
Naoya

wysota
23rd July 2009, 10:03
You are abusing print and str(). Don't do that, Qt objects are incomatible with them. Look at documentation of QItemSelection and extract needed data using appropriate methods from its API. QItemSelection::indexes() might be a good place to start.

naoyamakino
23rd July 2009, 23:50
Hi wysota, thank your for a reply. but I think I am stucked. I have been looking at API but I still cannot figure out how to determine which QStandardItem is selected on QListView. it seems like many people are having the same problem but noone provides a solution to this.

Thank you so much for your help.

wysota
24th July 2009, 00:25
I have already given you the solution. QItemSelection::indexes() provides a list of indexes which can then be converted into items using QStandardItemModel::itemFromIndex()

Please direct those "many people" to our forum, they will find their answers here :)

naoyamakino
24th July 2009, 00:44
YES!!!!! it now works!!!

def slot(self, selected, deselected):
indexes = selected.indexes()
for index in indexes:
item = self.contactList.iStandardModel.itemFromIndex(inde x)
print item.text()

you made my day! thank you so much!! I very much appreciate your support.
Best regards

Naoya

naoyamakino
24th July 2009, 01:30
Hi wysota, its me again. thank you for the help. and I am facing a new issue:rolleyes:
before I used to send a signal to determine if a selection is changed.

self.connect(self.contactList.selectionModel(),
QtCore.SIGNAL("selectionChanged(QItemSelection, QItemSelection)"),
self.slot)

but when I try something like;


self.connect(self.contactList.selectionModel(),
QtCore.SIGNAL("itemDoubleClicked(QItemSelection)"),
self.usernameClick)

self.connect(self.contactList.selectionModel(),
QtCore.SIGNAL("itemClicked(QItemSelection)"),
self.usernameSelect)

def usernameClick(self, contact):
print 'usernameclick'
indexes = contact.indexes()
for index in indexes:
item = self.contactList.iStandardModel.itemFromIndex(inde x)
self.usernameClickCallback(item.text())

def usernameSelect(self,contact):
print 'select'


it does not send a signal. I need to send two signals; one for double clicking the item(to pop up a chat window) and one for selection(to delete a contact and so on).
it this possible?

best regards

wysota
24th July 2009, 10:38
You can't emit signals that don't exist... double clicking on an item is handled by the QAbstractItemView subclass - see QAbstractItemView::doubleClicked().