diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | 4aed2c8219774f5d797760606b8489a92ddc5163 (patch) | |
tree | 3f8c130f7d269626bf6a9447407ef6c35954426a /kwin/kcmkwin/kwinrules/ruleswidget.cpp | |
download | tdebase-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.cpp | 803 |
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" |