You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdeadmin/ksysv/OldView.cpp

1151 lines
33 KiB

/***************************************************************************
begin : Sun Oct 3 1999
copyright : (C) 1997-2000 by Peter Putzer
email : putzer@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; version 2. *
* *
***************************************************************************/
/*****************************************
** **
** Main Widget **
** **
*****************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <qprogressdialog.h>
#include <qkeycode.h>
#include <qmessagebox.h>
#include <qgroupbox.h>
#include <qaccel.h>
#include <qscrollbar.h>
#include <qtextedit.h>
#include <qcstring.h>
#include <qclipboard.h>
#include <qheader.h>
#include <qlabel.h>
#include <qstylesheet.h>
#include <qwhatsthis.h>
#include <qlayout.h>
#include <qvbox.h>
#include <qvaluelist.h>
#include <qsplitter.h>
#include <qmap.h>
#include <kapplication.h>
#include <kdebug.h>
#include <kiconloader.h>
#include <kprocess.h>
#include <kstandarddirs.h>
#include <kcursor.h>
#include <kpopupmenu.h>
#include <kmessagebox.h>
#include <klocale.h>
#include <kglobalsettings.h>
#include <kaboutdata.h>
#include <kdialog.h>
#include <kdirwatch.h>
#include <kcompletion.h>
#include <krun.h>
#include <kopenwith.h>
#include <kmimemagic.h>
#include "kbusymanager.h"
#include "Properties.h"
#include "kscroller.h"
#include "IOCore.h"
#include "ksvdraglist.h"
#include "ksvdrag.h"
#include "trash.h"
#include "ksv_core.h"
#include "ksv_conf.h"
#include "OldView.h"
#include "ActionList.h"
#include "TopWidget.h"
KSVContent::KSVContent (KPopupMenu* openWithMenu, KSVTopLevel* parent, const char* name)
: QSplitter (QSplitter::Vertical, parent, name),
startRL (new KSVDragList*[ksv::runlevelNumber]),
stopRL (new KSVDragList*[ksv::runlevelNumber]),
conf(KSVConfig::self()),
mScriptBox (0L),
mRunlevels (new QVBox*[ksv::runlevelNumber]),
mOrigin (0L),
mOpenWithMenu (openWithMenu), m_buffer( QCString() )
{
setOpaqueResize( KGlobalSettings::opaqueResize() );
KXMLGUIFactory* factory = parent->factory();
mItemMenu = static_cast<KPopupMenu*> (factory->container ("item_menu", parent));
mItemMenu->insertTitle (i18n ("Runlevel Menu"), -1, 0);
mContextMenu = static_cast<KPopupMenu*> (factory->container ("list_menu", parent));
mContextMenu->insertTitle (i18n ("Runlevel Menu"), -1, 0);
mScriptMenu = static_cast<KPopupMenu*> (factory->container ("script_menu", parent));
mScriptMenu->insertTitle (i18n ("Services Menu"), -1, 0);
mScroller = new KScroller (this);
mContent = new QFrame(mScroller, "KSysV Real Content");
mScroller->setContent (mContent);
initLList();
// watch services dir
KDirWatch* dirwatch = KDirWatch::self();
dirwatch->addDir (conf->scriptPath ());
connect (dirwatch, SIGNAL (dirty (const QString&)),
this, SLOT (updateServicesAfterChange (const QString&)));
connect (dirwatch, SIGNAL (created (const QString&)),
this, SLOT (updateServicesAfterChange (const QString&)));
connect (dirwatch, SIGNAL (deleted (const QString&)),
this, SLOT (updateServicesAfterChange (const QString&)));
setSizes(KSVContent::panningFactorToSplitter (conf->panningFactor()));
// someone must have focus
scripts->setFocus();
// show/hide everything
for (int i = 0; i < ksv::runlevelNumber; ++i)
{
if (conf->showRunlevel (i))
mRunlevels[i]->show();
else
mRunlevels[i]->hide();
}
textDisplay->setStyleSheet (ksv::styleSheet());
// Open With... menu
connect (mOpenWithMenu, SIGNAL (activated (int)), this, SLOT (openWith (int)));
calcMinSize();
}
KSVContent::~KSVContent()
{
delete[] mRunlevels;
delete[] startRL;
delete[] stopRL;
delete scripts;
delete trash;
delete textDisplay ;
}
void KSVContent::updateServicesAfterChange (const QString& dir)
{
if (!dir.startsWith(conf->scriptPath()))
return;
// const bool enabled = scripts->isEnabled ();
initScripts();
}
void KSVContent::updateRunlevelsAfterChange ()
{
// MUTEX
KBusyManager::self()->setBusy (true);
// int i = 0;
for (int i = 0; i < ksv::runlevelNumber; ++i) {
startRL[i]->setEnabled(false);
startRL[i]->clear();
stopRL[i]->setEnabled(false);
stopRL[i]->clear();
}
initRunlevels();
for (int i = 0; i < ksv::runlevelNumber; ++i)
{
startRL[i]->setEnabled(true);
stopRL[i]->setEnabled(true);
}
// refresh GUI
qApp->processEvents();
scripts->setFocus();
KBusyManager::self()->restore();
}
void KSVContent::initLList()
{
QHBoxLayout *lay = new QHBoxLayout( mContent, KDialog::marginHint(), KDialog::spacingHint() );
mScriptBox = new QVBox (mContent);
lay->addWidget(mScriptBox);
mScriptBox->setSpacing (KDialog::spacingHint());
QVBox* scriptLabelBox = new QVBox (mScriptBox);
QLabel* servL = new QLabel (i18n("&Available\n" \
"Services"), scriptLabelBox);
// provide quickhelp
QWhatsThis::add (scriptLabelBox,
i18n("<p>These are the <img src=\"small|exec\"/> <strong>services</strong> available on your computer. " \
"To start a service, drag it onto the <em>Start</em> " \
"section of a runlevel.</p>" \
"<p>To stop one, do the same for the <em>Stop</em> section.</p>"));
QFont bold_font = QFont(KGlobalSettings::generalFont());
bold_font.setBold(TRUE);
servL->setFont(bold_font);
scripts = new KServiceDragList (scriptLabelBox, "Scripts");
scripts->setAcceptDrops (false);
scripts->setColumnWidthMode (KSVItem::SortNumber, QListView::Manual);
scripts->setColumnWidth(KSVItem::SortNumber,0);
scripts->setSorting (KSVItem::ServiceName);
scripts->header()->setResizeEnabled (false, 0);
scripts->setDefaultIcon (SmallIcon("exec"));
mOrigin = scripts;
// setBuddy
servL->setBuddy(scripts);
// doubleclick && return
connect (scripts, SIGNAL(executed(QListViewItem*)),
this, SLOT(slotScriptProperties(QListViewItem*)));
connect (scripts, SIGNAL (returnPressed (QListViewItem*)),
this, SLOT (slotScriptProperties (QListViewItem*)));
// context menus
connect (scripts, SIGNAL (contextMenu (KListView*, QListViewItem*, const QPoint&)),
this, SLOT (popupServicesMenu (KListView*, QListViewItem*, const QPoint&)));
// for cut & copy
connect (scripts, SIGNAL (newOrigin ()),
this, SLOT (fwdOrigin ()));
// for origin updates
connect (scripts, SIGNAL (newOrigin (KSVDragList*)),
this, SLOT (fwdOrigin (KSVDragList*)));
trash = new KSVTrash(mScriptBox, "Trash");
connect (trash, SIGNAL (undoAction (KSVAction*)), this, SLOT (fwdUndoAction (KSVAction*)));
QWhatsThis::add (trash,
i18n ("<p>You can drag services from a runlevel onto " \
"the <img src=\"small|trash\"/> <strong>trashcan</strong> to " \
"delete them from that runlevel.</p><p>The <strong>Undo command</strong> "\
"can be used to restore deleted entries.</p>"));
for(int i = 0; i < ksv::runlevelNumber; ++i)
{
mRunlevels[i] = new QVBox (mContent);
lay->addWidget(mRunlevels[i]);
mRunlevels[i]->setSpacing (KDialog::spacingHint());
// create QString for label
QString _label (i18n("Runlevel &%1").arg(i));
// and for the name
QString _name (i18n("Runlevel %1").arg(i));
QVBox* startBox = new QVBox (mRunlevels[i]);
QWhatsThis::add (startBox,
i18n("<p>These are the services <strong>started</strong> in runlevel %1.</p>" \
"<p>The number shown on the left of the <img src=\"user|ksysv_start\"/> icon " \
"determines the order in which the services are started. " \
"You can arrange them via drag and drop, as long as a suitable " \
"<em>sorting number</em> can be generated.</p><p>If that's not possible, you have " \
"to change the number manually via the <strong>Properties dialog box</strong>.</p>").arg(i));
QLabel* rlL = new QLabel(_label, startBox);
new QLabel(i18n("Start"), startBox);
rlL->setFont(bold_font);
// create the "START" list:
startRL[i] = new KSVDragList(startBox, (_name + " START").latin1());
startRL[i]->setDefaultIcon(SmallIcon("ksysv_start"));
QVBox* stopBox = new QVBox (mRunlevels[i]);
new QLabel(i18n("Stop"), stopBox);
QWhatsThis::add (stopBox,
i18n("<p>These are the services <strong>stopped</strong> in runlevel %1.</p>" \
"<p>The number shown on the left of the <img src=\"user|ksysv_stop\"/> icon " \
"determines the order in which the services are stopped. " \
"You can arrange them via drag and drop, as long as a suitable " \
"<em>sorting number</em> can be generated.</p><p>If that's not possible, you have " \
"to change the number manually via the <strong>Properties dialog box</strong>.</p>").arg(i));
// create the "STOP" list:
stopRL[i] = new KSVDragList(stopBox, (_name + " STOP").latin1());
stopRL[i]->setDefaultIcon(SmallIcon("ksysv_stop"));
// set the buddy widget for the "Runlevel %i" label... => the corresponding runlevel
rlL->setBuddy(startRL[i]);
// for cut'n'paste
connect (startRL[i], SIGNAL (newOrigin ()),
this, SLOT (fwdOrigin ()));
connect (startRL[i], SIGNAL (newOrigin (KSVDragList*)),
this, SLOT (fwdOrigin (KSVDragList*)));
connect (stopRL[i], SIGNAL (newOrigin ()),
this, SLOT (fwdOrigin ()));
connect (stopRL[i], SIGNAL (newOrigin (KSVDragList*)),
this, SLOT (fwdOrigin (KSVDragList*)));
}
lay->addStretch(1);
connect (scripts, SIGNAL(undoAction(KSVAction*)),
this, SLOT(fwdUndoAction(KSVAction*)));
// add text-diplay widget
textDisplay = new QTextEdit( QString::null, QString::null, this, "TextDisplayWidget" );
textDisplay->setTextFormat( Qt::RichText );
textDisplay->setReadOnly( true );
for (int i = 0; i < ksv::runlevelNumber; ++i)
{
connect (startRL[i], SIGNAL(newOrigin()), stopRL[i], SLOT(slotNewOrigin()));
connect (stopRL[i], SIGNAL(newOrigin()), startRL[i], SLOT(slotNewOrigin()));
connect (startRL[i], SIGNAL(undoAction(KSVAction*)),
this, SLOT(fwdUndoAction(KSVAction*)));
connect (stopRL[i], SIGNAL(undoAction(KSVAction*)),
this, SLOT(fwdUndoAction(KSVAction*)));
// doubleclick && return
connect (startRL[i], SIGNAL(executed(QListViewItem*)),
this, SLOT(slotDoubleClick(QListViewItem*)));
connect (stopRL[i], SIGNAL(executed(QListViewItem*)),
this, SLOT(slotDoubleClick(QListViewItem*)));
connect (startRL[i], SIGNAL(returnPressed(QListViewItem*)),
this, SLOT(slotDoubleClick(QListViewItem*)));
connect (stopRL[i], SIGNAL(returnPressed(QListViewItem*)),
this, SLOT(slotDoubleClick(QListViewItem*)));
// context menus
connect (startRL[i], SIGNAL (contextMenu (KListView*, QListViewItem*, const QPoint&)),
this, SLOT (popupRunlevelMenu (KListView*, QListViewItem*, const QPoint&)));
connect (stopRL[i], SIGNAL (contextMenu (KListView*, QListViewItem*, const QPoint&)),
this, SLOT (popupRunlevelMenu (KListView*, QListViewItem*, const QPoint&)));
// cannot generate sorting number
connect (startRL[i], SIGNAL(cannotGenerateNumber()),
this, SLOT(fwdCannotGenerateNumber()));
connect (stopRL[i], SIGNAL(cannotGenerateNumber()),
this, SLOT(fwdCannotGenerateNumber()));
// connecting origin things for "Scripts", too
connect (scripts, SIGNAL(newOrigin()), startRL[i], SLOT(slotNewOrigin()));
connect (scripts, SIGNAL(newOrigin()), stopRL[i], SLOT(slotNewOrigin()));
connect (startRL[i], SIGNAL(newOrigin()), scripts, SLOT(slotNewOrigin()));
connect (stopRL[i], SIGNAL(newOrigin()), scripts, SLOT(slotNewOrigin()));
// use this loop for setting tooltips
startRL[i]->setToolTip (i18n("Drag here to start services\n" \
"when entering runlevel %1").arg(i));
stopRL[i]->setToolTip (i18n("Drag here to stop services\n" \
"when entering runlevel %1").arg(i));
for (int j = 0; j < ksv::runlevelNumber; ++j)
{
if (i != j)
{
connect (startRL[i], SIGNAL (newOrigin()), startRL[j], SLOT (slotNewOrigin()));
connect (stopRL[i], SIGNAL (newOrigin()), stopRL[j], SLOT (slotNewOrigin()));
connect (startRL[i], SIGNAL(newOrigin()), stopRL[j], SLOT(slotNewOrigin()));
connect (stopRL[i], SIGNAL(newOrigin()), startRL[j], SLOT(slotNewOrigin()));
}
}
}
}
void KSVContent::fwdUndoAction (KSVAction* a)
{
emit undoAction(a);
}
void KSVContent::initScripts() {
QDir scriptDir = QDir(conf->scriptPath());
if (!scriptDir.exists())
return;
scriptDir.setFilter (QDir::Files | QDir::Hidden |
QDir::NoSymLinks | QDir::Executable);
scriptDir.setSorting (QDir::Name);
// const QFileInfoList *scriptList = scriptDir.entryInfoList();
QFileInfoListIterator it (*scriptDir.entryInfoList());
KCompletion* comp = ksv::serviceCompletion();
comp->clear ();
// clear the listview
scripts->setEnabled(false);
scripts->clear();
QFileInfo* fi; QString name;
while ((fi = it.current()))
{
name = fi->fileName();
scripts->initItem(name,
ksv::IO::relToAbs(conf->scriptPath(), fi->dirPath(FALSE)),
name, 0);
comp->addItem (name);
++it;
// keep GUI alive
qApp->processEvents();
}
scripts->setEnabled(true);
scripts->setToolTip (i18n("The services available on your computer"));
}
void KSVContent::initRunlevels()
{
for (int i = 0; i < ksv::runlevelNumber; ++i)
{
// clear the listviews
startRL[i]->clear();
stopRL[i]->clear();
const QString _path = conf->runlevelPath() + QString("/rc%1.d").arg(i);
if (!QDir(_path).exists())
continue;
QDir d = QDir(_path);
d.setFilter( QDir::Files );
d.setSorting( QDir::Name );
const QFileInfoList *rlList = d.entryInfoList();
QFileInfoListIterator it( *rlList ); // create list iterator
QFileInfo* fi; // pointer for traversing
while ( (fi=it.current()) )
{ // for each file...
info2Widget( fi, i);
++it; // goto next list element
// keep GUI alive
qApp->processEvents();
}
}
}
void KSVContent::info2Widget( QFileInfo* info, int index )
{
if (!info->exists())
return;
QString f_name = info->fileName();
QFileInfo link_info = QFileInfo(info->readLink());
QString l_base = link_info.fileName();
QString l_path = ksv::IO::relToAbs(conf->scriptPath(), link_info.dirPath(FALSE));
QString name;
int number;
ksv::IO::dissectFilename( f_name, name, number );
// finally insert the items...
if ( f_name.left(1) == "S" )
startRL[index]->initItem( l_base, l_path, name, number );
else
stopRL[index]->initItem( l_base, l_path, name, number );
}
void KSVContent::slotWriteSysV()
{
appendLog(i18n("<vip>WRITING CONFIGURATION</vip>"),
i18n("** WRITING CONFIGURATION **"));
for (int i = 0; i < ksv::runlevelNumber; ++i)
{
appendLog(i18n("<rl>RUNLEVEL %1</rl>").arg(i),
i18n("** RUNLEVEL %1 **").arg(i));
clearRL(i); // rm changed/deleted entries
// process "Start"
KSVItem* item = 0L;
for (QListViewItemIterator it (startRL[i]);
(item = static_cast<KSVItem*> (it.current()));
++it)
{
if (item->isChanged() || item->isNew())
writeToDisk (*item->data(), i, true);
}
// process "Stop"
for (QListViewItemIterator it (stopRL[i]);
(item = static_cast<KSVItem*> (it.current()));
++it)
{
if (item->isChanged() || item->isNew())
writeToDisk (*item->data(), i, false);
}
appendLog("<br/><br/>", "\n");
}
appendLog("<br/>", "");
}
void KSVContent::writeToDisk(const KSVData& _w, int _rl, bool _start) {
QString rich, plain;
ksv::IO::makeSymlink (_w, _rl, _start, rich, plain);
appendLog(rich, plain);
}
void KSVContent::repaintRunlevels ()
{
for (int i = 0; i < ksv::runlevelNumber; ++i)
{
startRL[i]->triggerUpdate();
stopRL[i]->triggerUpdate();
}
scripts->triggerUpdate();
}
void KSVContent::clearRL(int _rl)
{
QString path = conf->runlevelPath() + QString("/rc%1.d").arg(_rl);
QDir dir (path);
KSVData* d = 0L;
for (QPtrListIterator<KSVData> it (startRL[_rl]->getDeletedItems());
(d = it.current());
++it)
{
// ugly hack -> dont try to delete if entry is new (i.e. not save to disk)
if (d->newEntry() && d->originalRunlevel() != startRL[_rl]->name())
break;
QFileInfo file (path + QString("/S%1%2").arg(d->numberString()).arg(d->label()));
QString rich, plain;
ksv::IO::removeFile (file, dir, rich, plain);
appendLog(rich, plain);
}
// keep GUI alive
qApp->processEvents();
for (QPtrListIterator<KSVData> it (stopRL[_rl]->getDeletedItems());
(d = it.current());
++it)
{
// ugly, too
if (d->newEntry() && d->originalRunlevel() != stopRL[_rl]->name())
break;
QFileInfo file (path + QString("/K%1%2").arg(d->numberString()).arg(d->label()));
QString rich, plain;
ksv::IO::removeFile (file, dir, rich, plain);
appendLog(rich, plain);
}
// keep GUI alive
qApp->processEvents();
}
void KSVContent::infoOnData (KSVItem* item)
{
KSVData oldState = *item->data();
KSVData newState = oldState;
KSVEntryPropertiesDialog* props = new KSVEntryPropertiesDialog (newState, kapp->mainWidget());
connect (props, SIGNAL (editService (const QString&)),
this, SLOT (editService (const QString&)));
connect (props, SIGNAL (startService (const QString&)),
this, SLOT (startService (const QString&)));
connect (props, SIGNAL (stopService (const QString&)),
this, SLOT (stopService (const QString&)));
connect (props, SIGNAL (restartService (const QString&)),
this, SLOT (restartService (const QString&)));
int res = props->exec();
if (res == QDialog::Accepted
&& !(oldState == newState && oldState.number() == newState.number()))
{
item->copy (newState);
reSortRL();
emit undoAction(new ChangeAction(getOrigin(), &oldState, &newState));
}
}
void KSVContent::stopService ()
{
KSVContent::stopService (getOrigin()->currentItem()->filenameAndPath());
}
void KSVContent::stopService (const QString& path)
{
KProcess *_proc = new KProcess();
_proc->clearArguments();
*_proc << path << "stop";
connect(_proc, SIGNAL(processExited(KProcess*)), this, SLOT(slotExitedProcess(KProcess*)));
connect(_proc, SIGNAL(receivedStdout(KProcess*, char*, int)), this, SLOT(slotOutputOrError(KProcess*, char*, int)));
connect(_proc, SIGNAL(receivedStderr(KProcess*, char*, int)), this, SLOT(slotOutputOrError(KProcess*, char*, int)));
// refresh textDisplay
appendLog(i18n("** <stop>Stopping</stop> <cmd>%1</cmd> **<br/>").arg(path),
i18n("** Stopping %1 **").arg(path));
_proc->start(KProcess::NotifyOnExit, KProcess::AllOutput);
// notify parent
emit sigRun(path + i18n(" stop"));
}
void KSVContent::startService ()
{
KSVContent::startService (getOrigin()->currentItem()->filenameAndPath());
}
void KSVContent::startService (const QString& path)
{
KProcess* _proc = new KProcess();
_proc->clearArguments();
*_proc << path << "start";
connect(_proc, SIGNAL(processExited(KProcess*)), this, SLOT(slotExitedProcess(KProcess*)));
connect(_proc, SIGNAL(receivedStdout(KProcess*, char*, int)), this, SLOT(slotOutputOrError(KProcess*, char*, int)));
connect(_proc, SIGNAL(receivedStderr(KProcess*, char*, int)), this, SLOT(slotOutputOrError(KProcess*, char*, int)));
// refresh textDisplay
appendLog(i18n("** <start>Starting</start> <cmd>%1</cmd> **<br/>").arg(path),
i18n("** Starting %1 **").arg(path));
_proc->start(KProcess::NotifyOnExit, KProcess::AllOutput);
// notify parent
emit sigRun(path + i18n(" start"));
}
void KSVContent::editService()
{
editService (getOrigin()->currentItem()->filenameAndPath());
}
void KSVContent::editService (const QString& path)
{
// unfortunately KRun::run() only takes an URL-list instead of a single
// URL as an argument.
KURL url; url.setPath (path); KURL::List urls; urls << url;
KRun::run (*ksv::IO::preferredServiceForFile (path), urls);
}
void KSVContent::restartService ()
{
KSVContent::restartService (getOrigin()->currentItem()->filenameAndPath());
}
void KSVContent::restartService (const QString& path)
{
// restarting
KProcess *_proc = new KProcess();
_proc->clearArguments();
*_proc << path << "restart";
connect(_proc, SIGNAL(processExited(KProcess*)), this, SLOT(slotExitDuringRestart(KProcess*)));
connect(_proc, SIGNAL(receivedStdout(KProcess*, char*, int)), this, SLOT(slotOutputOrError(KProcess*, char*, int)));
connect(_proc, SIGNAL(receivedStderr(KProcess*, char*, int)), this, SLOT(slotOutputOrError(KProcess*, char*, int)));
// refresh textDisplay
appendLog(i18n("** Re-starting <cmd>%1</cmd> **</br>").arg(path),
i18n("** Re-starting %1 **").arg(path));
_proc->start(KProcess::NotifyOnExit, KProcess::AllOutput);
// notify parent
emit sigRun(path + i18n(" restart"));
}
void KSVContent::slotOutputOrError( KProcess*, char* _buffer, int _buflen) {
if (_buflen > 0) {
m_buffer += QCString( _buffer, _buflen + 1 );
appendLog( m_buffer );
}
}
void KSVContent::slotExitedProcess( KProcess* proc ) {
appendLog("<hr/>", "--------------");
emit sigStop();
delete proc;
}
void KSVContent::slotScriptsNotRemovable()
{
emit sigNotRemovable();
}
void KSVContent::slotDoubleClick (QListViewItem* item) {
infoOnData(static_cast<KSVItem*>(item));
}
void KSVContent::slotScriptProperties(QListViewItem* item)
{
KSVServicePropertiesDialog* prop =
new KSVServicePropertiesDialog (*static_cast<KSVItem*> (item)->data(), kapp->mainWidget());
connect (prop, SIGNAL (editService (const QString&)),
this, SLOT (editService (const QString&)));
connect (prop, SIGNAL (startService (const QString&)),
this, SLOT (startService (const QString&)));
connect (prop, SIGNAL (stopService (const QString&)),
this, SLOT (stopService (const QString&)));
connect (prop, SIGNAL (restartService (const QString&)),
this, SLOT (restartService (const QString&)));
prop->exec();
// delete prop;
}
void KSVContent::slotExitDuringRestart( KProcess* proc )
{
delete proc;
proc = new KProcess(); // necessary because otherwise we still have some
// signals connected that screw up our output
proc->clearArguments();
connect(proc, SIGNAL(processExited(KProcess*)), this, SLOT(slotExitedProcess(KProcess*)));
connect(proc, SIGNAL(receivedStdout(KProcess*, char*, int)), this, SLOT(slotOutputOrError(KProcess*, char*, int)));
connect(proc, SIGNAL(receivedStderr(KProcess*, char*, int)), this, SLOT(slotOutputOrError(KProcess*, char*, int)));
proc->start(KProcess::NotifyOnExit, KProcess::AllOutput);
}
KSVDragList* KSVContent::getOrigin()
{
return mOrigin;
}
void KSVContent::setDisplayScriptOutput(bool val)
{
if (val)
{
setSizes(KSVContent::panningFactorToSplitter (conf->panningFactor()));
textDisplay->show();
}
else
{
conf->setPanningFactor (KSVContent::splitterToPanningFactor (sizes()));
textDisplay->hide();
}
calcMinSize();
}
int KSVContent::splitterToPanningFactor (const QValueList<int>& list)
{
const int cont_size = *list.at(0);
const int log_size = *list.at(1);
return cont_size * 100 / (cont_size + log_size);
}
const QValueList<int>& KSVContent::panningFactorToSplitter (int panningFactor)
{
static QValueList<int> res;
res.clear();
res << panningFactor << 100 - panningFactor;
return res;
}
void KSVContent::appendLog (const QString& rich, const QString& plain)
{
static bool changed = false;
if (!changed)
{
changed = true;
emit logChanged();
}
mLogText += plain + "\n";
mXMLLogText += rich + "\n";
textDisplay->append (rich);
}
void KSVContent::appendLog(const QCString& _buffer)
{
QStringList _lines = QStringList::split( "\n", QString::fromLocal8Bit( _buffer ) );
for ( QStringList::Iterator it = _lines.begin(); it != _lines.end(); ++it )
appendLog( *it, *it );
m_buffer = QCString();
}
const QString& KSVContent::log () const
{
return mLogText;
}
const QString& KSVContent::xmlLog () const
{
return mXMLLogText;
}
void KSVContent::fwdCannotGenerateNumber() {
emit cannotGenerateNumber();
}
void KSVContent::updatePanningFactor()
{
conf->setPanningFactor(KSVContent::splitterToPanningFactor(sizes()));
}
void KSVContent::fwdOrigin ()
{
emit newOrigin();
}
void KSVContent::fwdOrigin (KSVDragList* list)
{
mOrigin = list;
}
void KSVContent::showEvent (QShowEvent* e)
{
calcMinSize();
QSplitter::showEvent (e);
}
void KSVContent::reSortRL()
{
getOrigin()->sort();
}
void KSVContent::pasteAppend()
{
KSVDragList* list = getOrigin();
if (list)
{
KSVData data;
if (KSVDrag::decodeNative (kapp->clipboard()->data(), data))
{
KSVAction* action = 0L;
if (list->insert (data, list->lastItem(), action))
{
emit undoAction (action);
}
}
}
}
void KSVContent::resizeEvent (QResizeEvent* e)
{
updatePanningFactor();
QSplitter::resizeEvent (e);
}
void KSVContent::moveEvent (QMoveEvent* e)
{
QSplitter::moveEvent (e);
}
void KSVContent::setColors (const QColor& newNormal,
const QColor& newSelected,
const QColor& changedNormal,
const QColor& changedSelected)
{
for (int i = 0; i < ksv::runlevelNumber; ++i)
{
startRL[i]->setNewNormalColor (newNormal);
startRL[i]->setNewSelectedColor (newSelected);
startRL[i]->setChangedNormalColor (changedNormal);
startRL[i]->setChangedSelectedColor (changedSelected);
startRL[i]->viewport()->update();
stopRL[i]->setNewNormalColor (newNormal);
stopRL[i]->setNewSelectedColor (newSelected);
stopRL[i]->setChangedNormalColor (changedNormal);
stopRL[i]->setChangedSelectedColor (changedSelected);
stopRL[i]->viewport()->update();
}
}
void KSVContent::multiplexEnabled (bool val)
{
QListView* list = getOrigin();
if (list)
{
list->clearSelection();
list->setCurrentItem (0L);
}
for (int i = 0; i < ksv::runlevelNumber; ++i)
{
startRL[i]->setEnabled (val);
startRL[i]->setAcceptDrops (val);
stopRL[i]->setEnabled (val);
stopRL[i]->setAcceptDrops (val);
}
if (!val)
{
mOrigin = 0L;
emit newOrigin ();
KSVConfig *config = KSVConfig::self();
QFileInfo *file = new QFileInfo( config->scriptPath() );
if ( !file->exists() )
{
int choice = KMessageBox::warningYesNo
(kapp->mainWidget(),
i18n ("<p>You have specified that your system's init " \
"scripts are located in the folder " \
"<tt><b>%1</b></tt>, but this folder does not "\
"exist. You probably selected the wrong " \
"distribution during configuration.</p> " \
"<p>If you reconfigure %2, it may be possible to "\
"fix the problem. If you choose to reconfigure, " \
"you should shut down the application " \
"and the configuration wizard will appear the " \
"next time %3 is run. If you choose not to " \
"reconfigure, you will not be able to view or " \
"edit your system's init configuration.</p>" \
"<p>Would you like to reconfigure %4?</p>")
.arg (config->scriptPath())
.arg (kapp->aboutData()->programName())
.arg (kapp->aboutData()->programName())
.arg (kapp->aboutData()->programName()),
i18n("Folder Does Not Exist"),i18n("Reconfigure"),i18n("Do Not Reconfigure"));
if ( choice == KMessageBox::Yes )
{
config->setConfigured(false);
config->writeSettings();
}
}
else
{
KMessageBox::information (kapp->mainWidget(),
i18n ("<p>You do not have the right permissions " \
"to edit your system's init configuration. " \
"However, you are free to browse the runlevels.</p>" \
"<p>If you really want to edit the " \
"configuration, either <strong>restart</strong> " \
"%1 <strong>as root</strong> (or another privileged "\
"user), or ask your sysadmin to install %2 " \
"<em>suid</em> or <em>sgid</em>.</p>" \
"<p>The latter way is not recommended though, " \
"due to security issues.</p>")
.arg (kapp->aboutData()->programName())
.arg (kapp->aboutData()->programName()),
i18n("Insufficient Permissions"),
ksv::notifications[ksv::RunlevelsReadOnly]);
}
delete file;
}
}
void KSVContent::hideRunlevel (int index)
{
mRunlevels[index]->hide();
calcMinSize();
}
void KSVContent::showRunlevel (int index)
{
mRunlevels[index]->show();
calcMinSize();
}
void KSVContent::popupRunlevelMenu (KListView* list, QListViewItem* i, const QPoint& p)
{
if (i)
mItemMenu->exec (p, 1);
else
{
if (!list->header()->rect().contains (list->mapFromGlobal(p)))
mContextMenu->exec (p, 1);
}
}
void KSVContent::popupServicesMenu (KListView*, QListViewItem* i, const QPoint& p)
{
if (i)
{
mOpenWithMenu->clear();
mOpenWithOffers
= ksv::IO::servicesForFile (static_cast<KSVItem*>(i)->filenameAndPath());
int i = 0;
for (KTrader::OfferList::Iterator it = mOpenWithOffers.begin();
it != mOpenWithOffers.end();
++it)
{
mOpenWithMenu->insertItem (SmallIconSet((*it)->icon()), (*it)->name(), i);
++i;
}
if (i >= 1)
mOpenWithMenu->insertSeparator();
mOpenWithMenu->insertItem (i18n ("&Other..."), this, SLOT (openWith()));
mScriptMenu->exec (p, 1);
}
}
void KSVContent::openWith ()
{
KURL url; url.setPath(static_cast<KSVItem*>(getOrigin()->currentItem())->filenameAndPath());
KURL::List urls; urls.append (url);
KRun::displayOpenWithDialog (urls);
kdDebug(3000) << "Opening with..." << endl;
}
void KSVContent::openWith (int index)
{
if (index < 0)
return;
KService::Ptr service = *mOpenWithOffers.at (index);
KURL url; url.setPath(static_cast<KSVItem*>(getOrigin()->currentItem())->filenameAndPath());
KURL::List urls; urls.append (url);
KRun::run (*service, urls);
kdDebug(3000) << "Opening with " << service->exec() << endl;
}
void KSVContent::calcMinSize ()
{
// Cryptic code alert: Changing w or h will change mMinSize
QCOORD& w = mMinSize.rwidth();
QCOORD& h = mMinSize.rheight();
w = 2 * KDialog::marginHint() + mScriptBox->sizeHint().width();
h = 2 * KDialog::marginHint() + mScriptBox->sizeHint().height();
for (int i = 0; i < ksv::runlevelNumber; ++i)
{
if (mRunlevels[i]->isHidden())
continue;
w += KDialog::spacingHint() + mRunlevels[i]->sizeHint().width();
h = kMax (h, mRunlevels[i]->sizeHint().height());
}
mContent->layout()->setEnabled(false);
mContent->setMinimumSize(mMinSize);
mScroller->updateScrollBars();
mContent->layout()->setEnabled(true);
}
void KSVContent::mergeLoadedPackage (QValueList<KSVData>* start,
QValueList<KSVData>* stop)
{
for (int i = 0; i < ksv::runlevelNumber; ++i)
{
merge (start[i], startRL[i]);
merge (stop[i], stopRL[i]);
}
}
void KSVContent::merge (QValueList<KSVData>& list, KSVDragList* widget)
{
typedef QMap<KSVData, bool> LoadMap;
LoadMap loaded;
for (QValueListIterator<KSVData> it = list.begin();
it != list.end();
++it)
{
KSVItem* exists = widget->match (*it);
if (exists)
{
KSVData oldState = *exists->data();
exists->setNumber ((*it).number());
exists->setLabel ((*it).label());
exists->setFilename ((*it).filename());
exists->setPath ((*it).path());
loaded[*exists->data()] = true;
if (exists->isChanged())
{
emit undoAction (new ChangeAction (widget, &oldState, exists->data()));
}
}
else
{
KSVItem* item = new KSVItem (widget, *it);
item->setNew (true);
loaded[*item->data()] = true;
emit undoAction (new AddAction (widget, item->data()));
}
kapp->processEvents ();
}
QPtrList<KSVItem> deleteList;
deleteList.setAutoDelete (true);
for (QListViewItemIterator it (widget); it.current(); ++it)
{
KSVItem* item = static_cast<KSVItem*> (it.current());
if (!loaded[*item->data()])
{
deleteList.append (item);
emit undoAction (new RemoveAction (widget, item->data()));
}
kapp->processEvents ();
}
widget->sort();
kapp->processEvents();
}
#include "OldView.moc"