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
34 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 <tqprogressdialog.h>
#include <tqkeycode.h>
#include <tqmessagebox.h>
#include <tqgroupbox.h>
#include <tqaccel.h>
#include <tqscrollbar.h>
#include <tqtextedit.h>
#include <tqcstring.h>
#include <tqclipboard.h>
#include <tqheader.h>
#include <tqlabel.h>
#include <tqstylesheet.h>
#include <tqwhatsthis.h>
#include <tqlayout.h>
#include <tqvbox.h>
#include <tqvaluelist.h>
#include <tqsplitter.h>
#include <tqmap.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* tqparent, const char* name)
: TQSplitter (Qt::Vertical, tqparent, name),
startRL (new KSVDragList*[ksv::runlevelNumber]),
stopRL (new KSVDragList*[ksv::runlevelNumber]),
conf(KSVConfig::self()),
mScriptBox (0L),
mRunlevels (new TQVBox*[ksv::runlevelNumber]),
mOrigin (0L),
mOpenWithMenu (openWithMenu), m_buffer( TQCString() )
{
setOpaqueResize( KGlobalSettings::opaqueResize() );
KXMLGUIFactory* factory = tqparent->factory();
mItemMenu = static_cast<KPopupMenu*> (factory->container ("item_menu", tqparent));
mItemMenu->insertTitle (i18n ("Runlevel Menu"), -1, 0);
mContextMenu = static_cast<KPopupMenu*> (factory->container ("list_menu", tqparent));
mContextMenu->insertTitle (i18n ("Runlevel Menu"), -1, 0);
mScriptMenu = static_cast<KPopupMenu*> (factory->container ("script_menu", tqparent));
mScriptMenu->insertTitle (i18n ("Services Menu"), -1, 0);
mScroller = new KScroller (this);
mContent = new TQFrame(mScroller, "KSysV Real Content");
mScroller->setContent (mContent);
initLList();
// watch services dir
KDirWatch* dirwatch = KDirWatch::self();
dirwatch->addDir (conf->scriptPath ());
connect (dirwatch, TQT_SIGNAL (dirty (const TQString&)),
this, TQT_SLOT (updateServicesAfterChange (const TQString&)));
connect (dirwatch, TQT_SIGNAL (created (const TQString&)),
this, TQT_SLOT (updateServicesAfterChange (const TQString&)));
connect (dirwatch, TQT_SIGNAL (deleted (const TQString&)),
this, TQT_SLOT (updateServicesAfterChange (const TQString&)));
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, TQT_SIGNAL (activated (int)), this, TQT_SLOT (openWith (int)));
calcMinSize();
}
KSVContent::~KSVContent()
{
delete[] mRunlevels;
delete[] startRL;
delete[] stopRL;
delete scripts;
delete trash;
delete textDisplay ;
}
void KSVContent::updateServicesAfterChange (const TQString& 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
tqApp->processEvents();
scripts->setFocus();
KBusyManager::self()->restore();
}
void KSVContent::initLList()
{
TQHBoxLayout *lay = new TQHBoxLayout( mContent, KDialog::marginHint(), KDialog::spacingHint() );
mScriptBox = new TQVBox (mContent);
lay->addWidget(mScriptBox);
mScriptBox->setSpacing (KDialog::spacingHint());
TQVBox* scriptLabelBox = new TQVBox (mScriptBox);
TQLabel* servL = new TQLabel (i18n("&Available\n" \
"Services"), scriptLabelBox);
// provide quickhelp
TQWhatsThis::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>"));
TQFont bold_font = TQFont(KGlobalSettings::generalFont());
bold_font.setBold(TRUE);
servL->setFont(bold_font);
scripts = new KServiceDragList (scriptLabelBox, "Scripts");
scripts->setAcceptDrops (false);
scripts->setColumnWidthMode (KSVItem::SortNumber, TQListView::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, TQT_SIGNAL(executed(TQListViewItem*)),
this, TQT_SLOT(slotScriptProperties(TQListViewItem*)));
connect (scripts, TQT_SIGNAL (returnPressed (TQListViewItem*)),
this, TQT_SLOT (slotScriptProperties (TQListViewItem*)));
// context menus
connect (scripts, TQT_SIGNAL (contextMenu (KListView*, TQListViewItem*, const TQPoint&)),
this, TQT_SLOT (popupServicesMenu (KListView*, TQListViewItem*, const TQPoint&)));
// for cut & copy
connect (scripts, TQT_SIGNAL (newOrigin ()),
this, TQT_SLOT (fwdOrigin ()));
// for origin updates
connect (scripts, TQT_SIGNAL (newOrigin (KSVDragList*)),
this, TQT_SLOT (fwdOrigin (KSVDragList*)));
trash = new KSVTrash(mScriptBox, "Trash");
connect (trash, TQT_SIGNAL (undoAction (KSVAction*)), this, TQT_SLOT (fwdUndoAction (KSVAction*)));
TQWhatsThis::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 TQVBox (mContent);
lay->addWidget(mRunlevels[i]);
mRunlevels[i]->setSpacing (KDialog::spacingHint());
// create TQString for label
TQString _label (i18n("Runlevel &%1").tqarg(i));
// and for the name
TQString _name (i18n("Runlevel %1").tqarg(i));
TQVBox* startBox = new TQVBox (mRunlevels[i]);
TQWhatsThis::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>").tqarg(i));
TQLabel* rlL = new TQLabel(_label, startBox);
new TQLabel(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"));
TQVBox* stopBox = new TQVBox (mRunlevels[i]);
new TQLabel(i18n("Stop"), stopBox);
TQWhatsThis::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>").tqarg(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], TQT_SIGNAL (newOrigin ()),
this, TQT_SLOT (fwdOrigin ()));
connect (startRL[i], TQT_SIGNAL (newOrigin (KSVDragList*)),
this, TQT_SLOT (fwdOrigin (KSVDragList*)));
connect (stopRL[i], TQT_SIGNAL (newOrigin ()),
this, TQT_SLOT (fwdOrigin ()));
connect (stopRL[i], TQT_SIGNAL (newOrigin (KSVDragList*)),
this, TQT_SLOT (fwdOrigin (KSVDragList*)));
}
lay->addStretch(1);
connect (scripts, TQT_SIGNAL(undoAction(KSVAction*)),
this, TQT_SLOT(fwdUndoAction(KSVAction*)));
// add text-diplay widget
textDisplay = new TQTextEdit( TQString(), TQString(), this, "TextDisplayWidget" );
textDisplay->setTextFormat( TQt::RichText );
textDisplay->setReadOnly( true );
for (int i = 0; i < ksv::runlevelNumber; ++i)
{
connect (startRL[i], TQT_SIGNAL(newOrigin()), stopRL[i], TQT_SLOT(slotNewOrigin()));
connect (stopRL[i], TQT_SIGNAL(newOrigin()), startRL[i], TQT_SLOT(slotNewOrigin()));
connect (startRL[i], TQT_SIGNAL(undoAction(KSVAction*)),
this, TQT_SLOT(fwdUndoAction(KSVAction*)));
connect (stopRL[i], TQT_SIGNAL(undoAction(KSVAction*)),
this, TQT_SLOT(fwdUndoAction(KSVAction*)));
// doubleclick && return
connect (startRL[i], TQT_SIGNAL(executed(TQListViewItem*)),
this, TQT_SLOT(slotDoubleClick(TQListViewItem*)));
connect (stopRL[i], TQT_SIGNAL(executed(TQListViewItem*)),
this, TQT_SLOT(slotDoubleClick(TQListViewItem*)));
connect (startRL[i], TQT_SIGNAL(returnPressed(TQListViewItem*)),
this, TQT_SLOT(slotDoubleClick(TQListViewItem*)));
connect (stopRL[i], TQT_SIGNAL(returnPressed(TQListViewItem*)),
this, TQT_SLOT(slotDoubleClick(TQListViewItem*)));
// context menus
connect (startRL[i], TQT_SIGNAL (contextMenu (KListView*, TQListViewItem*, const TQPoint&)),
this, TQT_SLOT (popupRunlevelMenu (KListView*, TQListViewItem*, const TQPoint&)));
connect (stopRL[i], TQT_SIGNAL (contextMenu (KListView*, TQListViewItem*, const TQPoint&)),
this, TQT_SLOT (popupRunlevelMenu (KListView*, TQListViewItem*, const TQPoint&)));
// cannot generate sorting number
connect (startRL[i], TQT_SIGNAL(cannotGenerateNumber()),
this, TQT_SLOT(fwdCannotGenerateNumber()));
connect (stopRL[i], TQT_SIGNAL(cannotGenerateNumber()),
this, TQT_SLOT(fwdCannotGenerateNumber()));
// connecting origin things for "Scripts", too
connect (scripts, TQT_SIGNAL(newOrigin()), startRL[i], TQT_SLOT(slotNewOrigin()));
connect (scripts, TQT_SIGNAL(newOrigin()), stopRL[i], TQT_SLOT(slotNewOrigin()));
connect (startRL[i], TQT_SIGNAL(newOrigin()), scripts, TQT_SLOT(slotNewOrigin()));
connect (stopRL[i], TQT_SIGNAL(newOrigin()), scripts, TQT_SLOT(slotNewOrigin()));
// use this loop for setting tooltips
startRL[i]->setToolTip (i18n("Drag here to start services\n" \
"when entering runlevel %1").tqarg(i));
stopRL[i]->setToolTip (i18n("Drag here to stop services\n" \
"when entering runlevel %1").tqarg(i));
for (int j = 0; j < ksv::runlevelNumber; ++j)
{
if (i != j)
{
connect (startRL[i], TQT_SIGNAL (newOrigin()), startRL[j], TQT_SLOT (slotNewOrigin()));
connect (stopRL[i], TQT_SIGNAL (newOrigin()), stopRL[j], TQT_SLOT (slotNewOrigin()));
connect (startRL[i], TQT_SIGNAL(newOrigin()), stopRL[j], TQT_SLOT(slotNewOrigin()));
connect (stopRL[i], TQT_SIGNAL(newOrigin()), startRL[j], TQT_SLOT(slotNewOrigin()));
}
}
}
}
void KSVContent::fwdUndoAction (KSVAction* a)
{
emit undoAction(a);
}
void KSVContent::initScripts() {
TQDir scriptDir = TQDir(conf->scriptPath());
if (!scriptDir.exists())
return;
scriptDir.setFilter (TQDir::Files | TQDir::Hidden |
TQDir::NoSymLinks | TQDir::Executable);
scriptDir.setSorting (TQDir::Name);
// const TQFileInfoList *scriptList = scriptDir.entryInfoList();
TQFileInfoListIterator it (*scriptDir.entryInfoList());
KCompletion* comp = ksv::serviceCompletion();
comp->clear ();
// clear the listview
scripts->setEnabled(false);
scripts->clear();
TQFileInfo* fi; TQString 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
tqApp->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 TQString _path = conf->runlevelPath() + TQString("/rc%1.d").tqarg(i);
if (!TQDir(_path).exists())
continue;
TQDir d = TQDir(_path);
d.setFilter( TQDir::Files );
d.setSorting( TQDir::Name );
const TQFileInfoList *rlList = d.entryInfoList();
TQFileInfoListIterator it( *rlList ); // create list iterator
TQFileInfo* fi; // pointer for traversing
while ( (fi=it.current()) )
{ // for each file...
info2Widget( fi, i);
++it; // goto next list element
// keep GUI alive
tqApp->processEvents();
}
}
}
void KSVContent::info2Widget( TQFileInfo* info, int index )
{
if (!info->exists())
return;
TQString f_name = info->fileName();
TQFileInfo link_info = TQFileInfo(info->readLink());
TQString l_base = link_info.fileName();
TQString l_path = ksv::IO::relToAbs(conf->scriptPath(), link_info.dirPath(FALSE));
TQString 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>").tqarg(i),
i18n("** RUNLEVEL %1 **").tqarg(i));
clearRL(i); // rm changed/deleted entries
// process "Start"
KSVItem* item = 0L;
for (TQListViewItemIterator it (startRL[i]);
(item = static_cast<KSVItem*> (it.current()));
++it)
{
if (item->isChanged() || item->isNew())
writeToDisk (*item->data(), i, true);
}
// process "Stop"
for (TQListViewItemIterator 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) {
TQString 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)
{
TQString path = conf->runlevelPath() + TQString("/rc%1.d").tqarg(_rl);
TQDir dir (path);
KSVData* d = 0L;
for (TQPtrListIterator<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;
TQFileInfo file (path + TQString("/S%1%2").tqarg(d->numberString()).tqarg(d->label()));
TQString rich, plain;
ksv::IO::removeFile (file, dir, rich, plain);
appendLog(rich, plain);
}
// keep GUI alive
tqApp->processEvents();
for (TQPtrListIterator<KSVData> it (stopRL[_rl]->getDeletedItems());
(d = it.current());
++it)
{
// ugly, too
if (d->newEntry() && d->originalRunlevel() != stopRL[_rl]->name())
break;
TQFileInfo file (path + TQString("/K%1%2").tqarg(d->numberString()).tqarg(d->label()));
TQString rich, plain;
ksv::IO::removeFile (file, dir, rich, plain);
appendLog(rich, plain);
}
// keep GUI alive
tqApp->processEvents();
}
void KSVContent::infoOnData (KSVItem* item)
{
KSVData oldState = *item->data();
KSVData newState = oldState;
KSVEntryPropertiesDialog* props = new KSVEntryPropertiesDialog (newState, kapp->mainWidget());
connect (props, TQT_SIGNAL (editService (const TQString&)),
this, TQT_SLOT (editService (const TQString&)));
connect (props, TQT_SIGNAL (startService (const TQString&)),
this, TQT_SLOT (startService (const TQString&)));
connect (props, TQT_SIGNAL (stopService (const TQString&)),
this, TQT_SLOT (stopService (const TQString&)));
connect (props, TQT_SIGNAL (restartService (const TQString&)),
this, TQT_SLOT (restartService (const TQString&)));
int res = props->exec();
if (res == TQDialog::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 TQString& path)
{
KProcess *_proc = new KProcess();
_proc->clearArguments();
*_proc << path << "stop";
connect(_proc, TQT_SIGNAL(processExited(KProcess*)), this, TQT_SLOT(slotExitedProcess(KProcess*)));
connect(_proc, TQT_SIGNAL(receivedStdout(KProcess*, char*, int)), this, TQT_SLOT(slotOutputOrError(KProcess*, char*, int)));
connect(_proc, TQT_SIGNAL(receivedStderr(KProcess*, char*, int)), this, TQT_SLOT(slotOutputOrError(KProcess*, char*, int)));
// refresh textDisplay
appendLog(i18n("** <stop>Stopping</stop> <cmd>%1</cmd> **<br/>").tqarg(path),
i18n("** Stopping %1 **").tqarg(path));
_proc->start(KProcess::NotifyOnExit, KProcess::AllOutput);
// notify tqparent
emit sigRun(path + i18n(" stop"));
}
void KSVContent::startService ()
{
KSVContent::startService (getOrigin()->currentItem()->filenameAndPath());
}
void KSVContent::startService (const TQString& path)
{
KProcess* _proc = new KProcess();
_proc->clearArguments();
*_proc << path << "start";
connect(_proc, TQT_SIGNAL(processExited(KProcess*)), this, TQT_SLOT(slotExitedProcess(KProcess*)));
connect(_proc, TQT_SIGNAL(receivedStdout(KProcess*, char*, int)), this, TQT_SLOT(slotOutputOrError(KProcess*, char*, int)));
connect(_proc, TQT_SIGNAL(receivedStderr(KProcess*, char*, int)), this, TQT_SLOT(slotOutputOrError(KProcess*, char*, int)));
// refresh textDisplay
appendLog(i18n("** <start>Starting</start> <cmd>%1</cmd> **<br/>").tqarg(path),
i18n("** Starting %1 **").tqarg(path));
_proc->start(KProcess::NotifyOnExit, KProcess::AllOutput);
// notify tqparent
emit sigRun(path + i18n(" start"));
}
void KSVContent::editService()
{
editService (getOrigin()->currentItem()->filenameAndPath());
}
void KSVContent::editService (const TQString& 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 TQString& path)
{
// restarting
KProcess *_proc = new KProcess();
_proc->clearArguments();
*_proc << path << "restart";
connect(_proc, TQT_SIGNAL(processExited(KProcess*)), this, TQT_SLOT(slotExitDuringRestart(KProcess*)));
connect(_proc, TQT_SIGNAL(receivedStdout(KProcess*, char*, int)), this, TQT_SLOT(slotOutputOrError(KProcess*, char*, int)));
connect(_proc, TQT_SIGNAL(receivedStderr(KProcess*, char*, int)), this, TQT_SLOT(slotOutputOrError(KProcess*, char*, int)));
// refresh textDisplay
appendLog(i18n("** Re-starting <cmd>%1</cmd> **</br>").tqarg(path),
i18n("** Re-starting %1 **").tqarg(path));
_proc->start(KProcess::NotifyOnExit, KProcess::AllOutput);
// notify tqparent
emit sigRun(path + i18n(" restart"));
}
void KSVContent::slotOutputOrError( KProcess*, char* _buffer, int _buflen) {
if (_buflen > 0) {
m_buffer += TQCString( _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 (TQListViewItem* item) {
infoOnData(static_cast<KSVItem*>(item));
}
void KSVContent::slotScriptProperties(TQListViewItem* item)
{
KSVServicePropertiesDialog* prop =
new KSVServicePropertiesDialog (*static_cast<KSVItem*> (item)->data(), kapp->mainWidget());
connect (prop, TQT_SIGNAL (editService (const TQString&)),
this, TQT_SLOT (editService (const TQString&)));
connect (prop, TQT_SIGNAL (startService (const TQString&)),
this, TQT_SLOT (startService (const TQString&)));
connect (prop, TQT_SIGNAL (stopService (const TQString&)),
this, TQT_SLOT (stopService (const TQString&)));
connect (prop, TQT_SIGNAL (restartService (const TQString&)),
this, TQT_SLOT (restartService (const TQString&)));
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, TQT_SIGNAL(processExited(KProcess*)), this, TQT_SLOT(slotExitedProcess(KProcess*)));
connect(proc, TQT_SIGNAL(receivedStdout(KProcess*, char*, int)), this, TQT_SLOT(slotOutputOrError(KProcess*, char*, int)));
connect(proc, TQT_SIGNAL(receivedStderr(KProcess*, char*, int)), this, TQT_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 TQValueList<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 TQValueList<int>& KSVContent::panningFactorToSplitter (int panningFactor)
{
static TQValueList<int> res;
res.clear();
res << panningFactor << 100 - panningFactor;
return res;
}
void KSVContent::appendLog (const TQString& rich, const TQString& plain)
{
static bool changed = false;
if (!changed)
{
changed = true;
emit logChanged();
}
mLogText += plain + "\n";
mXMLLogText += rich + "\n";
textDisplay->append (rich);
}
void KSVContent::appendLog(const TQCString& _buffer)
{
TQStringList _lines = TQStringList::split( "\n", TQString::fromLocal8Bit( _buffer ) );
for ( TQStringList::Iterator it = _lines.begin(); it != _lines.end(); ++it )
appendLog( *it, *it );
m_buffer = TQCString();
}
const TQString& KSVContent::log () const
{
return mLogText;
}
const TQString& 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 (TQShowEvent* e)
{
calcMinSize();
TQSplitter::showEvent (e);
}
void KSVContent::reSortRL()
{
getOrigin()->sort();
}
void KSVContent::pasteAppend()
{
KSVDragList* list = getOrigin();
if (list)
{
KSVData data;
if (KSVDrag::decodeNative (kapp->tqclipboard()->data(), data))
{
KSVAction* action = 0L;
if (list->insert (data, list->lastItem(), action))
{
emit undoAction (action);
}
}
}
}
void KSVContent::resizeEvent (TQResizeEvent* e)
{
updatePanningFactor();
TQSplitter::resizeEvent (e);
}
void KSVContent::moveEvent (TQMoveEvent* e)
{
TQSplitter::moveEvent (e);
}
void KSVContent::setColors (const TQColor& newNormal,
const TQColor& newSelected,
const TQColor& changedNormal,
const TQColor& 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)
{
TQListView* 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();
TQFileInfo *file = new TQFileInfo( 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, TQListViewItem* i, const TQPoint& p)
{
if (i)
mItemMenu->exec (p, 1);
else
{
if (!list->header()->rect().contains (list->mapFromGlobal(p)))
mContextMenu->exec (p, 1);
}
}
void KSVContent::popupServicesMenu (KListView*, TQListViewItem* i, const TQPoint& 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, TQT_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
TQCOORD& w = mMinSize.rwidth();
TQCOORD& h = mMinSize.rheight();
w = 2 * KDialog::marginHint() + mScriptBox->tqsizeHint().width();
h = 2 * KDialog::marginHint() + mScriptBox->tqsizeHint().height();
for (int i = 0; i < ksv::runlevelNumber; ++i)
{
if (mRunlevels[i]->isHidden())
continue;
w += KDialog::spacingHint() + mRunlevels[i]->tqsizeHint().width();
h = kMax (h, mRunlevels[i]->tqsizeHint().height());
}
mContent->tqlayout()->setEnabled(false);
mContent->setMinimumSize(mMinSize);
mScroller->updateScrollBars();
mContent->tqlayout()->setEnabled(true);
}
void KSVContent::mergeLoadedPackage (TQValueList<KSVData>* start,
TQValueList<KSVData>* stop)
{
for (int i = 0; i < ksv::runlevelNumber; ++i)
{
merge (start[i], startRL[i]);
merge (stop[i], stopRL[i]);
}
}
void KSVContent::merge (TQValueList<KSVData>& list, KSVDragList* widget)
{
typedef TQMap<KSVData, bool> LoadMap;
LoadMap loaded;
for (TQValueListIterator<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 ();
}
TQPtrList<KSVItem> deleteList;
deleteList.setAutoDelete (true);
for (TQListViewItemIterator 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"