File indexing completed on 2024-04-14 15:50:50

0001 /**
0002  * SPDX-FileCopyrightText: (C) 2003 by Sébastien Laoût <slaout@linux62.org>
0003  * SPDX-License-Identifier: GPL-2.0-or-later
0004  */
0005 
0006 #include "basketlistview.h"
0007 
0008 #include <QApplication>
0009 #include <QDebug>
0010 #include <QLocale>
0011 #include <QMimeData>
0012 #include <QToolTip>
0013 #include <QtCore/QRegExp>
0014 #include <QtGui/QBitmap>
0015 #include <QtGui/QDragEnterEvent>
0016 #include <QtGui/QDragLeaveEvent>
0017 #include <QtGui/QDragMoveEvent>
0018 #include <QtGui/QDropEvent>
0019 #include <QtGui/QFocusEvent>
0020 #include <QtGui/QPainter>
0021 #include <QtGui/QPixmap>
0022 #include <QtGui/QPixmapCache>
0023 #include <QtGui/QResizeEvent>
0024 #include <QtGui/QStandardItemModel>
0025 
0026 #include <KIconLoader>
0027 #include <KLocalizedString>
0028 #include <KStringHandler>
0029 
0030 #include "basketscene.h"
0031 #include "bnpview.h"
0032 #include "decoratedbasket.h"
0033 #include "global.h"
0034 #include "icon_names.h"
0035 #include "notedrag.h"
0036 #include "settings.h"
0037 #include "tools.h"
0038 
0039 /** class BasketListViewItem: */
0040 
0041 BasketListViewItem::BasketListViewItem(QTreeWidget *parent, BasketScene *basket)
0042     : QTreeWidgetItem(parent)
0043     , m_basket(basket)
0044     , m_isUnderDrag(false)
0045     , m_isAbbreviated(false)
0046 {
0047 }
0048 
0049 BasketListViewItem::BasketListViewItem(QTreeWidgetItem *parent, BasketScene *basket)
0050     : QTreeWidgetItem(parent)
0051     , m_basket(basket)
0052     , m_isUnderDrag(false)
0053     , m_isAbbreviated(false)
0054 {
0055 }
0056 
0057 BasketListViewItem::BasketListViewItem(QTreeWidget *parent, QTreeWidgetItem *after, BasketScene *basket)
0058     : QTreeWidgetItem(parent, after)
0059     , m_basket(basket)
0060     , m_isUnderDrag(false)
0061     , m_isAbbreviated(false)
0062 {
0063 }
0064 
0065 BasketListViewItem::BasketListViewItem(QTreeWidgetItem *parent, QTreeWidgetItem *after, BasketScene *basket)
0066     : QTreeWidgetItem(parent, after)
0067     , m_basket(basket)
0068     , m_isUnderDrag(false)
0069     , m_isAbbreviated(false)
0070 {
0071 }
0072 
0073 BasketListViewItem::~BasketListViewItem()
0074 {
0075 }
0076 
0077 QString BasketListViewItem::escapedName(const QString &string)
0078 {
0079     // Underlining the Alt+Letter shortcut (and escape all other '&' characters), if any:
0080     QString basketName = string;
0081     basketName.replace('&', "&&"); // First escape all the amperstamp
0082     QString letter;
0083     QRegExp letterExp("^Alt\\+(?:Shift\\+)?(.)$");
0084 
0085     QString basketShortcut = m_basket->shortcut().toString();
0086     if (letterExp.indexIn(basketShortcut) != -1) {
0087         int index;
0088         letter = letterExp.cap(1);
0089         if ((index = basketName.indexOf(letter)) != -1)
0090             basketName.insert(index, '&');
0091     }
0092 
0093     return basketName;
0094 }
0095 
0096 void BasketListViewItem::setup()
0097 {
0098     setText(/*column=*/0, escapedName(m_basket->basketName()));
0099 
0100     QPixmap icon = KIconLoader::global()->loadIcon(m_basket->icon(), KIconLoader::NoGroup, 16, KIconLoader::DefaultState, QStringList(), nullptr, /*canReturnNull=*/false);
0101 
0102     setIcon(/*column=*/0, icon);
0103     /*
0104         QBrush brush;
0105 
0106         bool withIcon = m_stateCopy || (m_tagCopy && !m_tagCopy->isMultiState());
0107         State* state = (m_tagCopy ? m_tagCopy->stateCopies[0]->newState : m_stateCopy->newState);
0108         brush.setColor(isSelected() ? qApp->palette().color(QPalette::Highlight)  : (withIcon && state->backgroundColor().isValid() ? state->backgroundColor() : viewport->palette().color(viewwport->backgroundRole())));
0109         setBackground(brush);
0110         */
0111 }
0112 
0113 BasketListViewItem *BasketListViewItem::lastChild()
0114 {
0115     int count = childCount();
0116     if (count <= 0)
0117         return nullptr;
0118     return (BasketListViewItem *)(child(count - 1));
0119 }
0120 
0121 QStringList BasketListViewItem::childNamesTree(int deep)
0122 {
0123     QStringList result;
0124 
0125     // Compute indentation spaces:
0126     QString spaces;
0127     for (int j = 0; j < deep; ++j)
0128         spaces += "  ";
0129 
0130     // Append the names of sub baskets
0131     if (deep > 0)
0132         result.append(spaces + basket()->basketName());
0133 
0134     // Append the children:
0135     for (int i = 0; i < childCount(); i++) {
0136         QStringList children = ((BasketListViewItem *)child(i))->childNamesTree(deep + 1);
0137         result.append(children);
0138     }
0139     return result;
0140 }
0141 
0142 void BasketListViewItem::moveChildsBaskets()
0143 {
0144     int insertAfterThis = 0;
0145     if (!parent())
0146         insertAfterThis = treeWidget()->indexOfTopLevelItem(this);
0147     for (int i = 0; i < childCount(); i++) {
0148         // Re-insert the item with the good parent:
0149         if (parent())
0150             parent()->insertChild(insertAfterThis, child(i));
0151         else
0152             treeWidget()->insertTopLevelItem(insertAfterThis, child(i));
0153         // And move it at the good place:
0154         insertAfterThis++;
0155     }
0156 }
0157 
0158 void BasketListViewItem::ensureVisible()
0159 {
0160     BasketListViewItem *item = this;
0161     while (item->parent()) {
0162         item = (BasketListViewItem *)(item->parent());
0163         item->setExpanded(true);
0164     }
0165 }
0166 
0167 bool BasketListViewItem::isShown()
0168 {
0169     QTreeWidgetItem *item = parent();
0170     while (item) {
0171         if (!item->isExpanded())
0172             return false;
0173         item = item->parent();
0174     }
0175     return true;
0176 }
0177 
0178 bool BasketListViewItem::isCurrentBasket()
0179 {
0180     return basket() == Global::bnpView->currentBasket();
0181 }
0182 
0183 bool BasketListViewItem::isUnderDrag()
0184 {
0185     return m_isUnderDrag;
0186 }
0187 
0188 bool BasketListViewItem::haveChildsLoading()
0189 {
0190     for (int i = 0; i < childCount(); i++) {
0191         BasketListViewItem *childItem = (BasketListViewItem *)child(i);
0192         if (!childItem->basket()->isLoaded() && !childItem->basket()->isLocked())
0193             return true;
0194         if (childItem->haveChildsLoading())
0195             return true;
0196     }
0197     return false;
0198 }
0199 
0200 bool BasketListViewItem::haveHiddenChildsLoading()
0201 {
0202     if (isExpanded())
0203         return false;
0204     return haveChildsLoading();
0205 }
0206 
0207 bool BasketListViewItem::haveChildsLocked()
0208 {
0209     for (int i = 0; i < childCount(); i++) {
0210         BasketListViewItem *childItem = (BasketListViewItem *)child(i);
0211         if (/*!*/ childItem->basket()->isLocked())
0212             return true;
0213         if (childItem->haveChildsLocked())
0214             return true;
0215     }
0216     return false;
0217 }
0218 
0219 bool BasketListViewItem::haveHiddenChildsLocked()
0220 {
0221     if (isExpanded())
0222         return false;
0223     return haveChildsLocked();
0224 }
0225 
0226 int BasketListViewItem::countChildsFound()
0227 {
0228     int count = 0;
0229     for (int i = 0; i < childCount(); i++) {
0230         BasketListViewItem *childItem = (BasketListViewItem *)child(i);
0231         count += childItem->basket()->countFounds();
0232         count += childItem->countChildsFound();
0233     }
0234     return count;
0235 }
0236 
0237 int BasketListViewItem::countHiddenChildsFound()
0238 {
0239     if (isExpanded())
0240         return 0;
0241     return countChildsFound();
0242 }
0243 
0244 void BasketListViewItem::setUnderDrag(bool underDrag)
0245 {
0246     m_isUnderDrag = underDrag;
0247 }
0248 
0249 bool BasketListViewItem::isAbbreviated()
0250 {
0251     return m_isAbbreviated;
0252 }
0253 
0254 void BasketListViewItem::setAbbreviated(bool b)
0255 {
0256     m_isAbbreviated = b;
0257 }
0258 
0259 /** class BasketTreeListView: */
0260 QString BasketTreeListView::TREE_ITEM_MIME_STRING = "application/x-basket-item";
0261 
0262 BasketTreeListView::BasketTreeListView(QWidget *parent)
0263     : QTreeWidget(parent)
0264     , m_autoOpenItem(nullptr)
0265     , m_itemUnderDrag(nullptr)
0266 {
0267     connect(&m_autoOpenTimer, &QTimer::timeout, this, &BasketTreeListView::autoOpen);
0268     setItemDelegate(new FoundCountIcon(this));
0269 }
0270 
0271 void BasketTreeListView::contextMenuEvent(QContextMenuEvent *e)
0272 {
0273     Q_EMIT contextMenuRequested(e->pos());
0274 }
0275 
0276 QStringList BasketTreeListView::mimeTypes() const
0277 {
0278     QStringList types;
0279     types << TREE_ITEM_MIME_STRING;
0280     types << NoteDrag::NOTE_MIME_STRING;
0281     return types;
0282 }
0283 
0284 QMimeData *BasketTreeListView::mimeData(const QList<QTreeWidgetItem *> items) const
0285 {
0286     QString mimeType = TREE_ITEM_MIME_STRING;
0287 
0288     QByteArray data = QByteArray();
0289     QDataStream out(&data, QIODevice::WriteOnly);
0290 
0291     if (items.isEmpty())
0292         return new QMimeData();
0293 
0294     for (int i = 0; i < items.count(); ++i) {
0295         BasketListViewItem *basketItem = static_cast<BasketListViewItem *>(items[i]);
0296         out << basketItem->basket()->basketName() << basketItem->basket()->folderName() << basketItem->basket()->icon();
0297     }
0298 
0299     QMimeData *mimeData = new QMimeData();
0300 
0301     mimeData->setData(mimeType, data);
0302     return mimeData;
0303 }
0304 
0305 bool BasketTreeListView::event(QEvent *e)
0306 {
0307     if (e->type() == QEvent::ToolTip) {
0308         QHelpEvent *he = static_cast<QHelpEvent *>(e);
0309         QTreeWidgetItem *item = itemAt(he->pos());
0310         BasketListViewItem *bitem = dynamic_cast<BasketListViewItem *>(item);
0311         if (bitem && bitem->isAbbreviated()) {
0312             QRect rect = visualItemRect(bitem);
0313             QToolTip::showText(rect.topLeft(), bitem->basket()->basketName(), viewport(), rect);
0314         }
0315         return true;
0316     }
0317     return QTreeWidget::event(e);
0318 }
0319 
0320 void BasketTreeListView::mousePressEvent(QMouseEvent *event)
0321 {
0322     m_dragStartPosition = event->pos();
0323     QTreeWidget::mousePressEvent(event);
0324 }
0325 
0326 void BasketTreeListView::mouseMoveEvent(QMouseEvent *event)
0327 {
0328     // QTreeWidget::mouseMoveEvent(event);
0329     if (!(event->buttons() & Qt::LeftButton)) {
0330         event->ignore();
0331         return;
0332     }
0333     if ((event->pos() - m_dragStartPosition).manhattanLength() < QApplication::startDragDistance()) {
0334         event->ignore();
0335         return;
0336     }
0337 
0338     QDrag *drag = new QDrag(this);
0339     QMimeData *mimeData = this->mimeData(this->selectedItems());
0340     drag->setMimeData(mimeData);
0341 
0342     Qt::DropAction dropAction = drag->exec(Qt::CopyAction | Qt::MoveAction);
0343     if (dropAction == Qt::MoveAction || dropAction == Qt::CopyAction)
0344         event->accept();
0345 }
0346 
0347 void BasketTreeListView::dragEnterEvent(QDragEnterEvent *event)
0348 {
0349     // TODO: accept everything? (forwarding dropped basket-notes and arbitrary data to the basket)
0350     // files: MoveAction vs. CopyAction, or acceptProposedAction()
0351 
0352     QTreeWidget::dragEnterEvent(event);
0353 }
0354 
0355 void BasketTreeListView::removeExpands()
0356 {
0357     QTreeWidgetItemIterator it(this);
0358     while (*it) {
0359         QTreeWidgetItem *item = *it;
0360         if (item->childCount() <= 0)
0361             item->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless);
0362         ++it;
0363     }
0364 }
0365 
0366 void BasketTreeListView::dragLeaveEvent(QDragLeaveEvent *event)
0367 {
0368     qDebug() << "BasketTreeListView::dragLeaveEvent";
0369     m_autoOpenItem = nullptr;
0370     m_autoOpenTimer.stop();
0371     setItemUnderDrag(nullptr);
0372     removeExpands();
0373     QTreeWidget::dragLeaveEvent(event);
0374 }
0375 
0376 void BasketTreeListView::dropEvent(QDropEvent *event)
0377 {
0378     if (event->mimeData()->hasFormat(TREE_ITEM_MIME_STRING)) {
0379         event->setDropAction(Qt::MoveAction);
0380         QTreeWidget::dropEvent(event);
0381     } else { // this handels application/x-basket-note drag events.
0382         qDebug() << "Forwarding dropped data to the basket";
0383         event->setDropAction(Qt::MoveAction);
0384         QTreeWidgetItem *item = itemAt(event->pos());
0385         BasketListViewItem *bitem = dynamic_cast<BasketListViewItem *>(item);
0386         if (bitem) {
0387             bitem->basket()->blindDrop(event->mimeData(), event->dropAction(), event->source());
0388         } else {
0389             qDebug() << "Forwarding failed: no bitem found";
0390         }
0391     }
0392 
0393     m_autoOpenItem = nullptr;
0394     m_autoOpenTimer.stop();
0395     setItemUnderDrag(nullptr);
0396     removeExpands();
0397 
0398     Global::bnpView->save(); // TODO: Don't save if it was not a basket drop...
0399 }
0400 
0401 void BasketTreeListView::dragMoveEvent(QDragMoveEvent *event)
0402 {
0403     // qDebug() << "BasketTreeListView::dragMoveEvent";
0404 
0405     if (!event->mimeData()->hasFormat(TREE_ITEM_MIME_STRING)) {
0406         QTreeWidgetItem *item = itemAt(event->pos());
0407         BasketListViewItem *bitem = dynamic_cast<BasketListViewItem *>(item);
0408         if (m_autoOpenItem != item) {
0409             m_autoOpenItem = item;
0410             m_autoOpenTimer.setSingleShot(true);
0411             m_autoOpenTimer.start(1700);
0412         }
0413 
0414         if (item) {
0415             event->accept();
0416         }
0417         setItemUnderDrag(bitem);
0418     }
0419 
0420     QTreeWidget::dragMoveEvent(event);
0421 }
0422 
0423 void BasketTreeListView::setItemUnderDrag(BasketListViewItem *item)
0424 {
0425     if (m_itemUnderDrag != item) {
0426         if (m_itemUnderDrag) {
0427             // Remove drag status from the old item
0428             m_itemUnderDrag->setUnderDrag(false);
0429         }
0430 
0431         m_itemUnderDrag = item;
0432 
0433         if (m_itemUnderDrag) {
0434             // add drag status to the new item
0435             m_itemUnderDrag->setUnderDrag(true);
0436         }
0437     }
0438 }
0439 
0440 void BasketTreeListView::autoOpen()
0441 {
0442     BasketListViewItem *item = (BasketListViewItem *)m_autoOpenItem;
0443     if (item)
0444         Global::bnpView->setCurrentBasket(item->basket());
0445 }
0446 
0447 void BasketTreeListView::resizeEvent(QResizeEvent *event)
0448 {
0449     QTreeWidget::resizeEvent(event);
0450 }
0451 
0452 /** We should NEVER get focus (because of QWidget::NoFocus focusPolicy())
0453  * but QTreeView can programatically give us the focus.
0454  * So we give it to the basket.
0455  */
0456 void BasketTreeListView::focusInEvent(QFocusEvent *)
0457 {
0458     BasketScene *basket = Global::bnpView->currentBasket();
0459     if (basket)
0460         basket->setFocus();
0461 }
0462 
0463 Qt::DropActions BasketTreeListView::supportedDropActions() const
0464 {
0465     return Qt::MoveAction | Qt::CopyAction;
0466 }
0467 
0468 BasketListViewItem *BasketTreeListView::getBasketInTree(const QModelIndex &index) const
0469 {
0470     QTreeWidgetItem *item = itemFromIndex(index);
0471     return dynamic_cast<BasketListViewItem *>(item);
0472 }
0473 
0474 void FoundCountIcon::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
0475 {
0476     QStyledItemDelegate::paint(painter, option, index);
0477 
0478     // Get access to basket pointer
0479     BasketListViewItem *basketInTree = m_basketTree->getBasketInTree(index);
0480     if (basketInTree == nullptr)
0481         return;
0482 
0483     const int BASKET_ICON_SIZE = 16; // [replace with m_basketTree->iconSize()]
0484     const int MARGIN = 1;
0485 
0486     BasketScene *basket = basketInTree->basket();
0487 
0488     // If we are filtering all baskets, and are effectively filtering on something:
0489     bool showLoadingIcon = false;
0490     bool showEncryptedIcon = false;
0491     QPixmap countPixmap;
0492     bool showCountPixmap = Global::bnpView->isFilteringAllBaskets() && Global::bnpView->currentBasket()->decoration()->filterBar()->filterData().isFiltering;
0493     if (showCountPixmap) {
0494         showLoadingIcon = (!basket->isLoaded() && !basket->isLocked()) || basketInTree->haveHiddenChildsLoading();
0495         showEncryptedIcon = basket->isLocked() || basketInTree->haveHiddenChildsLocked();
0496         bool childrenAreLoading = basketInTree->haveHiddenChildsLoading() || basketInTree->haveHiddenChildsLocked();
0497 
0498         countPixmap = foundCountPixmap(!basket->isLoaded(), basket->countFounds(), childrenAreLoading, basketInTree->countHiddenChildsFound(), m_basketTree->font(), option.rect.height() - 2 * MARGIN);
0499     }
0500     int effectiveWidth = option.rect.right() - (countPixmap.isNull() ? 0 : countPixmap.width() + MARGIN) - (showLoadingIcon || showEncryptedIcon ? BASKET_ICON_SIZE + MARGIN : 0);
0501 
0502     bool drawRoundRect = basket->backgroundColorSetting().isValid() || basket->textColorSetting().isValid();
0503 
0504     // Draw the rounded rectangle:
0505     if (drawRoundRect) {
0506         QPixmap roundRectBmp;
0507         QColor background = basket->backgroundColor();
0508         int textWidth = m_basketTree->fontMetrics().horizontalAdvance(basketInTree->text(/*column=*/0));
0509         int iconTextMargin = m_basketTree->style()->pixelMetric(QStyle::PM_FocusFrameHMargin); ///< Space between icon and text
0510 
0511         // Don't forget to update the key computation if parameters
0512         // affecting the rendering logic change
0513         QString key = QString("BLIRR::%1.%2.%3.%4").arg(option.rect.width()).arg(option.rect.size().height()).arg(textWidth).arg(background.rgb());
0514         if (!QPixmapCache::find(key, &roundRectBmp)) {
0515             // Draw first time
0516 
0517             roundRectBmp = QPixmap(option.rect.size());
0518             roundRectBmp.fill(Qt::transparent);
0519 
0520             QPainter brushPainter(&roundRectBmp);
0521 
0522             int cornerR = option.rect.height() / 2 - MARGIN;
0523 
0524             QRect roundRect(0, MARGIN, BASKET_ICON_SIZE + iconTextMargin + textWidth + 2 * cornerR, option.rect.height() - 2 * MARGIN);
0525 
0526             brushPainter.setPen(background);
0527             brushPainter.setBrush(background);
0528             brushPainter.setRenderHint(QPainter::Antialiasing);
0529             brushPainter.drawRoundedRect(roundRect, cornerR, cornerR);
0530 
0531             QPixmapCache::insert(key, roundRectBmp);
0532         }
0533 
0534         basketInTree->setBackground(0, QBrush(roundRectBmp));
0535         basketInTree->setForeground(0, QBrush(basket->textColor()));
0536     }
0537     // end if drawRoundRect
0538 
0539     // Render icons on the right
0540     int y = option.rect.center().y() - BASKET_ICON_SIZE / 2;
0541 
0542     if (!countPixmap.isNull()) {
0543         painter->drawPixmap(effectiveWidth, y, countPixmap);
0544         effectiveWidth += countPixmap.width() + MARGIN;
0545     }
0546     if (showLoadingIcon) {
0547         QPixmap icon = KIconLoader::global()->loadIcon(IconNames::LOADING, KIconLoader::NoGroup, BASKET_ICON_SIZE);
0548         painter->drawPixmap(effectiveWidth, y, icon);
0549         effectiveWidth += BASKET_ICON_SIZE + MARGIN;
0550     }
0551     if (showEncryptedIcon && !showLoadingIcon) {
0552         QPixmap icon = KIconLoader::global()->loadIcon(IconNames::LOCKED, KIconLoader::NoGroup, BASKET_ICON_SIZE);
0553         painter->drawPixmap(effectiveWidth, y, icon);
0554     }
0555 }
0556 
0557 QPixmap FoundCountIcon::circledTextPixmap(const QString &text, int height, const QFont &font, const QColor &color) const
0558 {
0559     QString key = QString("BLI-%1.%2.%3.%4").arg(text).arg(height).arg(font.toString()).arg(color.rgb());
0560     QPixmap cached;
0561     if (QPixmapCache::find(key, &cached)) {
0562         return cached;
0563     }
0564 
0565     // Compute the sizes of the image components:
0566     QRectF textRect = QFontMetrics(font).boundingRect(0, 0, /*width=*/1, height, Qt::AlignLeft | Qt::AlignTop, text);
0567     qreal xMargin = height / 6;
0568     qreal width = xMargin + textRect.width() + xMargin;
0569 
0570     // Create the background image:
0571     QPixmap background(3 * width, 3 * height); // We double the size to be able to smooth scale down it (== antialiased curves)
0572     QPainter backgroundPainter(&background);
0573     const QPalette &palette = m_basketTree->palette();
0574     backgroundPainter.fillRect(0, 0, background.width(), background.height(), palette.color(QPalette::Highlight));
0575     backgroundPainter.end();
0576 
0577     // Draw the curved rectangle:
0578     QBitmap curvedRectangle(3 * width, 3 * height);
0579     curvedRectangle.fill(Qt::color0);
0580     QPainter curvePainter(&curvedRectangle);
0581     curvePainter.setPen(Qt::color1);
0582     curvePainter.setBrush(Qt::color1);
0583     curvePainter.setClipRect(0, 0, 3 * (height / 5), 3 * (height));                     // If the width is small, don't fill the right part of the pixmap
0584     curvePainter.drawEllipse(0, 3 * (-height / 4), 3 * (height), 3 * (height * 3 / 2)); // Don't forget we double the sizes
0585     curvePainter.setClipRect(3 * (width - height / 5), 0, 3 * (height / 5), 3 * (height));
0586     curvePainter.drawEllipse(3 * (width - height), 3 * (-height / 4), 3 * (height), 3 * (height * 3 / 2));
0587     curvePainter.setClipping(false);
0588     curvePainter.fillRect(3 * (height / 6), 0, 3 * (width - 2 * height / 6), 3 * (height), curvePainter.brush());
0589     curvePainter.end();
0590 
0591     // Apply the curved rectangle as the mask of the background:
0592     background.setMask(curvedRectangle);
0593     QImage resultImage = background.toImage();
0594 
0595     // resultImage.setAlphaBuffer(true);
0596     // resultImage.convertToFormat(QImage::Format_ARGB32);
0597 
0598     // Scale down the image smoothly to get anti-aliasing:
0599     QPixmap pmScaled = QPixmap::fromImage(resultImage.scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
0600 
0601     // Draw the text, and return the result:
0602     QPainter painter(&pmScaled);
0603     painter.setPen(color);
0604     painter.setFont(font);
0605     painter.drawText(0 + 1, 0, width, height, Qt::AlignHCenter | Qt::AlignVCenter, text);
0606     painter.end();
0607 
0608     QPixmapCache::insert(key, pmScaled);
0609 
0610     return pmScaled;
0611 }
0612 
0613 QPixmap FoundCountIcon::foundCountPixmap(bool isLoading, int countFound, bool childrenAreLoading, int countChildsFound, const QFont &font, int height) const
0614 {
0615     if (isLoading)
0616         return QPixmap();
0617 
0618     QFont boldFont(font);
0619     boldFont.setBold(true);
0620 
0621     QString text;
0622     if (childrenAreLoading) {
0623         if (countChildsFound > 0)
0624             text = i18n("%1+%2+", QString::number(countFound), QString::number(countChildsFound));
0625         else
0626             text = i18n("%1+", QString::number(countFound));
0627     } else {
0628         if (countChildsFound > 0)
0629             text = i18n("%1+%2", QString::number(countFound), QString::number(countChildsFound));
0630         else if (countFound > 0)
0631             text = QString::number(countFound);
0632         else
0633             return QPixmap();
0634     }
0635 
0636     return circledTextPixmap(text, height, boldFont, m_basketTree->palette().color(QPalette::HighlightedText));
0637 }
0638 
0639 #include "moc_basketlistview.cpp"