diff options
Diffstat (limited to 'src/basketlistview.cpp')
-rw-r--r-- | src/basketlistview.cpp | 807 |
1 files changed, 807 insertions, 0 deletions
diff --git a/src/basketlistview.cpp b/src/basketlistview.cpp new file mode 100644 index 0000000..51b9747 --- /dev/null +++ b/src/basketlistview.cpp @@ -0,0 +1,807 @@ +/*************************************************************************** + * Copyright (C) 2003 by S�astien Laot * + * slaout@linux62.org * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include "basketlistview.h" +#include <qregexp.h> +#include <kglobalsettings.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kstringhandler.h> +#include <qpainter.h> +#include <qbitmap.h> +#include <qpixmapcache.h> +#include <qtooltip.h> +#include <iostream> +#include <kdebug.h> +#include "global.h" +#include "bnpview.h" +#include "basket.h" +#include "tools.h" +#include "settings.h" +#include "notedrag.h" + +/** class BasketListViewItem: */ + +BasketListViewItem::BasketListViewItem(QListView *parent, Basket *basket) + : QListViewItem(parent), m_basket(basket) + , m_isUnderDrag(false) + , m_isAbbreviated(false) +{ + setDropEnabled(true); +} + +BasketListViewItem::BasketListViewItem(QListViewItem *parent, Basket *basket) + : QListViewItem(parent), m_basket(basket) + , m_isUnderDrag(false) + , m_isAbbreviated(false) +{ + setDropEnabled(true); +} + +BasketListViewItem::BasketListViewItem(QListView *parent, QListViewItem *after, Basket *basket) + : QListViewItem(parent, after), m_basket(basket) + , m_isUnderDrag(false) + , m_isAbbreviated(false) +{ + setDropEnabled(true); +} + +BasketListViewItem::BasketListViewItem(QListViewItem *parent, QListViewItem *after, Basket *basket) + : QListViewItem(parent, after), m_basket(basket) + , m_isUnderDrag(false) + , m_isAbbreviated(false) +{ + setDropEnabled(true); +} + +BasketListViewItem::~BasketListViewItem() +{ +} + +bool BasketListViewItem::acceptDrop(const QMimeSource *) const +{ + std::cout << "accept" << std::endl; + return true; +} + +void BasketListViewItem::dropped(QDropEvent *event) +{ + std::cout << "Dropping into basket " << m_basket->name() << std::endl; + m_basket->contentsDropEvent(event); + //Global::bnpView->currentBasket()->contentsDropEvent(event); // FIXME +} + +int BasketListViewItem::width(const QFontMetrics &/* fontMetrics */, const QListView */*listView*/, int /* column */) const +{ + return listView()->visibleWidth() + 100; +/* + int BASKET_ICON_SIZE = 16; + int MARGIN = 1; + + QRect textRect = fontMetrics.boundingRect(0, 0, / *width=* /1, 500000, Qt::AlignAuto | Qt::AlignTop | Qt::ShowPrefix, text(column)); + + return MARGIN + BASKET_ICON_SIZE + MARGIN + textRect.width() + BASKET_ICON_SIZE/2 + MARGIN; +*/ +} + +QString BasketListViewItem::escapedName(const QString &string) +{ + // Underlining the Alt+Letter shortcut (and escape all other '&' characters), if any: + QString basketName = string; + basketName.replace('&', "&&"); // First escape all the amperstamp + QString letter; // Find the letter + QString altKey = /*i18n(*/"Alt"/*)*/; //i18n("The [Alt] key, as shown in shortcuts like Alt+C...", "Alt"); + QString shiftKey = /*i18n(*/"Shift"/*)*/; //i18n("The [Shift] key, as shown in shortcuts like Alt+Shift+1...", "Shift"); + QRegExp altLetterExp( QString("^%1\\+(.)$").arg(altKey) ); + QRegExp altShiftLetterExp( QString("^%1\\+%2\\+(.)$").arg(altKey, shiftKey) ); + if (altLetterExp.search(m_basket->shortcut().toStringInternal()) != -1) + letter = altLetterExp.cap(1); + if (letter.isEmpty() && altShiftLetterExp.search(m_basket->shortcut().toStringInternal()) != -1) + letter = altShiftLetterExp.cap(1); + if (!letter.isEmpty()) { + int index = basketName.find(letter, /*index=*/0, /*caseSensitive=*/false); + if (index != -1) + basketName.insert(index, '&'); + } + return basketName; +} + +void BasketListViewItem::setup() +{ + int BASKET_ICON_SIZE = 16; + int MARGIN = 1; + + setText(/*column=*/0, escapedName(m_basket->basketName())); + + widthChanged(); + QRect textRect = listView()->fontMetrics().boundingRect(0, 0, /*width=*/1, 500000, Qt::AlignAuto | Qt::AlignTop | Qt::ShowPrefix, text(/*column=*/0)); + + int height = MARGIN + QMAX(BASKET_ICON_SIZE, textRect.height()) + MARGIN; + setHeight(height); + + QPixmap icon = kapp->iconLoader()->loadIcon(m_basket->icon(), KIcon::NoGroup, 16, KIcon::DefaultState, 0L, /*canReturnNull=*/false); + + setPixmap(/*column=*/0, icon); + + repaint(); +} + +BasketListViewItem* BasketListViewItem::lastChild() +{ + QListViewItem *child = firstChild(); + while (child) { + if (child->nextSibling()) + child = child->nextSibling(); + else + return (BasketListViewItem*)child; + } + return 0; +} + +BasketListViewItem* BasketListViewItem::prevSibling() +{ + BasketListViewItem *item = this; + while (item) { + if (item->nextSibling() == this) + return item; + item = (BasketListViewItem*)(item->itemAbove()); + } + return 0; +} + +BasketListViewItem* BasketListViewItem::shownItemAbove() +{ + BasketListViewItem *item = (BasketListViewItem*)itemAbove(); + while (item) { + if (item->isShown()) + return item; + item = (BasketListViewItem*)(item->itemAbove()); + } + return 0; +} + +BasketListViewItem* BasketListViewItem::shownItemBelow() +{ + BasketListViewItem *item = (BasketListViewItem*)itemBelow(); + while (item) { + if (item->isShown()) + return item; + item = (BasketListViewItem*)(item->itemBelow()); + } + return 0; +} + +QStringList BasketListViewItem::childNamesTree(int deep) +{ + QStringList result; + for (QListViewItem *child = firstChild(); child; child = child->nextSibling()) { + BasketListViewItem *item = (BasketListViewItem*)child; + // Compute indentation spaces: + QString spaces; + for (int i = 0; i < deep; ++i) + spaces += " "; + // Append the name: + result.append(spaces + item->basket()->basketName()); + // Append the childs: + if (child->firstChild()) { + QStringList childs = item->childNamesTree(deep + 1); + for (QStringList::iterator it = childs.begin(); it != childs.end(); ++it) + result.append(*it); + } + } + return result; +} + +void BasketListViewItem::moveChildsBaskets() +{ + QListViewItem *insertAfterThis = this; + QListViewItem *nextOne; + for (QListViewItem *child = firstChild(); child; child = nextOne) { + nextOne = child->nextSibling(); + // Re-insert the item with the good parent: + takeItem(child); + if (parent()) + parent()->insertItem(child); + else + listView()->insertItem(child); + // And move it at the good place: + child->moveItem(insertAfterThis); + insertAfterThis = child; + } +} + +void BasketListViewItem::ensureVisible() +{ + BasketListViewItem *item = this; + while (item->parent()) { + item = (BasketListViewItem*)(item->parent()); + item->setOpen(true); + } +} + +bool BasketListViewItem::isShown() +{ + QListViewItem *item = parent(); + while (item) { + if (!item->isOpen()) + return false; + item = item->parent(); + } + return true; +} + +bool BasketListViewItem::isCurrentBasket() +{ + return basket() == Global::bnpView->currentBasket(); +} + +// TODO: Move this function from item.cpp to class Tools: +extern void drawGradient( QPainter *p, const QColor &colorTop, const QColor & colorBottom, + int x, int y, int w, int h, + bool sunken, bool horz, bool flat ); /*const*/ + +QPixmap BasketListViewItem::circledTextPixmap(const QString &text, int height, const QFont &font, const QColor &color) +{ + QString key = QString("BLI-%1.%2.%3.%4") + .arg(text).arg(height).arg(font.toString()).arg(color.rgb()); + if (QPixmap* cached=QPixmapCache::find(key)) { + return *cached; + } + + // Compute the sizes of the image components: + QRect textRect = QFontMetrics(font).boundingRect(0, 0, /*width=*/1, height, Qt::AlignAuto | Qt::AlignTop, text); + int xMargin = height / 6; + int width = xMargin + textRect.width() + xMargin; + + // Create the gradient image: + QPixmap gradient(3 * width, 3 * height); // We double the size to be able to smooth scale down it (== antialiased curves) + QPainter gradientPainter(&gradient); +#if 1 // Enable the new look of the gradient: + QColor topColor = KGlobalSettings::highlightColor().light(130); //120 + QColor topMidColor = KGlobalSettings::highlightColor().light(105); //105 + QColor bottomMidColor = KGlobalSettings::highlightColor().dark(130); //120 + QColor bottomColor = KGlobalSettings::highlightColor(); + drawGradient(&gradientPainter, topColor, topMidColor, + 0, 0, gradient.width(), gradient.height() / 2, /*sunken=*/false, /*horz=*/true, /*flat=*/false); + drawGradient(&gradientPainter, bottomMidColor, bottomColor, + 0, gradient.height() / 2, gradient.width(), gradient.height() - gradient.height() / 2, /*sunken=*/false, /*horz=*/true, /*flat=*/false); + gradientPainter.fillRect(0, 0, gradient.width(), 3, KGlobalSettings::highlightColor()); +#else + drawGradient(&gradientPainter, KGlobalSettings::highlightColor(), KGlobalSettings::highlightColor().dark(), + 0, 0, gradient.width(), gradient.height(), /*sunken=*/false, /*horz=*/true, /*flat=*/false); +#endif + gradientPainter.end(); + + // Draw the curved rectangle: + QBitmap curvedRectangle(3 * width, 3 * height); + curvedRectangle.fill(Qt::color0); + QPainter curvePainter(&curvedRectangle); + curvePainter.setPen(Qt::color1); + curvePainter.setBrush(Qt::color1); + curvePainter.setClipRect(0, 0, 3*(height / 5), 3*(height)); // If the width is small, don't fill the right part of the pixmap + curvePainter.drawEllipse(0, 3*(-height / 4), 3*(height), 3*(height * 3 / 2)); // Don't forget we double the sizes + curvePainter.setClipRect(3*(width - height / 5), 0, 3*(height / 5), 3*(height)); + curvePainter.drawEllipse(3*(width - height), 3*(-height / 4), 3*(height), 3*(height * 3 / 2)); + curvePainter.setClipping(false); + curvePainter.fillRect(3*(height / 6), 0, 3*(width - 2 * height / 6), 3*(height), curvePainter.brush()); + curvePainter.end(); + + // Apply the curved rectangle as the mask of the gradient: + gradient.setMask(curvedRectangle); + QImage resultImage = gradient.convertToImage(); + resultImage.setAlphaBuffer(true); + + // Scale down the image smoothly to get anti-aliasing: + QPixmap pmScaled; + pmScaled.convertFromImage(resultImage.smoothScale(width, height)); + + // Draw the text, and return the result: + QPainter painter(&pmScaled); + painter.setPen(color); + painter.setFont(font); + painter.drawText(0+1, 0, width, height, Qt::AlignHCenter | Qt::AlignVCenter, text); + painter.end(); + + QPixmapCache::insert(key, pmScaled); + + return pmScaled; +} + +QPixmap BasketListViewItem::foundCountPixmap(bool isLoading, int countFound, bool childsAreLoading, int countChildsFound, const QFont &font, int height) +{ + if (isLoading) + return QPixmap(); + + QFont boldFont(font); + boldFont.setBold(true); + + QString text; + if (childsAreLoading) { + if (countChildsFound > 0) + text = i18n("%1+%2+").arg(QString::number(countFound), QString::number(countChildsFound)); + else + text = i18n("%1+").arg(QString::number(countFound)); + } else { + if (countChildsFound > 0) + text = i18n("%1+%2").arg(QString::number(countFound), QString::number(countChildsFound)); + else if (countFound > 0) + text = QString::number(countFound); + else + return QPixmap(); + } + + return circledTextPixmap(text, height, boldFont, KGlobalSettings::highlightedTextColor()); +} + +bool BasketListViewItem::haveChildsLoading() +{ + QListViewItem *child = firstChild(); + while (child) { + BasketListViewItem *childItem = (BasketListViewItem*)child; + if (!childItem->basket()->isLoaded() && !childItem->basket()->isLocked()) + return true; + if (childItem->haveChildsLoading()) + return true; + child = child->nextSibling(); + } + return false; +} + +bool BasketListViewItem::haveHiddenChildsLoading() +{ + if (isOpen()) + return false; + return haveChildsLoading(); +} + +bool BasketListViewItem::haveChildsLocked() +{ + QListViewItem *child = firstChild(); + while (child) { + BasketListViewItem *childItem = (BasketListViewItem*)child; + if (/*!*/childItem->basket()->isLocked()) + return true; + if (childItem->haveChildsLocked()) + return true; + child = child->nextSibling(); + } + return false; +} + +bool BasketListViewItem::haveHiddenChildsLocked() +{ + if (isOpen()) + return false; + return haveChildsLocked(); +} + +int BasketListViewItem::countChildsFound() +{ + int count = 0; + QListViewItem *child = firstChild(); + while (child) { + BasketListViewItem *childItem = (BasketListViewItem*)child; + count += childItem->basket()->countFounds(); + count += childItem->countChildsFound(); + child = child->nextSibling(); + } + return count; +} + +int BasketListViewItem::countHiddenChildsFound() +{ + if (isOpen()) + return 0; + return countChildsFound(); +} + +void BasketListViewItem::paintCell(QPainter *painter, const QColorGroup &/*colorGroup*/, int /*column*/, int width, int /*align*/) +{ + // Workaround a Qt bug: + // When the splitter is moved to hide the tree view and then the application is restarted, + // Qt try to draw items with a negative size! + if (width <= 0) { + std::cout << "width <= 0" << std::endl; + return; + } + + int BASKET_ICON_SIZE = 16; + int MARGIN = 1; + + + // If we are filtering all baskets, and are effectively filtering on something: + bool showLoadingIcon = false; + bool showEncryptedIcon = false; + QPixmap countPixmap; + bool showCountPixmap = Global::bnpView->isFilteringAllBaskets() && + Global::bnpView->currentBasket()->decoration()->filterBar()->filterData().isFiltering; + if (showCountPixmap) { + showLoadingIcon = (!m_basket->isLoaded() && !m_basket->isLocked()) || haveHiddenChildsLoading(); + showEncryptedIcon = m_basket->isLocked() || haveHiddenChildsLocked(); + countPixmap = foundCountPixmap(!m_basket->isLoaded(), m_basket->countFounds(), haveHiddenChildsLoading() || haveHiddenChildsLocked(), + countHiddenChildsFound(), listView()->font(), height() - 2 * MARGIN); + } + int effectiveWidth = width - (countPixmap.isNull() ? 0 : countPixmap.width() + MARGIN) + - (showLoadingIcon || showEncryptedIcon ? BASKET_ICON_SIZE + MARGIN : 0)/* + - (showEncryptedIcon ? BASKET_ICON_SIZE + MARGIN : 0)*/; + + + bool drawRoundRect = m_basket->backgroundColorSetting().isValid() || m_basket->textColorSetting().isValid(); + QColor textColor = (drawRoundRect ? m_basket->textColor() : (isCurrentBasket() ? KGlobalSettings::highlightedTextColor() : KGlobalSettings::textColor())); + + BasketListViewItem *shownAbove = shownItemAbove(); + BasketListViewItem *shownBelow = shownItemBelow(); + + // Don't forget to update the key computation if parameters + // affecting the rendering logic change + QString key = QString("BLVI::pC-%1.%2.%3.%4.%5.%6.%7.%8.%9.%10.%11.%12.%13.%14.%15") + .arg(effectiveWidth) + .arg(drawRoundRect) + .arg(textColor.rgb()) + .arg(m_basket->backgroundColor().rgb()) + .arg(isCurrentBasket()) + .arg(shownBelow && shownBelow->isCurrentBasket()) + .arg(shownAbove && shownAbove->isCurrentBasket()) + .arg(showLoadingIcon) + .arg(showEncryptedIcon) + .arg(showCountPixmap) + .arg(m_basket->countFounds()) + .arg(countHiddenChildsFound()) + .arg(m_isUnderDrag) + .arg(m_basket->basketName()) + .arg(m_basket->icon()); + if (QPixmap* cached = QPixmapCache::find(key)) { + // Qt's documentation recommends copying the pointer + // into a QPixmap immediately + QPixmap cachedBuffer = *cached; + painter->drawPixmap(0, 0, cachedBuffer); + return; + } + + // Bufferize the drawing of items (otherwize, resizing the splitter make the tree act like a Christmas Tree ;-D ): + QPixmap theBuffer(width, height()); + QPainter thePainter(&theBuffer); + + // Fill with the basket background color: + QColor background = (isCurrentBasket() ? KGlobalSettings::highlightColor() : listView()->paletteBackgroundColor()); + thePainter.fillRect(0, 0, width, height(), background); + + int textWidth = effectiveWidth - MARGIN - BASKET_ICON_SIZE - MARGIN - MARGIN; + + // Draw the rounded rectangle: + if (drawRoundRect) { + QRect textRect = listView()->fontMetrics().boundingRect(0, 0, /*width=*/1, 500000, Qt::AlignAuto | Qt::AlignTop | Qt::ShowPrefix, text(/*column=*/0)); + int xRound = MARGIN; + int yRound = MARGIN; + int hRound = height() - 2 * MARGIN; + int wRound = QMIN(BASKET_ICON_SIZE + MARGIN + textRect.width() + hRound/2, effectiveWidth - MARGIN - MARGIN); + if (wRound > 0) { // Do not crash if there is no space anymore to draw the rounded rectangle: + QPixmap buffer(wRound * 2, hRound * 2); + buffer.fill(background); + QPainter pBuffer(&buffer); + QColor colorRound = m_basket->backgroundColor(); + pBuffer.setPen(colorRound); + pBuffer.setBrush(colorRound); + if (wRound > hRound) { // If the rectangle is smaller in width than in height, don't overlap ellipses... + pBuffer.drawEllipse(0, 0, hRound * 2, hRound * 2); + pBuffer.drawEllipse(wRound * 2 - hRound * 2, 0, hRound * 2, hRound * 2); + pBuffer.fillRect(hRound*2/2, 0, wRound * 2 - hRound * 2, hRound * 2, colorRound); + } else + pBuffer.drawEllipse(0, 0, wRound * 2, hRound * 2); + pBuffer.end(); + QImage imageToScale = buffer.convertToImage(); + QPixmap pmScaled; + pmScaled.convertFromImage(imageToScale.smoothScale(wRound, hRound)); + thePainter.drawPixmap(xRound, yRound, pmScaled); + textWidth -= hRound/2; + } + } + + QColor bgColor = listView()->paletteBackgroundColor(); + QColor selColor = KGlobalSettings::highlightColor(); + QColor midColor = Tools::mixColor(bgColor, selColor); + // Draw the left selection roundings: + if (isCurrentBasket()) { + thePainter.setPen(bgColor); + thePainter.drawPoint(0, 0); + thePainter.drawPoint(1, 0); + thePainter.drawPoint(0, 1); + thePainter.drawPoint(0, height() - 1); + thePainter.drawPoint(1, height() - 1); + thePainter.drawPoint(0, height() - 2); + thePainter.setPen(midColor); + thePainter.drawPoint(2, 0); + thePainter.drawPoint(0, 2); + thePainter.drawPoint(2, height() - 1); + thePainter.drawPoint(0, height() - 3); + } + // Draw the bottom-right selection roundings: + //BasketListViewItem *shownBelow = shownItemBelow(); + if (shownBelow && shownBelow->isCurrentBasket()) { + thePainter.setPen(selColor); + thePainter.drawPoint(width - 1, height() - 1); + thePainter.drawPoint(width - 2, height() - 1); + thePainter.drawPoint(width - 1, height() - 2); + thePainter.setPen(midColor); + thePainter.drawPoint(width - 3, height() - 1); + thePainter.drawPoint(width - 1, height() - 3); + } + // Draw the top-right selection roundings: + // BasketListViewItem *shownAbove = shownItemAbove(); + if (shownAbove && shownAbove->isCurrentBasket()) { + thePainter.setPen(selColor); + thePainter.drawPoint(width - 1, 0); + thePainter.drawPoint(width - 2, 0); + thePainter.drawPoint(width - 1, 1); + thePainter.setPen(midColor); + thePainter.drawPoint(width - 3, 0); + thePainter.drawPoint(width - 1, 2); + } + + // Draw the icon and text: + int yPixmap = (height() - BASKET_ICON_SIZE) / 2; + thePainter.drawPixmap(MARGIN, yPixmap, *pixmap(/*column=*/0)); + thePainter.setPen(textColor); + if (textWidth > 0) { // IF there is space left to draw the text: + int xText = MARGIN + BASKET_ICON_SIZE + MARGIN; + QString theText = m_basket->basketName(); + if (painter->fontMetrics().width(theText) > textWidth) { + theText = KStringHandler::rPixelSqueeze(theText, painter->fontMetrics(), textWidth); + m_isAbbreviated = true; + } + else { + m_isAbbreviated = false; + } + theText = escapedName(theText); + thePainter.drawText(xText, 0, textWidth, height(), Qt::AlignAuto | Qt::AlignVCenter | Qt::ShowPrefix, theText); + } + + // If we are filtering all baskets, and are effectively filtering on something: + if (!countPixmap.isNull()) + { + thePainter.drawPixmap(effectiveWidth, 1, countPixmap); + effectiveWidth += countPixmap.width() + MARGIN; + } + if (showLoadingIcon) { + QPixmap icon = kapp->iconLoader()->loadIcon("find", KIcon::NoGroup, 16, KIcon::DefaultState, 0L, /*canReturnNull=*/false); + thePainter.drawPixmap(effectiveWidth, 0, icon); + effectiveWidth += BASKET_ICON_SIZE + MARGIN; + } + if (showEncryptedIcon && !showLoadingIcon) { + QPixmap icon = kapp->iconLoader()->loadIcon("encrypted", KIcon::NoGroup, 16, KIcon::DefaultState, 0L, /*canReturnNull=*/false); + thePainter.drawPixmap(effectiveWidth, 0, icon); + } + + if (m_isUnderDrag) { + thePainter.drawWinFocusRect(0, 0, width, height()); + } + thePainter.end(); + + QPixmapCache::insert(key, theBuffer); + // Apply the buffer: + painter->drawPixmap(0, 0, theBuffer); +} + +void BasketListViewItem::setUnderDrag(bool underDrag) +{ + m_isUnderDrag = underDrag; +} + +bool BasketListViewItem::isAbbreviated() +{ + return m_isAbbreviated; +} + +/** class BasketListViewToolTip: */ + +class BasketTreeListView_ToolTip : public QToolTip { +public: + BasketTreeListView_ToolTip(BasketTreeListView* basketView) + : QToolTip(basketView->viewport()) + , m_basketView(basketView) + {} +public: + void maybeTip(const QPoint& pos) + { + QListViewItem *item = m_basketView->itemAt(m_basketView->contentsToViewport(pos)); + BasketListViewItem* bitem = dynamic_cast<BasketListViewItem*>(item); + if (bitem && bitem->isAbbreviated()) { + tip(m_basketView->itemRect(bitem), bitem->basket()->basketName()); + } + } +private: + BasketTreeListView* m_basketView; +}; + +/** class BasketTreeListView: */ + +BasketTreeListView::BasketTreeListView(QWidget *parent, const char *name) + : KListView(parent, name), m_autoOpenItem(0) + , m_itemUnderDrag(0) +{ + setWFlags(Qt::WStaticContents | WNoAutoErase); + clearWFlags(Qt::WStaticContents | WNoAutoErase); + //viewport()->clearWFlags(Qt::WStaticContents); + connect( &m_autoOpenTimer, SIGNAL(timeout()), this, SLOT(autoOpen()) ); + + new BasketTreeListView_ToolTip(this); +} + +void BasketTreeListView::viewportResizeEvent(QResizeEvent *event) +{ + KListView::viewportResizeEvent(event); + triggerUpdate(); +} + +void BasketTreeListView::contentsDragEnterEvent(QDragEnterEvent *event) +{ + if (event->provides("application/x-qlistviewitem")) { + QListViewItemIterator it(this); // TODO: Don't show expanders if it's not a basket drag... + while (it.current()) { + QListViewItem *item = it.current(); + if (!item->firstChild()) { + item->setExpandable(true); + item->setOpen(true); + } + ++it; + } + update(); + } + + KListView::contentsDragEnterEvent(event); +} + +void BasketTreeListView::removeExpands() +{ + QListViewItemIterator it(this); + while (it.current()) { + QListViewItem *item = it.current(); + if (!item->firstChild()) + item->setExpandable(false); + ++it; + } + viewport()->update(); +} + +void BasketTreeListView::contentsDragLeaveEvent(QDragLeaveEvent *event) +{ + std::cout << "BasketTreeListView::contentsDragLeaveEvent" << std::endl; + m_autoOpenItem = 0; + m_autoOpenTimer.stop(); + setItemUnderDrag(0); + removeExpands(); + KListView::contentsDragLeaveEvent(event); +} + +void BasketTreeListView::contentsDropEvent(QDropEvent *event) +{ + std::cout << "BasketTreeListView::contentsDropEvent()" << std::endl; + if (event->provides("application/x-qlistviewitem")) + { + KListView::contentsDropEvent(event); + } + else { + std::cout << "Forwarding dropped data to the basket" << std::endl; + QListViewItem *item = itemAt(contentsToViewport(event->pos())); + BasketListViewItem* bitem = dynamic_cast<BasketListViewItem*>(item); + if (bitem) { + bitem->basket()->blindDrop(event); + } + else { + std::cout << "Forwarding failed: no bitem found" << std::endl; + } + } + + m_autoOpenItem = 0; + m_autoOpenTimer.stop(); + setItemUnderDrag(0); + removeExpands(); + + Global::bnpView->save(); // TODO: Don't save if it was not a basket drop... +} + +void BasketTreeListView::contentsDragMoveEvent(QDragMoveEvent *event) +{ + std::cout << "BasketTreeListView::contentsDragMoveEvent" << std::endl; + if (event->provides("application/x-qlistviewitem")) + KListView::contentsDragMoveEvent(event); + else { + QListViewItem *item = itemAt(contentsToViewport(event->pos())); + BasketListViewItem* bitem = dynamic_cast<BasketListViewItem*>(item); + if (m_autoOpenItem != item) { + m_autoOpenItem = item; + m_autoOpenTimer.start(1700, /*singleShot=*/true); + } + if (item) { + event->acceptAction(true); + event->accept(true); + } + setItemUnderDrag(bitem); + + KListView::contentsDragMoveEvent(event); // FIXME: ADDED + } +} + +void BasketTreeListView::setItemUnderDrag(BasketListViewItem* item) +{ + if (m_itemUnderDrag != item) { + if (m_itemUnderDrag) { + // Remove drag status from the old item + m_itemUnderDrag->setUnderDrag(false); + repaintItem(m_itemUnderDrag); + } + + m_itemUnderDrag = item; + + if (m_itemUnderDrag) { + // add drag status to the new item + m_itemUnderDrag->setUnderDrag(true); + repaintItem(m_itemUnderDrag); + } + } +} + +void BasketTreeListView::autoOpen() +{ + BasketListViewItem *item = (BasketListViewItem*)m_autoOpenItem; + if (item) + Global::bnpView->setCurrentBasket(item->basket()); +} + +void BasketTreeListView::resizeEvent(QResizeEvent *event) +{ + KListView::resizeEvent(event); +} + +void BasketTreeListView::paintEmptyArea(QPainter *painter, const QRect &rect) +{ + QListView::paintEmptyArea(painter, rect); + + BasketListViewItem *last = Global::bnpView->lastListViewItem(); + if (last && !last->isShown()) + last = last->shownItemAbove(); + if (last && last->isCurrentBasket()) { + int y = last->itemPos() + last->height(); + QColor bgColor = paletteBackgroundColor(); + QColor selColor = KGlobalSettings::highlightColor(); + QColor midColor = Tools::mixColor(bgColor, selColor); + painter->setPen(selColor); + painter->drawPoint(visibleWidth() - 1, y); + painter->drawPoint(visibleWidth() - 2, y); + painter->drawPoint(visibleWidth() - 1, y + 1); + painter->setPen(midColor); + painter->drawPoint(visibleWidth() - 3, y); + painter->drawPoint(visibleWidth() - 1, y + 2); + } +} + +/** We should NEVER get focus (because of QWidget::NoFocus focusPolicy()) + * but KListView can programatically give us the focus. + * So we give it to the basket. + */ +void BasketTreeListView::focusInEvent(QFocusEvent*) +{ + //KListView::focusInEvent(event); + Basket *basket = Global::bnpView->currentBasket(); + if (basket) + basket->setFocus(); +} + +#include "basketlistview.moc" |