summaryrefslogtreecommitdiffstats
path: root/kwin/kcmkwin/kwinrules/ruleswidget.cpp
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit4aed2c8219774f5d797760606b8489a92ddc5163 (patch)
tree3f8c130f7d269626bf6a9447407ef6c35954426a /kwin/kcmkwin/kwinrules/ruleswidget.cpp
downloadtdebase-4aed2c8219774f5d797760606b8489a92ddc5163.tar.gz
tdebase-4aed2c8219774f5d797760606b8489a92ddc5163.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdebase@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kwin/kcmkwin/kwinrules/ruleswidget.cpp')
-rw-r--r--kwin/kcmkwin/kwinrules/ruleswidget.cpp803
1 files changed, 803 insertions, 0 deletions
diff --git a/kwin/kcmkwin/kwinrules/ruleswidget.cpp b/kwin/kcmkwin/kwinrules/ruleswidget.cpp
new file mode 100644
index 000000000..7a8afe292
--- /dev/null
+++ b/kwin/kcmkwin/kwinrules/ruleswidget.cpp
@@ -0,0 +1,803 @@
+/*
+ * Copyright (c) 2004 Lubos Lunak <l.lunak@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "ruleswidget.h"
+
+#include <klineedit.h>
+#include <krestrictedline.h>
+#include <kcombobox.h>
+#include <qcheckbox.h>
+#include <kpushbutton.h>
+#include <qlabel.h>
+#include <kwinmodule.h>
+#include <klocale.h>
+#include <qregexp.h>
+#include <qwhatsthis.h>
+#include <assert.h>
+#include <kmessagebox.h>
+#include <qtabwidget.h>
+#include <qtimer.h>
+
+#include "../../rules.h"
+
+#include "detectwidget.h"
+
+namespace KWinInternal
+{
+
+#define SETUP( var, type ) \
+ connect( enable_##var, SIGNAL( toggled( bool )), rule_##var, SLOT( setEnabled( bool ))); \
+ connect( enable_##var, SIGNAL( toggled( bool )), this, SLOT( updateEnable##var())); \
+ connect( rule_##var, SIGNAL( activated( int )), this, SLOT( updateEnable##var())); \
+ QWhatsThis::add( enable_##var, enableDesc ); \
+ QWhatsThis::add( rule_##var, type##RuleDesc );
+
+RulesWidget::RulesWidget( QWidget* parent, const char* name )
+: RulesWidgetBase( parent, name )
+, detect_dlg( NULL )
+ {
+ QString enableDesc =
+ i18n( "Enable this checkbox to alter this window property for the specified window(s)." );
+ QString setRuleDesc =
+ i18n( "Specify how the window property should be affected:<ul>"
+ "<li><em>Do Not Affect:</em> The window property will not be affected and therefore"
+ " the default handling for it will be used. Specifying this will block more generic"
+ " window settings from taking effect.</li>"
+ "<li><em>Apply Initially:</em> The window property will be only set to the given value"
+ " after the window is created. No further changes will be affected.</li>"
+ "<li><em>Remember:</em> The value of the window property will be remembered and every time"
+ " time the window is created, the last remembered value will be applied.</li>"
+ "<li><em>Force:</em> The window property will be always forced to the given value.</li>"
+ "<li><em>Apply Now:</em> The window property will be set to the given value immediately"
+ " and will not be affected later (this action will be deleted afterwards).</li>"
+ "<li><em>Force temporarily:</em> The window property will be forced to the given value"
+ " until it is hidden (this action will be deleted after the window is hidden).</li>"
+ "</ul>" );
+ QString forceRuleDesc =
+ i18n( "Specify how the window property should be affected:<ul>"
+ "<li><em>Do Not Affect:</em> The window property will not be affected and therefore"
+ " the default handling for it will be used. Specifying this will block more generic"
+ " window settings from taking effect.</li>"
+ "<li><em>Force:</em> The window property will be always forced to the given value.</li>"
+ "<li><em>Force temporarily:</em> The window property will be forced to the given value"
+ " until it is hidden (this action will be deleted after the window is hidden).</li>"
+ "</ul>" );
+ // window tabs have enable signals done in designer
+ // geometry tab
+ SETUP( position, set );
+ SETUP( size, set );
+ SETUP( desktop, set );
+ SETUP( maximizehoriz, set );
+ SETUP( maximizevert, set );
+ SETUP( minimize, set );
+ SETUP( shade, set );
+ SETUP( fullscreen, set );
+ SETUP( placement, force );
+ // preferences tab
+ SETUP( above, set );
+ SETUP( below, set );
+ SETUP( noborder, set );
+ SETUP( skiptaskbar, set );
+ SETUP( skippager, set );
+ SETUP( acceptfocus, force );
+ SETUP( closeable, force );
+ SETUP( opacityactive, force );
+ SETUP( opacityinactive, force );
+ SETUP( shortcut, force );
+ // workarounds tab
+ SETUP( fsplevel, force );
+ SETUP( moveresizemode, force );
+ SETUP( type, force );
+ SETUP( ignoreposition, force );
+ SETUP( minsize, force );
+ SETUP( maxsize, force );
+ SETUP( strictgeometry, force );
+ SETUP( disableglobalshortcuts, force );
+ KWinModule module;
+ int i;
+ for( i = 1;
+ i <= module.numberOfDesktops();
+ ++i )
+ desktop->insertItem( QString::number( i ).rightJustify( 2 ) + ":" + module.desktopName( i ));
+ desktop->insertItem( i18n( "All Desktops" ));
+ }
+
+#undef SETUP
+
+#define UPDATE_ENABLE_SLOT( var ) \
+void RulesWidget::updateEnable##var() \
+ { \
+ /* leave the label readable label_##var->setEnabled( enable_##var->isChecked() && rule_##var->currentItem() != 0 );*/ \
+ var->setEnabled( enable_##var->isChecked() && rule_##var->currentItem() != 0 ); \
+ }
+
+// geometry tab
+UPDATE_ENABLE_SLOT( position )
+UPDATE_ENABLE_SLOT( size )
+UPDATE_ENABLE_SLOT( desktop )
+UPDATE_ENABLE_SLOT( maximizehoriz )
+UPDATE_ENABLE_SLOT( maximizevert )
+UPDATE_ENABLE_SLOT( minimize )
+UPDATE_ENABLE_SLOT( shade )
+UPDATE_ENABLE_SLOT( fullscreen )
+UPDATE_ENABLE_SLOT( placement )
+// preferences tab
+UPDATE_ENABLE_SLOT( above )
+UPDATE_ENABLE_SLOT( below )
+UPDATE_ENABLE_SLOT( noborder )
+UPDATE_ENABLE_SLOT( skiptaskbar )
+UPDATE_ENABLE_SLOT( skippager )
+UPDATE_ENABLE_SLOT( acceptfocus )
+UPDATE_ENABLE_SLOT( closeable )
+UPDATE_ENABLE_SLOT( opacityactive )
+UPDATE_ENABLE_SLOT( opacityinactive )
+void RulesWidget::updateEnableshortcut()
+ {
+ shortcut->setEnabled( enable_shortcut->isChecked() && rule_shortcut->currentItem() != 0 );
+ shortcut_edit->setEnabled( enable_shortcut->isChecked() && rule_shortcut->currentItem() != 0 );
+ }
+// workarounds tab
+UPDATE_ENABLE_SLOT( fsplevel )
+UPDATE_ENABLE_SLOT( moveresizemode )
+UPDATE_ENABLE_SLOT( type )
+UPDATE_ENABLE_SLOT( ignoreposition )
+UPDATE_ENABLE_SLOT( minsize )
+UPDATE_ENABLE_SLOT( maxsize )
+UPDATE_ENABLE_SLOT( strictgeometry )
+UPDATE_ENABLE_SLOT( disableglobalshortcuts )
+
+#undef UPDATE_ENABLE_SLOT
+
+static const int set_rule_to_combo[] =
+ {
+ 0, // Unused
+ 0, // Don't Affect
+ 3, // Force
+ 1, // Apply
+ 2, // Remember
+ 4, // ApplyNow
+ 5 // ForceTemporarily
+ };
+
+static const Rules::SetRule combo_to_set_rule[] =
+ {
+ ( Rules::SetRule )Rules::DontAffect,
+ ( Rules::SetRule )Rules::Apply,
+ ( Rules::SetRule )Rules::Remember,
+ ( Rules::SetRule )Rules::Force,
+ ( Rules::SetRule )Rules::ApplyNow,
+ ( Rules::SetRule )Rules::ForceTemporarily
+ };
+
+static const int force_rule_to_combo[] =
+ {
+ 0, // Unused
+ 0, // Don't Affect
+ 1, // Force
+ 0, // Apply
+ 0, // Remember
+ 0, // ApplyNow
+ 2 // ForceTemporarily
+ };
+
+static const Rules::ForceRule combo_to_force_rule[] =
+ {
+ ( Rules::ForceRule )Rules::DontAffect,
+ ( Rules::ForceRule )Rules::Force,
+ ( Rules::ForceRule )Rules::ForceTemporarily
+ };
+
+static QString positionToStr( const QPoint& p )
+ {
+ if( p == invalidPoint )
+ return QString::null;
+ return QString::number( p.x()) + "," + QString::number( p.y());
+ }
+
+static QPoint strToPosition( const QString& str )
+ { // two numbers, with + or -, separated by any of , x X :
+ QRegExp reg( "\\s*([+-]?[0-9]*)\\s*[,xX:]\\s*([+-]?[0-9]*)\\s*" );
+ if( !reg.exactMatch( str ))
+ return invalidPoint;
+ return QPoint( reg.cap( 1 ).toInt(), reg.cap( 2 ).toInt());
+ }
+
+static QString sizeToStr( const QSize& s )
+ {
+ if( !s.isValid())
+ return QString::null;
+ return QString::number( s.width()) + "," + QString::number( s.height());
+ }
+
+static QSize strToSize( const QString& str )
+ { // two numbers, with + or -, separated by any of , x X :
+ QRegExp reg( "\\s*([+-]?[0-9]*)\\s*[,xX:]\\s*([+-]?[0-9]*)\\s*" );
+ if( !reg.exactMatch( str ))
+ return QSize();
+ return QSize( reg.cap( 1 ).toInt(), reg.cap( 2 ).toInt());
+ }
+
+//used for opacity settings
+static QString intToStr( const int& s )
+ {
+ if( s < 1 || s > 100 )
+ return QString::null;
+ return QString::number(s);
+ }
+
+static int strToInt( const QString& str )
+ {
+ int tmp = str.toInt();
+ if( tmp < 1 || tmp > 100 )
+ return 100;
+ return tmp;
+ }
+
+int RulesWidget::desktopToCombo( int d ) const
+ {
+ if( d >= 1 && d < desktop->count())
+ return d - 1;
+ return desktop->count() - 1; // on all desktops
+ }
+
+int RulesWidget::comboToDesktop( int val ) const
+ {
+ if( val == desktop->count() - 1 )
+ return NET::OnAllDesktops;
+ return val + 1;
+ }
+
+static int placementToCombo( Placement::Policy placement )
+ {
+ static const int conv[] =
+ {
+ 1, // NoPlacement
+ 0, // Default
+ 0, // Unknown
+ 6, // Random
+ 2, // Smart
+ 4, // Cascade
+ 5, // Centered
+ 7, // ZeroCornered
+ 8, // UnderMouse
+ 9, // OnMainWindow
+ 3 // Maximizing
+ };
+ return conv[ placement ];
+ }
+
+static Placement::Policy comboToPlacement( int val )
+ {
+ static const Placement::Policy conv[] =
+ {
+ Placement::Default,
+ Placement::NoPlacement,
+ Placement::Smart,
+ Placement::Maximizing,
+ Placement::Cascade,
+ Placement::Centered,
+ Placement::Random,
+ Placement::ZeroCornered,
+ Placement::UnderMouse,
+ Placement::OnMainWindow
+ // no Placement::Unknown
+ };
+ return conv[ val ];
+ }
+
+static int moveresizeToCombo( Options::MoveResizeMode mode )
+ {
+ return mode == Options::Opaque ? 0 : 1;
+ }
+
+static Options::MoveResizeMode comboToMoveResize( int val )
+ {
+ return val == 0 ? Options::Opaque : Options::Transparent;
+ }
+
+static int typeToCombo( NET::WindowType type )
+ {
+ if( type < NET::Normal || type > NET::Splash )
+ return 0; // Normal
+ static const int conv[] =
+ {
+ 0, // Normal
+ 7, // Desktop
+ 3, // Dock
+ 4, // Toolbar
+ 5, // Menu
+ 1, // Dialog
+ 8, // Override
+ 9, // TopMenu
+ 2, // Utility
+ 6 // Splash
+ };
+ return conv[ type ];
+ }
+
+static NET::WindowType comboToType( int val )
+ {
+ static const NET::WindowType conv[] =
+ {
+ NET::Normal,
+ NET::Dialog,
+ NET::Utility,
+ NET::Dock,
+ NET::Toolbar,
+ NET::Menu,
+ NET::Splash,
+ NET::Desktop,
+ NET::Override,
+ NET::TopMenu
+ };
+ return conv[ val ];
+ }
+
+#define GENERIC_RULE( var, func, Type, type, uimethod, uimethod0 ) \
+ if( rules->var##rule == Rules::Unused##Type##Rule ) \
+ { \
+ enable_##var->setChecked( false ); \
+ rule_##var->setCurrentItem( 0 ); \
+ var->uimethod0; \
+ updateEnable##var(); \
+ } \
+ else \
+ { \
+ enable_##var->setChecked( true ); \
+ rule_##var->setCurrentItem( type##_rule_to_combo[ rules->var##rule ] ); \
+ var->uimethod( func( rules->var )); \
+ updateEnable##var(); \
+ }
+
+#define CHECKBOX_SET_RULE( var, func ) GENERIC_RULE( var, func, Set, set, setChecked, setChecked( false ))
+#define LINEEDIT_SET_RULE( var, func ) GENERIC_RULE( var, func, Set, set, setText, setText( "" ))
+#define COMBOBOX_SET_RULE( var, func ) GENERIC_RULE( var, func, Set, set, setCurrentItem, setCurrentItem( 0 ))
+#define CHECKBOX_FORCE_RULE( var, func ) GENERIC_RULE( var, func, Force, force, setChecked, setChecked( false ))
+#define LINEEDIT_FORCE_RULE( var, func ) GENERIC_RULE( var, func, Force, force, setText, setText( "" ))
+#define COMBOBOX_FORCE_RULE( var, func ) GENERIC_RULE( var, func, Force, force, setCurrentItem, setCurrentItem( 0 ))
+
+void RulesWidget::setRules( Rules* rules )
+ {
+ Rules tmp;
+ if( rules == NULL )
+ rules = &tmp; // empty
+ description->setText( rules->description );
+ wmclass->setText( rules->wmclass );
+ whole_wmclass->setChecked( rules->wmclasscomplete );
+ wmclass_match->setCurrentItem( rules->wmclassmatch );
+ wmclassMatchChanged();
+ role->setText( rules->windowrole );
+ role_match->setCurrentItem( rules->windowrolematch );
+ roleMatchChanged();
+ types->setSelected( 0, rules->types & NET::NormalMask );
+ types->setSelected( 1, rules->types & NET::DialogMask );
+ types->setSelected( 2, rules->types & NET::UtilityMask );
+ types->setSelected( 3, rules->types & NET::DockMask );
+ types->setSelected( 4, rules->types & NET::ToolbarMask );
+ types->setSelected( 5, rules->types & NET::MenuMask );
+ types->setSelected( 6, rules->types & NET::SplashMask );
+ types->setSelected( 7, rules->types & NET::DesktopMask );
+ types->setSelected( 8, rules->types & NET::OverrideMask );
+ types->setSelected( 9, rules->types & NET::TopMenuMask );
+ title->setText( rules->title );
+ title_match->setCurrentItem( rules->titlematch );
+ titleMatchChanged();
+ extra->setText( rules->extrarole );
+ extra_match->setCurrentItem( rules->extrarolematch );
+ extraMatchChanged();
+ machine->setText( rules->clientmachine );
+ machine_match->setCurrentItem( rules->clientmachinematch );
+ machineMatchChanged();
+ LINEEDIT_SET_RULE( position, positionToStr );
+ LINEEDIT_SET_RULE( size, sizeToStr );
+ COMBOBOX_SET_RULE( desktop, desktopToCombo );
+ CHECKBOX_SET_RULE( maximizehoriz, );
+ CHECKBOX_SET_RULE( maximizevert, );
+ CHECKBOX_SET_RULE( minimize, );
+ CHECKBOX_SET_RULE( shade, );
+ CHECKBOX_SET_RULE( fullscreen, );
+ COMBOBOX_FORCE_RULE( placement, placementToCombo );
+ CHECKBOX_SET_RULE( above, );
+ CHECKBOX_SET_RULE( below, );
+ CHECKBOX_SET_RULE( noborder, );
+ CHECKBOX_SET_RULE( skiptaskbar, );
+ CHECKBOX_SET_RULE( skippager, );
+ CHECKBOX_FORCE_RULE( acceptfocus, );
+ CHECKBOX_FORCE_RULE( closeable, );
+ LINEEDIT_FORCE_RULE( opacityactive, intToStr );
+ LINEEDIT_FORCE_RULE( opacityinactive, intToStr );
+ LINEEDIT_SET_RULE( shortcut, );
+ COMBOBOX_FORCE_RULE( fsplevel, );
+ COMBOBOX_FORCE_RULE( moveresizemode, moveresizeToCombo );
+ COMBOBOX_FORCE_RULE( type, typeToCombo );
+ CHECKBOX_FORCE_RULE( ignoreposition, );
+ LINEEDIT_FORCE_RULE( minsize, sizeToStr );
+ LINEEDIT_FORCE_RULE( maxsize, sizeToStr );
+ CHECKBOX_FORCE_RULE( strictgeometry, );
+ CHECKBOX_FORCE_RULE( disableglobalshortcuts, );
+ }
+
+#undef GENERIC_RULE
+#undef CHECKBOX_SET_RULE
+#undef LINEEDIT_SET_RULE
+#undef COMBOBOX_SET_RULE
+#undef CHECKBOX_FORCE_RULE
+#undef LINEEDIT_FORCE_RULE
+#undef COMBOBOX_FORCE_RULE
+
+#define GENERIC_RULE( var, func, Type, type, uimethod ) \
+ if( enable_##var->isChecked()) \
+ { \
+ rules->var##rule = combo_to_##type##_rule[ rule_##var->currentItem() ]; \
+ rules->var = func( var->uimethod()); \
+ } \
+ else \
+ rules->var##rule = Rules::Unused##Type##Rule;
+
+#define CHECKBOX_SET_RULE( var, func ) GENERIC_RULE( var, func, Set, set, isChecked )
+#define LINEEDIT_SET_RULE( var, func ) GENERIC_RULE( var, func, Set, set, text )
+#define COMBOBOX_SET_RULE( var, func ) GENERIC_RULE( var, func, Set, set, currentItem )
+#define CHECKBOX_FORCE_RULE( var, func ) GENERIC_RULE( var, func, Force, force, isChecked )
+#define LINEEDIT_FORCE_RULE( var, func ) GENERIC_RULE( var, func, Force, force, text )
+#define COMBOBOX_FORCE_RULE( var, func ) GENERIC_RULE( var, func, Force, force, currentItem )
+
+Rules* RulesWidget::rules() const
+ {
+ Rules* rules = new Rules();
+ rules->description = description->text();
+ rules->wmclass = wmclass->text().utf8();
+ rules->wmclasscomplete = whole_wmclass->isChecked();
+ rules->wmclassmatch = static_cast< Rules::StringMatch >( wmclass_match->currentItem());
+ rules->windowrole = role->text().utf8();
+ rules->windowrolematch = static_cast< Rules::StringMatch >( role_match->currentItem());
+ rules->types = 0;
+ bool all_types = true;
+ for( unsigned int i = 0;
+ i < types->count();
+ ++i )
+ if( !types->isSelected( i ))
+ all_types = false;
+ if( all_types ) // if all types are selected, use AllTypesMask (for future expansion)
+ rules->types = NET::AllTypesMask;
+ else
+ {
+ rules->types |= types->isSelected( 0 ) ? NET::NormalMask : 0;
+ rules->types |= types->isSelected( 1 ) ? NET::DialogMask : 0;
+ rules->types |= types->isSelected( 2 ) ? NET::UtilityMask : 0;
+ rules->types |= types->isSelected( 3 ) ? NET::DockMask : 0;
+ rules->types |= types->isSelected( 4 ) ? NET::ToolbarMask : 0;
+ rules->types |= types->isSelected( 5 ) ? NET::MenuMask : 0;
+ rules->types |= types->isSelected( 6 ) ? NET::SplashMask : 0;
+ rules->types |= types->isSelected( 7 ) ? NET::DesktopMask : 0;
+ rules->types |= types->isSelected( 8 ) ? NET::OverrideMask : 0;
+ rules->types |= types->isSelected( 9 ) ? NET::TopMenuMask : 0;
+ }
+ rules->title = title->text();
+ rules->titlematch = static_cast< Rules::StringMatch >( title_match->currentItem());
+ rules->extrarole = extra->text().utf8();
+ rules->extrarolematch = static_cast< Rules::StringMatch >( extra_match->currentItem());
+ rules->clientmachine = machine->text().utf8();
+ rules->clientmachinematch = static_cast< Rules::StringMatch >( machine_match->currentItem());
+ LINEEDIT_SET_RULE( position, strToPosition );
+ LINEEDIT_SET_RULE( size, strToSize );
+ COMBOBOX_SET_RULE( desktop, comboToDesktop );
+ CHECKBOX_SET_RULE( maximizehoriz, );
+ CHECKBOX_SET_RULE( maximizevert, );
+ CHECKBOX_SET_RULE( minimize, );
+ CHECKBOX_SET_RULE( shade, );
+ CHECKBOX_SET_RULE( fullscreen, );
+ COMBOBOX_FORCE_RULE( placement, comboToPlacement );
+ CHECKBOX_SET_RULE( above, );
+ CHECKBOX_SET_RULE( below, );
+ CHECKBOX_SET_RULE( noborder, );
+ CHECKBOX_SET_RULE( skiptaskbar, );
+ CHECKBOX_SET_RULE( skippager, );
+ CHECKBOX_FORCE_RULE( acceptfocus, );
+ CHECKBOX_FORCE_RULE( closeable, );
+ LINEEDIT_FORCE_RULE( opacityactive, strToInt );
+ LINEEDIT_FORCE_RULE( opacityinactive, strToInt );
+ LINEEDIT_SET_RULE( shortcut, );
+ COMBOBOX_FORCE_RULE( fsplevel, );
+ COMBOBOX_FORCE_RULE( moveresizemode, comboToMoveResize );
+ COMBOBOX_FORCE_RULE( type, comboToType );
+ CHECKBOX_FORCE_RULE( ignoreposition, );
+ LINEEDIT_FORCE_RULE( minsize, strToSize );
+ LINEEDIT_FORCE_RULE( maxsize, strToSize );
+ CHECKBOX_FORCE_RULE( strictgeometry, );
+ CHECKBOX_FORCE_RULE( disableglobalshortcuts, );
+ return rules;
+ }
+
+#undef GENERIC_RULE
+#undef CHECKBOX_SET_RULE
+#undef LINEEDIT_SET_RULE
+#undef COMBOBOX_SET_RULE
+#undef CHECKBOX_FORCE_RULE
+#undef LINEEDIT_FORCE_RULE
+#undef COMBOBOX_FORCE_RULE
+
+#define STRING_MATCH_COMBO( type ) \
+void RulesWidget::type##MatchChanged() \
+ { \
+ edit_reg_##type->setEnabled( type##_match->currentItem() == Rules::RegExpMatch ); \
+ type->setEnabled( type##_match->currentItem() != Rules::UnimportantMatch ); \
+ }
+
+STRING_MATCH_COMBO( wmclass )
+STRING_MATCH_COMBO( role )
+STRING_MATCH_COMBO( title )
+STRING_MATCH_COMBO( extra )
+STRING_MATCH_COMBO( machine )
+
+#undef STRING_MATCH_COMBO
+
+void RulesWidget::detectClicked()
+ {
+ assert( detect_dlg == NULL );
+ detect_dlg = new DetectDialog;
+ connect( detect_dlg, SIGNAL( detectionDone( bool )), this, SLOT( detected( bool )));
+ detect_dlg->detect( 0 );
+ }
+
+void RulesWidget::detected( bool ok )
+ {
+ if( ok )
+ {
+ wmclass->setText( detect_dlg->selectedClass());
+ wmclass_match->setCurrentItem( Rules::ExactMatch );
+ wmclassMatchChanged(); // grrr
+ whole_wmclass->setChecked( detect_dlg->selectedWholeClass());
+ role->setText( detect_dlg->selectedRole());
+ role_match->setCurrentItem( detect_dlg->selectedRole().isEmpty()
+ ? Rules::UnimportantMatch : Rules::ExactMatch );
+ roleMatchChanged();
+ if( detect_dlg->selectedWholeApp())
+ {
+ for( unsigned int i = 0;
+ i < types->count();
+ ++i )
+ types->setSelected( i, true );
+ }
+ else
+ {
+ NET::WindowType type = detect_dlg->selectedType();
+ for( unsigned int i = 0;
+ i < types->count();
+ ++i )
+ types->setSelected( i, false );
+ types->setSelected( typeToCombo( type ), true );
+ }
+ title->setText( detect_dlg->selectedTitle());
+ title_match->setCurrentItem( detect_dlg->titleMatch());
+ titleMatchChanged();
+ machine->setText( detect_dlg->selectedMachine());
+ machine_match->setCurrentItem( Rules::UnimportantMatch );
+ machineMatchChanged();
+ // prefill values from to window to settings which already set
+ const KWin::WindowInfo& info = detect_dlg->windowInfo();
+ prefillUnusedValues( info );
+ }
+ delete detect_dlg;
+ detect_dlg = NULL;
+ detect_dlg_ok = ok;
+ }
+
+#define GENERIC_PREFILL( var, func, info, uimethod ) \
+ if( !enable_##var->isChecked()) \
+ { \
+ var->uimethod( func( info )); \
+ }
+
+#define CHECKBOX_PREFILL( var, func, info ) GENERIC_PREFILL( var, func, info, setChecked )
+#define LINEEDIT_PREFILL( var, func, info ) GENERIC_PREFILL( var, func, info, setText )
+#define COMBOBOX_PREFILL( var, func, info ) GENERIC_PREFILL( var, func, info, setCurrentItem )
+
+void RulesWidget::prefillUnusedValues( const KWin::WindowInfo& info )
+ {
+ LINEEDIT_PREFILL( position, positionToStr, info.frameGeometry().topLeft() );
+ LINEEDIT_PREFILL( size, sizeToStr, info.frameGeometry().size() );
+ COMBOBOX_PREFILL( desktop, desktopToCombo, info.desktop() );
+ CHECKBOX_PREFILL( maximizehoriz,, info.state() & NET::MaxHoriz );
+ CHECKBOX_PREFILL( maximizevert,, info.state() & NET::MaxVert );
+ CHECKBOX_PREFILL( minimize,, info.isMinimized() );
+ CHECKBOX_PREFILL( shade,, info.state() & NET::Shaded );
+ CHECKBOX_PREFILL( fullscreen,, info.state() & NET::FullScreen );
+ //COMBOBOX_PREFILL( placement, placementToCombo );
+ CHECKBOX_PREFILL( above,, info.state() & NET::KeepAbove );
+ CHECKBOX_PREFILL( below,, info.state() & NET::KeepBelow );
+ // noborder is only internal KWin information, so let's guess
+ CHECKBOX_PREFILL( noborder,, info.frameGeometry() == info.geometry() );
+ CHECKBOX_PREFILL( skiptaskbar,, info.state() & NET::SkipTaskbar );
+ CHECKBOX_PREFILL( skippager,, info.state() & NET::SkipPager );
+ //CHECKBOX_PREFILL( acceptfocus, );
+ //CHECKBOX_PREFILL( closeable, );
+ LINEEDIT_PREFILL( opacityactive, intToStr, 100 /*get the actual opacity somehow*/);
+ LINEEDIT_PREFILL( opacityinactive, intToStr, 100 /*get the actual opacity somehow*/);
+ //LINEEDIT_PREFILL( shortcut, );
+ //COMBOBOX_PREFILL( fsplevel, );
+ //COMBOBOX_PREFILL( moveresizemode, moveresizeToCombo );
+ COMBOBOX_PREFILL( type, typeToCombo, info.windowType( SUPPORTED_WINDOW_TYPES_MASK ) );
+ //CHECKBOX_PREFILL( ignoreposition, );
+ LINEEDIT_PREFILL( minsize, sizeToStr, info.frameGeometry().size() );
+ LINEEDIT_PREFILL( maxsize, sizeToStr, info.frameGeometry().size() );
+ //CHECKBOX_PREFILL( strictgeometry, );
+ //CHECKBOX_PREFILL( disableglobalshortcuts, );
+ }
+
+#undef GENERIC_PREFILL
+#undef CHECKBOX_PREFILL
+#undef LINEEDIT_PREFILL
+#undef COMBOBOX_PREFILL
+
+bool RulesWidget::finalCheck()
+ {
+ if( description->text().isEmpty())
+ {
+ if( !wmclass->text().isEmpty())
+ description->setText( i18n( "Settings for %1" ).arg( wmclass->text()));
+ else
+ description->setText( i18n( "Unnamed entry" ));
+ }
+ bool all_types = true;
+ for( unsigned int i = 0;
+ i < types->count();
+ ++i )
+ if( !types->isSelected( i ))
+ all_types = false;
+ if( wmclass_match->currentItem() == Rules::UnimportantMatch && all_types )
+ {
+ if( KMessageBox::warningContinueCancel( topLevelWidget(),
+ i18n( "You have specified the window class as unimportant.\n"
+ "This means the settings will possibly apply to windows from all applications. "
+ "If you really want to create a generic setting, it is recommended you at least "
+ "limit the window types to avoid special window types." )) != KMessageBox::Continue )
+ return false;
+ }
+ return true;
+ }
+
+void RulesWidget::prepareWindowSpecific( WId window )
+ {
+ tabs->setCurrentPage( 2 ); // geometry tab, skip tabs for window identification
+ KWin::WindowInfo info( window, -1U, -1U ); // read everything
+ prefillUnusedValues( info );
+ }
+
+void RulesWidget::shortcutEditClicked()
+ {
+ EditShortcutDialog dlg( topLevelWidget());
+ dlg.setShortcut( shortcut->text());
+ if( dlg.exec() == QDialog::Accepted )
+ shortcut->setText( dlg.shortcut());
+ }
+
+RulesDialog::RulesDialog( QWidget* parent, const char* name )
+: KDialogBase( parent, name, true, i18n( "Edit Window-Specific Settings" ), Ok | Cancel )
+ {
+ widget = new RulesWidget( this );
+ setMainWidget( widget );
+ }
+
+// window is set only for Alt+F3/Window-specific settings, because the dialog
+// is then related to one specific window
+Rules* RulesDialog::edit( Rules* r, WId window, bool show_hints )
+ {
+ rules = r;
+ widget->setRules( rules );
+ if( window != 0 )
+ widget->prepareWindowSpecific( window );
+ if( show_hints )
+ QTimer::singleShot( 0, this, SLOT( displayHints()));
+ exec();
+ return rules;
+ }
+
+void RulesDialog::displayHints()
+ {
+ QString str = "<qt><p>";
+ str += i18n( "This configuration dialog allows altering settings only for the selected window"
+ " or application. Find the setting you want to affect, enable the setting using the checkbox,"
+ " select in what way the setting should be affected and to which value." );
+#if 0 // maybe later
+ str += "</p><p>" + i18n( "Consult the documentation for more details." );
+#endif
+ str += "</p></qt>";
+ KMessageBox::information( this, str, QString::null, "displayhints" );
+ }
+
+void RulesDialog::accept()
+ {
+ if( !widget->finalCheck())
+ return;
+ rules = widget->rules();
+ KDialogBase::accept();
+ }
+
+EditShortcut::EditShortcut( QWidget* parent, const char* name )
+: EditShortcutBase( parent, name )
+ {
+ }
+
+void EditShortcut::editShortcut()
+ {
+ ShortcutDialog dlg( KShortcut( shortcut->text()), topLevelWidget());
+ if( dlg.exec() == QDialog::Accepted )
+ shortcut->setText( dlg.shortcut().toString());
+ }
+
+void EditShortcut::clearShortcut()
+ {
+ shortcut->setText( "" );
+ }
+
+EditShortcutDialog::EditShortcutDialog( QWidget* parent, const char* name )
+: KDialogBase( parent, name, true, i18n( "Edit Shortcut" ), Ok | Cancel )
+ {
+ widget = new EditShortcut( this );
+ setMainWidget( widget );
+ }
+
+void EditShortcutDialog::setShortcut( const QString& cut )
+ {
+ widget->shortcut->setText( cut );
+ }
+
+QString EditShortcutDialog::shortcut() const
+ {
+ return widget->shortcut->text();
+ }
+
+ShortcutDialog::ShortcutDialog( const KShortcut& cut, QWidget* parent, const char* name )
+ : KShortcutDialog( cut, false /*TODO???*/, parent, name )
+ {
+ }
+
+void ShortcutDialog::accept()
+ {
+ for( int i = 0;
+ ;
+ ++i )
+ {
+ KKeySequence seq = shortcut().seq( i );
+ if( seq.isNull())
+ break;
+ if( seq.key( 0 ) == Key_Escape )
+ {
+ reject();
+ return;
+ }
+ if( seq.key( 0 ) == Key_Space )
+ { // clear
+ setShortcut( KShortcut());
+ KShortcutDialog::accept();
+ return;
+ }
+ if( seq.key( 0 ).modFlags() == 0 )
+ { // no shortcuts without modifiers
+ KShortcut cut = shortcut();
+ cut.setSeq( i, KKeySequence());
+ setShortcut( cut );
+ return;
+ }
+ }
+ KShortcutDialog::accept();
+ }
+
+} // namespace
+
+#include "ruleswidget.moc"