New decoration kcm:

* Displays list with previews instead of a dropdown with just the name.
* Configuration is moved into an own dialog accessible via a configure button for each decoration
* Button configuration is moved into a dialog, by that the tabs are removed
* Aurorae themes are listed just like normal decorations
* GHNS support to download Aurorae themes
* Semi-live preview of changed: when configure dialog is closed the preview is updated
* About Dialog added for each decoration (needs updates in desktop files - the information is missing)

svn path=/trunk/KDE/kdebase/workspace/; revision=1077141
This commit is contained in:
Martin Gräßlin 2010-01-19 13:44:22 +00:00
parent f5dd7d7185
commit c9df18ab98
20 changed files with 1948 additions and 590 deletions

View file

@ -1,6 +1,24 @@
set(kcm_kwindecoration_PART_SRCS kwindecoration.cpp buttons.cpp preview.cpp )
# need a header file from Aurorae sources
include_directories(
${KDEBASE_WORKSPACE_SOURCE_DIR}/kwin/clients/aurorae/src/
)
set(kcm_kwindecoration_PART_SRCS
kwindecoration.cpp
buttons.cpp
buttonsconfigdialog.cpp
configdialog.cpp
preview.cpp
decorationdelegate.cpp
decorationmodel.cpp
auroraepreview.cpp
${KDEBASE_WORKSPACE_SOURCE_DIR}/kwin/clients/aurorae/src/themeconfig.cpp
)
kde4_add_ui_files(kcm_kwindecoration_PART_SRCS buttons.ui config.ui decoration.ui)
kde4_add_plugin(kcm_kwindecoration ${kcm_kwindecoration_PART_SRCS})
target_link_libraries(kcm_kwindecoration kdecorations ${X11_LIBRARIES})
target_link_libraries(kcm_kwindecoration ${KDE4_PLASMA_LIBS} ${KDE4_KNEWSTUFF3_LIBS} kdecorations ${X11_LIBRARIES})
install(TARGETS kcm_kwindecoration DESTINATION ${PLUGIN_INSTALL_DIR} )
########### install files ###############

View file

@ -0,0 +1,371 @@
/********************************************************************
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>
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( 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

View file

@ -0,0 +1,62 @@
/********************************************************************
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/>.
*********************************************************************/
#ifndef KWIN_AURORAEPREVIEW_H
#define KWIN_AURORAEPREVIEW_H
#include <QObject>
#include <QPixmap>
#include <QHash>
namespace Aurorae
{
class ThemeConfig;
}
namespace Plasma
{
class FrameSvg;
}
namespace KWin
{
class AuroraePreview : public QObject
{
public:
AuroraePreview( const QString& name, const QString& packageName,
const QString& themeRoot, QObject* parent = NULL );
~AuroraePreview();
QPixmap preview( const QSize& size, bool custom, const QString& left, const QString& right ) const;
private:
void initButtonFrame( const QString &button, const QString &themeName );
void 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;
Plasma::FrameSvg *m_svg;
Aurorae::ThemeConfig *m_themeConfig;
QHash<QString, Plasma::FrameSvg*> m_buttons;
QString m_title;
};
} // namespace KWin
#endif // KWIN_AURORAEPREVIEW_H

View file

@ -47,6 +47,9 @@
#define BUTTONDRAGMIMETYPE "application/x-kde_kwindecoration_buttons"
namespace KWin
{
ButtonDrag::ButtonDrag(Button btn)
: QMimeData()
{
@ -678,6 +681,7 @@ ButtonPositionWidget::ButtonPositionWidget(QWidget *parent)
// insert all possible buttons into the source (backwards to keep the preferred order...)
bool dummy;
m_supportedButtons = "MSHIAX_FBLR"; // support all buttons
new ButtonSourceItem(m_buttonSource, getButton('R', dummy) );
new ButtonSourceItem(m_buttonSource, getButton('L', dummy) );
new ButtonSourceItem(m_buttonSource, getButton('B', dummy) );
@ -695,61 +699,6 @@ ButtonPositionWidget::~ButtonPositionWidget()
{
}
void ButtonPositionWidget::setDecorationFactory(KDecorationFactory *factory)
{
if (!factory)
return;
m_factory = factory;
// get the list of supported buttons
if (m_factory->supports(KDecorationDefines::AbilityAnnounceButtons) ) {
QString supportedButtons;
if (m_factory->supports(KDecorationDefines::AbilityButtonMenu) )
supportedButtons.append('M');
if (m_factory->supports(KDecorationDefines::AbilityButtonOnAllDesktops) )
supportedButtons.append('S');
if (m_factory->supports(KDecorationDefines::AbilityButtonSpacer) )
supportedButtons.append('_');
if (m_factory->supports(KDecorationDefines::AbilityButtonHelp) )
supportedButtons.append('H');
if (m_factory->supports(KDecorationDefines::AbilityButtonMinimize) )
supportedButtons.append('I');
if (m_factory->supports(KDecorationDefines::AbilityButtonMaximize) )
supportedButtons.append('A');
if (m_factory->supports(KDecorationDefines::AbilityButtonClose) )
supportedButtons.append('X');
if (m_factory->supports(KDecorationDefines::AbilityButtonAboveOthers) )
supportedButtons.append('F');
if (m_factory->supports(KDecorationDefines::AbilityButtonBelowOthers) )
supportedButtons.append('B');
if (m_factory->supports(KDecorationDefines::AbilityButtonShade) )
supportedButtons.append('L');
if (m_factory->supports(KDecorationDefines::AbilityButtonResize) )
supportedButtons.append('R');
m_supportedButtons = supportedButtons;
} else {
// enable only buttons available before AbilityButton* introduction
m_supportedButtons = "MSHIAX_";
}
// update the button lists...
// 1. set status on the source items...
for (int i = 0; i < m_buttonSource->count(); i++) {
ButtonSourceItem *buttonItem = dynamic_cast<ButtonSourceItem*>(m_buttonSource->item(i));
if (buttonItem) {
Button b = buttonItem->button();
b.supported = m_supportedButtons.contains(b.type);
buttonItem->setButton(b);
}
}
// 2. rebuild the drop site items...
setButtonsLeft(buttonsLeft() );
setButtonsRight(buttonsRight() );
}
Button ButtonPositionWidget::getButton(QChar type, bool& success) {
success = true;
@ -857,6 +806,8 @@ void ButtonPositionWidget::setButtonsRight(const QString &buttons)
m_dropSite->update();
}
} // namespace KWin
#include "buttons.moc"
// vim: ts=4
// kate: space-indent off; tab-width 4;

View file

@ -38,6 +38,9 @@
class KDecorationFactory;
namespace KWin
{
/**
* This class holds the button data.
*/
@ -196,11 +199,6 @@ class ButtonPositionWidget : public QWidget
explicit ButtonPositionWidget(QWidget *parent = 0);
~ButtonPositionWidget();
/**
* set the factory, so the class e.g. knows which buttons are supported by the client
*/
void setDecorationFactory(KDecorationFactory *factory);
QString buttonsLeft() const;
QString buttonsRight() const;
void setButtonsLeft(const QString &buttons);
@ -220,6 +218,7 @@ class ButtonPositionWidget : public QWidget
QString m_supportedButtons;
};
} // namespace KWin
#endif
// vim: ts=4

