Results 1 to 8 of 8

Thread: Using QAbstractItemDelegate to display a TGA from a database

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Aug 2009
    Posts
    56
    Thanks
    14
    Thanked 1 Time in 1 Post

    Default Re: Using QAbstractItemDelegate to display a TGA from a database

    Actually, using a cache increased the performance enough I can use it. Here's the code

    Qt Code:
    1. #ifndef __BYTE_ARRAY_AS_IMAGE_ITEM_DELEGATE_H_
    2. #define __BYTE_ARRAY_AS_IMAGE_ITEM_DELEGATE_H_
    3.  
    4. #include <QItemDelegate>
    5. #include <QTimer>
    6.  
    7. class ModelIndicesDeferredPainter;
    8.  
    9. // If an item is a byte array, wait 100 milliseconds, then load it as an image if possible.
    10. class ByteArrayAsImageItemDelegate : public QItemDelegate
    11. {
    12. Q_OBJECT
    13. public:
    14. ByteArrayAsImageItemDelegate(QWidget *parent = 0) : QItemDelegate(parent) {}
    15.  
    16. virtual void paint(QPainter *painter, const QStyleOptionViewItem &option,
    17. const QModelIndex &index) const;
    18.  
    19. // This is needed because you can't emit events from paint() since paint() is const
    20. void SetDeferredPainter(ModelIndicesDeferredPainter *df) {deferredPainter=df;}
    21.  
    22. signals:
    23. void paintingDeferred(const QModelIndex& index);
    24.  
    25. protected:
    26. ModelIndicesDeferredPainter *deferredPainter;
    27. };
    28.  
    29. class ModelIndicesDeferredPainter : public QObject
    30. {
    31. Q_OBJECT
    32.  
    33. public:
    34. ModelIndicesDeferredPainter(QAbstractItemView *view, QObject *parent);
    35. bool paintLater(const QModelIndex& index);
    36.  
    37. protected slots:
    38. void paintPendingIndexes();
    39.  
    40. protected:
    41. QModelIndexList indicesToPaint;
    42. QAbstractItemView *storedItemView;
    43.  
    44. // Don't immediately load images. This way, if an image immediately goes out of viewable area, it is not drawn
    45. QTimer timer;
    46.  
    47. // This is needed so we know not to just call paintLater() again from ByteArrayAsImageItemDelegate
    48. bool isPaintingLater;
    49. };
    50.  
    51.  
    52. #endif
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. #include "ByteArrayAsImageItemDelegate.h"
    2. #include <QPainter>
    3. #include <QBuffer>
    4. #include <QImageReader>
    5. #include <QAbstractItemView>
    6. #include <QPixmapCache>
    7.  
    8. // From RakNet
    9. #include "SuperFastHash.h"
    10.  
    11. void ByteArrayAsImageItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
    12. const QModelIndex &index) const
    13. {
    14. const QVariant &v = index.data();
    15. if (v.type()==QVariant::ByteArray)
    16. {
    17. QByteArray ba = v.toByteArray();
    18. unsigned int hash = SuperFastHash(ba.data(),ba.length());
    19. QString hashKey;
    20. // Safer collision code commented out, in case I need it
    21. //hashKey.sprintf("%i%i%i",index.row(),index.column(),hash);
    22. // Faster, in case images are duplicated
    23. hashKey.sprintf("%i",hash);
    24. QPixmap pixmap;
    25. bool foundPixmap = QPixmapCache::find(hashKey, pixmap);
    26. bool paintLater;
    27. if (foundPixmap==false)
    28. {
    29. paintLater=deferredPainter->paintLater(index);
    30. if (paintLater==false)
    31. {
    32. // Load pixmap
    33. QBuffer buffer;
    34. buffer.setBuffer(&ba);
    35. buffer.open(QIODevice::ReadOnly);
    36. qir.setDevice(&buffer);
    37. QImage image;
    38. if (qir.read(&image))
    39. {
    40. pixmap = QPixmap::fromImage(image);
    41.  
    42. // Save to cache
    43. QPixmapCache::insert(hashKey,pixmap);
    44. }
    45. else
    46. {
    47. // Not an image?
    48. QItemDelegate::paint(painter,option,index);
    49. return;
    50. }
    51. }
    52. }
    53.  
    54. if (foundPixmap==true || paintLater==false)
    55. {
    56. // Paint
    57. QSize imageSize = pixmap.size();
    58. QRect drawRect;
    59. float scaleWidth, scaleHeight;
    60. float drawWidth, drawHeight;
    61. scaleWidth = (float) imageSize.width() / (float)option.rect.width();
    62. scaleHeight = (float)imageSize.height() / (float)option.rect.height();
    63. // Downscale by the larger of the two proportions
    64. if (scaleHeight > scaleWidth)
    65. {
    66. drawWidth=(float)imageSize.width()/scaleHeight;
    67. drawHeight=(float)imageSize.height()/scaleHeight;
    68. }
    69. else
    70. {
    71. drawWidth=(float)imageSize.width()/scaleWidth;
    72. drawHeight=(float)imageSize.height()/scaleWidth;
    73. }
    74.  
    75. float centerX = (float)option.rect.left() + (float)option.rect.width()/2.0;
    76. float centerY = (float)option.rect.top() + (float)option.rect.height()/2.0;
    77. drawRect.setLeft(centerX-drawWidth/2.0);
    78. drawRect.setRight(centerX+drawWidth/2.0);
    79. drawRect.setTop(centerY-drawHeight/2.0);
    80. drawRect.setBottom(centerY+drawHeight/2.0);
    81. painter->drawPixmap(drawRect, pixmap);
    82. }
    83.  
    84. }
    85. else
    86. {
    87. QItemDelegate::paint(painter,option,index);
    88. }
    89. }
    90. ModelIndicesDeferredPainter::ModelIndicesDeferredPainter(QAbstractItemView *view, QObject *parent)
    91. : QObject(parent)
    92. {
    93. storedItemView = view;
    94.  
    95. timer.setSingleShot(true);
    96. timer.setInterval(100);
    97. connect(&timer, SIGNAL(timeout()),
    98. this, SLOT(paintPendingIndexes()));
    99. isPaintingLater=false;
    100. }
    101.  
    102. bool ModelIndicesDeferredPainter::paintLater(const QModelIndex& index)
    103. {
    104. if (isPaintingLater)
    105. return false;
    106.  
    107. if (indicesToPaint.contains(index)==false)
    108. {
    109. indicesToPaint.append(index);
    110. timer.start();
    111. }
    112.  
    113. return true;
    114. }
    115.  
    116. void ModelIndicesDeferredPainter::paintPendingIndexes()
    117. {
    118. // This flag is needed so ByteArrayAsImageItemDelegate::paint does not just call paintLater again()
    119. isPaintingLater=true;
    120.  
    121. foreach(const QModelIndex& index, indicesToPaint)
    122. storedItemView->update(index);
    123. storedItemView->repaint();
    124.  
    125. isPaintingLater=false;
    126.  
    127. indicesToPaint.clear();
    128. }
    To copy to clipboard, switch view to plain text mode 

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

    Default Re: Using QAbstractItemDelegate to display a TGA from a database

    Why are you deferring anything? Not that I see what you are deferring...
    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. Threads and database connection
    By probine in forum Qt Programming
    Replies: 9
    Last Post: 7th August 2013, 08:30
  2. Regarding Database Display through user interface
    By Tavit in forum Qt Programming
    Replies: 1
    Last Post: 1st April 2008, 10:32
  3. Multiple database connections
    By cyberboy in forum Qt Programming
    Replies: 3
    Last Post: 30th March 2008, 16:56
  4. Display only PNG image on desktop
    By durbrak in forum Qt Programming
    Replies: 32
    Last Post: 15th March 2008, 21:55
  5. Database Master-Detail Entry Form
    By Phan Sin Tian in forum Newbie
    Replies: 4
    Last Post: 3rd February 2008, 14:31

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
  •  
Qt is a trademark of The Qt Company.