GUI for rules (=window specific settings). Have fun figuring out how it

works, because I haven't written any kind of docs for it yet, and
the most important button doesn't work yet either (yes, that one that
has it written on it). I just hope the GUI doesn't suck too much, because
I'm really bad at such things.

svn path=/trunk/kdebase/kwin/; revision=322524
This commit is contained in:
Luboš Luňák 2004-06-21 16:25:24 +00:00
parent 3932c8051b
commit 36b64e3897
18 changed files with 3425 additions and 8 deletions

View file

@ -1 +1 @@
SUBDIRS = kwinoptions kwindecoration
SUBDIRS = kwinoptions kwindecoration kwinrules

View file

@ -1,5 +1,3 @@
# kdebase/kcontrol/kwm
METASOURCES = AUTO
INCLUDES = $(all_includes)

View file

@ -0,0 +1,14 @@
METASOURCES = AUTO
AM_CPPFLAGS = $(all_includes) -DKCMRULES
kde_module_LTLIBRARIES = kcm_kwinrules.la
kcm_kwinrules_la_SOURCES = main.cpp ruleswidget.cpp ruleslist.cpp kwinsrc.cpp \
ruleswidgetbase.ui ruleslistbase.ui
kcm_kwinrules_la_LDFLAGS = -module -avoid-version $(all_libraries) -no-undefined
kcm_kwinrules_la_LIBADD = $(LIB_KDEUI)
messages:
$(XGETTEXT) *.cpp -o $(podir)/kcmkwm.pot
xdg_apps_DATA = kwinrules.desktop

View file

@ -0,0 +1,17 @@
[Desktop Entry]
Encoding=UTF-8
Icon=kcmkwm
Type=Application
Exec=kcmshell kwinrules
DocPath=kcontrol/windowmanagement/index.html
X-KDE-ModuleType=Library
X-KDE-Library=kwinrules
X-KDE-FactoryName=kwinrules
Name=Window-specific Settings
Comment=Configure settings specifically for a window
Keywords=size,position,state,window behavior,windows,specific,workarounds,remember,rules
Categories=Qt;KDE;X-KDE-settings-desktop

View file

@ -0,0 +1,7 @@
// Include some code from kwin core in order to avoid
// double implementation.
#include "ruleslist.h"
#include "../../rules.cpp"
#include "../../placement.cpp"
#include "../../options.cpp"

View file

