X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/e29e1cda15973969164d7b7fa805544189a5e172..e6ea3ab4c41dcc115143a237aafd3a1152849433:/src/kitemviews/kfileitemlistwidget.cpp diff --git a/src/kitemviews/kfileitemlistwidget.cpp b/src/kitemviews/kfileitemlistwidget.cpp index 64cc8b449..a495a4c2f 100644 --- a/src/kitemviews/kfileitemlistwidget.cpp +++ b/src/kitemviews/kfileitemlistwidget.cpp @@ -18,877 +18,163 @@ ***************************************************************************/ #include "kfileitemlistwidget.h" - -#include "kfileitemclipboard_p.h" #include "kfileitemmodel.h" #include "kitemlistview.h" -#include "kpixmapmodifier_p.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -// #define KFILEITEMLISTWIDGET_DEBUG - -KFileItemListWidget::KFileItemListWidget(QGraphicsItem* parent) : - KItemListWidget(parent), - m_isCut(false), - m_isHidden(false), - m_isExpandable(false), - m_dirtyLayout(true), - m_dirtyContent(true), - m_dirtyContentRoles(), - m_layout(IconsLayout), - m_pixmapPos(), - m_pixmap(), - m_scaledPixmapSize(), - m_iconRect(), - m_hoverPixmap(), - m_textPos(), - m_text(), - m_textRect(), - m_sortedVisibleRoles(), - m_expansionArea(), - m_customTextColor(), - m_additionalInfoTextColor(), - m_overlay() -{ - for (int i = 0; i < TextIdCount; ++i) { - m_text[i].setTextFormat(Qt::PlainText); - m_text[i].setPerformanceHint(QStaticText::AggressiveCaching); - } -} -KFileItemListWidget::~KFileItemListWidget() -{ -} +#include "dolphin_detailsmodesettings.h" -void KFileItemListWidget::setLayout(Layout layout) -{ - if (m_layout != layout) { - m_layout = layout; - m_dirtyLayout = true; - updateAdditionalInfoTextColor(); - update(); - } -} +#include +#include -KFileItemListWidget::Layout KFileItemListWidget::layout() const -{ - return m_layout; -} +#include -void KFileItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) +KFileItemListWidgetInformant::KFileItemListWidgetInformant() : + KStandardItemListWidgetInformant() { - const_cast(this)->triggerCacheRefreshing(); - - KItemListWidget::paint(painter, option, widget); - - // Draw expansion toggle '>' or 'V' - if (m_isExpandable && !m_expansionArea.isEmpty()) { - QStyleOption arrowOption; - arrowOption.rect = m_expansionArea.toRect(); - const QStyle::PrimitiveElement arrow = data()["isExpanded"].toBool() - ? QStyle::PE_IndicatorArrowDown : QStyle::PE_IndicatorArrowRight; - style()->drawPrimitive(arrow, &arrowOption, painter); - } - - const KItemListStyleOption& itemListStyleOption = styleOption(); - if (isHovered()) { - // Blend the unhovered and hovered pixmap if the hovering - // animation is ongoing - if (hoverOpacity() < 1.0) { - drawPixmap(painter, m_pixmap); - } - - const qreal opacity = painter->opacity(); - painter->setOpacity(hoverOpacity() * opacity); - drawPixmap(painter, m_hoverPixmap); - painter->setOpacity(opacity); - } else { - drawPixmap(painter, m_pixmap); - } - - painter->setFont(itemListStyleOption.font); - painter->setPen(textColor()); - painter->drawStaticText(m_textPos[Name], m_text[Name]); - - bool clipAdditionalInfoBounds = false; - if (m_layout == DetailsLayout) { - // Prevent a possible overlapping of the additional-information texts - // with the icon. This can happen if the user has minimized the width - // of the name-column to a very small value. - const qreal minX = m_pixmapPos.x() + m_pixmap.width() + 4 * itemListStyleOption.padding; - if (m_textPos[Name + 1].x() < minX) { - clipAdditionalInfoBounds = true; - painter->save(); - painter->setClipRect(minX, 0, size().width() - minX, size().height(), Qt::IntersectClip); - } - } - - painter->setPen(m_additionalInfoTextColor); - painter->setFont(itemListStyleOption.font); - for (int i = Name + 1; i < TextIdCount; ++i) { - painter->drawStaticText(m_textPos[i], m_text[i]); - } - - if (clipAdditionalInfoBounds) { - painter->restore(); - } - -#ifdef KFILEITEMLISTWIDGET_DEBUG - 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 } -QRectF KFileItemListWidget::iconRect() const +KFileItemListWidgetInformant::~KFileItemListWidgetInformant() { - const_cast(this)->triggerCacheRefreshing(); - return m_iconRect; } -QRectF KFileItemListWidget::textRect() const +QString KFileItemListWidgetInformant::itemText(int index, const KItemListView* view) const { - const_cast(this)->triggerCacheRefreshing(); - return m_textRect; -} + Q_ASSERT(qobject_cast(view->model())); + KFileItemModel* fileItemModel = static_cast(view->model()); -QRectF KFileItemListWidget::expansionToggleRect() const -{ - const_cast(this)->triggerCacheRefreshing(); - return m_isExpandable ? m_expansionArea : QRectF(); + const KFileItem item = fileItemModel->fileItem(index); + return item.text(); } -QRectF KFileItemListWidget::selectionToggleRect() const +bool KFileItemListWidgetInformant::itemIsLink(int index, const KItemListView* view) const { - const_cast(this)->triggerCacheRefreshing(); - - const int iconHeight = styleOption().iconSize; - - int toggleSize = KIconLoader::SizeSmall; - if (iconHeight >= KIconLoader::SizeEnormous) { - toggleSize = KIconLoader::SizeMedium; - } else if (iconHeight >= KIconLoader::SizeLarge) { - toggleSize = KIconLoader::SizeSmallMedium; - } - - QPointF pos = iconRect().topLeft(); - - // If the selection toggle has a very small distance to the - // widget borders, the size of the selection toggle will get - // increased to prevent an accidental clicking of the item - // when trying to hit the toggle. - const int widgetHeight = size().height(); - const int widgetWidth = size().width(); - const int minMargin = 2; - - if (toggleSize + minMargin * 2 >= widgetHeight) { - pos.rx() -= (widgetHeight - toggleSize) / 2; - toggleSize = widgetHeight; - pos.setY(0); - } - if (toggleSize + minMargin * 2 >= widgetWidth) { - pos.ry() -= (widgetWidth - toggleSize) / 2; - toggleSize = widgetWidth; - pos.setX(0); - } + Q_ASSERT(qobject_cast(view->model())); + KFileItemModel* fileItemModel = static_cast(view->model()); - return QRectF(pos, QSizeF(toggleSize, toggleSize)); + const KFileItem item = fileItemModel->fileItem(index); + return item.isLink(); } -QString KFileItemListWidget::roleText(const QByteArray& role, const QHash& values) +QString KFileItemListWidgetInformant::roleText(const QByteArray& role, + const QHash& values) const { QString text; const QVariant roleValue = values.value(role); - switch (roleTextId(role)) { - case Name: - case Permissions: - case Owner: - case Group: - case Type: - case Destination: - case Path: - text = roleValue.toString(); - break; + // Implementation note: In case if more roles require a custom handling + // use a hash + switch for a linear runtime. - case Size: { + if (role == "size") { if (values.value("isDir").toBool()) { - // The item represents a directory. Show the number of sub directories - // instead of the file size of the directory. + // The item represents a directory. if (!roleValue.isNull()) { - const int count = roleValue.toInt(); + const int count = values.value("count").toInt(); if (count < 0) { text = i18nc("@item:intable", "Unknown"); } else { - text = i18ncp("@item:intable", "%1 item", "%1 items", count); + if (DetailsModeSettings::directorySizeCount()) { + // Show the number of sub directories instead of the file size of the directory. + text = i18ncp("@item:intable", "%1 item", "%1 items", count); + } else { + // if we have directory size available + if (roleValue == -1) { + text = i18nc("@item:intable", "Unknown"); + } else { + const KIO::filesize_t size = roleValue.value(); + text = KFormat().formatByteSize(size); + } + } } } } else { - // Show the size in kilobytes (always round up) - const KLocale* locale = KGlobal::locale(); - const int roundInc = (locale->binaryUnitDialect() == KLocale::MetricBinaryDialect) ? 499 : 511; - const KIO::filesize_t size = roleValue.value() + roundInc; - text = locale->formatByteSize(size, 0, KLocale::DefaultBinaryDialect, KLocale::UnitKiloByte); - } - break; - } - - case Date: { + const KIO::filesize_t size = roleValue.value(); + text = KFormat().formatByteSize(size); + } + } else if (role == "modificationtime" || role == "creationtime" || role == "accesstime") { + bool ok; + const long long time = roleValue.toLongLong(&ok); + if (ok && time != -1) { + return QLocale().toString(QDateTime::fromSecsSinceEpoch(time), QLocale::ShortFormat); + } + } else if (role == "deletiontime" || role == "imageDateTime") { const QDateTime dateTime = roleValue.toDateTime(); - text = KGlobal::locale()->formatDateTime(dateTime); - break; - } - - default: - Q_ASSERT(false); - break; - } - - return text; -} - -void KFileItemListWidget::invalidateCache() -{ - m_dirtyLayout = true; - m_dirtyContent = true; -} - -void KFileItemListWidget::refreshCache() -{ -} - -void KFileItemListWidget::setTextColor(const QColor& color) -{ - if (color != m_customTextColor) { - m_customTextColor = color; - updateAdditionalInfoTextColor(); - update(); - } -} - -QColor KFileItemListWidget::textColor() const -{ - if (m_customTextColor.isValid() && !isSelected()) { - return m_customTextColor; - } - - const QPalette::ColorGroup group = isActiveWindow() ? QPalette::Active : QPalette::Inactive; - const QPalette::ColorRole role = isSelected() ? QPalette::HighlightedText : QPalette::Text; - return styleOption().palette.brush(group, role).color(); -} - -void KFileItemListWidget::setOverlay(const QPixmap& overlay) -{ - m_overlay = overlay; - m_dirtyContent = true; - update(); -} - -QPixmap KFileItemListWidget::overlay() const -{ - return m_overlay; -} - -void KFileItemListWidget::dataChanged(const QHash& current, - const QSet& roles) -{ - KItemListWidget::dataChanged(current, roles); - m_dirtyContent = true; - - QSet dirtyRoles; - if (roles.isEmpty()) { - dirtyRoles = visibleRoles().toSet(); - dirtyRoles.insert("iconPixmap"); - dirtyRoles.insert("iconName"); + text = QLocale().toString(dateTime, QLocale::ShortFormat); } else { - dirtyRoles = roles; - } - - QSetIterator it(dirtyRoles); - while (it.hasNext()) { - const QByteArray& role = it.next(); - m_dirtyContentRoles.insert(role); + text = KStandardItemListWidgetInformant::roleText(role, values); } -} - -void KFileItemListWidget::visibleRolesChanged(const QList& current, - const QList& previous) -{ - KItemListWidget::visibleRolesChanged(current, previous); - m_sortedVisibleRoles = current; - m_dirtyLayout = true; -} -void KFileItemListWidget::visibleRolesSizesChanged(const QHash& current, - const QHash& previous) -{ - KItemListWidget::visibleRolesSizesChanged(current, previous); - m_dirtyLayout = true; -} - -void KFileItemListWidget::styleOptionChanged(const KItemListStyleOption& current, - const KItemListStyleOption& previous) -{ - KItemListWidget::styleOptionChanged(current, previous); - updateAdditionalInfoTextColor(); - m_dirtyLayout = true; -} - -void KFileItemListWidget::hoveredChanged(bool hovered) -{ - Q_UNUSED(hovered); - m_dirtyLayout = true; -} - -void KFileItemListWidget::selectedChanged(bool selected) -{ - Q_UNUSED(selected); - updateAdditionalInfoTextColor(); -} - -void KFileItemListWidget::resizeEvent(QGraphicsSceneResizeEvent* event) -{ - KItemListWidget::resizeEvent(event); - m_dirtyLayout = true; + return text; } -void KFileItemListWidget::showEvent(QShowEvent* event) +QFont KFileItemListWidgetInformant::customizedFontForLinks(const QFont& baseFont) const { - 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())); + // The customized font should be italic if the file is a symbolic link. + QFont font(baseFont); + font.setItalic(true); + return font; } -void KFileItemListWidget::hideEvent(QHideEvent* event) -{ - disconnect(KFileItemClipboard::instance(), SIGNAL(cutItemsChanged()), - this, SLOT(slotCutItemsChanged())); - KItemListWidget::hideEvent(event); -} - -void KFileItemListWidget::slotCutItemsChanged() +KFileItemListWidget::KFileItemListWidget(KItemListWidgetInformant* informant, QGraphicsItem* parent) : + KStandardItemListWidget(informant, parent) { - 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() +KFileItemListWidget::~KFileItemListWidget() { - if ((!m_dirtyContent && !m_dirtyLayout) || index() < 0) { - return; - } - - refreshCache(); - - const QHash values = data(); - m_isExpandable = values["isExpandable"].toBool(); - m_isHidden = values["name"].toString().startsWith(QLatin1Char('.')); - - updateExpansionArea(); - updateTextsCache(); - updatePixmapCache(); - - m_dirtyLayout = false; - m_dirtyContent = false; - m_dirtyContentRoles.clear(); } -void KFileItemListWidget::updateExpansionArea() +KItemListWidgetInformant* KFileItemListWidget::createInformant() { - if (m_layout == DetailsLayout) { - const QHash values = data(); - Q_ASSERT(values.contains("expansionLevel")); - const KItemListStyleOption& option = styleOption(); - const int expansionLevel = values.value("expansionLevel", 0).toInt(); - if (expansionLevel >= 0) { - const qreal widgetHeight = size().height(); - const qreal expansionLevelSize = KIconLoader::SizeSmall; - const qreal x = option.padding + expansionLevel * widgetHeight; - const qreal y = (widgetHeight - expansionLevelSize) / 2; - m_expansionArea = QRectF(x, y, expansionLevelSize, expansionLevelSize); - return; - } - } - - m_expansionArea = QRectF(); + return new KFileItemListWidgetInformant(); } -void KFileItemListWidget::updatePixmapCache() +bool KFileItemListWidget::isRoleRightAligned(const QByteArray& role) const { - // Precondition: Requires already updated m_textPos values to calculate - // the remaining height when the alignment is vertical. - - const QSizeF widgetSize = size(); - const bool iconOnTop = (m_layout == IconsLayout); - const KItemListStyleOption& option = styleOption(); - const qreal padding = option.padding; - - const int maxIconWidth = iconOnTop ? widgetSize.width() - 2 * padding : option.iconSize; - const int maxIconHeight = option.iconSize; - - const QHash values = data(); - - bool updatePixmap = (m_pixmap.width() != maxIconWidth || m_pixmap.height() != maxIconHeight); - if (!updatePixmap && m_dirtyContent) { - updatePixmap = m_dirtyContentRoles.isEmpty() - || m_dirtyContentRoles.contains("iconPixmap") - || m_dirtyContentRoles.contains("iconName") - || m_dirtyContentRoles.contains("iconOverlays"); - } - - if (updatePixmap) { - m_pixmap = values["iconPixmap"].value(); - if (m_pixmap.isNull()) { - // Use the icon that fits to the MIME-type - QString iconName = values["iconName"].toString(); - if (iconName.isEmpty()) { - // The icon-name has not been not resolved by KFileItemModelRolesUpdater, - // use a generic icon as fallback - iconName = QLatin1String("unknown"); - } - m_pixmap = pixmapForIcon(iconName, maxIconHeight); - } else if (m_pixmap.width() != maxIconWidth || m_pixmap.height() != maxIconHeight) { - // A custom pixmap has been applied. Assure that the pixmap - // is scaled to the maximum available size. - KPixmapModifier::scale(m_pixmap, QSize(maxIconWidth, maxIconHeight)); - } - - 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); - } - } - - if (!m_overlay.isNull()) { - QPainter painter(&m_pixmap); - painter.drawPixmap(0, m_pixmap.height() - m_overlay.height(), m_overlay); - } - - int scaledIconSize = 0; - if (iconOnTop) { - scaledIconSize = static_cast(m_textPos[Name].y() - 2 * padding); - } else { - const int textRowsCount = (m_layout == CompactLayout) ? visibleRoles().count() : 1; - const qreal requiredTextHeight = textRowsCount * option.fontMetrics.height(); - scaledIconSize = (requiredTextHeight < maxIconHeight) ? - widgetSize.height() - 2 * padding : maxIconHeight; - } - - const int maxScaledIconWidth = iconOnTop ? widgetSize.width() - 2 * padding : scaledIconSize; - const int maxScaledIconHeight = scaledIconSize; - - m_scaledPixmapSize = m_pixmap.size(); - m_scaledPixmapSize.scale(maxScaledIconWidth, maxScaledIconHeight, Qt::KeepAspectRatio); - - if (iconOnTop) { - // Center horizontally and align on bottom within the icon-area - m_pixmapPos.setX((widgetSize.width() - m_scaledPixmapSize.width()) / 2); - m_pixmapPos.setY(padding + scaledIconSize - m_scaledPixmapSize.height()); - } else { - // Center horizontally and vertically within the icon-area - m_pixmapPos.setX(m_textPos[Name].x() - 2 * padding - - (scaledIconSize + m_scaledPixmapSize.width()) / 2); - m_pixmapPos.setY(padding - + (scaledIconSize - m_scaledPixmapSize.height()) / 2); - } - - m_iconRect = QRectF(m_pixmapPos, QSizeF(m_scaledPixmapSize)); - - // 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); - } else { - m_hoverPixmap = m_pixmap; - } - } else if (hoverOpacity() <= 0.0) { - // No hover animation is ongoing. Clear m_hoverPixmap to save memory. - m_hoverPixmap = QPixmap(); - } + return role == "size"; } -void KFileItemListWidget::updateTextsCache() +bool KFileItemListWidget::isHidden() const { - QTextOption textOption; - switch (m_layout) { - case IconsLayout: - textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); - textOption.setAlignment(Qt::AlignHCenter); - break; - case CompactLayout: - case DetailsLayout: - textOption.setAlignment(Qt::AlignLeft); - textOption.setWrapMode(QTextOption::NoWrap); - break; - default: - Q_ASSERT(false); - break; - } - - for (int i = 0; i < TextIdCount; ++i) { - m_text[i].setText(QString()); - m_text[i].setTextOption(textOption); - } - - switch (m_layout) { - case IconsLayout: updateIconsLayoutTextCache(); break; - case CompactLayout: updateCompactLayoutTextCache(); break; - case DetailsLayout: updateDetailsLayoutTextCache(); break; - default: Q_ASSERT(false); break; - } + return data().value("isHidden").toBool(); } -void KFileItemListWidget::updateIconsLayoutTextCache() +QFont KFileItemListWidget::customizedFont(const QFont& baseFont) const { - // +------+ - // | Icon | - // +------+ - // - // Name role that - // might get wrapped above - // several lines. - // Additional role 1 - // Additional role 2 - - const QHash values = data(); - - const KItemListStyleOption& option = styleOption(); - const qreal padding = option.padding; - const qreal maxWidth = size().width() - 2 * padding; - const qreal widgetHeight = size().height(); - const qreal fontHeight = option.fontMetrics.height(); - - // Initialize properties for the "name" role. It will be used as anchor - // for initializing the position of the other roles. - m_text[Name].setText(KStringHandler::preProcessWrap(values["name"].toString())); - - // Calculate the number of lines required for the name and the required width - int textLinesCountForName = 0; - qreal requiredWidthForName = 0; - QTextLine line; - - QTextLayout layout(m_text[Name].text(), option.font); - layout.setTextOption(m_text[Name].textOption()); - layout.beginLayout(); - while ((line = layout.createLine()).isValid()) { - line.setLineWidth(maxWidth); - requiredWidthForName = qMax(requiredWidthForName, line.naturalTextWidth()); - ++textLinesCountForName; - } - layout.endLayout(); - - // Use one line for each additional information - int textLinesCount = textLinesCountForName; - const int additionalRolesCount = qMax(visibleRoles().count() - 1, 0); - textLinesCount += additionalRolesCount; - - m_text[Name].setTextWidth(maxWidth); - m_textPos[Name] = QPointF(padding, widgetHeight - textLinesCount * fontHeight - padding); - m_textRect = QRectF(padding + (maxWidth - requiredWidthForName) / 2, - m_textPos[Name].y(), - requiredWidthForName, - textLinesCountForName * fontHeight); - - // Calculate the position for each additional information - qreal y = m_textPos[Name].y() + textLinesCountForName * fontHeight; - foreach (const QByteArray& role, m_sortedVisibleRoles) { - const TextId textId = roleTextId(role); - if (textId == Name) { - continue; - } - - const QString text = roleText(role, values); - m_text[textId].setText(text); - - qreal requiredWidth = 0; - - QTextLayout layout(text, option.font); - layout.setTextOption(m_text[textId].textOption()); - layout.beginLayout(); - QTextLine textLine = layout.createLine(); - if (textLine.isValid()) { - textLine.setLineWidth(maxWidth); - requiredWidth = textLine.naturalTextWidth(); - if (textLine.textLength() < text.length()) { - // TODO: QFontMetrics::elidedText() works different regarding the given width - // in comparison to QTextLine::setLineWidth(). It might happen that the text does - // not get elided although it does not fit into the given width. As workaround - // the padding is substracted. - const QString elidedText = option.fontMetrics.elidedText(text, Qt::ElideRight, maxWidth - padding); - m_text[textId].setText(elidedText); - } - } - layout.endLayout(); - - m_textPos[textId] = QPointF(padding, y); - m_text[textId].setTextWidth(maxWidth); - - const QRectF textRect(padding + (maxWidth - requiredWidth) / 2, y, requiredWidth, fontHeight); - m_textRect |= textRect; - - y += fontHeight; - } - - // Add a padding to the text rectangle - m_textRect.adjust(-padding, -padding, padding, padding); + // The customized font should be italic if the file is a symbolic link. + QFont font(baseFont); + font.setItalic(data().value("isLink").toBool()); + return font; } -void KFileItemListWidget::updateCompactLayoutTextCache() +int KFileItemListWidget::selectionLength(const QString& text) const { - // +------+ Name role - // | Icon | Additional role 1 - // +------+ Additional role 2 - - const QHash values = data(); - - const KItemListStyleOption& option = styleOption(); - const qreal widgetHeight = size().height(); - const qreal fontHeight = option.fontMetrics.height(); - const qreal textLinesHeight = qMax(visibleRoles().count(), 1) * fontHeight; - const int scaledIconSize = (textLinesHeight < option.iconSize) ? widgetHeight - 2 * option.padding : option.iconSize; - - qreal maximumRequiredTextWidth = 0; - const qreal x = option.padding * 3 + scaledIconSize; - qreal y = (widgetHeight - textLinesHeight) / 2; - const qreal maxWidth = size().width() - x - option.padding; - foreach (const QByteArray& role, m_sortedVisibleRoles) { - const TextId textId = roleTextId(role); - - const QString text = roleText(role, values); - m_text[textId].setText(text); - - qreal requiredWidth = option.fontMetrics.width(text); - if (requiredWidth > maxWidth) { - requiredWidth = maxWidth; - const QString elidedText = option.fontMetrics.elidedText(text, Qt::ElideRight, maxWidth); - m_text[textId].setText(elidedText); - } - - m_textPos[textId] = QPointF(x, y); - m_text[textId].setTextWidth(maxWidth); + // Select the text without MIME-type extension + int selectionLength = text.length(); - maximumRequiredTextWidth = qMax(maximumRequiredTextWidth, requiredWidth); - - y += fontHeight; + // If item is a directory, use the whole text length for + // selection (ignore all points) + if(data().value("isDir").toBool()) { + return selectionLength; } - m_textRect = QRectF(x - option.padding, 0, maximumRequiredTextWidth + 2 * option.padding, widgetHeight); -} - -void KFileItemListWidget::updateDetailsLayoutTextCache() -{ - // Precondition: Requires already updated m_expansionArea - // to determine the left position. - - // +------+ - // | Icon | Name role Additional role 1 Additional role 2 - // +------+ - m_textRect = QRectF(); + QMimeDatabase db; + const QString extension = db.suffixForFileName(text); + if (extension.isEmpty()) { + // For an unknown extension just exclude the extension after + // the last point. This does not work for multiple extensions like + // *.tar.gz but usually this is anyhow a known extension. + selectionLength = text.lastIndexOf(QLatin1Char('.')); - const KItemListStyleOption& option = styleOption(); - const QHash values = data(); - - const qreal widgetHeight = size().height(); - const int scaledIconSize = widgetHeight - 2 * option.padding; - const int fontHeight = option.fontMetrics.height(); - - const qreal columnPadding = option.padding * 3; - const qreal firstColumnInc = m_expansionArea.right() + option.padding * 2 + scaledIconSize; - qreal x = firstColumnInc; - const qreal y = qMax(qreal(option.padding), (widgetHeight - fontHeight) / 2); - - foreach (const QByteArray& role, m_sortedVisibleRoles) { - const TextId textId = roleTextId(role); - - QString text = roleText(role, values); - - // Elide the text in case it does not fit into the available column-width - qreal requiredWidth = option.fontMetrics.width(text); - const qreal columnWidth = visibleRolesSizes().value(role, QSizeF(0, 0)).width(); - qreal availableTextWidth = columnWidth - 2 * columnPadding; - if (textId == Name) { - availableTextWidth -= firstColumnInc; - } - - if (requiredWidth > availableTextWidth) { - text = option.fontMetrics.elidedText(text, Qt::ElideRight, availableTextWidth); - requiredWidth = option.fontMetrics.width(text); + // If no point could be found, use whole text length for selection. + if (selectionLength < 1) { + selectionLength = text.length(); } - m_text[textId].setText(text); - m_textPos[textId] = QPointF(x + columnPadding, y); - x += columnWidth; - - switch (textId) { - case Name: { - m_textRect = QRectF(m_textPos[textId].x() - option.padding, 0, - requiredWidth + 2 * option.padding, size().height()); - - // The column after the name should always be aligned on the same x-position independent - // from the expansion-level shown in the name column - x -= firstColumnInc; - break; - } - case Size: - // The values for the size should be right aligned - m_textPos[textId].rx() += columnWidth - requiredWidth - 2 * columnPadding; - break; - - default: - break; - } - } -} - -void KFileItemListWidget::updateAdditionalInfoTextColor() -{ - QColor c1; - if (m_customTextColor.isValid()) { - c1 = m_customTextColor; - } else if (isSelected() && m_layout != DetailsLayout) { - c1 = styleOption().palette.highlightedText().color(); - } else { - c1 = styleOption().palette.text().color(); - } - - // For the color of the additional info the inactive text color - // is not used as this might lead to unreadable text for some color schemes. Instead - // the text color c1 is slightly mixed with the background color. - const QColor c2 = styleOption().palette.base().color(); - const int p1 = 70; - const int p2 = 100 - p1; - m_additionalInfoTextColor = QColor((c1.red() * p1 + c2.red() * p2) / 100, - (c1.green() * p1 + c2.green() * p2) / 100, - (c1.blue() * p1 + c2.blue() * p2) / 100); -} - -void KFileItemListWidget::drawPixmap(QPainter* painter, const QPixmap& pixmap) -{ - if (m_scaledPixmapSize != pixmap.size()) { - QPixmap scaledPixmap = pixmap; - KPixmapModifier::scale(scaledPixmap, m_scaledPixmapSize); - painter->drawPixmap(m_pixmapPos, scaledPixmap); - -#ifdef KFILEITEMLISTWIDGET_DEBUG - painter->setPen(Qt::blue); - painter->drawRect(QRectF(m_pixmapPos, QSizeF(m_scaledPixmapSize))); -#endif - } else { - painter->drawPixmap(m_pixmapPos, pixmap); - } -} - -QPixmap KFileItemListWidget::pixmapForIcon(const QString& name, int size) -{ - const KIcon icon(name); - - int requestedSize; - if (size <= KIconLoader::SizeSmall) { - requestedSize = KIconLoader::SizeSmall; - } else if (size <= KIconLoader::SizeSmallMedium) { - requestedSize = KIconLoader::SizeSmallMedium; - } else if (size <= KIconLoader::SizeMedium) { - requestedSize = KIconLoader::SizeMedium; - } else if (size <= KIconLoader::SizeLarge) { - requestedSize = KIconLoader::SizeLarge; - } else if (size <= KIconLoader::SizeHuge) { - requestedSize = KIconLoader::SizeHuge; - } else if (size <= KIconLoader::SizeEnormous) { - requestedSize = KIconLoader::SizeEnormous; - } else if (size <= KIconLoader::SizeEnormous * 2) { - requestedSize = KIconLoader::SizeEnormous * 2; } else { - requestedSize = size; - } - - QPixmap pixmap = icon.pixmap(requestedSize, requestedSize); - if (requestedSize != size) { - KPixmapModifier::scale(pixmap, QSize(size, size)); - } - - return pixmap; -} - -KFileItemListWidget::TextId KFileItemListWidget::roleTextId(const QByteArray& role) -{ - static QHash rolesHash; - if (rolesHash.isEmpty()) { - rolesHash.insert("name", Name); - rolesHash.insert("size", Size); - rolesHash.insert("date", Date); - rolesHash.insert("permissions", Permissions); - rolesHash.insert("owner", Owner); - rolesHash.insert("group", Group); - rolesHash.insert("type", Type); - rolesHash.insert("destination", Destination); - rolesHash.insert("path", Path); + selectionLength -= extension.length() + 1; } - 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); + return selectionLength; } -#include "kfileitemlistwidget.moc"