Import of new Aurorae based on QGraphicsView and KDecoration instead of KCommonDecoration.

It should support everything the old engine supported. Only known regression is the lack of tooltips.
Now finally Aurorae is ready to get window tab support \o/

svn path=/trunk/KDE/kdebase/workspace/; revision=1114115
This commit is contained in:
Martin Gräßlin 2010-04-12 19:28:58 +00:00
parent d1570bbde0
commit 1bcd9fe4f6
15 changed files with 2287 additions and 979 deletions

View file

@ -1,6 +1,14 @@
########### decoration ###############
include_directories( ./lib )
set(kwin3_aurorae_PART_SRCS aurorae.cpp themeconfig.cpp)
set(kwin3_aurorae_PART_SRCS
aurorae.cpp
lib/auroraebutton.cpp
lib/auroraescene.cpp
lib/auroraetab.cpp
lib/auroraetheme.cpp
lib/themeconfig.cpp
)
kde4_add_plugin(kwin3_aurorae ${kwin3_aurorae_PART_SRCS})

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
/********************************************************************
Copyright (C) 2009 Martin Gräßlin <kde@martin-graesslin.com>
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
@ -20,14 +20,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "themeconfig.h"
#include <kdecoration.h>
#include <kdecorationfactory.h>
#include <kcommondecoration.h>
#include <KDE/Plasma/FrameSvg>
class QPropertyAnimation;
class QGraphicsView;
class QGraphicsScene;
namespace Aurorae
{
class AuroraeTheme;
class AuroraeScene;
class AuroraeFactory : public QObject, public KDecorationFactoryUnstable
{
@ -40,113 +42,55 @@ public:
bool supports(Ability ability) const;
virtual QList< BorderSize > borderSizes() const;
Plasma::FrameSvg *frame() {
return &m_frame;
}
Plasma::FrameSvg *button(const QString& b);
bool hasButton(const QString& button) {
return m_buttons.contains(button);
}
ThemeConfig &themeConfig() {
return m_themeConfig;
}
bool isValid() const {
return m_valid;
AuroraeTheme *theme() const {
return m_theme;
}
private:
AuroraeFactory();
void init();
void initButtonFrame(const QString& button);
void readThemeConfig();
private:
static AuroraeFactory *s_instance;
// theme name
QString m_themeName;
ThemeConfig m_themeConfig;
// deco
Plasma::FrameSvg m_frame;
// buttons
QHash< QString, Plasma::FrameSvg* > m_buttons;
bool m_valid;
AuroraeTheme *m_theme;
};
class AuroraeButton : public KCommonDecorationButton
class AuroraeClient : public KDecorationUnstable
{
Q_OBJECT
Q_PROPERTY(qreal animation READ animationProgress WRITE setAnimationProgress)
public:
AuroraeButton(ButtonType type, KCommonDecoration *parent);
void reset(unsigned long changed);
void enterEvent(QEvent *event);
void leaveEvent(QEvent *event);
void paintEvent(QPaintEvent *event);
qreal animationProgress() const;
void setAnimationProgress(qreal progress);
protected:
void mousePressEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
private:
enum ButtonState {
Active = 0x1,
Hover = 0x2,
Pressed = 0x4,
Deactivated = 0x8
};
Q_DECLARE_FLAGS(ButtonStates, ButtonState)
void paintButton(QPainter& painter, Plasma::FrameSvg* frame, ButtonStates states);
bool isAnimating() const;
private:
qreal m_animationProgress;
bool m_pressed;
QPropertyAnimation *m_animation;
};
class AuroraeClient : public KCommonDecorationUnstable
{
Q_OBJECT
Q_PROPERTY(qreal animation READ animationProgress WRITE setAnimationProgress)
public:
AuroraeClient(KDecorationBridge *bridge, KDecorationFactory *factory);
~AuroraeClient();
virtual void init();
virtual QString visibleName() const;
virtual QString defaultButtonsLeft() const;
virtual QString defaultButtonsRight() const;
virtual bool decorationBehaviour(DecorationBehaviour behaviour) const;
virtual int layoutMetric(LayoutMetric lm, bool respectWindowState = true,
const KCommonDecorationButton * = 0) const;
virtual KCommonDecorationButton *createButton(ButtonType type);
virtual void updateWindowShape();
AuroraeClient(KDecorationBridge* bridge, KDecorationFactory* factory);
virtual void activeChange();
virtual void borders(int& left, int& right, int& top, int& bottom) const;
virtual void captionChange();
virtual void desktopChange();
virtual void iconChange();
virtual void init();
virtual void maximizeChange();
virtual QSize minimumSize() const;
virtual Position mousePosition(const QPoint& p) const;
virtual void resize(const QSize& s);
virtual void shadeChange();
// optional overrides
virtual void padding(int &left, int &right, int &top, int &bottom) const;
virtual void reset(long unsigned int changed);
bool isAnimating() const;
qreal animationProgress() const;
void setAnimationProgress(qreal progress);
protected:
void reset(unsigned long changed);
void paintEvent(QPaintEvent *event);
private slots:
void menuClicked();
void toggleShade();
void keepAboveChanged(bool above);
void keepBelowChanged(bool below);
void toggleKeepAbove();
void toggleKeepBelow();
void titlePressed(Qt::MouseButton button, Qt::MouseButtons buttons);
void titleReleased(Qt::MouseButton button, Qt::MouseButtons buttons);
void titleMouseMoved(Qt::MouseButton button, Qt::MouseButtons buttons);
private:
void generateTextPixmap(QPixmap& pixmap, bool active);
qreal m_animationProgress;
QPixmap m_activeText;
QPixmap m_inactiveText;
QPropertyAnimation *m_animation;
void updateWindowShape();
AuroraeScene *m_scene;
QGraphicsView *m_view;
};
}

View file

@ -0,0 +1,442 @@
/*
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 "auroraebutton.h"
#include "auroraescene.h"
#include "auroraetheme.h"
#include "themeconfig.h"
// Qt
#include <QtCore/QEasingCurve>
#include <QtCore/QPropertyAnimation>
#include <QtCore/QTimer>
#include <QtGui/QGraphicsSceneEvent>
#include <QtGui/QPainter>
// KDE
#include <KDE/KIcon>
#include <KDE/KIconLoader>
#include <KDE/KIconEffect>
#include <KDE/Plasma/FrameSvg>
#include <KDE/Plasma/PaintUtils>
namespace Aurorae {
AuroraeButton::AuroraeButton(AuroraeTheme* theme, AuroraeButtonType type)
: QGraphicsWidget()
, m_theme(theme)
, m_type(type)
, m_pressed(false)
, m_hovered(false)
, m_animationProgress(0.0)
, m_animation(new QPropertyAnimation(this, "animation", this))
, m_checkable(false)
, m_checked(false)
{
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
setAcceptHoverEvents(true);
setAcceptedMouseButtons(Qt::LeftButton);
}
AuroraeButton::~AuroraeButton()
{
}
void AuroraeButton::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
Q_UNUSED(option)
Q_UNUSED(widget)
if (m_theme->hasButton(m_type)) {
ButtonStates state;
if (static_cast<AuroraeScene*>(scene())->isActive()) {
state |= Active;
}
if (m_hovered) {
state |= Hover;
}
if (m_pressed) {
state |= Pressed;
}
if (isCheckable() && isChecked()) {
state |= Pressed;
}
paintButton(painter, m_theme->button(currentType()), state);
}
}
AuroraeButtonType AuroraeButton::currentType() const
{
return m_type;
}
QSizeF AuroraeButton::sizeHint(Qt::SizeHint which, const QSizeF& constraint) const
{
Q_UNUSED(which)
Q_UNUSED(constraint)
switch (m_type) {
case MinimizeButton:
return QSizeF(m_theme->themeConfig().buttonWidthMinimize(),
m_theme->themeConfig().buttonHeight());
case MaximizeButton:
case RestoreButton:
return QSizeF(m_theme->themeConfig().buttonWidthMaximizeRestore(),
m_theme->themeConfig().buttonHeight());
case CloseButton:
return QSizeF(m_theme->themeConfig().buttonWidthClose(),
m_theme->themeConfig().buttonHeight());
case AllDesktopsButton:
return QSizeF(m_theme->themeConfig().buttonWidthAllDesktops(),
m_theme->themeConfig().buttonHeight());
case KeepAboveButton:
return QSizeF(m_theme->themeConfig().buttonWidthKeepAbove(),
m_theme->themeConfig().buttonHeight());
case KeepBelowButton:
return QSizeF(m_theme->themeConfig().buttonWidthKeepBelow(),
m_theme->themeConfig().buttonHeight());
case ShadeButton:
return QSizeF(m_theme->themeConfig().buttonWidthShade(),
m_theme->themeConfig().buttonHeight());
case HelpButton:
return QSizeF(m_theme->themeConfig().buttonWidthHelp(),
m_theme->themeConfig().buttonHeight());
default:
return QSizeF(m_theme->themeConfig().buttonWidth(), m_theme->themeConfig().buttonHeight());
}
}
void AuroraeButton::mousePressEvent(QGraphicsSceneMouseEvent* event)
{
Q_UNUSED(event)
m_pressed = true;
update();
}
void AuroraeButton::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
{
Q_UNUSED(event)
if (m_pressed) {
emit clicked();
}
m_pressed = false;
update();
QGraphicsItem::mouseReleaseEvent(event);
}
void AuroraeButton::hoverEnterEvent(QGraphicsSceneHoverEvent* event)
{
Q_UNUSED(event)
m_hovered = true;
if (isAnimating()) {
m_animation->stop();
}
m_animationProgress = 0.0;
int time = m_theme->themeConfig().animationTime();
if (time != 0) {
m_animation->setDuration(time);
m_animation->setEasingCurve(QEasingCurve::InQuad);
m_animation->setStartValue(0.0);
m_animation->setEndValue(1.0);
m_animation->start();
}
update();
}
void AuroraeButton::hoverLeaveEvent(QGraphicsSceneHoverEvent* event)
{
Q_UNUSED(event)
m_hovered = false;
if (isAnimating()) {
m_animation->stop();
}
m_animationProgress = 0.0;
int time = m_theme->themeConfig().animationTime();
if (time != 0) {
m_animation->setDuration(time);
m_animation->setEasingCurve(QEasingCurve::OutQuad);
m_animation->setStartValue(0.0);
m_animation->setEndValue(1.0);
m_animation->start();
}
update();
}
void AuroraeButton::paintButton(QPainter *painter, Plasma::FrameSvg *frame, ButtonStates states)
{
QString prefix = "active";
QString animationPrefix = "active";
bool hasInactive = false;
// check for inactive prefix
if (!states.testFlag(Active) && frame->hasElementPrefix("inactive")) {
// we have inactive, so we use it
hasInactive = true;
prefix = "inactive";
animationPrefix = "inactive";
}
if (states.testFlag(Hover)) {
if (states.testFlag(Active)) {
if (frame->hasElementPrefix("hover")) {
prefix = "hover";
}
} else {
if (hasInactive) {
if (frame->hasElementPrefix("hover-inactive")) {
prefix = "hover-inactive";
}
} else {
if (frame->hasElementPrefix("hover")) {
prefix = "hover";
}
}
}
}
if (states.testFlag(Pressed)) {
if (states.testFlag(Active)) {
if (frame->hasElementPrefix("pressed")) {
prefix = "pressed";
}
} else {
if (hasInactive) {
if (frame->hasElementPrefix("pressed-inactive")) {
prefix = "pressed-inactive";
}
} else {
if (frame->hasElementPrefix("pressed")) {
prefix = "pressed";
}
}
}
}
if (states.testFlag(Deactivated)) {
if (states.testFlag(Active)) {
if (frame->hasElementPrefix("deactivated")) {
prefix = "deactivated";
}
} else {
if (hasInactive) {
if (frame->hasElementPrefix("deactivated-inactive")) {
prefix = "deactivated-inactive";
}
} else {
if (frame->hasElementPrefix("deactivated")) {
prefix = "deactivated";
}
}
}
}
frame->setElementPrefix(prefix);
frame->resizeFrame(size());
if (isAnimating()) {
// there is an animation so we have to use it
// the animation is definately a hover animation as currently nothing else is supported
if (!states.testFlag(Hover)) {
// only have to set for not hover state as animationPrefix is set to (in)active by default
if (states.testFlag(Active)) {
if (frame->hasElementPrefix("hover")) {
animationPrefix = "hover";
}
} else {
if (hasInactive) {
if (frame->hasElementPrefix("hover-inactive")) {
animationPrefix = "hover-inactive";
}
} else {
if (frame->hasElementPrefix("hover")) {
animationPrefix = "hover";
}
}
}
}
QPixmap target = frame->framePixmap();
frame->setElementPrefix(animationPrefix);
frame->resizeFrame(size());
QPixmap result = Plasma::PaintUtils::transition(frame->framePixmap(),
target, m_animationProgress);
painter->drawPixmap(QRect(QPoint(0, 0), size().toSize()), result);
} else {
bool animation = false;
AuroraeScene *s = static_cast<AuroraeScene*>(scene());
if (s->isAnimating()) {
animationPrefix = prefix;
if (prefix.endsWith("-inactive")) {
animationPrefix.remove("-inactive");
} else {
animationPrefix = animationPrefix + "-inactive";
}
if (frame->hasElementPrefix(animationPrefix)) {
animation = true;
QPixmap target = frame->framePixmap();
frame->setElementPrefix(animationPrefix);
frame->resizeFrame(size());
QPixmap result = Plasma::PaintUtils::transition(frame->framePixmap(),
target, s->animationProgress());
painter->drawPixmap(0, 0, result);
}
}
if (!animation) {
frame->paintFrame(painter);
}
}
}
bool AuroraeButton::isAnimating() const
{
return (m_animation->state() == QAbstractAnimation::Running);
}
qreal AuroraeButton::animationProgress() const
{
return m_animationProgress;
}
void AuroraeButton::setAnimationProgress(qreal progress)
{
m_animationProgress = progress;
update();
}
/***********************************************
* AuroraeMaximizeButton
***********************************************/
AuroraeMaximizeButton::AuroraeMaximizeButton(AuroraeTheme* theme)
: AuroraeButton(theme, MaximizeButton)
, m_maximizeMode(KDecorationDefines::MaximizeRestore)
{
setAcceptedMouseButtons(Qt::LeftButton|Qt::RightButton|Qt::MidButton);
}
void AuroraeMaximizeButton::mousePressEvent(QGraphicsSceneMouseEvent* event)
{
AuroraeButton::mousePressEvent(event);
m_pressedButton = event->button();
}
void AuroraeMaximizeButton::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
{
if (isPressed() && m_pressedButton == event->button()) {
emit clicked(m_pressedButton);
}
setPressed(false);
update();
QGraphicsItem::mouseReleaseEvent(event);
}
AuroraeButtonType AuroraeMaximizeButton::currentType() const
{
if (m_maximizeMode == KDecorationDefines::MaximizeFull &&
theme()->hasButton(RestoreButton)) {
return RestoreButton;
} else {
return MaximizeButton;
}
}
void AuroraeMaximizeButton::setMaximizeMode(KDecorationDefines::MaximizeMode mode)
{
m_maximizeMode = mode;
update();
}
/************************************************
* AuroraeMenuButton
************************************************/
AuroraeMenuButton::AuroraeMenuButton(AuroraeTheme* theme)
: AuroraeButton(theme, MenuButton)
{
m_timer = new QTimer(this);
m_timer->setSingleShot(true);
m_timer->setInterval(QApplication::doubleClickInterval());
connect(m_timer, SIGNAL(timeout()), SIGNAL(clicked()));
}
void AuroraeMenuButton::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(option)
Q_UNUSED(widget)
if (m_icon.isNull()) {
return;
}
QPixmap iconPix = m_icon;
KIconEffect *effect = KIconLoader::global()->iconEffect();
AuroraeScene *s = static_cast<AuroraeScene*>(scene());
if (s->isActive()) {
if (isHovered()) {
iconPix = effect->apply(iconPix, KIconLoader::Desktop, KIconLoader::ActiveState);
}
} else {
iconPix = effect->apply(iconPix, KIconLoader::Desktop, KIconLoader::DisabledState);
}
if (s->isAnimating()) {
// animation
QPixmap oldPix = m_icon;
if (!s->isActive()) {
if (isHovered()) {
oldPix = effect->apply(iconPix, KIconLoader::Desktop, KIconLoader::ActiveState);
}
} else {
oldPix = effect->apply(iconPix, KIconLoader::Desktop, KIconLoader::DisabledState);
}
iconPix = Plasma::PaintUtils::transition(oldPix, iconPix, s->animationProgress());
}
painter->drawPixmap(0, 0, iconPix);
}
void AuroraeMenuButton::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)
{
Q_UNUSED(event)
emit doubleClicked();
}
void AuroraeMenuButton::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
{
Q_UNUSED(event)
if (isPressed()) {
if (m_timer->isActive()) {
m_timer->stop();
} else {
m_timer->start();
}
}
setPressed(false);
update();
QGraphicsItem::mouseReleaseEvent(event);
}
void AuroraeMenuButton::setIcon(const QPixmap& icon)
{
m_icon = icon;
update();
}
/************************************************
* AuroraeSpacer
************************************************/
AuroraeSpacer::AuroraeSpacer(AuroraeTheme *theme)
: QGraphicsWidget()
, m_theme(theme)
{
}
QSizeF AuroraeSpacer::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
{
Q_UNUSED(which)
Q_UNUSED(constraint)
return QSizeF(m_theme->themeConfig().explicitButtonSpacer(),
m_theme->themeConfig().buttonHeight());
}
} // namespace

