summaryrefslogtreecommitdiffstats
path: root/kdesktop/minicli.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kdesktop/minicli.cpp')
-rw-r--r--kdesktop/minicli.cpp1098
1 files changed, 1098 insertions, 0 deletions
diff --git a/kdesktop/minicli.cpp b/kdesktop/minicli.cpp
new file mode 100644
index 000000000..45816da08
--- /dev/null
+++ b/kdesktop/minicli.cpp
@@ -0,0 +1,1098 @@
+/* This file is part of the KDE project
+
+ Autocompletion code:
+ Copyright (C) 2009 Timothy Pearson <[email protected]>
+
+ Copyright (C) 1999-2002,2003 Dawit Alemayehu <[email protected]>
+ Copyright (C) 2000 Malte Starostik <[email protected]>
+ Copyright (C) 2003 Sven Leiber <[email protected]>
+
+ Kdesu integration:
+ Copyright (C) 2000 Geert Jansen <[email protected]>
+
+ Original authors:
+ Copyright (C) 1997 Matthias Ettrich <[email protected]>
+ Copyright (C) 1997 Torben Weis [ Added command completion ]
+ Copyright (C) 1999 Preston Brown <[email protected]>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <pwd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <tqvbox.h>
+#include <tqlabel.h>
+#include <tqbitmap.h>
+#include <tqfile.h>
+#include <tqslider.h>
+#include <tqlayout.h>
+#include <tqgroupbox.h>
+#include <tqcheckbox.h>
+#include <tqregexp.h>
+#include <tqwhatsthis.h>
+#include <tqstylesheet.h>
+
+#include <dcopclient.h>
+#include <tdelocale.h>
+#include <tdemessagebox.h>
+#include <kprocess.h>
+#include <kcombobox.h>
+#include <klineedit.h>
+#include <tdeapplication.h>
+#include <kdebug.h>
+#include <kpassdlg.h>
+#include <krun.h>
+#include <twin.h>
+#include <tdesu/su.h>
+#include <kstandarddirs.h>
+#include <tdeconfig.h>
+#include <kiconloader.h>
+#include <kpushbutton.h>
+#include <kguiitem.h>
+#include <kstdguiitem.h>
+#include <kmimetype.h>
+#include <kurifilter.h>
+#include <tdecompletionbox.h>
+
+#include "minicli.moc"
+#include "minicli_ui.h"
+#include "kdesktopsettings.h"
+
+#define TDESU_ERR strerror(errno)
+
+Minicli::Minicli( TQWidget *parent, const char *name)
+ :KDialog( parent, name, false, (WFlags)WType_TopLevel ),
+ m_autoCheckedRunInTerm(false), m_pURLCompletion(NULL), m_pEXECompletion(NULL)
+{
+ setPlainCaption( i18n("Run Command") );
+ KWin::setIcons( winId(), DesktopIcon("system-run"), SmallIcon("system-run") );
+
+ TQVBoxLayout* mainLayout = new TQVBoxLayout( this, 0, KDialog::spacingHint() );
+ m_dlg = new MinicliDlgUI (this);
+ mainLayout->addWidget(m_dlg);
+
+ m_dlg->lbRunIcon->setPixmap(DesktopIcon("kmenu"));
+ m_dlg->lbComment->setAlignment( TQt::WordBreak );
+
+ m_dlg->cbCommand->setDuplicatesEnabled( false );
+ m_dlg->cbCommand->setTrapReturnKey( true );
+
+ // Options button...
+ m_dlg->pbOptions->setGuiItem (KGuiItem( i18n("&Options >>"), "configure" ));
+
+ // Run button...
+ m_dlg->pbRun->setGuiItem (KGuiItem( i18n("&Run"), "run" ));
+
+ // Cancel button...
+ m_dlg->pbCancel->setGuiItem ( KStdGuiItem::cancel() );
+
+ if (!kapp->authorize("shell_access"))
+ m_dlg->pbOptions->hide();
+
+ m_dlg->pbRun->setEnabled(!m_dlg->cbCommand->currentText().isEmpty());
+ m_dlg->pbRun->setDefault( true );
+
+ // Do not show the advanced group box on startup...
+ m_dlg->gbAdvanced->hide();
+
+ // URI Filter meta object...
+ m_filterData = new KURIFilterData();
+
+ // Create a timer object...
+ m_parseTimer = new TQTimer(this);
+
+ m_FocusWidget = 0;
+
+ m_prevCached = false;
+ m_iPriority = 50;
+ m_iScheduler = StubProcess::SchedNormal;
+
+ m_dlg->leUsername->setText("root");
+
+ // Autocomplete system
+ m_filesystemAutocomplete = 0;
+ m_histfilesystemAutocomplete = 0;
+ m_systempathAutocomplete = 0;
+ m_pURLCompletion = new KURLCompletion(KURLCompletion::FileCompletion);
+ m_pEXECompletion = new KURLCompletion(KURLCompletion::SystemExeCompletion);
+ //m_pURLCompletion->setCompletionMode( TDEGlobalSettings::completionMode() );
+ connect( m_pURLCompletion, TQT_SIGNAL( match(const TQString&) ), TQT_SLOT( slotMatch(const TQString&) ));
+ connect( m_pEXECompletion, TQT_SIGNAL( match(const TQString&) ), TQT_SLOT( slotEXEMatch(const TQString&) ));
+
+ // Main widget buttons...
+ connect( m_dlg->pbRun, TQT_SIGNAL(clicked()), this, TQT_SLOT(accept()) );
+ connect( m_dlg->pbCancel, TQT_SIGNAL(clicked()), this, TQT_SLOT(reject()) );
+ connect( m_dlg->pbOptions, TQT_SIGNAL(clicked()), TQT_SLOT(slotAdvanced()) );
+ connect( m_parseTimer, TQT_SIGNAL(timeout()), TQT_SLOT(slotParseTimer()) );
+
+ connect( m_dlg->cbCommand, TQT_SIGNAL( textChanged( const TQString& ) ),
+ TQT_SLOT( slotCmdChanged(const TQString&) ) );
+
+ connect( m_dlg->cbCommand, TQT_SIGNAL( returnPressed() ),
+ m_dlg->pbRun, TQT_SLOT( animateClick() ) );
+
+ m_dlg->cbCommand->setHistoryEditorEnabled( true );
+ connect( m_dlg->cbCommand, TQT_SIGNAL(removed( const TQString&) ), TQT_SLOT(saveConfig()) );
+
+ // Advanced group box...
+ connect(m_dlg->cbPriority, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotChangeScheduler(bool)));
+ connect(m_dlg->slPriority, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(slotPriority(int)));
+ connect(m_dlg->cbRealtime, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotRealtime(bool)));
+ connect(m_dlg->cbAppcomplete, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotAppcompleteToggled(bool)));
+ connect(m_dlg->cbAutocomplete, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotAutocompleteToggled(bool)));
+ connect(m_dlg->cbAutohistory, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotAutohistoryToggled(bool)));
+ connect(m_dlg->cbRunAsOther, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotChangeUid(bool)));
+ connect(m_dlg->leUsername, TQT_SIGNAL(lostFocus()), TQT_SLOT(updateAuthLabel()));
+ connect(m_dlg->cbRunInTerminal, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotTerminal(bool)));
+
+ m_dlg->slPriority->setValue(50);
+
+ loadConfig();
+}
+
+Minicli::~Minicli()
+{
+ delete m_filterData;
+ delete m_pURLCompletion;
+ delete m_pEXECompletion;
+}
+
+void Minicli::setCommand(const TQString& command)
+{
+ m_dlg->cbCommand->lineEdit()->setText(command);
+ m_dlg->cbCommand->lineEdit()->deselect();
+ int firstSpace = command.find(' ');
+ if (firstSpace > 0) {
+ m_dlg->cbCommand->lineEdit()->setSelection(firstSpace+1, command.length());
+ }
+}
+
+TQSize Minicli::sizeHint() const
+{
+ int maxWidth = tqApp->desktop()->screenGeometry((TQWidget*)this).width();
+ if (maxWidth < 603)
+ {
+ // a sensible max for smaller screens
+ maxWidth = (maxWidth > 240) ? 240 : maxWidth;
+ }
+ else
+ {
+ maxWidth = maxWidth * 2 / 5;
+ }
+
+ return TQSize(maxWidth, -1);
+}
+
+void Minicli::show()
+{
+ KWin::setState( winId(), NET::StaysOnTop );
+ KDialog::show();
+}
+
+void Minicli::loadConfig()
+{
+ TQStringList histList = KDesktopSettings::history();
+ int maxHistory = KDesktopSettings::historyLength();
+ m_terminalAppList = KDesktopSettings::terminalApps();
+
+ if (m_terminalAppList.isEmpty())
+ m_terminalAppList << "ls"; // Default
+
+ bool block = m_dlg->cbCommand->signalsBlocked();
+ m_dlg->cbCommand->blockSignals( true );
+ m_dlg->cbCommand->setMaxCount( maxHistory );
+ m_dlg->cbCommand->setHistoryItems( histList );
+ m_dlg->cbCommand->blockSignals( block );
+
+ m_dlg->cbAutocomplete->setChecked( KDesktopSettings::miniCLIFilesystemAutoComplete() );
+ m_dlg->cbAppcomplete->setChecked( KDesktopSettings::miniCLISystempathAutoComplete() );
+ m_dlg->cbAutohistory->setChecked( KDesktopSettings::miniCLIHistoryAndFilesystemAutoComplete() );
+
+ m_filesystemAutocomplete = KDesktopSettings::miniCLIFilesystemAutoComplete();
+ m_systempathAutocomplete = KDesktopSettings::miniCLISystempathAutoComplete();
+ m_histfilesystemAutocomplete = KDesktopSettings::miniCLIHistoryAndFilesystemAutoComplete();
+
+ if (m_histfilesystemAutocomplete == true) {
+ m_dlg->cbAutocomplete->setDisabled( true );
+ }
+ else {
+ m_dlg->cbAutocomplete->setDisabled( false );
+ }
+
+ TQStringList compList = KDesktopSettings::completionItems();
+ if( compList.isEmpty() )
+ m_dlg->cbCommand->completionObject()->setItems( histList );
+ else
+ m_dlg->cbCommand->completionObject()->setItems( compList );
+
+ int mode = KDesktopSettings::completionMode();
+ m_dlg->cbCommand->setCompletionMode( (TDEGlobalSettings::Completion) mode );
+
+ TDECompletionBox* box = m_dlg->cbCommand->completionBox();
+ if (box)
+ box->setActivateOnSelect( false );
+
+ m_finalFilters = KURIFilter::self()->pluginNames();
+ m_finalFilters.remove("kuriikwsfilter");
+
+ m_middleFilters = m_finalFilters;
+ m_middleFilters.remove("localdomainurifilter");
+
+ // Provide username completions. Use saner and configurable maximum values.
+ int maxEntries = KDesktopSettings::maxUsernameCompletions();
+ TQStringList users;
+
+ struct passwd *pw;
+ setpwent();
+ for (int count=0; ((pw = getpwent()) != 0L) && (count < maxEntries); count++)
+ users << TQString::fromLocal8Bit(pw->pw_name);
+ endpwent();
+
+ TDECompletion *completion = new TDECompletion;
+ completion->setOrder(TDECompletion::Sorted);
+ completion->insertItems (users);
+
+ m_dlg->leUsername->setCompletionObject(completion, true);
+ m_dlg->leUsername->setCompletionMode(TDEGlobalSettings::completionMode());
+ m_dlg->leUsername->setAutoDeleteCompletionObject( true );
+
+}
+
+void Minicli::saveConfig()
+{
+ KDesktopSettings::setHistory( m_dlg->cbCommand->historyItems() );
+ KDesktopSettings::setTerminalApps( m_terminalAppList );
+ //KDesktopSettings::setCompletionItems( m_dlg->cbCommand->completionObject()->items() );
+ KDesktopSettings::setCompletionMode( m_dlg->cbCommand->completionMode() );
+ KDesktopSettings::setMiniCLIFilesystemAutoComplete( m_filesystemAutocomplete );
+ KDesktopSettings::setMiniCLISystempathAutoComplete( m_systempathAutocomplete );
+ KDesktopSettings::setMiniCLIHistoryAndFilesystemAutoComplete( m_histfilesystemAutocomplete );
+ KDesktopSettings::writeConfig();
+}
+
+void Minicli::clearHistory()
+{
+ m_dlg->cbCommand->clearHistory();
+ saveConfig();
+}
+
+void Minicli::accept()
+{
+ TQString cmd = m_dlg->cbCommand->currentText().stripWhiteSpace();
+ if (!cmd.isEmpty() && (cmd[0].isNumber() || (cmd[0] == '(')) &&
+ (TQRegExp("[a-zA-Z\\]\\[]").search(cmd) == -1))
+ {
+ TQString result = calculate(cmd);
+ if (!result.isEmpty())
+ m_dlg->cbCommand->setCurrentText(result);
+ return;
+ }
+
+ bool logout = (cmd == "logout");
+ bool lock = (cmd == "lock");
+
+ if( !logout && !lock && runCommand() == 1 )
+ return;
+
+ m_dlg->cbCommand->addToHistory( m_dlg->cbCommand->currentText().stripWhiteSpace() );
+ reset();
+ saveConfig();
+ TQDialog::accept();
+
+ if ( logout )
+ {
+ kapp->propagateSessionManager();
+ kapp->requestShutDown();
+ }
+ if ( lock )
+ {
+ TQCString appname( "kdesktop" );
+ int kicker_screen_number = tqt_xscreen();
+ if ( kicker_screen_number )
+ appname.sprintf("kdesktop-screen-%d", kicker_screen_number);
+ kapp->dcopClient()->send(appname, "KScreensaverIface", "lock()", TQString(""));
+ }
+}
+
+void Minicli::reject()
+{
+ reset();
+ TQDialog::reject();
+}
+
+void Minicli::reset()
+{
+ if( m_dlg->gbAdvanced->isShown() )
+ slotAdvanced();
+
+ bool block = m_dlg->cbCommand->signalsBlocked();
+ m_dlg->cbCommand->blockSignals( true );
+ m_dlg->cbCommand->clearEdit();
+ m_dlg->cbCommand->setFocus();
+ m_dlg->cbCommand->reset();
+ m_dlg->cbCommand->blockSignals( block );
+ m_dlg->pbRun->setEnabled( false );
+
+ m_iPriority = 50;
+ m_iScheduler = StubProcess::SchedNormal;
+
+ m_dlg->cbRunInTerminal->setChecked(false);
+ m_dlg->cbRunAsOther->setChecked(false);
+
+ m_dlg->leUsername->setText("root");
+
+ m_dlg->cbPriority->setChecked(false);
+
+ m_dlg->slPriority->setValue(m_iPriority);
+
+ m_dlg->cbRealtime->setChecked( m_iScheduler == StubProcess::SchedRealtime );
+ m_dlg->lePassword->erase();
+
+ m_FocusWidget = 0;
+ m_iconName = TQString::null;
+ m_prevIconName = TQString::null;
+
+ m_prevCached = false;
+ updateAuthLabel();
+ setIcon();
+}
+
+void Minicli::keyPressEvent( TQKeyEvent* e )
+{
+ if ( e->key() == Qt::Key_Escape )
+ {
+ e->accept();
+ m_dlg->pbCancel->animateClick();
+ return;
+ }
+
+ TQDialog::keyPressEvent( e );
+}
+
+TQString Minicli::terminalCommand (const TQString& cmd, const TQString& args)
+{
+ TQString terminal = KDesktopSettings::terminalApplication().stripWhiteSpace();
+ if (terminal.endsWith("konsole"))
+ terminal += " --noclose";
+
+ if( args.isEmpty() )
+ terminal += TQString(" -e /bin/sh -c \"%1\"").arg(cmd);
+ else
+ terminal += TQString(" -e /bin/sh -c \"%1 %2\"").arg(cmd).arg(args);
+
+ if (!m_terminalAppList.contains(cmd))
+ m_terminalAppList << cmd;
+
+ return terminal;
+}
+
+int Minicli::runCommand()
+{
+ m_parseTimer->stop();
+
+ // Make sure we have an updated data
+ parseLine( true );
+
+ // Ignore empty commands...
+ if ( m_dlg->cbCommand->currentText().isEmpty() )
+ return 1;
+
+ TQString cmd;
+ KURL uri = m_filterData->uri();
+ if ( uri.isLocalFile() && !uri.hasRef() && uri.query().isEmpty() )
+ cmd = uri.path();
+ else
+ cmd = uri.url();
+
+ TQCString asn;
+ if( tqApp->desktop()->isVirtualDesktop())
+ {
+ asn = TDEStartupInfo::createNewStartupId();
+ TDEStartupInfoId id;
+ id.initId( asn );
+ TDEStartupInfoData data;
+ data.setXinerama( tqApp->desktop()->screenNumber( this ));
+ TDEStartupInfo::sendChange( id, data );
+ }
+
+ // Determine whether the application should be run through
+ // the command line (terminal) interface...
+ bool useTerminal = m_dlg->cbRunInTerminal->isChecked();
+
+ kdDebug (1207) << "Use terminal ? " << useTerminal << endl;
+
+ if (!kapp->authorize("shell_access"))
+ useTerminal = false;
+
+ if( needsTDEsu() )
+ {
+ TQCString user;
+ struct passwd *pw;
+
+ if (m_dlg->cbRunAsOther)
+ {
+ pw = getpwnam(m_dlg->leUsername->text().local8Bit());
+ if (pw == 0L)
+ {
+ KMessageBox::sorry( this, i18n("<qt>The user <b>%1</b> "
+ "does not exist on this system.</qt>").arg(m_dlg->leUsername->text()));
+ return 1;
+ }
+ }
+ else
+ {
+ pw = getpwuid(getuid());
+ if (pw == 0L)
+ {
+ KMessageBox::error( this, i18n("You do not exist.\n"));
+ return 1;
+ }
+ }
+
+ user = pw->pw_name;
+
+ {
+ // Scoped. we want this object to go away before the fork
+ // (maybe not necessary, but can't hurt) according to the cvs log,
+ // creating the SuProcess object in the parent and using it in the
+ // child creates crashes, but we need to check password before the
+ // fork in order to not get in trouble with X for the messagebox
+
+ SuProcess proc_checkpwd;
+ proc_checkpwd.setUser( user );
+
+ if (m_dlg->cbPriority->isChecked())
+ {
+ proc_checkpwd.setPriority(m_iPriority);
+ proc_checkpwd.setScheduler(m_iScheduler);
+ }
+
+ if (proc_checkpwd.checkInstall(m_dlg->lePassword->password()) != 0)
+ {
+ KMessageBox::sorry(this, i18n("Incorrect password; please try again."));
+ return 1;
+ }
+ }
+
+ TQApplication::flushX();
+
+ int pid = fork();
+
+ if (pid < 0)
+ {
+ kdError(1207) << "fork(): " << TDESU_ERR << "\n";
+ return -1;
+ }
+
+ if (pid > 0)
+ return 0;
+
+ // From here on, this is child...
+
+ SuProcess proc;
+ proc.setUser(user);
+
+ if (m_dlg->cbPriority->isChecked())
+ {
+ proc.setPriority(m_iPriority);
+ proc.setScheduler(m_iScheduler);
+ }
+
+ TQCString command;
+
+ if (useTerminal)
+ command = terminalCommand( cmd, m_filterData->argsAndOptions() ).local8Bit();
+ else
+ {
+ command = cmd.local8Bit();
+ if( m_filterData->hasArgsAndOptions() )
+ command += m_filterData->argsAndOptions().local8Bit();
+ }
+
+ proc.setCommand(command);
+
+ // Block SIGCHLD because SuProcess::exec() uses waitpid()
+ sigset_t sset;
+ sigemptyset(&sset);
+ sigaddset(&sset, SIGCHLD);
+ sigprocmask(SIG_BLOCK, &sset, 0L);
+ proc.setTerminal(true);
+ proc.setErase(true);
+ _exit(proc.exec(m_dlg->lePassword->password()));
+ return 0;
+ }
+ else
+ {
+ TQString exec;
+
+ // yes, this is a hack, but there is no way of doing it
+ // through SuProcess without providing the user password
+ if (m_iPriority < 50)
+ {
+ // from tdesu_stub.c
+ int val = 20 - (int) (((double) m_iPriority) * 40 / 100 + 0.5);
+ cmd = "nice -n " + TQString::number( val ) + " " + cmd;
+ }
+
+ if (useTerminal)
+ {
+ cmd = terminalCommand( cmd, m_filterData->argsAndOptions() );
+ kdDebug(1207) << "Terminal command: " << cmd << endl;
+ }
+ else
+ {
+ switch( m_filterData->uriType() )
+ {
+ case KURIFilterData::LOCAL_FILE:
+ case KURIFilterData::LOCAL_DIR:
+ case KURIFilterData::NET_PROTOCOL:
+ case KURIFilterData::HELP:
+ {
+ // No need for kfmclient, KRun does it all (David)
+ (void) new KRun( m_filterData->uri(), parentWidget(), asn );
+ return 0;
+ }
+ case KURIFilterData::EXECUTABLE:
+ {
+ if( !m_filterData->hasArgsAndOptions() )
+ {
+ // Look for desktop file
+ KService::Ptr service = KService::serviceByDesktopName(cmd);
+ if (service && service->isValid() && service->type() == "Application")
+ {
+ notifyServiceStarted(service);
+ KRun::run(*service, KURL::List(), parentWidget(), asn );
+ return 0;
+ }
+ }
+ }
+ // fall-through to shell case
+ case KURIFilterData::SHELL:
+ {
+ if (kapp->authorize("shell_access"))
+ {
+ exec = cmd;
+
+ if( m_filterData->hasArgsAndOptions() )
+ cmd += m_filterData->argsAndOptions();
+
+ break;
+ }
+ else
+ {
+ KMessageBox::sorry( this, i18n("<center><b>%1</b></center>\n"
+ "You do not have permission to execute "
+ "this command.")
+ .arg( TQStyleSheet::convertFromPlainText(cmd) ));
+ return 1;
+ }
+ }
+ case KURIFilterData::UNKNOWN:
+ case KURIFilterData::ERROR:
+ default:
+ {
+ // Look for desktop file
+ KService::Ptr service = KService::serviceByDesktopName(cmd);
+ if (service && service->isValid() && service->type() == "Application")
+ {
+ notifyServiceStarted(service);
+ KRun::run(*service, KURL::List(), parentWidget(), asn );
+ return 0;
+ }
+
+ service = KService::serviceByName(cmd);
+ if (service && service->isValid() && service->type() == "Application")
+ {
+ notifyServiceStarted(service);
+ KRun::run(*service, KURL::List(), parentWidget(), asn );
+ return 0;
+ }
+
+ KMessageBox::sorry( this, i18n("<center><b>%1</b></center>\n"
+ "Could not run the specified command.")
+ .arg( TQStyleSheet::convertFromPlainText(cmd) ));
+ return 1;
+ }
+ }
+ }
+
+ if ( KRun::runCommand( cmd, exec, m_iconName, parentWidget(), asn ) )
+ return 0;
+ else
+ {
+ KMessageBox::sorry( this, i18n("<center><b>%1</b></center>\n"
+ "The specified command does not exist.").arg(cmd) );
+ return 1; // Let the user try again...
+ }
+ }
+}
+
+void Minicli::notifyServiceStarted(KService::Ptr service)
+{
+ // Inform other applications (like the quickstarter applet)
+ // that an application was started
+ TQByteArray params;
+ TQDataStream stream(params, IO_WriteOnly);
+ stream << "minicli" << service->storageId();
+ kdDebug() << "minicli appLauncher dcop signal: " << service->storageId() << endl;
+ TDEApplication::kApplication()->dcopClient()->emitDCOPSignal("appLauncher",
+ "serviceStartedByStorageId(TQString,TQString)", params);
+}
+
+void Minicli::slotCmdChanged(const TQString& text)
+{
+ bool isEmpty = text.isEmpty();
+ m_dlg->pbRun->setEnabled( !isEmpty );
+
+ if( isEmpty )
+ {
+ // Reset values to default
+ m_filterData->setData(KURL());
+
+ // Empty String is certainly no terminal application
+ slotTerminal(false);
+
+ // Reset the icon if needed...
+ const TQPixmap pixmap = DesktopIcon("kmenu");
+
+ if ( pixmap.serialNumber() != m_dlg->lbRunIcon->pixmap()->serialNumber())
+ m_dlg->lbRunIcon->setPixmap(pixmap);
+
+ return;
+ }
+ else if ((m_filesystemAutocomplete == true) && ( m_pURLCompletion )) {
+ // Attempt to autocomplete the entered URL if it starts with the / character, meaning I am looking for something on the filesystem
+ // Also use autocompletion if it appears that I am using some kind of ioslave, except the http:// ioslave
+ m_urlCompletionStarted = true; // flag for slotMatch()
+
+ if ((text.startsWith( "/" ) || text.startsWith( "~" ) || (text.contains("://", false) != 0)) && (text.contains("http://", false) == 0)) {
+ TQString completion = m_pURLCompletion->makeCompletion( text );
+ }
+ }
+ if ((m_systempathAutocomplete == true) && ( m_pEXECompletion )) {
+ // Attempt to autocomplete the entered URL if it starts with the / character, meaning I am looking for something on the filesystem
+ // Also use autocompletion if it appears that I am using some kind of ioslave, except the http:// ioslave
+ m_exeCompletionStarted = true; // flag for slotEXEMatch()
+
+ if (!((text.startsWith( "/" ) || text.startsWith( "~" ) || (text.contains("://", false) != 0)) && (text.contains("http://", false) == 0))) {
+ TQString completion = m_pEXECompletion->makeCompletion( text );
+ }
+ }
+
+ m_parseTimer->start(250, true);
+}
+
+// Handle match() from m_pURLCompletion
+void Minicli::slotMatch( const TQString &match )
+{
+ TQString current_text;
+ TQStringList histList = KDesktopSettings::history();
+ int maxHistory = KDesktopSettings::historyLength();
+ int maxAutocompletion = KDesktopSettings::miniCLIAutocompletionLength();
+
+ if ( match.isEmpty() ) // this case is handled directly
+ return;
+
+ // Check flag to avoid match() raised by rotation
+ if ( m_urlCompletionStarted ) {
+ m_urlCompletionStarted = false;
+
+ if (m_filesystemAutocomplete == true) {
+ bool block = m_dlg->cbCommand->signalsBlocked();
+ m_dlg->cbCommand->blockSignals( true );
+ TQStringList items = m_pURLCompletion->allMatches();
+ items.sort();
+ if (m_histfilesystemAutocomplete == true) {
+ // Add the history to the list
+ histList += items;
+ maxHistory += maxAutocompletion;
+ }
+ else {
+ histList = items;
+ maxHistory = maxAutocompletion;
+ }
+ current_text = m_dlg->cbCommand->currentText();
+ //histList.prepend ( current_text ); // Add the current text to the autocompletion list
+ m_dlg->cbCommand->setMaxCount( maxHistory );
+ m_dlg->cbCommand->completionObject()->setItems( histList );
+ m_dlg->cbCommand->setCurrentText( current_text );
+ m_dlg->cbCommand->blockSignals( block );
+ }
+ }
+}
+
+// Handle match() from m_pEXECompletion
+void Minicli::slotEXEMatch( const TQString &match )
+{
+ TQString current_text;
+ TQStringList histList = KDesktopSettings::history();
+ int maxHistory = KDesktopSettings::historyLength();
+ int maxAutocompletion = KDesktopSettings::miniCLIAutocompletionLength();
+
+ if ( match.isEmpty() ) // this case is handled directly
+ return;
+
+ // Check flag to avoid match() raised by rotation
+ if ( m_exeCompletionStarted ) {
+ m_exeCompletionStarted = false;
+
+ if (m_systempathAutocomplete == true) {
+ bool block = m_dlg->cbCommand->signalsBlocked();
+ m_dlg->cbCommand->blockSignals( true );
+ TQStringList items = m_pEXECompletion->allMatches();
+ items.sort();
+ if (m_histfilesystemAutocomplete == true) {
+ // Add the history to the list
+ histList += items;
+ maxHistory += maxAutocompletion;
+ }
+ else {
+ histList = items;
+ maxHistory = maxAutocompletion;
+ }
+ current_text = m_dlg->cbCommand->currentText();
+ //histList.prepend ( current_text ); // Add the current text to the autocompletion list
+ m_dlg->cbCommand->setMaxCount( maxHistory );
+ m_dlg->cbCommand->completionObject()->setItems( histList );
+ m_dlg->cbCommand->setCurrentText( current_text );
+ m_dlg->cbCommand->blockSignals( block );
+ }
+ }
+}
+
+void Minicli::slotAdvanced()
+{
+ if (m_dlg->gbAdvanced->isHidden())
+ {
+ m_dlg->gbAdvanced->show();
+ m_dlg->pbOptions->setText(i18n("&Options <<"));
+
+ // Set the focus back to the widget that had it to begin with, i.e.
+ // do not put the focus on the "Options" button.
+ m_FocusWidget = focusWidget();
+
+ if( m_FocusWidget )
+ m_FocusWidget->setFocus();
+ }
+ else
+ {
+ m_dlg->gbAdvanced->hide();
+ m_dlg->pbOptions->setText(i18n("&Options >>"));
+
+ if( m_FocusWidget && m_FocusWidget->parent() != m_dlg->gbAdvanced )
+ m_FocusWidget->setFocus();
+ }
+ adjustSize();
+}
+
+void Minicli::slotParseTimer()
+{
+ //kdDebug (1207) << "Minicli::slotParseTimer: Timed out..." << endl;
+ parseLine( false );
+}
+
+void Minicli::parseLine( bool final )
+{
+ TQString cmd = m_dlg->cbCommand->currentText().stripWhiteSpace();
+ m_filterData->setData( cmd );
+
+ if( final )
+ KURIFilter::self()->filterURI( *(m_filterData), m_finalFilters );
+ else
+ KURIFilter::self()->filterURI( *(m_filterData), m_middleFilters );
+
+ bool isTerminalApp = ((m_filterData->uriType() == KURIFilterData::EXECUTABLE) &&
+ m_terminalAppList.contains(m_filterData->uri().url()));
+
+ if( !isTerminalApp )
+ {
+ m_iconName = m_filterData->iconName();
+ setIcon();
+ }
+
+ if ( isTerminalApp && final && !m_dlg->cbRunInTerminal->isChecked() )
+ {
+ m_terminalAppList.remove( m_filterData->uri().url() );
+ isTerminalApp = false;
+ }
+ else
+ {
+ bool wasAutoChecked = m_autoCheckedRunInTerm;
+ bool willBeAutoChecked = isTerminalApp && !m_dlg->cbRunInTerminal->isChecked();
+ slotTerminal(isTerminalApp || (m_dlg->cbRunInTerminal->isChecked() && !m_autoCheckedRunInTerm));
+ if (!wasAutoChecked && willBeAutoChecked)
+ m_autoCheckedRunInTerm = true;
+ }
+
+ kdDebug (1207) << "Command: " << m_filterData->uri().url() << endl;
+ kdDebug (1207) << "Arguments: " << m_filterData->argsAndOptions() << endl;
+}
+
+void Minicli::setIcon ()
+{
+ if( m_iconName.isEmpty() || m_iconName == "unknown" || m_iconName == "kde" )
+ m_iconName = TQString::fromLatin1("kmenu");
+
+ TQPixmap icon;
+ if ((m_iconName == "application-x-executable") && (m_filterData->iconName() == "application-x-executable")) {
+ TQPixmap potentialIcon = m_filterData->customIconPixmap();
+ if (!potentialIcon.isNull()) {
+ icon = potentialIcon;
+ }
+ else {
+ icon = DesktopIcon( m_iconName );
+ }
+ }
+ else {
+ icon = DesktopIcon( m_iconName );
+ }
+
+ if ( m_iconName == "www" )
+ {
+ // Not using TDEIconEffect::overlay as that requires the same size
+ // for the icon and the overlay, also the overlay definately doesn't
+ // have a more that one-bit alpha channel here
+ TQPixmap overlay( locate ( "icon", KMimeType::favIconForURL( m_filterData->uri() ) + ".png" ) );
+ if ( !overlay.isNull() )
+ {
+ int x = icon.width() - overlay.width();
+ int y = icon.height() - overlay.height();
+ if ( icon.mask() )
+ {
+ TQBitmap mask = *icon.mask();
+ bitBlt( &mask, x, y,
+ overlay.mask() ? TQT_TQPIXMAP(const_cast<TQBitmap *>(overlay.mask())) : &overlay,
+ 0, 0, overlay.width(), overlay.height(),
+ overlay.mask() ? OrROP : SetROP );
+ icon.setMask(mask);
+ }
+ bitBlt( &icon, x, y, &overlay );
+ }
+ }
+
+ m_dlg->lbRunIcon->setPixmap( icon );
+}
+
+void Minicli::updateAuthLabel()
+{
+ if ((m_dlg->cbPriority->isChecked() && (m_iPriority > 50)) ||
+ (m_iScheduler != StubProcess::SchedNormal))
+ {
+ if (!m_prevCached && !m_dlg->leUsername->text().isEmpty())
+ {
+ //kdDebug(1207) << k_funcinfo << "Caching: user=" << m_dlg->leUsername->text() <<
+ // ", checked=" << m_dlg->cbRunAsOther->isChecked() << endl;
+
+ m_prevUser = m_dlg->leUsername->text();
+ m_prevPass = m_dlg->lePassword->text();
+ m_prevChecked = m_dlg->cbRunAsOther->isChecked();
+ m_prevCached = true;
+ }
+ if (m_dlg->leUsername->text() != TQString::fromLatin1("root"))
+ m_dlg->lePassword->setText(TQString::null);
+ m_dlg->leUsername->setText(TQString::fromLatin1("root"));
+ m_dlg->cbRunAsOther->setChecked(true);
+ m_dlg->cbRunAsOther->setEnabled(false);
+ m_dlg->leUsername->setEnabled(false);
+ m_dlg->lbUsername->setEnabled(true);
+ m_dlg->lePassword->setEnabled(true);
+ m_dlg->lbPassword->setEnabled(true);
+ }
+ else if (m_dlg->cbRunAsOther->isEnabled() &&
+ m_dlg->cbRunAsOther->isChecked() && !m_dlg->leUsername->text().isEmpty())
+ {
+ m_dlg->lePassword->setEnabled(true);
+ m_dlg->lbPassword->setEnabled(true);
+ }
+ else
+ {
+ if (m_prevCached)
+ {
+ m_dlg->leUsername->setText(m_prevUser);
+ m_dlg->lePassword->setText(m_prevPass);
+ m_dlg->cbRunAsOther->setChecked(m_prevChecked);
+ m_dlg->leUsername->setEnabled(m_prevChecked);
+ m_dlg->lbUsername->setEnabled(m_prevChecked);
+ }
+ else
+ {
+ m_dlg->cbRunAsOther->setChecked(false);
+ m_dlg->leUsername->setEnabled(false);
+ m_dlg->lbUsername->setEnabled(false);
+ }
+ m_dlg->cbRunAsOther->setEnabled(true);
+ m_dlg->lePassword->setEnabled(false);
+ m_dlg->lbPassword->setEnabled(false);
+ m_prevCached = false;
+ }
+}
+
+void Minicli::slotTerminal(bool enable)
+{
+ m_dlg->cbRunInTerminal->setChecked(enable);
+ m_autoCheckedRunInTerm = false;
+
+ if (enable)
+ {
+ m_prevIconName = m_iconName;
+ m_iconName = TQString::fromLatin1( "konsole" );
+ setIcon();
+ }
+ else if (!m_prevIconName.isEmpty())
+ {
+ m_iconName = m_prevIconName;
+ setIcon();
+ }
+}
+
+void Minicli::slotChangeUid(bool enable)
+{
+ m_dlg->leUsername->setEnabled(enable);
+ m_dlg->lbUsername->setEnabled(enable);
+
+ if(enable)
+ {
+ m_dlg->leUsername->selectAll();
+ m_dlg->leUsername->setFocus();
+ }
+
+ updateAuthLabel();
+}
+
+void Minicli::slotChangeScheduler(bool enable)
+{
+ m_dlg->slPriority->setEnabled(enable);
+ m_dlg->lbLowPriority->setEnabled(enable);
+ m_dlg->lbHighPriority->setEnabled(enable);
+
+ updateAuthLabel();
+}
+
+bool Minicli::needsTDEsu()
+{
+ return ((m_dlg->cbPriority->isChecked() && ((m_iPriority > 50) ||
+ (m_iScheduler != StubProcess::SchedNormal))) ||
+ (m_dlg->cbRunAsOther->isChecked() && !m_dlg->leUsername->text().isEmpty()));
+}
+
+void Minicli::slotRealtime(bool enabled)
+{
+ m_iScheduler = enabled ? StubProcess::SchedRealtime : StubProcess::SchedNormal;
+
+ if (enabled)
+ {
+ if (KMessageBox::warningContinueCancel(this,
+ i18n("Running a realtime application can be very dangerous. "
+ "If the application misbehaves, the system might hang "
+ "unrecoverably.\nAre you sure you want to continue?"),
+ i18n("Warning - Run Command"), KGuiItem(i18n("&Run Realtime")),TQString::null,KMessageBox::Notify|KMessageBox::PlainCaption)
+ != KMessageBox::Continue )
+ {
+ m_iScheduler = StubProcess::SchedNormal;
+ m_dlg->cbRealtime->setChecked(false);
+ }
+ }
+
+ updateAuthLabel();
+}
+
+void Minicli::slotAutocompleteToggled(bool enabled)
+{
+ if (enabled)
+ {
+ // Enable filesystem autocompletion
+ m_filesystemAutocomplete = true;
+ }
+ else {
+ // Enable history only autocompletion
+ m_filesystemAutocomplete = false;
+ }
+
+ TQString current_text = m_dlg->cbCommand->currentText();
+ m_dlg->cbCommand->setCurrentText( current_text ); // Force an update of the autocompletion list
+}
+
+void Minicli::slotAppcompleteToggled(bool enabled)
+{
+ m_systempathAutocomplete = enabled;
+
+ TQString current_text = m_dlg->cbCommand->currentText();
+ m_dlg->cbCommand->setCurrentText( current_text ); // Force an update of the autocompletion list
+}
+
+void Minicli::slotAutohistoryToggled(bool enabled)
+{
+ if (enabled)
+ {
+ // Enable history and filesystem autocompletion
+ m_histfilesystemAutocomplete = true;
+ m_filesystemAutocomplete = true;
+ m_dlg->cbAutocomplete->setChecked( true );
+ m_dlg->cbAutocomplete->setDisabled ( true );
+ }
+ else {
+ // Disable history and filesystem autocompletion
+ m_histfilesystemAutocomplete = false;
+ m_dlg->cbAutocomplete->setDisabled ( false );
+ }
+
+ TQString current_text = m_dlg->cbCommand->currentText();
+ m_dlg->cbCommand->setCurrentText( current_text ); // Force an update of the autocompletion list
+}
+
+void Minicli::slotPriority(int priority)
+{
+ // Provide a way to easily return to the default priority
+ if ((priority > 40) && (priority < 60))
+ {
+ priority = 50;
+ m_dlg->slPriority->setValue(50);
+ }
+
+ m_iPriority = priority;
+
+ updateAuthLabel();
+}
+
+TQString Minicli::calculate(const TQString &exp)
+{
+ TQString result, cmd;
+ const TQString bc = TDEStandardDirs::findExe("bc");
+ if ( !bc.isEmpty() )
+ cmd = TQString("echo %1 | %2").arg(TDEProcess::quote(TQString("scale=8; ")+exp), TDEProcess::quote(bc));
+ else
+ cmd = TQString("echo $((%1))").arg(exp);
+ FILE *fs = popen(TQFile::encodeName(cmd).data(), "r");
+ if (fs)
+ {
+ { // scope for QTextStream
+ TQTextStream ts(fs, IO_ReadOnly);
+ result = ts.read().stripWhiteSpace();
+ }
+ pclose(fs);
+ }
+ return result;
+}
+
+void Minicli::fontChange( const TQFont & )
+{
+ adjustSize();
+}
+
+// vim: set et ts=2 sts=2 sw=2:
+