@ -0,0 +1,99 @@
/*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "main.h"
#include <kglobal.h>
#include <qlayout.h>
#include <klocale.h>
#include <kapplication.h>
#include <dcopclient.h>
#include <kaboutdata.h>
#include "ruleslist.h"
extern "C"
KCModule *create_kwinrules( QWidget *parent, const char *name )
{
//CT there's need for decision: kwm or kwin?
KGlobal::locale()->insertCatalogue( "kcmkwm" );
return new KWinInternal::KCMRules( parent, name );
}
namespace KWinInternal
{
KCMRules::KCMRules( QWidget *parent, const char *name )
: KCModule( parent, name )
, config( "kwinrulesrc" )
{
QVBoxLayout *layout = new QVBoxLayout( this );
widget = new KCMRulesList( this );
layout->addWidget( widget );
connect( widget, SIGNAL( changed( bool )), SLOT( moduleChanged( bool )));
}
void KCMRules::load()
{
config.reparseConfiguration();
widget->load();
emit KCModule::changed( false );
}
void KCMRules::save()
{
widget->save();
emit KCModule::changed( false );
// Send signal to kwin
config.sync();
if( !kapp->dcopClient()->isAttached())
kapp->dcopClient()->attach();
kapp->dcopClient()->send("kwin*", "", "reconfigure()", "");
}
void KCMRules::defaults()
{
widget->defaults();
}
QString KCMRules::quickHelp() const
{
return i18n("<h1>Window-specific Settings</h1> Here you can customize window settings specifically only"
" for some windows."
" <p>Please note that this configuration will not take effect if you do not use"
" KWin as your window manager. If you do use a different window manager, please refer to its documentation"
" for how to customize window behavior.");
}
const KAboutData* KCMRules::aboutData() const
{
KAboutData *about = new KAboutData(I18N_NOOP( "kcmkwinrules" ),
I18N_NOOP( "Window-specific Settings Configuration Module" ),
0, 0, KAboutData::License_GPL, I18N_NOOP( "(c) 2004 KWin and KControl Authors" ));
about->addAuthor("Lubos Lunak",0,"l.lunak@kde.org");
return about;
}
void KCMRules::moduleChanged( bool state )
{
emit KCModule::changed( state );
}
}
#include "main.moc"

54
kcmkwin/kwinrules/main.h Normal file
View file

@ -0,0 +1,54 @@
/*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __MAIN_H__
#define __MAIN_H__
#include <kcmodule.h>
#include <kconfig.h>
class KConfig;
class KAboutData;
namespace KWinInternal
{
class KCMRulesList;
class KCMRules
: public KCModule
{
Q_OBJECT
public:
KCMRules( QWidget *parent, const char *name );
virtual void load();
virtual void save();
virtual void defaults();
virtual QString quickHelp() const;
virtual const KAboutData* aboutData() const;
protected slots:
void moduleChanged( bool state );
private:
KCMRulesList* widget;
KConfig config;
};
} // namespace
#endif

View file

@ -0,0 +1,193 @@
/*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "ruleslist.h"
#include <klistbox.h>
#include <kpushbutton.h>
#include <assert.h>
#include <kdebug.h>
#include <kconfig.h>
#include "ruleswidget.h"
namespace KWinInternal
{
KCMRulesList::KCMRulesList( QWidget* parent, const char* name )
: KCMRulesListBase( parent, name )
{
// connect both current/selected, so that current==selected (stupid QListBox :( )
connect( rules_listbox, SIGNAL( currentChanged( QListBoxItem* )),
SLOT( activeChanged( QListBoxItem*)));
connect( rules_listbox, SIGNAL( selectionChanged( QListBoxItem* )),
SLOT( activeChanged( QListBoxItem*)));
connect( new_button, SIGNAL( clicked()),
SLOT( newClicked()));
connect( modify_button, SIGNAL( clicked()),
SLOT( modifyClicked()));
connect( delete_button, SIGNAL( clicked()),
SLOT( deleteClicked()));
connect( moveup_button, SIGNAL( clicked()),
SLOT( moveupClicked()));
connect( movedown_button, SIGNAL( clicked()),
SLOT( movedownClicked()));
load();
}
KCMRulesList::~KCMRulesList()
{
for( QValueVector< Rules* >::Iterator it = rules.begin();
it != rules.end();
++it )
delete *it;
rules.clear();
}
void KCMRulesList::activeChanged( QListBoxItem* item )
{
if( item != NULL )
rules_listbox->setSelected( item, true ); // make current==selected
modify_button->setEnabled( item != NULL );
delete_button->setEnabled( item != NULL );
moveup_button->setEnabled( item != NULL && item->prev() != NULL );
movedown_button->setEnabled( item != NULL && item->next() != NULL );
}
void KCMRulesList::newClicked()
{
RulesDialog dlg;
Rules* rule = dlg.edit( NULL );
if( rule == NULL )
return;
int pos = rules_listbox->currentItem() + 1;
rules_listbox->insertItem( rule->description, pos );
rules_listbox->setSelected( pos, true );
rules.insert( rules.begin() + pos, rule );
emit changed( true );
}
void KCMRulesList::modifyClicked()
{
int pos = rules_listbox->currentItem();
assert( pos != -1 );
RulesDialog dlg;
Rules* rule = dlg.edit( rules[ pos ] );
if( rule == rules[ pos ] )
return;
delete rules[ pos ];
rules[ pos ] = rule;
rules_listbox->changeItem( rule->description, pos );
emit changed( true );
}
void KCMRulesList::deleteClicked()
{
int pos = rules_listbox->currentItem();
assert( pos != -1 );
rules_listbox->removeItem( pos );
rules.erase( rules.begin() + pos );
emit changed( true );
}
void KCMRulesList::moveupClicked()
{
int pos = rules_listbox->currentItem();
assert( pos != -1 );
if( pos > 0 )
{
QString txt = rules_listbox->text( pos );
rules_listbox->removeItem( pos );
rules_listbox->insertItem( txt, pos - 1 );
rules_listbox->setSelected( pos - 1, true );
Rules* rule = rules[ pos ];
rules[ pos ] = rules[ pos - 1 ];
rules[ pos - 1 ] = rule;
}
emit changed( true );
}
void KCMRulesList::movedownClicked()
{
int pos = rules_listbox->currentItem();
assert( pos != -1 );
if( pos < int( rules_listbox->count()) - 1 )
{
QString txt = rules_listbox->text( pos );
rules_listbox->removeItem( pos );
rules_listbox->insertItem( txt, pos + 1 );
rules_listbox->setSelected( pos + 1, true );
Rules* rule = rules[ pos ];
rules[ pos ] = rules[ pos + 1 ];
rules[ pos + 1 ] = rule;
}
emit changed( true );
}
void KCMRulesList::load()
{
rules_listbox->clear();
for( QValueVector< Rules* >::Iterator it = rules.begin();
it != rules.end();
++it )
delete *it;
rules.clear();
KConfig cfg( "kwinrulesrc", true );
cfg.setGroup( "General" );
int count = cfg.readNumEntry( "count" );
rules.reserve( count );
for( int i = 1;
i <= count;
++i )
{
cfg.setGroup( QString::number( i ));
Rules* rule = new Rules( cfg );
rules.append( rule );
rules_listbox->insertItem( rule->description );
}
if( rules.count() > 0 )
rules_listbox->setSelected( 0, true );
else
activeChanged( NULL );
}
void KCMRulesList::save()
{
KConfig cfg( "kwinrulesrc" );
cfg.setGroup( "General" );
cfg.writeEntry( "count", rules.count());
int i = 1;
for( QValueVector< Rules* >::ConstIterator it = rules.begin();
it != rules.end();
++it )
{
cfg.setGroup( QString::number( i ));
(*it)->write( cfg );
++i;
}
}
void KCMRulesList::defaults()
{
load();
}
} // namespace
#include "ruleslist.moc"

View file

@ -0,0 +1,59 @@
/*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __RULESLIST_H__
#define __RULESLIST_H__
#include "ruleslistbase.h"
#include <qvaluevector.h>
#include "../../rules.h"
class QListBoxItem;
namespace KWinInternal
{
class KCMRulesList
: public KCMRulesListBase
{
Q_OBJECT
public:
KCMRulesList( QWidget* parent = NULL, const char* name = NULL );
virtual ~KCMRulesList();
void load();
void save();
void defaults();
signals:
void changed( bool );
private slots:
void newClicked();
void modifyClicked();
void deleteClicked();
void moveupClicked();
void movedownClicked();
void activeChanged( QListBoxItem* );
private:
QValueVector< Rules* > rules;
};
} // namespace
#endif

View file

@ -0,0 +1,123 @@
<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
<class>KWinInternal::KCMRulesListBase</class>
<widget class="QWidget">
<property name="name">
<cstring>Form1</cstring>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>600</width>
<height>480</height>
</rect>
</property>
<property name="caption">
<string>Form1</string>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout4</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="KListBox">
<property name="name">
<cstring>rules_listbox</cstring>
</property>
</widget>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout3</cstring>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="KPushButton">
<property name="name">
<cstring>new_button</cstring>
</property>
<property name="text">
<string>&amp;New...</string>
</property>
<property name="accel">
<string>Alt+N</string>
</property>
</widget>
<widget class="KPushButton">
<property name="name">
<cstring>modify_button</cstring>
</property>
<property name="text">
<string>&amp;Modify...</string>
</property>
<property name="accel">
<string>Alt+M</string>
</property>
</widget>
<widget class="KPushButton">
<property name="name">
<cstring>delete_button</cstring>
</property>
<property name="text">
<string>Delete</string>
</property>
<property name="accel">
<string></string>
</property>
</widget>
<widget class="KPushButton">
<property name="name">
<cstring>moveup_button</cstring>
</property>
<property name="text">
<string>Move &amp;up</string>
</property>
<property name="accel">
<string>Alt+U</string>
</property>
</widget>
<widget class="KPushButton">
<property name="name">
<cstring>movedown_button</cstring>
</property>
<property name="text">
<string>Move &amp;down</string>
</property>
<property name="accel">
<string>Alt+D</string>
</property>
</widget>
<spacer>
<property name="name">
<cstring>spacer1</cstring>
</property>
<property name="orientation">
<enum>Vertical</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</vbox>
</widget>
</hbox>
</widget>
</hbox>
</widget>
<layoutdefaults spacing="6" margin="11"/>
<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/>
</UI>

View file

@ -0,0 +1,464 @@
/*
* 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., 675 Mass Ave, Cambridge, MA 02139, 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 "../../rules.h"
namespace KWinInternal
{
#define SETUP_ENABLE( var ) \
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()));
RulesWidget::RulesWidget( QWidget* parent, const char* name )
: RulesWidgetBase( parent, name )
{
// window tabs have enable signals done in designer
// geometry tab
SETUP_ENABLE( position );
SETUP_ENABLE( size );
SETUP_ENABLE( desktop );
SETUP_ENABLE( maximizehoriz );
SETUP_ENABLE( maximizevert );
SETUP_ENABLE( minimize );
SETUP_ENABLE( shade );
SETUP_ENABLE( fullscreen );
SETUP_ENABLE( placement );
// preferences tab
SETUP_ENABLE( above );
SETUP_ENABLE( below );
SETUP_ENABLE( noborder );
SETUP_ENABLE( skiptaskbar );
SETUP_ENABLE( skippager );
SETUP_ENABLE( acceptfocus );
SETUP_ENABLE( closeable );
// workarounds tab
SETUP_ENABLE( fsplevel );
SETUP_ENABLE( moveresizemode );
SETUP_ENABLE( type );
SETUP_ENABLE( ignoreposition );
SETUP_ENABLE( minsize );
SETUP_ENABLE( maxsize );
KWinModule module;
int i;
for( i = 1;
i <= module.numberOfDesktops();
++i )
desktop->insertItem( QString::number( i ).rightJustify( 2 ) + ":" + module.desktopName( i ));
for(;
i <= 16;
++i )
desktop->insertItem( QString::number( i ).rightJustify( 2 ));
desktop->insertItem( i18n( "All Desktops" ));
}
#undef ENABLE_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 )
// 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 )
#undef UPDATE_ENABLE_SLOT
static const int set_rule_to_combo[] =
{
0, // Unused
0, // Don't Affect
3, // Force
1, // Apply
2, // Remember
};
static const Rules::SetRule combo_to_set_rule[] =
{
( Rules::SetRule )Rules::DontAffect,
( Rules::SetRule )Rules::Apply,
( Rules::SetRule )Rules::Remember,
( Rules::SetRule )Rules::Force
};
static const int force_rule_to_combo[] =
{
0, // Unused
0, // Don't Affect
1 // Force
};
static const Rules::ForceRule combo_to_force_rule[] =
{
( Rules::ForceRule )Rules::DontAffect,
( Rules::ForceRule )Rules::Force
};
static QString positionToStr( const QPoint& p )
{
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 )
{
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());
}
static int desktopToCombo( int desktop )
{
if( desktop >= 1 && desktop <= 16 )
return desktop - 1;
return 16; // on all desktops
}
static int comboToDesktop( int val )
{
if( val == 16 )
return NET::OnAllDesktops;
return val + 1;
}
static int placementToCombo( Placement::Policy placement )
{
static const int conv[] =
{
1, // NoPlacement
0, // Default
5, // Random
2, // Smart
3, // Cascade
4, // Centered
6, // ZeroCornered
7, // UnderMouse
8 // OnMainWindow
};
return conv[ placement ];
}
static Placement::Policy comboToPlacement( int val )
{
static const Placement::Policy conv[] =
{
Placement::Default,
Placement::NoPlacement,
Placement::Smart,
Placement::Cascade,
Placement::Centered,
Placement::Random,
Placement::ZeroCornered,
Placement::UnderMouse,
Placement::OnMainWindow
};
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 );
reg_wmclass->setChecked( rules->wmclassregexp );
role->setText( rules->windowrole );
reg_role->setChecked( rules->windowroleregexp );
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 );
reg_title->setChecked( rules->titleregexp );
extra->setText( rules->extrarole );
reg_extra->setChecked( rules->extraroleregexp );
machine->setText( rules->clientmachine );
reg_machine->setChecked( rules->clientmachineregexp );
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, );
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 );
}
#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->wmclassregexp = reg_wmclass->isChecked();
rules->windowrole = role->text().utf8();
rules->windowroleregexp = reg_role->isChecked();
rules->types = 0;
bool all_types = true;
for( int i = 0;
i <= 9;
++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->titleregexp = reg_title->isChecked();
rules->extrarole = extra->text().utf8();
rules->extraroleregexp = reg_extra->isChecked();
rules->clientmachine = machine->text().utf8();
rules->clientmachineregexp = reg_machine->isChecked();
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, );
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 );
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
RulesDialog::RulesDialog( QWidget* parent, const char* name )
: KDialogBase( parent, name, true, "", Ok | Cancel )
{
widget = new RulesWidget( this );
setMainWidget( widget );
}
Rules* RulesDialog::edit( Rules* r )
{
rules = r;
widget->setRules( rules );
exec();
return rules;
}
void RulesDialog::accept()
{
KDialogBase::accept();
rules = widget->rules();
}
} // namespace
#include "ruleswidget.moc"

View file

@ -0,0 +1,86 @@
/*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __RULESWIDGET_H__
#define __RULESWIDGET_H__
#include <kdialogbase.h>
#include "ruleswidgetbase.h"
namespace KWinInternal
{
class Rules;
class RulesWidget
: public RulesWidgetBase
{
Q_OBJECT
public:
RulesWidget( QWidget* parent = NULL, const char* name = NULL );
void setRules( Rules* r );
Rules* rules() const;
signals:
void changed( bool state );
private slots:
// geometry tab
void updateEnableposition();
void updateEnablesize();
void updateEnabledesktop();
void updateEnablemaximizehoriz();
void updateEnablemaximizevert();
void updateEnableminimize();
void updateEnableshade();
void updateEnablefullscreen();
void updateEnableplacement();
// preferences tab
void updateEnableabove();
void updateEnablebelow();
void updateEnablenoborder();
void updateEnableskiptaskbar();
void updateEnableskippager();
void updateEnableacceptfocus();
void updateEnablecloseable();
// workarounds tab
void updateEnablefsplevel();
void updateEnablemoveresizemode();
void updateEnabletype();
void updateEnableignoreposition();
void updateEnableminsize();
void updateEnablemaxsize();
};
class RulesDialog
: public KDialogBase
{
Q_OBJECT
public:
RulesDialog( QWidget* parent = NULL, const char* name = NULL );
Rules* edit( Rules* r );
protected:
virtual void accept();
private:
RulesWidget* widget;
Rules* rules;
};
} // namespace
#endif

File diff suppressed because it is too large Load diff

View file

@ -11,6 +11,8 @@ License. See the file "COPYING" for the exact licensing terms.
#include "options.h"
#ifndef KCMRULES
#include <qpalette.h>
#include <qpixmap.h>
#include <kapplication.h>
@ -21,9 +23,13 @@ License. See the file "COPYING" for the exact licensing terms.
#include "client.h"
#endif
namespace KWinInternal
{
#ifndef KCMRULES
Options::Options()
: electric_borders( 0 ),
electric_border_delay(0)
@ -251,6 +257,7 @@ bool Options::checkIgnoreFocusStealing( const Client* c )
{
return ignoreFocusStealingClasses.contains(QString::fromLatin1(c->resourceClass()));
}
#endif
Options::MoveResizeMode Options::stringToMoveResizeMode( const QString& s )
{

View file

@ -10,17 +10,23 @@ You can Freely distribute this program under the GNU General Public
License. See the file "COPYING" for the exact licensing terms.
******************************************************************/
#include <qrect.h>
#include "placement.h"
#include <qrect.h>
#include <assert.h>
#ifndef KCMRULES
#include "workspace.h"
#include "client.h"
#include "options.h"
#include "placement.h"
#include "rules.h"
#endif
namespace KWinInternal
{
#ifndef KCMRULES
Placement::Placement(Workspace* w)
{
m_WorkspacePtr = w;
@ -480,6 +486,9 @@ QRect Placement::checkArea( const Client* c, const QRect& area )
return area;
}
#endif
Placement::Policy Placement::policyFromString( const QString& policy, bool no_special )
{
if( policy == "NoPlacement" )
@ -512,6 +521,8 @@ const char* Placement::policyToString( Policy policy )
}
#ifndef KCMRULES
// ********************
// Workspace
// ********************
@ -743,4 +754,6 @@ void Workspace::placeSmart(Client* c, const QRect& area)
initPositioning->placeSmart( c, area );
}
#endif
} // namespace