View file

@ -0,0 +1,168 @@
/*
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.
*/
#ifndef AURORAE_AURORAEBUTTON_H
#define AURORAE_AURORAEBUTTON_H
#include "auroraetheme.h"
#include <QtGui/QGraphicsWidget>
#include <kdecoration.h>
class QTimer;
class QPropertyAnimation;
namespace Plasma {
class FrameSvg;
}
namespace Aurorae {
class AuroraeTheme;
class AuroraeButton : public QGraphicsWidget
{
Q_OBJECT
Q_PROPERTY(qreal animation READ animationProgress WRITE setAnimationProgress)
public:
AuroraeButton(AuroraeTheme *theme, AuroraeButtonType type );
virtual ~AuroraeButton();
virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0);
AuroraeButtonType buttonType() const {
return m_type;
}
virtual void mousePressEvent(QGraphicsSceneMouseEvent* event);
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent* event);
virtual void hoverEnterEvent(QGraphicsSceneHoverEvent* event);
virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent* event);
virtual int type() const {
return m_type;
}
qreal animationProgress() const;
void setAnimationProgress(qreal progress);
void setCheckable(bool checkable) {
m_checkable = checkable;
}
bool isCheckable() const {
return m_checkable;
}
void setChecked(bool checked) {
m_checked = checked;
}
bool isChecked() const {
return m_checked;
}
Q_SIGNALS:
void clicked();
protected:
enum ButtonState {
Active = 0x1,
Hover = 0x2,
Pressed = 0x4,
Deactivated = 0x8
};
Q_DECLARE_FLAGS(ButtonStates, ButtonState)
virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF& constraint = QSizeF()) const;
virtual void paintButton(QPainter *painter, Plasma::FrameSvg *frame, ButtonStates states);
virtual bool isAnimating() const;
virtual AuroraeButtonType currentType() const;
AuroraeTheme *theme() const {
return m_theme;
}
bool isHovered() const {
return m_hovered;
}
bool isPressed() const {
return m_pressed;
}
void setPressed(bool pressed) {
m_pressed = pressed;
}
private:
AuroraeTheme *m_theme;
AuroraeButtonType m_type;
bool m_pressed;
bool m_hovered;
qreal m_animationProgress;
QPropertyAnimation *m_animation;
bool m_checkable;
bool m_checked;
};
class AuroraeMaximizeButton : public AuroraeButton
{
Q_OBJECT
public:
AuroraeMaximizeButton(AuroraeTheme* theme);
virtual void mousePressEvent(QGraphicsSceneMouseEvent* event);
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent* event);
void setMaximizeMode(KDecorationDefines::MaximizeMode mode);
Q_SIGNALS:
void clicked(Qt::MouseButtons button);
protected:
virtual AuroraeButtonType currentType() const;
private:
Qt::MouseButton m_pressedButton;
KDecorationDefines::MaximizeMode m_maximizeMode;
};
class AuroraeMenuButton : public AuroraeButton
{
Q_OBJECT
public:
AuroraeMenuButton(AuroraeTheme *theme);
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event);
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent* event);
void setIcon(const QPixmap &icon);
Q_SIGNALS:
void doubleClicked();
private:
QPixmap m_icon;
QTimer *m_timer;
};
class AuroraeSpacer : public QGraphicsWidget
{
public:
AuroraeSpacer(AuroraeTheme *theme);
virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF& constraint = QSizeF()) const;
private:
AuroraeTheme *m_theme;
};
} // namespace Aurorae
#endif // AURORAE_AURORAEBUTTON_H

