kwin/clients/aurorae/src/lib/auroraetab.cpp
Martin Gräßlin cf553792a9 Forward port 1214767: Honor font settings in Aurorae.
CCBUG: 249681

svn path=/trunk/KDE/kdebase/workspace/; revision=1214768
2011-01-16 10:25:22 +00:00

319 lines
11 KiB
C++

/*
Library for Aurorae window decoration themes.
Copyright (C) 2009, 2010 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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "auroraetab.h"
#include "auroraescene.h"
#include "auroraetheme.h"
#include "themeconfig.h"
#include <QtGui/QGraphicsDropShadowEffect>
#include <QtGui/QGraphicsSceneMouseEvent>
#include <QtGui/QPainter>
#include <QtGui/QStyle>
#include <KDE/KColorUtils>
#include <KDE/KGlobalSettings>
#include <KDE/Plasma/FrameSvg>
#include <KDE/Plasma/PaintUtils>
#include <KDE/Plasma/ToolTipManager>
namespace Aurorae
{
AuroraeTab::AuroraeTab(AuroraeTheme* theme, const QString& caption, int index)
: QGraphicsWidget()
, m_theme(theme)
, m_caption(caption)
, m_index(index)
, m_dblClicked(false)
, m_uid(-1)
, m_dragAllowed(true)
, m_clickInProgress(false)
{
m_effect = new QGraphicsDropShadowEffect(this);
if (m_theme->themeConfig().useTextShadow()) {
setGraphicsEffect(m_effect);
}
setAcceptHoverEvents(true);
connect(m_theme, SIGNAL(buttonSizesChanged()), SLOT(buttonSizesChanged()));
}
AuroraeTab::~AuroraeTab()
{
}
void AuroraeTab::activeChanged()
{
if (scene() == NULL) {
return;
}
const ThemeConfig &config = m_theme->themeConfig();
if (!config.useTextShadow()) {
return;
}
AuroraeScene *s = static_cast<AuroraeScene*>(scene());
if (s->tabCount() > 1) {
// graphics effect seems to be not side effect free and drops scheduled updates
// rendering tabs unreadable, therefore disabled.
m_effect->setEnabled(false);
} else {
m_effect->setEnabled(true);
}
const bool active = s->isActive();
m_effect->setXOffset(config.textShadowOffsetX());
m_effect->setYOffset(config.textShadowOffsetY());
m_effect->setColor(active ? config.activeTextShadowColor() : config.inactiveTextShadowColor());
}
void AuroraeTab::setCaption(const QString& caption)
{
if (m_caption == caption) {
return;
}
m_caption = caption;
updateGeometry();
update();
}
void AuroraeTab::setIcon(const QIcon &icon)
{
m_icon = icon;
}
void AuroraeTab::setIndex(int index)
{
m_index = index;
}
void AuroraeTab::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(option)
Q_UNUSED(widget)
painter->save();
painter->setRenderHint(QPainter::Antialiasing);
painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
AuroraeScene *s = static_cast<AuroraeScene*>(scene());
const bool active = s->isActive();
const bool useTabs = (s->tabCount() > 1);
const bool focused = s->isFocusedTab(m_index);
const ThemeConfig &conf = m_theme->themeConfig();
const DecorationPosition decoPos = s->isShade() ? DecorationTop : m_theme->decorationPosition();
painter->setFont(s->font(active));
if (useTabs) {
painter->save();
Plasma::FrameSvg *decoration = m_theme->decoration();
if (!decoration->hasElementPrefix("tab-active-focused") && m_index < s->tabCount()-1) {
QColor color = active ? conf.activeTextColor(true, false) : conf.inactiveTextColor(true, false);
painter->setPen(color);
QPointF point1 = rect().topRight();
QPointF point2 = rect().bottomRight();
if (decoPos == DecorationLeft || decoPos == DecorationRight) {
point1 = rect().topRight();
point2 = rect().topLeft();
}
painter->drawLine(point1, point2);
} else if (decoration->hasElementPrefix("tab-active-focused")) {
QString element = "tab-active-";
if (!active && decoration->hasElementPrefix("tab-inactive-focused")) {
element = "tab-inactive-";
}
bool useFocused = true;
if (!focused) {
if (element.startsWith(QLatin1String("tab-active")) &&
decoration->hasElementPrefix("tab-active-unfocused")) {
useFocused = false;
}
if (element.startsWith(QLatin1String("tab-inactive")) &&
decoration->hasElementPrefix("tab-inactive-unfocused")) {
useFocused = false;
}
}
element.append(useFocused ? "focused" : "unfocused");
decoration->setElementPrefix(element);
decoration->setEnabledBorders(Plasma::FrameSvg::AllBorders);
decoration->resizeFrame(size());
decoration->paintFrame(painter);
}
painter->restore();
}
Qt::Alignment align = conf.alignment();
if (align != Qt::AlignCenter && QApplication::layoutDirection() == Qt::RightToLeft) {
// have to swap the alignment to be consistent with other kwin decos.
// Decorations do not change in RTL mode
if (align == Qt::AlignLeft) {
align = Qt::AlignRight;
} else {
align = Qt::AlignLeft;
}
}
qreal w = rect().width();
qreal h = rect().height();
if (decoPos == DecorationLeft || decoPos == DecorationRight) {
h = rect().width();
w = rect().height();
}
const QRect textRect = painter->fontMetrics().boundingRect(QRect(rect().x(), rect().y(), w, h),
align | conf.verticalAlignment() | Qt::TextSingleLine,
m_caption);
if ((active && conf.haloActive()) ||
(!active && conf.haloInactive())) {
QRect haloRect = textRect;
if (haloRect.width() > w) {
haloRect.setWidth(w);
}
painter->save();
if (decoPos == DecorationLeft) {
painter->translate(rect().bottomLeft());
painter->rotate(270);
} else if (decoPos == DecorationRight) {
painter->translate(rect().topRight());
painter->rotate(90);
}
Plasma::PaintUtils::drawHalo(painter, haloRect);
painter->restore();
}
QPixmap pix(w, h);
pix.fill(Qt::transparent);
QPainter p(&pix);
QColor color;
if (active) {
color = conf.activeTextColor(useTabs, focused);
if (s->isAnimating()) {
color = KColorUtils::mix(conf.inactiveTextColor(useTabs, focused), conf.activeTextColor(useTabs, focused), s->animationProgress());
}
} else {
color = conf.inactiveTextColor(useTabs, focused);
if (s->isAnimating()){
color = KColorUtils::mix(conf.activeTextColor(useTabs, focused), conf.inactiveTextColor(useTabs, focused), s->animationProgress());
}
}
p.setPen(color);
p.setFont(s->font(active));
p.drawText(pix.rect(), align | conf.verticalAlignment() | Qt::TextSingleLine, m_caption);
if (textRect.width() > w) {
// Fade out effect
// based on fadeout of tasks applet in Plasma/desktop/applets/tasks/abstracttaskitem.cpp by
// Copyright (C) 2007 by Robert Knight <robertknight@gmail.com>
// Copyright (C) 2008 by Alexis Ménard <darktears31@gmail.com>
// Copyright (C) 2008 by Marco Martin <notmart@gmail.com>
QLinearGradient alphaGradient(0, 0, 1, 0);
alphaGradient.setCoordinateMode(QGradient::ObjectBoundingMode);
if (QApplication::layoutDirection() == Qt::LeftToRight) {
alphaGradient.setColorAt(0, QColor(0, 0, 0, 255));
alphaGradient.setColorAt(1, QColor(0, 0, 0, 0));
} else {
alphaGradient.setColorAt(0, QColor(0, 0, 0, 0));
alphaGradient.setColorAt(1, QColor(0, 0, 0, 255));
}
int fadeWidth = 30;
int x = pix.width() - fadeWidth;
QRect r = QStyle::visualRect(QApplication::layoutDirection(), pix.rect(),
QRect(x, 0, fadeWidth, pix.height()));
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
p.fillRect(r, alphaGradient);
}
p.end();
if (decoPos == DecorationLeft) {
painter->translate(rect().bottomLeft());
painter->rotate(270);
} else if (decoPos == DecorationRight) {
painter->translate(rect().topRight());
painter->rotate(90);
}
painter->drawPixmap(pix.rect(), pix);
painter->restore();
}
void AuroraeTab::buttonSizesChanged()
{
updateGeometry();
}
void AuroraeTab::setUniqueTabId(long int id)
{
m_uid = id;
if (m_clickInProgress) {
m_dragAllowed = true;
}
}
void AuroraeTab::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsItem::mousePressEvent(event);
event->accept();
m_clickPos = event->pos();
m_clickInProgress = true;
m_dragAllowed = false;
emit mouseButtonPress(event, m_index);
}
void AuroraeTab::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsItem::mouseReleaseEvent(event);
m_dragAllowed = false;
m_clickInProgress = false;
if (m_dblClicked && event->button() == Qt::LeftButton) {
// eat event
m_dblClicked = false;
return;
}
emit mouseButtonRelease(event, m_index);
}
void AuroraeTab::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{
m_clickInProgress = false;
if (event->button() == Qt::LeftButton) {
m_dblClicked = true;
emit mouseDblClicked();
}
}
void AuroraeTab::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
AuroraeScene *s = static_cast<AuroraeScene*>(scene());
if (s->tabCount() >= 1 && m_dragAllowed &&
(event->pos() - m_clickPos).manhattanLength() >= KGlobalSettings::dndEventDelay()) {
QDrag *drag = new QDrag(event->widget());
QMimeData *data = new QMimeData;
QString itemData = QString().setNum(m_uid) + '/' + QString().setNum(m_index);
data->setData(m_theme->tabDragMimeType(), itemData.toAscii());
drag->setMimeData(data);
QPixmap pix(size().toSize());
pix.fill(Qt::transparent);
QPainter painter(&pix);
s->render(&painter, pix.rect(), sceneBoundingRect());
drag->setPixmap(pix);
drag->exec();
if (!drag->target() && s->tabCount() > 1) {
emit tabRemoved(m_index);
}
}
}
void AuroraeTab::toolTipAboutToShow()
{
Plasma::ToolTipContent data;
data.setMainText(m_caption);
if (!m_icon.isNull()) {
data.setImage(m_icon);
}
Plasma::ToolTipManager::self()->setContent(this, data);
}
} // namespace