PDA

View Full Version : listview with custom delegate moves text bit out of place [pic and code example]



DoTheEvo
20th May 2015, 23:43
http://i.imgur.com/7BchqwR.gif

I first asked on stackoverflow - link (http://stackoverflow.com/questions/30175644/pyqt-listview-with-html-rich-text-delegate-moves-text-bit-out-of-placepic-and-c)

But no responses, few solutions I found out seems to be band aids that get ripped when I try to do more stuff with it.
I add icons and suddenly I have issues across various desktop environments. And moving text/items up and down by pixes makes it out of place in different DE...
All the while everything is nice, pretty and perfect when custom delegate for html tags is not in use.

heres the test code seen in the gif, theres bit more story on stackoverflow, with also pyqt5 and pyside versions.
Comment out the 39th line to use the default delegate.



from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys

class HTMLDelegate(QStyledItemDelegate):
def __init__(self, parent=None):
super(HTMLDelegate, self).__init__(parent)
self.doc = QTextDocument(self)

def paint(self, painter, option, index):
painter.save()

options = QStyleOptionViewItemV4(option)
self.initStyleOption(options, index)

self.doc.setHtml(options.text)
options.text = ""

style = QApplication.style() if options.widget is None \
else options.widget.style()
style.drawControl(QStyle.CE_ItemViewItem, options, painter)

ctx = QAbstractTextDocumentLayout.PaintContext()

if option.state & QStyle.State_Selected:
ctx.palette.setColor(QPalette.Text, option.palette.color(
QPalette.Active, QPalette.HighlightedText))

textRect = style.subElementRect(QStyle.SE_ItemViewItemText, options)
painter.translate(textRect.topLeft())
self.doc.documentLayout().draw(painter, ctx)

painter.restore()

if __name__ == '__main__':
app = QApplication(sys.argv)
data = ['1','2','3','4','5','6','7','8','9']
main_list = QListView()
main_list.setItemDelegate(HTMLDelegate())
main_list.setModel(QStringListModel(data))
main_list.show()
sys.exit(app.exec_())



One thing that might help me get to the point of this, is if I could find the code of the default delegate?
See how it is done, try some stuff... assuming it is somewhere declared in the similar format as how we are suppose to do the custom ones... but as a noobie I am having a hard time finding it

wysota
21st May 2015, 07:07
You need to reimplement sizeHint() for the delegate to compensate for a different size of the drawn text.

DoTheEvo
21st May 2015, 16:43
Thanks, I used this as size hint, in the code above where I have self.doc defined in the init



def sizeHint(self, option, index):
return QSize(self.doc.idealWidth(), self.doc.size().height())


it fixes the issue in all DEs I tried (i3, ubuntu, gnome, xfce, cinnamon) except KDE, pic shows in KDE

http://i.imgur.com/qfeYxiW.png

but as you said, it is solving this by enlarges the height of the row

http://i.imgur.com/i8Y7st4.png

It makes me feel like I am losing control, I have to adjust row height for text to be centered correctly instead of the text adjusting itself to the row?

I also tried to play a bit with statically setting return values of sizeHint, but since different DEs expect different height ranging from 22-28, it seems I cant just set stuff the same everywhere as I want it.

complete test-case code with sizehint (http://pastebin.com/Ee0vRiig)

wysota
21st May 2015, 17:07
It makes me feel like I am losing control, I have to adjust row height for text to be centered correctly instead of the text adjusting itself to the row?
You are not telling the text to adjust itself to anything.


I also tried to play a bit with statically setting return values of sizeHint, but since different DEs expect different height ranging from 22-28, it seems I cant just set stuff the same everywhere as I want it.

Would look really silly with a default DE font size set to 40pt or so. You can use QFontMetrics though.

DoTheEvo
21st May 2015, 17:38
You are not telling the text to adjust itself to anything.

Nope, but I would love to, assuming its relative positioning and not absolute with textRect.adjust(-1, -4, 0, 0)

Is there any way to fix KDE? Or to lower the items height without text going all crazy?

wysota
21st May 2015, 18:10
If you have a font size which takes n pixels to draw a single line, there is no way you are going to fit it into < n pixels. Thus assuming you have a row of n pixels, you need to find a font which will fit into that.

DoTheEvo
21st May 2015, 19:53
thanks, will digg some more I guess