View file

@ -17,8 +17,10 @@ License. See the file "COPYING" for the exact licensing terms.
#include <ksimpleconfig.h>
#include <qfile.h>
#ifndef KCMRULES
#include "client.h"
#include "workspace.h"
#endif
namespace KWinInternal
{
@ -70,6 +72,8 @@ Rules::Rules( const QString& str, bool temporary )
file.close();
KSimpleConfig cfg( file.name());
readFromCfg( cfg );
if( description.isEmpty())
description = "temporary";
file.unlink();
}
@ -108,6 +112,7 @@ static int limit0to4( int i ) { return QMAX( 0, QMIN( 4, i )); }
void Rules::readFromCfg( KConfig& cfg )
{
description = cfg.readEntry( "description" );
wmclass = cfg.readEntry( "wmclass" ).lower().latin1();
wmclassregexp = cfg.readBoolEntry( "wmclassregexp" );
wmclasscomplete = cfg.readBoolEntry( "wmclasscomplete" );
@ -199,6 +204,7 @@ void Rules::readFromCfg( KConfig& cfg )
void Rules::write( KConfig& cfg ) const
{
cfg.writeEntry( "description", description );
// always write wmclass
cfg.writeEntry( "wmclass", ( const char* )wmclass );
cfg.writeEntry( "wmclassregexp", wmclassregexp );
@ -261,6 +267,7 @@ NET::WindowType Rules::readType( KConfig& cfg, const QString& key )
return NET::Unknown;
}
#ifndef KCMRULES
bool Rules::match( const Client* c ) const
{
if( types != NET::AllTypesMask )
@ -496,14 +503,16 @@ bool Rules::discardTemporary( bool force )
}
return false;
}
#endif
#ifndef NDEBUG
kdbgstream& operator<<( kdbgstream& stream, const Rules* r )
{
return stream << "[" << r->wmclass << "/" << r->windowrole << "/" << r->title << "]";
return stream << "[" << r->description << "]";
}
#endif
#ifndef KCMRULES
void WindowRules::discardTemporary()
{
QValueVector< Rules* >::Iterator it2 = rules.begin();
@ -658,7 +667,8 @@ WindowRules Workspace::findWindowRules( const Client* c, bool ignore_temporary )
void Workspace::editWindowRules( Client* c )
{
// TODO
// TODO this should try to select or create a rule specific for the window
KApplication::kdeinitExec( "kcmshell", "kwinrules" );
}
void Workspace::loadWindowRules()
@ -740,4 +750,6 @@ void Workspace::rulesUpdated()
rulesUpdatedTimer.start( 1000, true );
}
#endif
} // namespace