View file

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>KWinDecorationButtonsConfigForm</class>
<widget class="QWidget" name="KWinDecorationButtonsConfigForm">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QCheckBox" name="showToolTipsCheckBox">
<property name="whatsThis">
<string>Enabling this checkbox will show window button tooltips. If this checkbox is off, no window button tooltips will be shown.</string>
</property>
<property name="text">
<string>&amp;Show window button tooltips</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="useCustomButtonPositionsCheckBox">
<property name="whatsThis">
<string>The appropriate settings can be found in the &quot;Buttons&quot; Tab; please note that this option is not available on all styles yet.</string>
</property>
<property name="text">
<string>Use custom titlebar button &amp;positions</string>
</property>
</widget>
</item>
<item>
<widget class="KWin::ButtonPositionWidget" name="buttonPositionWidget" native="true"/>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KWin::ButtonPositionWidget</class>
<extends>QWidget</extends>
<header>buttons.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,113 @@
/********************************************************************
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 "buttonsconfigdialog.h"
#include <QVBoxLayout>
#include <KLocale>
#include <kdecoration.h>
namespace KWin
{
KWinDecorationButtonsConfigForm::KWinDecorationButtonsConfigForm( QWidget* parent )
: QWidget( parent )
{
setupUi( this );
}
KWinDecorationButtonsConfigDialog::KWinDecorationButtonsConfigDialog( bool customPositions, bool showTooltips, QString buttonsLeft, QString buttonsRight, QWidget* parent, Qt::WFlags flags )
: KDialog( parent, flags )
, m_customPositions( customPositions )
, m_showTooltip( showTooltips )
, m_buttonsLeft( buttonsLeft )
, m_buttonsRight( buttonsRight )
{
m_ui = new KWinDecorationButtonsConfigForm( this );
setWindowTitle( i18n("Buttons") );
setButtons( KDialog::Ok | KDialog::Cancel | KDialog::Default | KDialog::Reset );
enableButton( KDialog::Reset, false );
QVBoxLayout* layout = new QVBoxLayout;
layout->addWidget( m_ui );
QWidget* main = new QWidget( this );
main->setLayout( layout );
setMainWidget( main );
connect( m_ui->buttonPositionWidget, SIGNAL(changed()), this, SLOT(changed()));
connect( m_ui->showToolTipsCheckBox, SIGNAL(stateChanged(int)), this, SLOT(changed()));
connect( m_ui->useCustomButtonPositionsCheckBox, SIGNAL(stateChanged(int)), this, SLOT(changed()));
connect( this, SIGNAL(defaultClicked()), this, SLOT(slotDefaultClicked()));
connect( this, SIGNAL(resetClicked()), this, SLOT(slotResetClicked()));
slotResetClicked();
}
KWinDecorationButtonsConfigDialog::~KWinDecorationButtonsConfigDialog()
{
}
bool KWinDecorationButtonsConfigDialog::customPositions() const
{
return m_ui->useCustomButtonPositionsCheckBox->isChecked();
}
bool KWinDecorationButtonsConfigDialog::showTooltips() const
{
return m_ui->showToolTipsCheckBox->isChecked();
}
QString KWinDecorationButtonsConfigDialog::buttonsLeft() const
{
return m_ui->buttonPositionWidget->buttonsLeft();
}
QString KWinDecorationButtonsConfigDialog::buttonsRight() const
{
return m_ui->buttonPositionWidget->buttonsRight();
}
void KWinDecorationButtonsConfigDialog::changed()
{
enableButton( KDialog::Reset, true );
}
void KWinDecorationButtonsConfigDialog::slotDefaultClicked()
{
m_ui->useCustomButtonPositionsCheckBox->setChecked( false );
m_ui->showToolTipsCheckBox->setChecked( true );
m_ui->buttonPositionWidget->setButtonsLeft( KDecorationOptions::defaultTitleButtonsLeft() );
m_ui->buttonPositionWidget->setButtonsRight( KDecorationOptions::defaultTitleButtonsRight() );
changed();
}
void KWinDecorationButtonsConfigDialog::slotResetClicked()
{
m_ui->useCustomButtonPositionsCheckBox->setChecked( m_customPositions );
m_ui->showToolTipsCheckBox->setChecked( m_showTooltip );
m_ui->buttonPositionWidget->setButtonsLeft( m_buttonsLeft );
m_ui->buttonPositionWidget->setButtonsRight( m_buttonsRight );
changed();
enableButton( KDialog::Reset, false );
}
} // namespace KWin
#include "buttonsconfigdialog.moc"

View file

@ -0,0 +1,66 @@
/********************************************************************
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/>.
*********************************************************************/
#ifndef KWINDECORATIONBUTTONSCONFIGDIALOG_H
#define KWINDECORATIONBUTTONSCONFIGDIALOG_H
#include <QWidget>
#include <KDialog>
#include "ui_buttons.h"
namespace KWin
{
class KWinDecorationButtonsConfigForm : public QWidget, public Ui::KWinDecorationButtonsConfigForm
{
Q_OBJECT
public:
explicit KWinDecorationButtonsConfigForm( QWidget* parent );
};
class KWinDecorationButtonsConfigDialog : public KDialog
{
Q_OBJECT
public:
KWinDecorationButtonsConfigDialog( bool customPositions, bool showTooltips, QString buttonsLeft, QString buttonsRight, QWidget* parent = 0, Qt::WFlags flags = 0 );
~KWinDecorationButtonsConfigDialog();
bool customPositions() const;
bool showTooltips() const;
QString buttonsLeft() const;
QString buttonsRight() const;
private slots:
void changed();
void slotDefaultClicked();
void slotResetClicked();
private:
KWinDecorationButtonsConfigForm* m_ui;
bool m_customPositions;
bool m_showTooltip;
QString m_buttonsLeft;
QString m_buttonsRight;
};
} // namespace KWin
#endif // KWINDECORATIONCONFIGBUTTONSDIALOG_H

View file

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>KWinDecorationConfigForm</class>
<widget class="QWidget" name="KWinDecorationConfigForm">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>188</width>
<height>38</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="borderLabel">
<property name="text">
<string>B&amp;order size:</string>
</property>
<property name="buddy">
<cstring>bordersCombo</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="KComboBox" name="bordersCombo">
<property name="whatsThis">
<string>Use this combobox to change the border size of the decoration.</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KComboBox</class>
<extends>QComboBox</extends>
<header>kcombobox.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,167 @@
/********************************************************************
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 "configdialog.h"
#include <QDBusConnection>
#include <QDBusMessage>
#include <KLibLoader>
#include <KVBox>
namespace KWin
{
static const char* const border_names[ KDecorationDefines::BordersCount ] =
{
I18N_NOOP( "Tiny" ),
I18N_NOOP( "Normal" ),
I18N_NOOP( "Large" ),
I18N_NOOP( "Very Large" ),
I18N_NOOP( "Huge" ),
I18N_NOOP( "Very Huge" ),
I18N_NOOP( "Oversized" )
};
KWinDecorationConfigForm::KWinDecorationConfigForm( QWidget* parent )
: QWidget( parent )
{
setupUi( this );
}
KWinDecorationConfigDialog::KWinDecorationConfigDialog( QString deco, const QList<QVariant>& borderSizes,
KDecorationDefines::BorderSize size,
QWidget* parent, Qt::WFlags flags )
: KDialog( parent, flags )
, m_borderSizes( borderSizes )
, m_kwinConfig( KSharedConfig::openConfig( "kwinrc" ) )
, m_pluginObject( 0 )
, m_pluginConfigWidget( 0 )
{
m_ui = new KWinDecorationConfigForm( this );
setWindowTitle( i18n("Decoration Options") );
setButtons( KDialog::Ok | KDialog::Cancel | KDialog::Default | KDialog::Reset );
enableButton( KDialog::Reset, false );
QVBoxLayout* layout = new QVBoxLayout;
layout->addWidget( m_ui );
// Use klibloader for library manipulation
KLibLoader* loader = KLibLoader::self();
KLibrary* library = loader->library( styleToConfigLib( deco ) );
if (library != NULL)
{
KLibrary::void_function_ptr alloc_ptr = library->resolveFunction("allocate_config");
if (alloc_ptr != NULL)
{
allocatePlugin = (QObject* (*)(KConfigGroup& conf, QWidget* parent))alloc_ptr;
KConfigGroup config( m_kwinConfig, "Style" );
m_pluginConfigWidget = new KVBox( this );
m_pluginObject = (QObject*)(allocatePlugin( config, m_pluginConfigWidget ));
// connect required signals and slots together...
connect( this, SIGNAL(accepted()), this, SLOT(slotAccepted()) );
connect( m_pluginObject, SIGNAL(changed()), this, SLOT(slotSelectionChanged()) );
connect( this, SIGNAL(pluginSave(KConfigGroup&)), m_pluginObject, SLOT(save(KConfigGroup &)) );
connect( this, SIGNAL(defaultClicked()), m_pluginObject, SLOT(defaults()) );
connect( this, SIGNAL(defaultClicked()), SLOT(slotDefault()) );
}
}
if( m_pluginConfigWidget )
{
layout->addWidget( m_pluginConfigWidget );
}
if( borderSizes.count() >= 2 )
{
foreach( const QVariant& borderSize, borderSizes )
{
KDecorationDefines::BorderSize currentSize =
static_cast<KDecorationDefines::BorderSize>( borderSize.toInt() );
m_ui->bordersCombo->addItem(i18n(border_names[currentSize]), borderSizeToIndex(currentSize, borderSizes) );
}
m_ui->bordersCombo->setCurrentIndex( borderSizeToIndex( size, borderSizes ) );
}
else
{
m_ui->bordersCombo->hide();
m_ui->borderLabel->hide();
}
QWidget* main = new QWidget( this );
main->setLayout( layout );
setMainWidget( main );
}
KWinDecorationConfigDialog::~KWinDecorationConfigDialog()
{
delete m_pluginObject;
}
KDecorationDefines::BorderSize KWinDecorationConfigDialog::borderSize() const
{
if( m_borderSizes.count() >= 2 )
return (KDecorationDefines::BorderSize)m_borderSizes.at( m_ui->bordersCombo->currentIndex() ).toInt();
return KDecorationDefines::BorderNormal;
}
int KWinDecorationConfigDialog::borderSizeToIndex( KDecorationDefines::BorderSize size, const QList< QVariant >& sizes )
{
int pos = 0;
for( QList< QVariant >::ConstIterator it = sizes.constBegin();
it != sizes.constEnd();
++it, ++pos )
if( size <= (*it).toInt() )
break;
return pos;
}
void KWinDecorationConfigDialog::slotAccepted()
{
KConfigGroup config( m_kwinConfig, "Style" );
emit pluginSave( config );
config.sync();
// Send signal to all kwin instances
QDBusMessage message =
QDBusMessage::createSignal("/KWin", "org.kde.KWin", "reloadConfig");
QDBusConnection::sessionBus().send(message);
}
void KWinDecorationConfigDialog::slotSelectionChanged()
{
enableButton( KDialog::Reset, true );
}
QString KWinDecorationConfigDialog::styleToConfigLib( const QString& styleLib ) const
{
if( styleLib.startsWith( "kwin3_" ))
return "kwin_" + styleLib.mid( 6 ) + "_config";
else
return styleLib + "_config";
}
void KWinDecorationConfigDialog::slotDefault()
{
if( m_borderSizes.count() >= 2 )
m_ui->bordersCombo->setCurrentIndex( borderSizeToIndex( BorderNormal, m_borderSizes ) );
}
} // namespace KWin
#include "configdialog.moc"

View file

@ -0,0 +1,73 @@
/********************************************************************
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/>.
*********************************************************************/
#ifndef KWINDECORATIONCONFIGDIALOG_H
#define KWINDECORATIONCONFIGDIALOG_H
#include <QWidget>
#include <kdialog.h>
#include <kdecoration.h>
#include "ui_config.h"
namespace KWin
{
class KWinDecorationConfigForm : public QWidget, public Ui::KWinDecorationConfigForm
{
Q_OBJECT
public:
explicit KWinDecorationConfigForm( QWidget* parent );
};
class KWinDecorationConfigDialog : public KDialog, public KDecorationDefines
{
Q_OBJECT
public:
KWinDecorationConfigDialog( QString decoLib, const QList<QVariant>& borderSizes,
KDecorationDefines::BorderSize size, QWidget* parent = 0,
Qt::WFlags flags = 0 );
~KWinDecorationConfigDialog();
KDecorationDefines::BorderSize borderSize() const;
signals:
void pluginSave( KConfigGroup& group );
private slots:
void slotSelectionChanged();
void slotAccepted();
void slotDefault();
private:
int borderSizeToIndex( KDecorationDefines::BorderSize size, const QList<QVariant>& sizes );
QString styleToConfigLib( const QString& styleLib ) const;
private:
KWinDecorationConfigForm* m_ui;
QList<QVariant> m_borderSizes;
KSharedConfigPtr m_kwinConfig;
QObject* (*allocatePlugin)( KConfigGroup& conf, QWidget* parent );
QObject* m_pluginObject;
QWidget* m_pluginConfigWidget;
};
} // namespace KWin
#endif // KWINDECORATIONCONFIGDIALOG_H

