From kde-commits Sat May 08 09:11:19 2010 From: =?utf-8?q?Jaros=C5=82aw=20Staniek?= Date: Sat, 08 May 2010 09:11:19 +0000 To: kde-commits Subject: koffice/kexi Message-Id: <20100508091119.0D3F9AC8B0 () svn ! kde ! org> X-MARC-Message: https://marc.info/?l=kde-commits&m=127330990710241 SVN commit 1124236 by staniek: Table View *Optimize display of scaled image entries in table grid by caching, table was previously unusable for 10+ rows BUG:234347 M +39 -8 kexiutils/utils.cpp M +10 -2 kexiutils/utils.h M +35 -3 widget/tableview/kexiblobtableedit.cpp --- trunk/koffice/kexi/kexiutils/utils.cpp #1124235:1124236 @@ -386,8 +386,10 @@ string[i] = QChar(string[i].unicode() - 47 - i); } -void KexiUtils::drawPixmap(QPainter& p, const WidgetMargins& margins, const QRect& rect, - const QPixmap& pixmap, Qt::Alignment alignment, bool scaledContents, bool keepAspectRatio) +static void drawOrScalePixmapInternal(QPainter* p, const WidgetMargins& margins, const QRect& rect, + QPixmap& pixmap, QPoint &pos, Qt::Alignment alignment, + bool scaledContents, bool keepAspectRatio, + Qt::TransformationMode transformMode = Qt::FastTransformation) { if (pixmap.isNull()) return; @@ -401,7 +403,7 @@ // QPainter p2; QPainter *target; // if (fast) { - target = &p; + target = p; // } else { //moved pixmapBuffer.resize(rect.size()-QSize(lineWidth, lineWidth)); //moved p2.begin(&pm, p.device()); @@ -410,11 +412,10 @@ //! @todo only create buffered pixmap of the minimum size and then do not fillRect() // target->fillRect(0,0,rect.width(),rect.height(), backgroundColor); - QPoint pos; if (scaledContents) { if (keepAspectRatio) { QImage img(pixmap.toImage()); - img = img.scaled(w, h, Qt::KeepAspectRatio); + img = img.scaled(w, h, Qt::KeepAspectRatio, transformMode); pos = rect.topLeft(); if (img.width() < w) { // int hAlign = QApplication::horizontalAlignment(alignment); @@ -437,15 +438,24 @@ else { // target->drawPixmap(pos, pixmapBuffer); } - p.drawImage(pos, img); + if (p) { + p->drawImage(pos, img); + } + else { + pixmap = QPixmap::fromImage(img); + } } else { if (!fast) { // pixmapBuffer = QPixmap(rect.size() - QSize(margins.right, margins.bottom)); // p2.begin(&pixmapBuffer); //, p.device()); // p2.drawPixmap(QRect(rect.x(), rect.y(), w, h), pixmap); - p.drawPixmap(QRect(rect.x(), rect.y(), w, h), pixmap); + pos = rect.topLeft(); + pixmap = pixmap.scaled(w, h, Qt::IgnoreAspectRatio, transformMode); + if (p) { + p->drawPixmap(pos, pixmap); } + } else { // target->drawPixmap(QRect(rect.x() + margins.left, rect.y() + margins.top, w, h), pixmap); } @@ -469,8 +479,11 @@ // target->drawPixmap(pos, pixmap); // if (!fast) // p2.begin(&pixmapBuffer, p.device()); - p.drawPixmap(margins.left + pos.x(), margins.top + pos.y(), pixmap); + pos += QPoint(margins.left, margins.top); + if (p) { + p->drawPixmap(pos, pixmap); } + } /* if (scaledContents && !fast && p.isActive()) { p2.end(); p.drawPixmap( @@ -481,6 +494,24 @@ }*/ } +void KexiUtils::drawPixmap(QPainter& p, const WidgetMargins& margins, const QRect& rect, + const QPixmap& pixmap, Qt::Alignment alignment, bool scaledContents, bool keepAspectRatio, + Qt::TransformationMode transformMode) +{ + QPixmap px(pixmap); + QPoint pos; + drawOrScalePixmapInternal(&p, margins, rect, px, pos, alignment, scaledContents, keepAspectRatio, transformMode); +} + +QPixmap KexiUtils::scaledPixmap(const WidgetMargins& margins, const QRect& rect, + const QPixmap& pixmap, QPoint& pos, Qt::Alignment alignment, + bool scaledContents, bool keepAspectRatio, Qt::TransformationMode transformMode) +{ + QPixmap px(pixmap); + drawOrScalePixmapInternal(0, margins, rect, px, pos, alignment, scaledContents, keepAspectRatio, transformMode); + return px; +} + QString KexiUtils::ptrToStringInternal(void* ptr, uint size) { QString str; --- trunk/koffice/kexi/kexiutils/utils.h #1124235:1124236 @@ -338,11 +338,19 @@ //! \return the sum of \a margins1 and \a margins1; each component is added separately. const WidgetMargins operator+ (const WidgetMargins& margins1, const WidgetMargins& margins2); -//! Draws pixmap on painter \a p using predefined parameters. +//! Draws pixmap @a pixmap on painter @a p using predefined parameters. //! Used in KexiDBImageBox and KexiBlobTableEdit. KEXIUTILS_EXPORT void drawPixmap(QPainter& p, const WidgetMargins& margins, const QRect& rect, - const QPixmap& pixmap, Qt::Alignment alignment, bool scaledContents, bool keepAspectRatio); + const QPixmap& pixmap, Qt::Alignment alignment, bool scaledContents, bool keepAspectRatio, + Qt::TransformationMode transformMode = Qt::FastTransformation); +//! Scales pixmap @a pixmap on painter @a p using predefined parameters. +//! Used in KexiDBImageBox and KexiBlobTableEdit. +KEXIUTILS_EXPORT QPixmap scaledPixmap(const WidgetMargins& margins, const QRect& rect, + const QPixmap& pixmap, QPoint& pos, Qt::Alignment alignment, + bool scaledContents, bool keepAspectRatio, + Qt::TransformationMode transformMode = Qt::FastTransformation); + //! A helper for automatic deleting of contents of containers. template class KEXIUTILS_EXPORT ContainerDeleter --- trunk/koffice/kexi/widget/tableview/kexiblobtableedit.cpp #1124235:1124236 @@ -52,6 +52,11 @@ #include #include +struct PixmapAndPos { + QPixmap pixmap; + QPoint pos; +}; + //! @internal class KexiBlobTableEdit::Private { @@ -68,6 +73,7 @@ KexiImageContextMenu *menu; bool readOnly; //!< cached for slotUpdateActionsAvailabilityRequested() bool setValueInternalEnabled; //!< used to disable KexiBlobTableEdit::setValueInternal() + QCache cachedPixmaps; }; //====================================================== @@ -210,16 +216,42 @@ Q_UNUSED(txt); Q_UNUSED(align); -//! @todo optimize: load to m_pixmap, downsize - QPixmap pixmap; + QPoint pos; + PixmapAndPos *pp = 0; x = 0; w -= 1; //a place for border h -= 1; //a place for border - if (p && val.canConvert(QVariant::ByteArray) && pixmap.loadFromData(val.toByteArray())) { + if (p) { + const QByteArray array(val.toByteArray()); +//! @todo optimize: keep this checksum in context of data +//! @todo optimize: for now 100 items are cached; set proper cache size, e.g. based on the number of blob items visible on screen + // the key is unique for this tuple: (checksum, w, h) + qulonglong sum((((qulonglong(qChecksum(array.constData(), array.length())) << 32) + w) << 16) + h); + pp = d->cachedPixmaps.object(sum); + if (!pp) { + QPixmap pixmap; + if (val.canConvert(QVariant::ByteArray) && pixmap.loadFromData(val.toByteArray())) { +#if 0 KexiUtils::drawPixmap(*p, KexiUtils::WidgetMargins()/*lineWidth*/, QRect(x, y_offset, w, h), pixmap, Qt::AlignCenter, true/*scaledContents*/, true/*keepAspectRatio*/); +#endif + QPoint pos; + pixmap = KexiUtils::scaledPixmap(KexiUtils::WidgetMargins()/*lineWidth*/, QRect(x, y_offset, w, h), + pixmap, pos, Qt::AlignCenter, true/*scaledContents*/, true/*keepAspectRatio*/, + Qt::SmoothTransformation); + if (!pixmap.isNull()) { + pp = new PixmapAndPos; + pp->pixmap = pixmap; + pp->pos = pos; + d->cachedPixmaps.insert(sum, pp); } } + } + if (pp) { + p->drawPixmap(pp->pos, pp->pixmap); + } + } +} bool KexiBlobTableEdit::cursorAtStart() {