kwin/kcmkwin/kwindecoration/auroraepreview.cpp
Martin Gräßlin 1bcd9fe4f6 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
2010-04-12 19:28:58 +00:00

381 lines
14 KiB
C++

/********************************************************************
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/>.
*********************************************************************/
#include "auroraepreview.h"
#include "themeconfig.h"
// Qt
#include <QFile>
#include <QFont>
#include <QPainter>
// KDE
#include <KGlobalSettings>
#include <KIcon>
#include <KLocale>
#include <KStandardDirs>
// Plasma
#include <Plasma/FrameSvg>
#include <Plasma/PaintUtils>
namespace KWin
{
AuroraePreview::AuroraePreview( const QString& name, const QString& packageName,
const QString& themeRoot, QObject* parent )
: QObject( parent )
, m_title( name )
{
m_svg = new Plasma::FrameSvg( this );
QString svgFile = themeRoot + "/decoration.svg";
if( QFile::exists( svgFile ) )
{
m_svg->setImagePath( svgFile );
}
else
{
m_svg->setImagePath( svgFile + 'z' );
}
m_svg->setEnabledBorders( Plasma::FrameSvg::AllBorders );
m_themeConfig = new Aurorae::ThemeConfig();
KConfig conf( "aurorae/themes/" + packageName + '/' + packageName + "rc", KConfig::FullConfig, "data" );
m_themeConfig->load( conf );
initButtonFrame( "minimize", packageName );
initButtonFrame( "maximize", packageName );
initButtonFrame( "restore", packageName );
initButtonFrame( "close", packageName );
initButtonFrame( "alldesktops", packageName );
initButtonFrame( "keepabove", packageName );
initButtonFrame( "keepbelow", packageName );
initButtonFrame( "shade", packageName );
initButtonFrame( "help", packageName );
}
AuroraePreview::~AuroraePreview()
{
delete m_themeConfig;
}
void AuroraePreview::initButtonFrame( const QString &button, const QString &themeName )
{
QString file( "aurorae/themes/" + themeName + '/' + button + ".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( this );
frame->setImagePath( path );
frame->setCacheAllRenderedFrames( true );
frame->setEnabledBorders( Plasma::FrameSvg::NoBorder );
m_buttons.insert( button, frame );
}
}
QPixmap AuroraePreview::preview( const QSize& size, bool custom,
const QString& left, const QString& right ) const
{
QPixmap pixmap( size );
pixmap.fill( Qt::transparent );
QPainter painter( &pixmap );
painter.save();
paintDeco( &painter, false, pixmap.rect(), 5 + m_themeConfig->paddingLeft() + m_themeConfig->borderLeft(),
5, 5, 5 + m_themeConfig->paddingBottom() + m_themeConfig->borderBottom(),
custom, left, right );
painter.restore();
painter.save();
int activeLeft = 5;
int activeTop = 5 + m_themeConfig->paddingTop() + m_themeConfig->titleEdgeTop() +
m_themeConfig->titleEdgeBottom() + m_themeConfig->titleHeight();
int activeRight = 5 + m_themeConfig->paddingRight() + m_themeConfig->borderRight();
int activeBottom = 5;
paintDeco( &painter, true, pixmap.rect(), activeLeft, activeTop, activeRight, activeBottom,
custom, left, right );
painter.restore();
// paint title
painter.save();
QFont font = painter.font();
font.setWeight( QFont::Bold );
painter.setPen( m_themeConfig->activeTextColor() );
painter.setFont( font );
painter.drawText( QRect( pixmap.rect().topLeft() + QPoint( activeLeft, activeTop ),
pixmap.rect().bottomRight() - QPoint( activeRight, activeBottom ) ),
Qt::AlignCenter | Qt::TextWordWrap, m_title );
painter.restore();
return pixmap;
}
void AuroraePreview::paintDeco( QPainter *painter, bool active, const QRect &rect,
int leftMargin, int topMargin, int rightMargin, int bottomMargin,
bool custom, const QString& left, const QString& right ) const
{
m_svg->setElementPrefix( "decoration" );
if( !active && m_svg->hasElementPrefix("decoration-inactive") )
{
m_svg->setElementPrefix( "decoration-inactive" );
}
m_svg->resizeFrame( QSize( rect.width() - leftMargin - rightMargin, rect.height() - topMargin - bottomMargin ) );
m_svg->paintFrame( painter, rect.topLeft() + QPoint( leftMargin, topMargin ) );
int y = rect.top() + topMargin + m_themeConfig->paddingTop() + m_themeConfig->titleEdgeTop() + m_themeConfig->buttonMarginTop();
int x = rect.left() + leftMargin + m_themeConfig->paddingLeft() + m_themeConfig->titleEdgeLeft();
int buttonWidth = m_themeConfig->buttonWidth();
int buttonHeight = m_themeConfig->buttonHeight();
foreach( const QChar &character, custom ? left : m_themeConfig->defaultButtonsLeft() )
{
QString buttonName;
int width = buttonWidth;
if( character == '_' )
{
x += m_themeConfig->explicitButtonSpacer() + m_themeConfig->buttonSpacing();
continue;
}
else if( character == 'M' )
{
KIcon icon = KIcon( "xorg" );
int iconSize = qMin( m_themeConfig->buttonWidthMenu(), m_themeConfig->buttonHeight() );
QSize buttonSize( iconSize,iconSize );
painter->drawPixmap( QPoint( x, y ), icon.pixmap( buttonSize ) );
x += m_themeConfig->buttonWidthMenu();
}
else if( character == 'S' )
{
buttonName = "alldesktops";
width = m_themeConfig->buttonWidthAllDesktops();
}
else if( character == 'H' )
{
buttonName = "help";
width = m_themeConfig->buttonWidthHelp();
}
else if( character == 'I' )
{
buttonName = "minimize";
width = m_themeConfig->buttonWidthMinimize();
}
else if( character == 'A' )
{
buttonName = "restore";
if( !m_buttons.contains( buttonName ) )
{
buttonName = "maximize";
}
width = m_themeConfig->buttonWidthMaximizeRestore();
}
else if( character == 'X' )
{
buttonName = "close";
width = m_themeConfig->buttonWidthClose();
}
else if( character == 'F' )
{
buttonName = "keepabove";
width = m_themeConfig->buttonWidthKeepAbove();
}
else if( character == 'B' )
{
buttonName = "keepbelow";
width = m_themeConfig->buttonWidthKeepBelow();
}
else if( character == 'L' )
{
buttonName = "shade";
width = m_themeConfig->buttonWidthShade();
}
if( !buttonName.isEmpty() && m_buttons.contains( buttonName ) )
{
Plasma::FrameSvg *frame = m_buttons.value( buttonName );
frame->setElementPrefix( "active" );
if( !active && frame->hasElementPrefix( "inactive" ) )
{
frame->setElementPrefix( "inactive" );
}
frame->resizeFrame( QSize( width, buttonHeight ) );
frame->paintFrame( painter, QPoint( x, y ) );
x += width;
}
x += m_themeConfig->buttonSpacing();
}
if( !m_themeConfig->defaultButtonsLeft().isEmpty() )
{
x -= m_themeConfig->buttonSpacing();
}
int titleLeft = x;
x = rect.right() - rightMargin - m_themeConfig->paddingRight() - m_themeConfig->titleEdgeRight();
QString rightButtons;
foreach( const QChar &character, custom ? right : m_themeConfig->defaultButtonsRight() )
{
rightButtons.prepend(character);
}
foreach (const QChar &character, rightButtons)
{
QString buttonName;
int width = buttonWidth;
if( character == '_' )
{
x -= m_themeConfig->explicitButtonSpacer() + m_themeConfig->buttonSpacing();
continue;
}
else if( character == 'M' )
{
KIcon icon = KIcon( "xorg" );
QSize buttonSize( buttonWidth, buttonHeight );
x -= m_themeConfig->buttonWidthMenu();
painter->drawPixmap( QPoint( x, y ), icon.pixmap( buttonSize ) );
}
else if( character == 'S' )
{
buttonName = "alldesktops";
width = m_themeConfig->buttonWidthAllDesktops();
}
else if( character == 'H' )
{
buttonName = "help";
width = m_themeConfig->buttonWidthHelp();
}
else if( character == 'I' )
{
buttonName = "minimize";
width = m_themeConfig->buttonWidthMinimize();
}
else if( character == 'A' )
{
buttonName = "restore";
if( !m_buttons.contains( buttonName ) )
{
buttonName = "maximize";
}
width = m_themeConfig->buttonWidthMaximizeRestore();
}
else if( character == 'X' )
{
buttonName = "close";
width = m_themeConfig->buttonWidthClose();
}
else if( character == 'F' )
{
buttonName = "keepabove";
width = m_themeConfig->buttonWidthKeepAbove();
}
else if( character == 'B' )
{
buttonName = "keepbelow";
width = m_themeConfig->buttonWidthKeepBelow();
}
else if( character == 'L' )
{
buttonName = "shade";
width = m_themeConfig->buttonWidthShade();
}
if( !buttonName.isEmpty() && m_buttons.contains( buttonName ) )
{
Plasma::FrameSvg *frame = m_buttons.value( buttonName );
frame->setElementPrefix( "active" );
if( !active && frame->hasElementPrefix( "inactive" ) )
{
frame->setElementPrefix( "inactive" );
}
frame->resizeFrame( QSize( width, buttonHeight ) );
x -= width;
frame->paintFrame( painter, QPoint( x, y) );
}
x -= m_themeConfig->buttonSpacing();
}
if( !rightButtons.isEmpty() )
{
x += m_themeConfig->buttonSpacing();
}
int titleRight = x;
// draw text
y = rect.top() + topMargin + m_themeConfig->paddingTop() + m_themeConfig->titleEdgeTop();
QRectF titleRect( QPointF( titleLeft, y ), QPointF( titleRight, y + m_themeConfig->titleHeight() ) );
QString caption = i18n( "Active Window" );
if( !active )
{
caption = i18n( "Inactive Window" );
}
painter->setFont( KGlobalSettings::windowTitleFont() );
if( ( active && m_themeConfig->haloActive() ) || ( !active && m_themeConfig->haloInactive() ) )
{
QRectF haloRect = painter->fontMetrics().boundingRect(titleRect.toRect(),
m_themeConfig->alignment() | m_themeConfig->verticalAlignment() | Qt::TextSingleLine,
caption);
if( haloRect.width() > titleRect.width() )
haloRect.setWidth( titleRect.width() );
Plasma::PaintUtils::drawHalo(painter, haloRect);
}
if( m_themeConfig->useTextShadow() )
{
// shadow code is inspired by Qt FAQ: How can I draw shadows behind text?
// see http://www.qtsoftware.com/developer/faqs/faq.2007-07-27.3052836051
painter->save();
if( active )
{
painter->setPen( m_themeConfig->activeTextShadowColor() );
}
else
{
painter->setPen( m_themeConfig->inactiveTextShadowColor() );
}
int dx = m_themeConfig->textShadowOffsetX();
int dy = m_themeConfig->textShadowOffsetY();
painter->setOpacity( 0.5 );
painter->drawText( titleRect.translated( dx, dy ),
m_themeConfig->alignment() | m_themeConfig->verticalAlignment() | Qt::TextSingleLine,
caption );
painter->setOpacity( 0.2 );
painter->drawText( titleRect.translated( dx+1, dy ),
m_themeConfig->alignment() | m_themeConfig->verticalAlignment() | Qt::TextSingleLine,
caption );
painter->drawText( titleRect.translated( dx-1, dy ),
m_themeConfig->alignment() | m_themeConfig->verticalAlignment() | Qt::TextSingleLine,
caption );
painter->drawText( titleRect.translated( dx, dy+1 ),
m_themeConfig->alignment() | m_themeConfig->verticalAlignment() | Qt::TextSingleLine,
caption );
painter->drawText( titleRect.translated( dx, dy-1 ),
m_themeConfig->alignment() | m_themeConfig->verticalAlignment() | Qt::TextSingleLine,
caption );
painter->restore();
painter->save();
}
if( active )
{
painter->setPen( m_themeConfig->activeTextColor() );
}
else
{
painter->setPen( m_themeConfig->inactiveTextColor() );
}
painter->drawText( titleRect,
m_themeConfig->alignment() | m_themeConfig->verticalAlignment() | Qt::TextSingleLine,
caption );
painter->restore();
}
} // namespace KWin