/* Library for Aurorae window decoration themes. Copyright (C) 2009, 2010 Martin Gräßlin 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 #include #include #include #include #include #include #include #include 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(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(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 // Copyright (C) 2008 by Alexis Ménard // Copyright (C) 2008 by Marco Martin 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(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