View file

@ -0,0 +1,607 @@
/*
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 "auroraescene.h"
#include "auroraebutton.h"
#include "auroraetab.h"
#include "auroraetheme.h"
#include "themeconfig.h"
// Qt
#include <QtCore/QPropertyAnimation>
#include <QtGui/QGraphicsLinearLayout>
#include <QtGui/QGraphicsSceneMouseEvent>
#include <QtGui/QIcon>
#include <QtGui/QPainter>
// KDE
#include <KDE/Plasma/FrameSvg>
#include <KDE/Plasma/PaintUtils>
namespace Aurorae {
AuroraeScene::AuroraeScene(Aurorae::AuroraeTheme* theme, const QString& leftButtons,
const QString& rightButtons, bool contextHelp, QObject* parent)
: QGraphicsScene(parent)
, m_theme(theme)
, m_leftButtons(0)
, m_rightButtons(0)
, m_title(0)
, m_active(false)
, m_animationProgress(0.0)
, m_animation(new QPropertyAnimation(this, "animation", this))
, m_maximizeMode(KDecorationDefines::MaximizeRestore)
, m_allDesktops(false)
, m_shade(false)
, m_keepAbove(false)
, m_keepBelow(false)
, m_leftButtonOrder(leftButtons)
, m_rightButtonOrder(rightButtons)
, m_dblClicked(false)
, m_contextHelp(contextHelp)
{
init();
connect(m_theme, SIGNAL(themeChanged()), SLOT(resetTheme()));
}
AuroraeScene::~AuroraeScene()
{
}
void AuroraeScene::init()
{
if (!m_theme->isValid()) {
return;
}
// left buttons
QGraphicsLinearLayout *leftButtonsLayout = new QGraphicsLinearLayout;
leftButtonsLayout->setSpacing(m_theme->themeConfig().buttonSpacing());
leftButtonsLayout->setContentsMargins(0, 0, 0, 0);
initButtons(leftButtonsLayout, m_leftButtonOrder);
m_leftButtons = new QGraphicsWidget;
m_leftButtons->setLayout(leftButtonsLayout);
addItem(m_leftButtons);
// right buttons
QGraphicsLinearLayout *rightButtonsLayout = new QGraphicsLinearLayout;
rightButtonsLayout->setSpacing(m_theme->themeConfig().buttonSpacing());
rightButtonsLayout->setContentsMargins(0, 0, 0, 0);
initButtons(rightButtonsLayout, m_rightButtonOrder);
m_rightButtons = new QGraphicsWidget;
m_rightButtons->setLayout(rightButtonsLayout);
addItem(m_rightButtons);
// title area
QGraphicsLinearLayout *titleLayout = new QGraphicsLinearLayout;
titleLayout->setSpacing(0);
titleLayout->setContentsMargins(0, 0, 0, 0);
m_title = new QGraphicsWidget;
AuroraeTab *tab = new AuroraeTab(m_theme, m_caption);
connect(this, SIGNAL(activeChanged()), tab, SLOT(activeChanged()));
titleLayout->addItem(tab);
m_title->setLayout(titleLayout);
addItem(m_title);
tab->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
setActive(m_active, false);
updateLayout();
// reset the icon
setIcon(m_iconPixmap);
update(sceneRect());
}
void AuroraeScene::resetTheme()
{
clear();
init();
}
void AuroraeScene::drawBackground(QPainter *painter, const QRectF &rect)
{
if (!m_theme->isValid()) {
return;
}
painter->setClipRect(rect);
painter->save();
painter->setRenderHint(QPainter::Antialiasing);
bool maximized = m_maximizeMode == KDecorationDefines::MaximizeFull; // TODO: check option
const ThemeConfig &conf = m_theme->themeConfig();
Plasma::FrameSvg *frame = m_theme->decoration();
frame->setElementPrefix("decoration");
if (!isActive() && frame->hasElementPrefix("decoration-inactive")) {
frame->setElementPrefix("decoration-inactive");
}
if (!m_theme->isCompositingActive() && frame->hasElementPrefix("decoration-opaque")) {
frame->setElementPrefix("decoration-opaque");
if (!isActive() && frame->hasElementPrefix("decoration-opaque-inactive")) {
frame->setElementPrefix("decoration-opaque-inactive");
}
}
if (maximized) {
if (frame->hasElementPrefix("decoration-maximized")) {
frame->setElementPrefix("decoration-maximized");
}
if (!isActive() && frame->hasElementPrefix("decoration-maximized-inactive")) {
frame->setElementPrefix("decoration-maximized-inactive");
}
if (!m_theme->isCompositingActive() && frame->hasElementPrefix("decoration-maximized-opaque")) {
frame->setElementPrefix("decoration-maximized-opaque");
if (!isActive() && frame->hasElementPrefix("decoration-maximized-opaque-inactive")) {
frame->setElementPrefix("decoration-maximized-opaque-inactive");
}
}
}
// restrict painting on the decoration - no need to paint behind the window
/*int left, right, top, bottom;
decoration()->borders(left, right, top, bottom);
if (!compositingActive() || (compositingActive() && !transparentRect().isNull())) {
// only clip when compositing is not active and we don't extend into the client
painter.setClipping(true);
painter.setClipRect(0, 0,
left + conf.paddingLeft(),
height() + conf.paddingTop() + conf.paddingBottom(),
Qt::ReplaceClip);
painter.setClipRect(0, 0,
width() + conf.paddingLeft() + conf.paddingRight(),
top + conf.paddingTop(),
Qt::UniteClip);
painter.setClipRect(width() - right + conf.paddingLeft(), 0,
right + conf.paddingRight(),
height() + conf.paddingTop() + conf.paddingBottom(),
Qt::UniteClip);
painter.setClipRect(0, height() - bottom + conf.paddingTop(),
width() + conf.paddingLeft() + conf.paddingRight(),
bottom + conf.paddingBottom(),
Qt::UniteClip);
}*/
// top
if (maximized) {
frame->setEnabledBorders(Plasma::FrameSvg::NoBorder);
} else {
frame->setEnabledBorders(Plasma::FrameSvg::AllBorders);
}
QRectF r = sceneRect();
if (maximized) {
r = QRectF(conf.paddingLeft(), conf.paddingTop(),
sceneRect().width() - conf.paddingRight() - conf.paddingLeft(),
sceneRect().height() - conf.paddingBottom() - conf.paddingTop());
if (true/*transparentRect().isNull()*/) {
r = QRectF(conf.paddingLeft(), conf.paddingTop(),
sceneRect().width() - conf.paddingRight() - conf.paddingLeft(),
conf.titleEdgeTopMaximized() + conf.titleHeight() + conf.titleEdgeBottomMaximized());
}
}
QRectF sourceRect = QRectF(QPointF(0, 0), r.size());
if (!m_theme->isCompositingActive()) {
if (frame->hasElementPrefix("decoration-opaque")) {
r = QRectF(conf.paddingLeft(), conf.paddingTop(),
sceneRect().width()-conf.paddingRight()-conf.paddingLeft(),
sceneRect().height()-conf.paddingBottom()-conf.paddingTop());
sourceRect = QRectF(0.0, 0.0, r.width(), r.height());
}
else {
r = QRectF(conf.paddingLeft(), conf.paddingTop(),
sceneRect().width(), sceneRect().height());
sourceRect = r;
}
}
frame->resizeFrame(r.size());
// animation
if (isAnimating() && frame->hasElementPrefix("decoration-inactive")) {
QPixmap target = frame->framePixmap();
frame->setElementPrefix("decoration-inactive");
if (!isActive()) {
frame->setElementPrefix("decoration");
}
if (!m_theme->isCompositingActive() && frame->hasElementPrefix("decoration-opaque-inactive")) {
frame->setElementPrefix("decoration-opaque-inactive");
if (!isActive()) {
frame->setElementPrefix("decoration-opaque");
}
}
if (maximized && frame->hasElementPrefix("decoration-maximized-inactive")) {
frame->setElementPrefix("decoration-maximized-inactive");
if (!isActive()) {
frame->setElementPrefix("decoration-maximized");
}
if (!m_theme->isCompositingActive() && frame->hasElementPrefix("decoration-maximized-opaque-inactive")) {
frame->setElementPrefix("decoration-maximized-opaque-inactive");
if (!isActive()) {
frame->setElementPrefix("decoration-maximized-opaque");
}
}
} else if (maximized && frame->hasElementPrefix("decoration-maximized")) {
frame->setElementPrefix("decoration-maximized");
}
frame->resizeFrame(r.size());
QPixmap result = Plasma::PaintUtils::transition(frame->framePixmap(),
target, m_animationProgress);
painter->drawPixmap(r.toRect(), result, sourceRect);
} else {
frame->paintFrame(painter, r, sourceRect);
}
painter->restore();
}
void AuroraeScene::updateLayout()
{
if (!m_theme->isValid()) {
return;
}
const ThemeConfig &config = m_theme->themeConfig();
int marginTop = qMin(config.buttonMarginTop(), config.titleHeight() - config.buttonHeight());
marginTop = qMax(marginTop, 0);
const int left = config.paddingLeft();
const int genericTop = config.paddingTop() + marginTop;
const int right = sceneRect().width() - m_rightButtons->preferredWidth() - config.paddingRight();
if (m_maximizeMode == KDecorationDefines::MaximizeFull) { // TODO: check option
const int top = genericTop + config.titleEdgeTopMaximized();
m_leftButtons->setGeometry(QRectF(QPointF(left + config.titleEdgeLeftMaximized(), top),
m_leftButtons->size()));
m_rightButtons->setGeometry(QRectF(QPointF(right - config.titleEdgeRightMaximized(), top),
m_rightButtons->size()));
// title
const int leftTitle = m_leftButtons->geometry().right() + config.titleBorderLeft();
const int titleWidth = m_rightButtons->geometry().left() - config.titleBorderRight() - leftTitle;
m_title->setGeometry(leftTitle, config.paddingTop() + config.titleEdgeTopMaximized(),
titleWidth, config.titleHeight());
m_title->layout()->invalidate();
} else {
const int top = genericTop + config.titleEdgeTop();
m_leftButtons->setGeometry(QRectF(QPointF(left + config.titleEdgeLeft(), top), m_leftButtons->size()));
m_rightButtons->setGeometry(QRectF(QPointF(right - config.titleEdgeRight(), top), m_rightButtons->size()));
// title
const int leftTitle = m_leftButtons->geometry().right() + config.titleBorderLeft();
const int titleWidth = m_rightButtons->geometry().left() - config.titleBorderRight() - leftTitle;
m_title->setGeometry(leftTitle, config.paddingTop() + config.titleEdgeTop(),
titleWidth, config.titleHeight());
m_title->layout()->invalidate();
}
}
void AuroraeScene::initButtons(QGraphicsLinearLayout* layout, const QString& buttons) const
{
if (!m_theme->isValid()) {
return;
}
foreach (const QChar &button, buttons) {
switch (button.toAscii()) {
case 'M': {
AuroraeMenuButton *button = new AuroraeMenuButton(m_theme);
connect(button, SIGNAL(clicked()), SIGNAL(menuClicked()));
connect(button, SIGNAL(doubleClicked()), SIGNAL(menuDblClicked()));
layout->addItem(button);
break;
}
case 'S':
if (m_theme->hasButton(AllDesktopsButton)) {
AuroraeButton *button = new AuroraeButton(m_theme, AllDesktopsButton);
button->setCheckable(true);
button->setChecked(m_allDesktops);
connect(button, SIGNAL(clicked()), SIGNAL(toggleOnAllDesktops()));
layout->addItem(button);
}
break;
case 'H':
if (m_contextHelp && m_theme->hasButton(HelpButton)) {
AuroraeButton *button = new AuroraeButton(m_theme, HelpButton);
connect(button, SIGNAL(clicked()), SIGNAL(showContextHelp()));
layout->addItem(button);
}
break;
case 'I':
if (m_theme->hasButton(MinimizeButton)) {
AuroraeButton *button = new AuroraeButton(m_theme, MinimizeButton);
connect(button, SIGNAL(clicked()), SIGNAL(minimizeWindow()));
layout->addItem(button);
}
break;
case 'A':
if (m_theme->hasButton(MaximizeButton) || m_theme->hasButton(RestoreButton)) {
AuroraeMaximizeButton *button = new AuroraeMaximizeButton(m_theme);
button->setMaximizeMode(m_maximizeMode);
connect(button, SIGNAL(clicked(Qt::MouseButtons)), SIGNAL(maximize(Qt::MouseButtons)));
layout->addItem(button);
}
break;
case 'X':
if (m_theme->hasButton(CloseButton)){
AuroraeButton *button = new AuroraeButton(m_theme, CloseButton);
connect(button, SIGNAL(clicked()), SIGNAL(closeWindow()));
layout->addItem(button);
}
break;
case 'F':
if (m_theme->hasButton(KeepAboveButton)) {
AuroraeButton *button = new AuroraeButton(m_theme, KeepAboveButton);
button->setCheckable(true);
button->setChecked(m_keepAbove);
connect(button, SIGNAL(clicked()), SIGNAL(toggleKeepAbove()));
layout->addItem(button);
}
break;
case 'B':
if (m_theme->hasButton(KeepBelowButton)) {
AuroraeButton *button = new AuroraeButton(m_theme, KeepBelowButton);
button->setCheckable(true);
button->setChecked(m_keepBelow);
connect(button, SIGNAL(clicked()), SIGNAL(toggleKeepBelow()));
layout->addItem(button);
}
break;
case 'L':
if (m_theme->hasButton(ShadeButton)) {
AuroraeButton *button = new AuroraeButton(m_theme, ShadeButton);
button->setCheckable(true);
button->setChecked(m_shade);
connect(button, SIGNAL(clicked()), SIGNAL(toggleShade()));
layout->addItem(button);
}
break;
case '_':
layout->addItem(new AuroraeSpacer(m_theme));
break;
default:
break; // nothing
}
}
}
void AuroraeScene::setIcon(const QIcon &icon)
{
m_iconPixmap = icon;
foreach (QGraphicsItem *item, items()) {
if (AuroraeMenuButton *button = dynamic_cast< AuroraeMenuButton* >(item)) {
const int iconSize = qMin(button->size().width(), button->size().height());
const QSize size = icon.actualSize(QSize(iconSize, iconSize));
QPixmap pix = icon.pixmap(size);
button->setIcon(pix);
}
}
}
bool AuroraeScene::isActive() const
{
return m_active;
}
void AuroraeScene::setActive(bool active, bool animate)
{
m_active = active;
if (isAnimating()) {
m_animation->stop();
}
m_animationProgress = 0.0;
int time = m_theme->themeConfig().animationTime();
if (time != 0 && animate) {
m_animation->setDuration(time);
m_animation->setEasingCurve(QEasingCurve::InOutQuad);
m_animation->setStartValue(0.0);
m_animation->setEndValue(1.0);
m_animation->start();
}
emit activeChanged();
update(sceneRect());
}
KDecorationDefines::MaximizeMode AuroraeScene::maximizeMode() const
{
return m_maximizeMode;
}
void AuroraeScene::setMaximizeMode(KDecorationDefines::MaximizeMode mode)
{
m_maximizeMode = mode;
foreach (QGraphicsItem *item, items()) {
if (AuroraeMaximizeButton *button = dynamic_cast< AuroraeMaximizeButton* >(item)) {
button->setMaximizeMode(mode);
}
}
updateLayout();
update(sceneRect());
}
bool AuroraeScene::isAnimating() const
{
return (m_animation->state() == QAbstractAnimation::Running);
}
qreal AuroraeScene::animationProgress() const
{
return m_animationProgress;
}
void AuroraeScene::setAnimationProgress(qreal progress)
{
m_animationProgress = progress;
update(sceneRect());
}
bool AuroraeScene::isAllDesktops() const
{
return m_allDesktops;
}
void AuroraeScene::setAllDesktops(bool all)
{
if (m_allDesktops == all) {
return;
}
m_allDesktops = all;
foreach (QGraphicsItem *item, items()) {
if (AuroraeButton *button = dynamic_cast< AuroraeButton* >(item)) {
if (button->type() == AllDesktopsButton) {
button->setChecked(m_allDesktops);
button->update();
}
}
}
}
bool AuroraeScene::isKeepAbove() const
{
return m_keepAbove;
}
void AuroraeScene::setKeepAbove(bool keep)
{
if (m_keepAbove == keep) {
return;
}
m_keepAbove = keep;
foreach (QGraphicsItem *item, items()) {
if (AuroraeButton *button = dynamic_cast< AuroraeButton* >(item)) {
if (button->type() == KeepAboveButton) {
button->setChecked(m_keepAbove);
button->update();
}
}
}
}
bool AuroraeScene::isKeepBelow() const
{
return m_keepBelow;
}
void AuroraeScene::setKeepBelow(bool keep)
{
if (m_keepBelow == keep) {
return;
}
m_keepBelow = keep;
foreach (QGraphicsItem *item, items()) {
if (AuroraeButton *button = dynamic_cast< AuroraeButton* >(item)) {
if (button->type() == KeepBelowButton) {
button->setChecked(m_keepBelow);
button->update();
}
}
}
}
bool AuroraeScene::isShade() const
{
return m_shade;
}
void AuroraeScene::setShade(bool shade)
{
if (m_shade == shade) {
return;
}
m_shade = shade;
foreach (QGraphicsItem *item, items()) {
if (AuroraeButton *button = dynamic_cast< AuroraeButton* >(item)) {
if (button->type() == ShadeButton) {
button->setChecked(m_shade);
button->update();
}
}
}
}
int AuroraeScene::leftButtonsWidth() const
{
if (!m_leftButtons) {
return 0;
}
return m_leftButtons->preferredWidth();
}
int AuroraeScene::rightButtonsWidth() const
{
if (!m_rightButtons) {
return 0;
}
return m_rightButtons->preferredWidth();
}
void AuroraeScene::setButtons(const QString &left, const QString &right)
{
m_leftButtonOrder = left;
m_rightButtonOrder = right;
resetTheme();
}
void AuroraeScene::setCaption(const QString &caption)
{
m_caption = caption;
foreach (QGraphicsItem *item, items()) {
if (AuroraeTab *tab = dynamic_cast<AuroraeTab*>(item)) {
tab->setCaption(caption);
}
}
}
void AuroraeScene::mousePressEvent(QGraphicsSceneMouseEvent* event)
{
QGraphicsScene::mousePressEvent(event);
if (!event->isAccepted()) {
event->accept();
emit titlePressed(event->button(), event->buttons());
}
}
void AuroraeScene::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
{
QGraphicsScene::mouseReleaseEvent(event);
if (!event->isAccepted()) {
if (m_dblClicked && event->button() == Qt::LeftButton) {
// eat event
m_dblClicked = false;
return;
}
emit titleReleased(event->button(), event->buttons());
}
}
void AuroraeScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)
{
QGraphicsScene::mouseDoubleClickEvent(event);
if (!event->isAccepted() && event->button() == Qt::LeftButton) {
m_dblClicked = true;
emit titleDoubleClicked();
}
}
void AuroraeScene::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
{
QGraphicsScene::mouseMoveEvent(event);
if (!event->isAccepted()) {
emit titleMouseMoved(event->button(), event->buttons());
}
}
void AuroraeScene::wheelEvent(QGraphicsSceneWheelEvent* event)
{
QGraphicsScene::wheelEvent(event);
if (!event->isAccepted()) {
emit wheelEvent(event->delta());
}
}
} // namespace

