X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/e9d29bcf30ccbd7c76ba37ce9efcfac1649fc46e..509464cce954f7fc4b00a9dafc2bc6355eb99ec6:/src/kitemviews/kstandarditemlistwidget.cpp diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp index 0cd11d363..72d10cf40 100644 --- a/src/kitemviews/kstandarditemlistwidget.cpp +++ b/src/kitemviews/kstandarditemlistwidget.cpp @@ -172,6 +172,8 @@ KStandardItemListWidget::KStandardItemListWidget(KItemListWidgetInformant* infor KItemListWidget(informant, parent), m_isCut(false), m_isHidden(false), + m_customizedFont(), + m_customizedFontMetrics(m_customizedFont), m_isExpandable(false), m_supportsItemExpanding(false), m_dirtyLayout(true), @@ -258,9 +260,19 @@ void KStandardItemListWidget::paint(QPainter* painter, const QStyleOptionGraphic drawPixmap(painter, m_pixmap); } - painter->setFont(itemListStyleOption.font); + painter->setFont(m_customizedFont); painter->setPen(m_isHidden ? m_additionalInfoTextColor : textColor()); const TextInfo* textInfo = m_textInfo.value("text"); + + if (!textInfo) { + // It seems that we can end up here even if m_textInfo does not contain + // the key "text", see bug 306167. According to triggerCacheRefreshing(), + // this can only happen if the index is negative. This can happen when + // the item is about to be removed, see KItemListView::slotItemsRemoved(). + // TODO: try to reproduce the crash and find a better fix. + return; + } + painter->drawStaticText(textInfo->pos, textInfo->staticText); bool clipAdditionalInfoBounds = false; @@ -277,7 +289,7 @@ void KStandardItemListWidget::paint(QPainter* painter, const QStyleOptionGraphic } painter->setPen(m_additionalInfoTextColor); - painter->setFont(itemListStyleOption.font); + painter->setFont(m_customizedFont); for (int i = 1; i < m_sortedVisibleRoles.count(); ++i) { const TextInfo* textInfo = m_textInfo.value(m_sortedVisibleRoles[i]); @@ -289,7 +301,7 @@ void KStandardItemListWidget::paint(QPainter* painter, const QStyleOptionGraphic QPointF pos = ratingTextInfo->pos; const Qt::Alignment align = ratingTextInfo->staticText.textOption().alignment(); if (align & Qt::AlignHCenter) { - pos.rx() += (size().width() - m_rating.width()) / 2; + pos.rx() += (size().width() - m_rating.width()) / 2 - 2; } painter->drawPixmap(pos, m_rating); } @@ -304,7 +316,7 @@ void KStandardItemListWidget::paint(QPainter* painter, const QStyleOptionGraphic painter->drawRect(m_iconRect); painter->setPen(Qt::red); - painter->drawText(QPointF(0, itemListStyleOption.fontMetrics.height()), QString::number(index())); + painter->drawText(QPointF(0, m_customizedFontMetrics.height()), QString::number(index())); painter->drawRect(rect()); #endif } @@ -349,7 +361,7 @@ QRectF KStandardItemListWidget::textFocusRect() const const KItemListStyleOption& option = styleOption(); if (option.extendedSelectionRegion) { const QString text = textInfo->staticText.text(); - rect.setWidth(option.fontMetrics.width(text) + 2 * option.padding); + rect.setWidth(m_customizedFontMetrics.width(text) + 2 * option.padding); } return rect; @@ -409,7 +421,7 @@ QPixmap KStandardItemListWidget::createDragPixmap(const QStyleOptionGraphicsItem QWidget* widget) { QPixmap pixmap = KItemListWidget::createDragPixmap(option, widget); - if (m_layout != DetailsLayout || styleOption().extendedSelectionRegion) { + if (m_layout != DetailsLayout) { return pixmap; } @@ -457,6 +469,16 @@ bool KStandardItemListWidget::isHidden() const return false; } +QFont KStandardItemListWidget::customizedFont(const QFont& baseFont) const +{ + return baseFont; +} + +QPalette::ColorRole KStandardItemListWidget::normalTextColorRole() const +{ + return QPalette::Text; +} + void KStandardItemListWidget::setTextColor(const QColor& color) { if (color != m_customTextColor) { @@ -473,8 +495,8 @@ QColor KStandardItemListWidget::textColor() const } 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(); + const QPalette::ColorRole role = isSelected() ? QPalette::HighlightedText : normalTextColorRole(); + return styleOption().palette.color(group, role); } void KStandardItemListWidget::setOverlay(const QPixmap& overlay) @@ -559,6 +581,7 @@ void KStandardItemListWidget::selectedChanged(bool selected) { Q_UNUSED(selected); updateAdditionalInfoTextColor(); + m_dirtyContent = true; } void KStandardItemListWidget::siblingsInformationChanged(const QBitArray& current, const QBitArray& previous) @@ -568,6 +591,11 @@ void KStandardItemListWidget::siblingsInformationChanged(const QBitArray& curren m_dirtyLayout = true; } +int KStandardItemListWidget::selectionLength(const QString& text) const +{ + return text.length(); +} + void KStandardItemListWidget::editedRoleChanged(const QByteArray& current, const QByteArray& previous) { Q_UNUSED(previous); @@ -576,6 +604,11 @@ void KStandardItemListWidget::editedRoleChanged(const QByteArray& current, const if (current.isEmpty() || !parent || current != "text") { if (m_roleEditor) { emit roleEditingCanceled(index(), current, data().value(current)); + + disconnect(m_roleEditor, SIGNAL(roleEditingCanceled(int,QByteArray,QVariant)), + this, SLOT(slotRoleEditingCanceled(int,QByteArray,QVariant))); + disconnect(m_roleEditor, SIGNAL(roleEditingFinished(int,QByteArray,QVariant)), + this, SLOT(slotRoleEditingFinished(int,QByteArray,QVariant))); m_roleEditor->deleteLater(); m_roleEditor = 0; } @@ -589,6 +622,7 @@ void KStandardItemListWidget::editedRoleChanged(const QByteArray& current, const m_roleEditor = new KItemListRoleEditor(parent); m_roleEditor->setIndex(index()); m_roleEditor->setRole(current); + m_roleEditor->setFont(styleOption().font); const QString text = data().value(current).toString(); m_roleEditor->setPlainText(text); @@ -596,18 +630,12 @@ void KStandardItemListWidget::editedRoleChanged(const QByteArray& current, const QTextOption textOption = textInfo->staticText.textOption(); m_roleEditor->document()->setDefaultTextOption(textOption); - // Select the text without MIME-type extension - int selectionLength = text.length(); - - const QString extension = KMimeType::extractKnownExtension(text); - if (!extension.isEmpty()) { - selectionLength -= extension.length() + 1; - } + const int textSelectionLength = selectionLength(text); - if (selectionLength > 0) { + if (textSelectionLength > 0) { QTextCursor cursor = m_roleEditor->textCursor(); cursor.movePosition(QTextCursor::StartOfBlock); - cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, selectionLength); + cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, textSelectionLength); m_roleEditor->setTextCursor(cursor); } @@ -676,21 +704,19 @@ void KStandardItemListWidget::slotCutItemsChanged() } void KStandardItemListWidget::slotRoleEditingCanceled(int index, - const QByteArray& role, - const QVariant& value) + const QByteArray& role, + const QVariant& value) { - m_roleEditor->deleteLater(); - m_roleEditor = 0; + closeRoleEditor(); emit roleEditingCanceled(index, role, value); setEditedRole(QByteArray()); } void KStandardItemListWidget::slotRoleEditingFinished(int index, - const QByteArray& role, - const QVariant& value) + const QByteArray& role, + const QVariant& value) { - m_roleEditor->deleteLater(); - m_roleEditor = 0; + closeRoleEditor(); emit roleEditingFinished(index, role, value); setEditedRole(QByteArray()); } @@ -706,6 +732,8 @@ void KStandardItemListWidget::triggerCacheRefreshing() const QHash values = data(); m_isExpandable = m_supportsItemExpanding && values["isExpandable"].toBool(); m_isHidden = isHidden(); + m_customizedFont = customizedFont(styleOption().font); + m_customizedFontMetrics = QFontMetrics(m_customizedFont); updateExpansionArea(); updateTextsCache(); @@ -792,11 +820,19 @@ void KStandardItemListWidget::updatePixmapCache() } if (m_isCut) { - applyCutEffect(m_pixmap); + KIconEffect* effect = KIconLoader::global()->iconEffect(); + m_pixmap = effect->apply(m_pixmap, KIconLoader::Desktop, KIconLoader::DisabledState); } if (m_isHidden) { - applyHiddenEffect(m_pixmap); + KIconEffect::semiTransparent(m_pixmap); + } + + if (isSelected()) { + const QColor color = palette().brush(QPalette::Normal, QPalette::Highlight).color(); + QImage image = m_pixmap.toImage(); + KIconEffect::colorize(image, color, 1.0f); + m_pixmap = QPixmap::fromImage(image); } } @@ -811,7 +847,7 @@ void KStandardItemListWidget::updatePixmapCache() scaledIconSize = static_cast(textInfo->pos.y() - 2 * padding); } else { const int textRowsCount = (m_layout == CompactLayout) ? visibleRoles().count() : 1; - const qreal requiredTextHeight = textRowsCount * option.fontMetrics.height(); + const qreal requiredTextHeight = textRowsCount * m_customizedFontMetrics.height(); scaledIconSize = (requiredTextHeight < maxIconHeight) ? widgetSize.height() - 2 * padding : maxIconHeight; } @@ -897,7 +933,7 @@ void KStandardItemListWidget::updateTextsCache() const qreal availableWidth = (m_layout == DetailsLayout) ? columnWidth("rating") - columnPadding(option) - : m_textRect.width(); + : size().width(); if (ratingSize.width() > availableWidth) { ratingSize.rwidth() = availableWidth; } @@ -931,7 +967,7 @@ void KStandardItemListWidget::updateIconsLayoutTextCache() const qreal padding = option.padding; const qreal maxWidth = size().width() - 2 * padding; const qreal widgetHeight = size().height(); - const qreal lineSpacing = option.fontMetrics.lineSpacing(); + const qreal lineSpacing = m_customizedFontMetrics.lineSpacing(); // Initialize properties for the "text" role. It will be used as anchor // for initializing the position of the other roles. @@ -947,7 +983,7 @@ void KStandardItemListWidget::updateIconsLayoutTextCache() const int additionalRolesCount = qMax(visibleRoles().count() - 1, 0); const int maxNameLines = (option.maxTextSize.height() / int(lineSpacing)) - additionalRolesCount; - QTextLayout layout(nameTextInfo->staticText.text(), option.font); + QTextLayout layout(nameTextInfo->staticText.text(), m_customizedFont); layout.setTextOption(nameTextInfo->staticText.textOption()); layout.beginLayout(); int nameLineIndex = 0; @@ -964,9 +1000,9 @@ void KStandardItemListWidget::updateIconsLayoutTextCache() if (textLength < nameText.length()) { // Elide the last line of the text QString lastTextLine = nameText.mid(line.textStart(), line.textLength()); - lastTextLine = option.fontMetrics.elidedText(lastTextLine, - Qt::ElideRight, - line.naturalTextWidth() - 1); + lastTextLine = m_customizedFontMetrics.elidedText(lastTextLine, + Qt::ElideRight, + line.naturalTextWidth() - 1); const QString elidedText = nameText.left(line.textStart()) + lastTextLine; nameTextInfo->staticText.setText(elidedText); } @@ -999,7 +1035,7 @@ void KStandardItemListWidget::updateIconsLayoutTextCache() qreal requiredWidth = 0; - QTextLayout layout(text, option.font); + QTextLayout layout(text, m_customizedFont); QTextOption textOption; textOption.setWrapMode(QTextOption::NoWrap); layout.setTextOption(textOption); @@ -1010,9 +1046,12 @@ void KStandardItemListWidget::updateIconsLayoutTextCache() textLine.setLineWidth(maxWidth); requiredWidth = textLine.naturalTextWidth(); if (requiredWidth > maxWidth) { - const QString elidedText = option.fontMetrics.elidedText(text, Qt::ElideRight, maxWidth); + const QString elidedText = m_customizedFontMetrics.elidedText(text, Qt::ElideRight, maxWidth); textInfo->staticText.setText(elidedText); - requiredWidth = option.fontMetrics.width(elidedText); + requiredWidth = m_customizedFontMetrics.width(elidedText); + } else if (role == "rating") { + // Use the width of the rating pixmap, because the rating text is empty. + requiredWidth = m_rating.width(); } } layout.endLayout(); @@ -1040,7 +1079,7 @@ void KStandardItemListWidget::updateCompactLayoutTextCache() const KItemListStyleOption& option = styleOption(); const qreal widgetHeight = size().height(); - const qreal lineSpacing = option.fontMetrics.lineSpacing(); + const qreal lineSpacing = m_customizedFontMetrics.lineSpacing(); const qreal textLinesHeight = qMax(visibleRoles().count(), 1) * lineSpacing; const int scaledIconSize = (textLinesHeight < option.iconSize) ? widgetHeight - 2 * option.padding : option.iconSize; @@ -1053,10 +1092,10 @@ void KStandardItemListWidget::updateCompactLayoutTextCache() TextInfo* textInfo = m_textInfo.value(role); textInfo->staticText.setText(text); - qreal requiredWidth = option.fontMetrics.width(text); + qreal requiredWidth = m_customizedFontMetrics.width(text); if (requiredWidth > maxWidth) { requiredWidth = maxWidth; - const QString elidedText = option.fontMetrics.elidedText(text, Qt::ElideRight, maxWidth); + const QString elidedText = m_customizedFontMetrics.elidedText(text, Qt::ElideRight, maxWidth); textInfo->staticText.setText(elidedText); } @@ -1086,7 +1125,7 @@ void KStandardItemListWidget::updateDetailsLayoutTextCache() const qreal widgetHeight = size().height(); const int scaledIconSize = widgetHeight - 2 * option.padding; - const int fontHeight = option.fontMetrics.height(); + const int fontHeight = m_customizedFontMetrics.height(); const qreal columnWidthInc = columnPadding(option); qreal firstColumnInc = scaledIconSize; @@ -1103,7 +1142,7 @@ void KStandardItemListWidget::updateDetailsLayoutTextCache() 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); + qreal requiredWidth = m_customizedFontMetrics.width(text); const qreal roleWidth = columnWidth(role); qreal availableTextWidth = roleWidth - columnWidthInc; @@ -1113,8 +1152,8 @@ void KStandardItemListWidget::updateDetailsLayoutTextCache() } if (requiredWidth > availableTextWidth) { - text = option.fontMetrics.elidedText(text, Qt::ElideRight, availableTextWidth); - requiredWidth = option.fontMetrics.width(text); + text = m_customizedFontMetrics.elidedText(text, Qt::ElideRight, availableTextWidth); + requiredWidth = m_customizedFontMetrics.width(text); } TextInfo* textInfo = m_textInfo.value(role); @@ -1222,6 +1261,22 @@ QRectF KStandardItemListWidget::roleEditingRect(const QByteArray& role) const return rect; } +void KStandardItemListWidget::closeRoleEditor() +{ + if (m_roleEditor->hasFocus()) { + // If the editing was not ended by a FocusOut event, we have + // to transfer the keyboard focus back to the KItemListContainer. + scene()->views()[0]->parentWidget()->setFocus(); + } + + disconnect(m_roleEditor, SIGNAL(roleEditingCanceled(int,QByteArray,QVariant)), + this, SLOT(slotRoleEditingCanceled(int,QByteArray,QVariant))); + disconnect(m_roleEditor, SIGNAL(roleEditingFinished(int,QByteArray,QVariant)), + this, SLOT(slotRoleEditingFinished(int,QByteArray,QVariant))); + m_roleEditor->deleteLater(); + m_roleEditor = 0; +} + QPixmap KStandardItemListWidget::pixmapForIcon(const QString& name, int size) { const KIcon icon(name); @@ -1253,17 +1308,6 @@ QPixmap KStandardItemListWidget::pixmapForIcon(const QString& name, int size) return pixmap; } -void KStandardItemListWidget::applyCutEffect(QPixmap& pixmap) -{ - KIconEffect* effect = KIconLoader::global()->iconEffect(); - pixmap = effect->apply(pixmap, KIconLoader::Desktop, KIconLoader::DisabledState); -} - -void KStandardItemListWidget::applyHiddenEffect(QPixmap& pixmap) -{ - KIconEffect::semiTransparent(pixmap); -} - QSizeF KStandardItemListWidget::preferredRatingSize(const KItemListStyleOption& option) { const qreal height = option.fontMetrics.ascent();