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.
1151 lines
33 KiB
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 <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* parent, const char* name)
|
|
: TQSplitter (Qt::Vertical, parent, 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 = 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 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").arg(i));
|
|
// and for the name
|
|
TQString _name (i18n("Runlevel %1").arg(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>").arg(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>").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], 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").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], 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").arg(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>").arg(i),
|
|
i18n("** RUNLEVEL %1 **").arg(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").arg(_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").arg(d->numberString()).arg(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").arg(d->numberString()).arg(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/>").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 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/>").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 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>").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 += 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->clipboard()->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->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 (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"
|