View file

@ -0,0 +1,126 @@
/*
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.
*/
#ifndef AURORAE_AURORAESCENE_H
#define AURORAE_AURORAESCENE_H
// #include "libaurorae_export.h"
#include <QtGui/QGraphicsScene>
#include <kdecoration.h>
class QGraphicsLayout;
class QGraphicsLinearLayout;
class QIcon;
class QPropertyAnimation;
namespace Aurorae {
class AuroraeTheme;
class /*LIBAURORAE_EXPORT*/ AuroraeScene : public QGraphicsScene
{
Q_OBJECT
Q_PROPERTY(qreal animation READ animationProgress WRITE setAnimationProgress)
public:
AuroraeScene(AuroraeTheme *theme, const QString &leftButtons, const QString &rightButtons, bool contextHelp, QObject* parent = 0);
virtual ~AuroraeScene();
void updateLayout();
void setActive(bool active, bool animate = true);
bool isActive() const;
void setIcon(const QIcon &icon);
void setAllDesktops(bool all);
bool isAllDesktops() const;
void setKeepAbove(bool keep);
bool isKeepAbove() const;
void setKeepBelow(bool keep);
bool isKeepBelow() const;
void setShade(bool shade);
bool isShade() const;
void setMaximizeMode(KDecorationDefines::MaximizeMode mode);
KDecorationDefines::MaximizeMode maximizeMode() const;
bool isAnimating() const;
qreal animationProgress() const;
void setAnimationProgress(qreal progress);
int leftButtonsWidth() const;
int rightButtonsWidth() const;
void setButtons(const QString &left, const QString &right);
void setCaption(const QString &caption);
Q_SIGNALS:
void menuClicked();
void menuDblClicked();
void showContextHelp();
void maximize(Qt::MouseButtons button);
void minimizeWindow();
void closeWindow();
void toggleOnAllDesktops();
void toggleKeepAbove();
void toggleKeepBelow();
void toggleShade();
void titlePressed(Qt::MouseButton, Qt::MouseButtons);
void titleReleased(Qt::MouseButton, Qt::MouseButtons);
void titleDoubleClicked();
void titleMouseMoved(Qt::MouseButton, Qt::MouseButtons);
void wheelEvent(int delta);
void activeChanged();
protected:
virtual void drawBackground(QPainter* painter, const QRectF& rect);
virtual void mousePressEvent(QGraphicsSceneMouseEvent* event);
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent* event);
virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event);
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent* event);
virtual void wheelEvent(QGraphicsSceneWheelEvent* event);
private Q_SLOTS:
void resetTheme();
private:
void init();
void initButtons(QGraphicsLinearLayout *layout, const QString &buttons) const;
AuroraeTheme *m_theme;
QGraphicsWidget *m_leftButtons;
QGraphicsWidget *m_rightButtons;
QGraphicsWidget *m_title;
bool m_active;
qreal m_animationProgress;
QPropertyAnimation *m_animation;
KDecorationDefines::MaximizeMode m_maximizeMode;
QIcon m_iconPixmap;
bool m_allDesktops;
bool m_shade;
bool m_keepAbove;
bool m_keepBelow;
QString m_leftButtonOrder;
QString m_rightButtonOrder;
QString m_caption;
bool m_dblClicked;
bool m_contextHelp;
};
} // namespace
#endif // AURORAE_AURORAESCENE_H