View file

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>KWinDecorationForm</class>
<widget class="QWidget" name="KWinDecorationForm">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>681</width>
<height>515</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="KLineEdit" name="searchEdit">
<property name="clickMessage">
<string>Search</string>
</property>
<property name="showClearButton" stdset="0">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QListView" name="decorationList">
<property name="whatsThis">
<string>Select the window decoration. This is the look and feel of both the window borders and the window handle.</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="KPushButton" name="configureButtonsButton">
<property name="text">
<string>Configure Buttons ...</string>
</property>
</widget>
</item>
<item>
<widget class="KPushButton" name="ghnsButton">
<property name="text">
<string>Get New Decorations ...</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KPushButton</class>
<extends>QPushButton</extends>
<header>kpushbutton.h</header>
</customwidget>
<customwidget>
<class>KLineEdit</class>
<extends>QLineEdit</extends>
<header>klineedit.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,176 @@
/********************************************************************
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 "decorationdelegate.h"
#include "decorationmodel.h"
#include "configdialog.h"
#include <QPainter>
#include <QSortFilterProxyModel>
#include <QApplication>
#include <KAboutData>
#include <KAboutApplicationDialog>
#include <KPushButton>
namespace KWin
{
const int margin = 5;
DecorationDelegate::DecorationDelegate( QAbstractItemView* itemView, QObject* parent )
: KWidgetItemDelegate( itemView, parent )
, m_button( new KPushButton )
, m_itemView( itemView )
{
m_button->setIcon( KIcon( "configure" ) );
}
DecorationDelegate::~DecorationDelegate()
{
delete m_button;
}
void DecorationDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
// highlight selected item
QApplication::style()->drawControl( QStyle::CE_ItemViewItem, &option, painter );
QPixmap pixmap = index.model()->data( index, DecorationModel::PixmapRole ).value<QPixmap>();
const QSize previewArea = option.rect.size() -
QSize( 3 * margin + m_button->sizeHint().width(), 2 * margin);
if( pixmap.isNull() || pixmap.size() != previewArea )
{
emit regeneratePreview( static_cast< const QSortFilterProxyModel* >( index.model() )->mapToSource( index ),
previewArea );
}
else
painter->drawPixmap( option.rect.topLeft() + QPoint( margin, margin ), pixmap );
}
QSize DecorationDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
Q_UNUSED( option )
Q_UNUSED( index )
const QSize pixmapSize = QSize( 400, 150 );
const QSize buttonSize = m_button->sizeHint();
const int width = margin * 3 + pixmapSize.width() + buttonSize.width();
const int height = qMax( margin * 2 + pixmapSize.height(), margin * 2 + buttonSize.height() * 2 );
return QSize( width, height );
}
QList< QWidget* > DecorationDelegate::createItemWidgets() const
{
QList<QWidget*> widgets;
KPushButton *info = new KPushButton;
info->setIcon( KIcon( "dialog-information" ) );
setBlockedEventTypes( info, QList<QEvent::Type>() << QEvent::MouseButtonPress
<< QEvent::MouseButtonRelease << QEvent::MouseButtonDblClick
<< QEvent::KeyPress << QEvent::KeyRelease);
KPushButton *configure = new KPushButton;
configure->setIcon( KIcon( "configure" ) );
setBlockedEventTypes( configure, QList<QEvent::Type>() << QEvent::MouseButtonPress
<< QEvent::MouseButtonRelease << QEvent::MouseButtonDblClick
<< QEvent::KeyPress << QEvent::KeyRelease);
connect( configure, SIGNAL(clicked(bool)), SLOT(slotConfigure()) );
connect( info, SIGNAL(clicked(bool)), SLOT(slotInfo()) );
widgets << info << configure;
return widgets;
}
void DecorationDelegate::updateItemWidgets(const QList< QWidget* > widgets, const QStyleOptionViewItem& option, const QPersistentModelIndex& index) const
{
KPushButton *button = static_cast<KPushButton*>( widgets[0] );
button->resize( button->sizeHint() );
button->move( option.rect.left() + option.rect.width() - margin - button->width(),
option.rect.height() / 2 - button->sizeHint().height() );
if( !index.isValid() )
button->setVisible( false );
if( widgets.size() > 1 )
{
button = static_cast<KPushButton*>( widgets[1] );
button->resize( button->sizeHint() );
button->move( option.rect.left() + option.rect.width() - margin - button->width(),
option.rect.height() / 2 );
if( !index.isValid() )
button->setVisible( false );
}
}
void DecorationDelegate::slotConfigure()
{
if (!focusedIndex().isValid())
return;
const QModelIndex index = focusedIndex();
QString name = focusedIndex().model()->data( index , DecorationModel::LibraryNameRole ).toString();
QList< QVariant > borderSizes = focusedIndex().model()->data( index , DecorationModel::BorderSizesRole ).toList();
const KDecorationDefines::BorderSize size =
static_cast<KDecorationDefines::BorderSize>( itemView()->model()->data( index, DecorationModel::BorderSizeRole ).toInt() );
QPointer< KWinDecorationConfigDialog > configDialog =
new KWinDecorationConfigDialog( name, borderSizes, size, m_itemView );
if( configDialog->exec() == KDialog::Accepted )
{
static_cast< DecorationModel* >( itemView()->model() )->setBorderSize( index, configDialog->borderSize() );
static_cast< DecorationModel* >( itemView()->model() )->regeneratePreview( focusedIndex() );
}
delete configDialog;
}
void DecorationDelegate::slotInfo()
{
if (!focusedIndex().isValid())
return;
const QModelIndex index = focusedIndex();
const QString name = index.model()->data( index, Qt::DisplayRole ).toString();
const QString comment = index.model()->data( index, DecorationModel::PackageDescriptionRole ).toString();
const QString author = index.model()->data( index, DecorationModel::PackageAuthorRole ).toString();
const QString email = index.model()->data( index, DecorationModel::PackageEmailRole ).toString();
const QString website = index.model()->data( index, DecorationModel::PackageWebsiteRole ).toString();
const QString version = index.model()->data( index, DecorationModel::PackageVersionRole ).toString();
const QString license = index.model()->data( index, DecorationModel::PackageLicenseRole ).toString();
KAboutData aboutData(name.toUtf8(), name.toUtf8(), ki18n(name.toUtf8()), version.toUtf8(), ki18n(comment.toUtf8()), KAboutLicense::byKeyword(license).key(), ki18n(QByteArray()), ki18n(QByteArray()), website.toLatin1());
aboutData.setProgramIconName("preferences-system-windows-action");
const QStringList authors = author.split(',');
const QStringList emails = email.split(',');
int i = 0;
if( authors.count() == emails.count() )
{
foreach( const QString &author, authors )
{
if( !author.isEmpty() )
{
aboutData.addAuthor(ki18n(author.toUtf8()), ki18n(QByteArray()), emails[i].toUtf8(), 0);
}
i++;
}
}
QPointer<KAboutApplicationDialog> about = new KAboutApplicationDialog( &aboutData, itemView() );
about->exec();
delete about;
}
} // namespace KWin

View file

@ -0,0 +1,55 @@
/********************************************************************
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/>.
*********************************************************************/
#ifndef PREVIEWDELEGATE_H
#define PREVIEWDELEGATE_H
#include <KWidgetItemDelegate>
class KPushButton;
namespace KWin
{
class DecorationDelegate : public KWidgetItemDelegate
{
Q_OBJECT
public:
DecorationDelegate( QAbstractItemView* itemView, QObject* parent = 0 );
~DecorationDelegate();
virtual void paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
virtual QSize sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const;
virtual QList< QWidget* > createItemWidgets() const;
virtual void updateItemWidgets(const QList< QWidget* > widgets, const QStyleOptionViewItem& option, const QPersistentModelIndex& index) const;
signals:
void regeneratePreview( const QModelIndex& index, const QSize& size ) const;
private slots:
void slotConfigure();
void slotInfo();
private:
KPushButton* m_button;
QAbstractItemView* m_itemView;
};
} // namespace KWin
#endif // PREVIEWDELEGATE_H

