summaryrefslogtreecommitdiffstats
path: root/khotkeys/shared
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 /khotkeys/shared
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 'khotkeys/shared')
-rw-r--r--khotkeys/shared/Makefile.am15
-rw-r--r--khotkeys/shared/action_data.cpp378
-rw-r--r--khotkeys/shared/action_data.h446
-rw-r--r--khotkeys/shared/actions.cpp450
-rw-r--r--khotkeys/shared/actions.h305
-rw-r--r--khotkeys/shared/conditions.cpp504
-rw-r--r--khotkeys/shared/conditions.h296
-rw-r--r--khotkeys/shared/gestures.cpp449
-rw-r--r--khotkeys/shared/gestures.h122
-rw-r--r--khotkeys/shared/input.cpp253
-rw-r--r--khotkeys/shared/input.h87
-rw-r--r--khotkeys/shared/khlistbox.cpp103
-rw-r--r--khotkeys/shared/khlistbox.h64
-rw-r--r--khotkeys/shared/khlistview.cpp122
-rw-r--r--khotkeys/shared/khlistview.h69
-rw-r--r--khotkeys/shared/khotkeysglobal.cpp100
-rw-r--r--khotkeys/shared/khotkeysglobal.h59
-rw-r--r--khotkeys/shared/settings.cpp265
-rw-r--r--khotkeys/shared/settings.h61
-rw-r--r--khotkeys/shared/sound.cpp343
-rw-r--r--khotkeys/shared/sound.h58
-rw-r--r--khotkeys/shared/soundrecorder.cpp86
-rw-r--r--khotkeys/shared/soundrecorder.h62
-rw-r--r--khotkeys/shared/triggers.cpp435
-rw-r--r--khotkeys/shared/triggers.h260
-rw-r--r--khotkeys/shared/voices.cpp303
-rw-r--r--khotkeys/shared/voices.h83
-rw-r--r--khotkeys/shared/voicesignature.cpp422
-rw-r--r--khotkeys/shared/voicesignature.h101
-rw-r--r--khotkeys/shared/windows.cpp376
-rw-r--r--khotkeys/shared/windows.h264
31 files changed, 6941 insertions, 0 deletions
diff --git a/khotkeys/shared/Makefile.am b/khotkeys/shared/Makefile.am
new file mode 100644
index 000000000..4e20f6083
--- /dev/null
+++ b/khotkeys/shared/Makefile.am
@@ -0,0 +1,15 @@
+lib_LTLIBRARIES = libkhotkeys_shared.la
+
+libkhotkeys_shared_la_SOURCES = action_data.cpp khotkeysglobal.cpp triggers.cpp windows.cpp \
+ settings.cpp actions.cpp input.cpp conditions.cpp khlistview.cpp khlistbox.cpp \
+ gestures.cpp voices.cpp voicesignature.cpp sound.cpp soundrecorder.cpp
+libkhotkeys_shared_la_LIBADD = $(LIB_KIO) $(XTESTLIB) -lXext -lX11 $(X_PRE_LIBS)
+libkhotkeys_shared_la_LDFLAGS = $(all_libraries) $(X_LDFLAGS) -version-info 1:0:0 -no-undefined
+
+INCLUDES = $(all_includes)
+
+noinst_HEADERS = action_data.h khotkeysglobal.h triggers.h windows.h actions.h input.h \
+ settings.h conditions.h khlistview.h khlistbox.h gestures.h voices.h \
+ voicesignature.h sound.h soundrecorder.h
+
+METASOURCES = AUTO
diff --git a/khotkeys/shared/action_data.cpp b/khotkeys/shared/action_data.cpp
new file mode 100644
index 000000000..96e3e5559
--- /dev/null
+++ b/khotkeys/shared/action_data.cpp
@@ -0,0 +1,378 @@
+/****************************************************************************
+
+ KHotKeys
+
+ Copyright (C) 1999-2001 Lubos Lunak <l.lunak@kde.org>
+
+ Distributed under the terms of the GNU General Public License version 2.
+
+****************************************************************************/
+
+#define _ACTION_DATA_CPP_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "action_data.h"
+
+#include <kconfig.h>
+
+#include "actions.h"
+
+namespace KHotKeys
+{
+
+// Action_data_base
+
+Action_data_base::Action_data_base( Action_data_group* parent_P, const QString& name_P,
+ const QString& comment_P, Condition_list* conditions_P, bool enabled_P )
+ : _parent( parent_P ), _conditions( conditions_P ), _name( name_P ), _comment( comment_P ),
+ _enabled( enabled_P )
+ {
+ if( parent())
+ parent()->add_child( this );
+ if( _conditions != NULL )
+ _conditions->set_data( this );
+ }
+
+Action_data_base::Action_data_base( KConfig& cfg_P, Action_data_group* parent_P )
+ : _parent( parent_P )
+ {
+ QString save_cfg_group = cfg_P.group();
+ _name = cfg_P.readEntry( "Name" );
+ _comment = cfg_P.readEntry( "Comment" );
+ _enabled = cfg_P.readBoolEntry( "Enabled", true );
+ cfg_P.setGroup( save_cfg_group + "Conditions" );
+ _conditions = new Condition_list( cfg_P, this );
+ cfg_P.setGroup( save_cfg_group );
+ if( parent())
+ parent()->add_child( this );
+ }
+
+Action_data_base::~Action_data_base()
+ {
+// kdDebug( 1217 ) << "~Action_data_base() :" << this << endl;
+ if( parent())
+ parent()->remove_child( this );
+ delete _conditions;
+ }
+
+void Action_data_base::cfg_write( KConfig& cfg_P ) const
+ {
+ cfg_P.writeEntry( "Type", "ERROR" ); // derived classes should call with their type
+ cfg_P.writeEntry( "Name", name());
+ cfg_P.writeEntry( "Comment", comment());
+ cfg_P.writeEntry( "Enabled", enabled( true ));
+ QString save_cfg_group = cfg_P.group();
+ cfg_P.setGroup( save_cfg_group + "Conditions" );
+ assert( conditions() != NULL );
+ conditions()->cfg_write( cfg_P );
+ cfg_P.setGroup( save_cfg_group );
+ }
+
+
+Action_data_base* Action_data_base::create_cfg_read( KConfig& cfg_P, Action_data_group* parent_P )
+ {
+ QString type = cfg_P.readEntry( "Type" );
+ if( type == "ACTION_DATA_GROUP" )
+ {
+ if( cfg_P.readBoolEntry( "AllowMerge", false ))
+ {
+ for( Action_data_group::Iterator it = parent_P->first_child();
+ it;
+ ++it )
+ {
+ if( Action_data_group* existing = dynamic_cast< Action_data_group* >( *it ))
+ {
+ if( cfg_P.readEntry( "Name" ) == existing->name())
+ return existing;
+ }
+ }
+ }
+ return new Action_data_group( cfg_P, parent_P );
+ }
+ if( type == "GENERIC_ACTION_DATA" )
+ return new Generic_action_data( cfg_P, parent_P );
+ if( type == "COMMAND_URL_SHORTCUT_ACTION_DATA" )
+ return new Command_url_shortcut_action_data( cfg_P, parent_P );
+ if( type == "MENUENTRY_SHORTCUT_ACTION_DATA" )
+ return new Menuentry_shortcut_action_data( cfg_P, parent_P );
+ if( type == "DCOP_SHORTCUT_ACTION_DATA" )
+ return new Dcop_shortcut_action_data( cfg_P, parent_P );
+ if( type == "KEYBOARD_INPUT_SHORTCUT_ACTION_DATA" )
+ return new Keyboard_input_shortcut_action_data( cfg_P, parent_P );
+ if( type == "KEYBOARD_INPUT_GESTURE_ACTION_DATA" )
+ return new Keyboard_input_gesture_action_data( cfg_P, parent_P );
+ if( type == "ACTIVATE_WINDOW_SHORTCUT_ACTION_DATA" )
+ return new Activate_window_shortcut_action_data( cfg_P, parent_P );
+ kdWarning( 1217 ) << "Unknown Action_data_base type read from cfg file\n";
+ return NULL;
+ }
+
+bool Action_data_base::cfg_is_enabled( KConfig& cfg_P )
+ {
+ return cfg_P.readBoolEntry( "Enabled", true );
+ }
+
+void Action_data_base::reparent( Action_data_group* new_parent_P )
+ {
+ if( parent())
+ parent()->remove_child( this );
+ _parent = new_parent_P;
+ if( parent())
+ parent()->add_child( this );
+ }
+
+bool Action_data_base::enabled( bool ignore_group_P ) const
+ {
+ if( ignore_group_P )
+ return _enabled;
+ else
+ return _enabled && ( parent() == NULL || parent()->enabled( false ));
+ }
+
+bool Action_data_base::conditions_match() const
+ {
+ return ( conditions() ? conditions()->match() : true )
+ && ( parent() ? parent()->conditions_match() : true );
+ }
+
+// Action_data_group
+
+Action_data_group::Action_data_group( KConfig& cfg_P, Action_data_group* parent_P )
+ : Action_data_base( cfg_P, parent_P )
+ {
+ unsigned int system_group_tmp = cfg_P.readUnsignedNumEntry( "SystemGroup", 0 );
+ if( system_group_tmp >= SYSTEM_MAX )
+ system_group_tmp = 0;
+ _system_group = static_cast< system_group_t >( system_group_tmp );
+ }
+
+void Action_data_group::cfg_write( KConfig& cfg_P ) const
+ {
+ Action_data_base::cfg_write( cfg_P );
+ cfg_P.writeEntry( "SystemGroup", system_group());
+ cfg_P.writeEntry( "Type", "ACTION_DATA_GROUP" );
+ }
+
+void Action_data_group::update_triggers()
+ {
+ for( Action_data_group::Iterator it = first_child();
+ it;
+ ++it )
+ ( *it )->update_triggers();
+ }
+
+// Action_data
+
+Action_data::Action_data( KConfig& cfg_P, Action_data_group* parent_P )
+ : Action_data_base( cfg_P, parent_P )
+ {
+ QString save_cfg_group = cfg_P.group();
+ cfg_P.setGroup( save_cfg_group + "Triggers" );
+ _triggers = new Trigger_list( cfg_P, this );
+ cfg_P.setGroup( save_cfg_group + "Actions" );
+ _actions = new Action_list( cfg_P, this );
+ cfg_P.setGroup( save_cfg_group );
+ }
+
+Action_data::~Action_data()
+ {
+// kdDebug( 1217 ) << "~Action_data" << this << endl;
+ delete _triggers;
+ delete _actions;
+ // CHECKME jeste remove z parenta ?
+ }
+
+void Action_data::cfg_write( KConfig& cfg_P ) const
+ {
+ Action_data_base::cfg_write( cfg_P );
+ QString save_cfg_group = cfg_P.group();
+ cfg_P.setGroup( save_cfg_group + "Triggers" );
+ triggers()->cfg_write( cfg_P );
+ cfg_P.setGroup( save_cfg_group + "Actions" );
+ actions()->cfg_write( cfg_P );
+ cfg_P.setGroup( save_cfg_group );
+ }
+
+void Action_data::execute()
+ {
+ for( Action_list::Iterator it( *_actions );
+ it;
+ ++it )
+ it.current()->execute();
+// CHECKME nebo nejak zpozdeni ?
+ }
+
+void Action_data::add_trigger( Trigger* trigger_P )
+ {
+ _triggers->append( trigger_P );
+ }
+
+void Action_data::add_triggers( Trigger_list* triggers_P )
+ {
+ for( Trigger_list::Iterator it = *triggers_P;
+ it;
+ ++it )
+ _triggers->append( *it );
+ triggers_P->setAutoDelete( false );
+ delete triggers_P;
+ }
+
+void Action_data::set_triggers( Trigger_list* triggers_P )
+ {
+ assert( _triggers == NULL );
+ _triggers = triggers_P;
+ }
+
+void Action_data::add_action( Action* action_P, Action* after_P )
+ {
+ int index = 0;
+ for( Action_list::Iterator it = *_actions;
+ it;
+ ++it )
+ {
+ ++index;
+ if( *it == after_P )
+ break;
+ }
+ _actions->insert( index, action_P );
+ }
+
+void Action_data::add_actions( Action_list* actions_P, Action* after_P )
+ {
+ int index = 0;
+ for( Action_list::Iterator it = *_actions;
+ it;
+ ++it )
+ {
+ ++index;
+ if( *it == after_P )
+ break;
+ }
+ for( Action_list::Iterator it = *actions_P;
+ it;
+ ++it )
+ _actions->insert( index++, *it );
+ actions_P->setAutoDelete( false );
+ delete actions_P;
+ }
+
+void Action_data::set_actions( Action_list* actions_P )
+ {
+ assert( _actions == NULL );
+ _actions = actions_P;
+ }
+
+void Action_data::update_triggers()
+ {
+ bool activate = conditions_match() && enabled( false );
+ kdDebug( 1217 ) << "Update triggers: " << name() << ":" << activate << endl;
+ for( Trigger_list::Iterator it = ( *triggers());
+ it;
+ ++it )
+ ( *it )->activate( activate );
+ }
+
+// Generic_action_data
+
+void Generic_action_data::cfg_write( KConfig& cfg_P ) const
+ {
+ base::cfg_write( cfg_P );
+ cfg_P.writeEntry( "Type", "GENERIC_ACTION_DATA" );
+ }
+
+// Command_url_shortcut_action_data
+
+Command_url_shortcut_action_data::Command_url_shortcut_action_data( Action_data_group* parent_P,
+ const QString& name_P, const QString& comment_P,
+ const KShortcut& shortcut_P, const QString& command_url_P, bool enabled_P )
+ : Simple_action_data< Shortcut_trigger, Command_url_action >( parent_P, name_P,
+ comment_P, enabled_P )
+ {
+ set_action( new Command_url_action( this, command_url_P ));
+ set_trigger( new Shortcut_trigger( this, shortcut_P ));
+ }
+
+template<> KDE_EXPORT
+void Simple_action_data< Shortcut_trigger, Command_url_action >
+ ::cfg_write( KConfig& cfg_P ) const
+ {
+ base::cfg_write( cfg_P );
+ cfg_P.writeEntry( "Type", "COMMAND_URL_SHORTCUT_ACTION_DATA" );
+ }
+
+// Menuentry_shortcut_action_data
+
+Menuentry_shortcut_action_data::Menuentry_shortcut_action_data( Action_data_group* parent_P,
+ const QString& name_P, const QString& comment_P,
+ const KShortcut& shortcut_P, const QString& menuentry_P, bool enabled_P )
+ : Simple_action_data< Shortcut_trigger, Menuentry_action >( parent_P, name_P,
+ comment_P, enabled_P )
+ {
+ set_action( new Menuentry_action( this, menuentry_P ));
+ set_trigger( new Shortcut_trigger( this, shortcut_P ));
+ }
+
+template<> KDE_EXPORT
+void Simple_action_data< Shortcut_trigger, Menuentry_action >
+ ::cfg_write( KConfig& cfg_P ) const
+ {
+ base::cfg_write( cfg_P );
+ cfg_P.writeEntry( "Type", "MENUENTRY_SHORTCUT_ACTION_DATA" );
+ }
+
+// Dcop_shortcut_action_data
+
+template<> KDE_EXPORT
+void Simple_action_data< Shortcut_trigger, Dcop_action >
+ ::cfg_write( KConfig& cfg_P ) const
+ {
+ base::cfg_write( cfg_P );
+ cfg_P.writeEntry( "Type", "DCOP_SHORTCUT_ACTION_DATA" );
+ }
+
+// Keyboard_input_shortcut_action_data
+
+template<> KDE_EXPORT
+void Simple_action_data< Shortcut_trigger, Keyboard_input_action >
+ ::cfg_write( KConfig& cfg_P ) const
+ {
+ base::cfg_write( cfg_P );
+ cfg_P.writeEntry( "Type", "KEYBOARD_INPUT_SHORTCUT_ACTION_DATA" );
+ }
+
+// Activate_window_shortcut_action_data
+
+template<> KDE_EXPORT
+void Simple_action_data< Shortcut_trigger, Activate_window_action >
+ ::cfg_write( KConfig& cfg_P ) const
+ {
+ base::cfg_write( cfg_P );
+ cfg_P.writeEntry( "Type", "ACTIVATE_WINDOW_SHORTCUT_ACTION_DATA" );
+ }
+
+// Keyboard_input_gesture_action_data
+
+void Keyboard_input_gesture_action_data::set_action( Keyboard_input_action* action_P )
+ {
+ Action_list* tmp = new Action_list( "Keyboard_input_gesture_action_data" );
+ tmp->append( action_P );
+ set_actions( tmp );
+ }
+
+const Keyboard_input_action* Keyboard_input_gesture_action_data::action() const
+ {
+ if( actions() == NULL ) // CHECKME tohle poradne zkontrolovat
+ return NULL;
+ return static_cast< Keyboard_input_action* >( const_cast< Action_list* >( actions())->first());
+ }
+
+void Keyboard_input_gesture_action_data::cfg_write( KConfig& cfg_P ) const
+ {
+ base::cfg_write( cfg_P );
+ cfg_P.writeEntry( "Type", "KEYBOARD_INPUT_GESTURE_ACTION_DATA" );
+ }
+
+} // namespace KHotKeys
diff --git a/khotkeys/shared/action_data.h b/khotkeys/shared/action_data.h
new file mode 100644
index 000000000..9d6018c2c
--- /dev/null
+++ b/khotkeys/shared/action_data.h
@@ -0,0 +1,446 @@
+/****************************************************************************
+
+ KHotKeys
+
+ Copyright (C) 1999-2001 Lubos Lunak <l.lunak@kde.org>
+
+ Distributed under the terms of the GNU General Public License version 2.
+
+****************************************************************************/
+
+#ifndef _ACTION_DATA_H_
+#define _ACTION_DATA_H_
+
+#include <assert.h>
+#include <qstring.h>
+#include <qptrlist.h>
+
+#include <kdebug.h>
+
+class KConfig;
+
+#include "khotkeysglobal.h"
+
+#include "windows.h"
+#include "conditions.h"
+#include "triggers.h"
+#include "actions.h"
+
+namespace KHotKeys
+{
+
+class Action_data_group;
+
+class KDE_EXPORT Action_data_base
+ {
+ public:
+ Action_data_base( Action_data_group* parent_P, const QString& name_P,
+ const QString& comment_P, Condition_list* condition_P, bool enabled_P );
+ Action_data_base( KConfig& cfg_P, Action_data_group* parent_P );
+ virtual ~Action_data_base();
+ virtual void cfg_write( KConfig& cfg_P ) const = 0;
+ const Condition_list* conditions() const;
+ Action_data_group* parent() const;
+ void reparent( Action_data_group* new_parent_P );
+ virtual void update_triggers() = 0;
+ bool conditions_match() const;
+ const QString& name() const;
+ void set_name( const QString& name_P );
+ const QString& comment() const;
+ bool enabled( bool ignore_group_P ) const;
+ static Action_data_base* create_cfg_read( KConfig& cfg_P, Action_data_group* parent_P );
+ static bool cfg_is_enabled( KConfig& cfg_P );
+ protected:
+ void set_conditions( Condition_list* conditions_P );
+ private:
+ Action_data_group* _parent;
+ Condition_list* _conditions;
+ QString _name;
+ QString _comment;
+ bool _enabled; // is not really important, only used in conf. module and when reading cfg. file
+ KHOTKEYS_DISABLE_COPY( Action_data_base );
+ };
+
+class KDE_EXPORT Action_data_group
+ : public Action_data_base
+ {
+ public:
+ enum system_group_t { SYSTEM_NONE, SYSTEM_MENUENTRIES,
+ SYSTEM_ROOT, /* last one*/ SYSTEM_MAX }; // don't remove entries
+ Action_data_group( Action_data_group* parent_P, const QString& name_P,
+ const QString& comment_P, Condition_list* conditions_P, system_group_t system_group_P,
+ bool enabled_P );
+ Action_data_group( KConfig& cfg_P, Action_data_group* parent_P );
+ virtual ~Action_data_group();
+ virtual void update_triggers();
+ virtual void cfg_write( KConfig& cfg_P ) const;
+ typedef QPtrListIterator< Action_data_base > Iterator; // CHECKME neni const :(
+ Iterator first_child() const;
+ bool is_system_group() const;
+ system_group_t system_group() const;
+ using Action_data_base::set_conditions; // make public
+ protected:
+ QPtrList< Action_data_base > list;
+ system_group_t _system_group; // e.g. menuedit entries, can't be deleted or renamed
+ friend class Action_data_base; // CHECKME
+ void add_child( Action_data_base* child_P );
+ void remove_child( Action_data_base* child_P );
+ };
+
+// this one represents a "whole" action, i.e. triggers, resulting actions, etc.
+class KDE_EXPORT Action_data
+ : public Action_data_base
+ {
+ typedef Action_data_base base;
+ public:
+ Action_data( Action_data_group* parent_P, const QString& name_P,
+ const QString& comment_P, Trigger_list* triggers_P, Condition_list* conditions_P,
+ Action_list* actions_P, bool enabled_P = true );
+ Action_data( KConfig& cfg_P, Action_data_group* parent_P );
+ virtual ~Action_data();
+ virtual void update_triggers();
+ virtual void cfg_write( KConfig& cfg_P ) const = 0;
+ virtual void execute();
+ const Trigger_list* triggers() const;
+ const Action_list* actions() const;
+ protected:
+ virtual void add_trigger( Trigger* trigger_P );
+ virtual void add_triggers(
+ Trigger_list* triggers_P ); // Trigger_list instance will be deleted
+ virtual void set_triggers( Trigger_list* triggers_P );
+ virtual void add_action( Action* action_P, Action* after_P = NULL );
+ virtual void add_actions( Action_list* actions_P,
+ Action* after_P = NULL ); // Action_list will be deleted
+ virtual void set_actions( Action_list* actions_P );
+ private:
+ Trigger_list* _triggers;
+ Action_list* _actions;
+#if 0
+ action_type_t _type;
+ static const char* const types[];
+#endif
+ };
+
+class KDE_EXPORT Generic_action_data
+ : public Action_data
+ {
+ typedef Action_data base;
+ public:
+ Generic_action_data( Action_data_group* parent_P, const QString& name_P,
+ const QString& comment_P, Trigger_list* triggers_P, Condition_list* conditions_P,
+ Action_list* actions_P, bool enabled_P = true );
+ Generic_action_data( KConfig& cfg_P, Action_data_group* parent_P );
+ virtual void cfg_write( KConfig& cfg_P ) const;
+ using Action_data_base::set_conditions; // make public
+ using Action_data::add_trigger; // make public
+ using Action_data::add_triggers; // make public
+ using Action_data::set_triggers; // make public
+ using Action_data::add_action; // make public
+ using Action_data::add_actions; // make public
+ using Action_data::set_actions; // make public
+ };
+
+template< typename T, typename A >
+class KDE_EXPORT Simple_action_data
+ : public Action_data
+ {
+ typedef Action_data base;
+ public:
+ Simple_action_data( Action_data_group* parent_P, const QString& name_P,
+ const QString& comment_P, bool enabled_P = true );
+ Simple_action_data( KConfig& cfg_P, Action_data_group* parent_P );
+ const A* action() const;
+ const T* trigger() const;
+ // CHECKME kontrola, ze se dava jen jedna akce ?
+ void set_action( A* action_P );
+ void set_trigger( T* trigger_P );
+ virtual void cfg_write( KConfig& cfg_P ) const;
+ };
+
+class KDE_EXPORT Command_url_shortcut_action_data
+ : public Simple_action_data< Shortcut_trigger, Command_url_action >
+ {
+ typedef Simple_action_data< Shortcut_trigger, Command_url_action > base;
+ public:
+ Command_url_shortcut_action_data( Action_data_group* parent_P, const QString& name_P,
+ const QString& comment_P, bool enabled_P = true );
+ Command_url_shortcut_action_data( Action_data_group* parent_P, const QString& name_P,
+ const QString& comment_P, const KShortcut& shortcut_P, const QString& command_url_P,
+ bool enabled_P = true );
+ Command_url_shortcut_action_data( KConfig& cfg_P, Action_data_group* parent_P );
+ };
+
+class KDE_EXPORT Menuentry_shortcut_action_data
+ : public Simple_action_data< Shortcut_trigger, Menuentry_action >
+ {
+ typedef Simple_action_data< Shortcut_trigger, Menuentry_action > base;
+ public:
+ Menuentry_shortcut_action_data( Action_data_group* parent_P, const QString& name_P,
+ const QString& comment_P, bool enabled_P = true );
+ Menuentry_shortcut_action_data( Action_data_group* parent_P, const QString& name_P,
+ const QString& comment_P, const KShortcut& shortcut_P, const QString& command_url_P,
+ bool enabled_P = true );
+ Menuentry_shortcut_action_data( KConfig& cfg_P, Action_data_group* parent_P );
+ };
+
+typedef Simple_action_data< Shortcut_trigger, Dcop_action > Dcop_shortcut_action_data;
+typedef Simple_action_data< Shortcut_trigger, Keyboard_input_action >
+ Keyboard_input_shortcut_action_data;
+typedef Simple_action_data< Shortcut_trigger, Activate_window_action >
+ Activate_window_shortcut_action_data;
+
+class KDE_EXPORT Keyboard_input_gesture_action_data
+ : public Action_data
+ {
+ typedef Action_data base;
+ public:
+ Keyboard_input_gesture_action_data( Action_data_group* parent_P, const QString& name_P,
+ const QString& comment_P, bool enabled_P = true );
+ Keyboard_input_gesture_action_data( KConfig& cfg_P, Action_data_group* parent_P );
+ const Keyboard_input_action* action() const;
+ // CHECKME kontrola, ze se dava jen jedna akce ?
+ void set_action( Keyboard_input_action* action_P );
+ enum { NUM_TRIGGERS = 3 }; // needs changing code elsewhere
+ using Action_data::set_triggers; // make public // CHECKME kontrola poctu?
+ virtual void cfg_write( KConfig& cfg_P ) const;
+ };
+
+
+//***************************************************************************
+// Inline
+//***************************************************************************
+
+// Action_data_base
+
+inline
+const Condition_list* Action_data_base::conditions() const
+ {
+// assert( _conditions != NULL );
+ return _conditions;
+ }
+
+inline
+void Action_data_base::set_conditions( Condition_list* conditions_P )
+ {
+ assert( _conditions == NULL );
+ _conditions = conditions_P;
+ }
+
+inline
+Action_data_group* Action_data_base::parent() const
+ {
+ return _parent;
+ }
+
+inline
+void Action_data_base::set_name( const QString& name_P )
+ {
+ _name = name_P;
+ }
+
+inline
+const QString& Action_data_base::name() const
+ {
+ return _name;
+ }
+
+inline
+const QString& Action_data_base::comment() const
+ {
+ return _comment;
+ }
+
+// Action_data_group
+
+inline
+Action_data_group::Action_data_group( Action_data_group* parent_P, const QString& name_P,
+ const QString& comment_P, Condition_list* conditions_P, system_group_t system_group_P,
+ bool enabled_P )
+ : Action_data_base( parent_P, name_P, comment_P, conditions_P, enabled_P ),
+ _system_group( system_group_P )
+ {
+ }
+
+inline
+Action_data_group::~Action_data_group()
+ {
+// kdDebug( 1217 ) << "~Action_data_group() :" << list.count() << endl;
+ while( list.first())
+ delete list.first();
+ }
+
+inline
+Action_data_group::Iterator Action_data_group::first_child() const
+ {
+ return Iterator( list );
+ }
+
+inline
+bool Action_data_group::is_system_group() const
+ {
+ return _system_group != SYSTEM_NONE;
+ }
+
+inline
+Action_data_group::system_group_t Action_data_group::system_group() const
+ {
+ return _system_group;
+ }
+
+inline
+void Action_data_group::add_child( Action_data_base* child_P )
+ {
+ list.append( child_P ); // CHECKME tohle asi znemozni je mit nejak rucne serazene
+ }
+
+inline
+void Action_data_group::remove_child( Action_data_base* child_P )
+ {
+ list.removeRef( child_P ); // is not auto-delete
+ }
+
+// Action_data
+
+inline
+Action_data::Action_data( Action_data_group* parent_P, const QString& name_P,
+ const QString& comment_P, Trigger_list* triggers_P, Condition_list* conditions_P,
+ Action_list* actions_P, bool enabled_P )
+ : Action_data_base( parent_P, name_P, comment_P, conditions_P, enabled_P ),
+ _triggers( triggers_P ), _actions( actions_P )
+ {
+ }
+
+inline
+const Trigger_list* Action_data::triggers() const
+ {
+// assert( _triggers != NULL );
+ return _triggers;
+ }
+
+inline
+const Action_list* Action_data::actions() const
+ {
+// assert( _actions != NULL );
+ return _actions;
+ }
+
+// Generic_action_data
+
+inline
+Generic_action_data::Generic_action_data( Action_data_group* parent_P, const QString& name_P,
+ const QString& comment_P, Trigger_list* triggers_P, Condition_list* conditions_P,
+ Action_list* actions_P, bool enabled_P )
+ : Action_data( parent_P, name_P, comment_P, triggers_P, conditions_P, actions_P, enabled_P )
+ {
+ }
+
+inline
+Generic_action_data::Generic_action_data( KConfig& cfg_P, Action_data_group* parent_P )
+ : Action_data( cfg_P, parent_P )
+ { // CHECKME do nothing ?
+ }
+
+// Simple_action_data
+
+template< typename T, typename A >
+inline
+Simple_action_data< T, A >::Simple_action_data( Action_data_group* parent_P,
+ const QString& name_P, const QString& comment_P, bool enabled_P )
+ : Action_data( parent_P, name_P, comment_P, NULL,
+ new Condition_list( "", this ), NULL, enabled_P )
+ {
+ }
+
+template< typename T, typename A >
+inline
+Simple_action_data< T, A >::Simple_action_data( KConfig& cfg_P, Action_data_group* parent_P )
+ : Action_data( cfg_P, parent_P )
+ { // CHECKME nothing ?
+ }
+
+template< typename T, typename A >
+void Simple_action_data< T, A >::set_action( A* action_P )
+ {
+ Action_list* tmp = new Action_list( "Simple_action_data" );
+ tmp->append( action_P );
+ set_actions( tmp );
+ }
+
+template< typename T, typename A >
+void Simple_action_data< T, A >::set_trigger( T* trigger_P )
+ {
+ Trigger_list* tmp = new Trigger_list( "Simple_action" );
+ tmp->append( trigger_P );
+ set_triggers( tmp );
+ }
+
+template< typename T, typename A >
+const A* Simple_action_data< T, A >::action() const
+ {
+ if( actions() == NULL || actions()->count() == 0 ) // CHECKME tohle poradne zkontrolovat
+ return NULL;
+ return static_cast< A* >( const_cast< Action_list* >( actions())->first());
+ }
+
+template< typename T, typename A >
+const T* Simple_action_data< T, A >::trigger() const
+ {
+ if( triggers() == NULL || triggers()->count() == 0 ) // CHECKME tohle poradne zkontrolovat
+ return NULL;
+ return static_cast< T* >( const_cast< Trigger_list* >( triggers())->first());
+ }
+
+// Command_url_action_data
+
+inline
+Command_url_shortcut_action_data::Command_url_shortcut_action_data( Action_data_group* parent_P,
+ const QString& name_P, const QString& comment_P, bool enabled_P )
+ : Simple_action_data< Shortcut_trigger, Command_url_action >( parent_P, name_P,
+ comment_P, enabled_P )
+ {
+ }
+
+inline
+Command_url_shortcut_action_data::Command_url_shortcut_action_data( KConfig& cfg_P,
+ Action_data_group* parent_P )
+ : Simple_action_data< Shortcut_trigger, Command_url_action >( cfg_P, parent_P )
+ {
+ }
+
+// Menuentry_action_data
+
+inline
+Menuentry_shortcut_action_data::Menuentry_shortcut_action_data( Action_data_group* parent_P,
+ const QString& name_P, const QString& comment_P, bool enabled_P )
+ : Simple_action_data< Shortcut_trigger, Menuentry_action >( parent_P, name_P,
+ comment_P, enabled_P )
+ {
+ }
+
+inline
+Menuentry_shortcut_action_data::Menuentry_shortcut_action_data( KConfig& cfg_P,
+ Action_data_group* parent_P )
+ : Simple_action_data< Shortcut_trigger, Menuentry_action >( cfg_P, parent_P )
+ {
+ }
+
+// Keyboard_input_gesture_action_data
+
+inline
+Keyboard_input_gesture_action_data::Keyboard_input_gesture_action_data(
+ Action_data_group* parent_P, const QString& name_P, const QString& comment_P, bool enabled_P )
+ : Action_data( parent_P, name_P, comment_P, NULL,
+ new Condition_list( "", this ), NULL, enabled_P )
+ {
+ }
+
+inline
+Keyboard_input_gesture_action_data::Keyboard_input_gesture_action_data( KConfig& cfg_P,
+ Action_data_group* parent_P )
+ : Action_data( cfg_P, parent_P )
+ { // CHECKME nothing ?
+ }
+
+} // namespace KHotKeys
+
+#endif
diff --git a/khotkeys/shared/actions.cpp b/khotkeys/shared/actions.cpp
new file mode 100644
index 000000000..144a277af
--- /dev/null
+++ b/khotkeys/shared/actions.cpp
@@ -0,0 +1,450 @@
+/****************************************************************************
+
+ KHotKeys
+
+ Copyright (C) 1999-2001 Lubos Lunak <l.lunak@kde.org>
+
+ Distributed under the terms of the GNU General Public License version 2.
+
+****************************************************************************/
+
+#define _ACTIONS_CPP_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "actions.h"
+
+#include <krun.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kurifilter.h>
+#include <kglobal.h>
+#include <kstandarddirs.h>
+#include <kapplication.h>
+#include <dcopclient.h>
+#include <kdesktopfile.h>
+#include <klocale.h>
+#include <kaccel.h>
+#include <kservice.h>
+#include <kprocess.h>
+
+#include "windows.h"
+#include "action_data.h"
+
+#include <X11/X.h>
+
+namespace KHotKeys
+{
+
+// Action
+
+Action* Action::create_cfg_read( KConfig& cfg_P, Action_data* data_P )
+ {
+ QString type = cfg_P.readEntry( "Type" );
+ if( type == "COMMAND_URL" )
+ return new Command_url_action( cfg_P, data_P );
+ if( type == "MENUENTRY" )
+ return new Menuentry_action( cfg_P, data_P );
+ if( type == "DCOP" )
+ return new Dcop_action( cfg_P, data_P );
+ if( type == "KEYBOARD_INPUT" )
+ return new Keyboard_input_action( cfg_P, data_P );
+ if( type == "ACTIVATE_WINDOW" )
+ return new Activate_window_action( cfg_P, data_P );
+ kdWarning( 1217 ) << "Unknown Action type read from cfg file\n";
+ return NULL;
+ }
+
+void Action::cfg_write( KConfig& cfg_P ) const
+ {
+ cfg_P.writeEntry( "Type", "ERROR" ); // derived classes should call with their type
+ }
+
+// Action_list
+
+Action_list::Action_list( KConfig& cfg_P, Action_data* data_P )
+ : QPtrList< Action >()
+ {
+ setAutoDelete( true );
+ QString save_cfg_group = cfg_P.group();
+ int cnt = cfg_P.readNumEntry( "ActionsCount", 0 );
+ for( int i = 0;
+ i < cnt;
+ ++i )
+ {
+ cfg_P.setGroup( save_cfg_group + QString::number( i ));
+ Action* action = Action::create_cfg_read( cfg_P, data_P );
+ if( action )
+ append( action );
+ }
+ cfg_P.setGroup( save_cfg_group );
+ }
+
+void Action_list::cfg_write( KConfig& cfg_P ) const
+ {
+ QString save_cfg_group = cfg_P.group();
+ int i = 0;
+ for( Iterator it( *this );
+ it;
+ ++it, ++i )
+ {
+ cfg_P.setGroup( save_cfg_group + QString::number( i ));
+ it.current()->cfg_write( cfg_P );
+ }
+ cfg_P.setGroup( save_cfg_group );
+ cfg_P.writeEntry( "ActionsCount", i );
+ }
+
+// Command_url_action
+
+Command_url_action::Command_url_action( KConfig& cfg_P, Action_data* data_P )
+ : Action( cfg_P, data_P )
+ {
+ _command_url = cfg_P.readEntry( "CommandURL" );
+ }
+
+void Command_url_action::cfg_write( KConfig& cfg_P ) const
+ {
+ base::cfg_write( cfg_P );
+ cfg_P.writeEntry( "CommandURL", command_url());
+ cfg_P.writeEntry( "Type", "COMMAND_URL" ); // overwrites value set in base::cfg_write()
+ }
+
+void Command_url_action::execute()
+ {
+ if( command_url().isEmpty())
+ return;
+ KURIFilterData uri;
+ QString cmd = command_url();
+ static bool sm_ready = false;
+ if( !sm_ready )
+ {
+ kapp->propagateSessionManager();
+ sm_ready = true;
+ }
+// int space_pos = command_url().find( ' ' );
+// if( command_url()[ 0 ] != '\'' && command_url()[ 0 ] != '"' && space_pos > -1
+// && command_url()[ space_pos - 1 ] != '\\' )
+// cmd = command_url().left( space_pos ); // get first 'word'
+ uri.setData( cmd );
+ KURIFilter::self()->filterURI( uri );
+ if( uri.uri().isLocalFile() && !uri.uri().hasRef() )
+ cmd = uri.uri().path();
+ else
+ cmd = uri.uri().url();
+ switch( uri.uriType())
+ {
+ case KURIFilterData::LOCAL_FILE:
+ case KURIFilterData::LOCAL_DIR:
+ case KURIFilterData::NET_PROTOCOL:
+ case KURIFilterData::HELP:
+ {
+ ( void ) new KRun( uri.uri());
+ break;
+ }
+ case KURIFilterData::EXECUTABLE:
+ {
+ if (!kapp->authorize("shell_access"))
+ return;
+ if( !uri.hasArgsAndOptions())
+ {
+ KService::Ptr service = KService::serviceByDesktopName( cmd );
+ if( service != NULL )
+ {
+ KRun::run( *service, KURL::List());
+ break;
+ }
+ }
+ // fall though
+ }
+ case KURIFilterData::SHELL:
+ {
+ if (!kapp->authorize("shell_access"))
+ return;
+ if( !KRun::runCommand(
+ cmd + ( uri.hasArgsAndOptions() ? uri.argsAndOptions() : "" ),
+ cmd, uri.iconName())) {
+ // CHECKME ?
+ }
+ break;
+ }
+ default: // error
+ return;
+ }
+ timeout.start( 1000, true ); // 1sec timeout
+ }
+
+QString Command_url_action::description() const
+ {
+ return i18n( "Command/URL : " ) + command_url();
+ }
+
+Action* Command_url_action::copy( Action_data* data_P ) const
+ {
+ return new Command_url_action( data_P, command_url());
+ }
+
+// Menuentry_action
+
+void Menuentry_action::cfg_write( KConfig& cfg_P ) const
+ {
+ base::cfg_write( cfg_P );
+ cfg_P.writeEntry( "Type", "MENUENTRY" ); // overwrites value set in base::cfg_write()
+ }
+
+KService::Ptr Menuentry_action::service() const
+ {
+ if (!_service)
+ {
+ const_cast<Menuentry_action *>(this)->_service = KService::serviceByStorageId(command_url());
+ }
+ return _service;
+ }
+
+void Menuentry_action::execute()
+ {
+ (void) service();
+ if (!_service)
+ return;
+ KRun::run( *_service, KURL::List());
+ timeout.start( 1000, true ); // 1sec timeout
+ }
+
+QString Menuentry_action::description() const
+ {
+ (void) service();
+ return i18n( "Menuentry : " ) + (_service ? _service->name() : QString::null);
+ }
+
+Action* Menuentry_action::copy( Action_data* data_P ) const
+ {
+ return new Menuentry_action( data_P, command_url());
+ }
+
+// Dcop_action
+
+Dcop_action::Dcop_action( KConfig& cfg_P, Action_data* data_P )
+ : Action( cfg_P, data_P )
+ {
+ app = cfg_P.readEntry( "RemoteApp" );
+ obj = cfg_P.readEntry( "RemoteObj" );
+ call = cfg_P.readEntry( "Call" );
+ args = cfg_P.readEntry( "Arguments" );
+ }
+
+void Dcop_action::cfg_write( KConfig& cfg_P ) const
+ {
+ base::cfg_write( cfg_P );
+ cfg_P.writeEntry( "Type", "DCOP" ); // overwrites value set in base::cfg_write()
+ cfg_P.writeEntry( "RemoteApp", app );
+ cfg_P.writeEntry( "RemoteObj", obj );
+ cfg_P.writeEntry( "Call", call );
+ cfg_P.writeEntry( "Arguments", args );
+ }
+
+void Dcop_action::execute()
+ {
+ if( app.isEmpty() || obj.isEmpty() || call.isEmpty())
+ return;
+ QStringList args_list;
+ QString args_str = args;
+ while( !args_str.isEmpty())
+ {
+ unsigned int pos = 0;
+ while( args_str[ pos ] == ' ' )
+ ++pos;
+ if( args_str[ pos ] == '\"' || args_str[ pos ] == '\'' )
+ {
+ QString val = "";
+ QChar sep = args_str[ pos ];
+ bool skip = false;
+ ++pos;
+ for(;
+ pos < args_str.length();
+ ++pos )
+ {
+ if( args_str[ pos ] == '\\' )
+ {
+ skip = true;
+ continue;
+ }
+ if( !skip && args_str[ pos ] == sep )
+ break;
+ skip = false;
+ val += args_str[ pos ];
+ }
+ if( pos >= args_str.length())
+ return;
+ ++pos;
+ args_str = args_str.mid( pos );
+ args_list.append( val );
+ }
+ else
+ {
+ // one word
+ if( pos != 0 )
+ args_str = args_str.mid( pos );
+ int nxt_pos = args_str.find( ' ' );
+ args_list.append( args_str.left( nxt_pos )); // should be ok if nxt_pos is -1
+ args_str = nxt_pos >= 0 ? args_str.mid( nxt_pos ) : "";
+ }
+ }
+ kdDebug( 1217 ) << "DCOP call:" << app << ":" << obj << ":" << call << ":" << args_list << endl;
+ KProcess proc;
+ proc << "dcop" << app << obj << call << args_list;
+ proc.start( KProcess::DontCare );
+ }
+
+QString Dcop_action::description() const
+ {
+ return i18n( "DCOP : " ) + remote_application() + "::" + remote_object() + "::"
+ + called_function();
+ }
+
+Action* Dcop_action::copy( Action_data* data_P ) const
+ {
+ return new Dcop_action( data_P, remote_application(), remote_object(),
+ called_function(), arguments());
+ }
+
+// Keyboard_input_action
+
+Keyboard_input_action::Keyboard_input_action( KConfig& cfg_P, Action_data* data_P )
+ : Action( cfg_P, data_P )
+ {
+ _input = cfg_P.readEntry( "Input" );
+ if( cfg_P.readBoolEntry( "IsDestinationWindow" ))
+ {
+ QString save_cfg_group = cfg_P.group();
+ cfg_P.setGroup( save_cfg_group + "DestinationWindow" );
+ _dest_window = new Windowdef_list( cfg_P );
+ _active_window = false; // ignored with _dest_window set anyway
+ cfg_P.setGroup( save_cfg_group );
+ }
+ else
+ {
+ _dest_window = NULL;
+ _active_window = cfg_P.readBoolEntry( "ActiveWindow" );
+ }
+ }
+
+Keyboard_input_action::~Keyboard_input_action()
+ {
+ delete _dest_window;
+ }
+
+void Keyboard_input_action::cfg_write( KConfig& cfg_P ) const
+ {
+ base::cfg_write( cfg_P );
+ cfg_P.writeEntry( "Type", "KEYBOARD_INPUT" ); // overwrites value set in base::cfg_write()
+ cfg_P.writeEntry( "Input", input());
+ if( dest_window() != NULL )
+ {
+ cfg_P.writeEntry( "IsDestinationWindow", true );
+ QString save_cfg_group = cfg_P.group();
+ cfg_P.setGroup( save_cfg_group + "DestinationWindow" );
+ dest_window()->cfg_write( cfg_P );
+ cfg_P.setGroup( save_cfg_group );
+ }
+ else
+ cfg_P.writeEntry( "IsDestinationWindow", false );
+ cfg_P.writeEntry( "ActiveWindow", _active_window );
+ }
+
+void Keyboard_input_action::execute()
+ {
+ if( input().isEmpty())
+ return;
+ Window w = InputFocus;
+ if( dest_window() != NULL )
+ {
+ w = windows_handler->find_window( dest_window());
+ if( w == None )
+ w = InputFocus;
+ }
+ else
+ {
+ if( !_active_window )
+ w = windows_handler->action_window();
+ if( w == None )
+ w = InputFocus;
+ }
+ int last_index = -1, start = 0;
+ while(( last_index = input().find( ':', last_index + 1 )) != -1 ) // find next ';'
+ {
+ QString key = input().mid( start, last_index - start ).stripWhiteSpace();
+ if( key == "Enter" && KKey( key ).keyCodeQt() == 0 )
+ key = "Return"; // CHECKE hack
+ keyboard_handler->send_macro_key( KKey( key ), w );
+ start = last_index + 1;
+ }
+ // and the last one
+ QString key = input().mid( start, input().length()).stripWhiteSpace();
+ if( key == "Enter" && KKey( key ).keyCodeQt() == 0 )
+ key = "Return";
+ keyboard_handler->send_macro_key( KKey( key ), w ); // the rest
+ XFlush( qt_xdisplay());
+ }
+
+QString Keyboard_input_action::description() const
+ {
+ QString tmp = input();
+ tmp.replace( '\n', ' ' );
+ tmp.truncate( 30 );
+ return i18n( "Keyboard input : " ) + tmp;
+ }
+
+Action* Keyboard_input_action::copy( Action_data* data_P ) const
+ {
+ return new Keyboard_input_action( data_P, input(),
+ dest_window() ? dest_window()->copy() : NULL, _active_window );
+ }
+
+// Activate_window_action
+
+Activate_window_action::Activate_window_action( KConfig& cfg_P, Action_data* data_P )
+ : Action( cfg_P, data_P )
+ {
+ QString save_cfg_group = cfg_P.group();
+ cfg_P.setGroup( save_cfg_group + "Window" );
+ _window = new Windowdef_list( cfg_P );
+ cfg_P.setGroup( save_cfg_group );
+ }
+
+Activate_window_action::~Activate_window_action()
+ {
+ delete _window;
+ }
+
+void Activate_window_action::cfg_write( KConfig& cfg_P ) const
+ {
+ base::cfg_write( cfg_P );
+ cfg_P.writeEntry( "Type", "ACTIVATE_WINDOW" ); // overwrites value set in base::cfg_write()
+ QString save_cfg_group = cfg_P.group();
+ cfg_P.setGroup( save_cfg_group + "Window" );
+ window()->cfg_write( cfg_P );
+ cfg_P.setGroup( save_cfg_group );
+ }
+
+void Activate_window_action::execute()
+ {
+ if( window()->match( windows_handler->active_window()))
+ return; // is already active
+ WId win_id = windows_handler->find_window( window());
+ if( win_id != None )
+ windows_handler->activate_window( win_id );
+ }
+
+QString Activate_window_action::description() const
+ {
+ return i18n( "Activate window : " ) + window()->comment();
+ }
+
+Action* Activate_window_action::copy( Action_data* data_P ) const
+ {
+ return new Activate_window_action( data_P, window()->copy());
+ }
+
+} // namespace KHotKeys
diff --git a/khotkeys/shared/actions.h b/khotkeys/shared/actions.h
new file mode 100644
index 000000000..5295d5be9
--- /dev/null
+++ b/khotkeys/shared/actions.h
@@ -0,0 +1,305 @@
+/****************************************************************************
+
+ KHotKeys
+
+ Copyright (C) 1999-2001 Lubos Lunak <l.lunak@kde.org>
+
+ Distributed under the terms of the GNU General Public License version 2.
+
+****************************************************************************/
+
+#ifndef _ACTIONS_H_
+#define _ACTIONS_H_
+
+
+#include <qstring.h>
+#include <qptrlist.h>
+#include <qtimer.h>
+
+#include <kservice.h>
+
+class KConfig;
+
+#include "khotkeysglobal.h"
+
+namespace KHotKeys
+{
+
+class Action_data;
+class Windowdef_list;
+
+// this one is a base for all "real" resulting actions, e.g. running a command,
+// Action_data instances usually contain at least one Action
+class KDE_EXPORT Action
+ {
+ public:
+ Action( Action_data* data_P );
+ Action( KConfig& cfg_P, Action_data* data_P );
+ virtual ~Action();
+ virtual void execute() = 0;
+ virtual QString description() const = 0;
+ virtual void cfg_write( KConfig& cfg_P ) const;
+ virtual Action* copy( Action_data* data_P ) const = 0;
+ static Action* create_cfg_read( KConfig& cfg_P, Action_data* data_P );
+ protected:
+ Action_data* const data;
+ KHOTKEYS_DISABLE_COPY( Action );
+ };
+
+class KDE_EXPORT Action_list
+ : public QPtrList< Action >
+ {
+ public:
+ Action_list( const QString& comment_P ); // CHECKME nebo i data ?
+ Action_list( KConfig& cfg_P, Action_data* data_P );
+ void cfg_write( KConfig& cfg_P ) const;
+ typedef QPtrListIterator< Action > Iterator;
+ const QString& comment() const;
+ private:
+ QString _comment;
+ KHOTKEYS_DISABLE_COPY( Action_list );
+ };
+
+class KDE_EXPORT Command_url_action
+ : public Action
+ {
+ typedef Action base;
+ public:
+ Command_url_action( Action_data* data_P, const QString& command_url_P );
+ Command_url_action( KConfig& cfg_P, Action_data* data_P );
+ virtual void cfg_write( KConfig& cfg_P ) const;
+ virtual void execute();
+ virtual QString description() const;
+ const QString& command_url() const;
+ virtual Action* copy( Action_data* data_P ) const;
+ protected:
+ QTimer timeout;
+ private:
+ QString _command_url;
+ };
+
+class KDE_EXPORT Menuentry_action
+ : public Command_url_action
+ {
+ typedef Command_url_action base;
+ public:
+ Menuentry_action( Action_data* data_P, const QString& menuentry_P );
+ Menuentry_action( KConfig& cfg_P, Action_data* data_P );
+ virtual void cfg_write( KConfig& cfg_P ) const;
+ virtual void execute();
+ virtual QString description() const;
+ virtual Action* copy( Action_data* data_P ) const;
+ KService::Ptr service() const;
+ private:
+ KService::Ptr _service;
+ };
+
+class KDE_EXPORT Dcop_action
+ : public Action
+ {
+ typedef Action base;
+ public:
+ Dcop_action( Action_data* data_P, const QString& app_P, const QString& obj_P,
+ const QString& call_P, const QString& args_P );
+ Dcop_action( KConfig& cfg_P, Action_data* data_P );
+ virtual void cfg_write( KConfig& cfg_P ) const;
+ virtual void execute();
+ const QString& remote_application() const;
+ const QString& remote_object() const;
+ const QString& called_function() const;
+ const QString& arguments() const;
+ virtual QString description() const;
+ virtual Action* copy( Action_data* data_P ) const;
+ private:
+ QString app; // CHECKME QCString ?
+ QString obj;
+ QString call;
+ QString args;
+ };
+
+class KDE_EXPORT Keyboard_input_action
+ : public Action
+ {
+ typedef Action base;
+ public:
+ Keyboard_input_action( Action_data* data_P, const QString& input_P,
+ const Windowdef_list* dest_window_P, bool active_window_P );
+ Keyboard_input_action( KConfig& cfg_P, Action_data* data_P );
+ virtual ~Keyboard_input_action();
+ virtual void cfg_write( KConfig& cfg_P ) const;
+ virtual void execute();
+ const QString& input() const;
+ // send to specific window: dest_window != NULL
+ // send to active window: dest_window == NULL && activeWindow() == true
+ // send to action window: dest_window == NULL && activeWindow() == false
+ const Windowdef_list* dest_window() const;
+ bool activeWindow() const;
+ virtual QString description() const;
+ virtual Action* copy( Action_data* data_P ) const;
+ private:
+ QString _input;
+ const Windowdef_list* _dest_window;
+ bool _active_window;
+ };
+
+class KDE_EXPORT Activate_window_action
+ : public Action
+ {
+ typedef Action base;
+ public:
+ Activate_window_action( Action_data* data_P, const Windowdef_list* window_P );
+ Activate_window_action( KConfig& cfg_P, Action_data* data_P );
+ virtual ~Activate_window_action();
+ virtual void cfg_write( KConfig& cfg_P ) const;
+ virtual void execute();
+ const Windowdef_list* window() const;
+ virtual QString description() const;
+ virtual Action* copy( Action_data* data_P ) const;
+ private:
+ const Windowdef_list* _window;
+ };
+
+//***************************************************************************
+// Inline
+//***************************************************************************
+
+// Action
+
+inline
+Action::Action( Action_data* data_P )
+ : data( data_P )
+ {
+ }
+
+inline
+Action::Action( KConfig&, Action_data* data_P )
+ : data( data_P )
+ {
+ }
+
+inline
+Action::~Action()
+ {
+ }
+
+// Action_list
+
+inline
+Action_list::Action_list( const QString& comment_P )
+ : QPtrList< Action >(), _comment( comment_P )
+ {
+ setAutoDelete( true );
+ }
+
+inline
+const QString& Action_list::comment() const
+ {
+ return _comment;
+ }
+
+// Command_url_action
+
+inline
+Command_url_action::Command_url_action( Action_data* data_P, const QString& command_url_P )
+ : Action( data_P ), _command_url( command_url_P )
+ {
+ }
+
+inline
+const QString& Command_url_action::command_url() const
+ {
+ return _command_url;
+ }
+
+// Menuentry_action
+
+inline
+Menuentry_action::Menuentry_action( Action_data* data_P, const QString& menuentry_P )
+ : Command_url_action( data_P, menuentry_P )
+ {
+ }
+
+inline
+Menuentry_action::Menuentry_action( KConfig& cfg_P, Action_data* data_P )
+ : Command_url_action( cfg_P, data_P )
+ {
+ }
+
+// DCOP_action
+
+inline
+Dcop_action::Dcop_action( Action_data* data_P, const QString& app_P, const QString& obj_P,
+ const QString& call_P, const QString& args_P )
+ : Action( data_P ), app( app_P ), obj( obj_P ), call( call_P ), args( args_P )
+ {
+ }
+
+inline
+const QString& Dcop_action::remote_application() const
+ {
+ return app;
+ }
+
+inline
+const QString& Dcop_action::remote_object() const
+ {
+ return obj;
+ }
+
+inline
+const QString& Dcop_action::called_function() const
+ {
+ return call;
+ }
+
+inline
+const QString& Dcop_action::arguments() const
+ {
+ return args;
+ }
+
+// Keyboard_input_action
+
+inline
+Keyboard_input_action::Keyboard_input_action( Action_data* data_P, const QString& input_P,
+ const Windowdef_list* dest_window_P, bool active_window_P )
+ : Action( data_P ), _input( input_P ), _dest_window( dest_window_P ), _active_window( active_window_P )
+ {
+ }
+
+inline
+const QString& Keyboard_input_action::input() const
+ {
+ return _input;
+ }
+
+inline
+const Windowdef_list* Keyboard_input_action::dest_window() const
+ {
+ return _dest_window;
+ }
+
+inline
+bool Keyboard_input_action::activeWindow() const
+ {
+ return _active_window;
+ }
+
+// Activate_window_action
+
+inline
+Activate_window_action::Activate_window_action( Action_data* data_P,
+ const Windowdef_list* window_P )
+ : Action( data_P ), _window( window_P )
+ {
+ }
+
+inline
+const Windowdef_list* Activate_window_action::window() const
+ {
+ return _window;
+ }
+
+} // namespace KHotKeys
+
+#endif
diff --git a/khotkeys/shared/conditions.cpp b/khotkeys/shared/conditions.cpp
new file mode 100644
index 000000000..01d236934
--- /dev/null
+++ b/khotkeys/shared/conditions.cpp
@@ -0,0 +1,504 @@
+/****************************************************************************
+
+ KHotKeys
+
+ Copyright (C) 1999-2001 Lubos Lunak <l.lunak@kde.org>
+
+ Distributed under the terms of the GNU General Public License version 2.
+
+****************************************************************************/
+
+#define _CONDITIONS_CPP_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "conditions.h"
+
+#ifdef KHOTKEYS_DEBUG
+#include <typeinfo>
+#endif
+
+#include <kconfig.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <assert.h>
+
+#include <X11/Xlib.h>
+#include <fixx11h.h>
+
+#include "action_data.h"
+
+namespace KHotKeys
+{
+
+// Condition
+
+Condition::Condition( Condition_list_base* parent_P )
+ : _parent( parent_P )
+ {
+ if( _parent )
+ _parent->append( this );
+ }
+
+Condition::Condition( KConfig&, Condition_list_base* parent_P )
+ : _parent( parent_P )
+ {
+ if( _parent )
+ _parent->append( this );
+ }
+
+Condition* Condition::create_cfg_read( KConfig& cfg_P, Condition_list_base* parent_P )
+ {
+ QString type = cfg_P.readEntry( "Type" );
+ if( type == "ACTIVE_WINDOW" )
+ return new Active_window_condition( cfg_P, parent_P );
+ if( type == "EXISTING_WINDOW" )
+ return new Existing_window_condition( cfg_P, parent_P );
+ if( type == "NOT" )
+ return new Not_condition( cfg_P, parent_P );
+ if( type == "AND" )
+ return new And_condition( cfg_P, parent_P );
+ if( type == "OR" )
+ return new Or_condition( cfg_P, parent_P );
+ kdWarning( 1217 ) << "Unknown Condition type read from cfg file\n";
+ return NULL;
+ }
+
+Condition::~Condition()
+ {
+ if( _parent )
+ _parent->remove( this );
+ }
+
+
+void Condition::cfg_write( KConfig& cfg_P ) const
+ {
+ cfg_P.writeEntry( "Type", "ERROR" );
+ }
+
+void Condition::updated() const
+ {
+ if( !khotkeys_active())
+ return;
+ assert( _parent != NULL );
+ _parent->updated();
+ }
+
+#ifdef KHOTKEYS_DEBUG
+void Condition::debug( int depth_P )
+ {
+ char tmp[ 1024 ];
+ int i;
+ for( i = 0;
+ i < depth_P;
+ ++i )
+ tmp[ i ] = ' ';
+ tmp[ i ] = '\0';
+ kdDebug( 1217 ) << tmp << description() << ":(" << this << ")" << endl;
+ }
+
+void Condition::debug_list( const QPtrList< Condition >& list_P, int depth_P )
+ {
+ char tmp[ 1024 ];
+ int i;
+ for( i = 0;
+ i < depth_P;
+ ++i )
+ tmp[ i ] = ' ';
+ tmp[ i ] = '\0';
+ for( QPtrListIterator< Condition > it( list_P );
+ it;
+ ++it )
+ (*it)->debug( depth_P + 1 );
+ }
+#endif
+
+
+// Condition_list_base
+
+Condition_list_base::Condition_list_base( KConfig& cfg_P, Condition_list_base* parent_P )
+ : Condition( parent_P )
+ {
+ QString save_cfg_group = cfg_P.group();
+ int cnt = cfg_P.readNumEntry( "ConditionsCount", 0 );
+ for( int i = 0;
+ i < cnt;
+ ++i )
+ {
+ cfg_P.setGroup( save_cfg_group + QString::number( i ));
+ (void) Condition::create_cfg_read( cfg_P, this );
+ }
+ cfg_P.setGroup( save_cfg_group );
+ }
+
+Condition_list_base::~Condition_list_base()
+ {
+ while( !isEmpty())
+ {
+ Condition* c = getFirst();
+ remove( c );
+ delete c;
+ }
+ }
+
+void Condition_list_base::cfg_write( KConfig& cfg_P ) const
+ {
+ QString save_cfg_group = cfg_P.group();
+ int i = 0;
+ for( Iterator it( *this );
+ it;
+ ++it, ++i )
+ {
+ cfg_P.setGroup( save_cfg_group + QString::number( i ));
+ it.current()->cfg_write( cfg_P );
+ }
+ cfg_P.setGroup( save_cfg_group );
+ cfg_P.writeEntry( "ConditionsCount", i );
+ }
+
+bool Condition_list_base::accepts_children() const
+ {
+ return true;
+ }
+
+#ifdef KHOTKEYS_DEBUG
+void Condition_list_base::debug( int depth_P )
+ {
+ char tmp[ 1024 ];
+ int i;
+ for( i = 0;
+ i < depth_P;
+ ++i )
+ tmp[ i ] = ' ';
+ tmp[ i ] = '\0';
+ kdDebug( 1217 ) << tmp << typeid( *this ).name() << ":(" << this << ")" << endl;
+ debug_list( *this, depth_P + 1 );
+ }
+#endif
+
+// Condition_list
+
+Condition_list::Condition_list( KConfig& cfg_P, Action_data_base* data_P )
+ : Condition_list_base( cfg_P, NULL ), data( data_P )
+ {
+ _comment = cfg_P.readEntry( "Comment" );
+ }
+
+void Condition_list::cfg_write( KConfig& cfg_P ) const
+ {
+ base::cfg_write( cfg_P );
+ cfg_P.writeEntry( "Comment", comment());
+ }
+
+Condition_list* Condition_list::copy( Action_data_base* data_P ) const
+ {
+ Condition_list* ret = new Condition_list( comment(), data_P );
+ for( Iterator it( *this );
+ it;
+ ++it )
+ ret->append( it.current()->copy( ret ));
+ return ret;
+ }
+
+
+bool Condition_list::match() const
+ {
+ if( count() == 0 ) // no conditions to match => ok
+ return true;
+ for( Iterator it( *this );
+ it;
+ ++it )
+ if( it.current()->match()) // OR
+ return true;
+ return false;
+ }
+
+void Condition_list::updated() const
+ {
+ if( !khotkeys_active())
+ return;
+ data->update_triggers();
+// base::updated(); no need to, doesn't have parent
+ }
+
+// CHECKME tohle je drobet hack, jeste to zvazit
+void Condition_list::set_data( Action_data_base* data_P )
+ {
+ assert( data == NULL || data == data_P );
+ data = data_P;
+ }
+
+const QString Condition_list::description() const
+ {
+ assert( false );
+ return QString::null;
+ }
+
+Condition_list* Condition_list::copy( Condition_list_base* ) const
+ {
+ assert( false );
+ return NULL;
+ }
+
+// Active_window_condition
+
+Active_window_condition::Active_window_condition( KConfig& cfg_P, Condition_list_base* parent_P )
+ : Condition( cfg_P, parent_P )
+ {
+ QString save_cfg_group = cfg_P.group();
+ cfg_P.setGroup( save_cfg_group + "Window" );
+ _window = new Windowdef_list( cfg_P );
+ cfg_P.setGroup( save_cfg_group );
+ init();
+ set_match();
+ }
+
+void Active_window_condition::init()
+ {
+ connect( windows_handler, SIGNAL( active_window_changed( WId )),
+ this, SLOT( active_window_changed( WId )));
+ }
+
+bool Active_window_condition::match() const
+ {
+ return is_match;
+ }
+
+void Active_window_condition::set_match()
+ {
+ is_match = window()->match( Window_data( windows_handler->active_window()));
+ kdDebug( 1217 ) << "Active_window_condition::set_match :" << is_match << endl;
+ updated();
+ }
+
+void Active_window_condition::cfg_write( KConfig& cfg_P ) const
+ {
+ base::cfg_write( cfg_P );
+ QString save_cfg_group = cfg_P.group();
+ cfg_P.setGroup( save_cfg_group + "Window" );
+ window()->cfg_write( cfg_P );
+ cfg_P.setGroup( save_cfg_group );
+ cfg_P.writeEntry( "Type", "ACTIVE_WINDOW" ); // overwrites value set in base::cfg_write()
+ }
+
+#ifndef COVARIANT_RETURN_BROKEN
+Active_window_condition* Active_window_condition::copy( Condition_list_base* parent_P ) const
+#else
+Condition* Active_window_condition::copy( Condition_list_base* parent_P ) const
+#endif
+ {
+ return new Active_window_condition( window()->copy(), parent_P );
+ }
+
+const QString Active_window_condition::description() const
+ {
+ return i18n( "Active window: " ) + window()->comment();
+ }
+
+void Active_window_condition::active_window_changed( WId )
+ {
+ set_match();
+ }
+
+Active_window_condition::~Active_window_condition()
+ {
+ disconnect( windows_handler, NULL, this, NULL );
+ delete _window;
+ }
+
+// Existing_window_condition
+
+Existing_window_condition::Existing_window_condition( KConfig& cfg_P, Condition_list_base* parent_P )
+ : Condition( cfg_P, parent_P )
+ {
+ QString save_cfg_group = cfg_P.group();
+ cfg_P.setGroup( save_cfg_group + "Window" );
+ _window = new Windowdef_list( cfg_P );
+ cfg_P.setGroup( save_cfg_group );
+ init();
+ set_match();
+ }
+
+void Existing_window_condition::init()
+ {
+ connect( windows_handler, SIGNAL( window_added( WId )), this, SLOT( window_added( WId )));
+ connect( windows_handler, SIGNAL( window_removed( WId )), this, SLOT( window_removed( WId )));
+ }
+
+bool Existing_window_condition::match() const
+ {
+ return is_match;
+ }
+
+void Existing_window_condition::set_match( WId w_P )
+ {
+ if( w_P != None && !is_match )
+ is_match = window()->match( Window_data( w_P ));
+ else
+ is_match = windows_handler->find_window( window()) != None;
+ kdDebug( 1217 ) << "Existing_window_condition::set_match :" << is_match << endl;
+ updated();
+ }
+
+void Existing_window_condition::cfg_write( KConfig& cfg_P ) const
+ {
+ base::cfg_write( cfg_P );
+ QString save_cfg_group = cfg_P.group();
+ cfg_P.setGroup( save_cfg_group + "Window" );
+ window()->cfg_write( cfg_P );
+ cfg_P.setGroup( save_cfg_group );
+ cfg_P.writeEntry( "Type", "EXISTING_WINDOW" ); // overwrites value set in base::cfg_write()
+ }
+
+#ifndef COVARIANT_RETURN_BROKEN
+Existing_window_condition* Existing_window_condition::copy( Condition_list_base* parent_P ) const
+#else
+Condition* Existing_window_condition::copy( Condition_list_base* parent_P ) const
+#endif
+ {
+ return new Existing_window_condition( window()->copy(), parent_P );
+ }
+
+const QString Existing_window_condition::description() const
+ {
+ return i18n( "Existing window: " ) + window()->comment();
+ }
+
+void Existing_window_condition::window_added( WId w_P )
+ {
+ set_match( w_P );
+ }
+
+void Existing_window_condition::window_removed( WId )
+ {
+ set_match();
+ }
+
+Existing_window_condition::~Existing_window_condition()
+ {
+ disconnect( windows_handler, NULL, this, NULL );
+ delete _window;
+ }
+
+// Not_condition
+
+Not_condition::Not_condition( KConfig& cfg_P, Condition_list_base* parent_P )
+ : Condition_list_base( cfg_P, parent_P )
+ {
+ // CHECKME kontrola poctu ?
+ }
+
+bool Not_condition::match() const
+ {
+ return condition() ? !condition()->match() : false;
+ }
+
+void Not_condition::cfg_write( KConfig& cfg_P ) const
+ {
+ base::cfg_write( cfg_P );
+ cfg_P.writeEntry( "Type", "NOT" ); // overwrites value set in base::cfg_write()
+ }
+
+Not_condition* Not_condition::copy( Condition_list_base* parent_P ) const
+ {
+ Not_condition* ret = new Not_condition( parent_P );
+ if( condition())
+ ret->append( condition()->copy( ret ));
+ return ret;
+ }
+
+const QString Not_condition::description() const
+ {
+ return i18n( "Not_condition", "Not" );
+ }
+
+bool Not_condition::accepts_children() const
+ {
+ return count() == 0;
+ }
+
+// And_condition
+
+And_condition::And_condition( KConfig& cfg_P, Condition_list_base* parent_P )
+ : Condition_list_base( cfg_P, parent_P )
+ {
+ // CHECKME kontrola poctu ?
+ }
+
+bool And_condition::match() const
+ {
+ for( Iterator it( *this );
+ it;
+ ++it )
+ if( !it.current()->match()) // AND
+ return false;
+ return true; // all true (or empty)
+ }
+
+void And_condition::cfg_write( KConfig& cfg_P ) const
+ {
+ base::cfg_write( cfg_P );
+ cfg_P.writeEntry( "Type", "AND" ); // overwrites value set in base::cfg_write()
+ }
+
+And_condition* And_condition::copy( Condition_list_base* parent_P ) const
+ {
+ And_condition* ret = new And_condition( parent_P );
+ for( Iterator it( *this );
+ it;
+ ++it )
+ ret->append( (*it)->copy( ret ));
+ return ret;
+ }
+
+const QString And_condition::description() const
+ {
+ return i18n( "And_condition", "And" );
+ }
+
+// Or_condition
+
+Or_condition::Or_condition( KConfig& cfg_P, Condition_list_base* parent_P )
+ : Condition_list_base( cfg_P, parent_P )
+ {
+ // CHECKME kontrola poctu ?
+ }
+
+bool Or_condition::match() const
+ {
+ if( count() == 0 ) // empty => ok
+ return true;
+ for( Iterator it( *this );
+ it;
+ ++it )
+ if( it.current()->match()) // OR
+ return true;
+ return false;
+ }
+
+void Or_condition::cfg_write( KConfig& cfg_P ) const
+ {
+ base::cfg_write( cfg_P );
+ cfg_P.writeEntry( "Type", "OR" ); // overwrites value set in base::cfg_write()
+ }
+
+Or_condition* Or_condition::copy( Condition_list_base* parent_P ) const
+ {
+ Or_condition* ret = new Or_condition( parent_P );
+ for( Iterator it( *this );
+ it;
+ ++it )
+ ret->append( (*it)->copy( ret ));
+ return ret;
+ }
+
+const QString Or_condition::description() const
+ {
+ return i18n( "Or_condition", "Or" );
+ }
+
+} // namespace KHotKeys
+
+#include "conditions.moc"
diff --git a/khotkeys/shared/conditions.h b/khotkeys/shared/conditions.h
new file mode 100644
index 000000000..59133f4d3
--- /dev/null
+++ b/khotkeys/shared/conditions.h
@@ -0,0 +1,296 @@
+/****************************************************************************
+
+ KHotKeys
+
+ Copyright (C) 1999-2001 Lubos Lunak <l.lunak@kde.org>
+
+ Distributed under the terms of the GNU General Public License version 2.
+
+****************************************************************************/
+
+#ifndef _CONDITIONS_H_
+#define _CONDITIONS_H_
+
+#include <qobject.h>
+#include <qptrlist.h>
+#include <qstring.h>
+
+#include "khotkeysglobal.h"
+#include "windows.h"
+
+#include <X11/Xlib.h>
+#include <fixx11h.h>
+
+class KConfig;
+
+namespace KHotKeys
+{
+
+class Action_data_base;
+class Action_data;
+class Condition_list_base;
+
+class KDE_EXPORT Condition
+ {
+ public:
+ Condition( Condition_list_base* parent_P );
+ Condition( KConfig& cfg_P, Condition_list_base* parent_P );
+ virtual ~Condition();
+ virtual bool match() const = 0;
+ virtual void updated() const; // called when the condition changes
+ virtual void cfg_write( KConfig& cfg_P ) const = 0;
+ virtual const QString description() const = 0;
+ virtual Condition* copy( Condition_list_base* parent_P ) const = 0;
+ const Condition_list_base* parent() const;
+ Condition_list_base* parent();
+ static Condition* create_cfg_read( KConfig& cfg_P, Condition_list_base* parent_P );
+ protected:
+ Condition_list_base* const _parent;
+ KHOTKEYS_DISABLE_COPY( Condition );
+ };
+
+class KDE_EXPORT Condition_list_base
+ : public Condition, public QPtrList< Condition > // inheritance ?
+ {
+ typedef Condition base;
+ public:
+ Condition_list_base( Condition_list_base* parent_P );
+ Condition_list_base( const QPtrList< Condition >& children_P,
+ Condition_list_base* parent_P );
+ Condition_list_base( KConfig& cfg_P, Condition_list_base* parent_P );
+ virtual ~Condition_list_base();
+ virtual void cfg_write( KConfig& cfg_P ) const;
+ virtual bool accepts_children() const;
+ typedef QPtrListIterator< Condition > Iterator;
+ };
+
+class KDE_EXPORT Condition_list
+ : public Condition_list_base
+ {
+ typedef Condition_list_base base;
+ public:
+ Condition_list( const QString& comment_P, Action_data_base* data_P );
+ Condition_list( KConfig& cfg_P, Action_data_base* data_P );
+ void cfg_write( KConfig& cfg_P ) const;
+ Condition_list* copy( Action_data_base* data_P ) const;
+ virtual bool match() const;
+ const QString& comment() const;
+ void set_data( Action_data_base* data_P );
+ virtual void updated() const;
+ virtual Condition_list* copy( Condition_list_base* parent_P ) const;
+ virtual const QString description() const;
+ private:
+ QString _comment;
+ Action_data_base* data;
+ };
+
+class KDE_EXPORT Active_window_condition
+ : public QObject, public Condition
+ {
+ Q_OBJECT
+ typedef Condition base;
+ public:
+ Active_window_condition( Windowdef_list* window_P, Condition_list_base* parent_P );
+ Active_window_condition( KConfig& cfg_P, Condition_list_base* parent_P );
+ virtual ~Active_window_condition();
+ virtual bool match() const;
+ virtual void cfg_write( KConfig& cfg_P ) const;
+ const Windowdef_list* window() const;
+#ifndef COVARIANT_RETURN_BROKEN
+ virtual Active_window_condition* copy( Condition_list_base* parent_P ) const;
+#else
+ virtual Condition* copy( Condition_list_base* parent_P ) const;
+#endif
+ virtual const QString description() const;
+ public slots:
+ void active_window_changed( WId );
+ private:
+ void init();
+ void set_match();
+ Windowdef_list* _window;
+ bool is_match;
+ };
+
+class KDE_EXPORT Existing_window_condition
+ : public QObject, public Condition
+ {
+ Q_OBJECT
+ typedef Condition base;
+ public:
+ Existing_window_condition( Windowdef_list* window_P, Condition_list_base* parent_P );
+ Existing_window_condition( KConfig& cfg_P, Condition_list_base* parent_P );
+ virtual ~Existing_window_condition();
+ virtual bool match() const;
+ virtual void cfg_write( KConfig& cfg_P ) const;
+ const Windowdef_list* window() const;
+#ifndef COVARIANT_RETURN_BROKEN
+ virtual Existing_window_condition* copy( Condition_list_base* parent_P ) const;
+#else
+ virtual Condition* copy( Condition_list_base* parent_P ) const;
+#endif
+ virtual const QString description() const;
+ public slots:
+ void window_added( WId w_P );
+ void window_removed( WId w_P );
+ private:
+ void init();
+ void set_match( WId w_P = None );
+ Windowdef_list* _window;
+ bool is_match;
+ };
+
+class KDE_EXPORT Not_condition
+ : public Condition_list_base
+ {
+ typedef Condition_list_base base;
+ public:
+ Not_condition( Condition_list_base* parent_P );
+ Not_condition( KConfig& cfg_P, Condition_list_base* parent_P );
+ virtual bool match() const;
+ virtual void cfg_write( KConfig& cfg_P ) const;
+ virtual Not_condition* copy( Condition_list_base* parent_P ) const;
+ virtual const QString description() const;
+ const Condition* condition() const;
+ virtual bool accepts_children() const;
+ };
+
+class KDE_EXPORT And_condition
+ : public Condition_list_base
+ {
+ typedef Condition_list_base base;
+ public:
+ And_condition( Condition_list_base* parent_P );
+ And_condition( KConfig& cfg_P, Condition_list_base* parent_P );
+ virtual bool match() const;
+ virtual void cfg_write( KConfig& cfg_P ) const;
+ virtual And_condition* copy( Condition_list_base* parent_P ) const;
+ virtual const QString description() const;
+ };
+
+class KDE_EXPORT Or_condition
+ : public Condition_list_base
+ {
+ typedef Condition_list_base base;
+ public:
+ Or_condition( Condition_list_base* parent_P );
+ Or_condition( KConfig& cfg_P, Condition_list_base* parent_P );
+ virtual bool match() const;
+ virtual void cfg_write( KConfig& cfg_P ) const;
+ virtual Or_condition* copy( Condition_list_base* parent_P ) const;
+ virtual const QString description() const;
+ };
+
+//***************************************************************************
+// Inline
+//***************************************************************************
+
+// Condition
+
+inline
+const Condition_list_base* Condition::parent() const
+ {
+ return _parent;
+ }
+
+inline
+Condition_list_base* Condition::parent()
+ {
+ return _parent;
+ }
+
+// Condition_list_base
+
+inline
+Condition_list_base::Condition_list_base( Condition_list_base* parent_P )
+ : Condition( parent_P ), QPtrList< Condition >()
+ {
+ }
+
+inline
+Condition_list_base::Condition_list_base( const QPtrList< Condition >& children_P,
+ Condition_list_base* parent_P )
+ : Condition( parent_P ), QPtrList< Condition >( children_P )
+ {
+ }
+
+// Condition_list
+
+inline
+Condition_list::Condition_list( const QString& comment_P, Action_data_base* data_P )
+ : Condition_list_base( NULL ), _comment( comment_P ), data( data_P )
+ {
+ }
+
+inline
+const QString& Condition_list::comment() const
+ {
+ return _comment;
+ }
+
+// Active_window_condition
+
+inline
+Active_window_condition::Active_window_condition( Windowdef_list* window_P,
+ Condition_list_base* parent_P )
+ : Condition( parent_P ), _window( window_P )
+ {
+ init();
+ set_match();
+ }
+
+inline
+const Windowdef_list* Active_window_condition::window() const
+ {
+ return _window;
+ }
+
+// Existing_window_condition
+
+inline
+Existing_window_condition::Existing_window_condition( Windowdef_list* window_P,
+ Condition_list_base* parent_P )
+ : Condition( parent_P ), _window( window_P ), is_match( false )
+ {
+ init();
+ set_match();
+ }
+
+inline
+const Windowdef_list* Existing_window_condition::window() const
+ {
+ return _window;
+ }
+
+// Not_condition
+
+inline
+Not_condition::Not_condition( Condition_list_base* parent_P )
+ : Condition_list_base( parent_P )
+ {
+ }
+
+inline
+const Condition* Not_condition::condition() const
+ {
+ return getFirst();
+ }
+
+// And_condition
+
+inline
+And_condition::And_condition( Condition_list_base* parent_P )
+ : Condition_list_base( parent_P )
+ {
+ }
+
+// Or_condition
+
+inline
+Or_condition::Or_condition( Condition_list_base* parent_P )
+ : Condition_list_base( parent_P )
+ {
+ }
+
+} // namespace KHotKeys
+
+#endif
diff --git a/khotkeys/shared/gestures.cpp b/khotkeys/shared/gestures.cpp
new file mode 100644
index 000000000..11cc44e22
--- /dev/null
+++ b/khotkeys/shared/gestures.cpp
@@ -0,0 +1,449 @@
+/****************************************************************************
+
+ KHotKeys
+
+ Copyright (C) 1999-2002 Lubos Lunak <l.lunak@kde.org>
+
+ Distributed under the terms of the GNU General Public License version 2.
+
+ Based on LibStroke :
+ ( libstroke - an X11 stroke interface library
+ Copyright (c) 1996,1997,1998,1999 Mark F. Willey, ETLA Technical
+ There is a reference application available on the LibStroke Home Page:
+ http://www.etla.net/~willey/projects/libstroke/ )
+
+****************************************************************************/
+
+#define _GESTURES_CPP_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "gestures.h"
+
+#include <stdlib.h>
+#include <math.h>
+#include <assert.h>
+
+#include <X11/Xlib.h>
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kxerrorhandler.h>
+#include <kkeynative.h>
+
+#include "input.h"
+#include "windows.h"
+
+#include "voices.h"
+
+namespace KHotKeys
+{
+
+Gesture* gesture_handler;
+
+Gesture::Gesture( bool /*enabled_P*/, QObject* parent_P )
+ : _enabled( false ), recording( false ), button( 0 ), exclude( NULL )
+ {
+ (void) new DeleteObject( this, parent_P );
+ assert( gesture_handler == NULL );
+ gesture_handler = this;
+ connect( &nostroke_timer, SIGNAL( timeout()), SLOT( stroke_timeout()));
+ connect( windows_handler, SIGNAL( active_window_changed( WId )),
+ SLOT( active_window_changed( WId )));
+ }
+
+Gesture::~Gesture()
+ {
+ enable( false );
+ gesture_handler = NULL;
+ }
+
+void Gesture::enable( bool enabled_P )
+ {
+ if( _enabled == enabled_P )
+ return;
+ _enabled = enabled_P;
+ assert( button != 0 );
+ update_grab();
+ }
+
+void Gesture::set_exclude( Windowdef_list* windows_P )
+ {
+ delete exclude;
+ // check for count() > 0 - empty exclude list means no window is excluded,
+ // but empty Windowdef_list matches everything
+ if( windows_P != NULL && windows_P->count() > 0 )
+ exclude = windows_P->copy();
+ else
+ exclude = NULL;
+ update_grab();
+ }
+
+void Gesture::update_grab()
+ {
+ if( _enabled && handlers.count() > 0
+ && ( exclude == NULL || !exclude->match( Window_data( windows_handler->active_window()))))
+ {
+ kapp->removeX11EventFilter( this ); // avoid being installed twice
+ kapp->installX11EventFilter( this );
+ // CHECKME at se grabuje jen kdyz je alespon jedno gesto?
+ grab_mouse( true );
+ }
+ else
+ {
+ grab_mouse( false );
+ kapp->removeX11EventFilter( this );
+ }
+ }
+
+void Gesture::active_window_changed( WId )
+ {
+ update_grab();
+ }
+
+void Gesture::register_handler( QObject* receiver_P, const char* slot_P )
+ {
+ if( handlers.contains( receiver_P ))
+ return;
+ handlers[ receiver_P ] = true;
+ connect( this, SIGNAL( handle_gesture( const QString&, WId )),
+ receiver_P, slot_P );
+ if( handlers.count() == 1 )
+ update_grab();
+ }
+
+void Gesture::unregister_handler( QObject* receiver_P, const char* slot_P )
+ {
+ if( !handlers.contains( receiver_P ))
+ return;
+ handlers.remove( receiver_P );
+ disconnect( this, SIGNAL( handle_gesture( const QString&, WId )),
+ receiver_P, slot_P );
+ if( handlers.count() == 0 )
+ update_grab();
+ }
+
+bool Gesture::x11Event( XEvent* ev_P )
+ {
+/* kdDebug(1217) << k_funcinfo << " ( type = " << ev_P->type << " )" << KeyRelease << " " << KeyPress <<endl;
+ if( ev_P->type == XKeyPress || ev_P->type == XKeyRelease )
+ {
+ return voice_handler->x11Event( ev_P );
+ }*/
+
+ if( ev_P->type == ButtonPress && ev_P->xbutton.button == button )
+ {
+ kdDebug( 1217 ) << "GESTURE: mouse press" << endl;
+ stroke.reset();
+ stroke.record( ev_P->xbutton.x, ev_P->xbutton.y );
+ nostroke_timer.start( timeout, true );
+ recording = true;
+ start_x = ev_P->xbutton.x_root;
+ start_y = ev_P->xbutton.y_root;
+ return true;
+ }
+ else if( ev_P->type == ButtonRelease && ev_P->xbutton.button == button
+ && recording )
+ {
+ recording = false;
+ nostroke_timer.stop();
+ stroke.record( ev_P->xbutton.x, ev_P->xbutton.y );
+ QString gesture( stroke.translate());
+ if( gesture.isEmpty())
+ {
+ kdDebug( 1217 ) << "GESTURE: replay" << endl;
+ XAllowEvents( qt_xdisplay(), AsyncPointer, CurrentTime );
+ XUngrabPointer( qt_xdisplay(), CurrentTime );
+ mouse_replay( true );
+ return true;
+ }
+ kdDebug( 1217 ) << "GESTURE: got: " << gesture << endl;
+ emit handle_gesture( gesture, windows_handler->window_at_position( start_x, start_y ));
+ return true;
+ }
+ else if( ev_P->type == MotionNotify && recording )
+ { // ignore small initial movement
+ if( nostroke_timer.isActive()
+ && abs( start_x - ev_P->xmotion.x_root ) < 10
+ && abs( start_y - ev_P->xmotion.y_root ) < 10 )
+ return true;
+ nostroke_timer.stop();
+ stroke.record( ev_P->xmotion.x, ev_P->xmotion.y );
+ }
+ return false;
+ }
+
+void Gesture::stroke_timeout()
+ {
+ kdDebug( 1217 ) << "GESTURE: timeout" << endl;
+ XAllowEvents( qt_xdisplay(), AsyncPointer, CurrentTime );
+ XUngrabPointer( qt_xdisplay(), CurrentTime );
+ mouse_replay( false );
+ recording = false;
+ }
+
+void Gesture::mouse_replay( bool release_P )
+ {
+ bool was_enabled = _enabled;
+ enable( false );
+ Mouse::send_mouse_button( button, release_P );
+ enable( was_enabled );
+ }
+
+void Gesture::grab_mouse( bool grab_P )
+ {
+ if( grab_P )
+ {
+ KXErrorHandler handler;
+ static int mask[] = { 0, Button1MotionMask, Button2MotionMask, Button3MotionMask,
+ Button4MotionMask, Button5MotionMask, ButtonMotionMask, ButtonMotionMask,
+ ButtonMotionMask, ButtonMotionMask };
+#define XCapL KKeyNative::modXLock()
+#define XNumL KKeyNative::modXNumLock()
+#define XScrL KKeyNative::modXScrollLock()
+ unsigned int mods[ 8 ] =
+ {
+ 0, XCapL, XNumL, XNumL | XCapL,
+ XScrL, XScrL | XCapL,
+ XScrL | XNumL, XScrL | XNumL | XCapL
+ };
+#undef XCapL
+#undef XNumL
+#undef XScrL
+ for( int i = 0;
+ i < 8;
+ ++i )
+ XGrabButton( qt_xdisplay(), button, mods[ i ], qt_xrootwin(), False,
+ ButtonPressMask | ButtonReleaseMask | mask[ button ], GrabModeAsync, GrabModeAsync,
+ None, None );
+ bool err = handler.error( true );
+ kdDebug( 1217 ) << "Gesture grab:" << err << endl;
+ }
+ else
+ {
+ kdDebug( 1217 ) << "Gesture ungrab" << endl;
+ XUngrabButton( qt_xdisplay(), button, AnyModifier, qt_xrootwin());
+ }
+ }
+
+void Gesture::set_mouse_button( unsigned int button_P )
+ {
+ if( button == button_P )
+ return;
+ if( !_enabled )
+ {
+ button = button_P;
+ return;
+ }
+ grab_mouse( false );
+ button = button_P;
+ grab_mouse( true );
+ }
+
+void Gesture::set_timeout( int timeout_P )
+ {
+ timeout = timeout_P;
+ }
+
+Stroke::Stroke()
+ {
+ reset();
+ points = new point[ MAX_POINTS ]; // CHECKME
+ }
+
+Stroke::~Stroke()
+ {
+ delete[] points;
+ }
+
+void Stroke::reset()
+ {
+ min_x = 10000;
+ min_y = 10000;
+ max_x = -1;
+ max_y = -1;
+ point_count = -1;
+ }
+
+bool Stroke::record( int x, int y )
+ {
+ if( point_count >= MAX_POINTS )
+ return false;
+ if( point_count == -1 )
+ {
+ ++point_count;
+ points[ point_count ].x = x;
+ points[ point_count ].y = y;
+ min_x = max_x = x;
+ min_y = max_y = y;
+ }
+ else
+ {
+ // interpolate between last and current point
+ int delx = x - points[ point_count ].x;
+ int dely = y - points[ point_count ].y;
+ if( abs( delx ) > abs( dely )) // step by the greatest delta direction
+ {
+ float iy = points[ point_count ].y;
+ // go from the last point to the current, whatever direction it may be
+ for( int ix = points[ point_count ].x;
+ ( delx > 0 ) ? ( ix < x ) : ( ix > x );
+ ( delx > 0 ) ? ++ix : --ix )
+ {
+ // step the other axis by the correct increment
+ if( dely < 0 )
+ iy -= fabs( dely / ( float ) delx );
+ else
+ iy += fabs( dely / ( float ) delx );
+ // add the interpolated point
+ ++point_count;
+ if( point_count >= MAX_POINTS )
+ return false;
+ points[ point_count ].x = ix;
+ points[ point_count ].y = ( int )iy;
+ }
+ // add the last point
+ ++point_count;
+ if( point_count >= MAX_POINTS )
+ return false;
+ points[ point_count ].x = x;
+ points[ point_count ].y = y;
+ // update metrics, it's ok to do it only for the last point
+ if( x < min_x )
+ min_x = x;
+ if( x > max_x )
+ max_x = x;
+ if( y < min_y )
+ min_y = y;
+ if( y > max_y )
+ max_y = y;
+ }
+ else
+ { // same thing, but for dely larger than delx case...
+ float ix = points[ point_count ].x;
+ // go from the last point to the current, whatever direction it may be
+ for( int iy = points[ point_count ].y;
+ ( dely > 0 ) ? ( iy < y ) : ( iy > y );
+ ( dely > 0 ) ? ++iy : --iy )
+ {
+ // step the other axis by the correct increment
+ if( delx < 0 )
+ ix -= fabs( delx / ( float ) dely );
+ else
+ ix += fabs( delx / ( float ) dely );
+ // add the interpolated point
+ ++point_count;
+ if( point_count >= MAX_POINTS )
+ return false;
+ points[ point_count ].x = ( int )ix;
+ points[ point_count ].y = iy;
+ }
+ // add the last point
+ ++point_count;
+ if( point_count >= MAX_POINTS )
+ return false;
+ points[ point_count ].x = x;
+ points[ point_count ].y = y;
+ // update metrics, ts's ok to do it only for the last point
+ if( x < min_x )
+ min_x = x;
+ if( x > max_x )
+ max_x = x;
+ if( y < min_y )
+ min_y = y;
+ if( y > max_y )
+ max_y = y;
+ }
+ }
+ return true;
+ }
+
+char* Stroke::translate( int min_bin_points_percentage_P, int scale_ratio_P, int min_points_P )
+ {
+ if( point_count < min_points_P )
+ return NULL;
+ // determine size of grid
+ delta_x = max_x - min_x;
+ delta_y = max_y - min_y;
+ if( delta_x > scale_ratio_P * delta_y )
+ {
+ int avg_y = ( max_y + min_y ) / 2;
+ min_y = avg_y - delta_x / 2;
+ max_y = avg_y + delta_x / 2;
+ delta_y = max_y - min_y;
+ }
+ else if( delta_y > scale_ratio_P * delta_x )
+ {
+ int avg_x = ( max_x + min_x ) / 2;
+ min_x = avg_x - delta_y / 2;
+ max_x = avg_x + delta_y / 2;
+ delta_x = max_x - min_x;
+ }
+ // calculate bin boundary positions
+ bound_x_1 = min_x + delta_x / 3;
+ bound_x_2 = min_x + 2 * delta_x / 3;
+ bound_y_1 = min_y + delta_y / 3;
+ bound_y_2 = min_y + 2 * delta_y / 3;
+
+ int sequence_count = 0;
+ // points-->sequence translation scratch variables
+ int prev_bin = 0;
+ int current_bin = 0;
+ int bin_count = 0;
+// build string by placing points in bins, collapsing bins and discarding
+// those with too few points...
+ for( int pos = 0;
+ pos <= point_count;
+ ++pos )
+ {
+ // figure out which bin the point falls in
+ current_bin = bin( points[ pos ].x, points[ pos ].y );
+ // if this is the first point, consider it the previous bin, too.
+ if( prev_bin == 0 )
+ prev_bin = current_bin;
+ if( prev_bin == current_bin )
+ bin_count++;
+ else
+ { // we are moving to a new bin -- consider adding to the sequence
+ // CHECKME tohle taky konfigurovatelne ?
+ if( bin_count >= ( min_bin_points_percentage_P * point_count / 100 )
+ || sequence_count == 0 )
+ {
+ if( sequence_count >= MAX_SEQUENCE )
+ return NULL;
+ ret_val[ sequence_count++ ] = prev_bin + '0';
+ }
+ // restart counting points in the new bin
+ bin_count=0;
+ prev_bin = current_bin;
+ }
+ }
+
+ // add the last run of points to the sequence
+ if( sequence_count >= MAX_SEQUENCE - 1 )
+ return NULL;
+ ret_val[ sequence_count++ ] = current_bin + '0';
+ ret_val[ sequence_count ] = 0; // endmark
+ return ret_val;
+ }
+
+/* figure out which bin the point falls in */
+int Stroke::bin( int x, int y )
+ {
+ int bin_num = 1;
+ if( x > bound_x_1 )
+ ++bin_num;
+ if( x > bound_x_2 )
+ ++bin_num;
+ if( y < bound_y_1 )
+ bin_num += 3;
+ if( y < bound_y_2 )
+ bin_num += 3;
+ return bin_num;
+ }
+
+} // namespace KHotKeys
+
+#include "gestures.moc"
diff --git a/khotkeys/shared/gestures.h b/khotkeys/shared/gestures.h
new file mode 100644
index 000000000..4c210528a
--- /dev/null
+++ b/khotkeys/shared/gestures.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+
+ KHotKeys
+
+ Copyright (C) 1999-2002 Lubos Lunak <l.lunak@kde.org>
+
+ Distributed under the terms of the GNU General Public License version 2.
+
+****************************************************************************/
+
+#ifndef _GESTURES_H_
+#define _GESTURES_H_
+
+#include <qwidget.h>
+#include <qtimer.h>
+
+#include <X11/Xlib.h>
+#include <fixx11h.h>
+
+#include "windows.h"
+
+namespace KHotKeys
+{
+
+class Gesture;
+KDE_EXPORT extern Gesture* gesture_handler;
+
+class KDE_EXPORT Stroke
+ {
+ public:
+ // maximum number of numbers in stroke
+ enum { MAX_SEQUENCE = 25 };
+ // largest number of points allowed to be sampled
+ enum { MAX_POINTS = 5000 };
+ // default percentage of sample points in a bin from all points to be valid
+ enum { MIN_BIN_POINTS_PERCENTAGE = 5 };
+ // default threshold of size of smaller axis needed for it to define its own bin size
+ enum { SCALE_RATIO = 4 };
+ // default number of sample points required to have a valid stroke
+ enum { MIN_POINTS = 10 };
+ Stroke();
+ ~Stroke();
+ bool record( int x, int y );
+ char* translate( int min_bin_points_percentage_P = MIN_BIN_POINTS_PERCENTAGE,
+ int scale_ratio_P = SCALE_RATIO, int min_points_P = MIN_POINTS ); // CHECKME returns ret_val ( see below )
+ void reset();
+ protected:
+ int bin( int x, int y );
+ // metrics for input stroke
+ int min_x, min_y;
+ int max_x, max_y;
+ int point_count;
+ int delta_x, delta_y;
+ int bound_x_1, bound_x_2;
+ int bound_y_1, bound_y_2;
+ struct point
+ {
+ int x;
+ int y;
+ };
+ point* points;
+ char ret_val[ MAX_SEQUENCE ];
+ };
+
+class KDE_EXPORT Gesture
+ : public QWidget // not QObject because of x11EventFilter()
+ {
+ Q_OBJECT
+ public:
+ Gesture( bool enabled_P, QObject* parent_P );
+ virtual ~Gesture();
+ void enable( bool enable_P );
+ void set_mouse_button( unsigned int button_P );
+ void set_timeout( int time_P );
+ void set_exclude( Windowdef_list* windows_P );
+ void register_handler( QObject* receiver_P, const char* slot_P );
+ void unregister_handler( QObject* receiver_P, const char* slot_P );
+ protected:
+ virtual bool x11Event( XEvent* ev_P );
+ private slots:
+ void stroke_timeout();
+ void active_window_changed( WId window_P );
+ signals:
+ void handle_gesture( const QString &gesture, WId window );
+ private:
+ void update_grab();
+ void grab_mouse( bool grab_P );
+ void mouse_replay( bool release_P );
+ bool _enabled;
+ Stroke stroke;
+ int start_x, start_y;
+ QTimer nostroke_timer;
+ bool recording;
+ unsigned int button;
+ int timeout;
+ WId gesture_window;
+ Windowdef_list* exclude;
+ QMap< QObject*, bool > handlers; // bool is just a dummy
+ };
+
+// Gesture class must be QWidget derived because of x11Event()
+// but it should be QObject owned -> use a QObject proxy that will delete it
+class DeleteObject
+ : public QObject
+ {
+ Q_OBJECT
+ public:
+ DeleteObject( QWidget* widget_P, QObject* parent_P )
+ : QObject( parent_P ), widget( widget_P ) {}
+ virtual ~DeleteObject() { delete widget; }
+ private:
+ QWidget* widget;
+ };
+
+
+//***************************************************************************
+// Inline
+//***************************************************************************
+
+} // namespace KHotKeys
+
+#endif
diff --git a/khotkeys/shared/input.cpp b/khotkeys/shared/input.cpp
new file mode 100644
index 000000000..021dedf93
--- /dev/null
+++ b/khotkeys/shared/input.cpp
@@ -0,0 +1,253 @@
+/****************************************************************************
+
+ KHotKeys
+
+ Copyright (C) 1999-2001 Lubos Lunak <l.lunak@kde.org>
+
+ Distributed under the terms of the GNU General Public License version 2.
+
+****************************************************************************/
+
+#define _INPUT_CPP_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "input.h"
+
+#include <assert.h>
+#include <qwidget.h>
+
+#include <kglobalaccel.h>
+#include <kdebug.h>
+#include <kapplication.h>
+#include <kdeversion.h>
+#include <qtimer.h>
+#include <kkeynative.h>
+
+#include "khotkeysglobal.h"
+
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+
+#include "windows.h"
+
+namespace KHotKeys
+{
+
+// Kbd
+
+Kbd::Kbd( bool grabbing_enabled_P, QObject* parent_P )
+ : QObject( parent_P )
+ {
+ assert( keyboard_handler == NULL );
+ keyboard_handler = this;
+ kga = new KGlobalAccel( NULL );
+ kga->setEnabled( grabbing_enabled_P );
+ }
+
+Kbd::~Kbd()
+ {
+ keyboard_handler = NULL;
+ delete kga;
+ }
+
+void Kbd::insert_item( const KShortcut& shortcut_P, Kbd_receiver* receiver_P )
+ {
+ Receiver_data& rcv = receivers[ receiver_P ];
+ rcv.shortcuts.append( shortcut_P );
+ if( rcv.active )
+ grab_shortcut( shortcut_P );
+ }
+
+void Kbd::remove_item( const KShortcut& shortcut_P, Kbd_receiver* receiver_P )
+ {
+ Receiver_data& rcv = receivers[ receiver_P ];
+ rcv.shortcuts.remove( shortcut_P );
+ if( rcv.active )
+ ungrab_shortcut( shortcut_P );
+ if( rcv.shortcuts.count() == 0 )
+ receivers.remove( receiver_P );
+ }
+
+void Kbd::activate_receiver( Kbd_receiver* receiver_P )
+ {
+ Receiver_data& rcv = receivers[ receiver_P ];
+ if( rcv.active )
+ return;
+ rcv.active = true;
+ for( QValueList< KShortcut >::ConstIterator it( rcv.shortcuts.begin());
+ it != rcv.shortcuts.end();
+ ++it )
+ grab_shortcut( *it );
+ }
+
+void Kbd::deactivate_receiver( Kbd_receiver* receiver_P )
+ {
+ Receiver_data& rcv = receivers[ receiver_P ];
+ if( !rcv.active )
+ return;
+ rcv.active = false;
+ for( QValueList< KShortcut >::ConstIterator it( rcv.shortcuts.begin());
+ it != rcv.shortcuts.end();
+ ++it )
+ ungrab_shortcut( *it );
+ }
+
+void Kbd::grab_shortcut( const KShortcut& shortcut_P )
+ {
+ if( grabs.contains( shortcut_P ))
+ ++grabs[ shortcut_P ];
+ else
+ {
+ grabs[ shortcut_P ] = 1;
+#if 0
+ // CHECKME ugly ugly hack
+ QString name = ' ' + QString::number( keycode_P );
+ kga->insertItem( "", name, keycode_P );
+ kga->connectItem( name, this, SLOT( key_slot( int )));
+#endif
+ QString name = ' ' + shortcut_P.toStringInternal();
+ kga->insert( name, name, QString::null, shortcut_P, shortcut_P,
+ this, SLOT( key_slot( QString )));
+ QTimer::singleShot( 0, this, SLOT( update_connections()));
+ }
+ }
+
+void Kbd::ungrab_shortcut( const KShortcut& shortcut_P )
+ {
+ if( !grabs.contains( shortcut_P ))
+ return;
+ if( --grabs[ shortcut_P ] == 0 )
+ {
+#if 0
+ // CHECKME workaround for KGlobalAccel::disconnectItem() not working
+ kga->setItemEnabled( ' ' + QString::number( keycode_P ), false );
+ // kga->disconnectItem( ' ' + QString::number( keycode_P ), NULL, NULL );
+ kga->removeItem( ' ' + QString::number( keycode_P ));
+#endif
+ kga->remove( ' ' + shortcut_P.toStringInternal());
+ grabs.remove( shortcut_P );
+ QTimer::singleShot( 0, this, SLOT( update_connections()));
+ }
+ }
+
+void Kbd::update_connections()
+ {
+ kga->updateConnections();
+ }
+
+void Kbd::key_slot( QString key_P )
+ {
+ kdDebug( 1217 ) << "Key pressed:" << key_P << endl;
+ KShortcut shortcut( key_P );
+ if( !grabs.contains( shortcut ))
+ return;
+ for( QMap< Kbd_receiver*, Receiver_data >::ConstIterator it = receivers.begin();
+ it != receivers.end();
+ ++it )
+ if( ( *it ).shortcuts.contains( shortcut ) && ( *it ).active
+ && it.key()->handle_key( shortcut ))
+ return;
+ }
+
+
+#ifdef HAVE_XTEST
+
+} // namespace KHotKeys
+#include <X11/extensions/XTest.h>
+namespace KHotKeys
+{
+
+static bool xtest_available = false;
+static bool xtest_inited = false;
+static bool xtest()
+ {
+ if( xtest_inited )
+ return xtest_available;
+ xtest_inited = true;
+ int dummy1, dummy2, dummy3, dummy4;
+ xtest_available =
+ ( XTestQueryExtension( qt_xdisplay(), &dummy1, &dummy2, &dummy3, &dummy4 ) == True );
+ return xtest_available;
+ }
+#endif
+
+// CHECKME nevola XFlush(), musi se pak volat rucne
+bool Kbd::send_macro_key( const KKey& key, Window window_P )
+ {
+ unsigned int keysym = KKeyNative( key ).sym();
+ KeyCode x_keycode = XKeysymToKeycode( qt_xdisplay(), keysym );
+ if( x_keycode == NoSymbol )
+ return false;
+ unsigned int x_mod = KKeyNative( key ).mod();
+#ifdef HAVE_XTEST
+ if( xtest() && window_P == None )
+ {
+ // CHECKME tohle jeste potrebuje modifikatory
+ bool ret = XTestFakeKeyEvent( qt_xdisplay(), x_keycode, True, CurrentTime );
+ ret = ret && XTestFakeKeyEvent( qt_xdisplay(), x_keycode, False, CurrentTime );
+ return ret;
+ }
+#endif
+ if( window_P == None || window_P == InputFocus )
+ window_P = windows_handler->active_window();
+ if( window_P == None ) // CHECKME tohle cele je ponekud ...
+ window_P = InputFocus;
+ XEvent ev;
+ ev.type = KeyPress;
+ ev.xkey.display = qt_xdisplay();
+ ev.xkey.window = window_P;
+ ev.xkey.root = qt_xrootwin(); // I don't know whether these have to be set
+ ev.xkey.subwindow = None; // to these values, but it seems to work, hmm
+ ev.xkey.time = CurrentTime;
+ ev.xkey.x = 0;
+ ev.xkey.y = 0;
+ ev.xkey.x_root = 0;
+ ev.xkey.y_root = 0;
+ ev.xkey.keycode = x_keycode;
+ ev.xkey.state = x_mod;
+ ev.xkey.same_screen = True;
+ bool ret = XSendEvent( qt_xdisplay(), window_P, True, KeyPressMask, &ev );
+#if 1
+ ev.type = KeyRelease; // is this actually really needed ??
+ ev.xkey.display = qt_xdisplay();
+ ev.xkey.window = window_P;
+ ev.xkey.root = qt_xrootwin();
+ ev.xkey.subwindow = None;
+ ev.xkey.time = CurrentTime;
+ ev.xkey.x = 0;
+ ev.xkey.y = 0;
+ ev.xkey.x_root = 0;
+ ev.xkey.y_root = 0;
+ ev.xkey.state = x_mod;
+ ev.xkey.keycode = x_keycode;
+ ev.xkey.same_screen = True;
+ ret = ret && XSendEvent( qt_xdisplay(), window_P, True, KeyReleaseMask, &ev );
+#endif
+ // Qt's autorepeat compression is broken and can create "aab" from "aba"
+ // XSync() should create delay longer than Qt's max autorepeat interval
+ XSync( qt_xdisplay(), False );
+ return ret;
+ }
+
+bool Mouse::send_mouse_button( int button_P, bool release_P )
+ {
+#ifdef HAVE_XTEST
+ if( xtest())
+ {
+ // CHECKME tohle jeste potrebuje modifikatory
+ // a asi i spravnou timestamp misto CurrentTime
+ bool ret = XTestFakeButtonEvent( qt_xdisplay(), button_P, True, CurrentTime );
+ if( release_P )
+ ret = ret && XTestFakeButtonEvent( qt_xdisplay(), button_P, False, CurrentTime );
+ return ret;
+ }
+#endif
+ return false;
+ }
+
+} // namespace KHotKeys
+
+#include "input.moc"
diff --git a/khotkeys/shared/input.h b/khotkeys/shared/input.h
new file mode 100644
index 000000000..1983bcf0b
--- /dev/null
+++ b/khotkeys/shared/input.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+
+ KHotKeys
+
+ Copyright (C) 1999-2001 Lubos Lunak <l.lunak@kde.org>
+
+ Distributed under the terms of the GNU General Public License version 2.
+
+****************************************************************************/
+
+#ifndef _INPUT_H_
+#define _INPUT_H_
+
+#include <qobject.h>
+#include <qwindowdefs.h>
+#include <qmap.h>
+#include <qwidget.h>
+#include <qvaluelist.h>
+#include <kshortcut.h>
+
+#include <X11/X.h>
+#include <fixx11h.h>
+
+class KGlobalAccel;
+
+namespace KHotKeys
+{
+
+class Kbd_receiver
+ {
+ public:
+ virtual bool handle_key( const KShortcut& shortcut_P ) = 0;
+ };
+
+class Kbd
+ : public QObject
+ {
+ Q_OBJECT
+ public:
+ Kbd( bool grabbing_enabled_P, QObject* parent_P );
+ virtual ~Kbd();
+ void insert_item( const KShortcut& shortcut_P, Kbd_receiver* receiver_P );
+ void remove_item( const KShortcut& shortcut_P, Kbd_receiver* receiver_P );
+ void activate_receiver( Kbd_receiver* receiver_P );
+ void deactivate_receiver( Kbd_receiver* receiver_P );
+ static bool send_macro_key( const KKey& key, Window window_P = InputFocus );
+ protected:
+ bool x11EventFilter( const XEvent* );
+ void grab_shortcut( const KShortcut& shortcut_P );
+ void ungrab_shortcut( const KShortcut& shortcut_P );
+ private slots:
+ void key_slot( QString key_P );
+ void update_connections();
+ private:
+ struct Receiver_data
+ {
+ Receiver_data();
+ QValueList< KShortcut > shortcuts;
+ bool active;
+ };
+ QMap< Kbd_receiver*, Receiver_data > receivers;
+ QMap< KShortcut, int > grabs;
+ KGlobalAccel* kga;
+ };
+
+class Mouse
+ {
+ public:
+ static bool send_mouse_button( int button_P, bool release_P );
+ };
+
+
+//***************************************************************************
+// Inline
+//***************************************************************************
+
+// Kbd::Receiver_data
+
+inline
+Kbd::Receiver_data::Receiver_data()
+ : active( false )
+ {
+ }
+
+} // namespace KHotKeys
+
+#endif
diff --git a/khotkeys/shared/khlistbox.cpp b/khotkeys/shared/khlistbox.cpp
new file mode 100644
index 000000000..694fb658b
--- /dev/null
+++ b/khotkeys/shared/khlistbox.cpp
@@ -0,0 +1,103 @@
+/****************************************************************************
+
+ KHotKeys
+
+ Copyright (C) 1999-2002 Lubos Lunak <l.lunak@kde.org>
+
+ Distributed under the terms of the GNU General Public License version 2.
+
+****************************************************************************/
+
+#define _KHLISTBOX_CPP_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "khlistbox.h"
+
+#include <kdebug.h>
+
+namespace KHotKeys
+{
+
+KHListBox::KHListBox( QWidget* parent_P, const char* name_P )
+ : QListBox( parent_P, name_P ), saved_current_item( NULL ),
+ in_clear( false ), force_select( false )
+ {
+ connect( this, SIGNAL( selectionChanged( QListBoxItem* )),
+ SLOT( slot_selection_changed( QListBoxItem* )));
+ connect( this, SIGNAL( currentChanged( QListBoxItem* )),
+ SLOT( slot_current_changed( QListBoxItem* )));
+ // CHECKME grrr
+ connect( this, SIGNAL( selectionChanged()),
+ SLOT( slot_selection_changed()));
+ connect( &insert_select_timer, SIGNAL( timeout()),
+ SLOT( slot_insert_select()));
+ }
+
+void KHListBox::slot_selection_changed()
+ {
+ if( saved_current_item == NULL )
+ slot_selection_changed( NULL );
+ else if( !saved_current_item->isSelected()) // no way
+ setSelected( saved_current_item, true );
+ }
+
+void KHListBox::slot_selection_changed( QListBoxItem* item_P )
+ {
+ if( item_P == saved_current_item )
+ return;
+ saved_current_item = item_P;
+ setCurrentItem( saved_current_item );
+ emit current_changed( saved_current_item );
+ }
+
+void KHListBox::slot_current_changed( QListBoxItem* item_P )
+ {
+ insert_select_timer.stop();
+ if( item_P == saved_current_item )
+ return;
+ saved_current_item = item_P;
+ setSelected( saved_current_item, true );
+ emit current_changed( saved_current_item );
+ }
+
+// neni virtual :((
+void KHListBox::clear()
+ {
+ in_clear = true;
+ QListBox::clear();
+ in_clear = false;
+ slot_selection_changed( NULL );
+ }
+
+
+// neni virtual :(( a vubec nefunguje
+void KHListBox::insertItem( QListBoxItem* item_P )
+ {
+ bool set = false;
+ if( !in_clear )
+ set = count() == 0;
+ QListBox::insertItem( item_P );
+ if( set && force_select )
+ {
+ bool block = signalsBlocked();
+ blockSignals( true );
+ setCurrentItem( item_P );
+ blockSignals( block );
+ insert_select_timer.start( 0, true );
+ }
+ }
+
+// items are often inserted using the QListBoxItem constructor,
+// which means that a derived class are not yet fully created
+void KHListBox::slot_insert_select()
+ {
+ slot_current_changed( item( currentItem()));
+ }
+
+
+} // namespace KHotKeys
+
+#include "khlistbox.moc"
diff --git a/khotkeys/shared/khlistbox.h b/khotkeys/shared/khlistbox.h
new file mode 100644
index 000000000..95bd32963
--- /dev/null
+++ b/khotkeys/shared/khlistbox.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+
+ KHotKeys
+
+ Copyright (C) 1999-2002 Lubos Lunak <l.lunak@kde.org>
+
+ Distributed under the terms of the GNU General Public License version 2.
+
+****************************************************************************/
+
+#ifndef _KHLISTBOX_H_
+#define _KHLISTBOX_H_
+
+#include <qtimer.h>
+
+#include <klistbox.h>
+
+namespace KHotKeys
+{
+
+class KHListBox
+ : public QListBox
+ {
+ Q_OBJECT
+ Q_PROPERTY( bool forceSelect READ forceSelect WRITE setForceSelect )
+ public:
+ KHListBox( QWidget* parent_P, const char* name_P = NULL );
+ virtual void clear();
+ virtual void insertItem( QListBoxItem* item_P );
+ bool forceSelect() const;
+ void setForceSelect( bool force_P );
+ signals:
+ void current_changed( QListBoxItem* item_P );
+ private slots:
+ void slot_selection_changed( QListBoxItem* item_P );
+ void slot_selection_changed();
+ void slot_current_changed( QListBoxItem* item_P );
+ void slot_insert_select();
+ private:
+ QListBoxItem* saved_current_item;
+ bool in_clear;
+ bool force_select;
+ QTimer insert_select_timer;
+ };
+
+//***************************************************************************
+// Inline
+//***************************************************************************
+
+inline
+void KHListBox::setForceSelect( bool force_P )
+ {
+ force_select = force_P;
+ }
+
+inline
+bool KHListBox::forceSelect() const
+ {
+ return force_select;
+ }
+
+} // namespace KHotKeys
+
+#endif
diff --git a/khotkeys/shared/khlistview.cpp b/khotkeys/shared/khlistview.cpp
new file mode 100644
index 000000000..45a1d04f9
--- /dev/null
+++ b/khotkeys/shared/khlistview.cpp
@@ -0,0 +1,122 @@
+/****************************************************************************
+
+ KHotKeys
+
+ Copyright (C) 1999-2002 Lubos Lunak <l.lunak@kde.org>
+
+ Distributed under the terms of the GNU General Public License version 2.
+
+****************************************************************************/
+
+#define _KHLISTVIEW_CPP_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "khlistview.h"
+
+#include <kdebug.h>
+
+namespace KHotKeys
+{
+
+KHListView::KHListView( QWidget* parent_P, const char* name_P )
+ : KListView( parent_P, name_P ), saved_current_item( NULL ),
+ in_clear( false ), ignore( false ), force_select( false )
+ {
+ connect( this, SIGNAL( selectionChanged( QListViewItem* )),
+ SLOT( slot_selection_changed( QListViewItem* )));
+ connect( this, SIGNAL( currentChanged( QListViewItem* )),
+ SLOT( slot_current_changed( QListViewItem* )));
+ // CHECKME grrr
+ connect( this, SIGNAL( selectionChanged()),
+ SLOT( slot_selection_changed()));
+ connect( &insert_select_timer, SIGNAL( timeout()),
+ SLOT( slot_insert_select()));
+ }
+
+void KHListView::slot_selection_changed()
+ {
+ if( ignore )
+ return;
+ if( saved_current_item == NULL )
+ slot_selection_changed( NULL );
+ else if( !saved_current_item->isSelected()) // no way
+ setSelected( saved_current_item, true );
+ }
+
+void KHListView::slot_selection_changed( QListViewItem* item_P )
+ {
+ if( ignore )
+ return;
+ if( item_P == saved_current_item )
+ return;
+ saved_current_item = item_P;
+ setCurrentItem( saved_current_item );
+ emit current_changed( saved_current_item );
+ }
+
+void KHListView::slot_current_changed( QListViewItem* item_P )
+ {
+ if( ignore )
+ return;
+ insert_select_timer.stop();
+ if( item_P == saved_current_item )
+ return;
+ saved_current_item = item_P;
+ setSelected( saved_current_item, true );
+ emit current_changed( saved_current_item );
+ }
+
+void KHListView::clear()
+ {
+ in_clear = true;
+ KListView::clear();
+ in_clear = false;
+ slot_selection_changed( NULL );
+ }
+
+void KHListView::insertItem( QListViewItem* item_P )
+ {
+ bool set = false;
+ if( !in_clear )
+ set = childCount() == 0;
+ KListView::insertItem( item_P );
+ if( set && force_select )
+ {
+ bool block = signalsBlocked();
+ blockSignals( true );
+// SELI tohle spis jen blokovat sebe?
+ setCurrentItem( item_P );
+ blockSignals( block );
+ insert_select_timer.start( 0, true );
+ }
+ }
+
+void KHListView::clearSelection()
+ {
+ KListView::clearSelection();
+ slot_current_changed( currentItem());
+ }
+
+// items are often inserted using the QListViewItem constructor,
+// which means that a derived class are not yet fully created
+void KHListView::slot_insert_select()
+ {
+ if( ignore )
+ return;
+ slot_current_changed( currentItem());
+ }
+
+void KHListView::contentsDropEvent( QDropEvent* e )
+ {
+ bool save_ignore = ignore;
+ ignore = true;
+ KListView::contentsDropEvent( e );
+ ignore = save_ignore;
+ }
+
+} // namespace KHotKeys
+
+#include "khlistview.moc"
diff --git a/khotkeys/shared/khlistview.h b/khotkeys/shared/khlistview.h
new file mode 100644
index 000000000..69986299d
--- /dev/null
+++ b/khotkeys/shared/khlistview.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+
+ KHotKeys
+
+ Copyright (C) 1999-2002 Lubos Lunak <l.lunak@kde.org>
+
+ Distributed under the terms of the GNU General Public License version 2.
+
+****************************************************************************/
+
+#ifndef _KHLISTVIEW_H_
+#define _KHLISTVIEW_H_
+
+#include <qtimer.h>
+
+#include <klistview.h>
+#include <kdemacros.h>
+
+namespace KHotKeys
+{
+
+class KDE_EXPORT KHListView
+ : public KListView
+ {
+ Q_OBJECT
+ Q_PROPERTY( bool forceSelect READ forceSelect WRITE setForceSelect )
+ public:
+ KHListView( QWidget* parent_P, const char* name_P = NULL );
+ virtual void clear();
+ virtual void insertItem( QListViewItem* item_P );
+ virtual void clearSelection();
+ bool forceSelect() const;
+ void setForceSelect( bool force_P );
+ signals:
+ void current_changed( QListViewItem* item_P );
+ protected:
+ virtual void contentsDropEvent (QDropEvent*);
+ private slots:
+ void slot_selection_changed( QListViewItem* item_P );
+ void slot_selection_changed();
+ void slot_current_changed( QListViewItem* item_P );
+ void slot_insert_select();
+ private:
+ QListViewItem* saved_current_item;
+ bool in_clear;
+ bool ignore;
+ bool force_select;
+ QTimer insert_select_timer;
+ };
+
+//***************************************************************************
+// Inline
+//***************************************************************************
+
+inline
+void KHListView::setForceSelect( bool force_P )
+ {
+ force_select = force_P;
+ }
+
+inline
+bool KHListView::forceSelect() const
+ {
+ return force_select;
+ }
+
+} // namespace KHotKeys
+
+#endif
diff --git a/khotkeys/shared/khotkeysglobal.cpp b/khotkeys/shared/khotkeysglobal.cpp
new file mode 100644
index 000000000..2b430fc8c
--- /dev/null
+++ b/khotkeys/shared/khotkeysglobal.cpp
@@ -0,0 +1,100 @@
+/****************************************************************************
+
+ KHotKeys
+
+ Copyright (C) 1999-2001 Lubos Lunak <l.lunak@kde.org>
+
+ Distributed under the terms of the GNU General Public License version 2.
+
+****************************************************************************/
+
+#define _KHOTKEYSGLOBAL_CPP_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "khotkeysglobal.h"
+
+#include <assert.h>
+#include <kdebug.h>
+#include <kstandarddirs.h>
+#include <klibloader.h>
+
+#include "input.h"
+#include "windows.h"
+#include "triggers.h"
+#include "gestures.h"
+#include "voices.h"
+#include "soundrecorder.h"
+
+namespace KHotKeys
+{
+
+Kbd* keyboard_handler;
+Windows* windows_handler;
+static bool _khotkeys_active = false;
+
+void init_global_data( bool active_P, QObject* owner_P )
+ {
+ assert( keyboard_handler == NULL );
+ assert( windows_handler == NULL );
+ assert( gesture_handler == NULL );
+ static_cast< void >( new Kbd( active_P, owner_P ));
+ static_cast< void >( new Windows( active_P, owner_P ));
+ static_cast< void >( new Gesture( active_P, owner_P ));
+ static_cast< void >( new Voice( active_P, owner_P ));
+ khotkeys_set_active( false );
+ }
+
+void khotkeys_set_active( bool active_P )
+ {
+ _khotkeys_active = active_P;
+ }
+
+bool khotkeys_active()
+ {
+ return _khotkeys_active;
+ }
+
+// does the opposite of KStandardDirs::findResource() i.e. e.g.
+// "/opt/kde2/share/applnk/System/konsole.desktop" -> "System/konsole.desktop"
+QString get_menu_entry_from_path( const QString& path_P )
+ {
+ QStringList dirs = KGlobal::dirs()->resourceDirs( "apps" );
+ for( QStringList::ConstIterator it = dirs.begin();
+ it != dirs.end();
+ ++it )
+ if( path_P.find( *it ) == 0 )
+ {
+ QString ret = path_P;
+ ret.remove( 0, (*it).length());
+ if( ret[ 0 ] == '/' )
+ ret.remove( 0, 1 );
+ return ret;
+ }
+ return path_P;
+ }
+
+static int have_arts = -1;
+
+bool haveArts()
+ {
+ if( have_arts == -1 )
+ {
+ have_arts = 0;
+ KLibrary* arts = KLibLoader::self()->library( "khotkeys_arts" );
+ if( arts == NULL )
+ kdDebug( 1217 ) << "Couldn't load khotkeys_arts:" << KLibLoader::self()->lastErrorMessage() << endl;
+ if( arts != NULL && SoundRecorder::init( arts ))
+ have_arts = 1;
+ }
+ return have_arts != 0;
+ }
+
+void disableArts()
+ {
+ have_arts = 0;
+ }
+
+} // namespace KHotKeys
diff --git a/khotkeys/shared/khotkeysglobal.h b/khotkeys/shared/khotkeysglobal.h
new file mode 100644
index 000000000..873473e0f
--- /dev/null
+++ b/khotkeys/shared/khotkeysglobal.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+
+ KHotKeys
+
+ Copyright (C) 1999-2001 Lubos Lunak <l.lunak@kde.org>
+
+ Distributed under the terms of the GNU General Public License version 2.
+
+****************************************************************************/
+
+#ifndef _KHOTKEYSGLOBAL_H_
+#define _KHOTKEYSGLOBAL_H_
+
+#define KHOTKEYS_VERSION "2.1"
+#define KHOTKEYS_CONFIG_FILE "khotkeysrc"
+
+//#ifndef NDEBUG
+//#define KHOTKEYS_DEBUG
+//#endif
+
+#include <qstring.h>
+
+#include <klocale.h>
+
+class KConfig;
+class QObject;
+
+namespace KHotKeys
+{
+
+class Kbd;
+class Windows;
+class Action_data_group;
+
+extern Kbd* keyboard_handler;
+extern Windows* windows_handler;
+
+#define KHOTKEYS_DISABLE_COPY( cls ) private: cls( const cls& ); cls& operator=( const cls& )
+
+// CHECKME hmms :(
+KDE_EXPORT bool khotkeys_active();
+KDE_EXPORT void khotkeys_set_active( bool active_P );
+
+QString get_menu_entry_from_path( const QString& path_P );
+
+KDE_EXPORT void init_global_data( bool active_P, QObject* owner_P );
+
+const char* const MENU_EDITOR_ENTRIES_GROUP_NAME = I18N_NOOP( "Menu Editor entries" );
+
+KDE_EXPORT bool haveArts();
+KDE_EXPORT void disableArts();
+
+//***************************************************************************
+// Inline
+//***************************************************************************
+
+} // namespace KHotKeys
+
+#endif
diff --git a/khotkeys/shared/settings.cpp b/khotkeys/shared/settings.cpp
new file mode 100644
index 000000000..829c8521a
--- /dev/null
+++ b/khotkeys/shared/settings.cpp
@@ -0,0 +1,265 @@
+/****************************************************************************
+
+ KHotKeys
+
+ Copyright (C) 1999-2001 Lubos Lunak <l.lunak@kde.org>
+
+ Distributed under the terms of the GNU General Public License version 2.
+
+****************************************************************************/
+
+#define _SETTINGS_CPP_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "settings.h"
+
+#include <kconfig.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kaccel.h>
+#include <kglobal.h>
+#include <kmessagebox.h>
+
+#include "triggers.h"
+#include "conditions.h"
+#include "action_data.h"
+
+namespace KHotKeys
+{
+
+// Settings
+
+Settings::Settings()
+ : actions( NULL ), gestures_exclude( NULL )
+ {
+ }
+
+bool Settings::read_settings( bool include_disabled_P )
+ {
+ KConfig cfg( KHOTKEYS_CONFIG_FILE, true );
+ return read_settings( cfg, include_disabled_P, ImportNone );
+ }
+
+bool Settings::import( KConfig& cfg_P, bool ask_P )
+ {
+ return read_settings( cfg_P, true, ask_P ? ImportAsk : ImportSilent );
+ }
+
+bool Settings::read_settings( KConfig& cfg_P, bool include_disabled_P, ImportType import_P )
+ {
+ if( actions == NULL )
+ actions = new Action_data_group( NULL, "should never see", "should never see",
+ NULL, Action_data_group::SYSTEM_ROOT, true );
+ if( cfg_P.groupList().count() == 0 ) // empty
+ return false;
+ cfg_P.setGroup( "Main" ); // main group
+ if( import_P == ImportNone ) // reading main cfg file
+ already_imported = cfg_P.readListEntry( "AlreadyImported" );
+ else
+ {
+ QString import_id = cfg_P.readEntry( "ImportId" );
+ if( !import_id.isEmpty())
+ {
+ if( already_imported.contains( import_id ))
+ {
+ if( import_P == ImportSilent
+ || KMessageBox::warningContinueCancel( NULL,
+ i18n( "This \"actions\" file has already been imported before. "
+ "Are you sure you want to import it again?" )) != KMessageBox::Continue )
+ return true; // import "successful"
+ }
+ else
+ already_imported.append( import_id );
+ }
+ else
+ {
+ if( import_P != ImportSilent
+ && KMessageBox::warningContinueCancel( NULL,
+ i18n( "This \"actions\" file has no ImportId field and therefore it cannot be determined "
+ "whether or not it has been imported already. Are you sure you want to import it?" ))
+ == KMessageBox::Cancel )
+ return true;
+ }
+ }
+ int version = cfg_P.readNumEntry( "Version", -1234576 );
+ switch( version )
+ {
+ case 1:
+ read_settings_v1( cfg_P );
+ break;
+ case 2:
+ read_settings_v2( cfg_P, include_disabled_P );
+ break;
+ default:
+ kdWarning( 1217 ) << "Unknown cfg. file version\n";
+ return false;
+ case -1234576: // no config file
+ if( import_P ) // if importing, this is an error
+ return false;
+ break;
+ }
+ if( import_P != ImportNone )
+ return true; // don't read global settings
+ cfg_P.setGroup( "Main" ); // main group
+ daemon_disabled = cfg_P.readBoolEntry( "Disabled", false );
+ cfg_P.setGroup( "Gestures" );
+ gestures_disabled_globally = cfg_P.readBoolEntry( "Disabled", true );
+ gesture_mouse_button = cfg_P.readNumEntry( "MouseButton", 2 );
+ gesture_mouse_button = KCLAMP( gesture_mouse_button, 2, 9 );
+ gesture_timeout = cfg_P.readNumEntry( "Timeout", 300 );
+ cfg_P.setGroup( "GesturesExclude" );
+ delete gestures_exclude;
+ gestures_exclude = new Windowdef_list( cfg_P );
+ cfg_P.setGroup( "Voice" );
+ voice_shortcut=KShortcut( cfg_P.readEntry("Shortcut" , "") );
+ return true;
+ }
+
+void Settings::write_settings()
+ {
+ KConfig cfg( KHOTKEYS_CONFIG_FILE, false );
+// CHECKME smazat stare sekce ?
+ QStringList groups = cfg.groupList();
+ for( QStringList::ConstIterator it = groups.begin();
+ it != groups.end();
+ ++it )
+ cfg.deleteGroup( *it );
+ cfg.setGroup( "Main" ); // main group
+ cfg.writeEntry( "Version", 2 ); // now it's version 2 cfg. file
+ cfg.writeEntry( "AlreadyImported", already_imported );
+ cfg.setGroup( "Data" );
+ int cnt = write_actions_recursively_v2( cfg, actions, true );
+ cfg.setGroup( "Main" );
+ cfg.writeEntry( "Autostart", cnt != 0 && !daemon_disabled );
+ cfg.writeEntry( "Disabled", daemon_disabled );
+ cfg.setGroup( "Gestures" );
+ cfg.writeEntry( "Disabled", gestures_disabled_globally );
+ cfg.writeEntry( "MouseButton", gesture_mouse_button );
+ cfg.writeEntry( "Timeout", gesture_timeout );
+ if( gestures_exclude != NULL )
+ {
+ cfg.setGroup( "GesturesExclude" );
+ gestures_exclude->cfg_write( cfg );
+ }
+ else
+ cfg.deleteGroup( "GesturesExclude" );
+ cfg.setGroup( "Voice" );
+ cfg.writeEntry("Shortcut" , voice_shortcut.toStringInternal() );
+
+ }
+
+
+// return value means the number of enabled actions written in the cfg file
+// i.e. 'Autostart' for value > 0 should be on
+int Settings::write_actions_recursively_v2( KConfig& cfg_P, Action_data_group* parent_P, bool enabled_P )
+ {
+ int enabled_cnt = 0;
+ QString save_cfg_group = cfg_P.group();
+ int cnt = 0;
+ for( Action_data_group::Iterator it = parent_P->first_child();
+ it;
+ ++it )
+ {
+ ++cnt;
+ if( enabled_P && (*it)->enabled( true ))
+ ++enabled_cnt;
+ cfg_P.setGroup( save_cfg_group + "_" + QString::number( cnt ));
+ ( *it )->cfg_write( cfg_P );
+ Action_data_group* grp = dynamic_cast< Action_data_group* >( *it );
+ if( grp != NULL )
+ enabled_cnt += write_actions_recursively_v2( cfg_P, grp, enabled_P && (*it)->enabled( true ));
+ }
+ cfg_P.setGroup( save_cfg_group );
+ cfg_P.writeEntry( "DataCount", cnt );
+ return enabled_cnt;
+ }
+
+void Settings::read_settings_v2( KConfig& cfg_P, bool include_disabled_P )
+ {
+ cfg_P.setGroup( "Data" );
+ read_actions_recursively_v2( cfg_P, actions, include_disabled_P );
+ }
+
+void Settings::read_actions_recursively_v2( KConfig& cfg_P, Action_data_group* parent_P,
+ bool include_disabled_P )
+ {
+ QString save_cfg_group = cfg_P.group();
+ int cnt = cfg_P.readNumEntry( "DataCount" );
+ for( int i = 1;
+ i <= cnt;
+ ++i )
+ {
+ cfg_P.setGroup( save_cfg_group + "_" + QString::number( i ));
+ if( include_disabled_P || Action_data_base::cfg_is_enabled( cfg_P ))
+ {
+ Action_data_base* new_action = Action_data_base::create_cfg_read( cfg_P, parent_P );
+ Action_data_group* grp = dynamic_cast< Action_data_group* >( new_action );
+ if( grp != NULL )
+ read_actions_recursively_v2( cfg_P, grp, include_disabled_P );
+ }
+ }
+ cfg_P.setGroup( save_cfg_group );
+ }
+
+// backward compatibility
+void Settings::read_settings_v1( KConfig& cfg_P )
+ {
+ int sections = cfg_P.readNumEntry( "Num_Sections", 0 );
+ Action_data_group* menuentries = NULL;
+ for( Action_data_group::Iterator it( actions->first_child());
+ *it;
+ ++it )
+ {
+ Action_data_group* tmp = dynamic_cast< Action_data_group* >( *it );
+ if( tmp == NULL )
+ continue;
+ if( tmp->system_group() == Action_data_group::SYSTEM_MENUENTRIES )
+ {
+ menuentries = tmp;
+ break;
+ }
+ }
+ for( int sect = 1;
+ sect <= sections;
+ ++sect )
+ {
+ QString group = QString( "Section%1" ).arg( sect );
+ if( !cfg_P.hasGroup( group ))
+ continue;
+ cfg_P.setGroup( group );
+ QString name = cfg_P.readEntry( "Name" );
+ if( name.isNull() )
+ continue;
+ QString shortcut = cfg_P.readEntry( "Shortcut" );
+ if( shortcut.isNull() )
+ continue;
+ QString run = cfg_P.readEntry( "Run" );
+ if( run.isNull() )
+ continue;
+ bool menuentry = cfg_P.readBoolEntry( "MenuEntry", false );
+ // CHECKME tohle pridavani az pak je trosku HACK
+ if( menuentry )
+ {
+ if( menuentries == NULL )
+ {
+ menuentries = new Action_data_group( actions,
+ i18n( MENU_EDITOR_ENTRIES_GROUP_NAME ),
+ i18n( "These entries were created using Menu Editor." ), NULL,
+ Action_data_group::SYSTEM_MENUENTRIES, true );
+ menuentries->set_conditions( new Condition_list( "", menuentries ));
+ }
+ ( void ) new Menuentry_shortcut_action_data( menuentries, name, "",
+ KShortcut( shortcut ), run );
+ }
+ else
+ {
+ ( void ) new Command_url_shortcut_action_data( actions, name, "",
+ KShortcut( shortcut ), run );
+ }
+ }
+ }
+
+} // namespace KHotKeys
diff --git a/khotkeys/shared/settings.h b/khotkeys/shared/settings.h
new file mode 100644
index 000000000..cf05dcd31
--- /dev/null
+++ b/khotkeys/shared/settings.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+
+ KHotKeys
+
+ Copyright (C) 1999-2001 Lubos Lunak <l.lunak@kde.org>
+
+ Distributed under the terms of the GNU General Public License version 2.
+
+****************************************************************************/
+
+#ifndef _SETTINGS_H_
+#define _SETTINGS_H_
+
+#include "actions.h"
+#include <kshortcut.h>
+
+class KConfig;
+
+namespace KHotKeys
+{
+
+enum ImportType
+ {
+ ImportNone, // no import is done
+ ImportAsk, // if already imported before, ask (called from GUI)
+ ImportSilent // if already imported before, ignore (called from the update script)
+ };
+
+class KDE_EXPORT Settings
+ {
+ public:
+ Settings();
+ bool read_settings( bool include_disabled_P );
+ void write_settings();
+ bool import( KConfig& cfg_P, bool ask_P );
+ Action_data_group* actions;
+ bool gestures_disabled_globally;
+ int gesture_mouse_button;
+ int gesture_timeout;
+ bool daemon_disabled;
+ Windowdef_list* gestures_exclude;
+ KShortcut voice_shortcut;
+ protected:
+ bool read_settings( KConfig& cfg_P, bool include_disabled_P, ImportType import_P );
+ void read_settings_v1( KConfig& cfg_P );
+ void read_settings_v2( KConfig& cfg_P, bool include_disabled_P );
+ int write_actions_recursively_v2( KConfig& cfg_P, Action_data_group* parent_P, bool enabled_P );
+ void read_actions_recursively_v2( KConfig& cfg_P, Action_data_group* parent_P,
+ bool include_disabled_P );
+ private:
+ QStringList already_imported;
+ KHOTKEYS_DISABLE_COPY( Settings );
+ };
+
+//***************************************************************************
+// Inline
+//***************************************************************************
+
+} // namespace KHotKeys
+
+#endif
diff --git a/khotkeys/shared/sound.cpp b/khotkeys/shared/sound.cpp
new file mode 100644
index 000000000..e8d4191eb
--- /dev/null
+++ b/khotkeys/shared/sound.cpp
@@ -0,0 +1,343 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Olivier Goffart *
+ * ogoffart@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 "sound.h"
+#include <qfile.h>
+#include <qdatastream.h>
+#include <kdebug.h>
+
+
+
+
+Sound::Sound()
+{
+}
+
+
+Sound::~Sound()
+{
+}
+
+
+#define READ_FROM_STREAM(FORMAT,NAME) FORMAT NAME; stream >> NAME;
+#define MAGIC(CH) { \
+ stream >> magic; \
+ if( magic != ( (CH)[0] | (CH)[1]<<8 | (CH)[2]<< 16 | (CH)[3] << 24 ) ) \
+ { \
+ kdWarning() << k_funcinfo << "bad format " << magic << " != " << CH "\n";\
+ return;\
+ } }
+
+#define ABS(X) ( (X>0) ? X : -X )
+
+void Sound::load(const QString& filename)
+{
+ kdDebug() << k_funcinfo << filename << endl;
+ data=QMemArray<Q_INT32>();
+ QFile file(filename);
+ if(!file.open(IO_ReadOnly))
+ {
+ kdWarning() << k_funcinfo <<"unable to open file" << endl;
+ return;
+ }
+ QDataStream stream(&file);
+ stream.setByteOrder( QDataStream::LittleEndian );
+ Q_INT32 magic;
+
+ MAGIC("RIFF");
+ READ_FROM_STREAM(Q_UINT32,ChunkSize);
+ MAGIC("WAVE");
+ MAGIC("fmt ");
+ READ_FROM_STREAM(Q_UINT32,ChunkSize2);
+ READ_FROM_STREAM(Q_INT16,AudioFormat);
+ READ_FROM_STREAM(Q_UINT16,NumberOfChannels);
+ READ_FROM_STREAM(Q_UINT32,SampleRate);
+ _fs=SampleRate;
+ READ_FROM_STREAM(Q_UINT32,ByteRate);
+ READ_FROM_STREAM(Q_UINT16,BlockAlign);
+ READ_FROM_STREAM(Q_UINT16,BitsPerSample);
+ MAGIC("data");
+ READ_FROM_STREAM(QByteArray,SoundData);
+ NumberOfChannels=1; //Wav i play are broken
+
+ file.close();
+
+ uint BytePS=BitsPerSample/8;
+ uint NumberOfSamples = (SoundData.size())/(NumberOfChannels*BytePS);
+
+
+ data.resize(NumberOfSamples);
+
+// kdDebug() << k_funcinfo << NumberOfSamples << " samples" << endl;
+
+ max=0;
+ for(unsigned long int f=0;f<NumberOfSamples;f++)
+ {
+ Q_INT32 nb=0;
+ for(uint k=0;k<BytePS;k++)
+ {
+ nb |= (SoundData[f*BytePS+k]&0x000000FF) << (k*8);
+ }
+ if(nb & (1 << (BytePS*8 -1)) )
+ nb = nb-(1<<BytePS*8);
+ data[f]=nb;
+ if(ABS(nb)>max)
+ {
+ max=ABS(nb);
+ }
+ }
+
+/* static int q=0;
+ QString name="test" + QString::number(q++) + ".wav";
+ save(name);*/
+
+}
+
+#define SMAGIC(CH) { stream << ( Q_INT32) ( (CH)[0] | (CH)[1]<<8 | (CH)[2]<< 16 | (CH)[3] << 24 ) ; }
+
+void Sound::save(const QString& filename) const
+{
+ kdDebug( 1217 ) << k_funcinfo << filename << " - " << data.size() << endl;
+ QFile file(filename);
+ if(!file.open(IO_WriteOnly))
+ {
+ kdWarning() << k_funcinfo <<"unable to open file" << endl;
+ return;
+ }
+ QDataStream stream(&file);
+ stream.setByteOrder( QDataStream::LittleEndian );
+
+
+ QByteArray SoundData(data.size()*2);
+
+ for(unsigned long int f=0;f<data.size();f++)
+ {
+ Q_UINT16 val= (signed short int) ( (data.at(f) * ((double)(1<<13)/(signed)max) ) );
+ SoundData[ 2*f ]= val & 0x00FF;
+ SoundData[2*f+1]= (val & 0xFF00) >> 8;
+
+// kdDebug( 1217 ) << k_funcinfo << data.at(f) << " / " << max << " = " << val << " | " << SoundData[ 2*f ] << " "<< SoundData[ 2*f+1 ] << endl;
+ }
+
+ Q_UINT16 NumberOfChannels=2;
+ Q_UINT32 SampleRate=_fs;
+
+ SMAGIC("RIFF");
+ //READ_FROM_STREAM(Q_UINT32,ChunkSize);
+ stream << (Q_UINT32)(36+ SoundData.size());
+ SMAGIC("WAVE");
+ SMAGIC("fmt ");
+ //READ_FROM_STREAM(Q_UINT32,ChunkSize2);
+ stream << (Q_UINT32)(16);
+ //READ_FROM_STREAM(Q_INT16,AudioFormat);
+ stream << (Q_INT16)(1);
+ //READ_FROM_STREAM(Q_UINT16,NumberOfChannels);
+ stream << (Q_UINT16)(NumberOfChannels);
+ //READ_FROM_STREAM(Q_UINT32,SampleRate);
+ stream << (Q_UINT32)(SampleRate);
+ //READ_FROM_STREAM(Q_UINT32,ByteRate);
+ stream << (Q_UINT32)(NumberOfChannels*SampleRate*16/8);
+ //READ_FROM_STREAM(Q_UINT16,BlockAlign);
+ stream << (Q_UINT16)(16/8 *NumberOfChannels);
+ //READ_FROM_STREAM(Q_UINT16,BitsPerSample);
+ stream << (Q_UINT16)(16);
+ SMAGIC("data");
+ //READ_FROM_STREAM(QByteArray,SoundData);
+ stream << SoundData;
+
+ file.close();
+
+}
+
+
+
+
+#if 0
+void Sound::load(const QString& filename)
+{
+ cout << "saout \n";
+ data=QMemArray<long unsigned int>();
+ static const int BUFFER_LEN = 4096;
+
+ //code from libtunepimp
+ //(wav_trm.cpp)
+
+ FILE *source;
+ unsigned char buffer[100], *copyBuffer;
+ unsigned int bytes;
+ unsigned long ulRIFF;
+ unsigned long ulLength;
+ unsigned long ulWAVE;
+ unsigned long ulType;
+ unsigned long ulCount;
+ unsigned long ulLimit;
+ bool haveWaveHeader = false;
+ unsigned long waveSize = 0;
+ WAVEFORMAT waveFormat;
+ int toRead;
+ mb_int64_t fileLen = 0;
+
+ source = fopen(filename.ascii(), "rb");
+ if (source == NULL)
+ {
+// errorString = string("File not found");
+// fclose(source);
+ cout << "File not found \n";
+ return;
+ }
+
+ fseek(source, 0, SEEK_END);
+ fileLen = ftell(source);
+ fseek(source, 0, SEEK_SET);
+
+ if (fread(buffer, 1, 12, source) != 12)
+ {
+// errorString = string("File is too short");
+ cout << "File is to short \n";
+ fclose(source);
+ return ;
+ }
+
+ ulRIFF = (unsigned long)(((unsigned long *)buffer)[0]);
+ ulLength = (unsigned long)(((unsigned long *)buffer)[1]);
+ ulWAVE = (unsigned long)(((unsigned long *)buffer)[2]);
+
+ if(ulRIFF != MAKEFOURCC('R', 'I', 'F', 'F') ||
+ ulWAVE != MAKEFOURCC('W', 'A', 'V', 'E'))
+ {
+// errorString = strdup("File is not in WAVE format");
+ cout << "File is not WAVE \n";
+ fclose(source);
+ return ;
+ }
+
+ // Run through the bytes looking for the tags
+ ulCount = 0;
+ ulLimit = ulLength - 4;
+ while (ulCount < ulLimit && waveSize == 0)
+ {
+ if (fread(buffer, 1, 8, source) != 8)
+ {
+// errorString = strdup("File is too short");
+ cout << "File is to short \n";
+ fclose(source);
+ return;
+ }
+
+ ulType = (unsigned long)(((unsigned long *)buffer)[0]);
+ ulLength = (unsigned long)(((unsigned long *)buffer)[1]);
+ switch (ulType)
+ {
+ // format
+ case MAKEFOURCC('f', 'm', 't', ' '):
+ if (ulLength < sizeof(WAVEFORMAT))
+ {
+// errorString = strdup("File is too short");
+ cout << "File is to short \n";
+ fclose(source);
+ return ;
+ }
+
+ if (fread(&waveFormat, 1, ulLength, source) != ulLength)
+ {
+// errorString = strdup("File is too short");
+ cout << "File is to short \n";
+ fclose(source);
+ return ;
+ }
+
+ if (waveFormat.wFormatTag != WAVE_FORMAT_PCM)
+ {
+// errorString = strdup("Unsupported WAV format");
+ cout << "Unsupported WAVE \n";
+ fclose(source);
+ return ;
+ }
+ haveWaveHeader = true;
+
+ ulCount += ulLength;
+ break;
+
+ // data
+ case MAKEFOURCC('d', 'a', 't', 'a'):
+ waveSize = ulLength;
+ break;
+
+ default:
+ fseek(source, ulLength, SEEK_CUR);
+ break;
+
+ }
+ }
+
+
+ if (!haveWaveHeader)
+ {
+// errorString = strdup("Could not find WAV header");
+ cout << "Header nbot found \n";
+ fclose(source);
+ return ;
+ }
+
+ fileLen -= (mb_int64_t)ftell(source);
+ fileLen /= waveFormat.nChannels;
+ fileLen /= (waveFormat.nBlockAlign / waveFormat.nChannels);
+
+ fileLen /= waveFormat.nSamplesPerSec;
+
+ //on ne lit qu'un channel
+ //waveSize=fileLen;
+ data.resize(waveSize);
+ unsigned long pos=0;
+
+ cout << "Weeee "<< waveSize <<"\n";
+
+ copyBuffer = (unsigned char*)malloc(BUFFER_LEN);
+ if (copyBuffer == NULL)
+ {
+// errorString = strdup("Cannot allocate buffer space.");
+ return ;
+ }
+
+ for(;;)
+ {
+ toRead = min(waveSize, (unsigned long)BUFFER_LEN);
+ if (toRead <= 0)
+ break;
+
+ bytes = fread(copyBuffer, 1, toRead, source);
+ if (bytes <= 0)
+ break;
+
+ for(uint f=0;f<bytes;f+=4)
+ {
+ data[pos]=(((unsigned long*)copyBuffer)[f/4]);
+ pos++;
+ }
+
+ waveSize -= toRead;
+ }
+ free(copyBuffer);
+ fclose(source);
+
+ return ;
+}
+
+#endif
diff --git a/khotkeys/shared/sound.h b/khotkeys/shared/sound.h
new file mode 100644
index 000000000..1a38f182f
--- /dev/null
+++ b/khotkeys/shared/sound.h
@@ -0,0 +1,58 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Olivier Goffart *
+ * ogoffart@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. *
+ ***************************************************************************/
+#ifndef SOUND_H
+#define SOUND_H
+
+#include <qmemarray.h>
+#include <qstring.h>
+#include <kdemacros.h>
+
+/**
+@author Olivier Goffart
+*/
+class KDE_EXPORT Sound{
+public:
+ Sound();
+ ~Sound();
+
+ void load(const QString &filename);
+ void save(const QString &filename) const;
+
+ unsigned int size() const
+ {
+ return data.size();
+ }
+
+ inline float at(int pos) const
+ {
+ return (float)(data.at(pos))/max;
+ }
+
+ inline uint fs() const
+ {
+ return _fs;
+ }
+
+ QMemArray<Q_INT32> data;
+ Q_UINT32 max;
+ uint _fs;
+};
+
+#endif
diff --git a/khotkeys/shared/soundrecorder.cpp b/khotkeys/shared/soundrecorder.cpp
new file mode 100644
index 000000000..fc2031113
--- /dev/null
+++ b/khotkeys/shared/soundrecorder.cpp
@@ -0,0 +1,86 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Olivier Goffart *
+ * ogoffart@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. *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include "soundrecorder.h"
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <qtimer.h>
+#include <klibloader.h>
+
+#include "khotkeysglobal.h"
+
+namespace KHotKeys
+{
+
+SoundRecorder::create_ptr SoundRecorder::create_fun = NULL;
+
+bool SoundRecorder::init( KLibrary* lib )
+{
+#ifdef HAVE_ARTS
+ if( create_fun == NULL && lib != NULL )
+ create_fun = (create_ptr) lib->symbol( "khotkeys_soundrecorder_create" );
+#endif
+// kdDebug( 1217 ) << "soundrecorder:" << create_fun << ":" << lib << endl;
+ return create_fun != NULL;
+}
+
+SoundRecorder* SoundRecorder::create( QObject* parent, const char* name )
+{
+#ifdef HAVE_ARTS
+ if( create_fun != NULL )
+ return create_fun( parent, name );
+#endif
+ return new SoundRecorder( parent, name );
+}
+
+SoundRecorder::SoundRecorder(QObject *parent, const char *name) : QObject(parent, name) {}
+
+SoundRecorder::~SoundRecorder()
+{
+}
+
+void SoundRecorder::start()
+{
+}
+
+void SoundRecorder::stop()
+{
+}
+
+void SoundRecorder::abort()
+{
+}
+
+
+Sound SoundRecorder::sound()
+{
+ Sound s;
+ return s;
+}
+
+}
+
+#include "soundrecorder.moc"
diff --git a/khotkeys/shared/soundrecorder.h b/khotkeys/shared/soundrecorder.h
new file mode 100644
index 000000000..d9539c4c5
--- /dev/null
+++ b/khotkeys/shared/soundrecorder.h
@@ -0,0 +1,62 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Olivier Goffart *
+ * ogoffart@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. *
+ ***************************************************************************/
+#ifndef RECORDER_H
+#define RECORDER_H
+
+#include <qobject.h>
+#include "sound.h"
+#include <kdemacros.h>
+
+class KLibrary;
+
+namespace KHotKeys
+{
+
+
+
+/**
+@author Olivier Goffart
+*/
+class KDE_EXPORT SoundRecorder : public QObject
+{
+Q_OBJECT
+public:
+ static SoundRecorder* create( QObject* parent = 0, const char* name = 0 );
+ virtual ~SoundRecorder();
+
+ virtual void start();
+ virtual void stop();
+ virtual void abort();
+ virtual Sound sound();
+
+ static bool init( KLibrary* );
+signals:
+ void recorded(const Sound&);
+
+protected:
+ SoundRecorder(QObject *parent = 0, const char *name = 0);
+ typedef SoundRecorder* (*create_ptr)( QObject*, const char* );
+private:
+ static create_ptr create_fun;
+};
+
+}
+
+#endif
diff --git a/khotkeys/shared/triggers.cpp b/khotkeys/shared/triggers.cpp
new file mode 100644
index 000000000..1febedfa9
--- /dev/null
+++ b/khotkeys/shared/triggers.cpp
@@ -0,0 +1,435 @@
+/****************************************************************************
+
+ KHotKeys
+
+ Copyright (C) 1999-2001 Lubos Lunak <l.lunak@kde.org>
+
+ Distributed under the terms of the GNU General Public License version 2.
+
+****************************************************************************/
+
+#define _TRIGGERS_CPP_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "triggers.h"
+
+#include <kglobalaccel.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kwinmodule.h>
+#include <klocale.h>
+#include <netwm_def.h>
+#include <kaccel.h>
+
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+
+#include "actions.h"
+#include "action_data.h"
+#include "input.h"
+#include "gestures.h"
+#include "windows.h"
+#include "voices.h"
+
+namespace KHotKeys
+{
+
+// Trigger
+
+void Trigger::cfg_write( KConfig& cfg_P ) const
+ {
+ cfg_P.writeEntry( "Type", "ERROR" );
+ }
+
+Trigger* Trigger::create_cfg_read( KConfig& cfg_P, Action_data* data_P )
+ {
+ QString type = cfg_P.readEntry( "Type" );
+ if( type == "SHORTCUT" || type == "SINGLE_SHORTCUT" )
+ return new Shortcut_trigger( cfg_P, data_P );
+ if( type == "WINDOW" )
+ return new Window_trigger( cfg_P, data_P );
+ if( type == "GESTURE" )
+ return new Gesture_trigger(cfg_P, data_P );
+ if( type == "VOICE" )
+ return new Voice_trigger (cfg_P, data_P );
+
+ kdWarning( 1217 ) << "Unknown Trigger type read from cfg file\n";
+ return NULL;
+ }
+
+// Trigger_list
+
+Trigger_list::Trigger_list( KConfig& cfg_P, Action_data* data_P )
+ : QPtrList< Trigger >()
+ {
+ setAutoDelete( true );
+ _comment = cfg_P.readEntry( "Comment" );
+ QString save_cfg_group = cfg_P.group();
+ int cnt = cfg_P.readNumEntry( "TriggersCount", 0 );
+ for( int i = 0;
+ i < cnt;
+ ++i )
+ {
+ cfg_P.setGroup( save_cfg_group + QString::number( i ));
+ Trigger* trigger = Trigger::create_cfg_read( cfg_P, data_P );
+ if( trigger )
+ append( trigger );
+ }
+ cfg_P.setGroup( save_cfg_group );
+ }
+
+void Trigger_list::cfg_write( KConfig& cfg_P ) const
+ {
+ cfg_P.writeEntry( "Comment", comment());
+ QString save_cfg_group = cfg_P.group();
+ int i = 0;
+ for( Iterator it( *this );
+ it;
+ ++it, ++i )
+ {
+ cfg_P.setGroup( save_cfg_group + QString::number( i ));
+ it.current()->cfg_write( cfg_P );
+ }
+ cfg_P.setGroup( save_cfg_group );
+ cfg_P.writeEntry( "TriggersCount", i );
+ }
+
+Trigger_list* Trigger_list::copy( Action_data* data_P ) const
+ {
+ Trigger_list* ret = new Trigger_list( comment());
+ for( Iterator it( *this );
+ it;
+ ++it )
+ ret->append( it.current()->copy( data_P ));
+ return ret;
+ }
+
+void Trigger_list::activate( bool activate_P )
+ {
+ for( Iterator it( *this );
+ it;
+ ++it )
+ ( *it )->activate( activate_P );
+ }
+
+// Shortcut_trigger
+
+Shortcut_trigger::Shortcut_trigger( Action_data* data_P, const KShortcut& shortcut_P )
+ : Trigger( data_P ), _shortcut( shortcut_P )
+ {
+ keyboard_handler->insert_item( shortcut(), this );
+ }
+
+Shortcut_trigger::Shortcut_trigger( KConfig& cfg_P, Action_data* data_P )
+ : Trigger( cfg_P, data_P ), _shortcut( cfg_P.readEntry( "Key", 0 ))
+ {
+ keyboard_handler->insert_item( shortcut(), this );
+ }
+
+Shortcut_trigger::~Shortcut_trigger()
+ {
+ keyboard_handler->remove_item( shortcut(), this );
+ }
+
+void Shortcut_trigger::cfg_write( KConfig& cfg_P ) const
+ {
+ base::cfg_write( cfg_P );
+ cfg_P.writeEntry( "Key", _shortcut.toStringInternal());
+ cfg_P.writeEntry( "Type", "SHORTCUT" ); // overwrites value set in base::cfg_write()
+ }
+
+Shortcut_trigger* Shortcut_trigger::copy( Action_data* data_P ) const
+ {
+ kdDebug( 1217 ) << "Shortcut_trigger::copy()" << endl;
+ return new Shortcut_trigger( data_P ? data_P : data, shortcut());
+ }
+
+const QString Shortcut_trigger::description() const
+ {
+ // CHECKME vice mods
+ return i18n( "Shortcut trigger: " ) + _shortcut.toString();
+ // CHECKME i18n pro toString() ?
+ }
+
+bool Shortcut_trigger::handle_key( const KShortcut& shortcut_P )
+ {
+ if( shortcut() == shortcut_P )
+ {
+ windows_handler->set_action_window( 0 ); // use active window
+ data->execute();
+ return true;
+ }
+ return false;
+ }
+
+void Shortcut_trigger::activate( bool activate_P )
+ {
+ if( activate_P && khotkeys_active())
+ keyboard_handler->activate_receiver( this );
+ else
+ keyboard_handler->deactivate_receiver( this );
+ }
+
+// Window_trigger
+
+Window_trigger::Window_trigger( KConfig& cfg_P, Action_data* data_P )
+ : Trigger( cfg_P, data_P ), active( false )
+ {
+// kdDebug( 1217 ) << "Window_trigger" << endl;
+ QString save_cfg_group = cfg_P.group();
+ cfg_P.setGroup( save_cfg_group + "Windows" );
+ _windows = new Windowdef_list( cfg_P );
+ cfg_P.setGroup( save_cfg_group );
+ window_actions = cfg_P.readNumEntry( "WindowActions" );
+ init();
+ }
+
+Window_trigger::~Window_trigger()
+ {
+// kdDebug( 1217 ) << "~Window_trigger :" << this << endl;
+ disconnect( windows_handler, NULL, this, NULL );
+ delete _windows;
+ }
+
+void Window_trigger::init()
+ {
+ kdDebug( 1217 ) << "Window_trigger::init()" << endl;
+ connect( windows_handler, SIGNAL( window_added( WId )), this, SLOT( window_added( WId )));
+ connect( windows_handler, SIGNAL( window_removed( WId )), this, SLOT( window_removed( WId )));
+ if( window_actions & ( WINDOW_ACTIVATES | WINDOW_DEACTIVATES /*| WINDOW_DISAPPEARS*/ ))
+ connect( windows_handler, SIGNAL( active_window_changed( WId )),
+ this, SLOT( active_window_changed( WId )));
+ connect( windows_handler, SIGNAL( window_changed( WId, unsigned int )),
+ this, SLOT( window_changed( WId, unsigned int )));
+ }
+
+void Window_trigger::activate( bool activate_P )
+ {
+ active = activate_P && khotkeys_active();
+ }
+
+void Window_trigger::window_added( WId window_P )
+ {
+ bool matches = windows()->match( Window_data( window_P ));
+ existing_windows[ window_P ] = matches;
+ kdDebug( 1217 ) << "Window_trigger::w_added() : " << matches << endl;
+ if( active && matches && ( window_actions & WINDOW_APPEARS ))
+ {
+ windows_handler->set_action_window( window_P );
+ data->execute();
+ }
+ }
+
+void Window_trigger::window_removed( WId window_P )
+ {
+ if( existing_windows.contains( window_P ))
+ {
+ bool matches = existing_windows[ window_P ];
+ kdDebug( 1217 ) << "Window_trigger::w_removed() : " << matches << endl;
+ if( active && matches && ( window_actions & WINDOW_DISAPPEARS ))
+ {
+ windows_handler->set_action_window( window_P );
+ data->execute();
+ }
+ existing_windows.remove( window_P );
+ // CHECKME jenze co kdyz se window_removed zavola pred active_window_changed ?
+ }
+ else
+ kdDebug( 1217 ) << "Window_trigger::w_removed()" << endl;
+ }
+
+void Window_trigger::active_window_changed( WId window_P )
+ {
+ bool was_match = false;
+ if( existing_windows.contains( last_active_window ))
+ was_match = existing_windows[ last_active_window ];
+ if( active && was_match && ( window_actions & WINDOW_DEACTIVATES ))
+ {
+ windows_handler->set_action_window( window_P );
+ data->execute();
+ }
+/* bool matches = windows()->match( Window_data( window_P ));
+ existing_windows[ window_P ] = matches;*/
+ bool matches = existing_windows.contains( window_P )
+ ? existing_windows[ window_P ] : false;
+ if( active && matches && ( window_actions & WINDOW_ACTIVATES ))
+ {
+ windows_handler->set_action_window( window_P );
+ data->execute();
+ }
+ kdDebug( 1217 ) << "Window_trigger::a_w_changed() : " << was_match << "|" << matches << endl;
+ last_active_window = window_P;
+ }
+
+void Window_trigger::window_changed( WId window_P, unsigned int dirty_P )
+ { // CHECKME snad nebude mit vliv, kdyz budu kaslat na properties_P a zkratka
+ // kontrolovat kazdou zmenu
+ // CHECKME kdyz se zmeni okno z match na non-match, asi to nebrat jako DISAPPEAR
+ if( ! ( dirty_P & ( NET::WMName | NET::WMWindowType )))
+ return;
+ kdDebug( 1217 ) << "Window_trigger::w_changed()" << endl;
+ bool was_match = false;
+ if( existing_windows.contains( window_P ))
+ was_match = existing_windows[ window_P ];
+ bool matches = windows()->match( Window_data( window_P ));
+ existing_windows[ window_P ] = matches;
+ if( active && matches && !was_match )
+ if( window_actions & WINDOW_APPEARS )
+ {
+ windows_handler->set_action_window( window_P );
+ data->execute();
+ }
+ else if( window_actions & WINDOW_ACTIVATES && window_P == windows_handler->active_window())
+ {
+ windows_handler->set_action_window( window_P );
+ data->execute();
+ }
+ kdDebug( 1217 ) << "Window_trigger::w_changed() : " << was_match << "|" << matches << endl;
+ }
+
+void Window_trigger::cfg_write( KConfig& cfg_P ) const
+ {
+ base::cfg_write( cfg_P );
+ QString save_cfg_group = cfg_P.group();
+ cfg_P.setGroup( save_cfg_group + "Windows" );
+ windows()->cfg_write( cfg_P );
+ cfg_P.setGroup( save_cfg_group );
+ cfg_P.writeEntry( "WindowActions", window_actions );
+ cfg_P.writeEntry( "Type", "WINDOW" ); // overwrites value set in base::cfg_write()
+ }
+
+#ifndef COVARIANT_RETURN_BROKEN // stupid gcc, it doesn't even warn it can't do this
+Window_trigger* Window_trigger::copy( Action_data* data_P ) const
+#else
+Trigger* Window_trigger::copy( Action_data* data_P ) const
+#endif
+ {
+ Window_trigger* ret = new Window_trigger( data_P ? data_P : data, windows()->copy(),
+ window_actions );
+ ret->existing_windows = existing_windows; // CHECKME je tohle vazne treba ?
+ return ret;
+ }
+
+const QString Window_trigger::description() const
+ {
+ return i18n( "Window trigger: " ) + windows()->comment();
+ }
+
+// Gesture_trigger
+
+Gesture_trigger::Gesture_trigger( Action_data* data_P, const QString &gesturecode_P )
+ : Trigger( data_P ), _gesturecode( gesturecode_P )
+ {
+ }
+
+Gesture_trigger::Gesture_trigger( KConfig& cfg_P, Action_data* data_P )
+ : Trigger( cfg_P, data_P )
+ {
+ _gesturecode = cfg_P.readEntry( "Gesture" );
+ }
+
+Gesture_trigger::~Gesture_trigger()
+ {
+ gesture_handler->unregister_handler( this, SLOT( handle_gesture( const QString&, WId )));
+ }
+
+void Gesture_trigger::cfg_write( KConfig& cfg_P ) const
+ {
+ base::cfg_write( cfg_P );
+ cfg_P.writeEntry( "Gesture", gesturecode());
+ cfg_P.writeEntry( "Type", "GESTURE" ); // overwrites value set in base::cfg_write()
+ }
+
+Trigger* Gesture_trigger::copy( Action_data* data_P ) const
+ {
+ kdDebug( 1217 ) << "Gesture_trigger::copy()" << endl;
+ return new Gesture_trigger( data_P ? data_P : data, gesturecode());
+ }
+
+const QString Gesture_trigger::description() const
+ {
+ return i18n( "Gesture trigger: " ) + gesturecode();
+ }
+
+void Gesture_trigger::handle_gesture( const QString &gesture_P, WId window_P )
+ {
+ if( gesturecode() == gesture_P )
+ {
+ windows_handler->set_action_window( window_P );
+ data->execute();
+ }
+ }
+
+void Gesture_trigger::activate( bool activate_P )
+ {
+ if( activate_P )
+ gesture_handler->register_handler( this, SLOT( handle_gesture( const QString&, WId )));
+ else
+ gesture_handler->unregister_handler( this, SLOT( handle_gesture( const QString&, WId )));
+ }
+
+
+// Voice_trigger
+
+ Voice_trigger::Voice_trigger( Action_data* data_P, const QString &Voicecode_P, const VoiceSignature& signature1_P, const VoiceSignature& signature2_P )
+ : Trigger( data_P ), _voicecode( Voicecode_P )
+ {
+ _voicesignature[0]=signature1_P;
+ _voicesignature[1]=signature2_P;
+ }
+
+Voice_trigger::Voice_trigger( KConfig& cfg_P, Action_data* data_P )
+ : Trigger( cfg_P, data_P )
+ {
+ _voicecode = cfg_P.readEntry( "Name" );
+ _voicesignature[0].read( &cfg_P , "Signature1" );
+ _voicesignature[1].read( &cfg_P , "Signature2" );
+ }
+
+Voice_trigger::~Voice_trigger()
+ {
+ voice_handler->unregister_handler( this );
+ }
+
+void Voice_trigger::cfg_write( KConfig& cfg_P ) const
+ {
+ base::cfg_write( cfg_P );
+ cfg_P.writeEntry( "Name", voicecode());
+ cfg_P.writeEntry( "Type", "VOICE" ); // overwrites value set in base::cfg_write()
+ _voicesignature[0].write( &cfg_P , "Signature1" );
+ _voicesignature[1].write( &cfg_P , "Signature2" );
+ }
+
+Trigger* Voice_trigger::copy( Action_data* data_P ) const
+ {
+ kdDebug( 1217 ) << "Voice_trigger::copy()" << endl;
+ return new Voice_trigger( data_P ? data_P : data, voicecode(), voicesignature(1) , voicesignature(2) );
+ }
+
+const QString Voice_trigger::description() const
+ {
+ return i18n( "Voice trigger: " ) + voicecode();
+ }
+
+void Voice_trigger::handle_Voice( )
+ {
+ windows_handler->set_action_window( 0 ); // use active window
+ data->execute();
+
+ }
+
+void Voice_trigger::activate( bool activate_P )
+ {
+ if( activate_P && khotkeys_active())
+ voice_handler->register_handler( this );
+ else
+ voice_handler->unregister_handler( this );
+ }
+
+
+} // namespace KHotKeys
+
+#include "triggers.moc"
diff --git a/khotkeys/shared/triggers.h b/khotkeys/shared/triggers.h
new file mode 100644
index 000000000..2f921beff
--- /dev/null
+++ b/khotkeys/shared/triggers.h
@@ -0,0 +1,260 @@
+/****************************************************************************
+
+ KHotKeys
+
+ Copyright (C) 1999-2001 Lubos Lunak <l.lunak@kde.org>
+
+ Distributed under the terms of the GNU General Public License version 2.
+
+****************************************************************************/
+
+#ifndef _TRIGGERS_H_
+#define _TRIGGERS_H_
+
+#include <qptrlist.h>
+#include <qtimer.h>
+#include <qmap.h>
+#include <kdemacros.h>
+
+#include "khotkeysglobal.h"
+#include "voicesignature.h"
+
+#include "input.h"
+
+class KConfig;
+
+namespace KHotKeys
+{
+
+class Windowdef_list;
+class Action_data;
+
+class KDE_EXPORT Trigger
+ {
+ public:
+ Trigger( Action_data* data_P );
+ Trigger( KConfig& cfg_P, Action_data* data_P );
+ virtual ~Trigger();
+ virtual void cfg_write( KConfig& cfg_P ) const = 0;
+ virtual Trigger* copy( Action_data* data_P ) const = 0;
+ virtual const QString description() const = 0;
+ static Trigger* create_cfg_read( KConfig& cfg_P, Action_data* data_P );
+ virtual void activate( bool activate_P ) = 0;
+ protected:
+ Action_data* const data;
+ KHOTKEYS_DISABLE_COPY( Trigger );
+ };
+
+class KDE_EXPORT Trigger_list
+ : public QPtrList< Trigger >
+ {
+ public:
+ Trigger_list( const QString& comment_P ); // CHECKME nebo i data ?
+ Trigger_list( KConfig& cfg_P, Action_data* data_P );
+ void activate( bool activate_P );
+ void cfg_write( KConfig& cfg_P ) const;
+ typedef QPtrListIterator< Trigger > Iterator;
+ const QString& comment() const;
+ Trigger_list* copy( Action_data* data_P ) const;
+ private:
+ QString _comment;
+ KHOTKEYS_DISABLE_COPY( Trigger_list );
+ };
+
+class KDE_EXPORT Shortcut_trigger
+ : public Trigger, public Kbd_receiver
+ {
+ typedef Trigger base;
+ public:
+ Shortcut_trigger( Action_data* data_P, const KShortcut& shortcut_P );
+ Shortcut_trigger( KConfig& cfg_P, Action_data* data_P );
+ virtual ~Shortcut_trigger();
+ virtual void cfg_write( KConfig& cfg_P ) const;
+ virtual Shortcut_trigger* copy( Action_data* data_P ) const;
+ virtual const QString description() const;
+ const KShortcut& shortcut() const;
+ virtual bool handle_key( const KShortcut& shortcut_P );
+ virtual void activate( bool activate_P );
+ private:
+ KShortcut _shortcut;
+ };
+
+class KDE_EXPORT Window_trigger
+ : public QObject, public Trigger
+ {
+ Q_OBJECT
+ typedef Trigger base;
+ public:
+ enum window_action_t
+ {
+ WINDOW_APPEARS = ( 1 << 0 ),
+ WINDOW_DISAPPEARS = ( 1 << 1 ),
+ WINDOW_ACTIVATES = ( 1 << 2 ),
+ WINDOW_DEACTIVATES = ( 1 << 3 )
+ };
+ Window_trigger( Action_data* data_P, Windowdef_list* windows_P, int window_actions_P );
+ Window_trigger( KConfig& cfg_P, Action_data* data_P );
+ virtual ~Window_trigger();
+ virtual void cfg_write( KConfig& cfg_P ) const;
+#ifndef COVARIANT_RETURN_BROKEN // stupid gcc, it doesn't even warn it can't do this
+ virtual Window_trigger* copy( Action_data* data_P ) const;
+#else
+ virtual Trigger* copy( Action_data* data_P ) const;
+#endif
+ virtual const QString description() const;
+ const Windowdef_list* windows() const;
+ bool triggers_on( window_action_t w_action_P ) const;
+ virtual void activate( bool activate_P );
+ protected: // CHECKME neco private ?
+ Windowdef_list* _windows;
+ int window_actions;
+ void init();
+ typedef QMap< WId, bool > Windows_map;
+ Windows_map existing_windows;
+ WId last_active_window;
+ protected slots:
+ void window_added( WId window_P );
+ void window_removed( WId window_P );
+ void active_window_changed( WId window_P );
+ void window_changed( WId window_P, unsigned int dirty_P );
+ protected:
+ bool active;
+ };
+
+class KDE_EXPORT Gesture_trigger
+ : public QObject, public Trigger
+ {
+ Q_OBJECT
+ typedef Trigger base;
+ public:
+ Gesture_trigger( Action_data* data_P, const QString& gesture_P );
+ Gesture_trigger( KConfig& cfg_P, Action_data* data_P );
+ virtual ~Gesture_trigger();
+ virtual void cfg_write( KConfig& cfg_P ) const;
+ virtual Trigger* copy( Action_data* data_P ) const;
+ virtual const QString description() const;
+ const QString& gesturecode() const;
+ virtual void activate( bool activate_P );
+ protected slots:
+ void handle_gesture( const QString& gesture_P, WId window_P );
+ private:
+ QString _gesturecode;
+ };
+
+
+class KDE_EXPORT Voice_trigger
+ : public QObject, public Trigger
+ {
+ Q_OBJECT
+ typedef Trigger base;
+ public:
+ Voice_trigger( Action_data* data_P, const QString& Voice_P, const VoiceSignature & signature1_P, const VoiceSignature & signature2_P );
+ Voice_trigger( KConfig& cfg_P, Action_data* data_P );
+ virtual ~Voice_trigger();
+ virtual void cfg_write( KConfig& cfg_P ) const;
+ virtual Trigger* copy( Action_data* data_P ) const;
+ virtual const QString description() const;
+ const QString& voicecode() const;
+ virtual void activate( bool activate_P );
+ VoiceSignature voicesignature( int ech ) const;
+ public slots:
+ void handle_Voice( );
+ private:
+ QString _voicecode;
+ VoiceSignature _voicesignature[2];
+ };
+
+
+//***************************************************************************
+// Inline
+//***************************************************************************
+
+// Trigger
+
+inline
+Trigger::Trigger( Action_data* data_P )
+ : data( data_P )
+ {
+ }
+
+inline
+Trigger::Trigger( KConfig&, Action_data* data_P )
+ : data( data_P )
+ {
+ }
+
+inline
+Trigger::~Trigger()
+ {
+ }
+
+// Trigger_list
+
+inline
+Trigger_list::Trigger_list( const QString& comment_P )
+ : QPtrList< Trigger >(), _comment( comment_P )
+ {
+ setAutoDelete( true );
+ }
+
+inline
+const QString& Trigger_list::comment() const
+ {
+ return _comment;
+ }
+
+// Shortcut_trigger
+
+inline
+const KShortcut& Shortcut_trigger::shortcut() const
+ {
+ return _shortcut;
+ }
+
+// Window_trigger
+
+inline
+Window_trigger::Window_trigger( Action_data* data_P, Windowdef_list* windows_P,
+ int window_actions_P )
+ : Trigger( data_P ), _windows( windows_P ), window_actions( window_actions_P ),
+ last_active_window( None ), active( false )
+ {
+ init();
+ }
+
+inline
+const Windowdef_list* Window_trigger::windows() const
+ {
+ return _windows;
+ }
+
+inline
+bool Window_trigger::triggers_on( window_action_t w_action_P ) const
+ {
+ return window_actions & w_action_P;
+ }
+
+// Gesture_trigger
+
+inline
+const QString& Gesture_trigger::gesturecode() const
+ {
+ return _gesturecode;
+ }
+
+// Voice_trigger
+inline
+const QString& Voice_trigger::voicecode() const
+ {
+ return _voicecode;
+ }
+
+inline
+VoiceSignature Voice_trigger::voicesignature(int ech) const
+ {
+ return _voicesignature[ech-1];
+ }
+
+} // namespace KHotKeys
+
+#endif
diff --git a/khotkeys/shared/voices.cpp b/khotkeys/shared/voices.cpp
new file mode 100644
index 000000000..e0dc95613
--- /dev/null
+++ b/khotkeys/shared/voices.cpp
@@ -0,0 +1,303 @@
+/****************************************************************************
+
+ KHotKeys
+
+ Copyright (C) 2005 Olivier Goffart <ogoffart @ kde.org>
+
+ Distributed under the terms of the GNU General Public License version 2.
+
+****************************************************************************/
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "voices.h"
+#include "voicesignature.h"
+#include "triggers.h"
+#include "soundrecorder.h"
+
+#include <stdlib.h>
+#include <math.h>
+#include <assert.h>
+
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kxerrorhandler.h>
+#include <kkeynative.h>
+#include <qtimer.h>
+#include <kglobalaccel.h>
+
+
+#include <X11/Xlib.h>
+#include <fixx11h.h>
+
+namespace KHotKeys
+{
+
+Voice* voice_handler;
+
+Voice::Voice( bool enabled_P, QObject* parent_P )
+ : QObject( parent_P) ,_enabled( enabled_P ), _recording( false ), _recorder(0)
+ {
+ assert( voice_handler == NULL );
+ voice_handler = this;
+
+ _kga=0L;
+ _timer=0L;
+
+ kdDebug(1217) << k_funcinfo << endl;
+
+ }
+
+Voice::~Voice()
+ {
+ kdDebug(1217) << k_funcinfo << endl;
+ enable( false );
+ voice_handler = NULL;
+ }
+
+
+void Voice::enable( bool enabled_P )
+ {
+#ifndef HAVE_ARTS
+ enabled_P = false; // never enabled when there's no support
+#endif
+ if( _enabled == enabled_P )
+ return;
+ _enabled = enabled_P;
+ if( _enabled ) // activate the shortcut
+ set_shortcut( _shortcut );
+ else
+ {
+ delete _kga;
+ _kga = NULL;
+ }
+ }
+
+void Voice::register_handler( Voice_trigger *trigger_P )
+ {
+ if( !_references.contains( trigger_P ))
+ _references.append(trigger_P);
+ }
+
+void Voice::unregister_handler( Voice_trigger *trigger_P )
+ {
+ _references.remove(trigger_P);
+ }
+
+
+void Voice::record_start()
+{
+ kdDebug(1217) << k_funcinfo << endl;
+ if(!_recorder)
+ {
+ _recorder= SoundRecorder::create(this);
+ connect(_recorder, SIGNAL(recorded(const Sound& )), this, SLOT(slot_sound_recorded(const Sound& )));
+ }
+
+ _recorder->start();
+ _recording=true;
+}
+
+void Voice::record_stop()
+{
+ if(!_recording)
+ return;
+
+ kdDebug(1217) << k_funcinfo << endl;
+ delete _timer;
+ _timer=0L;
+ _recording=false;
+ if(_recorder)
+ _recorder->stop();
+}
+
+
+void Voice::slot_sound_recorded(const Sound &sound_P)
+{
+ VoiceSignature signature(sound_P);
+
+ Voice_trigger *trig=0L;
+ Voice_trigger *sec_trig=0L;
+ double minimum=800000;
+ double second_minimum=80000;
+ int got_count=0;
+ QValueList<Voice_trigger*>::Iterator it;
+ for ( it = _references.begin(); it != _references.end(); ++it )
+ {
+ for(int ech=1; ech<=2 ; ech++)
+ {
+ Voice_trigger *t=*it;
+
+ double diff=VoiceSignature::diff(signature, t->voicesignature(ech));
+ if(minimum>=diff)
+ {
+ second_minimum=minimum;
+ minimum=diff;
+ sec_trig=trig;
+ trig=t;
+ }
+ else if(second_minimum>=diff)
+ {
+ second_minimum=diff;
+ sec_trig=t;
+ }
+ if( diff < REJECT_FACTOR_DIFF )
+ got_count++;
+ kdDebug(1217) << k_funcinfo << ( (diff < REJECT_FACTOR_DIFF) ? "+++" : "---" ) <<t->voicecode() << ech << " : " << diff << endl;
+ }
+ }
+// double ecart_relatif=(second_minimum-minimum)/minimum;
+
+// kdDebug(1217) << k_funcinfo << ecart_relatif << endl;
+
+ if(trig)
+ kdDebug(1217) << k_funcinfo << "**** " << trig->voicecode() << " : " << minimum << endl;
+
+
+// if(trig && ecart_relatif > REJECT_FACTOR_ECART_REL)
+// if(trig && got_count==1)
+ bool selected=trig && (got_count==1 || ( minimum < 1.5*REJECT_FACTOR_DIFF && trig==sec_trig ) );
+
+ if(selected)
+ {
+ trig->handle_Voice();
+ }
+
+}
+
+
+/*bool Voice::x11Event( XEvent* pEvent )
+{
+ if( pEvent->type != XKeyPress && pEvent->type != XKeyRelease )
+ return false;
+
+ KKeyNative keyNative( pEvent );
+
+ //kdDebug(1217) << k_funcinfo << keyNative.key().toString() << endl;
+
+ if(_shortcut.contains(keyNative))
+ {
+ if(pEvent->type == XKeyPress && !_recording )
+ {
+ record_start();
+ return true;
+ }
+ if(pEvent->type == XKeyRelease && _recording )
+ {
+ record_stop();
+ return true;
+ }
+ }
+ return false;
+}
+
+
+*/
+
+
+void Voice::set_shortcut( const KShortcut &shortcut)
+{
+ _shortcut = shortcut;
+ if( !_enabled )
+ return;
+ if(!_kga)
+ _kga = new KGlobalAccel( this );
+ _kga->remove("voice");
+
+ _kga->insert( "voice", i18n("Voice"), QString::null, shortcut, 0, this, SLOT(slot_key_pressed())) ;
+ _kga->updateConnections();
+}
+
+void Voice::slot_key_pressed()
+{
+ if( !haveArts())
+ return;
+ if( _recording )
+ record_stop();
+ else
+ {
+ record_start();
+ if(!_timer)
+ {
+ _timer=new QTimer(this);
+ connect(_timer, SIGNAL(timeout()) , this, SLOT(slot_timeout()));
+ }
+
+ _timer->start(1000*20,true);
+ }
+}
+
+
+void Voice::slot_timeout()
+{
+ if(_recording && _recorder)
+ {
+ _recorder->abort();
+ _recording=false;
+ }
+ _timer->deleteLater();
+ _timer=0L;
+}
+
+
+QString Voice::isNewSoundFarEnough(const VoiceSignature& signature, const QString &currentTrigger)
+{
+ Voice_trigger *trig=0L;
+ Voice_trigger *sec_trig=0L;
+ double minimum=800000;
+ double second_minimum=80000;
+ int got_count=0;
+ QValueList<Voice_trigger*>::Iterator it;
+ for ( it = _references.begin(); it != _references.end(); ++it )
+ {
+ Voice_trigger *t=*it;
+ if(t->voicecode()==currentTrigger)
+ continue;
+
+ for(int ech=1; ech<=2 ; ech++)
+ {
+ double diff=VoiceSignature::diff(signature, t->voicesignature(ech));
+ if(minimum>=diff)
+ {
+ second_minimum=minimum;
+ minimum=diff;
+ sec_trig=trig;
+ trig=t;
+ }
+ else if(second_minimum>=diff)
+ {
+ second_minimum=diff;
+ sec_trig=t;
+ }
+ if( diff < REJECT_FACTOR_DIFF )
+ got_count++;
+ kdDebug(1217) << k_funcinfo << ( (diff < REJECT_FACTOR_DIFF) ? "+++" : "---" ) <<t->voicecode() << ech << " : " << diff << endl;
+ }
+ }
+
+ if(trig)
+ kdDebug(1217) << k_funcinfo << "**** " << trig->voicecode() << " : " << minimum << endl;
+
+ bool selected=trig && ((got_count==1 && minimum < REJECT_FACTOR_DIFF*0.7 ) || ( minimum < REJECT_FACTOR_DIFF && trig==sec_trig ) );
+ return selected ? trig->voicecode() : QString::null;
+}
+
+bool Voice::doesVoiceCodeExists(const QString &vc)
+{
+ QValueList<Voice_trigger*>::Iterator it;
+ for ( it = _references.begin(); it != _references.end(); ++it )
+ {
+ Voice_trigger *t=*it;
+ if(t->voicecode()==vc)
+ return true;
+ }
+ return false;
+}
+
+} // namespace KHotKeys
+
+#include "voices.moc"
diff --git a/khotkeys/shared/voices.h b/khotkeys/shared/voices.h
new file mode 100644
index 000000000..b0193e7c2
--- /dev/null
+++ b/khotkeys/shared/voices.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+
+ KHotKeys
+
+ Copyright (C) 2005 Olivier Goffart <ogoffart @ kde.org>
+
+ Distributed under the terms of the GNU General Public License version 2.
+
+****************************************************************************/
+
+#ifndef VOICES_H_
+#define VOICES_H_
+
+#include <qwidget.h>
+#include <kshortcut.h>
+
+class Sound;
+class QTimer;
+class KGlobalAccel;
+
+namespace KHotKeys
+{
+
+class Voice;
+class SoundRecorder;
+
+class Voice_trigger;
+class VoiceSignature;
+
+
+class KDE_EXPORT Voice : public QObject
+ {
+ Q_OBJECT
+ public:
+ Voice( bool enabled_P, QObject* parent_P );
+ virtual ~Voice();
+ void enable( bool enable_P );
+
+ void register_handler( Voice_trigger* );
+ void unregister_handler( Voice_trigger* );
+// bool x11Event( XEvent* e );
+
+ void set_shortcut( const KShortcut &k);
+
+ /**
+ * return QString::null is a new signature is far enough from others signature
+ * otherwise, return the stringn which match.
+ */
+ QString isNewSoundFarEnough(const VoiceSignature& s, const QString& currentTrigger);
+
+ bool doesVoiceCodeExists(const QString &s);
+
+ public slots:
+ void record_start();
+ void record_stop();
+
+ private slots:
+ void slot_sound_recorded( const Sound & );
+ void slot_key_pressed();
+ void slot_timeout();
+
+ signals:
+ void handle_voice( const QString &voice );
+ private:
+
+ bool _enabled;
+ bool _recording;
+
+ QValueList<Voice_trigger *> _references;
+ SoundRecorder *_recorder;
+
+ KShortcut _shortcut;
+ KGlobalAccel *_kga;
+
+ QTimer *_timer;
+ };
+
+
+KDE_EXPORT extern Voice* voice_handler;
+
+} // namespace KHotKeys
+
+#endif
diff --git a/khotkeys/shared/voicesignature.cpp b/khotkeys/shared/voicesignature.cpp
new file mode 100644
index 000000000..c77c278b3
--- /dev/null
+++ b/khotkeys/shared/voicesignature.cpp
@@ -0,0 +1,422 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Olivier Goffart *
+ * ogoffart@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 "voicesignature.h"
+#include "sound.h"
+#include <kconfig.h>
+
+#include <math.h>
+#ifdef PI
+#undef PI
+#endif
+#define PI (2.0 * asin(1.0))
+
+
+#include <kdebug.h>
+#include <qdatetime.h>
+
+#undef Complex
+
+namespace KHotKeys
+{
+
+
+inline static float ABS(float X)
+{
+ return (X>0) ? X : -X ;
+}
+inline static int MAX(int X , int Y)
+{
+ return (X>Y) ? X : Y ;
+}
+inline static int MIN(int X , int Y)
+{
+ return (X<Y) ? X : Y ;
+}
+
+
+
+
+
+
+class Complex
+{
+ public:
+ Complex () {}
+ Complex (double re): _re(re), _im(0.0) {}
+ Complex (double re, double im): _re(re), _im(im) {}
+ double Re () const { return _re; }
+ double Im () const { return _im; }
+ void operator += (const Complex& c)
+ {
+ _re += c._re;
+ _im += c._im;
+ }
+ void operator -= (const Complex& c)
+ {
+ _re -= c._re;
+ _im -= c._im;
+ }
+ void operator *= (const Complex& c)
+ {
+ double reT = c._re * _re - c._im * _im;
+ _im = c._re * _im + c._im * _re;
+ _re = reT;
+ }
+ Complex operator- ()
+ {
+ return Complex (-_re, -_im);
+ }
+ Complex operator- (const Complex& c) const
+ {
+ return Complex (_re - c._re, _im - c._im);
+ }
+ Complex operator+ (const Complex& c) const
+ {
+ return Complex (_re + c._re, _im + c._im);
+ }
+ Complex operator* (const Complex& c) const
+ {
+ return Complex (_re * c._re - _im * c._im , _im * c._re + _re * c._im);
+ }
+ double Mod () const { return sqrt (_re * _re + _im * _im); }
+
+ static Complex fromExp(double mod, double arg) { return Complex(mod*cos(arg) , mod*sin(arg)); }
+ private:
+ double _re;
+ double _im;
+};
+
+static inline double hamming(uint n, uint size)
+{
+ return HAMMING ? 0.54-0.46*cos( 2*PI*n /(size-1) ) : 1;
+}
+
+
+static QMemArray<double> fft(const Sound& sound, unsigned int start, unsigned int stop)
+{
+ if(start>=stop || sound.size() == 0)
+ return QMemArray<double>();
+
+ //We need a sample with a size of a power of two
+ uint size=stop-start;
+ unsigned short log2size=0;
+ while( (1<<log2size) < size )
+ log2size++;
+
+ int diff=(1<<log2size) - size;
+ if(diff > size/4 || 1<<log2size > sound.size() )
+ {
+ log2size--;
+ diff=(1<<log2size) - size;
+ }
+ size=1<<log2size;
+ int start2=start-diff/2;
+ int stop2=start2+ size;
+ if(start2<0)
+ {
+ stop2-=start2;
+ start2=0;
+ }
+ if(stop2>sound.size())
+ {
+ start2-= stop2 - sound.size();
+ stop2=sound.size();
+ if(start2<0)
+ {
+ stop2-=start2;
+ start2=0;
+ }
+ }
+
+ //Generate an array to work in
+ QMemArray<Complex> samples(size);
+
+ //Fill it with samples in the "reversed carry" order
+ int rev_carry = 0;
+ for (uint f = 0; f < size - 1; f++)
+ {
+ samples[f]=sound.at(start2+rev_carry)* hamming(rev_carry, size);
+// KDEBUG(rev_carry);
+ int mask = size>>1; // N / 2
+ // add 1 backwards
+ while (rev_carry >= mask)
+ {
+ rev_carry -= mask; // turn off this bit
+ mask >>= 1;
+ }
+ rev_carry += mask;
+ }
+ samples[size-1]=sound.at(start2+size-1)*hamming(size-1, size);
+
+ //FFT
+ for(uint level=0; level < log2size; level++)
+ {
+ for( int k=0; k< (size>>1) ; k++)
+ {
+ uint indice1 = (k << (level+1) ) % (size-1); // (k*2*2^l)%(N-1)
+ uint indice2 = indice1 + (1<<level); // (k*2*2^l)%(N-1) + 2^l
+
+ uint coefW = ( k << (level+1) ) / (size-1); // (k*2*2^l) div (N-1)
+ double Wexpn=-2 * PI * coefW / (2 << level); // -2 pi n / 2^(l+1)
+ Complex W=Complex::fromExp(1, Wexpn) ;
+
+
+ //OPERATION BUTTERFLY
+ Complex a=samples[indice1];
+ Complex b=samples[indice2];
+ samples[indice1]=a+W*b;
+ samples[indice2]=a-W*b;
+
+// kdDebug() << k_funcinfo << "PAPILLON s_" << indice1 << " s_" << indice2 << " W_" << (2<<level) << "^" << coefW << endl;
+ }
+ }
+
+ QMemArray<double> result(size);
+ for(uint f=0;f<size;f++)
+ {
+ result[f]=samples[f].Mod() / size;
+
+ }
+ return result;
+}
+
+
+
+
+QMemArray<double> VoiceSignature::fft(const Sound& sound, unsigned int start, unsigned int stop)
+{
+ return KHotKeys::fft(sound, start, stop);
+ /*QMemArray<double> result(8000);
+ for(int f=0; f<8000;f++)
+ {
+ Complex c(0);
+
+ for(uint x=start; x<stop; x++)
+ {
+ Complex s(sound.at(x));
+ double angle=-2*PI*f*x/8000;
+ s*= Complex( cos(angle) , sin(angle) );
+ c+=s;
+ }
+ result[f]= c.Mod()/(stop-start) ;
+ }
+ return result;*/
+}
+
+bool VoiceSignature::window(const Sound& sound, unsigned int *_start, unsigned int *_stop)
+{
+ bool isNoise=false;
+ unsigned int length=sound.size();
+ uint unit=WINDOW_UNIT;
+ if(length < unit )
+ return false;
+
+ //Fenêtrage
+ unsigned int start=0 , stop=0;
+ double moy=0;
+ for(uint x=0;x<unit;x++)
+ {
+ moy+=ABS(sound.at(x));
+ }
+
+ if(moy>WINDOW_MINIMUM*unit)
+ isNoise=true;
+
+ for(uint x=unit; x<length; x++)
+ {
+ if(moy<WINDOW_MINIMUM*unit)
+ {
+ if(stop==0)
+ start=x-unit/2;
+ }
+ else
+ stop=x-unit/2;
+ moy+=ABS(sound.at(x));
+ moy-=ABS(sound.at(x-unit));
+
+ }
+
+ if(moy>WINDOW_MINIMUM*unit && isNoise)
+ return false;
+
+ stop=MIN(length,stop+WINDOW_MINIMUM_ECART);
+ start=MAX(0 ,start-WINDOW_MINIMUM_ECART);
+
+ if(_start)
+ *_start=start;
+ if(_stop)
+ *_stop=stop;
+ return start<stop;
+}
+
+//finally doesn't give better results
+/*#define HZ_TO_MEL(F) (1127*log(1+(F)/700.0))
+#define MEL_TO_HZ(M) ( ( exp((M)/1127.0) -1) *700 )*/
+#define HZ_TO_MEL(F) (F)
+#define MEL_TO_HZ(F) (F)
+
+
+VoiceSignature::VoiceSignature(const Sound& sound)
+{
+ static uint temp_wind=0, temp_fft=0, temp_moy=0;
+ QTime t;
+ t.start();
+
+ unsigned int start , stop;
+ if(!window(sound,&start,&stop))
+ {
+ kdWarning( 1217 ) << k_funcinfo << "No voice found in the sound" << endl ;
+ return;
+ }
+
+ temp_wind+=t.restart();
+
+ uint length=stop-start;
+
+ for(int wind=0; wind<WINDOW_NUMBER; wind++)
+ {
+ unsigned int w_start=MAX(start, start+ (int)((wind - WINDOW_SUPER)*length/WINDOW_NUMBER));
+ unsigned int w_stop =MIN(stop , start+ (int)((wind+1.0+WINDOW_SUPER)*length/WINDOW_NUMBER));
+
+
+ QMemArray<double> fourrier=fft(sound, w_start,w_stop);
+
+ temp_fft+=t.restart();
+
+ //MEL conversion
+ double mel_start=HZ_TO_MEL(FFT_RANGE_INF);
+ uint mel_stop=HZ_TO_MEL(FFT_RANGE_SUP);
+
+ for(int four=0; four<FOUR_NUMBER; four++)
+ {
+ unsigned int wf_start=mel_start + four*(mel_stop-mel_start)/FOUR_NUMBER;
+ unsigned int wf_stop=mel_start + (four+1)*(mel_stop-mel_start)/FOUR_NUMBER;
+
+ unsigned int f_start=MEL_TO_HZ( wf_start )*fourrier.size()/sound.fs();
+ unsigned int f_stop=MEL_TO_HZ( wf_stop )*fourrier.size()/sound.fs();
+ unsigned int f_size=f_stop-f_start;
+
+ double nb=0;
+ for(uint f=f_start; f<f_stop; f++)
+ {
+ int freq=f*fourrier.size()/sound.fs();
+ nb+=fourrier[f]*FFT_PONDERATION(freq);
+ }
+ nb/=(f_size);
+ data[wind][four]=nb;
+ }
+
+ temp_moy+=t.restart();
+
+ }
+
+// kdDebug( 1217 ) << k_funcinfo << "wind: "<< temp_wind << " - fft: " << temp_fft << " - moy: " << temp_moy << endl;
+}
+
+
+
+VoiceSignature::~VoiceSignature()
+{
+}
+
+
+
+float VoiceSignature::diff(const VoiceSignature &s1, const VoiceSignature &s2)
+{
+ if(s1.isNull() || s2.isNull())
+ return 1000000;
+#if 0
+ double result=0;
+ for(int x=0;x<WINDOW_NUMBER;x++)
+ for(int y=0;y<FOUR_NUMBER;y++)
+ {
+ double d1=s1.data[x][y]-s2.data[x][y];
+ result+= d1*d1;//*pond[x][y];
+ }
+ return result;
+#endif
+
+ //DTW
+ // http://tcts.fpms.ac.be/cours/1005-08/speech/projects/2001/delfabro_henry_poitoux/
+
+ const int I=WINDOW_NUMBER;
+ const int J=WINDOW_NUMBER;
+ double g[I+1][J+1];
+ for(int f=1;f<=J;f++)
+ g[0][f]=10000000;
+ for(int f=1;f<=I;f++)
+ g[f][0]=10000000;
+ g[0][0]=0;
+ for(int i=1;i<=I;i++)
+ for(int j=1;j<=J;j++)
+ {
+ double d=0;
+ for(int f=0;f<FOUR_NUMBER;f++)
+ {
+ double d1=s1.data[i-1][f]-s2.data[j-1][f];
+ d+= d1*d1;//*pond[x][y];
+ }
+ d=sqrt(d);
+ g[i][j]=QMIN(QMIN( g[i-1][j]+d, g[i][j-1]+d ) , g[i-1][j-1]+d+d );
+ }
+
+ return g[I][J]/(I+J);
+}
+
+
+
+
+
+int VoiceSignature::size1()
+{
+ return WINDOW_NUMBER;
+}
+
+int VoiceSignature::size2()
+{
+ return FOUR_NUMBER;
+}
+
+QMap<int, QMap<int, double> > VoiceSignature::pond;
+
+
+
+void VoiceSignature::write(KConfigBase *cfg, const QString &key) const
+{
+ QStringList sl;
+ for(int x=0;x<WINDOW_NUMBER;x++)
+ for(int y=0;y<FOUR_NUMBER;y++)
+ {
+ sl.append( QString::number(data[x][y]) );
+ }
+ cfg->writeEntry(key,sl);
+}
+
+void VoiceSignature::read(KConfigBase *cfg, const QString &key)
+{
+ QStringList sl=cfg->readListEntry(key);
+ for(int x=0;x<WINDOW_NUMBER;x++)
+ for(int y=0;y<FOUR_NUMBER;y++)
+ {
+ data[x][y]= sl[x*FOUR_NUMBER+y].toDouble();
+ }
+}
+
+}
diff --git a/khotkeys/shared/voicesignature.h b/khotkeys/shared/voicesignature.h
new file mode 100644
index 000000000..b4857efd2
--- /dev/null
+++ b/khotkeys/shared/voicesignature.h
@@ -0,0 +1,101 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Olivier Goffart *
+ * ogoffart@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. *
+ ***************************************************************************/
+#ifndef SIGNATURE_H
+#define SIGNATURE_H
+
+
+#include <qmemarray.h>
+#include <qmap.h>
+#include <kdemacros.h>
+
+class Sound;
+class KConfigBase;
+
+
+#define WINDOW_MINIMUM 0.10
+#define WINDOW_MINIMUM_ECART 200
+#define WINDOW_NUMBER 7
+#define WINDOW_SUPER 0.43
+#define WINDOW_UNIT sound.fs()/4
+#define FOUR_NUMBER 7
+#define FOUR_SUPER 0
+
+
+#define FFT_RANGE_INF 370
+#define FFT_RANGE_SUP 2000
+// #define FFT_PONDERATION(f) ((double)log(1+(f))/log(10))
+#define FFT_PONDERATION(f) 1
+
+
+// theses settings are better in a 8000Hz fs
+/*#define FFT_RANGE_INF 300
+#define FFT_RANGE_SUP 1500*/
+
+
+//#define REJECT_FACTOR_ECART_REL 0.5
+#define REJECT_FACTOR_DIFF 0.0018
+
+
+
+#define HAMMING false
+
+
+
+
+namespace KHotKeys
+{
+
+
+/**
+@author Olivier Goffart
+*/
+class KDE_EXPORT VoiceSignature{
+public:
+ explicit VoiceSignature(const Sound& s);
+
+ VoiceSignature(){}
+ ~VoiceSignature();
+
+ QMap<int, QMap<int, double> > data;
+
+ static QMap<int, QMap<int, double> > pond;
+
+ static float diff(const VoiceSignature &s1, const VoiceSignature &s2);
+
+
+ static int size1();
+ static int size2();
+
+
+ static QMemArray<double> fft(const Sound& sound, unsigned int start, unsigned int stop);
+ static bool window(const Sound& sound, unsigned int *start, unsigned int *stop);
+
+ void write(KConfigBase *cfg, const QString &key) const;
+ void read(KConfigBase *cfg, const QString &key);
+
+ inline bool isNull() const
+ {
+ return data.isEmpty();
+ }
+};
+
+}
+
+#endif
diff --git a/khotkeys/shared/windows.cpp b/khotkeys/shared/windows.cpp
new file mode 100644
index 000000000..d269ef2fe
--- /dev/null
+++ b/khotkeys/shared/windows.cpp
@@ -0,0 +1,376 @@
+/****************************************************************************
+
+ KHotKeys
+
+ Copyright (C) 1999-2001 Lubos Lunak <l.lunak@kde.org>
+
+ Distributed under the terms of the GNU General Public License version 2.
+
+****************************************************************************/
+
+#define _WINDOWS_CPP_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "windows.h"
+
+#include <assert.h>
+#include <qregexp.h>
+
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kwinmodule.h>
+#include <kwin.h>
+#include <klocale.h>
+
+#include "khotkeysglobal.h"
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+extern Atom qt_window_role;
+
+namespace KHotKeys
+{
+
+// Windows
+
+Windows::Windows( bool enable_signal_P, QObject* parent_P )
+ : QObject( parent_P ), signals_enabled( enable_signal_P ),
+ kwin_module( new KWinModule( this )), _action_window( 0 )
+ {
+ assert( windows_handler == NULL );
+ windows_handler = this;
+ if( signals_enabled )
+ {
+ connect( kwin_module, SIGNAL( windowAdded( WId )), SLOT( window_added_slot( WId )));
+ connect( kwin_module, SIGNAL( windowRemoved( WId )), SLOT( window_removed_slot( WId )));
+ connect( kwin_module, SIGNAL( activeWindowChanged( WId )),
+ SLOT( active_window_changed_slot( WId )));
+ }
+ }
+
+Windows::~Windows()
+ {
+ windows_handler = NULL;
+ }
+
+void Windows::window_added_slot( WId window_P )
+ {
+ if( signals_enabled )
+ emit window_added( window_P );
+ // CHECKME tyhle i dalsi by asi mely jit nastavit, jestli aktivuji vsechny, nebo jen jeden
+ // pripojeny slot ( stejne jako u Kdb, kde by to take melo jit nastavit )
+ }
+
+void Windows::window_removed_slot( WId window_P )
+ {
+ if( signals_enabled )
+ emit window_removed( window_P );
+ if( window_P == _action_window )
+ _action_window = 0;
+ }
+
+void Windows::active_window_changed_slot( WId window_P )
+ {
+ if( signals_enabled )
+ emit active_window_changed( window_P );
+ }
+
+void Windows::window_changed_slot( WId window_P )
+ {
+ if( signals_enabled )
+ emit window_changed( window_P );
+ }
+
+void Windows::window_changed_slot( WId window_P, unsigned int flags_P )
+ {
+ if( signals_enabled )
+ emit window_changed( window_P, flags_P );
+ }
+
+QString Windows::get_window_role( WId id_P )
+ {
+ // TODO this is probably just a hack
+ return KWin::readNameProperty( id_P, qt_window_role );
+ }
+
+QString Windows::get_window_class( WId id_P )
+ {
+ XClassHint hints_ret;
+ if( XGetClassHint( qt_xdisplay(), id_P, &hints_ret ) == 0 ) // 0 means error
+ return "";
+ QString ret( hints_ret.res_name );
+ ret += ' ';
+ ret += hints_ret.res_class;
+ XFree( hints_ret.res_name );
+ XFree( hints_ret.res_class );
+ return ret;
+ }
+
+WId Windows::active_window()
+ {
+ return kwin_module->activeWindow();
+ }
+
+WId Windows::action_window()
+ {
+ return _action_window;
+ }
+
+void Windows::set_action_window( WId window_P )
+ {
+ _action_window = window_P;
+ }
+
+WId Windows::find_window( const Windowdef_list* window_P )
+ {
+ for( QValueList< WId >::ConstIterator it = kwin_module->windows().begin();
+ it != kwin_module->windows().end();
+ ++it )
+ {
+ Window_data tmp( *it );
+ if( window_P->match( tmp ))
+ return *it;
+ }
+ return None;
+ }
+
+WId Windows::window_at_position( int x, int y )
+ {
+ Window child, dummy;
+ Window parent = qt_xrootwin();
+ Atom wm_state = XInternAtom( qt_xdisplay(), "WM_STATE", False );
+ for( int i = 0;
+ i < 10;
+ ++i )
+ {
+ int destx, desty;
+ // find child at that position
+ if( !XTranslateCoordinates( qt_xdisplay(), parent, parent, x, y, &destx, &desty, &child )
+ || child == None )
+ return 0;
+ // and now transform coordinates to the child
+ if( !XTranslateCoordinates( qt_xdisplay(), parent, child, x, y, &destx, &desty, &dummy ))
+ return 0;
+ x = destx;
+ y = desty;
+ Atom type;
+ int format;
+ unsigned long nitems, after;
+ unsigned char* prop;
+ if( XGetWindowProperty( qt_xdisplay(), child, wm_state, 0, 0, False, AnyPropertyType,
+ &type, &format, &nitems, &after, &prop ) == Success )
+ {
+ if( prop != NULL )
+ XFree( prop );
+ if( type != None )
+ return child;
+ }
+ parent = child;
+ }
+ return 0;
+
+ }
+
+void Windows::activate_window( WId id_P )
+ {
+ KWin::forceActiveWindow( id_P );
+ }
+
+// Window_data
+
+Window_data::Window_data( WId id_P )
+ : type( NET::Unknown )
+ {
+ KWin::WindowInfo kwin_info = KWin::windowInfo( id_P, NET::WMName | NET::WMWindowType ); // TODO optimize
+ if( kwin_info.valid())
+ {
+ title = kwin_info.name();
+ role = windows_handler->get_window_role( id_P );
+ wclass = windows_handler->get_window_class( id_P );
+ type = kwin_info.windowType( SUPPORTED_WINDOW_TYPES_MASK );
+ if( type == NET::Override ) // HACK consider non-NETWM fullscreens to be normal too
+ type = NET::Normal;
+ if( type == NET::Unknown )
+ type = NET::Normal;
+ }
+ }
+
+// Windowdef
+
+void Windowdef::cfg_write( KConfig& cfg_P ) const
+ {
+ cfg_P.writeEntry( "Type", "ERROR" );
+ cfg_P.writeEntry( "Comment", comment());
+ }
+
+Windowdef::Windowdef( KConfig& cfg_P )
+ {
+ _comment = cfg_P.readEntry( "Comment" );
+ }
+
+Windowdef* Windowdef::create_cfg_read( KConfig& cfg_P )
+ {
+ QString type = cfg_P.readEntry( "Type" );
+ if( type == "SIMPLE" )
+ return new Windowdef_simple( cfg_P );
+ kdWarning( 1217 ) << "Unknown Windowdef type read from cfg file\n";
+ return NULL;
+ }
+
+// Windowdef_list
+
+Windowdef_list::Windowdef_list( KConfig& cfg_P )
+ : QPtrList< Windowdef >()
+ {
+ setAutoDelete( true );
+ QString save_cfg_group = cfg_P.group();
+ _comment = cfg_P.readEntry( "Comment" );
+ int cnt = cfg_P.readNumEntry( "WindowsCount", 0 );
+ for( int i = 0;
+ i < cnt;
+ ++i )
+ {
+ cfg_P.setGroup( save_cfg_group + QString::number( i ));
+ Windowdef* window = Windowdef::create_cfg_read( cfg_P );
+ if( window )
+ append( window );
+ }
+ cfg_P.setGroup( save_cfg_group );
+ }
+
+void Windowdef_list::cfg_write( KConfig& cfg_P ) const
+ {
+ QString save_cfg_group = cfg_P.group();
+ int i = 0;
+ for( Iterator it( *this );
+ it;
+ ++it, ++i )
+ {
+ cfg_P.setGroup( save_cfg_group + QString::number( i ));
+ it.current()->cfg_write( cfg_P );
+ }
+ cfg_P.setGroup( save_cfg_group );
+ cfg_P.writeEntry( "WindowsCount", i );
+ cfg_P.writeEntry( "Comment", comment());
+ }
+
+Windowdef_list* Windowdef_list::copy() const
+ {
+ Windowdef_list* ret = new Windowdef_list( comment());
+ for( Iterator it( *this );
+ it;
+ ++it )
+ ret->append( it.current()->copy());
+ return ret;
+ }
+
+
+bool Windowdef_list::match( const Window_data& window_P ) const
+ {
+ if( count() == 0 ) // CHECKME no windows to match => ok
+ return true;
+ for( Iterator it( *this );
+ it;
+ ++it )
+ if( it.current()->match( window_P ))
+ return true;
+ return false;
+ }
+
+// Windowdef_simple
+
+Windowdef_simple::Windowdef_simple( const QString& comment_P, const QString& title_P,
+ substr_type_t title_type_P, const QString& wclass_P, substr_type_t wclass_type_P,
+ const QString& role_P, substr_type_t role_type_P, int window_types_P )
+ : Windowdef( comment_P ), _title( title_P ), title_type( title_type_P ),
+ _wclass( wclass_P ), wclass_type( wclass_type_P ), _role( role_P ),
+ role_type( role_type_P ), _window_types( window_types_P )
+ {
+ }
+
+Windowdef_simple::Windowdef_simple( KConfig& cfg_P )
+ : Windowdef( cfg_P )
+ {
+ _title = cfg_P.readEntry( "Title" );
+ title_type = static_cast< substr_type_t >( cfg_P.readNumEntry( "TitleType" ));
+ _wclass = cfg_P.readEntry( "Class" );
+ wclass_type = static_cast< substr_type_t >( cfg_P.readNumEntry( "ClassType" ));
+ _role = cfg_P.readEntry( "Role" );
+ role_type = static_cast< substr_type_t >( cfg_P.readNumEntry( "RoleType" ));
+ _window_types = cfg_P.readNumEntry( "WindowTypes" );
+ }
+
+void Windowdef_simple::cfg_write( KConfig& cfg_P ) const
+ {
+ base::cfg_write( cfg_P );
+ cfg_P.writeEntry( "Title", title());
+ cfg_P.writeEntry( "TitleType", title_type );
+ cfg_P.writeEntry( "Class", wclass());
+ cfg_P.writeEntry( "ClassType", wclass_type );
+ cfg_P.writeEntry( "Role", role());
+ cfg_P.writeEntry( "RoleType", role_type );
+ cfg_P.writeEntry( "WindowTypes", window_types());
+ cfg_P.writeEntry( "Type", "SIMPLE" ); // overwrites value set in base::cfg_write()
+ }
+
+bool Windowdef_simple::match( const Window_data& window_P )
+ {
+ if( !type_match( window_P.type ))
+ return false;
+ if( !is_substr_match( window_P.title, title(), title_type ))
+ return false;
+ if( !is_substr_match( window_P.wclass, wclass(), wclass_type ))
+ return false;
+ if( !is_substr_match( window_P.role, role(), role_type ))
+ return false;
+ kdDebug( 1217 ) << "window match:" << window_P.title << ":OK" << endl;
+ return true;
+ }
+
+bool Windowdef_simple::is_substr_match( const QString& str1_P, const QString& str2_P,
+ substr_type_t type_P )
+ {
+ switch( type_P )
+ {
+ case NOT_IMPORTANT :
+ return true;
+ case CONTAINS :
+ return str1_P.contains( str2_P ) > 0;
+ case IS :
+ return str1_P == str2_P;
+ case REGEXP :
+ {
+ QRegExp rg( str2_P );
+ return rg.search( str1_P ) >= 0;
+ }
+ case CONTAINS_NOT :
+ return str1_P.contains( str2_P ) == 0;
+ case IS_NOT :
+ return str1_P != str2_P;
+ case REGEXP_NOT :
+ {
+ QRegExp rg( str2_P );
+ return rg.search( str1_P ) < 0;
+ }
+ }
+ return false;
+ }
+
+Windowdef* Windowdef_simple::copy() const
+ {
+ return new Windowdef_simple( comment(), title(), title_match_type(), wclass(),
+ wclass_match_type(), role(), role_match_type(), window_types());
+ }
+
+const QString Windowdef_simple::description() const
+ {
+ return i18n( "Window simple: " ) + comment();
+ }
+
+} // namespace KHotKeys
+
+#include "windows.moc"
diff --git a/khotkeys/shared/windows.h b/khotkeys/shared/windows.h
new file mode 100644
index 000000000..f048ce6b9
--- /dev/null
+++ b/khotkeys/shared/windows.h
@@ -0,0 +1,264 @@
+/****************************************************************************
+
+ KHotKeys
+
+ Copyright (C) 1999-2001 Lubos Lunak <l.lunak@kde.org>
+
+ Distributed under the terms of the GNU General Public License version 2.
+
+****************************************************************************/
+
+#ifndef _WINDOWS_H_
+#define _WINDOWS_H_
+
+#include <sys/types.h>
+
+#include <qobject.h>
+#include <qstring.h>
+#include <qptrlist.h>
+
+#include <netwm_def.h>
+
+#include "khotkeysglobal.h"
+
+class KConfig;
+class KWinModule;
+
+namespace KHotKeys
+{
+
+const int SUPPORTED_WINDOW_TYPES_MASK = NET::NormalMask | NET::DesktopMask | NET::DockMask
+ | NET::ToolbarMask | NET::MenuMask | NET::DialogMask | NET::OverrideMask | NET::TopMenuMask
+ | NET::UtilityMask | NET::SplashMask;
+
+class Windowdef_list;
+/*class Action_data_base;*/
+
+class KDE_EXPORT Windows
+ : public QObject
+ {
+ Q_OBJECT
+ public:
+ Windows( bool enable_signals_P, QObject* parent_P );
+ virtual ~Windows();
+ QString get_window_class( WId id_P );
+ QString get_window_role( WId id_P );
+ WId active_window();
+ void set_action_window( WId window );
+ WId action_window();
+ WId find_window( const Windowdef_list* window_P );
+ static WId window_at_position( int x, int y );
+ static void activate_window( WId id_P );
+ signals:
+ void window_added( WId window_P );
+ void window_removed( WId window_P );
+ void active_window_changed( WId window_P );
+ void window_changed( WId window_P );
+ void window_changed( WId window_P, unsigned int flags_P );
+ protected slots:
+ void window_added_slot( WId window_P );
+ void window_removed_slot( WId window_P );
+ void active_window_changed_slot( WId window_P );
+ void window_changed_slot( WId window_P );
+ void window_changed_slot( WId window_P, unsigned int flags_P );
+ private:
+ bool signals_enabled;
+ KWinModule* kwin_module;
+ WId _action_window;
+ };
+
+struct KDE_EXPORT Window_data
+ {
+ Window_data( WId id_P );
+ QString title; // _NET_WM_NAME or WM_NAME
+ QString role; // WM_WINDOW_ROLE
+ QString wclass; // WM_CLASS
+ NET::WindowType type;
+ };
+
+class KDE_EXPORT Windowdef
+ {
+ public:
+ Windowdef( const QString& comment_P );
+ Windowdef( KConfig& cfg_P );
+ virtual ~Windowdef();
+ const QString& comment() const;
+ virtual bool match( const Window_data& window_P ) = 0;
+ static Windowdef* create_cfg_read( KConfig& cfg_P/*, Action_data_base* data_P*/ );
+ virtual void cfg_write( KConfig& cfg_P ) const = 0;
+ virtual Windowdef* copy( /*Action_data_base* data_P*/ ) const = 0;
+ virtual const QString description() const = 0;
+ private:
+ QString _comment;
+ KHOTKEYS_DISABLE_COPY( Windowdef ); // CHECKME asi pak udelat i pro vsechny potomky, at se nezapomene
+ };
+
+class KDE_EXPORT Windowdef_list
+ : public QPtrList< Windowdef >
+ {
+ public:
+ Windowdef_list( const QString& comment_P );
+ Windowdef_list( KConfig& cfg_P/*, Action_data_base* data_P*/ );
+ void cfg_write( KConfig& cfg_P ) const;
+ bool match( const Window_data& window_P ) const;
+ Windowdef_list* copy( /*Action_data_base* data_P*/ ) const;
+ typedef QPtrListIterator< Windowdef > Iterator;
+ const QString& comment() const;
+ private:
+ QString _comment;
+ KHOTKEYS_DISABLE_COPY( Windowdef_list );
+ };
+
+class KDE_EXPORT Windowdef_simple
+ : public Windowdef
+ {
+ typedef Windowdef base;
+ public:
+ enum substr_type_t
+ {
+ NOT_IMPORTANT,
+ CONTAINS,
+ IS,
+ REGEXP,
+ CONTAINS_NOT,
+ IS_NOT,
+ REGEXP_NOT
+ };
+ enum window_type_t
+ {
+ WINDOW_TYPE_NORMAL = ( 1 << NET::Normal ),
+ WINDOW_TYPE_DESKTOP = ( 1 << NET::Desktop ),
+ WINDOW_TYPE_DOCK = ( 1 << NET::Dock ),
+// WINDOW_TYPE_TOOL = ( 1 << NET::Tool ),
+// WINDOW_TYPE_MENU = ( 1 << NET::Menu ),
+ WINDOW_TYPE_DIALOG = ( 1 << NET::Dialog )
+ };
+ Windowdef_simple( const QString& comment_P, const QString& title_P,
+ substr_type_t title_type_P, const QString& wclass_P, substr_type_t wclass_type_P,
+ const QString& role_P, substr_type_t role_type_P, int window_types_P );
+ Windowdef_simple( KConfig& cfg_P );
+ virtual bool match( const Window_data& window_P );
+ virtual void cfg_write( KConfig& cfg_P ) const;
+ const QString& title() const;
+ substr_type_t title_match_type() const;
+ const QString& wclass() const;
+ substr_type_t wclass_match_type() const;
+ const QString& role() const;
+ substr_type_t role_match_type() const;
+ int window_types() const;
+ bool type_match( window_type_t type_P ) const;
+ bool type_match( NET::WindowType type_P ) const;
+ virtual Windowdef* copy( /*Action_data_base* data_P*/ ) const;
+ virtual const QString description() const;
+ protected:
+ bool is_substr_match( const QString& str1_P, const QString& str2_P,
+ substr_type_t type_P );
+ private:
+ QString _title;
+ substr_type_t title_type;
+ QString _wclass;
+ substr_type_t wclass_type;
+ QString _role;
+ substr_type_t role_type;
+ int _window_types;
+ };
+
+//***************************************************************************
+// Inline
+//***************************************************************************
+
+// Windowdef
+
+inline
+Windowdef::Windowdef( const QString& comment_P )
+ : _comment( comment_P )
+ {
+ }
+
+inline
+const QString& Windowdef::comment() const
+ {
+ return _comment;
+ }
+
+inline
+Windowdef::~Windowdef()
+ {
+ }
+
+// Windowdef_list
+
+inline
+Windowdef_list::Windowdef_list( const QString& comment_P )
+ : QPtrList< Windowdef >(), _comment( comment_P )
+ {
+ setAutoDelete( true );
+ }
+
+inline
+const QString& Windowdef_list::comment() const
+ {
+ return _comment;
+ }
+
+// Windowdef_simple
+
+inline
+const QString& Windowdef_simple::title() const
+ {
+ return _title;
+ }
+
+inline
+Windowdef_simple::substr_type_t Windowdef_simple::title_match_type() const
+ {
+ return title_type;
+ }
+
+inline
+const QString& Windowdef_simple::wclass() const
+ {
+ return _wclass;
+ }
+
+inline
+Windowdef_simple::substr_type_t Windowdef_simple::wclass_match_type() const
+ {
+ return wclass_type;
+ }
+
+inline
+const QString& Windowdef_simple::role() const
+ {
+ return _role;
+ }
+
+inline
+Windowdef_simple::substr_type_t Windowdef_simple::role_match_type() const
+ {
+ return role_type;
+ }
+
+inline
+int Windowdef_simple::window_types() const
+ {
+ return _window_types;
+ }
+
+inline
+bool Windowdef_simple::type_match( window_type_t type_P ) const
+ {
+ return window_types() & type_P;
+ }
+
+inline
+bool Windowdef_simple::type_match( NET::WindowType type_P ) const
+ {
+ return ( window_types() & ( 1 << type_P ))
+ || ( type_P == NET::Unknown && ( window_types() & WINDOW_TYPE_NORMAL ));
+ // CHECKME HACK haaaack !
+ }
+
+} // namespace KHotKeys
+
+#endif