From c9df18ab9814089231fc62397e6e8661f45504bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Tue, 19 Jan 2010 13:44:22 +0000 Subject: [PATCH] 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 --- kcmkwin/kwindecoration/CMakeLists.txt | 22 +- kcmkwin/kwindecoration/auroraepreview.cpp | 371 ++++++++++ kcmkwin/kwindecoration/auroraepreview.h | 62 ++ kcmkwin/kwindecoration/buttons.cpp | 61 +- kcmkwin/kwindecoration/buttons.h | 9 +- kcmkwin/kwindecoration/buttons.ui | 52 ++ .../kwindecoration/buttonsconfigdialog.cpp | 113 ++++ kcmkwin/kwindecoration/buttonsconfigdialog.h | 66 ++ kcmkwin/kwindecoration/config.ui | 49 ++ kcmkwin/kwindecoration/configdialog.cpp | 167 +++++ kcmkwin/kwindecoration/configdialog.h | 73 ++ kcmkwin/kwindecoration/decoration.ui | 81 +++ kcmkwin/kwindecoration/decorationdelegate.cpp | 176 +++++ kcmkwin/kwindecoration/decorationdelegate.h | 55 ++ kcmkwin/kwindecoration/decorationmodel.cpp | 313 +++++++++ kcmkwin/kwindecoration/decorationmodel.h | 127 ++++ kcmkwin/kwindecoration/kwindecoration.cpp | 640 +++++------------- kcmkwin/kwindecoration/kwindecoration.h | 80 +-- kcmkwin/kwindecoration/preview.cpp | 20 +- kcmkwin/kwindecoration/preview.h | 1 + 20 files changed, 1948 insertions(+), 590 deletions(-) create mode 100644 kcmkwin/kwindecoration/auroraepreview.cpp create mode 100644 kcmkwin/kwindecoration/auroraepreview.h create mode 100644 kcmkwin/kwindecoration/buttons.ui create mode 100644 kcmkwin/kwindecoration/buttonsconfigdialog.cpp create mode 100644 kcmkwin/kwindecoration/buttonsconfigdialog.h create mode 100644 kcmkwin/kwindecoration/config.ui create mode 100644 kcmkwin/kwindecoration/configdialog.cpp create mode 100644 kcmkwin/kwindecoration/configdialog.h create mode 100644 kcmkwin/kwindecoration/decoration.ui create mode 100644 kcmkwin/kwindecoration/decorationdelegate.cpp create mode 100644 kcmkwin/kwindecoration/decorationdelegate.h create mode 100644 kcmkwin/kwindecoration/decorationmodel.cpp create mode 100644 kcmkwin/kwindecoration/decorationmodel.h diff --git a/kcmkwin/kwindecoration/CMakeLists.txt b/kcmkwin/kwindecoration/CMakeLists.txt index 97f6b08c13..407ccaee94 100644 --- a/kcmkwin/kwindecoration/CMakeLists.txt +++ b/kcmkwin/kwindecoration/CMakeLists.txt @@ -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 ############### diff --git a/kcmkwin/kwindecoration/auroraepreview.cpp b/kcmkwin/kwindecoration/auroraepreview.cpp new file mode 100644 index 0000000000..408d848e6a --- /dev/null +++ b/kcmkwin/kwindecoration/auroraepreview.cpp @@ -0,0 +1,371 @@ +/******************************************************************** +KWin - the KDE window manager +This file is part of the KDE project. + +Copyright (C) 2009 Martin Gräßlin + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ +#include "auroraepreview.h" +#include "themeconfig.h" +// Qt +#include +#include +#include +// KDE +#include +#include +#include +#include +// Plasma +#include + +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 diff --git a/kcmkwin/kwindecoration/auroraepreview.h b/kcmkwin/kwindecoration/auroraepreview.h new file mode 100644 index 0000000000..3299f1c82d --- /dev/null +++ b/kcmkwin/kwindecoration/auroraepreview.h @@ -0,0 +1,62 @@ +/******************************************************************** +KWin - the KDE window manager +This file is part of the KDE project. + +Copyright (C) 2009 Martin Gräßlin + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ +#ifndef KWIN_AURORAEPREVIEW_H +#define KWIN_AURORAEPREVIEW_H +#include +#include +#include + +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 m_buttons; + QString m_title; +}; + +} // namespace KWin + +#endif // KWIN_AURORAEPREVIEW_H diff --git a/kcmkwin/kwindecoration/buttons.cpp b/kcmkwin/kwindecoration/buttons.cpp index 758bb8ae39..e86a3cff08 100644 --- a/kcmkwin/kwindecoration/buttons.cpp +++ b/kcmkwin/kwindecoration/buttons.cpp @@ -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(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; diff --git a/kcmkwin/kwindecoration/buttons.h b/kcmkwin/kwindecoration/buttons.h index 701ccc4805..1d61b5c1bb 100644 --- a/kcmkwin/kwindecoration/buttons.h +++ b/kcmkwin/kwindecoration/buttons.h @@ -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 diff --git a/kcmkwin/kwindecoration/buttons.ui b/kcmkwin/kwindecoration/buttons.ui new file mode 100644 index 0000000000..3526f45d2d --- /dev/null +++ b/kcmkwin/kwindecoration/buttons.ui @@ -0,0 +1,52 @@ + + + KWinDecorationButtonsConfigForm + + + + 0 + 0 + 400 + 300 + + + + Form + + + + + + Enabling this checkbox will show window button tooltips. If this checkbox is off, no window button tooltips will be shown. + + + &Show window button tooltips + + + + + + + The appropriate settings can be found in the "Buttons" Tab; please note that this option is not available on all styles yet. + + + Use custom titlebar button &positions + + + + + + + + + + + KWin::ButtonPositionWidget + QWidget +
buttons.h
+ 1 +
+
+ + +
diff --git a/kcmkwin/kwindecoration/buttonsconfigdialog.cpp b/kcmkwin/kwindecoration/buttonsconfigdialog.cpp new file mode 100644 index 0000000000..260fc3a3cc --- /dev/null +++ b/kcmkwin/kwindecoration/buttonsconfigdialog.cpp @@ -0,0 +1,113 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2009 Martin Gräßlin + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ +#include "buttonsconfigdialog.h" + +#include + +#include +#include + +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" diff --git a/kcmkwin/kwindecoration/buttonsconfigdialog.h b/kcmkwin/kwindecoration/buttonsconfigdialog.h new file mode 100644 index 0000000000..fdeffe48b5 --- /dev/null +++ b/kcmkwin/kwindecoration/buttonsconfigdialog.h @@ -0,0 +1,66 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2009 Martin Gräßlin + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ +#ifndef KWINDECORATIONBUTTONSCONFIGDIALOG_H +#define KWINDECORATIONBUTTONSCONFIGDIALOG_H + +#include +#include + +#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 diff --git a/kcmkwin/kwindecoration/config.ui b/kcmkwin/kwindecoration/config.ui new file mode 100644 index 0000000000..f1e56590ab --- /dev/null +++ b/kcmkwin/kwindecoration/config.ui @@ -0,0 +1,49 @@ + + + KWinDecorationConfigForm + + + + 0 + 0 + 188 + 38 + + + + Form + + + + + + + + B&order size: + + + bordersCombo + + + + + + + Use this combobox to change the border size of the decoration. + + + + + + + + + + KComboBox + QComboBox +
kcombobox.h
+
+
+ + +
diff --git a/kcmkwin/kwindecoration/configdialog.cpp b/kcmkwin/kwindecoration/configdialog.cpp new file mode 100644 index 0000000000..bfffe31778 --- /dev/null +++ b/kcmkwin/kwindecoration/configdialog.cpp @@ -0,0 +1,167 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2009 Martin Gräßlin + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ +#include "configdialog.h" + +#include +#include + +#include +#include + +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& 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( 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" diff --git a/kcmkwin/kwindecoration/configdialog.h b/kcmkwin/kwindecoration/configdialog.h new file mode 100644 index 0000000000..fbbf2b78f4 --- /dev/null +++ b/kcmkwin/kwindecoration/configdialog.h @@ -0,0 +1,73 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2009 Martin Gräßlin + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ +#ifndef KWINDECORATIONCONFIGDIALOG_H +#define KWINDECORATIONCONFIGDIALOG_H +#include +#include +#include +#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& 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& sizes ); + QString styleToConfigLib( const QString& styleLib ) const; + + private: + KWinDecorationConfigForm* m_ui; + QList m_borderSizes; + KSharedConfigPtr m_kwinConfig; + + QObject* (*allocatePlugin)( KConfigGroup& conf, QWidget* parent ); + QObject* m_pluginObject; + QWidget* m_pluginConfigWidget; +}; + +} // namespace KWin + +#endif // KWINDECORATIONCONFIGDIALOG_H diff --git a/kcmkwin/kwindecoration/decoration.ui b/kcmkwin/kwindecoration/decoration.ui new file mode 100644 index 0000000000..b05a7e8419 --- /dev/null +++ b/kcmkwin/kwindecoration/decoration.ui @@ -0,0 +1,81 @@ + + + KWinDecorationForm + + + + 0 + 0 + 681 + 515 + + + + Form + + + + + + Search + + + true + + + + + + + Select the window decoration. This is the look and feel of both the window borders and the window handle. + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Configure Buttons ... + + + + + + + Get New Decorations ... + + + + + + + + + + KPushButton + QPushButton +
kpushbutton.h
+
+ + KLineEdit + QLineEdit +
klineedit.h
+
+
+ + +
diff --git a/kcmkwin/kwindecoration/decorationdelegate.cpp b/kcmkwin/kwindecoration/decorationdelegate.cpp new file mode 100644 index 0000000000..27272d9635 --- /dev/null +++ b/kcmkwin/kwindecoration/decorationdelegate.cpp @@ -0,0 +1,176 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2009 Martin Gräßlin + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ +#include "decorationdelegate.h" +#include "decorationmodel.h" +#include "configdialog.h" +#include +#include +#include +#include +#include +#include + +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(); + + 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 widgets; + KPushButton *info = new KPushButton; + info->setIcon( KIcon( "dialog-information" ) ); + setBlockedEventTypes( info, QList() << QEvent::MouseButtonPress + << QEvent::MouseButtonRelease << QEvent::MouseButtonDblClick + << QEvent::KeyPress << QEvent::KeyRelease); + + KPushButton *configure = new KPushButton; + configure->setIcon( KIcon( "configure" ) ); + setBlockedEventTypes( configure, QList() << 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( 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( 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( 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 about = new KAboutApplicationDialog( &aboutData, itemView() ); + about->exec(); + delete about; + } + +} // namespace KWin diff --git a/kcmkwin/kwindecoration/decorationdelegate.h b/kcmkwin/kwindecoration/decorationdelegate.h new file mode 100644 index 0000000000..6c031883e2 --- /dev/null +++ b/kcmkwin/kwindecoration/decorationdelegate.h @@ -0,0 +1,55 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2009 Martin Gräßlin + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ +#ifndef PREVIEWDELEGATE_H +#define PREVIEWDELEGATE_H +#include + +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 diff --git a/kcmkwin/kwindecoration/decorationmodel.cpp b/kcmkwin/kwindecoration/decorationmodel.cpp new file mode 100644 index 0000000000..af73a8c084 --- /dev/null +++ b/kcmkwin/kwindecoration/decorationmodel.cpp @@ -0,0 +1,313 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2009 Martin Gräßlin + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ +#include "decorationmodel.h" +#include "preview.h" +#include "auroraepreview.h" +// kwin +#include +// Qt +#include +#include +// KDE +#include +#include +#include + +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::iterator it = m_decorations.begin(); + + for( int i=0; ireset( 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::iterator it = m_decorations.begin(); + + while( it != m_decorations.end() ) + { + if( (*it).type == DecorationModelData::AuroraeDecoration ) + (*it).borderSize = size; + ++it; + } + } + +} // namespace KWin diff --git a/kcmkwin/kwindecoration/decorationmodel.h b/kcmkwin/kwindecoration/decorationmodel.h new file mode 100644 index 0000000000..abccc0d9c6 --- /dev/null +++ b/kcmkwin/kwindecoration/decorationmodel.h @@ -0,0 +1,127 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2009 Martin Gräßlin + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +#ifndef PREVIEWMODEL_H +#define PREVIEWMODEL_H +#include +#include +#include +#include + +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 m_decorations; + KDecorationPlugins* m_plugins; + KDecorationPreview* m_preview; + bool m_customButtons; + QString m_leftButtons; + QString m_rightButtons; +}; + +} // namespace KWin + +#endif // PREVIEWMODEL_H diff --git a/kcmkwin/kwindecoration/kwindecoration.cpp b/kcmkwin/kwindecoration/kwindecoration.cpp index 265e80d5eb..a26949f890 100644 --- a/kcmkwin/kwindecoration/kwindecoration.cpp +++ b/kcmkwin/kwindecoration/kwindecoration.cpp @@ -4,6 +4,7 @@ Copyright (c) 2001 Karol Szwed http://gallium.n3.net/ + Copyright 2009, 2010 Martin Gräßlin 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 -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - +#include "buttonsconfigdialog.h" +#include "decorationdelegate.h" +#include "decorationmodel.h" +// Qt #include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include +#include +// KDE +#include +#include +#include +#include #include -#include // KCModule plugin interface // ========================= K_PLUGIN_FACTORY(KWinDecoFactory, - registerPlugin(); + registerPlugin(); ) 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::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::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::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( border_size ) ); + conf.writeEntry("ButtonsOnLeft", m_leftButtons ); + conf.writeEntry("ButtonsOnRight", m_rightButtons ); + conf.writeEntry( "BorderSize", + static_cast( 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::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.