View file

@ -0,0 +1,313 @@
/********************************************************************
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 "decorationmodel.h"
#include "preview.h"
#include "auroraepreview.h"
// kwin
#include <kdecorationfactory.h>
// Qt
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
// KDE
#include <KConfigGroup>
#include <KDesktopFile>
#include <KStandardDirs>
namespace KWin
{
DecorationModel::DecorationModel( KSharedConfigPtr config, QObject* parent )
: QAbstractListModel( parent )
, m_plugins( new KDecorationPreviewPlugins( config ) )
, m_preview( new KDecorationPreview() )
, m_customButtons( false )
, m_leftButtons( QString() )
, m_rightButtons( QString() )
{
findDecorations();
}
DecorationModel::~DecorationModel()
{
delete m_preview;
delete m_plugins;
}
void DecorationModel::reload()
{
m_decorations.clear();
findDecorations();
}
// Find all theme desktop files in all 'data' dirs owned by kwin.
// And insert these into a DecorationInfo structure
void DecorationModel::findDecorations()
{
beginResetModel();
const QStringList dirList = KGlobal::dirs()->findDirs("data", "kwin");
foreach( const QString &dir, dirList )
{
QDir d( dir );
if( d.exists() )
{
foreach( const QFileInfo& fi, d.entryInfoList() )
{
const QString filename( fi.absoluteFilePath() );
if( KDesktopFile::isDesktopFile(filename) )
{
const KDesktopFile desktopFile( filename );
const QString libName = desktopFile.desktopGroup().readEntry( "X-KDE-Library" );
if( !libName.isEmpty() && libName.startsWith( "kwin3_" ) )
{
if( libName == "kwin3_aurorae" )
{
// read the Aurorae themes
findAuroraeThemes();
continue;
}
DecorationModelData data;
data.name = desktopFile.readName();
data.libraryName = libName;
data.type = DecorationModelData::NativeDecoration;
data.aurorae = NULL;
data.borderSize = KDecorationDefines::BorderNormal;
metaData( data, desktopFile );
m_decorations.append(data);
}
}
}
}
}
qSort( m_decorations.begin(), m_decorations.end(), DecorationModelData::less );
endResetModel();
}
void DecorationModel::findAuroraeThemes()
{
// get all desktop themes
QStringList themes = KGlobal::dirs()->findAllResources("data",
"aurorae/themes/*/metadata.desktop",
KStandardDirs::NoDuplicates);
foreach(const QString &theme, themes)
{
int themeSepIndex = theme.lastIndexOf( '/', -1 );
QString themeRoot = theme.left( themeSepIndex );
int themeNameSepIndex = themeRoot.lastIndexOf( '/', -1 );
QString packageName = themeRoot.right( themeRoot.length() - themeNameSepIndex - 1 );
KDesktopFile df( theme );
QString name = df.readName();
if( name.isEmpty() )
{
name = packageName;
}
DecorationModelData data;
data.name = name;
data.libraryName = "kwin3_aurorae";
data.type = DecorationModelData::AuroraeDecoration;
data.auroraeName = packageName;
data.aurorae = new AuroraePreview( name, packageName, themeRoot, this );
data.borderSize = KDecorationDefines::BorderNormal;
metaData( data, df );
m_decorations.append(data);
}
}
void DecorationModel::metaData( DecorationModelData& data, const KDesktopFile& df )
{
data.comment = df.readComment();
data.author = df.desktopGroup().readEntry( "X-KDE-PluginInfo-Author", QString() );
data.email = df.desktopGroup().readEntry( "X-KDE-PluginInfo-Email", QString() );
data.version = df.desktopGroup().readEntry( "X-KDE-PluginInfo-Version", QString() );
data.license = df.desktopGroup().readEntry( "X-KDE-PluginInfo-License", QString() );
data.website = df.desktopGroup().readEntry( "X-KDE-PluginInfo-Website", QString() );
}
int DecorationModel::rowCount( const QModelIndex& parent ) const
{
Q_UNUSED( parent )
return m_decorations.count();
}
QVariant DecorationModel::data( const QModelIndex& index, int role ) const
{
if( !index.isValid() )
return QVariant();
switch( role )
{
case Qt::DisplayRole:
case NameRole:
return m_decorations[ index.row() ].name;
case LibraryNameRole:
return m_decorations[ index.row() ].libraryName;
case PixmapRole:
return m_decorations[ index.row() ].preview;
case TypeRole:
return m_decorations[ index.row() ].type;
case AuroraeNameRole:
return m_decorations[ index.row() ].auroraeName;
case PackageDescriptionRole:
return m_decorations[ index.row() ].comment;
case PackageAuthorRole:
return m_decorations[ index.row() ].author;
case PackageEmailRole:
return m_decorations[ index.row() ].email;
case PackageWebsiteRole:
return m_decorations[ index.row() ].website;
case PackageVersionRole:
return m_decorations[ index.row() ].version;
case PackageLicenseRole:
return m_decorations[ index.row() ].license;
case BorderSizeRole:
return static_cast< int >( m_decorations[ index.row() ].borderSize );
case BorderSizesRole:
{
QList< QVariant > sizes;
if( m_plugins->loadPlugin( m_decorations[ index.row() ].libraryName ) &&
m_plugins->factory() != NULL )
{
foreach( KDecorationDefines::BorderSize size, m_plugins->factory()->borderSizes() )
sizes << int(size) ;
}
return sizes;
}
default:
return QVariant();
}
}
void DecorationModel::changeButtons( bool custom, const QString& left, const QString& right )
{
bool regenerate = (custom != m_customButtons);
if( !regenerate && custom )
regenerate = (left != m_leftButtons) || (right != m_rightButtons);
m_customButtons = custom;
m_leftButtons = left;
m_rightButtons = right;
if( regenerate )
regeneratePreviews();
}
void DecorationModel::setButtons(bool custom, const QString& left, const QString& right)
{
m_customButtons = custom;
m_leftButtons = left;
m_rightButtons = right;
}
void DecorationModel::regeneratePreviews()
{
QList<DecorationModelData>::iterator it = m_decorations.begin();
for( int i=0; i<m_decorations.count(); i++ )
{
regeneratePreview( index( i ), m_decorations.at(i).preview.size() );
}
}
void DecorationModel::regeneratePreview( const QModelIndex& index, const QSize& size )
{
DecorationModelData& data = m_decorations[ index.row() ];
switch( data.type )
{
case DecorationModelData::NativeDecoration:
m_plugins->reset( KDecoration::SettingDecoration );
if ( m_plugins->loadPlugin( data.libraryName ) &&
m_preview->recreateDecoration( m_plugins ) )
m_preview->enablePreview();
else
m_preview->disablePreview();
m_plugins->destroyPreviousPlugin();
m_preview->resize( size );
m_preview->setTempButtons( m_plugins, m_customButtons, m_leftButtons, m_rightButtons );
m_preview->setTempBorderSize( m_plugins, data.borderSize );
data.preview = m_preview->preview();
break;
case DecorationModelData::AuroraeDecoration:
data.preview = data.aurorae->preview( size, m_customButtons, m_leftButtons, m_rightButtons );
break;
default:
// nothing
break;
}
emit dataChanged( index, index );
}
void DecorationModel::regeneratePreview( const QModelIndex& index )
{
regeneratePreview( index, m_decorations.at( index.row() ).preview.size() );
}
QModelIndex DecorationModel::indexOfLibrary( const QString& libraryName ) const
{
for( int i=0; i<m_decorations.count(); i++ )
{
if( m_decorations.at( i ).libraryName.compare( libraryName ) == 0 )
return index( i );
}
return QModelIndex();
}
QModelIndex DecorationModel::indexOfName( const QString& decoName ) const
{
for( int i=0; i<m_decorations.count(); i++ )
{
if( m_decorations.at( i ).name.compare( decoName ) == 0 )
return index( i );
}
return QModelIndex();
}
QModelIndex DecorationModel::indexOfAuroraeName( const QString& auroraeName ) const
{
for( int i=0; i<m_decorations.count(); i++ )
{
const DecorationModelData& data = m_decorations.at( i );
if( data.type == DecorationModelData::AuroraeDecoration &&
data.auroraeName.compare( auroraeName ) == 0 )
return index( i );
}
return QModelIndex();
}
void DecorationModel::setBorderSize( const QModelIndex& index, KDecorationDefines::BorderSize size )
{
if( !index.isValid() )
return;
m_decorations[ index.row() ].borderSize = size;
}
void DecorationModel::resetAuroraeBorderSizes( KDecorationDefines::BorderSize size )
{
QList<DecorationModelData>::iterator it = m_decorations.begin();
while( it != m_decorations.end() )
{
if( (*it).type == DecorationModelData::AuroraeDecoration )
(*it).borderSize = size;
++it;
}
}
} // namespace KWin