View file

@ -0,0 +1,157 @@
/*
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/PaintUtils>
namespace Aurorae
{
AuroraeTab::AuroraeTab(AuroraeTheme* theme, const QString& caption)
: QGraphicsWidget()
, m_theme(theme)
, m_caption(caption)
{
m_effect = new QGraphicsDropShadowEffect(this);
if (m_theme->themeConfig().useTextShadow()) {
setGraphicsEffect(m_effect);
}
setAcceptedMouseButtons(Qt::NoButton);
}
AuroraeTab::~AuroraeTab()
{
}
void AuroraeTab::activeChanged()
{
const ThemeConfig &config = m_theme->themeConfig();
if (!config.useTextShadow()) {
return;
}
const bool active = static_cast<AuroraeScene*>(scene())->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::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 ThemeConfig &conf = m_theme->themeConfig();
const QRect textRect = painter->fontMetrics().boundingRect(rect().toRect(),
conf.alignment() | conf.verticalAlignment() | Qt::TextSingleLine,
m_caption);
if ((active && conf.haloActive()) ||
(!active && conf.haloInactive())) {
QRect haloRect = textRect;
if (haloRect.width() > rect().width()) {
haloRect.setWidth(rect().width());
}
Plasma::PaintUtils::drawHalo(painter, haloRect);
}
QPixmap pix(rect().size().toSize());
pix.fill(Qt::transparent);
QPainter p(&pix);
QColor color;
if (active) {
color = conf.activeTextColor();
if (s->isAnimating()) {
color = KColorUtils::mix(conf.inactiveTextColor(), conf.activeTextColor(), s->animationProgress());
}
} else {
color = conf.inactiveTextColor();
if (s->isAnimating()){
color = KColorUtils::mix(conf.activeTextColor(), conf.inactiveTextColor(), s->animationProgress());
}
}
p.setPen(color);
p.drawText(pix.rect(), conf.alignment() | conf.verticalAlignment() | Qt::TextSingleLine, m_caption);
if (textRect.width() > rect().width()) {
// 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();
painter->drawPixmap(rect().toRect(), pix);
painter->restore();
}
QSizeF AuroraeTab::sizeHint(Qt::SizeHint which, const QSizeF& constraint) const
{
QFont titleFont = KGlobalSettings::windowTitleFont();
QFontMetricsF fm(titleFont);
switch (which) {
case Qt::MinimumSize:
fm.boundingRect(m_caption.left(3)).size();
break;
case Qt::PreferredSize:
return fm.boundingRect(m_caption).size();
case Qt::MaximumSize:
return QSizeF(scene()->sceneRect().width(), m_theme->themeConfig().titleHeight());
default:
return QGraphicsWidget::sizeHint(which, constraint);
}
return QGraphicsWidget::sizeHint(which, constraint);
}
} // namespace

View file

@ -0,0 +1,53 @@
/*
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.
*/
#ifndef AURORAE_AURORAETAB_H
#define AURORAE_AURORAETAB_H
#include <QtGui/QGraphicsWidget>
class QGraphicsDropShadowEffect;
namespace Aurorae {
class AuroraeTheme;
class AuroraeTab : public QGraphicsWidget
{
Q_OBJECT
public:
AuroraeTab(AuroraeTheme *theme, const QString &caption);
virtual ~AuroraeTab();
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
void setCaption(const QString &caption);
public Q_SLOTS:
void activeChanged();
protected:
virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF& constraint = QSizeF()) const;
private:
AuroraeTheme *m_theme;
QString m_caption;
QGraphicsDropShadowEffect *m_effect;
};
}
#endif // AURORAE_AURORAETAB_H

