/**************************************************************************** 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 <tdeconfig.h> #include <kdebug.h> #include <kurifilter.h> #include <tdeglobal.h> #include <kstandarddirs.h> #include <tdeapplication.h> #include <dcopclient.h> #include <kdesktopfile.h> #include <tdelocale.h> #include <tdeaccel.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( TDEConfig& cfg_P, Action_data* data_P ) { TQString 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( TDEConfig& cfg_P ) const { cfg_P.writeEntry( "Type", "ERROR" ); // derived classes should call with their type } // Action_list Action_list::Action_list( TDEConfig& cfg_P, Action_data* data_P ) : TQPtrList< Action >() { setAutoDelete( true ); TQString 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 + TQString::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( TDEConfig& cfg_P ) const { TQString save_cfg_group = cfg_P.group(); int i = 0; for( Iterator it( *this ); it; ++it, ++i ) { cfg_P.setGroup( save_cfg_group + TQString::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( TDEConfig& cfg_P, Action_data* data_P ) : Action( cfg_P, data_P ) { _command_url = cfg_P.readEntry( "CommandURL" ); } void Command_url_action::cfg_write( TDEConfig& 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; TQString 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 } TQString 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( TDEConfig& 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 } TQString Menuentry_action::description() const { (void) service(); return i18n( "Menuentry : " ) + (_service ? _service->name() : TQString::null); } Action* Menuentry_action::copy( Action_data* data_P ) const { return new Menuentry_action( data_P, command_url()); } // Dcop_action Dcop_action::Dcop_action( TDEConfig& 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( TDEConfig& 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; TQStringList args_list; TQString args_str = args; while( !args_str.isEmpty()) { unsigned int pos = 0; while( args_str[ pos ] == ' ' ) ++pos; if( args_str[ pos ] == '\"' || args_str[ pos ] == '\'' ) { TQString val = ""; TQChar 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; TDEProcess proc; proc << "dcop" << app << obj << call << args_list; proc.start( TDEProcess::DontCare ); } TQString 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( TDEConfig& cfg_P, Action_data* data_P ) : Action( cfg_P, data_P ) { _input = cfg_P.readEntry( "Input" ); if( cfg_P.readBoolEntry( "IsDestinationWindow" )) { TQString 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( TDEConfig& 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 ); TQString 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 ';' { TQString 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 TQString 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( tqt_xdisplay()); } TQString Keyboard_input_action::description() const { TQString 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( TDEConfig& cfg_P, Action_data* data_P ) : Action( cfg_P, data_P ) { TQString 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( TDEConfig& cfg_P ) const { base::cfg_write( cfg_P ); cfg_P.writeEntry( "Type", "ACTIVATE_WINDOW" ); // overwrites value set in base::cfg_write() TQString 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 ); } TQString 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