#include <QStyleOption>
#include <QTextLayout>
#include <QTextLine>
+#include <QPixmapCache>
// #define KSTANDARDITEMLISTWIDGET_DEBUG
m_additionalInfoTextColor(),
m_overlay(),
m_rating(),
- m_roleEditor(0)
+ m_roleEditor(0),
+ m_oldRoleEditor(0)
{
}
m_textInfo.clear();
delete m_roleEditor;
+ delete m_oldRoleEditor;
}
void KStandardItemListWidget::setLayout(Layout layout)
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);
- }
+ /*
+ * Linear interpolation between m_pixmap and m_hoverPixmap.
+ *
+ * Note that this cannot be achieved by painting m_hoverPixmap over
+ * m_pixmap, even if the opacities are adjusted. For details see
+ * https://git.reviewboard.kde.org/r/109614/
+ */
+ // Paint pixmap1 so that pixmap1 = m_pixmap * (1.0 - hoverOpacity())
+ QPixmap pixmap1(m_pixmap.size());
+ pixmap1.fill(Qt::transparent);
+ {
+ QPainter p(&pixmap1);
+ p.setOpacity(1.0 - hoverOpacity());
+ p.drawPixmap(0, 0, m_pixmap);
+ }
- const qreal opacity = painter->opacity();
- painter->setOpacity(hoverOpacity() * opacity);
- drawPixmap(painter, m_hoverPixmap);
- painter->setOpacity(opacity);
+ // Paint pixmap2 so that pixmap2 = m_hoverPixmap * hoverOpacity()
+ QPixmap pixmap2(pixmap1.size());
+ pixmap2.fill(Qt::transparent);
+ {
+ QPainter p(&pixmap2);
+ p.setOpacity(hoverOpacity());
+ p.drawPixmap(0, 0, m_hoverPixmap);
+ }
+
+ // Paint pixmap2 on pixmap1 using CompositionMode_Plus
+ // Now pixmap1 = pixmap2 + m_pixmap * (1.0 - hoverOpacity())
+ // = m_hoverPixmap * hoverOpacity() + m_pixmap * (1.0 - hoverOpacity())
+ {
+ QPainter p(&pixmap1);
+ p.setCompositionMode(QPainter::CompositionMode_Plus);
+ p.drawPixmap(0, 0, pixmap2);
+ }
+
+ // Finally paint pixmap1 on the widget
+ drawPixmap(painter, pixmap1);
+ } else {
+ drawPixmap(painter, m_hoverPixmap);
+ }
} else {
drawPixmap(painter, m_pixmap);
}
painter->setFont(m_customizedFont);
- painter->setPen(m_isHidden ? m_additionalInfoTextColor : textColor());
+ painter->setPen(textColor());
const TextInfo* textInfo = m_textInfo.value("text");
if (!textInfo) {
painter->setPen(Qt::green);
painter->drawRect(m_iconRect);
+ painter->setPen(Qt::blue);
+ painter->drawRect(m_textRect);
+
painter->setPen(Qt::red);
painter->drawText(QPointF(0, m_customizedFontMetrics.height()), QString::number(index()));
painter->drawRect(rect());
QColor KStandardItemListWidget::textColor() const
{
- if (m_customTextColor.isValid() && !isSelected()) {
- return m_customTextColor;
+ if (!isSelected()) {
+ if (m_isHidden) {
+ return m_additionalInfoTextColor;
+ } else if (m_customTextColor.isValid()) {
+ return m_customTextColor;
+ }
}
const QPalette::ColorGroup group = isActiveWindow() ? QPalette::Active : QPalette::Inactive;
{
Q_UNUSED(previous);
- QGraphicsView* parent = scene()->views()[0];
- if (current.isEmpty() || !parent || current != "text") {
+ QGraphicsView* parent = scene()->views()[0];
+ 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();
+ disconnect(m_roleEditor, SIGNAL(roleEditingCanceled(QByteArray,QVariant)),
+ this, SLOT(slotRoleEditingCanceled(QByteArray,QVariant)));
+ disconnect(m_roleEditor, SIGNAL(roleEditingFinished(QByteArray,QVariant)),
+ this, SLOT(slotRoleEditingFinished(QByteArray,QVariant)));
+ m_oldRoleEditor = m_roleEditor;
+ m_roleEditor->hide();
m_roleEditor = 0;
}
return;
+ } else if (m_oldRoleEditor) {
+ // Delete the old editor before constructing the new one to
+ // prevent a memory leak.
+ m_oldRoleEditor->deleteLater();
+ m_oldRoleEditor = 0;
}
Q_ASSERT(!m_roleEditor);
const TextInfo* textInfo = m_textInfo.value("text");
m_roleEditor = new KItemListRoleEditor(parent);
- m_roleEditor->setIndex(index());
m_roleEditor->setRole(current);
m_roleEditor->setFont(styleOption().font);
m_roleEditor->setTextCursor(cursor);
}
- connect(m_roleEditor, SIGNAL(roleEditingCanceled(int,QByteArray,QVariant)),
- this, SLOT(slotRoleEditingCanceled(int,QByteArray,QVariant)));
- connect(m_roleEditor, SIGNAL(roleEditingFinished(int,QByteArray,QVariant)),
- this, SLOT(slotRoleEditingFinished(int,QByteArray,QVariant)));
+ connect(m_roleEditor, SIGNAL(roleEditingCanceled(QByteArray,QVariant)),
+ this, SLOT(slotRoleEditingCanceled(QByteArray,QVariant)));
+ connect(m_roleEditor, SIGNAL(roleEditingFinished(QByteArray,QVariant)),
+ this, SLOT(slotRoleEditingFinished(QByteArray,QVariant)));
// Adjust the geometry of the editor
QRectF rect = roleEditingRect(current);
}
}
-void KStandardItemListWidget::slotRoleEditingCanceled(int index,
- const QByteArray& role,
+void KStandardItemListWidget::slotRoleEditingCanceled(const QByteArray& role,
const QVariant& value)
{
closeRoleEditor();
- emit roleEditingCanceled(index, role, value);
+ emit roleEditingCanceled(index(), role, value);
setEditedRole(QByteArray());
}
-void KStandardItemListWidget::slotRoleEditingFinished(int index,
- const QByteArray& role,
+void KStandardItemListWidget::slotRoleEditingFinished(const QByteArray& role,
const QVariant& value)
{
closeRoleEditor();
- emit roleEditingFinished(index, role, value);
+ emit roleEditingFinished(index(), role, value);
setEditedRole(QByteArray());
}
if (isSelected()) {
const QColor color = palette().brush(QPalette::Normal, QPalette::Highlight).color();
QImage image = m_pixmap.toImage();
- KIconEffect::colorize(image, color, 1.0f);
+ KIconEffect::colorize(image, color, 0.8f);
m_pixmap = QPixmap::fromImage(image);
}
}
y += lineSpacing;
}
- m_textRect = QRectF(x - option.padding, 0, maximumRequiredTextWidth + 2 * option.padding, widgetHeight);
+ m_textRect = QRectF(x - 2 * option.padding, 0, maximumRequiredTextWidth + 3 * option.padding, widgetHeight);
}
void KStandardItemListWidget::updateDetailsLayoutTextCache()
const qreal textWidth = option.extendedSelectionRegion
? size().width() - textInfo->pos.x()
: requiredWidth + 2 * option.padding;
- m_textRect = QRectF(textInfo->pos.x() - option.padding, 0,
- textWidth, size().height());
+ m_textRect = QRectF(textInfo->pos.x() - 2 * option.padding, 0,
+ textWidth + 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
QRect siblingRect(x, 0, siblingSize, siblingSize);
QStyleOption option;
+ option.palette.setColor(QPalette::Text, option.palette.color(normalTextColorRole()));
bool isItemSibling = true;
const QBitArray siblings = siblingsInformation();
void KStandardItemListWidget::closeRoleEditor()
{
+ disconnect(m_roleEditor, SIGNAL(roleEditingCanceled(QByteArray,QVariant)),
+ this, SLOT(slotRoleEditingCanceled(QByteArray,QVariant)));
+ disconnect(m_roleEditor, SIGNAL(roleEditingFinished(QByteArray,QVariant)),
+ this, SLOT(slotRoleEditingFinished(QByteArray,QVariant)));
+
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_oldRoleEditor = m_roleEditor;
+ m_roleEditor->hide();
m_roleEditor = 0;
}
QPixmap KStandardItemListWidget::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;
- }
+ const QString key = "KStandardItemListWidget:" % name % ":" % QString::number(size);
+ QPixmap pixmap;
+
+ if (!QPixmapCache::find(key, pixmap)) {
+ 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;
+ }
+
+ pixmap = icon.pixmap(requestedSize, requestedSize);
+ if (requestedSize != size) {
+ KPixmapModifier::scale(pixmap, QSize(size, size));
+ }
- QPixmap pixmap = icon.pixmap(requestedSize, requestedSize);
- if (requestedSize != size) {
- KPixmapModifier::scale(pixmap, QSize(size, size));
+ QPixmapCache::insert(key, pixmap);
}
return pixmap;