View file

@ -0,0 +1,324 @@
/*
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 "auroraetheme.h"
#include "themeconfig.h"
// Qt
#include <QtCore/QHash>
// KDE
#include <KDE/KConfig>
#include <KDE/KConfigGroup>
#include <KDE/KDebug>
#include <KDE/KStandardDirs>
#include <KDE/KGlobal>
#include <KDE/Plasma/FrameSvg>
namespace Aurorae {
/************************************************
* AuroraeThemePrivate
************************************************/
class AuroraeThemePrivate
{
public:
AuroraeThemePrivate();
~AuroraeThemePrivate();
void initButtonFrame(AuroraeButtonType type);
void reset();
QString themeName;
Aurorae::ThemeConfig themeConfig;
Plasma::FrameSvg *decoration;
QHash< AuroraeButtonType, Plasma::FrameSvg* > buttons;
bool activeCompositing;
KDecorationDefines::BorderSize borderSize;
};
AuroraeThemePrivate::AuroraeThemePrivate()
: decoration(0)
, activeCompositing(true)
, borderSize(KDecoration::BorderNormal)
{
}
AuroraeThemePrivate::~AuroraeThemePrivate()
{
while (!buttons.isEmpty()) {
Plasma::FrameSvg *button = buttons.begin().value();
delete button;
button = 0;
buttons.remove(buttons.begin().key());
}
}
void AuroraeThemePrivate::initButtonFrame(AuroraeButtonType type)
{
QString file("aurorae/themes/" + themeName + '/' + AuroraeTheme::mapButtonToName(type) + ".svg");
QString path = KGlobal::dirs()->findResource("data", file);
if (path.isEmpty()) {
// let's look for svgz
file.append("z");
path = KGlobal::dirs()->findResource("data", file);
}
if (!path.isEmpty()) {
Plasma::FrameSvg *frame = new Plasma::FrameSvg();
frame->setImagePath(path);
frame->setCacheAllRenderedFrames(true);
frame->setEnabledBorders(Plasma::FrameSvg::NoBorder);
buttons[ type ] = frame;
} else {
kDebug(1216) << "No button for: " << AuroraeTheme::mapButtonToName(type);
}
}
void AuroraeThemePrivate::reset()
{
decoration->clearCache();
delete decoration;
decoration = 0;
while (!buttons.isEmpty()) {
Plasma::FrameSvg *button = buttons.begin().value();
button->clearCache();
delete button;
button = 0;
buttons.remove(buttons.begin().key());
}
}
/************************************************
* AuroraeTheme
************************************************/
AuroraeTheme::AuroraeTheme(QObject* parent)
: QObject(parent)
, d(new AuroraeThemePrivate)
{
}
AuroraeTheme::~AuroraeTheme()
{
delete d;
}
bool AuroraeTheme::isValid() const
{
return !d->themeName.isNull();
}
void AuroraeTheme::loadTheme(const QString &name, const KConfig &config)
{
if (!d->themeName.isNull()) {
// only reset if the theme has been initialized at least once
d->reset();
}
d->themeName = name;
QString file("aurorae/themes/" + d->themeName + "/decoration.svg");
QString path = KGlobal::dirs()->findResource("data", file);
if (path.isEmpty()) {
file += 'z';
path = KGlobal::dirs()->findResource("data", file);
}
if (path.isEmpty()) {
kDebug(1216) << "Could not find decoration svg: aborting";
d->themeName = QString();
return;
}
d->decoration = new Plasma::FrameSvg(this);
d->decoration->setImagePath(path);
d->decoration->setCacheAllRenderedFrames(true);
d->decoration->setEnabledBorders(Plasma::FrameSvg::AllBorders);
// load the buttons
d->initButtonFrame(MinimizeButton);
d->initButtonFrame(MaximizeButton);
d->initButtonFrame(RestoreButton);
d->initButtonFrame(CloseButton);
d->initButtonFrame(AllDesktopsButton);
d->initButtonFrame(KeepAboveButton);
d->initButtonFrame(KeepBelowButton);
d->initButtonFrame(ShadeButton);
d->initButtonFrame(HelpButton);
d->themeConfig.load(config);
emit themeChanged();
}
void AuroraeTheme::readThemeConfig(const KConfig &config)
{
// read config values
d->themeConfig.load(config);
emit themeChanged();
}
Plasma::FrameSvg *AuroraeTheme::button(AuroraeButtonType b) const
{
if (hasButton(b)) {
return d->buttons[ b ];
} else {
return NULL;
}
}
Plasma::FrameSvg *AuroraeTheme::decoration() const
{
return d->decoration;
}
bool AuroraeTheme::hasButton(AuroraeButtonType button) const
{
return d->buttons.contains(button);
}
QLatin1String AuroraeTheme::mapButtonToName(AuroraeButtonType type)
{
switch(type) {
case MinimizeButton:
return QLatin1String("minimize");
case MaximizeButton:
return QLatin1String("maximize");
case RestoreButton:
return QLatin1String("restore");
case CloseButton:
return QLatin1String("close");
case AllDesktopsButton:
return QLatin1String("alldesktops");
case KeepAboveButton:
return QLatin1String("keepabove");
case KeepBelowButton:
return QLatin1String("keepbelow");
case ShadeButton:
return QLatin1String("shade");
case HelpButton:
return QLatin1String("help");
default:
return QLatin1String("");
}
}
const QString &AuroraeTheme::themeName() const
{
return d->themeName;
}
const Aurorae::ThemeConfig &AuroraeTheme::themeConfig() const
{
return d->themeConfig;
}
void AuroraeTheme::borders(int& left, int& top, int& right, int& bottom, bool maximized) const
{
if (maximized) {
left = 0;
right = 0;
bottom = 0;
top = d->themeConfig.titleHeight() + d->themeConfig.titleEdgeTopMaximized() + d->themeConfig.titleEdgeBottomMaximized();
} else {
switch (d->borderSize) {
case KDecoration::BorderTiny:
if (isCompositingActive()) {
left = qMin(0, (int)left - d->themeConfig.borderLeft() - d->themeConfig.paddingLeft());
right = qMin(0, (int)right - d->themeConfig.borderRight() - d->themeConfig.paddingRight());
bottom = qMin(0, (int)bottom - d->themeConfig.borderBottom() - d->themeConfig.paddingBottom());
} else {
left = qMin(0, (int)left - d->themeConfig.borderLeft());
right = qMin(0, (int)right - d->themeConfig.borderRight());
bottom = qMin(0, (int)bottom - d->themeConfig.borderBottom());
}
break;
case KDecoration::BorderLarge:
left = right = bottom = 4;
break;
case KDecoration::BorderVeryLarge:
left = right = bottom = 8;
break;
case KDecoration::BorderHuge:
left = right = bottom = 12;
break;
case KDecoration::BorderVeryHuge:
left = right = bottom = 23;
break;
case KDecoration::BorderOversized:
left = right = bottom = 36;
break;
case KDecoration::BorderNormal:
default:
left = right = bottom = 0;
}
left += d->themeConfig.borderLeft();
right += d->themeConfig.borderRight();
bottom += d->themeConfig.borderBottom();
top = d->themeConfig.titleHeight() + d->themeConfig.titleEdgeTop() + d->themeConfig.titleEdgeBottom();
}
}
void AuroraeTheme::padding(int& left, int& top, int& right, int& bottom) const
{
left = d->themeConfig.paddingLeft();
top = d->themeConfig.paddingTop();
right = d->themeConfig.paddingRight();
bottom = d->themeConfig.paddingBottom();
}
void AuroraeTheme::titleEdges(int &left, int &top, int &right, int &bottom, bool maximized) const
{
if (maximized) {
left = d->themeConfig.titleEdgeLeftMaximized();
top = d->themeConfig.titleEdgeTopMaximized();
right = d->themeConfig.titleEdgeRightMaximized();
bottom = d->themeConfig.titleEdgeBottomMaximized();
} else {
left = d->themeConfig.titleEdgeLeft();
top = d->themeConfig.titleEdgeTop();
right = d->themeConfig.titleEdgeRight();
bottom = d->themeConfig.titleEdgeBottom();
}
}
void AuroraeTheme::buttonMargins(int &left, int &top, int &right) const
{
left = d->themeConfig.titleBorderLeft();
top = d->themeConfig.buttonMarginTop();
right = d->themeConfig.titleBorderRight();
}
bool AuroraeTheme::isCompositingActive() const
{
return d->activeCompositing;
}
void AuroraeTheme::setCompositingActive(bool active)
{
d->activeCompositing = active;
}
QString AuroraeTheme::defaultButtonsLeft() const
{
return d->themeConfig.defaultButtonsLeft();
}
QString AuroraeTheme::defaultButtonsRight() const
{
return d->themeConfig.defaultButtonsRight();
}
void AuroraeTheme::setBorderSize(KDecorationDefines::BorderSize size)
{
d->borderSize = size;
}
} // namespace

