X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/bf1a8f989e75a50c9a5c839e69573a87ab9ad934..cc0ce2a7aade290595bb34891bb8a6ed4c78fd4d:/src/kitemviews/kfileitemlistwidget.cpp diff --git a/src/kitemviews/kfileitemlistwidget.cpp b/src/kitemviews/kfileitemlistwidget.cpp index 897600e60..7e28c5d37 100644 --- a/src/kitemviews/kfileitemlistwidget.cpp +++ b/src/kitemviews/kfileitemlistwidget.cpp @@ -19,6 +19,7 @@ #include "kfileitemlistwidget.h" +#include "kfileitemclipboard_p.h" #include "kfileitemmodel.h" #include "kitemlistview.h" #include "kpixmapmodifier_p.h" @@ -37,11 +38,13 @@ #include #include -//#define KFILEITEMLISTWIDGET_DEBUG +// #define KFILEITEMLISTWIDGET_DEBUG KFileItemListWidget::KFileItemListWidget(QGraphicsItem* parent) : KItemListWidget(parent), - m_isDir(false), + m_isCut(false), + m_isHidden(false), + m_isExpandable(false), m_dirtyLayout(true), m_dirtyContent(true), m_dirtyContentRoles(), @@ -49,7 +52,8 @@ KFileItemListWidget::KFileItemListWidget(QGraphicsItem* parent) : m_pixmapPos(), m_pixmap(), m_scaledPixmapSize(), - m_hoverPixmapRect(), + m_originalPixmapSize(), + m_iconRect(), m_hoverPixmap(), m_textPos(), m_text(), @@ -75,6 +79,7 @@ void KFileItemListWidget::setLayout(Layout layout) if (m_layout != layout) { m_layout = layout; m_dirtyLayout = true; + updateAdditionalInfoTextColor(); update(); } } @@ -86,12 +91,12 @@ KFileItemListWidget::Layout KFileItemListWidget::layout() const void KFileItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) { - KItemListWidget::paint(painter, option, widget); - const_cast(this)->triggerCacheRefreshing(); + KItemListWidget::paint(painter, option, widget); + // Draw expansion toggle '>' or 'V' - if (m_isDir && !m_expansionArea.isEmpty()) { + if (m_isExpandable && !m_expansionArea.isEmpty()) { QStyleOption arrowOption; arrowOption.rect = m_expansionArea.toRect(); const QStyle::PrimitiveElement arrow = data()["isExpanded"].toBool() @@ -143,8 +148,11 @@ void KFileItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsIte } #ifdef KFILEITEMLISTWIDGET_DEBUG - painter->setPen(Qt::red); painter->setBrush(Qt::NoBrush); + painter->setPen(Qt::green); + painter->drawRect(m_iconRect); + + painter->setPen(Qt::red); painter->drawText(QPointF(0, itemListStyleOption.fontMetrics.height()), QString::number(index())); painter->drawRect(rect()); #endif @@ -153,11 +161,7 @@ void KFileItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsIte QRectF KFileItemListWidget::iconRect() const { const_cast(this)->triggerCacheRefreshing(); - - QRectF bounds = m_hoverPixmapRect; - const qreal margin = styleOption().margin; - bounds.adjust(-margin, -margin, margin, margin); - return bounds; + return m_iconRect; } QRectF KFileItemListWidget::textRect() const @@ -169,7 +173,7 @@ QRectF KFileItemListWidget::textRect() const QRectF KFileItemListWidget::expansionToggleRect() const { const_cast(this)->triggerCacheRefreshing(); - return m_isDir ? m_expansionArea : QRectF(); + return m_isExpandable ? m_expansionArea : QRectF(); } QRectF KFileItemListWidget::selectionToggleRect() const @@ -278,7 +282,7 @@ void KFileItemListWidget::setTextColor(const QColor& color) QColor KFileItemListWidget::textColor() const { - if (m_customTextColor.isValid()) { + if (m_customTextColor.isValid() && !isSelected()) { return m_customTextColor; } @@ -362,6 +366,40 @@ void KFileItemListWidget::resizeEvent(QGraphicsSceneResizeEvent* event) m_dirtyLayout = true; } +void KFileItemListWidget::showEvent(QShowEvent* event) +{ + KItemListWidget::showEvent(event); + + // Listen to changes of the clipboard to mark the item as cut/uncut + KFileItemClipboard* clipboard = KFileItemClipboard::instance(); + + const KUrl itemUrl = data().value("url").value(); + m_isCut = clipboard->isCut(itemUrl); + + connect(clipboard, SIGNAL(cutItemsChanged()), + this, SLOT(slotCutItemsChanged())); +} + +void KFileItemListWidget::hideEvent(QHideEvent* event) +{ + disconnect(KFileItemClipboard::instance(), SIGNAL(cutItemsChanged()), + this, SLOT(slotCutItemsChanged())); + + KItemListWidget::hideEvent(event); +} + +void KFileItemListWidget::slotCutItemsChanged() +{ + const KUrl itemUrl = data().value("url").value(); + const bool isCut = KFileItemClipboard::instance()->isCut(itemUrl); + if (m_isCut != isCut) { + m_isCut = isCut; + m_pixmap = QPixmap(); + m_dirtyContent = true; + update(); + } +} + void KFileItemListWidget::triggerCacheRefreshing() { if ((!m_dirtyContent && !m_dirtyLayout) || index() < 0) { @@ -370,7 +408,9 @@ void KFileItemListWidget::triggerCacheRefreshing() refreshCache(); - m_isDir = data()["isDir"].toBool(); + const QHash values = data(); + m_isExpandable = values["isExpandable"].toBool(); + m_isHidden = values["name"].toString().startsWith(QLatin1Char('.')); updateExpansionArea(); updateTextsCache(); @@ -388,15 +428,17 @@ void KFileItemListWidget::updateExpansionArea() Q_ASSERT(values.contains("expansionLevel")); const KItemListStyleOption& option = styleOption(); const int expansionLevel = values.value("expansionLevel", 0).toInt(); - - const qreal widgetHeight = size().height(); - const qreal expansionLevelSize = KIconLoader::SizeSmall; - const qreal x = option.margin + expansionLevel * widgetHeight; - const qreal y = (widgetHeight - expansionLevelSize) / 2; - m_expansionArea = QRectF(x, y, expansionLevelSize, expansionLevelSize); - } else { - m_expansionArea = QRectF(); + if (expansionLevel >= 0) { + const qreal widgetHeight = size().height(); + const qreal expansionLevelSize = KIconLoader::SizeSmall; + const qreal x = option.margin + expansionLevel * widgetHeight; + const qreal y = (widgetHeight - expansionLevelSize) / 2; + m_expansionArea = QRectF(x, y, expansionLevelSize, expansionLevelSize); + return; + } } + + m_expansionArea = QRectF(); } void KFileItemListWidget::updatePixmapCache() @@ -424,7 +466,8 @@ void KFileItemListWidget::updatePixmapCache() if (!updatePixmap && m_dirtyContent) { updatePixmap = m_dirtyContentRoles.isEmpty() || m_dirtyContentRoles.contains("iconPixmap") - || m_dirtyContentRoles.contains("iconName"); + || m_dirtyContentRoles.contains("iconName") + || m_dirtyContentRoles.contains("iconOverlays"); } if (updatePixmap) { @@ -438,7 +481,7 @@ void KFileItemListWidget::updatePixmapCache() iconName = QLatin1String("unknown"); } m_pixmap = pixmapForIcon(iconName, iconHeight); - m_hoverPixmapRect.setSize(m_pixmap.size()); + m_originalPixmapSize = m_pixmap.size(); } else if (m_pixmap.size() != QSize(iconHeight, iconHeight)) { // A custom pixmap has been applied. Assure that the pixmap // is scaled to the available size. @@ -447,7 +490,7 @@ void KFileItemListWidget::updatePixmapCache() if (scale) { KPixmapModifier::scale(m_pixmap, QSize(iconHeight, iconHeight)); } - m_hoverPixmapRect.setSize(m_pixmap.size()); + m_originalPixmapSize = m_pixmap.size(); // To simplify the handling of scaling the original pixmap // will be embedded into a square pixmap. @@ -455,20 +498,40 @@ void KFileItemListWidget::updatePixmapCache() squarePixmap.fill(Qt::transparent); QPainter painter(&squarePixmap); - int x, y; - if (iconOnTop) { - x = (iconHeight - m_pixmap.width()) / 2; // Center horizontally - y = iconHeight - m_pixmap.height(); // Align on bottom - painter.drawPixmap(x, y, m_pixmap); - } else { - x = iconHeight - m_pixmap.width(); // Align right - y = (iconHeight - m_pixmap.height()) / 2; // Center vertically - painter.drawPixmap(x, y, m_pixmap); + const int x = (iconHeight - m_pixmap.width()) / 2; // Center horizontally + int y = iconHeight - m_pixmap.height(); // Move to bottom + if (!iconOnTop) { + y /= 2.0; // Center vertically } + painter.drawPixmap(x, y, m_pixmap); m_pixmap = squarePixmap; } else { - m_hoverPixmapRect.setSize(m_pixmap.size()); + m_originalPixmapSize = m_pixmap.size(); + } + + const QStringList overlays = values["iconOverlays"].toStringList(); + + // Strangely KFileItem::overlays() returns empty string-values, so + // we need to check first whether an overlay must be drawn at all. + // It is more efficient to do it here, as KIconLoader::drawOverlays() + // assumes that an overlay will be drawn and has some additional + // setup time. + foreach (const QString& overlay, overlays) { + if (!overlay.isEmpty()) { + // There is at least one overlay, draw all overlays above m_pixmap + // and cancel the check + KIconLoader::global()->drawOverlays(overlays, m_pixmap, KIconLoader::Desktop); + break; + } + } + + if (m_isCut) { + applyCutEffect(m_pixmap); + } + + if (m_isHidden) { + applyHiddenEffect(m_pixmap); } Q_ASSERT(m_pixmap.height() == iconHeight); @@ -488,17 +551,31 @@ void KFileItemListWidget::updatePixmapCache() m_pixmapPos.setY(option.margin); // Center the hover rectangle horizontally and align it on bottom - const qreal x = m_pixmapPos.x() + (m_scaledPixmapSize.width() - m_hoverPixmapRect.width()) / 2.0; - const qreal y = m_pixmapPos.y() + m_scaledPixmapSize.height() - m_hoverPixmapRect.height(); - m_hoverPixmapRect.moveTopLeft(QPointF(x, y)); + qreal hoverWidth = m_originalPixmapSize.width(); + qreal hoverHeight = m_originalPixmapSize.height(); + if (scaledIconHeight != m_pixmap.height()) { + const qreal scaleFactor = qreal(scaledIconHeight) / qreal(m_pixmap.height()); + hoverWidth *= scaleFactor; + hoverHeight *= scaleFactor; + } + const qreal hoverX = m_pixmapPos.x() + (m_scaledPixmapSize.width() - hoverWidth) / 2.0; + qreal hoverY = m_scaledPixmapSize.height() - hoverHeight; + if (!iconOnTop) { + hoverY /= 2.0; + } + hoverY += m_pixmapPos.y(); + m_iconRect = QRectF(hoverX, hoverY, hoverWidth, hoverHeight); + const qreal margin = option.margin; + m_iconRect.adjust(-margin, -margin, margin, margin); + // Prepare the pixmap that is used when the item gets hovered if (isHovered()) { m_hoverPixmap = m_pixmap; KIconEffect* effect = KIconLoader::global()->iconEffect(); // In the KIconLoader terminology, active = hover. if (effect->hasEffect(KIconLoader::Desktop, KIconLoader::ActiveState)) { - m_hoverPixmap = effect->apply(m_pixmap, KIconLoader::Desktop, KIconLoader::ActiveState); + m_hoverPixmap = effect->apply(m_pixmap, KIconLoader::Desktop, KIconLoader::ActiveState); } else { m_hoverPixmap = m_pixmap; } @@ -585,9 +662,9 @@ void KFileItemListWidget::updateIconsLayoutTextCache() m_text[Name].setTextWidth(maxWidth); m_textPos[Name] = QPointF(option.margin, widgetHeight - textLinesCount * fontHeight - option.margin); m_textRect = QRectF(option.margin + (maxWidth - requiredWidthForName) / 2, - m_textPos[Name].y(), - requiredWidthForName, - m_text[Name].size().height()); + m_textPos[Name].y(), + requiredWidthForName, + textLinesCountForName * fontHeight); // Calculate the position for each additional information qreal y = m_textPos[Name].y() + textLinesCountForName * fontHeight; @@ -765,29 +842,18 @@ void KFileItemListWidget::updateAdditionalInfoTextColor() void KFileItemListWidget::drawPixmap(QPainter* painter, const QPixmap& pixmap) { - const bool isHiddenItem = m_text[Name].text().startsWith(QLatin1Char('.')); - qreal opacity; - if (isHiddenItem) { - opacity = painter->opacity(); - painter->setOpacity(opacity * 0.3); - } - if (m_scaledPixmapSize != pixmap.size()) { QPixmap scaledPixmap = pixmap; KPixmapModifier::scale(scaledPixmap, m_scaledPixmapSize); painter->drawPixmap(m_pixmapPos, scaledPixmap); #ifdef KFILEITEMLISTWIDGET_DEBUG - painter->setPen(Qt::green); + painter->setPen(Qt::blue); painter->drawRect(QRectF(m_pixmapPos, QSizeF(scaledPixmap.size()))); #endif } else { painter->drawPixmap(m_pixmapPos, pixmap); } - - if (isHiddenItem) { - painter->setOpacity(opacity); - } } QPixmap KFileItemListWidget::pixmapForIcon(const QString& name, int size) @@ -839,4 +905,15 @@ KFileItemListWidget::TextId KFileItemListWidget::roleTextId(const QByteArray& ro return rolesHash.value(role); } +void KFileItemListWidget::applyCutEffect(QPixmap& pixmap) +{ + KIconEffect* effect = KIconLoader::global()->iconEffect(); + pixmap = effect->apply(pixmap, KIconLoader::Desktop, KIconLoader::DisabledState); +} + +void KFileItemListWidget::applyHiddenEffect(QPixmap& pixmap) +{ + KIconEffect::semiTransparent(pixmap); +} + #include "kfileitemlistwidget.moc"