View file

@ -0,0 +1,127 @@
/********************************************************************
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/>.
*********************************************************************/
#ifndef PREVIEWMODEL_H
#define PREVIEWMODEL_H
#include <QAbstractListModel>
#include <QPixmap>
#include <KConfig>
#include <kdecoration.h>
class KDesktopFile;
class KDecorationPlugins;
class KDecorationPreview;
namespace KWin
{
class AuroraePreview;
class DecorationModelData
{
public:
enum DecorationType
{
NativeDecoration = 0,
AuroraeDecoration = 1
};
QString name;
QString libraryName;
QPixmap preview;
DecorationType type;
QString comment;
QString author;
QString email;
QString website;
QString version;
QString license;
QString auroraeName;
AuroraePreview *aurorae;
KDecorationDefines::BorderSize borderSize;
static bool less( const DecorationModelData& a, const DecorationModelData& b )
{ return a.name < b.name; }
};
class DecorationModel : public QAbstractListModel
{
Q_OBJECT
public:
enum
{
NameRole = Qt::UserRole,
LibraryNameRole = Qt::UserRole + 1,
PixmapRole = Qt::UserRole + 2,
TypeRole = Qt::UserRole + 3,
AuroraeNameRole = Qt::UserRole + 4,
PackageDescriptionRole = Qt::UserRole + 5,
PackageAuthorRole = Qt::UserRole + 6,
PackageEmailRole = Qt::UserRole + 7,
PackageWebsiteRole = Qt::UserRole + 8,
PackageVersionRole = Qt::UserRole + 9,
PackageLicenseRole = Qt::UserRole + 10,
BorderSizeRole = Qt::UserRole + 11,
BorderSizesRole = Qt::UserRole + 12
};
DecorationModel( KSharedConfigPtr config, QObject* parent = 0 );
~DecorationModel();
virtual QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const;
virtual int rowCount( const QModelIndex& parent = QModelIndex() ) const;
void reload();
void regeneratePreview( const QModelIndex& index );
/**
* Changes the button state and regenerates the preview.
*/
void changeButtons( bool custom, const QString& left, const QString& right );
/**
* Changes the button state without regenerating the preview.
*/
void setButtons( bool custom, const QString& left, const QString& right );
void setBorderSize( const QModelIndex& index, KDecorationDefines::BorderSize size );
void resetAuroraeBorderSizes( KDecorationDefines::BorderSize size );
QModelIndex indexOfLibrary( const QString& libraryName ) const;
QModelIndex indexOfName( const QString& decoName ) const;
QModelIndex indexOfAuroraeName( const QString& auroraeName ) const;
public slots:
void regeneratePreview( const QModelIndex& index, const QSize& size );
private:
void findDecorations();
void findAuroraeThemes();
void regeneratePreviews();
void metaData( DecorationModelData& data, const KDesktopFile& df );
QList<DecorationModelData> m_decorations;
KDecorationPlugins* m_plugins;
KDecorationPreview* m_preview;
bool m_customButtons;
QString m_leftButtons;
QString m_rightButtons;
};
} // namespace KWin
#endif // PREVIEWMODEL_H

View file

