/***************************************************************************
plugin_kateinsertcommand . cpp - description
- - - - - - - - - - - - - - - - - - -
begin : THU Apr 19 2001
copyright : ( C ) 2001 by Anders Lund
email : anders @ alweb . dk
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/***************************************************************************
* *
* 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 . *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//BEGIN includes
# include "plugin_kateinsertcommand.h"
# include "plugin_kateinsertcommand.moc"
# include <tqbuttongroup.h>
# include <tqcheckbox.h>
# include <tqdir.h>
# include <tqfile.h>
# include <tqlabel.h>
# include <tqlayout.h>
# include <tqradiobutton.h>
# include <tqspinbox.h>
# include <tqstringlist.h>
# include <tqwhatsthis.h>
# include <tqwidget.h>
# include <tdeaction.h>
# include <kanimwidget.h>
# include <tdeconfig.h>
# include <kdebug.h>
# include <tdefiledialog.h>
# include <kiconloader.h>
# include <tdelocale.h>
# include <tdemessagebox.h>
# include <kprocess.h>
# include <kstandarddirs.h>
# include <kgenericfactory.h>
# include <tdeapplication.h>
//END includes
K_EXPORT_COMPONENT_FACTORY ( kateinsertcommandplugin , KGenericFactory < PluginKateInsertCommand > ( " kateinsertcommand " ) )
//BEGIN obligatory stuff
class PluginView : public KXMLGUIClient
{
friend class PluginKateInsertCommand ;
public :
Kate : : MainWindow * win ;
} ;
//END
//BEGIN PluginKateInsertCommand
PluginKateInsertCommand : : PluginKateInsertCommand ( TQObject * parent , const char * name , const TQStringList & )
: Kate : : Plugin ( ( Kate : : Application * ) parent , name ) ,
kv ( 0 ) ,
sh ( 0 )
{
config = new TDEConfig ( " kateinsertcommandpluginrc " ) ;
cmdhist = config - > readListEntry ( " Command History " ) ;
wdlg = 0 ;
workingdir = TQDir : : currentDirPath ( ) ;
}
PluginKateInsertCommand : : ~ PluginKateInsertCommand ( )
{
// write config file
config - > writeEntry ( " Command History " , cmdhist ) ;
config - > writeEntry ( " Dialog Settings " , dialogSettings ) ;
config - > sync ( ) ;
delete config ;
delete sh ;
}
void PluginKateInsertCommand : : addView ( Kate : : MainWindow * win )
{
// TODO: doesn't this have to be deleted?
PluginView * view = new PluginView ( ) ;
( void ) new TDEAction ( i18n ( " Insert Command... " ) , " " , 0 , this ,
TQ_SLOT ( slotInsertCommand ( ) ) , view - > actionCollection ( ) ,
" edit_insert_command " ) ;
view - > setInstance ( new TDEInstance ( " kate " ) ) ;
view - > setXMLFile ( " plugins/kateinsertcommand/ui.rc " ) ;
win - > guiFactory ( ) - > addClient ( view ) ;
view - > win = win ;
m_views . append ( view ) ;
}
void PluginKateInsertCommand : : removeView ( Kate : : MainWindow * win )
{
for ( uint z = 0 ; z < m_views . count ( ) ; z + + )
if ( m_views . at ( z ) - > win = = win )
{
PluginView * view = m_views . at ( z ) ;
m_views . remove ( view ) ;
win - > guiFactory ( ) - > removeClient ( view ) ;
delete view ;
}
}
void PluginKateInsertCommand : : slotInsertCommand ( )
{
if ( ! kapp - > authorize ( " shell_access " ) ) {
KMessageBox : : sorry ( 0 , i18n ( " You are not allowed to execute arbitrary external applications. If you want to be able to do this, contact your system administrator. " ) , i18n ( " Access Restrictions " ) ) ;
return ;
}
if ( sh & & sh - > isRunning ( ) ) {
KMessageBox : : sorry ( 0 , i18n ( " A process is currently being executed. " ) ,
i18n ( " Error " ) ) ;
return ;
}
if ( ! application ( ) - > activeMainWindow ( ) | | ! application ( ) - > activeMainWindow ( ) - > viewManager ( ) - > activeView ( ) )
return ;
kv = application ( ) - > activeMainWindow ( ) - > viewManager ( ) - > activeView ( ) ;
TQString dir = workingdir ;
TQString docdir ;
KURL docurl = kv - > getDoc ( ) - > url ( ) ;
if ( docurl . isLocalFile ( ) )
docdir = docurl . directory ( ) ;
TQString lwd ( config - > readPathEntry ( " Last WD " ) ) ;
switch ( ( int ) config - > readNumEntry ( " Start In " , 0 ) )
{
case 1 :
if ( ! docdir . isEmpty ( ) ) dir = docdir ;
break ;
case 2 :
if ( ! lwd . isEmpty ( ) ) dir = lwd ;
break ;
default :
break ;
}
dialogSettings = config - > readNumEntry ( " Dialog Settings " , 0 ) ;
CmdPrompt * d = new CmdPrompt ( ( TQWidget * ) kv , 0 , cmdhist , dir ,
docdir , dialogSettings ) ;
if ( d - > exec ( ) & & ! d - > command ( ) . isEmpty ( ) ) {
if ( ! sh ) {
sh = new KShellProcess ;
connect ( sh , TQ_SIGNAL ( receivedStdout ( TDEProcess * , char * , int ) ) ,
this , TQ_SLOT ( slotReceivedStdout ( TDEProcess * , char * , int ) ) ) ;
connect ( sh , TQ_SIGNAL ( receivedStderr ( TDEProcess * , char * , int ) ) ,
this , TQ_SLOT ( slotReceivedStderr ( TDEProcess * , char * , int ) ) ) ;
connect ( sh , TQ_SIGNAL ( processExited ( TDEProcess * ) ) ,
this , TQ_SLOT ( slotProcessExited ( TDEProcess * ) ) ) ;
}
sh - > clearArguments ( ) ;
bInsStdErr = d - > insertStdErr ( ) ;
if ( d - > printCmd ( ) ) {
if ( ! d - > wd ( ) . isEmpty ( ) )
kv - > insertText ( d - > wd ( ) + " : " ) ;
kv - > insertText ( d - > command ( ) + " : \n " ) ;
}
if ( ! d - > wd ( ) . isEmpty ( ) ) {
* sh < < " cd " < < d - > wd ( ) < < " && " ;
config - > writePathEntry ( " Last WD " , d - > wd ( ) ) ;
}
* sh < < TQFile : : encodeName ( d - > command ( ) ) . data ( ) ;
sh - > start ( TDEProcess : : NotifyOnExit , TDEProcess : : All ) ;
// add command to history
if ( cmdhist . contains ( d - > command ( ) ) ) {
cmdhist . remove ( d - > command ( ) ) ;
}
cmdhist . prepend ( d - > command ( ) ) ;
int cmdhistlen = config - > readNumEntry ( " Command History Length " , 20 ) ;
while ( ( int ) cmdhist . count ( ) > cmdhistlen )
cmdhist . remove ( cmdhist . last ( ) ) ;
// save dialog state
dialogSettings = 0 ;
if ( d - > insertStdErr ( ) )
dialogSettings + = 1 ;
if ( d - > printCmd ( ) )
dialogSettings + = 2 ;
cmd = d - > command ( ) ;
delete d ;
// If process is still running, display a dialog to cancel...
slotShowWaitDlg ( ) ;
config - > writeEntry ( " Dialog Settings " , dialogSettings ) ;
config - > sync ( ) ;
}
}
void PluginKateInsertCommand : : slotAbort ( )
{
if ( sh - > isRunning ( ) )
if ( ! sh - > kill ( ) )
KMessageBox : : sorry ( 0 , i18n ( " Could not kill command. " ) , i18n ( " Kill Failed " ) ) ;
}
void PluginKateInsertCommand : : slotShowWaitDlg ( )
{
if ( sh - > isRunning ( ) ) {
wdlg = new WaitDlg ( ( TQWidget * ) kv , i18n (
" Executing command: \n %1 \n \n Press 'Cancel' to abort. " ) . arg ( cmd ) ) ;
connect ( wdlg , TQ_SIGNAL ( cancelClicked ( ) ) , this , TQ_SLOT ( slotAbort ( ) ) ) ;
}
if ( sh - > isRunning ( ) ) // we may have finished while creating the dialog.
wdlg - > show ( ) ;
else if ( wdlg ) { // process may have exited before the WaitDlg constructor returned.
delete wdlg ;
wdlg = 0 ;
}
}
void PluginKateInsertCommand : : slotReceivedStdout ( TDEProcess * /*p*/ , char * text ,
int len )
{
TQString t = TQString : : fromLocal8Bit ( text ) ;
t . truncate ( len ) ;
kv - > insertText ( t ) ;
}
void PluginKateInsertCommand : : slotReceivedStderr ( TDEProcess * p , char * text ,
int len )
{
if ( bInsStdErr )
slotReceivedStdout ( p , text , len ) ;
}
void PluginKateInsertCommand : : slotProcessExited ( TDEProcess * p )
{
if ( wdlg ) {
wdlg - > hide ( ) ;
delete wdlg ;
wdlg = 0 ;
}
if ( ! p - > normalExit ( ) )
KMessageBox : : sorry ( 0 , i18n ( " Command exited with status %1 " ) .
arg ( p - > exitStatus ( ) ) , i18n ( " Oops! " ) ) ;
kv - > setFocus ( ) ;
}
//END PluginKateInsertCommand
//BEGIN PluginConfigPage
Kate : : PluginConfigPage * PluginKateInsertCommand : : configPage ( uint ,
TQWidget * w , const char */ * name */ )
{
InsertCommandConfigPage * p = new InsertCommandConfigPage ( this , w ) ;
initConfigPage ( p ) ;
connect ( p , TQ_SIGNAL ( configPageApplyRequest ( InsertCommandConfigPage * ) ) ,
this , TQ_SLOT ( applyConfig ( InsertCommandConfigPage * ) ) ) ;
return ( Kate : : PluginConfigPage * ) p ;
}
void PluginKateInsertCommand : : initConfigPage ( InsertCommandConfigPage * p )
{
p - > sb_cmdhistlen - > setValue ( config - > readNumEntry ( " Command History Length " , 20 ) ) ;
p - > rg_startin - > setButton ( config - > readNumEntry ( " Start In " , 0 ) ) ;
}
void PluginKateInsertCommand : : applyConfig ( InsertCommandConfigPage * p )
{
config - > writeEntry ( " Command History Length " , p - > sb_cmdhistlen - > value ( ) ) ;
// truncate the cmd hist if nessecary?
config - > writeEntry ( " Start In " , p - > rg_startin - > id ( p - > rg_startin - > selected ( ) ) ) ;
config - > sync ( ) ;
}
//END PluginConfigPage
//BEGIN CmdPrompt
// This is a simple dialog to retrieve a command and decide if
// stdErr should be included in the text inserted.
CmdPrompt : : CmdPrompt ( TQWidget * parent ,
const char * name ,
const TQStringList & cmdhist ,
const TQString & dir ,
const TQString & /*docdir*/ ,
int settings )
: KDialogBase ( parent , name , true , i18n ( " Insert Command " ) , Ok | Cancel , Ok , true )
{
TQWidget * page = new TQWidget ( this ) ;
setMainWidget ( page ) ;
TQVBoxLayout * lo = new TQVBoxLayout ( page , 0 , spacingHint ( ) ) ;
TQLabel * l = new TQLabel ( i18n ( " Enter &command: " ) , page ) ;
lo - > addWidget ( l ) ;
cmb_cmd = new KHistoryCombo ( true , page ) ;
cmb_cmd - > setHistoryItems ( cmdhist , true ) ;
cmb_cmd - > setCurrentItem ( 0 ) ;
cmb_cmd - > lineEdit ( ) - > setSelection ( 0 , cmb_cmd - > currentText ( ) . length ( ) ) ;
l - > setBuddy ( cmb_cmd ) ;
cmb_cmd - > setFocus ( ) ;
lo - > addWidget ( cmb_cmd ) ;
connect ( cmb_cmd - > lineEdit ( ) , TQ_SIGNAL ( textChanged ( const TQString & ) ) ,
this , TQ_SLOT ( slotTextChanged ( const TQString & ) ) ) ;
TQLabel * lwd = new TQLabel ( i18n ( " Choose &working folder: " ) , page ) ;
lo - > addWidget ( lwd ) ;
wdreq = new KURLRequester ( page ) ;
if ( ! dir . isEmpty ( ) )
wdreq - > setURL ( dir ) ;
wdreq - > setMode ( static_cast < KFile : : Mode > ( KFile : : Directory | KFile : : LocalOnly | KFile : : ExistingOnly ) ) ;
lwd - > setBuddy ( wdreq ) ;
lo - > addWidget ( wdreq ) ;
//kdDebug()<<"settings: "<<settings<<endl;
cb_insStdErr = new TQCheckBox ( i18n ( " Insert Std&Err messages " ) , page ) ;
cb_insStdErr - > setChecked ( settings & 1 ) ;
lo - > addWidget ( cb_insStdErr ) ;
cb_printCmd = new TQCheckBox ( i18n ( " &Print command name " ) , page ) ;
cb_printCmd - > setChecked ( settings & 2 ) ;
lo - > addWidget ( cb_printCmd ) ;
TQWhatsThis : : add ( cmb_cmd , i18n (
" Enter the shell command, the output of which you want inserted into your "
" document. Feel free to use a pipe or two if you wish. " ) ) ;
TQWhatsThis : : add ( wdreq , i18n (
" Sets the working folder of the command. The command executed is 'cd <dir> "
" && <command>' " ) ) ;
TQWhatsThis : : add ( cb_insStdErr , i18n (
" Check this if you want the error output from <command> inserted as well. \n "
" Some commands, such as locate, print everything to STDERR " ) ) ;
TQWhatsThis : : add ( cb_printCmd , i18n (
" If you check this, the command string will be printed followed by a "
" newline before the output. " ) ) ;
slotTextChanged ( cmb_cmd - > lineEdit ( ) - > text ( ) ) ;
}
CmdPrompt : : ~ CmdPrompt ( ) { }
void CmdPrompt : : slotTextChanged ( const TQString & text )
{
enableButtonOK ( ! text . isEmpty ( ) ) ;
}
//END CmdPrompt
//BEGIN WaitDlg implementation
// This is a dialog that is displayed while a command is running,
// with a cancel button to allow the user to kill the command
WaitDlg : : WaitDlg ( TQWidget * parent , const TQString & text , const TQString & title )
: KDialogBase ( parent , " wait dialog " , true , title , Cancel , Cancel , true )
{
TQWidget * page = new TQWidget ( this ) ;
setMainWidget ( page ) ;
TQHBoxLayout * lo = new TQHBoxLayout ( page , 0 , spacingHint ( ) ) ;
KAnimWidget * aw = new KAnimWidget ( TQString : : fromLatin1 ( " kde " ) , 48 , page ) ;
lo - > addWidget ( aw ) ;
TQLabel * l = new TQLabel ( text , page ) ;
lo - > addWidget ( l ) ;
aw - > start ( ) ;
}
WaitDlg : : ~ WaitDlg ( )
{
}
//END WaitDlg
//BEGIN InsertCommandConfigPage
// This is the config page for this plugin.
InsertCommandConfigPage : : InsertCommandConfigPage ( TQObject * /*parent*/ ,
TQWidget * parentWidget )
: Kate : : PluginConfigPage ( parentWidget )
{
TQVBoxLayout * lo = new TQVBoxLayout ( this ) ;
lo - > setSpacing ( KDialogBase : : spacingHint ( ) ) ;
// command history length
TQHBox * hb1 = new TQHBox ( this ) ;
hb1 - > setSpacing ( KDialogBase : : spacingHint ( ) ) ;
( void ) new TQLabel ( i18n ( " Remember " ) , hb1 ) ;
sb_cmdhistlen = new TQSpinBox ( hb1 ) ;
TQLabel * l1 = new TQLabel ( sb_cmdhistlen , i18n ( " Co&mmands " ) , hb1 ) ;
hb1 - > setStretchFactor ( l1 , 1 ) ;
lo - > addWidget ( hb1 ) ;
// dir history length
// initial dir choice
rg_startin = new TQButtonGroup ( 1 , TQt : : Horizontal , i18n ( " Start In " ) , this ) ;
rg_startin - > setRadioButtonExclusive ( true ) ;
( void ) new TQRadioButton ( i18n ( " Application &working folder " ) , rg_startin ) ;
( void ) new TQRadioButton ( i18n ( " &Document folder " ) , rg_startin ) ;
( void ) new TQRadioButton ( i18n ( " &Latest used working folder " ) , rg_startin ) ;
lo - > addWidget ( rg_startin ) ;
// other?
lo - > addStretch ( 1 ) ; // look nice
// Be helpfull!
TQWhatsThis : : add ( sb_cmdhistlen , i18n (
" Sets the number of commands to remember. The command history is saved "
" over sessions. " ) ) ;
TQWhatsThis : : add ( rg_startin , i18n (
" <qt><p>Decides what is suggested as <em>working folder</em> for the "
" command.</p><p><strong>Application Working Folder (default):</strong> "
" The folder from which you launched the application hosting the plugin, "
" usually your home folder.</p><p><strong>Document Folder:</strong> The "
" folder of the document. Used only for local documents.</p><p><strong> "
" Latest Working Folder:</strong> The folder used last time you used this "
" plugin.</p></qt> " ) ) ;
}
void InsertCommandConfigPage : : apply ( )
{
emit configPageApplyRequest ( this ) ;
}
//END InsertCommandConfigPage