diff options
Diffstat (limited to 'kate/insertcommand/plugin_kateinsertcommand.cpp')
| -rw-r--r-- | kate/insertcommand/plugin_kateinsertcommand.cpp | 417 | 
1 files changed, 417 insertions, 0 deletions
diff --git a/kate/insertcommand/plugin_kateinsertcommand.cpp b/kate/insertcommand/plugin_kateinsertcommand.cpp new file mode 100644 index 0000000..eadbc02 --- /dev/null +++ b/kate/insertcommand/plugin_kateinsertcommand.cpp @@ -0,0 +1,417 @@ + /*************************************************************************** +                          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 <qbuttongroup.h> +#include <qcheckbox.h> +#include <qdir.h> +#include <qfile.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qradiobutton.h> +#include <qspinbox.h> +#include <qstringlist.h> +#include <qwhatsthis.h> +#include <qwidget.h> + +#include <kaction.h> +#include <kanimwidget.h> +#include <kconfig.h> +#include <kdebug.h> +#include <kfiledialog.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kprocess.h> +#include <kstandarddirs.h> +#include <kgenericfactory.h> +#include <kapplication.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( QObject* parent, const char* name, const QStringList& ) +    : Kate::Plugin ( (Kate::Application *)parent, name ), +      kv              ( 0 ), +      sh              ( 0 ) +{ +  config = new KConfig("kateinsertcommandpluginrc"); +  cmdhist = config->readListEntry("Command History"); +  wdlg = 0; +  workingdir = QDir::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 KAction ( i18n("Insert Command..."), "", 0, this, +                      SLOT( slotInsertCommand() ), view->actionCollection(), +                      "edit_insert_command" ); + +    view->setInstance (new KInstance("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(); + +  QString dir = workingdir; +  QString docdir; +  KURL docurl = kv->getDoc()->url(); +  if (docurl.isLocalFile()) +    docdir = docurl.directory(); +  QString 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((QWidget*)kv, 0, cmdhist, dir, +                               docdir, dialogSettings); +  if ( d->exec() && ! d->command().isEmpty() ) { +    if ( ! sh ) { +    sh = new KShellProcess; + +    connect ( sh, SIGNAL(receivedStdout(KProcess*, char*, int)), +              this, SLOT(slotReceivedStdout(KProcess*, char*, int)) ); +    connect ( sh, SIGNAL(receivedStderr(KProcess*, char*, int)), +              this, SLOT(slotReceivedStderr(KProcess*, char*, int)) ); +    connect ( sh, SIGNAL(processExited(KProcess*)), +              this, SLOT(slotProcessExited(KProcess*)) ) ; +    } + +    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 << QFile::encodeName(d->command()); +    sh->start( KProcess::NotifyOnExit, KProcess::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( (QWidget*)kv, i18n( +        "Executing command:\n%1\n\nPress 'Cancel' to abort.").arg(cmd)  ); +      connect(wdlg, SIGNAL(cancelClicked()), this, 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( KProcess* /*p*/, char* text, +                                                  int len ) +{ +  QString t = QString::fromLocal8Bit ( text ); +  t.truncate(len); +  kv->insertText( t ); +} + +void PluginKateInsertCommand::slotReceivedStderr( KProcess* p, char* text, +                                                  int len ) +{ +  if ( bInsStdErr ) +    slotReceivedStdout( p, text, len ); +} + +void PluginKateInsertCommand::slotProcessExited( KProcess* 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, +                                  QWidget *w, const char */*name*/) +{ +  InsertCommandConfigPage* p = new InsertCommandConfigPage(this, w); +  initConfigPage( p ); +  connect( p, SIGNAL(configPageApplyRequest(InsertCommandConfigPage*)), +           this, 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(QWidget* parent, +                     const char* name, +                     const QStringList& cmdhist, +                     const QString& dir, +                     const QString& /*docdir*/, +                     int settings) +  : KDialogBase (parent, name, true, i18n("Insert Command"), Ok|Cancel, Ok, true) +{ +   QWidget *page = new QWidget( this ); +   setMainWidget(page); + +   QVBoxLayout *lo = new QVBoxLayout( page, 0, spacingHint() ); + +   QLabel *l = new QLabel( 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(),SIGNAL(textChanged ( const QString & )), +            this, SLOT( slotTextChanged(const QString &))); + +   QLabel *lwd = new QLabel( 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 QCheckBox( i18n("Insert Std&Err messages"), page ); +   cb_insStdErr->setChecked(settings & 1); +   lo->addWidget( cb_insStdErr ); +   cb_printCmd = new QCheckBox( i18n("&Print command name"), page ); +   cb_printCmd->setChecked(settings & 2); +   lo->addWidget( cb_printCmd ); + +   QWhatsThis::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.") ); +   QWhatsThis::add( wdreq, i18n( +     "Sets the working folder of the command. The command executed is 'cd <dir> " +     "&& <command>'") ); +   QWhatsThis::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") ); +   QWhatsThis::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 QString &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(QWidget* parent, const QString& text, const QString& title) +  : KDialogBase( parent, "wait dialog", true, title, Cancel, Cancel, true ) +{ +  QWidget *page = new QWidget( this ); +  setMainWidget( page ); +  QHBoxLayout *lo = new QHBoxLayout( page, 0, spacingHint() ); + +  KAnimWidget *aw = new KAnimWidget( QString::fromLatin1("kde"), 48, page ); +  lo->addWidget(aw); +  QLabel *l = new QLabel( text, page ); +  lo->addWidget( l ); + +  aw->start(); +} +WaitDlg::~WaitDlg() +{ +} +//END WaitDlg + +//BEGIN InsertCommandConfigPage +// This is the config page for this plugin. +InsertCommandConfigPage::InsertCommandConfigPage(QObject* /*parent*/, +                                                 QWidget *parentWidget) +  : Kate::PluginConfigPage( parentWidget ) +{ +  QVBoxLayout* lo = new QVBoxLayout( this ); +  lo->setSpacing(KDialogBase::spacingHint()); + +  // command history length +  QHBox *hb1 = new QHBox( this ); +  hb1->setSpacing(KDialogBase::spacingHint()); +  (void) new QLabel( i18n("Remember"), hb1 ); +  sb_cmdhistlen = new QSpinBox( hb1 ); +  QLabel *l1 =  new QLabel( sb_cmdhistlen, i18n("Co&mmands"), hb1); +  hb1->setStretchFactor(l1, 1); +  lo->addWidget( hb1 ); + +  // dir history length + +  // initial dir choice +  rg_startin = new QButtonGroup( 1, Qt::Horizontal, i18n("Start In"), this ); +  rg_startin->setRadioButtonExclusive( true ); +  (void) new QRadioButton( i18n("Application &working folder"), rg_startin); +  (void) new QRadioButton( i18n("&Document folder"), rg_startin); +  (void) new QRadioButton( i18n("&Latest used working folder"), rg_startin); +  lo->addWidget( rg_startin ); +  // other? + +  lo->addStretch(1);  // look nice + +  // Be helpfull! +  QWhatsThis::add( sb_cmdhistlen, i18n( +    "Sets the number of commands to remember. The command history is saved " +    "over sessions.") ); +  QWhatsThis::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 +// kate: space-indent on; indent-width 2; replace-tabs on;  | 