View file

@ -0,0 +1,127 @@
/*
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.
*/
#ifndef AURORAETHEME_H
#define AURORAETHEME_H
// #include "libaurorae_export.h"
#include <QtCore/QObject>
#include <QtGui/QGraphicsItem>
#include <kdecoration.h>
namespace Plasma {
class FrameSvg;
}
class KConfig;
namespace Aurorae {
class AuroraeThemePrivate;
class AuroraeTab;
class AuroraeScene;
class AuroraeButton;
class AuroraeMaximizeButton;
class AuroraeSpacer;
class ThemeConfig;
enum AuroraeButtonType {
MinimizeButton = QGraphicsItem::UserType+1,
MaximizeButton,
RestoreButton,
CloseButton,
AllDesktopsButton,
KeepAboveButton,
KeepBelowButton,
ShadeButton,
HelpButton,
MenuButton
};
class /*LIBAURORAE_EXPORT*/ AuroraeTheme : public QObject
{
Q_OBJECT
public:
AuroraeTheme(QObject* parent = 0);
virtual ~AuroraeTheme();
// TODO: KSharedConfigPtr
void loadTheme(const QString &name, const KConfig &config);
bool isValid() const;
void readThemeConfig(const KConfig& config);
const QString &themeName() const;
/**
* Sets the borders according to maximized state.
* Borders are global to all windows.
*/
void borders(int &left, int &top, int &right, int &bottom, bool maximized) const;
/**
* Sets the padding according.
* Padding is global to all windows.
*/
void padding(int &left, int &top, int &right, int &bottom) const;
/**
* Sets the title edges according to maximized state.
* Title edges are global to all windows.
*/
void titleEdges(int &left, int &top, int &right, int &bottom, bool maximized) const;
/**
* Sets the button margins.
* Button margins are global to all windows. There is no button margin bottom.
*/
void buttonMargins(int& left, int& top, int& right) const;
void setCompositingActive(bool active);
bool isCompositingActive() const;
/**
* @returns The FrameSvg containing the decoration.
*/
Plasma::FrameSvg *decoration() const;
/**
* @returns The FrameSvg for the specified button or NULL if there is no such button.
*/
Plasma::FrameSvg *button(AuroraeButtonType button) const;
/**
* @returns true if the theme contains a FrameSvg for specified button.
*/
bool hasButton(AuroraeButtonType button) const;
QString defaultButtonsLeft() const;
QString defaultButtonsRight() const;
void setBorderSize(KDecorationDefines::BorderSize size);
// TODO: move to namespace
static QLatin1String mapButtonToName(AuroraeButtonType type);
Q_SIGNALS:
void themeChanged();
private:
const ThemeConfig &themeConfig() const;
AuroraeThemePrivate* const d;
friend class Aurorae::AuroraeButton;
friend class Aurorae::AuroraeMaximizeButton;
friend class Aurorae::AuroraeSpacer;
friend class Aurorae::AuroraeScene;
friend class Aurorae::AuroraeTab;
};
} // namespace
#endif // AURORAETHEME_H

