Results 1 to 20 of 35

Thread: How to simplify a complex item delegate?

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Aug 2012
    Location
    Wrocław, Poland
    Posts
    25
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Question How to simplify a complex item delegate?

    I have a QListView which paints (and measures) its items with a custom QStyledItemDelegate.

    But over time the item grew quite complex. When it was still a thumbnail and to the right of it a bunch of header/value label pairs aligned in a column the code was long and ugly but it was still manageable. But when now I have to add some additional icons the measuring and painting code got really awful. It feels more than natural to use a custom QWidget instead since it can easily use all the goodies of UI Designer, styling and so on.

    However by reading documentation and tutorials I felt like it is the *View family of widgets that gets "more love" than the *Widget family. While my personal experience leads me to think that QAbstractItemModel-based approach to Model/View framework is actually quite limited and doing anything more than what Qt has thought about quickly becomes quite difficult.

    Or is there maybe some other approach to writing custom QStyledItemDelegate which deals with complexity better?

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,360
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: How to simplify a complex item delegate?

    It really depends on what you want to do. For some cases it might be feasible to replace QListView with QDeclarativeView and implement the list in QML where it is much easier to code delegates. But again, maybe it is easy to do what you want with item views and you just need to restructure your code.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  3. #3
    Join Date
    Aug 2012
    Location
    Wrocław, Poland
    Posts
    25
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: How to simplify a complex item delegate?

    Quote Originally Posted by wysota View Post
    It really depends on what you want to do.
    For example something like the Windows Media Player list view shown here. Or even its sub-case: just the album thumbnail with labels on the right. The more data you have the more difficult it gets to do it with QAbstractItemDelegate. Not to mention how styling gets difficult.

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,360
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: How to simplify a complex item delegate?

    If you have a single constant layout then implementing such a delegate is trivial. I thought you wanted something more complex. Just bear in mind this is a table (or even a tree) and not a list.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  5. #5
    Join Date
    Aug 2012
    Location
    Wrocław, Poland
    Posts
    25
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: How to simplify a complex item delegate?

    Quote Originally Posted by wysota View Post
    If you have a single constant layout then implementing such a delegate is trivial.
    I would not agree with that. Especially after writing such a delegate just few days ago (and mine had just a thumbnail + 2 pairs of header/value labels). It took me some time (OK, I'm know to Qt) and resulting code is long, difficult to understand and maintain. Even thou it contains mostly just calls to measuring functions. Adding another 2 labels or some extra icons, especially by someone else after some time would be really painful.

    And such layout code felt like a natural candidate for generalization and extraction as a separate class/function. With this question I was trying to know those generalization.

    Quote Originally Posted by wysota View Post
    I thought you wanted something more complex. Just bear in mind this is a table (or even a tree) and not a list.
    It is not really important. After all it was just an example.

  6. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,360
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: How to simplify a complex item delegate?

    Quote Originally Posted by Adam Badura View Post
    I would not agree with that. Especially after writing such a delegate just few days ago (and mine had just a thumbnail + 2 pairs of header/value labels). It took me some time (OK, I'm know to Qt) and resulting code is long, difficult to understand and maintain.
    Well, you have every right to disagree however in my opinion the delegate for the thumbnail and those three labels is around 3-6 lines long (depending how you choose to implement it).

    And such layout code felt like a natural candidate for generalization and extraction as a separate class/function. With this question I was trying to know those generalization.
    You can write such layout engine however in my opinion it is an overkill since your "layout" is static and always the same. Having a layout engine makes sense if you expect to have different layouts in every item or you expect that some pieces of data will change their visual position and the layout will have to be recalculated.


    It is not really important. After all it was just an example.
    On the contrary, this is very important. In a list you have to render the whole row in one go. With a table or a tree every column is rendered separately thus implementation of each delegate is greatly simplified. You have to choose proper tools for each job.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  7. #7
    Join Date
    Aug 2012
    Location
    Wrocław, Poland
    Posts
    25
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: How to simplify a complex item delegate?

    Quote Originally Posted by wysota View Post
    Well, you have every right to disagree however in my opinion the delegate for the thumbnail and those three labels is around 3-6 lines long (depending how you choose to implement it).
    Could you provide an example? Since maybe I just did it in some very sub-optimal way.

    In my case it is a QTreeView but it could be limited to QListView as we are using it that way currently. There is a thumbnail in Qt::DecorationRole. To the right of it there are two text fields stacked vertically: "Name: ..." with value taken from Qt::DisplayRole and "Length: ..." with value from custom role. The header labels are aligned to the left, and the values are aligned to the left so there are two columns.

  8. #8
    Join Date
    Aug 2012
    Location
    Wrocław, Poland
    Posts
    25
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: How to simplify a complex item delegate?

    Dear wysota, you wrote:

    Quote Originally Posted by wysota View Post
    If you have a single constant layout then implementing such a delegate is trivial.
    and

    Quote Originally Posted by wysota View Post
    Well, you have every right to disagree however in my opinion the delegate for the thumbnail and those three labels is around 3-6 lines long (depending how you choose to implement it).
    Since I found it highly questionable I asked for that simple thing:

    Quote Originally Posted by Adam Badura View Post
    Could you provide an example? Since maybe I just did it in some very sub-optimal way.

    In my case it is a QTreeView but it could be limited to QListView as we are using it that way currently. There is a thumbnail in Qt::DecorationRole. To the right of it there are two text fields stacked vertically: "Name: ..." with value taken from Qt::DisplayRole and "Length: ..." with value from custom role. The header labels are aligned to the left, and the values are aligned to the left so there are two columns.
    Over 10 days passed. You were here. And yet you did not provide those trivial 3-6 lines... Let others who come here with similar issue judge that...

  9. #9
    Join Date
    Jan 2006
    Location
    Germany
    Posts
    4,380
    Thanks
    19
    Thanked 1,005 Times in 913 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60
    Wiki edits
    5

    Default Re: How to simplify a complex item delegate?

    Let others who come here with similar issue judge that...
    Well it is because he don't want to write the delegate for you and one annoying thing is when people requesting code but didn't provide what they have tried so far. This leads to the conclusion - which my not be valid in every case - that nothing has be done so far... So I can understand him. And the attitude you are showing is not helpful either. (Beside, if someone has more than 28.000 posts and more then 4.000 thanks, which is the most here, he probably is a nice guy. In this case, I can confirm that)

    As to your problem: Have you seen the Star delegate Example? From there:
    Qt Code:
    1. void StarDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
    2. const QModelIndex &index) const
    3. {
    4. if (qVariantCanConvert<StarRating>(index.data())) {
    5. StarRating starRating = qVariantValue<StarRating>(index.data());
    6.  
    7. if (option.state & QStyle::State_Selected)
    8. painter->fillRect(option.rect, option.palette.highlight());
    9.  
    10. starRating.paint(painter, option.rect, option.palette,
    11. StarRating::ReadOnly);
    12. } else {
    13. QStyledItemDelegate::paint(painter, option, index);
    14. }
    15. }
    To copy to clipboard, switch view to plain text mode 
    Which total represent your example link of a music player.

  10. #10
    Join Date
    Aug 2012
    Location
    Wrocław, Poland
    Posts
    25
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: How to simplify a complex item delegate?

    Quote Originally Posted by Lykurg View Post
    Which total represent your example link of a music player.
    It does not. The star sample skips the most important (for me) part: the thumbnail and stacked labels on the right of it. And that is what I actually want to achieve (the Windows Media Player sample was just first that same to my mind - and that I found - when trying to provide some sample). What I wanted to achieve I have described in the very first post (second paragraph) and in the one that asked explicitly for the "trivial code" (also second paragraph).

    By the way: In my Qt 4.8.4 when I build Examples and Demos with qmake -tp vc -r the resulting Visual Studio solution did not open cleanly in Visual Studio since some projects had same names and the solution didn't use its folders. Yet I believe this is only a "GUI issue". MS Build shouldn't care about it anyway. More important issue was that the star example wasn't build at all! It is not included in its "parent .pro file".

    I didn't post more details on my current state since I considered that irrelevant and "obfuscated" to much with particular details of my project while my investigations and research lead me to think it is a general issue rather than my specific one. But sure, I can give more details. This is how it looks now:

    Example.jpg

    It is a QTreeView (from historical reasons and for future extensions; for what it is now it could very well be just a QListView). The white header at the begining (with "Adam Badura") is a header with single column. Bellow are the items. The backgrounds alternate (although even-background is not visible here). Various states are represented with various background colors. On the left of each item there is a thumbnail (in this quickly-taken snapshot all thumbnails are same). To the right of it are the stacked labels (likely soon we will want to add at least two more labels). The green arrow is a quickly added icon. It does not align to anythig (yet).

    The view itself works in two modes. This is the "expanded" one. The "simple" one has shorter single-line items done mostly with default drawing. It is done by alternating item delegate. But I'm considering switching to alternating QTreeViews instead (that would just share single model) as it seems simpler and does not require use of apparently undocumented QTreeView::doItemsLayout() function.

    Now the crucial part of the code it auxiliary delegate function measureItem (it is my own function). It measures and lays out all the parts of the item and the item itself. Then I call it from QStyledItemDelegate::sizeHint (for the item size) and from QStyledItemDelegate::paint (which next just calls a bunch of drawing functions within the already computed rectangles). Code is following:

    Qt Code:
    1. void ElExtendedPlaylistEditorDelegate::measureItem(
    2. QStyleOptionViewItemV4 const& option,
    3. QStyle const* stylePtr,
    4. QModelIndex const& index,
    5. QRect& item,
    6. QRect& thumbnail,
    7. QRect& nameHeaderLabel,
    8. QRect& nameDataLabel,
    9. QRect& lengthHeaderLabel,
    10. QRect& lengthDataLabel,
    11. QRect& videoEffectImageRect
    12. ) const
    13. {
    14. // More or less arbitrarily selected values.
    15.  
    16. // Margins within the item in which components will be laid out.
    17. QMargins padding( 2, 2, 2, 2 );
    18. // Enough to show a reasonable icon.
    19. int minimumThumbnailHeight = 64;
    20. // HD aspect ratio.
    21. boost::rational< int > thumbnailAspectRatio( 1920, 1080 );
    22.  
    23. int thumbnailLabelsMargin =
    24. stylePtr->layoutSpacing(
    25. QSizePolicy::DefaultType,
    26. QSizePolicy::Label,
    27. Qt::Horizontal,
    28. &option,
    29. option.widget
    30. );
    31. if ( thumbnailLabelsMargin == -1 )
    32. thumbnailLabelsMargin = 5;
    33.  
    34. int labelsVerticalMargin =
    35. stylePtr->layoutSpacing(
    36. QSizePolicy::Label,
    37. QSizePolicy::Label,
    38. Qt::Vertical,
    39. &option,
    40. option.widget
    41. );
    42. if ( labelsVerticalMargin == -1 )
    43. labelsVerticalMargin = 2;
    44.  
    45. // Obtain/reformat some data.
    46.  
    47. EbTimecode length =
    48. index.data(
    49. sps::spsGUI::PlaylistModel::CustomRole::ITEM_LENGTH
    50. ).value< EbTimecode >();
    51. QString lengthString = length.getTimecodeString();
    52.  
    53.  
    54. // Measure components which are not flexible.
    55.  
    56. // Note that the measuring includes a space between header and data. This way
    57. // margin is scaled well with the font that is used rather than fixed to given
    58. // pixels value.
    59.  
    60. nameHeaderLabel =
    61. stylePtr->itemTextRect(
    62. option.fontMetrics,
    63. QRect(),
    64. Qt::AlignLeft | Qt::AlignBottom,
    65. ( option.state & QStyle::State_Enabled ) != 0,
    66. tr( "Name:" ) + " "
    67. );
    68.  
    69. nameDataLabel =
    70. stylePtr->itemTextRect(
    71. option.fontMetrics,
    72. QRect(),
    73. Qt::AlignLeft | Qt::AlignBottom,
    74. ( option.state & QStyle::State_Enabled ) != 0,
    75. option.text
    76. );
    77.  
    78. lengthHeaderLabel =
    79. stylePtr->itemTextRect(
    80. option.fontMetrics,
    81. QRect(),
    82. Qt::AlignLeft | Qt::AlignBottom,
    83. ( option.state & QStyle::State_Enabled ) != 0,
    84. tr( "Length:" ) + " "
    85. );
    86.  
    87. lengthDataLabel =
    88. stylePtr->itemTextRect(
    89. option.fontMetrics,
    90. QRect(),
    91. Qt::AlignLeft | Qt::AlignBottom,
    92. ( option.state & QStyle::State_Enabled ) != 0,
    93. lengthString
    94. );
    95.  
    96. // it will be changed after demo:)
    97. videoEffectImageRect = QRect( 0, 0, 30, 20 );
    98.  
    99. // Now start laying out the components with labels.
    100.  
    101. nameHeaderLabel.translate(
    102. -nameHeaderLabel.left(),
    103. -nameHeaderLabel.top()
    104. + option.rect.top()
    105. + padding.top()
    106. );
    107. nameDataLabel.translate(
    108. -nameDataLabel.left(),
    109. -nameDataLabel.top()
    110. + option.rect.top()
    111. + padding.top()
    112. );
    113.  
    114. Q_ASSERT( nameHeaderLabel.height() == nameDataLabel.height() );
    115. int nameJoinedLabelHeight =
    116. ( std::max )( nameHeaderLabel.height(), nameDataLabel.height() );
    117.  
    118. lengthHeaderLabel.translate(
    119. -lengthHeaderLabel.left(),
    120. -lengthHeaderLabel.top()
    121. + option.rect.top()
    122. + padding.top()
    123. + nameJoinedLabelHeight
    124. + labelsVerticalMargin
    125. );
    126. lengthDataLabel.translate(
    127. -lengthDataLabel.left(),
    128. -lengthDataLabel.top()
    129. + option.rect.top()
    130. + padding.top()
    131. + nameJoinedLabelHeight
    132. + labelsVerticalMargin
    133. );
    134. videoEffectImageRect.translate(
    135. -videoEffectImageRect.left(),
    136. -videoEffectImageRect.top()
    137. + option.rect.top()
    138. + padding.top()
    139. + nameJoinedLabelHeight
    140. + labelsVerticalMargin
    141. + labelsVerticalMargin
    142. );
    143.  
    144. Q_ASSERT( lengthHeaderLabel.height() == lengthDataLabel.height() );
    145. int lengthJoinedLabelHeight =
    146. ( std::max )( lengthHeaderLabel.height(), lengthDataLabel.height() );
    147.  
    148. int headersWidth =
    149. ( std::max )( nameHeaderLabel.width(), lengthHeaderLabel.width() );
    150.  
    151. nameHeaderLabel.translate(
    152. option.rect.left()
    153. + padding.left(),
    154. 0
    155. );
    156. nameDataLabel.translate(
    157. option.rect.left()
    158. + padding.left()
    159. + headersWidth,
    160. 0
    161. );
    162.  
    163. lengthHeaderLabel.translate(
    164. option.rect.left()
    165. + padding.left(),
    166. 0
    167. );
    168. lengthDataLabel.translate(
    169. option.rect.left()
    170. + padding.left()
    171. + headersWidth,
    172. 0
    173. );
    174. videoEffectImageRect.translate(
    175. option.rect.left()
    176. + padding.left()
    177. + headersWidth
    178. + lengthDataLabel.width(),
    179. 0
    180. );
    181.  
    182. int labelsWidth =
    183. headersWidth
    184. + ( std::max )( nameDataLabel.width(), lengthDataLabel.width() );
    185. int labelsHeight =
    186. nameJoinedLabelHeight
    187. + labelsVerticalMargin
    188. + lengthJoinedLabelHeight;
    189.  
    190.  
    191. // Now that the labels are laid out we have to include the thumbnail.
    192.  
    193. int thumbnailHeight =
    194. (std::max )( minimumThumbnailHeight, labelsHeight );
    195. auto thumbnailWidthExact = thumbnailAspectRatio * thumbnailHeight;
    196. int thumbnailWidth = boost::rational_cast< int >( thumbnailWidthExact );
    197.  
    198. Q_ASSERT( thumbnailHeight >= labelsHeight );
    199. int itemContentsHeight = thumbnailHeight;
    200.  
    201. int itemContentsWidth =
    202. thumbnailWidth
    203. + thumbnailLabelsMargin
    204. + labelsWidth;
    205.  
    206.  
    207. thumbnail.setCoords(
    208. option.rect.left()
    209. + padding.left(),
    210. option.rect.top()
    211. + padding.top(),
    212. option.rect.left()
    213. + padding.left()
    214. + thumbnailWidth,
    215. option.rect.top()
    216. + padding.top()
    217. + itemContentsHeight
    218. );
    219.  
    220. // Offset labels by the thumbnail width (plus margin).
    221.  
    222. nameHeaderLabel.translate(
    223. thumbnailWidth + thumbnailLabelsMargin,
    224. 0
    225. );
    226. nameDataLabel.translate(
    227. thumbnailWidth + thumbnailLabelsMargin,
    228. 0
    229. );
    230. lengthHeaderLabel.translate(
    231. thumbnailWidth + thumbnailLabelsMargin,
    232. 0
    233. );
    234. lengthDataLabel.translate(
    235. thumbnailWidth + thumbnailLabelsMargin,
    236. 0
    237. );
    238.  
    239. videoEffectImageRect.translate(
    240. thumbnailWidth + thumbnailLabelsMargin,
    241. 0
    242. );
    243.  
    244. // Finally item size itself.
    245.  
    246. item.setCoords(
    247. option.rect.left(),
    248. option.rect.top(),
    249. option.rect.left()
    250. + padding.left()
    251. + itemContentsWidth
    252. + padding.right(),
    253. option.rect.top()
    254. + padding.top()
    255. + itemContentsHeight
    256. + padding.bottom()
    257. );
    258. }
    To copy to clipboard, switch view to plain text mode 

    As can be seen obviously it is neither trivial nor 3-6 lines...

    And now consider that user requests a change and wants the "header labels" ("Name:" and "Length:") to be aligned to right rather than to left in its column. It can be done. But it requires a programmer who understands the code. While conceptually it should be just "changing an enum value" and I believe UI Designer would allow such change much easier. But since I have QTreeView I cannot design my items in UI Designer...

  11. #11
    Join Date
    Dec 2012
    Posts
    90
    Thanks
    5
    Thanked 20 Times in 18 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: How to simplify a complex item delegate?

    I have a crazy idea.

    What if you add to your delegate pointer to a shadow QWidget.
    Then you'll do all the custom layout in designer, and add resulting QWidget to your delegate.
    Then in paint event you apply necessary tweaks to the widget, and then render it using QWidget::render ()!

  12. The following user says thank you to lanz for this useful post:

    Adam Badura (20th February 2013)

  13. #12
    Join Date
    Jan 2006
    Location
    Germany
    Posts
    4,380
    Thanks
    19
    Thanked 1,005 Times in 913 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60
    Wiki edits
    5

    Default Re: How to simplify a complex item delegate?

    Quote Originally Posted by Adam Badura View Post
    It does not. The star sample skips the most important (for me) part: the thumbnail and stacked labels on the right of it.
    Ups, I call that selective perception... Right.

    Now the crucial part of the code
    Ok, you have a tree view: 1st column the image -> handled by the standard item delegate. 2nd column the labels. To simplify that and to extend it easily use loops e.g.
    Qt Code:
    1. QList<QPair<QString,QString> > labels; // a pair has "label:value"
    2. // max width of label description:
    3. int maxDescWidth = 0;
    4. foreach(QPair<QString,QString> l, labels)
    5. maxDescWidth = qMax(maxDescWidth, fontmetrics.width(l.first));
    6.  
    7. // then drawing
    8. int height = fontmetrics.height() + padding;
    9. for(int i = /*...*/) {
    10. painter->drawText(QRect(0,i*height, maxDescWidth, height), Qt::AlignRight, labels.at(i).first);
    11. // same for the text.
    12. }
    To copy to clipboard, switch view to plain text mode 

    That's just a quick mockup but I guess you see where it is going. This way you don't need a function calculating each bounding rect.

  14. The following user says thank you to Lykurg for this useful post:

    Adam Badura (20th February 2013)

  15. #13
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,360
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: How to simplify a complex item delegate?

    Quote Originally Posted by Adam Badura View Post
    Over 10 days passed. You were here. And yet you did not provide those trivial 3-6 lines...
    Ouch, sorry, I forgot about it.

    This should work (not tested but you should get the picture...)

    Qt Code:
    1. void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const {
    2. QPixmap px = index.data(Qt::DecorationRole).toPixmap();
    3. painter->drawPixmap(option.rect.topLeft()+QPoint(1,1), px);
    4. painter->drawText(option.rect.adjusted(px.width+1+5, 1, -1, -1), Qt::AlighLeft|Qt::AlignTop, QString("%1\n%2\n%3").arg(index.data(Qt::DisplayRole).toString()).arg(index.data(...).toString()).arg(index.data(...).toString()));
    5. }
    To copy to clipboard, switch view to plain text mode 

    Similar for sizeHint(), just use QFontMetrics::boundingRect() instead of painting.

    Edit: Next time, instead of assuming my bad will, just send me a PM with a reminder or bump the thread.
    Last edited by wysota; 20th February 2013 at 12:02.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


Similar Threads

  1. QLabel as an item delegate
    By qlands in forum Qt Programming
    Replies: 13
    Last Post: 12th August 2011, 11:51
  2. Using model indices in complex model item relationships
    By hackerNovitiate in forum Newbie
    Replies: 0
    Last Post: 29th June 2011, 14:30
  3. Replies: 0
    Last Post: 10th March 2011, 11:44
  4. Replies: 5
    Last Post: 10th August 2009, 10:50
  5. Delegate for a certain item?
    By somebody in forum Qt Programming
    Replies: 1
    Last Post: 18th August 2008, 22:55

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.