2009-09-13 11:36:45 +00:00
|
|
|
/********************************************************************
|
|
|
|
KWin - the KDE window manager
|
|
|
|
This file is part of the KDE project.
|
|
|
|
|
|
|
|
Copyright (C) 2009 Martin Gräßlin <kde@martin-graesslin.com>
|
|
|
|
|
|
|
|
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, see <http://www.gnu.org/licenses/>.
|
|
|
|
*********************************************************************/
|
|
|
|
//own
|
|
|
|
#include "desktopitemdelegate.h"
|
|
|
|
// tabbox
|
|
|
|
#include "clientitemdelegate.h"
|
|
|
|
#include "clientmodel.h"
|
|
|
|
#include "desktopmodel.h"
|
|
|
|
#include "tabboxconfig.h"
|
|
|
|
// Qt
|
|
|
|
#include <QPainter>
|
|
|
|
// KDE
|
|
|
|
#include <KGlobalSettings>
|
|
|
|
#include <KIcon>
|
|
|
|
#include <KIconEffect>
|
|
|
|
#include <KIconLoader>
|
|
|
|
#include <Plasma/FrameSvg>
|
|
|
|
#include <Plasma/Theme>
|
|
|
|
|
|
|
|
namespace KWin
|
|
|
|
{
|
|
|
|
namespace TabBox
|
|
|
|
{
|
|
|
|
|
|
|
|
DesktopItemDelegate::DesktopItemDelegate(QObject* parent)
|
|
|
|
: QAbstractItemDelegate(parent)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
m_frame = new Plasma::FrameSvg(this);
|
|
|
|
m_frame->setImagePath("widgets/viewitem");
|
|
|
|
m_frame->setElementPrefix("hover");
|
|
|
|
m_frame->setCacheAllRenderedFrames(true);
|
|
|
|
m_frame->setEnabledBorders(Plasma::FrameSvg::AllBorders);
|
|
|
|
m_clientDelegate = new ClientItemDelegate(this);
|
|
|
|
}
|
2009-09-13 11:36:45 +00:00
|
|
|
|
|
|
|
DesktopItemDelegate::~DesktopItemDelegate()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
}
|
2009-09-13 11:36:45 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void DesktopItemDelegate::setConfig(const KWin::TabBox::ItemLayoutConfig& config)
|
|
|
|
{
|
2009-09-13 11:36:45 +00:00
|
|
|
m_config = config;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-09-13 11:36:45 +00:00
|
|
|
|
|
|
|
void DesktopItemDelegate::setLayouts(QMap< QString, ItemLayoutConfig >& layouts)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2009-09-13 11:36:45 +00:00
|
|
|
m_layouts = layouts;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-09-13 11:36:45 +00:00
|
|
|
|
|
|
|
QSize DesktopItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
Q_UNUSED(option)
|
|
|
|
if (!index.isValid())
|
|
|
|
return QSize(0, 0);
|
2009-09-13 11:36:45 +00:00
|
|
|
|
|
|
|
qreal width = 0.0;
|
|
|
|
qreal height = 0.0;
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int i = 0; i < m_config.count(); i++) {
|
|
|
|
QSizeF row = rowSize(index, i);
|
|
|
|
width = qMax<qreal>(width, row.width());
|
2009-09-13 11:36:45 +00:00
|
|
|
height += row.height();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-09-13 11:36:45 +00:00
|
|
|
qreal left, top, right, bottom;
|
2011-01-30 14:34:42 +00:00
|
|
|
m_frame->getMargins(left, top, right, bottom);
|
2009-09-13 11:36:45 +00:00
|
|
|
|
|
|
|
// find icon elements which have a row span
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int i = 0; i < m_config.count(); i++) {
|
|
|
|
ItemLayoutConfigRow row = m_config.row(i);
|
|
|
|
for (int j = 0; j < row.count(); j++) {
|
|
|
|
ItemLayoutConfigRowElement element = row.element(j);
|
|
|
|
if (element.type() == ItemLayoutConfigRowElement::ElementIcon && element.isRowSpan())
|
|
|
|
height = qMax<qreal>(height, element.iconSize().height());
|
2009-09-13 11:36:45 +00:00
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
return QSize(width + left + right, height + top + bottom);
|
|
|
|
}
|
2009-09-13 11:36:45 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void DesktopItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
|
|
|
{
|
|
|
|
if (!index.isValid())
|
2009-09-13 11:36:45 +00:00
|
|
|
return;
|
|
|
|
qreal left, top, right, bottom;
|
2011-01-30 14:34:42 +00:00
|
|
|
m_frame->getMargins(left, top, right, bottom);
|
2009-09-13 11:36:45 +00:00
|
|
|
|
|
|
|
qreal y = option.rect.top() + top;
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int i = 0; i < m_config.count(); i++) {
|
|
|
|
qreal rowHeight = rowSize(index, i).height();
|
2009-09-13 11:36:45 +00:00
|
|
|
qreal x = option.rect.left() + left ;
|
2011-01-30 14:34:42 +00:00
|
|
|
ItemLayoutConfigRow row = m_config.row(i);
|
|
|
|
for (int j = 0; j < row.count(); j++) {
|
|
|
|
ItemLayoutConfigRowElement element = row.element(j);
|
|
|
|
switch(element.type()) {
|
|
|
|
case ItemLayoutConfigRowElement::ElementDesktopName: {
|
|
|
|
x += paintTextElement(painter, option, element, x, y, rowHeight,
|
|
|
|
index.model()->data(index, Qt::DisplayRole).toString());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ItemLayoutConfigRowElement::ElementIcon: {
|
|
|
|
qreal rectWidth = (qreal)option.rect.width();
|
|
|
|
qreal maxWidth = qMin<qreal>(element.width(), rectWidth);
|
|
|
|
if (element.isStretch())
|
|
|
|
maxWidth = qMax<qreal>(maxWidth, option.rect.left() + option.rect.width() - x);
|
|
|
|
qreal iconX = x + maxWidth * 0.5 - element.iconSize().width() * 0.5;
|
|
|
|
qreal iconY = y + rowHeight * 0.5 - element.iconSize().height() * 0.5;
|
|
|
|
if (element.isRowSpan())
|
|
|
|
iconY = option.rect.top() + option.rect.height() * 0.5 - element.iconSize().height() * 0.5;
|
|
|
|
QRectF iconRect = QRectF(iconX, iconY, element.iconSize().width(), element.iconSize().height());
|
2009-09-13 11:36:45 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
// icon
|
|
|
|
painter->save();
|
|
|
|
KIcon icon("user-desktop");
|
|
|
|
QPixmap iconPixmap = icon.pixmap(QSize(64, 64));
|
|
|
|
if (m_config.isHighlightSelectedIcons() && option.state & QStyle::State_Selected) {
|
|
|
|
KIconEffect *effect = KIconLoader::global()->iconEffect();
|
|
|
|
iconPixmap = effect->apply(iconPixmap, KIconLoader::Desktop, KIconLoader::ActiveState);
|
|
|
|
}
|
|
|
|
if (m_config.isGrayscaleDeselectedIcons() && !(option.state & QStyle::State_Selected)) {
|
|
|
|
KIconEffect *effect = KIconLoader::global()->iconEffect();
|
|
|
|
iconPixmap = effect->apply(iconPixmap, KIconLoader::Desktop, KIconLoader::DisabledState);
|
|
|
|
}
|
|
|
|
QRectF sourceRect = QRectF(0.0, 0.0, iconPixmap.width(), iconPixmap.height());
|
|
|
|
painter->drawPixmap(iconRect, iconPixmap, sourceRect);
|
|
|
|
painter->restore();
|
|
|
|
x += element.width();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ItemLayoutConfigRowElement::ElementEmpty:
|
|
|
|
x += element.width();
|
|
|
|
break;
|
|
|
|
case ItemLayoutConfigRowElement::ElementClientList: {
|
|
|
|
m_clientDelegate->setConfig(m_layouts[ element.clientListLayoutName()]);
|
|
|
|
ClientModel* clientModel = static_cast< ClientModel* >(
|
|
|
|
index.model()->data(index, DesktopModel::ClientModelRole).value< void* >());
|
|
|
|
TabBoxClientList clients = clientModel->clientList();
|
|
|
|
qreal partX = 0.0;
|
|
|
|
qreal partY = 0.0;
|
|
|
|
qreal itemWidth = element.width();
|
|
|
|
if (element.isStretch())
|
|
|
|
itemWidth = option.rect.x() + option.rect.width() - x;
|
|
|
|
foreach (TabBoxClient * client, clients) {
|
|
|
|
if (!client)
|
|
|
|
continue;
|
|
|
|
QModelIndex clientIndex = clientModel->index(client);
|
|
|
|
QStyleOptionViewItem itemOption = option;
|
|
|
|
itemOption.state = QStyle::State_Item;
|
|
|
|
QSizeF itemSize = m_clientDelegate->sizeHint(itemOption, clientIndex);
|
|
|
|
// TabBoxHandler gives the same config to the client models as used here
|
|
|
|
// so row and column do not represent the actual used layout for this list
|
|
|
|
switch(element.clientListLayoutMode()) {
|
|
|
|
case TabBoxConfig::HorizontalLayout:
|
|
|
|
itemOption.rect = QRect(partX + x, y, itemWidth - partX, rowHeight);
|
|
|
|
partX += qMin(itemWidth - partX, itemSize.width());
|
|
|
|
break;
|
|
|
|
case TabBoxConfig::VerticalLayout:
|
|
|
|
itemOption.rect = QRect(x, y + partY, itemWidth, itemSize.height());
|
|
|
|
partY += itemSize.height();
|
|
|
|
break;
|
|
|
|
case TabBoxConfig::HorizontalVerticalLayout:
|
|
|
|
// TODO: complicated
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break; // nothing
|
2009-09-13 11:36:45 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
if ((partX > itemWidth) || (partX + x > option.rect.x() + option.rect.width())) {
|
|
|
|
partX = itemWidth;
|
|
|
|
break;
|
2009-09-13 11:36:45 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
if ((partY > rowHeight) || (y + partY > option.rect.y() + option.rect.height())) {
|
|
|
|
partY = rowHeight;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
m_clientDelegate->paint(painter, itemOption, clientIndex);
|
2009-09-13 11:36:45 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
x += itemWidth;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break; // do nothing
|
2009-09-13 11:36:45 +00:00
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
y += rowHeight;
|
2009-09-13 11:36:45 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-09-13 11:36:45 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
qreal DesktopItemDelegate::paintTextElement(QPainter* painter, const QStyleOptionViewItem& option,
|
|
|
|
const ItemLayoutConfigRowElement& element,
|
|
|
|
const qreal& x, const qreal& y, const qreal& rowHeight, QString text) const
|
|
|
|
{
|
2009-09-13 11:36:45 +00:00
|
|
|
painter->save();
|
|
|
|
QFont font = KGlobalSettings::generalFont();
|
2011-01-30 14:34:42 +00:00
|
|
|
if (element.isSmallTextSize())
|
2009-09-13 11:36:45 +00:00
|
|
|
font = KGlobalSettings::smallestReadableFont();
|
2011-01-30 14:34:42 +00:00
|
|
|
font.setBold(element.isBold());
|
|
|
|
font.setItalic(element.isItalic());
|
2009-09-13 11:36:45 +00:00
|
|
|
text = element.prefix() + text + element.suffix();
|
2011-01-30 14:34:42 +00:00
|
|
|
painter->setFont(font);
|
|
|
|
painter->setPen(Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor));
|
2009-09-13 11:36:45 +00:00
|
|
|
qreal width = element.width();
|
2011-01-30 14:34:42 +00:00
|
|
|
if (element.isStretch()) {
|
2009-09-13 11:36:45 +00:00
|
|
|
qreal left, top, right, bottom;
|
2011-01-30 14:34:42 +00:00
|
|
|
m_frame->getMargins(left, top, right, bottom);
|
2009-09-13 11:36:45 +00:00
|
|
|
width = option.rect.left() + option.rect.width() - x - right;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
text = QFontMetricsF(font).elidedText(text, Qt::ElideRight, width);
|
|
|
|
QRectF rect = QRectF(x, y, width, rowHeight);
|
|
|
|
painter->drawText(rect, element.alignment() | Qt::TextSingleLine, text);
|
2009-09-13 11:36:45 +00:00
|
|
|
painter->restore();
|
|
|
|
return width;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-09-13 11:36:45 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
QSizeF DesktopItemDelegate::rowSize(const QModelIndex& index, int row) const
|
|
|
|
{
|
|
|
|
ItemLayoutConfigRow currentRow = m_config.row(row);
|
2009-09-13 11:36:45 +00:00
|
|
|
qreal rowWidth = 0.0;
|
|
|
|
qreal rowHeight = 0.0;
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int j = 0; j < currentRow.count(); j++) {
|
|
|
|
ItemLayoutConfigRowElement element = currentRow.element(j);
|
|
|
|
switch(element.type()) {
|
|
|
|
case ItemLayoutConfigRowElement::ElementDesktopName: {
|
|
|
|
QSizeF size = textElementSizeHint(index, element,
|
|
|
|
index.model()->data(index, Qt::DisplayRole).toString());
|
|
|
|
rowWidth += size.width();
|
|
|
|
rowHeight = qMax<qreal>(rowHeight, size.height());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ItemLayoutConfigRowElement::ElementIcon:
|
|
|
|
rowWidth += qMax<qreal>(element.iconSize().width(), element.width());
|
|
|
|
if (!element.isRowSpan())
|
|
|
|
rowHeight = qMax<qreal>(rowHeight, element.iconSize().height());
|
|
|
|
break;
|
|
|
|
case ItemLayoutConfigRowElement::ElementEmpty:
|
|
|
|
rowWidth += element.width();
|
|
|
|
break;
|
|
|
|
case ItemLayoutConfigRowElement::ElementClientList: {
|
|
|
|
m_clientDelegate->setConfig(m_layouts[ element.clientListLayoutName()]);
|
|
|
|
ClientModel* clientModel = static_cast< ClientModel* >(
|
|
|
|
index.model()->data(index, DesktopModel::ClientModelRole).value< void* >());
|
|
|
|
TabBoxClientList clients = clientModel->clientList();
|
|
|
|
qreal elementWidth = 0.0;
|
|
|
|
qreal elementHeight = 0.0;
|
|
|
|
foreach (TabBoxClient * client, clients) {
|
|
|
|
if (!client)
|
|
|
|
continue;
|
|
|
|
QModelIndex clientIndex = clientModel->index(client);
|
|
|
|
QStyleOptionViewItem itemOption = QStyleOptionViewItem();
|
|
|
|
QSizeF itemSize = m_clientDelegate->sizeHint(itemOption, clientIndex);
|
|
|
|
switch(element.clientListLayoutMode()) {
|
|
|
|
case TabBoxConfig::HorizontalLayout:
|
|
|
|
elementWidth += itemSize.width();
|
|
|
|
elementHeight = qMax<qreal>(elementHeight, itemSize.height());
|
|
|
|
break;
|
|
|
|
case TabBoxConfig::VerticalLayout:
|
|
|
|
elementWidth = qMax<qreal>(elementWidth, itemSize.width());
|
|
|
|
elementHeight += itemSize.height();
|
|
|
|
break;
|
|
|
|
case TabBoxConfig::HorizontalVerticalLayout:
|
|
|
|
// TODO: complicated
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break; // nothing
|
2009-09-13 11:36:45 +00:00
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
if (element.isStretch())
|
|
|
|
rowWidth += elementWidth;
|
|
|
|
else
|
|
|
|
rowWidth += qMin(elementWidth, element.width());
|
|
|
|
rowHeight = qMax<qreal>(rowHeight, elementHeight);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break; // do nothing
|
2009-09-13 11:36:45 +00:00
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
return QSizeF(rowWidth, rowHeight);
|
|
|
|
}
|
2009-09-13 11:36:45 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
QSizeF DesktopItemDelegate::textElementSizeHint(const QModelIndex& index, const ItemLayoutConfigRowElement& element, QString text) const
|
|
|
|
{
|
|
|
|
Q_UNUSED(index)
|
2009-09-13 11:36:45 +00:00
|
|
|
QFont font = KGlobalSettings::generalFont();
|
2011-01-30 14:34:42 +00:00
|
|
|
if (element.isSmallTextSize())
|
2009-09-13 11:36:45 +00:00
|
|
|
font = KGlobalSettings::smallestReadableFont();
|
2011-01-30 14:34:42 +00:00
|
|
|
font.setBold(element.isBold());
|
|
|
|
font.setItalic(element.isItalic());
|
2009-09-13 11:36:45 +00:00
|
|
|
text = element.prefix() + text + element.suffix();
|
2011-01-30 14:34:42 +00:00
|
|
|
QFontMetricsF fm(font);
|
2009-09-13 11:36:45 +00:00
|
|
|
qreal width = element.width();
|
2011-01-30 14:34:42 +00:00
|
|
|
if (element.isStretch())
|
|
|
|
width = fm.width(text);
|
|
|
|
qreal height = fm.boundingRect(text).height();
|
|
|
|
return QSizeF(width, height);
|
|
|
|
}
|
2009-09-13 11:36:45 +00:00
|
|
|
|
|
|
|
} // namespace Tabbox
|
|
|
|
} // namespace KWin
|