Updated the README file with some contributor tips.
[basket4.git] / src / basketlistview.cpp
blobc4e344c6e18d5c3e3e39cb6be6e79b972cf34bde
1 /***************************************************************************
2 * Copyright (C) 2003 by S�astien Laot *
3 * slaout@linux62.org *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
21 #include "basketlistview.h"
22 #include <qregexp.h>
23 //Added by qt3to4:
24 #include <QDragLeaveEvent>
25 #include <QPixmap>
26 #include <QDragEnterEvent>
27 #include <QDragMoveEvent>
28 #include <QDropEvent>
29 #include <QResizeEvent>
30 #include <QFocusEvent>
31 #include <kglobalsettings.h>
32 #include <kiconloader.h>
33 #include <klocale.h>
34 #include <kstringhandler.h>
35 #include <qpainter.h>
36 #include <qbitmap.h>
37 #include <qpixmapcache.h>
38 #include <qtooltip.h>
39 #include <iostream>
40 #include <kdebug.h>
41 #include "global.h"
42 #include "bnpview.h"
43 #include "basket.h"
44 #include "tools.h"
45 #include "settings.h"
46 #include "notedrag.h"
48 /** class BasketListViewItem: */
50 BasketListViewItem::BasketListViewItem(Q3ListView *parent, Basket *basket)
51 : Q3ListViewItem(parent), m_basket(basket)
52 , m_isUnderDrag(false)
53 , m_isAbbreviated(false)
55 setDropEnabled(true);
58 BasketListViewItem::BasketListViewItem(Q3ListViewItem *parent, Basket *basket)
59 : Q3ListViewItem(parent), m_basket(basket)
60 , m_isUnderDrag(false)
61 , m_isAbbreviated(false)
63 setDropEnabled(true);
66 BasketListViewItem::BasketListViewItem(Q3ListView *parent, Q3ListViewItem *after, Basket *basket)
67 : Q3ListViewItem(parent, after), m_basket(basket)
68 , m_isUnderDrag(false)
69 , m_isAbbreviated(false)
71 setDropEnabled(true);
74 BasketListViewItem::BasketListViewItem(Q3ListViewItem *parent, Q3ListViewItem *after, Basket *basket)
75 : Q3ListViewItem(parent, after), m_basket(basket)
76 , m_isUnderDrag(false)
77 , m_isAbbreviated(false)
79 setDropEnabled(true);
82 BasketListViewItem::~BasketListViewItem()
86 bool BasketListViewItem::acceptDrop(const QMimeSource *) const
88 std::cout << "accept" << std::endl;
89 return true;
92 void BasketListViewItem::dropped(QDropEvent *event)
94 std::cout << "Dropping into basket " << m_basket->name() << std::endl;
95 m_basket->contentsDropEvent(event);
96 //Global::bnpView->currentBasket()->contentsDropEvent(event); // FIXME
99 int BasketListViewItem::width(const QFontMetrics &/* fontMetrics */, const Q3ListView */*listView*/, int /* column */) const
101 return listView()->visibleWidth() + 100;
103 int BASKET_ICON_SIZE = 16;
104 int MARGIN = 1;
106 QRect textRect = fontMetrics.boundingRect(0, 0, / *width=* /1, 500000, Qt::AlignLeft | Qt::AlignTop | Qt::TextShowMnemonic, text(column));
108 return MARGIN + BASKET_ICON_SIZE + MARGIN + textRect.width() + BASKET_ICON_SIZE/2 + MARGIN;
112 QString BasketListViewItem::escapedName(const QString &string)
114 // Underlining the Alt+Letter shortcut (and escape all other '&' characters), if any:
115 QString basketName = string;
116 basketName.replace('&', "&&"); // First escape all the amperstamp
117 QString letter; // Find the letter
118 QString altKey = /*i18n(*/"Alt"/*)*/; //i18n("The [Alt] key, as shown in shortcuts like Alt+C...", "Alt");
119 QString shiftKey = /*i18n(*/"Shift"/*)*/; //i18n("The [Shift] key, as shown in shortcuts like Alt+Shift+1...", "Shift");
120 QRegExp altLetterExp( QString("^%1\\+(.)$").arg(altKey) );
121 QRegExp altShiftLetterExp( QString("^%1\\+%2\\+(.)$").arg(altKey, shiftKey) );
122 if (altLetterExp.search(m_basket->shortcut().toStringInternal()) != -1)
123 letter = altLetterExp.cap(1);
124 if (letter.isEmpty() && altShiftLetterExp.search(m_basket->shortcut().toStringInternal()) != -1)
125 letter = altShiftLetterExp.cap(1);
126 if (!letter.isEmpty()) {
127 int index = basketName.find(letter, /*index=*/0, /*caseSensitive=*/false);
128 if (index != -1)
129 basketName.insert(index, '&');
131 return basketName;
134 void BasketListViewItem::setup()
136 int BASKET_ICON_SIZE = 16;
137 int MARGIN = 1;
139 setText(/*column=*/0, escapedName(m_basket->basketName()));
141 widthChanged();
142 QRect textRect = listView()->fontMetrics().boundingRect(0, 0, /*width=*/1, 500000, Qt::AlignLeft | Qt::AlignTop | Qt::TextShowMnemonic, text(/*column=*/0));
144 int height = MARGIN + qMax(BASKET_ICON_SIZE, textRect.height()) + MARGIN;
145 setHeight(height);
147 QPixmap icon = kapp->iconLoader()->loadIcon(m_basket->icon(), KIconLoader::NoGroup, 16, KIconLoader::DefaultState, 0L, /*canReturnNull=*/false);
149 setPixmap(/*column=*/0, icon);
151 repaint();
154 BasketListViewItem* BasketListViewItem::lastChild()
156 Q3ListViewItem *child = firstChild();
157 while (child) {
158 if (child->nextSibling())
159 child = child->nextSibling();
160 else
161 return (BasketListViewItem*)child;
163 return 0;
166 BasketListViewItem* BasketListViewItem::prevSibling()
168 BasketListViewItem *item = this;
169 while (item) {
170 if (item->nextSibling() == this)
171 return item;
172 item = (BasketListViewItem*)(item->itemAbove());
174 return 0;
177 BasketListViewItem* BasketListViewItem::shownItemAbove()
179 BasketListViewItem *item = (BasketListViewItem*)itemAbove();
180 while (item) {
181 if (item->isShown())
182 return item;
183 item = (BasketListViewItem*)(item->itemAbove());
185 return 0;
188 BasketListViewItem* BasketListViewItem::shownItemBelow()
190 BasketListViewItem *item = (BasketListViewItem*)itemBelow();
191 while (item) {
192 if (item->isShown())
193 return item;
194 item = (BasketListViewItem*)(item->itemBelow());
196 return 0;
199 QStringList BasketListViewItem::childNamesTree(int deep)
201 QStringList result;
202 for (Q3ListViewItem *child = firstChild(); child; child = child->nextSibling()) {
203 BasketListViewItem *item = (BasketListViewItem*)child;
204 // Compute indentation spaces:
205 QString spaces;
206 for (int i = 0; i < deep; ++i)
207 spaces += " ";
208 // Append the name:
209 result.append(spaces + item->basket()->basketName());
210 // Append the childs:
211 if (child->firstChild()) {
212 QStringList childs = item->childNamesTree(deep + 1);
213 for (QStringList::iterator it = childs.begin(); it != childs.end(); ++it)
214 result.append(*it);
217 return result;
220 void BasketListViewItem::moveChildsBaskets()
222 Q3ListViewItem *insertAfterThis = this;
223 Q3ListViewItem *nextOne;
224 for (Q3ListViewItem *child = firstChild(); child; child = nextOne) {
225 nextOne = child->nextSibling();
226 // Re-insert the item with the good parent:
227 takeItem(child);
228 if (parent())
229 parent()->insertItem(child);
230 else
231 listView()->insertItem(child);
232 // And move it at the good place:
233 child->moveItem(insertAfterThis);
234 insertAfterThis = child;
238 void BasketListViewItem::ensureVisible()
240 BasketListViewItem *item = this;
241 while (item->parent()) {
242 item = (BasketListViewItem*)(item->parent());
243 item->setOpen(true);
247 bool BasketListViewItem::isShown()
249 Q3ListViewItem *item = parent();
250 while (item) {
251 if (!item->isOpen())
252 return false;
253 item = item->parent();
255 return true;
258 bool BasketListViewItem::isCurrentBasket()
260 return basket() == Global::bnpView->currentBasket();
263 // TODO: Move this function from item.cpp to class Tools:
264 extern void drawGradient( QPainter *p, const QColor &colorTop, const QColor & colorBottom,
265 int x, int y, int w, int h,
266 bool sunken, bool horz, bool flat ); /*const*/
268 QPixmap BasketListViewItem::circledTextPixmap(const QString &text, int height, const QFont &font, const QColor &color)
270 QString key = QString("BLI-%1.%2.%3.%4")
271 .arg(text).arg(height).arg(font.toString()).arg(color.rgb());
272 if (QPixmap* cached=QPixmapCache::find(key)) {
273 return *cached;
276 // Compute the sizes of the image components:
277 QRect textRect = QFontMetrics(font).boundingRect(0, 0, /*width=*/1, height, Qt::AlignLeft | Qt::AlignTop, text);
278 int xMargin = height / 6;
279 int width = xMargin + textRect.width() + xMargin;
281 // Create the gradient image:
282 QPixmap gradient(3 * width, 3 * height); // We double the size to be able to smooth scale down it (== antialiased curves)
283 QPainter gradientPainter(&gradient);
284 #if 1 // Enable the new look of the gradient:
285 QColor topColor = KGlobalSettings::highlightColor().light(130); //120
286 QColor topMidColor = KGlobalSettings::highlightColor().light(105); //105
287 QColor bottomMidColor = KGlobalSettings::highlightColor().dark(130); //120
288 QColor bottomColor = KGlobalSettings::highlightColor();
289 drawGradient(&gradientPainter, topColor, topMidColor,
290 0, 0, gradient.width(), gradient.height() / 2, /*sunken=*/false, /*horz=*/true, /*flat=*/false);
291 drawGradient(&gradientPainter, bottomMidColor, bottomColor,
292 0, gradient.height() / 2, gradient.width(), gradient.height() - gradient.height() / 2, /*sunken=*/false, /*horz=*/true, /*flat=*/false);
293 gradientPainter.fillRect(0, 0, gradient.width(), 3, KGlobalSettings::highlightColor());
294 #else
295 drawGradient(&gradientPainter, KGlobalSettings::highlightColor(), KGlobalSettings::highlightColor().dark(),
296 0, 0, gradient.width(), gradient.height(), /*sunken=*/false, /*horz=*/true, /*flat=*/false);
297 #endif
298 gradientPainter.end();
300 // Draw the curved rectangle:
301 QBitmap curvedRectangle(3 * width, 3 * height);
302 curvedRectangle.fill(Qt::color0);
303 QPainter curvePainter(&curvedRectangle);
304 curvePainter.setPen(Qt::color1);
305 curvePainter.setBrush(Qt::color1);
306 curvePainter.setClipRect(0, 0, 3*(height / 5), 3*(height)); // If the width is small, don't fill the right part of the pixmap
307 curvePainter.drawEllipse(0, 3*(-height / 4), 3*(height), 3*(height * 3 / 2)); // Don't forget we double the sizes
308 curvePainter.setClipRect(3*(width - height / 5), 0, 3*(height / 5), 3*(height));
309 curvePainter.drawEllipse(3*(width - height), 3*(-height / 4), 3*(height), 3*(height * 3 / 2));
310 curvePainter.setClipping(false);
311 curvePainter.fillRect(3*(height / 6), 0, 3*(width - 2 * height / 6), 3*(height), curvePainter.brush());
312 curvePainter.end();
314 // Apply the curved rectangle as the mask of the gradient:
315 gradient.setMask(curvedRectangle);
316 QImage resultImage = gradient.convertToImage();
317 resultImage.setAlphaBuffer(true);
319 // Scale down the image smoothly to get anti-aliasing:
320 QPixmap pmScaled;
321 pmScaled.convertFromImage(resultImage.smoothScale(width, height));
323 // Draw the text, and return the result:
324 QPainter painter(&pmScaled);
325 painter.setPen(color);
326 painter.setFont(font);
327 painter.drawText(0+1, 0, width, height, Qt::AlignHCenter | Qt::AlignVCenter, text);
328 painter.end();
330 QPixmapCache::insert(key, pmScaled);
332 return pmScaled;
335 QPixmap BasketListViewItem::foundCountPixmap(bool isLoading, int countFound, bool childsAreLoading, int countChildsFound, const QFont &font, int height)
337 if (isLoading)
338 return QPixmap();
340 QFont boldFont(font);
341 boldFont.setBold(true);
343 QString text;
344 if (childsAreLoading) {
345 if (countChildsFound > 0)
346 text = i18n("%1+%2+").arg(QString::number(countFound), QString::number(countChildsFound));
347 else
348 text = i18n("%1+").arg(QString::number(countFound));
349 } else {
350 if (countChildsFound > 0)
351 text = i18n("%1+%2").arg(QString::number(countFound), QString::number(countChildsFound));
352 else if (countFound > 0)
353 text = QString::number(countFound);
354 else
355 return QPixmap();
358 return circledTextPixmap(text, height, boldFont, KGlobalSettings::highlightedTextColor());
361 bool BasketListViewItem::haveChildsLoading()
363 Q3ListViewItem *child = firstChild();
364 while (child) {
365 BasketListViewItem *childItem = (BasketListViewItem*)child;
366 if (!childItem->basket()->isLoaded() && !childItem->basket()->isLocked())
367 return true;
368 if (childItem->haveChildsLoading())
369 return true;
370 child = child->nextSibling();
372 return false;
375 bool BasketListViewItem::haveHiddenChildsLoading()
377 if (isOpen())
378 return false;
379 return haveChildsLoading();
382 bool BasketListViewItem::haveChildsLocked()
384 Q3ListViewItem *child = firstChild();
385 while (child) {
386 BasketListViewItem *childItem = (BasketListViewItem*)child;
387 if (/*!*/childItem->basket()->isLocked())
388 return true;
389 if (childItem->haveChildsLocked())
390 return true;
391 child = child->nextSibling();
393 return false;
396 bool BasketListViewItem::haveHiddenChildsLocked()
398 if (isOpen())
399 return false;
400 return haveChildsLocked();
403 int BasketListViewItem::countChildsFound()
405 int count = 0;
406 Q3ListViewItem *child = firstChild();
407 while (child) {
408 BasketListViewItem *childItem = (BasketListViewItem*)child;
409 count += childItem->basket()->countFounds();
410 count += childItem->countChildsFound();
411 child = child->nextSibling();
413 return count;
416 int BasketListViewItem::countHiddenChildsFound()
418 if (isOpen())
419 return 0;
420 return countChildsFound();
423 void BasketListViewItem::paintCell(QPainter *painter, const QColorGroup &/*colorGroup*/, int /*column*/, int width, int /*align*/)
425 // Workaround a Qt bug:
426 // When the splitter is moved to hide the tree view and then the application is restarted,
427 // Qt try to draw items with a negative size!
428 if (width <= 0) {
429 std::cout << "width <= 0" << std::endl;
430 return;
433 int BASKET_ICON_SIZE = 16;
434 int MARGIN = 1;
437 // If we are filtering all baskets, and are effectively filtering on something:
438 bool showLoadingIcon = false;
439 bool showEncryptedIcon = false;
440 QPixmap countPixmap;
441 bool showCountPixmap = Global::bnpView->isFilteringAllBaskets() &&
442 Global::bnpView->currentBasket()->decoration()->filterBar()->filterData().isFiltering;
443 if (showCountPixmap) {
444 showLoadingIcon = (!m_basket->isLoaded() && !m_basket->isLocked()) || haveHiddenChildsLoading();
445 showEncryptedIcon = m_basket->isLocked() || haveHiddenChildsLocked();
446 countPixmap = foundCountPixmap(!m_basket->isLoaded(), m_basket->countFounds(), haveHiddenChildsLoading() || haveHiddenChildsLocked(),
447 countHiddenChildsFound(), listView()->font(), height() - 2 * MARGIN);
449 int effectiveWidth = width - (countPixmap.isNull() ? 0 : countPixmap.width() + MARGIN)
450 - (showLoadingIcon || showEncryptedIcon ? BASKET_ICON_SIZE + MARGIN : 0)/*
451 - (showEncryptedIcon ? BASKET_ICON_SIZE + MARGIN : 0)*/;
454 bool drawRoundRect = m_basket->backgroundColorSetting().isValid() || m_basket->textColorSetting().isValid();
455 QColor textColor = (drawRoundRect ? m_basket->textColor() : (isCurrentBasket() ? KGlobalSettings::highlightedTextColor() : KGlobalSettings::textColor()));
457 BasketListViewItem *shownAbove = shownItemAbove();
458 BasketListViewItem *shownBelow = shownItemBelow();
460 // Don't forget to update the key computation if parameters
461 // affecting the rendering logic change
462 QString key = QString("BLVI::pC-%1.%2.%3.%4.%5.%6.%7.%8.%9.%10.%11.%12.%13.%14.%15")
463 .arg(effectiveWidth)
464 .arg(drawRoundRect)
465 .arg(textColor.rgb())
466 .arg(m_basket->backgroundColor().rgb())
467 .arg(isCurrentBasket())
468 .arg(shownBelow && shownBelow->isCurrentBasket())
469 .arg(shownAbove && shownAbove->isCurrentBasket())
470 .arg(showLoadingIcon)
471 .arg(showEncryptedIcon)
472 .arg(showCountPixmap)
473 .arg(m_basket->countFounds())
474 .arg(countHiddenChildsFound())
475 .arg(m_isUnderDrag)
476 .arg(m_basket->basketName())
477 .arg(m_basket->icon());
478 if (QPixmap* cached = QPixmapCache::find(key)) {
479 // Qt's documentation recommends copying the pointer
480 // into a QPixmap immediately
481 QPixmap cachedBuffer = *cached;
482 painter->drawPixmap(0, 0, cachedBuffer);
483 return;
486 // Bufferize the drawing of items (otherwize, resizing the splitter make the tree act like a Christmas Tree ;-D ):
487 QPixmap theBuffer(width, height());
488 QPainter thePainter(&theBuffer);
490 // Fill with the basket background color:
491 QColor background = (isCurrentBasket() ? KGlobalSettings::highlightColor() : listView()->paletteBackgroundColor());
492 thePainter.fillRect(0, 0, width, height(), background);
494 int textWidth = effectiveWidth - MARGIN - BASKET_ICON_SIZE - MARGIN - MARGIN;
496 // Draw the rounded rectangle:
497 if (drawRoundRect) {
498 QRect textRect = listView()->fontMetrics().boundingRect(0, 0, /*width=*/1, 500000, Qt::AlignLeft | Qt::AlignTop | Qt::TextShowMnemonic, text(/*column=*/0));
499 int xRound = MARGIN;
500 int yRound = MARGIN;
501 int hRound = height() - 2 * MARGIN;
502 int wRound = qMin(BASKET_ICON_SIZE + MARGIN + textRect.width() + hRound/2, effectiveWidth - MARGIN - MARGIN);
503 if (wRound > 0) { // Do not crash if there is no space anymore to draw the rounded rectangle:
504 QPixmap buffer(wRound * 2, hRound * 2);
505 buffer.fill(background);
506 QPainter pBuffer(&buffer);
507 QColor colorRound = m_basket->backgroundColor();
508 pBuffer.setPen(colorRound);
509 pBuffer.setBrush(colorRound);
510 if (wRound > hRound) { // If the rectangle is smaller in width than in height, don't overlap ellipses...
511 pBuffer.drawEllipse(0, 0, hRound * 2, hRound * 2);
512 pBuffer.drawEllipse(wRound * 2 - hRound * 2, 0, hRound * 2, hRound * 2);
513 pBuffer.fillRect(hRound*2/2, 0, wRound * 2 - hRound * 2, hRound * 2, colorRound);
514 } else
515 pBuffer.drawEllipse(0, 0, wRound * 2, hRound * 2);
516 pBuffer.end();
517 QImage imageToScale = buffer.convertToImage();
518 QPixmap pmScaled;
519 pmScaled.convertFromImage(imageToScale.smoothScale(wRound, hRound));
520 thePainter.drawPixmap(xRound, yRound, pmScaled);
521 textWidth -= hRound/2;
525 QColor bgColor = listView()->paletteBackgroundColor();
526 QColor selColor = KGlobalSettings::highlightColor();
527 QColor midColor = Tools::mixColor(bgColor, selColor);
528 // Draw the left selection roundings:
529 if (isCurrentBasket()) {
530 thePainter.setPen(bgColor);
531 thePainter.drawPoint(0, 0);
532 thePainter.drawPoint(1, 0);
533 thePainter.drawPoint(0, 1);
534 thePainter.drawPoint(0, height() - 1);
535 thePainter.drawPoint(1, height() - 1);
536 thePainter.drawPoint(0, height() - 2);
537 thePainter.setPen(midColor);
538 thePainter.drawPoint(2, 0);
539 thePainter.drawPoint(0, 2);
540 thePainter.drawPoint(2, height() - 1);
541 thePainter.drawPoint(0, height() - 3);
543 // Draw the bottom-right selection roundings:
544 //BasketListViewItem *shownBelow = shownItemBelow();
545 if (shownBelow && shownBelow->isCurrentBasket()) {
546 thePainter.setPen(selColor);
547 thePainter.drawPoint(width - 1, height() - 1);
548 thePainter.drawPoint(width - 2, height() - 1);
549 thePainter.drawPoint(width - 1, height() - 2);
550 thePainter.setPen(midColor);
551 thePainter.drawPoint(width - 3, height() - 1);
552 thePainter.drawPoint(width - 1, height() - 3);
554 // Draw the top-right selection roundings:
555 // BasketListViewItem *shownAbove = shownItemAbove();
556 if (shownAbove && shownAbove->isCurrentBasket()) {
557 thePainter.setPen(selColor);
558 thePainter.drawPoint(width - 1, 0);
559 thePainter.drawPoint(width - 2, 0);
560 thePainter.drawPoint(width - 1, 1);
561 thePainter.setPen(midColor);
562 thePainter.drawPoint(width - 3, 0);
563 thePainter.drawPoint(width - 1, 2);
566 // Draw the icon and text:
567 int yPixmap = (height() - BASKET_ICON_SIZE) / 2;
568 thePainter.drawPixmap(MARGIN, yPixmap, *pixmap(/*column=*/0));
569 thePainter.setPen(textColor);
570 if (textWidth > 0) { // IF there is space left to draw the text:
571 int xText = MARGIN + BASKET_ICON_SIZE + MARGIN;
572 QString theText = m_basket->basketName();
573 if (painter->fontMetrics().width(theText) > textWidth) {
574 theText = KStringHandler::rPixelSqueeze(theText, painter->fontMetrics(), textWidth);
575 m_isAbbreviated = true;
577 else {
578 m_isAbbreviated = false;
580 theText = escapedName(theText);
581 thePainter.drawText(xText, 0, textWidth, height(), Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, theText);
584 // If we are filtering all baskets, and are effectively filtering on something:
585 if (!countPixmap.isNull())
587 thePainter.drawPixmap(effectiveWidth, 1, countPixmap);
588 effectiveWidth += countPixmap.width() + MARGIN;
590 if (showLoadingIcon) {
591 QPixmap icon = kapp->iconLoader()->loadIcon("find", KIconLoader::NoGroup, 16, KIconLoader::DefaultState, 0L, /*canReturnNull=*/false);
592 thePainter.drawPixmap(effectiveWidth, 0, icon);
593 effectiveWidth += BASKET_ICON_SIZE + MARGIN;
595 if (showEncryptedIcon && !showLoadingIcon) {
596 QPixmap icon = kapp->iconLoader()->loadIcon("encrypted", KIconLoader::NoGroup, 16, KIconLoader::DefaultState, 0L, /*canReturnNull=*/false);
597 thePainter.drawPixmap(effectiveWidth, 0, icon);
600 if (m_isUnderDrag) {
601 thePainter.drawWinFocusRect(0, 0, width, height());
603 thePainter.end();
605 QPixmapCache::insert(key, theBuffer);
606 // Apply the buffer:
607 painter->drawPixmap(0, 0, theBuffer);
610 void BasketListViewItem::setUnderDrag(bool underDrag)
612 m_isUnderDrag = underDrag;
615 bool BasketListViewItem::isAbbreviated()
617 return m_isAbbreviated;
620 /** class BasketListViewToolTip: */
622 class BasketTreeListView_ToolTip : public QToolTip {
623 public:
624 BasketTreeListView_ToolTip(BasketTreeListView* basketView)
625 : QToolTip(basketView->viewport())
626 , m_basketView(basketView)
628 public:
629 void maybeTip(const QPoint& pos)
631 Q3ListViewItem *item = m_basketView->itemAt(m_basketView->contentsToViewport(pos));
632 BasketListViewItem* bitem = dynamic_cast<BasketListViewItem*>(item);
633 if (bitem && bitem->isAbbreviated()) {
634 tip(m_basketView->itemRect(bitem), bitem->basket()->basketName());
637 private:
638 BasketTreeListView* m_basketView;
641 /** class BasketTreeListView: */
643 BasketTreeListView::BasketTreeListView(QWidget *parent, const char *name)
644 : K3ListView(parent, name), m_autoOpenItem(0)
645 , m_itemUnderDrag(0)
647 setWFlags(Qt::WStaticContents | WNoAutoErase);
648 clearWFlags(Qt::WStaticContents | WNoAutoErase);
649 //viewport()->clearWFlags(Qt::WStaticContents);
650 connect( &m_autoOpenTimer, SIGNAL(timeout()), this, SLOT(autoOpen()) );
652 new BasketTreeListView_ToolTip(this);
655 void BasketTreeListView::viewportResizeEvent(QResizeEvent *event)
657 K3ListView::viewportResizeEvent(event);
658 triggerUpdate();
661 void BasketTreeListView::contentsDragEnterEvent(QDragEnterEvent *event)
663 if (event->provides("application/x-qlistviewitem")) {
664 Q3ListViewItemIterator it(this); // TODO: Don't show expanders if it's not a basket drag...
665 while (it.current()) {
666 Q3ListViewItem *item = it.current();
667 if (!item->firstChild()) {
668 item->setExpandable(true);
669 item->setOpen(true);
671 ++it;
673 update();
676 K3ListView::contentsDragEnterEvent(event);
679 void BasketTreeListView::removeExpands()
681 Q3ListViewItemIterator it(this);
682 while (it.current()) {
683 Q3ListViewItem *item = it.current();
684 if (!item->firstChild())
685 item->setExpandable(false);
686 ++it;
688 viewport()->update();
691 void BasketTreeListView::contentsDragLeaveEvent(QDragLeaveEvent *event)
693 std::cout << "BasketTreeListView::contentsDragLeaveEvent" << std::endl;
694 m_autoOpenItem = 0;
695 m_autoOpenTimer.stop();
696 setItemUnderDrag(0);
697 removeExpands();
698 K3ListView::contentsDragLeaveEvent(event);
701 void BasketTreeListView::contentsDropEvent(QDropEvent *event)
703 std::cout << "BasketTreeListView::contentsDropEvent()" << std::endl;
704 if (event->provides("application/x-qlistviewitem"))
706 K3ListView::contentsDropEvent(event);
708 else {
709 std::cout << "Forwarding dropped data to the basket" << std::endl;
710 Q3ListViewItem *item = itemAt(contentsToViewport(event->pos()));
711 BasketListViewItem* bitem = dynamic_cast<BasketListViewItem*>(item);
712 if (bitem) {
713 bitem->basket()->blindDrop(event);
715 else {
716 std::cout << "Forwarding failed: no bitem found" << std::endl;
720 m_autoOpenItem = 0;
721 m_autoOpenTimer.stop();
722 setItemUnderDrag(0);
723 removeExpands();
725 Global::bnpView->save(); // TODO: Don't save if it was not a basket drop...
728 void BasketTreeListView::contentsDragMoveEvent(QDragMoveEvent *event)
730 std::cout << "BasketTreeListView::contentsDragMoveEvent" << std::endl;
731 if (event->provides("application/x-qlistviewitem"))
732 K3ListView::contentsDragMoveEvent(event);
733 else {
734 Q3ListViewItem *item = itemAt(contentsToViewport(event->pos()));
735 BasketListViewItem* bitem = dynamic_cast<BasketListViewItem*>(item);
736 if (m_autoOpenItem != item) {
737 m_autoOpenItem = item;
738 m_autoOpenTimer.start(1700, /*singleShot=*/true);
740 if (item) {
741 event->acceptAction(true);
742 event->accept(true);
744 setItemUnderDrag(bitem);
746 K3ListView::contentsDragMoveEvent(event); // FIXME: ADDED
750 void BasketTreeListView::setItemUnderDrag(BasketListViewItem* item)
752 if (m_itemUnderDrag != item) {
753 if (m_itemUnderDrag) {
754 // Remove drag status from the old item
755 m_itemUnderDrag->setUnderDrag(false);
756 repaintItem(m_itemUnderDrag);
759 m_itemUnderDrag = item;
761 if (m_itemUnderDrag) {
762 // add drag status to the new item
763 m_itemUnderDrag->setUnderDrag(true);
764 repaintItem(m_itemUnderDrag);
769 void BasketTreeListView::autoOpen()
771 BasketListViewItem *item = (BasketListViewItem*)m_autoOpenItem;
772 if (item)
773 Global::bnpView->setCurrentBasket(item->basket());
776 void BasketTreeListView::resizeEvent(QResizeEvent *event)
778 K3ListView::resizeEvent(event);
781 void BasketTreeListView::paintEmptyArea(QPainter *painter, const QRect &rect)
783 Q3ListView::paintEmptyArea(painter, rect);
785 BasketListViewItem *last = Global::bnpView->lastListViewItem();
786 if (last && !last->isShown())
787 last = last->shownItemAbove();
788 if (last && last->isCurrentBasket()) {
789 int y = last->itemPos() + last->height();
790 QColor bgColor = paletteBackgroundColor();
791 QColor selColor = KGlobalSettings::highlightColor();
792 QColor midColor = Tools::mixColor(bgColor, selColor);
793 painter->setPen(selColor);
794 painter->drawPoint(visibleWidth() - 1, y);
795 painter->drawPoint(visibleWidth() - 2, y);
796 painter->drawPoint(visibleWidth() - 1, y + 1);
797 painter->setPen(midColor);
798 painter->drawPoint(visibleWidth() - 3, y);
799 painter->drawPoint(visibleWidth() - 1, y + 2);
803 /** We should NEVER get focus (because of QWidget::NoFocus focusPolicy())
804 * but K3ListView can programatically give us the focus.
805 * So we give it to the basket.
807 void BasketTreeListView::focusInEvent(QFocusEvent*)
809 //K3ListView::focusInEvent(event);
810 Basket *basket = Global::bnpView->currentBasket();
811 if (basket)
812 basket->setFocus();
815 #include "basketlistview.moc"