abcef60190
Fixes incorrect initial text shadow position in Aurorae. Unfortunately QGraphicsDropShadowEffect seems to be not side effect free. Updates to the scene are not propagated leaving the tabs in a wrong visual state. Therefore text shadow is disabled for window tabbing. I will investigate further to see if it gets fixed in Qt 4.7. CCBUG: 248754 svn path=/trunk/KDE/kdebase/workspace/; revision=1169087
300 lines
10 KiB
C++
300 lines
10 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>
|
|
|
|
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);
|
|
}
|
|
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::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();
|
|
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.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);
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace
|