" ); } +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 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; diff --git a/kcmkwin/kwindecoration/kwindecoration.h b/kcmkwin/kwindecoration/kwindecoration.h index 83bfa9194d..99d46bf7bf 100644 --- a/kcmkwin/kwindecoration/kwindecoration.h +++ b/kcmkwin/kwindecoration/kwindecoration.h @@ -4,6 +4,7 @@ Copyright (c) 2001 Karol Szwed http://gallium.n3.net/ + Copyright 2009, 2010 Martin Gräßlin Supports new kwin configuration plugins, and titlebar button position modification via dnd interface. @@ -31,31 +32,25 @@ #define KWINDECORATION_H #include -#include "buttons.h" #include -#include -#include #include -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 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 diff --git a/kcmkwin/kwindecoration/preview.cpp b/kcmkwin/kwindecoration/preview.cpp index 55f0339736..ca4856d52d 100644 --- a/kcmkwin/kwindecoration/preview.cpp +++ b/kcmkwin/kwindecoration/preview.cpp @@ -39,8 +39,6 @@ #include #include -// 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 ); diff --git a/kcmkwin/kwindecoration/preview.h b/kcmkwin/kwindecoration/preview.h index fab1783e07..f0f57ee9e0 100644 --- a/kcmkwin/kwindecoration/preview.h +++ b/kcmkwin/kwindecoration/preview.h @@ -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* );