@@ -352,40 +352,32 @@ def sizeHint(
352352 item : ListItem = index .data (QtCore .Qt .ItemDataRole .UserRole )
353353 target_width = option .rect .width ()
354354
355- base_h = item .height
356- ellipse_size = base_h * 0.8
357-
358- right_reserved = base_h
359-
360- left_reserved = 10
361- if item .left_icon :
362- left_reserved = (base_h * 0.1 ) + ellipse_size + 8 + _TEXT_LEFT_PADDING
363-
364355 if item ._lfontsize > 0 and item ._lfontsize != option .font .pointSize ():
365356 f = QtGui .QFont (option .font )
366357 f .setPointSize (item ._lfontsize )
367358 fm = QtGui .QFontMetrics (f )
368359 else :
369360 fm = option .fontMetrics
370361
362+ right_text_w = 0
371363 if item .right_text :
372364 if item ._rfontsize > 0 and item ._rfontsize != option .font .pointSize ():
373365 fr = QtGui .QFont (option .font )
374366 fr .setPointSize (item ._rfontsize )
375367 fmr = QtGui .QFontMetrics (fr )
376368 else :
377369 fmr = option .fontMetrics
378- right_reserved += fmr .horizontalAdvance (item .right_text ) + 10
379-
380- if item .right_icon :
381- right_reserved += ellipse_size
382-
383- text_avail_width = max (target_width - left_reserved - right_reserved , 50 )
370+ right_text_w = fmr .horizontalAdvance (item .right_text )
384371
385372 collapsed_h = int (item .height * 1.1 )
373+ text_rect = self ._text_rect (
374+ item ,
375+ QtCore .QRect (option .rect .x (), option .rect .y (), target_width , collapsed_h ),
376+ right_text_w ,
377+ )
378+ text_avail_width = max (int (text_rect .width ()), 50 )
386379 lines = item .text .split ("\n " )
387- # paint() insets the row by 2px per side before fitting lines
388- max_lines = max (1 , (collapsed_h - 4 ) // fm .lineSpacing ())
380+ max_lines = max (1 , int (text_rect .height ()) // fm .lineSpacing ())
389381
390382 item .needs_expansion = len (lines ) > max_lines or any (
391383 fm .horizontalAdvance (line ) > text_avail_width for line in lines
@@ -394,15 +386,34 @@ def sizeHint(
394386 if not item .is_expanded :
395387 return QtCore .QSize (target_width , collapsed_h )
396388
397- text_rect = fm .boundingRect (
398- QtCore .QRect (0 , 0 , int ( text_avail_width ) , 0 ),
389+ bounds = fm .boundingRect (
390+ QtCore .QRect (0 , 0 , text_avail_width , 0 ),
399391 QtCore .Qt .AlignmentFlag .AlignLeft | QtCore .Qt .TextFlag .TextWordWrap ,
400392 item .text ,
401393 )
402394
403- final_height = max (item .height , text_rect .height () - 1 )
395+ final_height = max (item .height , bounds .height () - 1 )
404396 return QtCore .QSize (target_width , int (final_height * 1.2 ))
405397
398+ @staticmethod
399+ def _text_rect (
400+ item : ListItem , row : QtCore .QRect , right_text_w : int
401+ ) -> QtCore .QRectF :
402+ """Main-text area of *row*, shared by sizeHint and paint so overflow matches elision."""
403+ rect = row .adjusted (2 , 2 , - 2 , - 2 )
404+ icon = item .height * 0.8
405+ left = rect .left () + 10 + (icon + _TEXT_LEFT_PADDING if item .left_icon else 0 )
406+ right = rect .right () - item .height * 0.1 - icon - right_text_w - 10
407+ return QtCore .QRectF (left , rect .top (), right - left , rect .height ())
408+
409+ @staticmethod
410+ def _collapsed_lines (text : str , max_lines : int ) -> list [str ]:
411+ """Lines a collapsed row draws; overflow folds into the last so elision marks the cut."""
412+ lines = text .split ("\n " )
413+ if len (lines ) > max_lines :
414+ lines [max_lines - 1 :] = [" " .join (lines [max_lines - 1 :])]
415+ return lines
416+
406417 def paint (
407418 self ,
408419 painter : QtGui .QPainter ,
@@ -448,7 +459,6 @@ def paint(
448459 )
449460 painter .drawPixmap (ellipse_rect .toRect (), icon_scaled )
450461
451- left_margin = 10
452462 left_icon_rect = QtCore .QRectF (
453463 rect .left () + ellipse_margin ,
454464 rect .top () + ellipse_margin ,
@@ -466,22 +476,6 @@ def paint(
466476 left_pixmap = self ._get_scaled (item .left_icon , icon_size )
467477 painter .drawPixmap (left_icon_rect .toRect (), left_pixmap )
468478
469- text_margin = int (
470- rect .right () - ellipse_size - ellipse_margin - rect .height () * 0.10
471- )
472-
473- text_left = (
474- rect .left ()
475- + left_margin
476- + (left_icon_rect .width () + _TEXT_LEFT_PADDING if item .left_icon else 0 )
477- )
478- text_rect = QtCore .QRectF (
479- text_left ,
480- rect .top (),
481- text_margin - text_left ,
482- rect .height (),
483- )
484-
485479 painter .setPen (QtGui .QColor (255 , 255 , 255 ))
486480
487481 _font = painter .font ()
@@ -497,21 +491,17 @@ def paint(
497491
498492 right_metrics = QtGui .QFontMetrics (right_font )
499493
500- right_text_x = (
501- ellipse_rect .right ()
502- - right_metrics .horizontalAdvance (item .right_text )
503- - left_icon_rect .width ()
504- - left_margin
494+ text_rect = self ._text_rect (
495+ item , option .rect , right_metrics .horizontalAdvance (item .right_text )
505496 )
506497
507498 if not item .is_expanded :
508- max_main_text_width = int (right_text_x - left_margin )
509499 max_lines = max (1 , int (text_rect .height ()) // metrics .lineSpacing ())
510500 text = "\n " .join (
511501 metrics .elidedText (
512- line , QtCore .Qt .TextElideMode .ElideRight , max_main_text_width
502+ line , QtCore .Qt .TextElideMode .ElideRight , int ( text_rect . width ())
513503 )
514- for line in item .text . split ( " \n " )[: max_lines ]
504+ for line in self . _collapsed_lines ( item .text , max_lines )
515505 )
516506 painter .drawText (
517507 text_rect ,
@@ -531,7 +521,7 @@ def paint(
531521 painter .setFont (right_font )
532522 painter .setPen (QtGui .QColor (160 , 160 , 160 ))
533523 painter .drawText (
534- int (right_text_x ),
524+ int (text_rect . right () ),
535525 int (
536526 ellipse_rect .top ()
537527 + (ellipse_rect .height () + right_metrics .ascent ()) / 2
0 commit comments