10
rules.h
View file

@ -30,6 +30,8 @@ namespace KWinInternal
class Client;
class Rules;
#ifndef KCMRULES // only for kwin core
class WindowRules
: public KDecorationDefines
{
@ -66,6 +68,7 @@ class WindowRules
MaximizeMode checkMaximizeHoriz( MaximizeMode mode, bool init ) const;
QValueVector< Rules* > rules;
};
#endif
class Rules
: public KDecorationDefines
@ -75,6 +78,7 @@ class Rules
Rules( KConfig& );
Rules( const QString&, bool temporary );
void write( KConfig& ) const;
#ifndef KCMRULES
bool update( Client* );
bool isTemporary() const;
bool match( const Client* c ) const;
@ -104,6 +108,7 @@ class Rules
bool applyMoveResizeMode( Options::MoveResizeMode& mode ) const;
bool applyCloseable( bool& closeable ) const;
private:
#endif
enum // values are saved to the cfg file
{
Unused = 0,
@ -126,11 +131,14 @@ class Rules
static SetRule readSetRule( KConfig&, const QString& key );
static ForceRule readForceRule( KConfig&, const QString& key );
static NET::WindowType readType( KConfig&, const QString& key );
#ifndef KCMRULES
static bool checkSetRule( SetRule rule, bool init );
static bool checkForceRule( ForceRule rule );
static bool checkSetStop( SetRule rule );
static bool checkForceStop( ForceRule rule );
#endif
int temporary_state; // e.g. for kstart
QString description;
QCString wmclass;
bool wmclassregexp;
bool wmclasscomplete;
@ -190,6 +198,7 @@ class Rules
friend kdbgstream& operator<<( kdbgstream& stream, const Rules* );
};
#ifndef KCMRULES
inline
bool Rules::checkSetRule( SetRule rule, bool init )
{
@ -229,6 +238,7 @@ inline
WindowRules::WindowRules()
{
}
#endif
#ifdef NDEBUG
inline

View file

@ -58,7 +58,7 @@ QPopupMenu* Workspace::clientPopup()
advanced_popup->insertItem( SmallIconSet( "down" ), i18n("Keep &Below Others"), Options::KeepBelowOp );
advanced_popup->insertItem( SmallIconSet( "window_fullscreen" ), i18n("&Fullscreen"), Options::FullScreenOp );
advanced_popup->insertItem( i18n("&No Border"), Options::NoBorderOp );
advanced_popup->insertItem( SmallIconSet( "filesave" ), i18n("&Special Window Rules"), Options::WindowRulesOp );
advanced_popup->insertItem( SmallIconSet( "filesave" ), i18n("&Special Window Settings..."), Options::WindowRulesOp );
popup->insertItem(i18n("Ad&vanced"), advanced_popup );
desk_popup_index = popup->count();