@ -4,6 +4,7 @@
Copyright (c) 2001
Karol Szwed <gallium@kde.org>
http://gallium.n3.net/
Copyright 2009, 2010 Martin Gräßlin <kde@martin-graesslin.com>
Supports new kwin configuration plugins, and titlebar button position
modification via dnd interface.
@ -26,167 +27,72 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
// own
#include "kwindecoration.h"
#include "preview.h"
#include <assert.h>
#include <QDir>
#include <QFileInfo>
#include <QLayout>
#include <QGroupBox>
#include <QGridLayout>
#include <QCheckBox>
#include <KComboBox>
#include <KTabWidget>
#include <QLabel>
#include <QFile>
#include <QSlider>
#include "buttonsconfigdialog.h"
#include "decorationdelegate.h"
#include "decorationmodel.h"
// Qt
#include <QtDBus/QtDBus>
#include <kapplication.h>
#include <kcombobox.h>
#include <kdebug.h>
#include <kdesktopfile.h>
#include <kstandarddirs.h>
#include <kglobal.h>
#include <klocale.h>
#include <kdialog.h>
#include <kaboutdata.h>
#include <kdecoration_plugins_p.h>
#include <kdecorationfactory.h>
#include <kvbox.h>
#include <QtGui/QSortFilterProxyModel>
// KDE
#include <KAboutData>
#include <KDialog>
#include <KLocale>
#include <KNS3/DownloadDialog>
#include <KPluginFactory>
#include <KPluginLoader>
// KCModule plugin interface
// =========================
K_PLUGIN_FACTORY(KWinDecoFactory,
registerPlugin<KWinDecorationModule>();
registerPlugin<KWin::KWinDecorationModule>();
)
K_EXPORT_PLUGIN(KWinDecoFactory("kcmkwindecoration"))
KWinDecorationModule::KWinDecorationModule(QWidget* parent, const QVariantList &)
: KCModule(KWinDecoFactory::componentData(), parent),
kwinConfig(KSharedConfig::openConfig("kwinrc")),
pluginObject(0),
library(NULL)
namespace KWin
{
KWinDecorationForm::KWinDecorationForm( QWidget* parent )
: QWidget( parent )
{
setupUi( this );
}
KWinDecorationModule::KWinDecorationModule(QWidget* parent, const QVariantList &)
: KCModule(KWinDecoFactory::componentData(), parent)
, kwinConfig(KSharedConfig::openConfig("kwinrc"))
, m_showTooltips( false )
, m_customPositions( false )
, m_leftButtons( QString() )
, m_rightButtons( QString() )
, m_configLoaded( false )
{
m_ui = new KWinDecorationForm( this );
DecorationDelegate* delegate = new DecorationDelegate( m_ui->decorationList, this );
m_ui->decorationList->setItemDelegate( delegate );
m_ui->configureButtonsButton->setIcon( KIcon( "configure" ) );
m_ui->ghnsButton->setIcon( KIcon( "get-hot-new-stuff" ) );
QVBoxLayout* layout = new QVBoxLayout( this );
layout->addWidget( m_ui );
KConfigGroup style( kwinConfig, "Style");
plugins = new KDecorationPreviewPlugins(kwinConfig);
QVBoxLayout* layout = new QVBoxLayout(this);
// Set up the decoration lists and other UI settings
m_model = new DecorationModel( kwinConfig, this );
m_proxyModel = new QSortFilterProxyModel( this );
m_proxyModel->setSourceModel( m_model );
m_proxyModel->setFilterCaseSensitivity( Qt::CaseInsensitive );
m_ui->decorationList->setModel( m_proxyModel );
// Save this for later...
// cbUseMiniWindows = new QCheckBox( i18n( "Render mini &titlebars for all windows"), checkGroup );
// QWhatsThis::add( cbUseMiniWindows, i18n( "Note that this option is not available on all styles yet" ) );
tabWidget = new KTabWidget( this );
layout->addWidget( tabWidget );
// Page 1 (General Options)
QWidget *pluginPage = new QWidget( tabWidget );
QVBoxLayout* pluginLayout = new QVBoxLayout(pluginPage);
// decoration chooser
decorationList = new KComboBox( pluginPage );
QString whatsThis = i18n("Select the window decoration. This is the look and feel of both "
"the window borders and the window handle.");
decorationList->setWhatsThis( whatsThis);
pluginLayout->addWidget(decorationList);
pluginSettingsGrp = new QGroupBox( i18n("Decoration Options"), pluginPage );
QVBoxLayout *pluginSettingsLayout = new QVBoxLayout();
pluginSettingsGrp->setFlat( true );
pluginSettingsLayout->setMargin( 0 );
pluginSettingsGrp->setLayout( pluginSettingsLayout );
pluginLayout->addWidget( pluginSettingsGrp );
pluginLayout->addStretch();
// Border size chooser
lBorder = new QLabel (i18n("B&order size:"), pluginSettingsGrp);
cBorder = new KComboBox(pluginSettingsGrp);
lBorder->setBuddy(cBorder);
cBorder->setWhatsThis( i18n( "Use this combobox to change the border size of the decoration." ));
lBorder->hide();
cBorder->hide();
QHBoxLayout *borderSizeLayout = new QHBoxLayout();
pluginSettingsLayout->addLayout( borderSizeLayout );
borderSizeLayout->addWidget(lBorder);
borderSizeLayout->addWidget(cBorder);
borderSizeLayout->addStretch();
pluginConfigWidget = new KVBox(pluginSettingsGrp);
pluginSettingsLayout->addWidget( pluginConfigWidget );
// Page 2 (Button Selector)
QWidget* buttonPage = new QWidget( tabWidget );
QVBoxLayout* buttonLayout = new QVBoxLayout(buttonPage);
cbShowToolTips = new QCheckBox(
i18n("&Show window button tooltips"), buttonPage );
cbShowToolTips->setWhatsThis(
i18n( "Enabling this checkbox will show window button tooltips. "
"If this checkbox is off, no window button tooltips will be shown."));
cbUseCustomButtonPositions = new QCheckBox(
i18n("Use custom titlebar button &positions"), buttonPage );
cbUseCustomButtonPositions->setWhatsThis(
i18n( "The appropriate settings can be found in the \"Buttons\" Tab; "
"please note that this option is not available on all styles yet." ) );
buttonLayout->addWidget( cbShowToolTips );
buttonLayout->addWidget( cbUseCustomButtonPositions );
// Add nifty dnd button modification widgets
buttonPositionWidget = new ButtonPositionWidget(buttonPage);
buttonPositionWidget->setObjectName("button_position_widget");
buttonPositionWidget->setDecorationFactory(plugins->factory() );
QHBoxLayout* buttonControlLayout = new QHBoxLayout();
buttonLayout->addLayout( buttonControlLayout );
buttonControlLayout->addSpacing(20);
buttonControlLayout->addWidget(buttonPositionWidget);
// buttonLayout->addStretch();
// preview
QVBoxLayout* previewLayout = new QVBoxLayout();
layout->addLayout( previewLayout );
previewLayout->setMargin( 0 );
preview = new KDecorationPreview( this );
previewLayout->addWidget(preview);
preview->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
tabWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
// Load all installed decorations into memory
// Set up the decoration lists and other UI settings
findDecorations();
createDecorationList();
readConfig( style );
resetPlugin( style );
tabWidget->addTab( pluginPage, i18n("&Window Decoration") );
tabWidget->addTab( buttonPage, i18n("&Buttons") );
connect( buttonPositionWidget, SIGNAL(changed()), this, SLOT(slotButtonsChanged()) ); // update preview etc.
connect( buttonPositionWidget, SIGNAL(changed()), this, SLOT(slotSelectionChanged()) ); // emit changed()...
connect( decorationList, SIGNAL(activated(const QString&)), SLOT(slotSelectionChanged()) );
connect( decorationList, SIGNAL(activated(const QString&)),
SLOT(slotChangeDecoration(const QString&)) );
connect( cbUseCustomButtonPositions, SIGNAL(clicked()), SLOT(slotSelectionChanged()) );
connect(cbUseCustomButtonPositions, SIGNAL(toggled(bool)), buttonPositionWidget, SLOT(setEnabled(bool)));
connect(cbUseCustomButtonPositions, SIGNAL(toggled(bool)), this, SLOT(slotButtonsChanged()) );
connect( cbShowToolTips, SIGNAL(clicked()), SLOT(slotSelectionChanged()) );
connect( cBorder, SIGNAL( activated( int )), SLOT( slotBorderChanged( int )));
// connect( cbUseMiniWindows, SIGNAL(clicked()), SLOT(slotSelectionChanged()) );
connect( m_ui->decorationList, SIGNAL(activated(QModelIndex)), SLOT(slotSelectionChanged()) );
connect( m_ui->configureButtonsButton, SIGNAL(clicked(bool)), this, SLOT(slotConfigureButtons()));
connect( m_ui->ghnsButton, SIGNAL(clicked(bool)), SLOT(slotGHNSClicked()) );
connect( m_ui->searchEdit, SIGNAL(textChanged(QString)), m_proxyModel, SLOT(setFilterFixedString(QString)));
connect( delegate, SIGNAL(regeneratePreview(QModelIndex,QSize)),
m_model, SLOT(regeneratePreview(QModelIndex,QSize)));
KAboutData *about =
new KAboutData(I18N_NOOP("kcmkwindecoration"), 0,
@ -200,284 +106,71 @@ KWinDecorationModule::KWinDecorationModule(QWidget* parent, const QVariantList &
KWinDecorationModule::~KWinDecorationModule()
{
delete preview; // needs to be destroyed before plugins
delete plugins;
}
// Find all theme desktop files in all 'data' dirs owned by kwin.
// And insert these into a DecorationInfo structure
void KWinDecorationModule::findDecorations()
{
const QStringList dirList = KGlobal::dirs()->findDirs("data", "kwin");
QStringList::ConstIterator it;
for (it = dirList.constBegin(); it != dirList.constEnd(); ++it)
{
QDir d(*it);
if (d.exists())
foreach (const QFileInfo& fi, d.entryInfoList())
{
QString filename(fi.absoluteFilePath());
if (KDesktopFile::isDesktopFile(filename))
{
KDesktopFile desktopFile(filename);
QString libName = desktopFile.desktopGroup().readEntry("X-KDE-Library");
if (!libName.isEmpty() && libName.startsWith( "kwin3_" ))
{
DecorationInfo di;
di.name = desktopFile.readName();
di.libraryName = libName;
decorations.append( di );
}
}
}
}
}
// Fills the decorationList with a list of available kwin decorations
void KWinDecorationModule::createDecorationList()
{
QList<DecorationInfo>::ConstIterator it;
// Sync with kwin hardcoded KDE2 style which has no desktop item
QStringList decorationNames;
// decorationNames.append( i18n("KDE 2") );
for (it = decorations.constBegin(); it != decorations.constEnd(); ++it)
{
decorationNames.append((*it).name);
}
decorationNames.sort();
decorationList->addItems(decorationNames);
}
// Reset the decoration plugin to what the user just selected
void KWinDecorationModule::slotChangeDecoration( const QString & text)
{
KConfig _kwinConfig( "kwinrc" );
KConfigGroup kwinConfig(&_kwinConfig, "Style");
// Let the user see config options for the currently selected decoration
resetPlugin( kwinConfig, text );
}
// This is the selection handler setting
void KWinDecorationModule::slotSelectionChanged()
{
emit KCModule::changed(true);
}
static const char* const border_names[ KDecorationDefines::BordersCount ] =
{
I18N_NOOP( "Tiny" ),
I18N_NOOP( "Normal" ),
I18N_NOOP( "Large" ),
I18N_NOOP( "Very Large" ),
I18N_NOOP( "Huge" ),
I18N_NOOP( "Very Huge" ),
I18N_NOOP( "Oversized" )
};
int KWinDecorationModule::borderSizeToIndex( BorderSize size, QList< BorderSize > sizes )
{
int pos = 0;
for( QList< BorderSize >::ConstIterator it = sizes.constBegin();
it != sizes.constEnd();
++it, ++pos )
if( size <= *it )
break;
return pos;
}
KDecorationDefines::BorderSize KWinDecorationModule::indexToBorderSize( int index,
QList< BorderSize > sizes )
{
QList< BorderSize >::ConstIterator it = sizes.constBegin();
for(;
it != sizes.constEnd();
++it, --index )
if( index == 0 )
break;
return *it;
}
void KWinDecorationModule::slotBorderChanged( int size )
{
if( lBorder->isHidden())
return;
emit KCModule::changed( true );
QList< BorderSize > sizes;
if( plugins->factory() != NULL )
sizes = plugins->factory()->borderSizes();
assert( sizes.count() >= 2 );
border_size = indexToBorderSize( size, sizes );
// update preview
preview->setTempBorderSize(plugins, border_size);
}
void KWinDecorationModule::slotButtonsChanged()
{
// update preview
preview->setTempButtons(plugins, cbUseCustomButtonPositions->isChecked(), buttonPositionWidget->buttonsLeft(), buttonPositionWidget->buttonsRight() );
}
QString KWinDecorationModule::decorationName( QString& libName )
{
QString decoName;
QList<DecorationInfo>::Iterator it;
for( it = decorations.begin(); it != decorations.end(); ++it )
if ( (*it).libraryName == libName )
{
decoName = (*it).name;
break;
}
return decoName;
}
QString KWinDecorationModule::decorationLibName( const QString& name )
{
QString libName;
// Find the corresponding library name to that of
// the current plugin name
QList<DecorationInfo>::Iterator it;
for( it = decorations.begin(); it != decorations.end(); ++it )
if ( (*it).name == name )
{
libName = (*it).libraryName;
break;
}
// if (libName.isEmpty())
// libName = "kwin_default"; // KDE 2
return libName;
}
// Loads/unloads and inserts the decoration config plugin into the
// pluginConfigWidget, allowing for dynamic configuration of decorations
void KWinDecorationModule::resetPlugin( KConfigGroup& conf, const QString& currentDecoName )
{
// Config names are "kwin_icewm_config"
// for "kwin3_icewm" kwin client
QString oldName = styleToConfigLib( oldLibraryName );
QString currentName;
if (!currentDecoName.isEmpty())
currentName = decorationLibName( currentDecoName ); // Use what the user selected
else
currentName = currentLibraryName; // Use what was read from readConfig()
if( plugins->loadPlugin( currentName )
&& preview->recreateDecoration( plugins ))
preview->enablePreview();
else
preview->disablePreview();
plugins->destroyPreviousPlugin();
checkSupportedBorderSizes();
// inform buttonPositionWidget about the new factory...
buttonPositionWidget->setDecorationFactory(plugins->factory() );
currentName = styleToConfigLib( currentName );
// Delete old plugin widget if it exists
delete pluginObject;
pluginObject = 0;
// Free the old library if possible
if (library != NULL)
library->unload();
library = new KLibrary( currentName );
if (library != NULL)
{
KLibrary::void_function_ptr alloc_ptr = library->resolveFunction("allocate_config");
if (alloc_ptr != NULL)
{
allocatePlugin = (QObject* (*)(KConfigGroup& conf, QWidget* parent))alloc_ptr;
pluginObject = (QObject*)(allocatePlugin( conf, pluginConfigWidget ));
// connect required signals and slots together...
connect( pluginObject, SIGNAL(changed()), this, SLOT(slotSelectionChanged()) );
connect( this, SIGNAL(pluginLoad(const KConfigGroup&)), pluginObject, SLOT(load(const KConfigGroup&)) );
connect( this, SIGNAL(pluginSave(KConfigGroup &)), pluginObject, SLOT(save(KConfigGroup &)) );
connect( this, SIGNAL(pluginDefaults()), pluginObject, SLOT(defaults()) );
pluginSettingsGrp->show();
return;
}
}
if ( cBorder->isHidden() )
pluginSettingsGrp->hide();
else if (pluginSettingsGrp->isHidden() )
pluginSettingsGrp->show();
}
// Reads the kwin config settings, and sets all UI controls to those settings
// Updating the config plugin if required
void KWinDecorationModule::readConfig( const KConfigGroup & conf )
{
// General tab
// ============
cbShowToolTips->setChecked( conf.readEntry("ShowToolTips", true));
// cbUseMiniWindows->setChecked( conf.readEntry("MiniWindowBorders", false));
m_showTooltips = conf.readEntry("ShowToolTips", true);
// Find the corresponding decoration name to that of
// the current plugin library name
oldLibraryName = currentLibraryName;
currentLibraryName = conf.readEntry("PluginLib",
((QPixmap::defaultDepth() > 8) ? "kwin3_oxygen" : "kwin3_plastik"));
QString decoName = decorationName( currentLibraryName );
QString libraryName = conf.readEntry("PluginLib",
((QPixmap::defaultDepth() > 8) ? "kwin3_oxygen" : "kwin3_plastik"));
if (decoName.isEmpty())
{ // Selected decoration doesn't exist, use the default
currentLibraryName = ((QPixmap::defaultDepth() > 8) ? "kwin3_oxygen" : "kwin3_plastik");
decoName = decorationName( currentLibraryName );
}
if( libraryName.isEmpty() )
{ // Selected decoration doesn't exist, use the default
libraryName = ( ( QPixmap::defaultDepth() > 8 ) ? "kwin3_oxygen" : "kwin3_plastik" );
}
// If we are using the "default" kde client, use the "default" entry.
// if (decoName.isEmpty())
// decoName = i18n("KDE 2");
int numDecos = decorationList->count();
for (int i = 0; i < numDecos; ++i)
{
if (decorationList->itemText(i) == decoName)
{
decorationList->setCurrentIndex(i);
break;
}
}
const int bsize = conf.readEntry( "BorderSize", (int)BorderNormal );
BorderSize borderSize = BorderNormal;
if( bsize >= BorderTiny && bsize < BordersCount )
borderSize = static_cast< BorderSize >( bsize );
if( libraryName == "kwin3_aurorae" )
{
KConfig auroraeConfig( "auroraerc" );
KConfigGroup group( &auroraeConfig, "Engine");
const QString themeName = group.readEntry( "ThemeName", "example-deco" );
const QModelIndex index = m_proxyModel->mapFromSource( m_model->indexOfAuroraeName( themeName ) );
if( index.isValid() )
{
m_model->resetAuroraeBorderSizes( borderSize );
m_ui->decorationList->setCurrentIndex( index );
}
}
else
{
const QModelIndex index = m_proxyModel->mapFromSource( m_model->indexOfLibrary( libraryName ) );
if( index.isValid() )
{
m_model->setBorderSize( index, borderSize );
m_ui->decorationList->setCurrentIndex( index );
}
}
// Buttons tab
// ============
bool customPositions = conf.readEntry("CustomButtonPositions", false);
cbUseCustomButtonPositions->setChecked( customPositions );
buttonPositionWidget->setEnabled( customPositions );
m_customPositions = conf.readEntry("CustomButtonPositions", false);
// Menu and onAllDesktops buttons are default on LHS
buttonPositionWidget->setButtonsLeft( conf.readEntry("ButtonsOnLeft", KDecorationOptions::defaultTitleButtonsLeft()) );
m_leftButtons = conf.readEntry("ButtonsOnLeft", KDecorationOptions::defaultTitleButtonsLeft());
// Help, Minimize, Maximize and Close are default on RHS
buttonPositionWidget->setButtonsRight( conf.readEntry("ButtonsOnRight", KDecorationOptions::defaultTitleButtonsRight()) );
int bsize = conf.readEntry( "BorderSize", (int)BorderNormal );
if( bsize >= BorderTiny && bsize < BordersCount )
border_size = static_cast< BorderSize >( bsize );
else
border_size = BorderNormal;
checkSupportedBorderSizes();
m_rightButtons = conf.readEntry("ButtonsOnRight", KDecorationOptions::defaultTitleButtonsRight());
if( m_configLoaded )
m_model->changeButtons( m_customPositions, m_leftButtons, m_rightButtons );
else
{
m_configLoaded = true;
m_model->setButtons( m_customPositions, m_leftButtons, m_rightButtons );
}
emit KCModule::changed(false);
}
@ -486,25 +179,27 @@ void KWinDecorationModule::readConfig( const KConfigGroup & conf )
// Writes the selected user configuration to the kwin config file
void KWinDecorationModule::writeConfig( KConfigGroup & conf )
{
QString name = decorationList->currentText();
QString libName = decorationLibName( name );
KConfig _kwinConfig( "kwinrc" );
KConfigGroup kwinConfig(&_kwinConfig, "Style");
const QModelIndex index = m_proxyModel->mapToSource( m_ui->decorationList->currentIndex() );
const QString libName = m_model->data( index, DecorationModel::LibraryNameRole ).toString();
// General settings
conf.writeEntry("PluginLib", libName);
conf.writeEntry("CustomButtonPositions", cbUseCustomButtonPositions->isChecked());
conf.writeEntry("ShowToolTips", cbShowToolTips->isChecked());
// conf.writeEntry("MiniWindowBorders", cbUseMiniWindows->isChecked());
conf.writeEntry("CustomButtonPositions", m_customPositions );
conf.writeEntry("ShowToolTips", m_showTooltips );
// Button settings
conf.writeEntry("ButtonsOnLeft", buttonPositionWidget->buttonsLeft() );
conf.writeEntry("ButtonsOnRight", buttonPositionWidget->buttonsRight() );
conf.writeEntry("BorderSize", static_cast<int>( border_size ) );
conf.writeEntry("ButtonsOnLeft", m_leftButtons );
conf.writeEntry("ButtonsOnRight", m_rightButtons );
conf.writeEntry( "BorderSize",
static_cast<int>( m_model->data( index, DecorationModel::BorderSizeRole ).toInt()));
oldLibraryName = currentLibraryName;
currentLibraryName = libName;
if( m_model->data( index, DecorationModel::TypeRole ).toInt() == DecorationModelData::AuroraeDecoration )
{
KConfig auroraeConfig( "auroraerc" );
KConfigGroup group( &auroraeConfig, "Engine");
group.writeEntry( "ThemeName", m_model->data( index, DecorationModel::AuroraeNameRole ).toString() );
group.sync();
}
// We saved, so tell kcmodule that there have been no new user changes made.
emit KCModule::changed(false);
@ -514,83 +209,41 @@ void KWinDecorationModule::writeConfig( KConfigGroup & conf )
// Virutal functions required by KCModule
void KWinDecorationModule::load()
{
KConfig _kwinConfig( "kwinrc" );
KConfigGroup kwinConfig(&_kwinConfig, "Style");
const KConfigGroup config( kwinConfig, "Style" );
// Reset by re-reading the config
readConfig( kwinConfig );
resetPlugin( kwinConfig );
// Reset by re-reading the config
readConfig( config );
}
void KWinDecorationModule::save()
{
KConfig _kwinConfig( "kwinrc" );
KConfigGroup kwinConfig(&_kwinConfig, "Style");
KConfigGroup config( kwinConfig, "Style" );
writeConfig( config );
config.sync();
writeConfig( kwinConfig );
emit pluginSave( kwinConfig );
kwinConfig.sync();
// Send signal to all kwin instances
QDBusMessage message =
QDBusMessage::createSignal("/KWin", "org.kde.KWin", "reloadConfig");
QDBusConnection::sessionBus().send(message);
}
void KWinDecorationModule::defaults()
{
// Set the KDE defaults
cbUseCustomButtonPositions->setChecked( false );
buttonPositionWidget->setEnabled( false );
cbShowToolTips->setChecked( true );
// cbUseMiniWindows->setChecked( false);
// Don't set default for now
// decorationList->setSelected(
// decorationList->findItem( i18n("KDE 2") ), true ); // KDE classic client
decorationList->setCurrentItem( i18n("Oxygen"), true ); // KDE classic client
slotChangeDecoration(i18n("Oxygen"));
m_customPositions = false;
m_showTooltips = true;
const QModelIndex index = m_proxyModel->mapFromSource( m_model->indexOfName( i18n("Oxygen") ) );
if( index.isValid() )
m_ui->decorationList->setCurrentIndex( index );
buttonPositionWidget->setButtonsLeft(KDecorationOptions::defaultTitleButtonsLeft());
buttonPositionWidget->setButtonsRight(KDecorationOptions::defaultTitleButtonsRight());
m_leftButtons = KDecorationOptions::defaultTitleButtonsLeft();
m_rightButtons = KDecorationOptions::defaultTitleButtonsRight();
border_size = BorderNormal;
checkSupportedBorderSizes();
m_model->changeButtons( m_customPositions, m_leftButtons, m_rightButtons );
// Set plugin defaults
emit pluginDefaults();
}
void KWinDecorationModule::checkSupportedBorderSizes()
{
QList< BorderSize > sizes;
if( plugins->factory() != NULL )
sizes = plugins->factory()->borderSizes();
if( sizes.count() < 2 ) {
lBorder->hide();
cBorder->hide();
} else {
cBorder->clear();
for (QList<BorderSize>::const_iterator it = sizes.constBegin(); it != sizes.constEnd(); ++it) {
BorderSize size = *it;
cBorder->addItem(i18n(border_names[size]), borderSizeToIndex(size,sizes) );
}
int pos = borderSizeToIndex( border_size, sizes );
lBorder->show();
cBorder->show();
cBorder->setCurrentIndex(pos);
slotBorderChanged( pos );
}
}
QString KWinDecorationModule::styleToConfigLib( QString& styleLib )
{
if( styleLib.startsWith( "kwin3_" ))
return "kwin_" + styleLib.mid( 6 ) + "_config";
else
return styleLib + "_config";
emit changed( true );
}
QString KWinDecorationModule::quickHelp() const
@ -605,6 +258,53 @@ QString KWinDecorationModule::quickHelp() const
"and you can change the positions of the buttons to your liking.</p>" );
}
void KWinDecorationModule::slotConfigureButtons()
{
QPointer< KWinDecorationButtonsConfigDialog > configDialog = new KWinDecorationButtonsConfigDialog( m_customPositions, m_showTooltips, m_leftButtons, m_rightButtons, this );
if( configDialog->exec() == KDialog::Accepted )
{
m_customPositions = configDialog->customPositions();
m_showTooltips = configDialog->showTooltips();
m_leftButtons = configDialog->buttonsLeft();
m_rightButtons = configDialog->buttonsRight();
m_model->changeButtons( m_customPositions, m_leftButtons, m_rightButtons );
emit changed( true );
}
delete configDialog;
}
void KWinDecorationModule::slotGHNSClicked()
{
QPointer<KNS3::DownloadDialog> downloadDialog = new KNS3::DownloadDialog( "aurorae.knsrc", this );
if( downloadDialog->exec() == KDialog::Accepted )
{
if( !downloadDialog->changedEntries().isEmpty() )
{
const QModelIndex index = m_proxyModel->mapToSource( m_ui->decorationList->currentIndex() );
const QString libraryName = m_model->data( index, DecorationModel::LibraryNameRole ).toString();
bool aurorae = m_model->data( index, DecorationModel::TypeRole ).toInt() == DecorationModelData::AuroraeDecoration;
const QString auroraeName = m_model->data( index, DecorationModel::AuroraeNameRole ).toString();
m_model->reload();
if( aurorae )
{
const QModelIndex proxyIndex = m_proxyModel->mapFromSource( m_model->indexOfAuroraeName( auroraeName ) );
if( proxyIndex.isValid() )
m_ui->decorationList->setCurrentIndex( proxyIndex );
}
else
{
const QModelIndex proxyIndex = m_proxyModel->mapFromSource( m_model->indexOfLibrary( libraryName ) );
if( proxyIndex.isValid() )
m_ui->decorationList->setCurrentIndex( proxyIndex );
}
}
}
delete downloadDialog;
}
} // namespace KWin
#include "kwindecoration.moc"
// vim: ts=4
// kate: space-indent off; tab-width 4;

View file

@ -4,6 +4,7 @@
Copyright (c) 2001
Karol Szwed <gallium@kde.org>
http://gallium.n3.net/
Copyright 2009, 2010 Martin Gräßlin <kde@martin-graesslin.com>
Supports new kwin configuration plugins, and titlebar button position
modification via dnd interface.
@ -31,31 +32,25 @@
#define KWINDECORATION_H
#include <kcmodule.h>
#include "buttons.h"
#include <kconfig.h>
#include <klibrary.h>
#include <kapplication.h>
#include <kdecoration.h>
class KComboBox;
class QCheckBox;
class QGroupBox;
class QLabel;
class KComboBox;
class KTabWidget;
class KVBox;
#include "ui_decoration.h"
class KDecorationPlugins;
class KDecorationPreview;
// Stores themeName and its corresponding library Name
struct DecorationInfo
class QSortFilterProxyModel;
namespace KWin
{
QString name;
QString libraryName;
};
class DecorationModel;
class KWinDecorationForm : public QWidget, public Ui::KWinDecorationForm
{
Q_OBJECT
public:
explicit KWinDecorationForm( QWidget* parent );
};
class KWinDecorationModule : public KCModule, public KDecorationDefines
{
@ -79,54 +74,27 @@ class KWinDecorationModule : public KCModule, public KDecorationDefines
protected slots:
// Allows us to turn "save" on
void slotSelectionChanged();
void slotChangeDecoration( const QString & );
void slotBorderChanged( int );
void slotButtonsChanged();
void slotConfigureButtons();
void slotGHNSClicked();
private:
void readConfig( const KConfigGroup& conf );
void writeConfig( KConfigGroup &conf );
void findDecorations();
void createDecorationList();
void updateSelection();
QString decorationLibName( const QString& name );
QString decorationName ( QString& libName );
static QString styleToConfigLib( QString& styleLib );
void resetPlugin( KConfigGroup& conf, const QString& currentDecoName = QString() );
void checkSupportedBorderSizes();
static int borderSizeToIndex( BorderSize size, QList< BorderSize > sizes );
static BorderSize indexToBorderSize( int index, QList< BorderSize > sizes );
KTabWidget* tabWidget;
// Page 1
KComboBox* decorationList;
QList<DecorationInfo> decorations;
KDecorationPreview* preview;
KDecorationPlugins* plugins;
KSharedConfigPtr kwinConfig;
QCheckBox* cbUseCustomButtonPositions;
// QCheckBox* cbUseMiniWindows;
QCheckBox* cbShowToolTips;
QLabel* lBorder;
KComboBox* cBorder;
BorderSize border_size;
KWinDecorationForm* m_ui;
bool m_showTooltips;
bool m_customPositions;
QString m_leftButtons;
QString m_rightButtons;
QObject* pluginObject;
QWidget* pluginConfigWidget;
QString currentLibraryName;
QString oldLibraryName;
KLibrary* library;
QObject* (*allocatePlugin)( KConfigGroup& conf, QWidget* parent );
// Page 2
ButtonPositionWidget *buttonPositionWidget;
KVBox* buttonPage;
QGroupBox *pluginSettingsGrp;
DecorationModel* m_model;
QSortFilterProxyModel* m_proxyModel;
bool m_configLoaded;
};
} //namespace
#endif
// vim: ts=4

View file

@ -39,8 +39,6 @@
#include <QX11Info>
#include <kwindowsystem.h>
// FRAME the preview doesn't update to reflect the changes done in the kcm
KDecorationPreview::KDecorationPreview( QWidget* parent )
: QWidget( parent )
{
@ -125,6 +123,24 @@ void KDecorationPreview::paintEvent( QPaintEvent* e )
}
}
QPixmap KDecorationPreview::preview()
{
QPixmap pixmap( size() );
pixmap.fill( Qt::transparent );
if ( deco[Inactive] )
{
QWidget *w = deco[Inactive]->widget();
w->render( &pixmap, w->mapToParent( QPoint(0, 0) ) );
}
if ( deco[Active] )
{
QWidget *w = deco[Active]->widget();
w->render( &pixmap, w->mapToParent( QPoint(0, 0) ) );
}
return pixmap;
}
void KDecorationPreview::resizeEvent( QResizeEvent* e )
{
QWidget::resizeEvent( e );

View file

@ -54,6 +54,7 @@ class KDecorationPreview
QRect windowGeometry( bool ) const;
void setTempBorderSize(KDecorationPlugins* plugin, KDecorationDefines::BorderSize size);
void setTempButtons(KDecorationPlugins* plugin, bool customEnabled, const QString &left, const QString &right);
QPixmap preview();
protected:
virtual void paintEvent( QPaintEvent* );
virtual void resizeEvent( QResizeEvent* );