View file

@ -27,9 +27,9 @@ ThemeConfig::ThemeConfig()
{
}
void ThemeConfig::load(KConfig *conf)
void ThemeConfig::load(const KConfig &conf)
{
KConfigGroup general(conf, "General");
KConfigGroup general(&conf, "General");
m_activeTextColor = general.readEntry("ActiveTextColor", QColor(Qt::black));
m_inactiveTextColor = general.readEntry("InactiveTextColor", QColor(Qt::black));
m_useTextShadow = general.readEntry("UseTextShadow", false);
@ -64,7 +64,7 @@ void ThemeConfig::load(KConfig *conf)
m_defaultButtonsRight = general.readEntry("RightButtons", KDecorationOptions::defaultTitleButtonsRight());
m_shadow = general.readEntry("Shadow", true);
KConfigGroup border(conf, "Layout");
KConfigGroup border(&conf, "Layout");
// default values taken from KCommonDecoration::layoutMetric() in kcommondecoration.cpp
m_borderLeft = border.readEntry("BorderLeft", 5);
m_borderRight = border.readEntry("BorderRight", 5);

View file

@ -30,7 +30,7 @@ class ThemeConfig
{
public:
ThemeConfig();
void load(KConfig *conf);
void load(const KConfig &conf);
~ThemeConfig() {};
// active window
QColor activeTextColor() const {

View file

@ -1,6 +1,6 @@
# need a header file from Aurorae sources
include_directories(
${KDEBASE_WORKSPACE_SOURCE_DIR}/kwin/clients/aurorae/src/
${KDEBASE_WORKSPACE_SOURCE_DIR}/kwin/clients/aurorae/src/lib
)
set(kcm_kwindecoration_PART_SRCS
@ -12,7 +12,7 @@ set(kcm_kwindecoration_PART_SRCS
decorationdelegate.cpp
decorationmodel.cpp
auroraepreview.cpp
${KDEBASE_WORKSPACE_SOURCE_DIR}/kwin/clients/aurorae/src/themeconfig.cpp
${KDEBASE_WORKSPACE_SOURCE_DIR}/kwin/clients/aurorae/src/lib/themeconfig.cpp
)
kde4_add_ui_files(kcm_kwindecoration_PART_SRCS buttons.ui config.ui decoration.ui)

View file

@ -54,7 +54,7 @@ AuroraePreview::AuroraePreview( const QString& name, const QString& packageName,
m_themeConfig = new Aurorae::ThemeConfig();
KConfig conf( "aurorae/themes/" + packageName + '/' + packageName + "rc", KConfig::FullConfig, "data" );
m_themeConfig->load( &conf );
m_themeConfig->load( conf );
initButtonFrame( "minimize", packageName );
initButtonFrame( "maximize", packageName );