summaryrefslogtreecommitdiffstats
path: root/ksysv/TopWidget.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ksysv/TopWidget.cpp')
-rw-r--r--ksysv/TopWidget.cpp1109
1 files changed, 1109 insertions, 0 deletions
diff --git a/ksysv/TopWidget.cpp b/ksysv/TopWidget.cpp
new file mode 100644
index 0000000..854c9cf
--- /dev/null
+++ b/ksysv/TopWidget.cpp
@@ -0,0 +1,1109 @@
+/*
+ Requires the Qt widget libraries, available at no cost at
+ http://www.troll.no
+
+ Copyright (C) 1997-2000 Peter Putzer
+ putzer@kde.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+/****************************************************************
+**
+** KSysV
+** Toplevel Widget
+**
+****************************************************************/
+
+#include <ctype.h>
+
+#include <qpopupmenu.h>
+#include <qkeycode.h>
+#include <qmessagebox.h>
+#include <qfontmetrics.h>
+#include <qpainter.h>
+#include <qmultilineedit.h>
+#include <qdatetime.h>
+#include <kprinter.h>
+#include <qpaintdevicemetrics.h>
+#include <qbuttongroup.h>
+#include <qclipboard.h>
+#include <qtooltip.h>
+#include <qcheckbox.h>
+#include <qhbox.h>
+#include <qregexp.h>
+#include <qdatastream.h>
+#include <qpixmapcache.h>
+#include <qtextview.h>
+#include <qfileinfo.h>
+#include <qtextstream.h>
+#include <qwhatsthis.h>
+#include <qsimplerichtext.h>
+
+#include <kresolver.h>
+#include <ktoolbar.h>
+#include <kkeydialog.h>
+#include <kmenubar.h>
+#include <kcompletion.h>
+#include <kaction.h>
+#include <kstdaction.h>
+#include <kdebug.h>
+#include <kapplication.h>
+#include <kglobal.h>
+#include <khelpmenu.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kstdaccel.h>
+#include <kedittoolbar.h>
+#include <kiconloader.h>
+#include <kfiledialog.h>
+#include <kaboutdata.h>
+#include <kcursor.h>
+
+#include "kbusymanager.h"
+#include "ServiceDlg.h"
+#include "PreferencesDialog.h"
+#include "ActionList.h"
+#include "ksv_core.h"
+#include "ksv_conf.h"
+#include "RunlevelAuthIcon.h"
+#include "ksvdraglist.h"
+#include "Data.h"
+#include "ksvdrag.h"
+#include "OldView.h"
+#include "IOCore.h"
+#include "TopWidget.h"
+#include <qlabel.h>
+#include <kstatusbar.h>
+
+namespace Status
+{
+ enum {
+ Changed, Checklist, Writable
+ };
+} // namespace Status
+
+KSVTopLevel::KSVTopLevel()
+ : KMainWindow(0, 0L, WStyle_ContextHelp|WDestructiveClose),
+ mConfig(KSVConfig::self()),
+ mView (0L),
+ mPreferences (0L),
+
+ mEditUndo (0L), mEditCut (0L), mEditCopy (0L), mEditPaste (0L),
+ mEditProperties (0L),
+
+ mFileRevert (0L), mFileLoad (0L), mFilePrint (0L), mFilePrintLog (0L),
+ mFileSave (0L), mFileSaveAs (0L), mFileSaveLog(0L), mFileQuit (0L),
+
+ mToolsStartService (0L), mToolsStopService (0L),
+ mToolsRestartService (0L), mToolsEditService (0L),
+
+ mOptionsToggleLog (0L),
+
+ mOpenWith (0L), mOpenDefault (0L),
+
+ mUndoList (new ActionList (this, "UndoList")),
+ mRedoList (new ActionList (this, "RedoList")),
+ mStartDlg (new ServiceDlg (i18n("Start Service"),
+ i18n("&Choose which service to start:"),
+ this)),
+ mStopDlg (new ServiceDlg (i18n("Stop Service"),
+ i18n("&Choose which service to stop:"),
+ this)),
+ mRestartDlg (new ServiceDlg (i18n("Restart Service"),
+ i18n("&Choose which service to restart:"),
+ this)),
+ mEditDlg (new ServiceDlg (i18n("Edit Service"),
+ i18n("&Choose which service to edit:"),
+ this)),
+ mVisible (new QCheckBox*[ksv::runlevelNumber])
+{
+ setCaption(false);
+
+ initStatusBar(); // order dependency
+ initActions(); // order dependency
+ mView = new KSVContent (mOpenWith->popupMenu(), this, "Content"); // order dependency
+ initTools(); // order dependency
+
+ setCentralWidget(mView);
+
+ // ensure that the statusbar gets updated correctly
+ connect (mView, SIGNAL(sigRun(const QString&)), this, SLOT(slotUpdateRunning(const QString&)));
+ connect (mView, SIGNAL(sigStop()), statusBar(), SLOT(clear()));
+ connect (mView, SIGNAL(cannotGenerateNumber()), this, SLOT(catchCannotGenerateNumber()));
+ connect (mView, SIGNAL(undoAction(KSVAction*)), this, SLOT(pushUndoAction(KSVAction*)));
+ connect (mView, SIGNAL(logChanged()), this, SLOT(enableLogActions()));
+
+ // cut & copy
+ connect (mView, SIGNAL (newOrigin()),
+ this, SLOT (dispatchEdit()));
+
+ // undo
+ connect (mUndoList, SIGNAL(empty()), this, SLOT(disableUndo()));
+ connect (mUndoList, SIGNAL(filled()), this, SLOT(enableUndo()));
+
+ // and redo
+ connect (mRedoList, SIGNAL(empty()), this, SLOT(disableRedo()));
+ connect (mRedoList, SIGNAL(filled()), this, SLOT(enableRedo()));
+
+ // paste
+ connect (kapp->clipboard(), SIGNAL (dataChanged()),
+ this, SLOT (dispatchEdit()));
+
+ // init mView according to saved preferences
+ slotReadConfig();
+ initView();
+ setMinimumSize(600,400);
+
+ // restore size and position
+ move(mConfig->position()); // doesnt seem to work while unmapped
+ setAutoSaveSettings();
+
+ // start watching the directories
+ mAuth->setCheckEnabled(true);
+
+ dispatchEdit(); // disable cut & copy on startup
+}
+
+KSVTopLevel::~KSVTopLevel()
+{
+ mUndoList->clear();
+ mRedoList->clear();
+
+ delete[] mVisible;
+}
+
+void KSVTopLevel::initTools()
+{
+ connect (mStartDlg, SIGNAL(doAction(const QString&)),
+ mView, SLOT(startService(const QString&)));
+ connect (mStopDlg, SIGNAL(doAction(const QString&)),
+ mView, SLOT(editService(const QString&)));
+ connect (mRestartDlg, SIGNAL(doAction(const QString&)),
+ mView, SLOT(restartService(const QString&)));
+ connect (mEditDlg, SIGNAL(doAction(const QString&)),
+ mView, SLOT(editService(const QString&)));
+
+ connect (mStartDlg, SIGNAL (display (bool)),
+ this, SLOT (dispatchStartService (bool)));
+ connect (mStopDlg, SIGNAL (display (bool)),
+ this, SLOT (dispatchStopService (bool)));
+ connect (mRestartDlg, SIGNAL (display (bool)),
+ this, SLOT (dispatchRestartService (bool)));
+ connect (mEditDlg, SIGNAL (display (bool)),
+ this, SLOT (dispatchEditService (bool)));
+
+}
+
+void KSVTopLevel::initActions ()
+{
+ KActionCollection* coll = actionCollection();
+
+ // setup File menu
+ mFileRevert = KStdAction::revert (this, SLOT (slotClearChanges()), coll);
+ mFileRevert->setText (i18n("Re&vert Configuration"));
+
+ mFileLoad = KStdAction::open (this, SLOT (load()), coll);
+ mFileLoad->setText (i18n ("&Open..."));
+
+ mFileSave = KStdAction::save(this, SLOT(slotAcceptChanges()), coll);
+ mFileSave->setText (i18n("&Save Configuration"));
+
+ mFileSaveAs = KStdAction::saveAs (this, SLOT (saveAs ()), coll);
+
+ mFileSaveLog = KStdAction::save (this, SLOT(slotSaveLog()), coll, "ksysv_save_log");
+ mFileSaveLog->setText (i18n("Save &Log..."));
+ mFileSaveLog->setShortcut (Key_L+CTRL);
+ mFileSaveLog->setEnabled (false);
+
+ // disabled due to complexity
+ // mFilePrint = KStdAction::print (this, SLOT (print()), coll);
+
+ mFilePrintLog = KStdAction::print(this, SLOT(printLog()), coll, "ksysv_print_log");
+ mFilePrintLog->setText( i18n("&Print Log..."));
+ mFilePrintLog->setEnabled (false);
+
+ mFileQuit = KStdAction::quit(this, SLOT(close()), coll);
+
+ // setup Edit menu
+ mEditUndo = KStdAction::undo(this, SLOT(editUndo()), coll);
+ mEditUndo->setEnabled (false);
+ mEditRedo = KStdAction::redo(this, SLOT(editRedo()), coll);
+ mEditUndo->setEnabled (false);
+ mEditCut = KStdAction::cut(this, SLOT(editCut()), coll);
+ mEditCopy = KStdAction::copy(this, SLOT(editCopy()), coll);
+ mEditPaste = KStdAction::paste(this, SLOT(editPaste()), coll);
+ mPasteAppend = KStdAction::paste (this, SLOT (pasteAppend()),
+ coll, "ksysv_paste_append");
+
+ mEditProperties = new KAction (i18n("P&roperties"), 0,
+ this, SLOT(properties()),
+ coll, "ksysv_properties");
+
+ mOpenDefault = new KAction (i18n ("&Open"), 0,
+ this, SLOT (editService()),
+ coll, "ksysv_open_service");
+
+ mOpenWith = new KActionMenu (i18n ("Open &With"), coll, "ksysv_open_with");
+
+ // setup Settings menu
+ createStandardStatusBarAction();
+ setStandardToolBarMenuEnabled(true);
+ KStdAction::keyBindings (this, SLOT(configureKeys()), coll);
+ KStdAction::configureToolbars (this, SLOT(configureToolbars()), coll);
+ KStdAction::saveOptions(this, SLOT(saveOptions()), coll);
+ KStdAction::preferences(this, SLOT(slotShowConfig()), coll);
+ mOptionsToggleLog = new KToggleAction (i18n("Show &Log"), "toggle_log", 0,
+ this, SLOT (toggleLog()),
+ coll, "ksysv_toggle_log");
+ mOptionsToggleLog->setCheckedState(i18n("Hide &Log"));
+
+ // setup Tools menu
+ mToolsStartService = new KToggleAction (i18n("&Start Service..."), "ksysv_start", 0,
+ mStartDlg, SLOT (toggle()),
+ coll, "ksysv_start_service");
+
+ mToolsStopService = new KToggleAction (i18n("&Stop Service..."), "ksysv_stop", 0,
+ mStopDlg, SLOT (toggle()),
+ coll, "ksysv_stop_service");
+
+ mToolsRestartService = new KToggleAction (i18n("&Restart Service..."), 0,
+ mRestartDlg, SLOT (toggle()),
+ coll, "ksysv_restart_service");
+
+ mToolsEditService = new KToggleAction (i18n("&Edit Service..."), 0,
+ mEditDlg, SLOT (toggle()),
+ coll, "ksysv_edit_service");
+
+ createGUI(xmlFile());
+}
+
+//
+bool KSVTopLevel::queryExit()
+{
+ uint res = KMessageBox::Continue;
+
+ if (mChanged) {
+ res = KMessageBox::warningContinueCancel(kapp->mainWidget(),
+ i18n("There are unsaved changes. Are you sure you want to quit?"),
+ i18n("Quit"),
+ KStdGuiItem::quit());
+
+ }
+
+ return res == KMessageBox::Continue;
+}
+
+void KSVTopLevel::slotClearChanges()
+{
+ if (mChanged &&
+ KMessageBox::Yes ==
+ KMessageBox::questionYesNo(kapp->mainWidget(),
+ i18n("Do you really want to revert all unsaved changes?"),
+ i18n("Revert Configuration"),
+ i18n("&Revert"),
+ KStdGuiItem::cancel()))
+ {
+ mUndoList->undoAll();
+ mRedoList->clear();
+ }
+}
+
+void KSVTopLevel::slotAcceptChanges() {
+ if (KMessageBox::Continue ==
+ KMessageBox::warningContinueCancel(kapp->mainWidget(),
+ i18n("You're about to save the changes made to your init "
+ "configuration. Wrong settings can "
+ "make your system hang on startup.\n"
+ "Do you wish to continue?"),
+ i18n("Save Configuration"),
+ KStdGuiItem::save()))
+ {
+ mView->slotWriteSysV();
+ initView();
+ }
+}
+
+void KSVTopLevel::initView()
+{
+ const bool authEnabled = mAuth->isCheckEnabled();
+ mAuth->setCheckEnabled(false);
+
+ mUndoList->clear();
+ mRedoList->clear();
+
+ mView->initScripts();
+ mView->initRunlevels();
+
+ setChanged(false);
+
+ // disable ToolsMenu_ entries when they can't do anything
+ ServiceDlg* tmp = new ServiceDlg ("","", this);
+
+ tmp->resetChooser (mView->scripts, false);
+ if (!tmp->count())
+ {
+ mToolsStartService->setEnabled (false);
+ mToolsStopService->setEnabled (false);
+ mToolsRestartService->setEnabled (false);
+ }
+ else
+ {
+ mToolsStartService->setEnabled (true);
+ mToolsStopService->setEnabled (true);
+ mToolsRestartService->setEnabled (true);
+ }
+
+ tmp->resetChooser (mView->scripts, true);
+ if (!tmp->count())
+ {
+ mToolsEditService->setEnabled (false);
+ }
+ else
+ {
+
+ mToolsEditService->setEnabled (true);
+ }
+ delete tmp;
+
+ // reset tools
+ mStartDlg->resetChooser (mView->scripts, false);
+ mStopDlg->resetChooser (mView->scripts, false);
+ mRestartDlg->resetChooser (mView->scripts, false);
+ mEditDlg->resetChooser (mView->scripts, true);
+
+ mAuth->setCheckEnabled(authEnabled);
+}
+
+void KSVTopLevel::initStatusBar()
+{
+ KStatusBar* status = statusBar();
+
+ QHBox* visBox = new QHBox (status, "visBox");
+ QButtonGroup* group = new QButtonGroup (this, "visButtonGroup");
+ group->hide();
+ connect (group, SIGNAL (clicked (int)), this, SLOT (toggleRunlevel (int)));
+
+ QWhatsThis::add (visBox, i18n ("<p>Click on the checkboxes to <strong>show</strong> or "\
+ "<strong>hide</strong> runlevels.</p> " \
+ "<p>The list of currently visible runlevels is saved "\
+ "when you use the <strong>Save Options command</strong>.</p>"));
+ QToolTip::add (visBox, i18n ("Show only the selected runlevels"));
+
+ new QLabel (i18n("Show runlevels:"), visBox, "visLabel");
+ for (int i = 0; i < ksv::runlevelNumber; ++i)
+ {
+ QString label; label.setNum (i);
+
+ mVisible[i] = new QCheckBox (label, visBox, label.latin1());
+ mVisible[i]->setChecked (mConfig->showRunlevel (i));
+
+ group->insert (mVisible[i]);
+ }
+
+ QHBox* authIconBox = new QHBox (status, "AuthIconBox");
+ QWidget* strut = new QWidget (authIconBox, "Strut");
+ strut->setFixedWidth (KDialog::spacingHint());
+ mAuth = new RunlevelAuthIcon (mConfig->scriptPath(), mConfig->runlevelPath(), authIconBox);
+ connect (mAuth, SIGNAL (authChanged(bool)), mView, SLOT(multiplexEnabled(bool)));
+ connect (mAuth, SIGNAL (authChanged(bool)), this, SLOT(writingEnabled(bool)));
+
+ QWhatsThis::add (authIconBox, i18n ("<p>If the lock is closed <img src=\"user|ksysv_locked\"/>, "\
+ "you don't have the right " \
+ "<strong>permissions</strong> to edit the init configuration.</p>" \
+ "<p>Either restart %1 as root (or another more privileged user), " \
+ "or ask your sysadmin to install %1 <em>suid</em> or " \
+ "<em>sgid</em>.</p><p>The latter way is <strong>not</strong> "\
+ "recommended though, due to security issues.</p>")
+ .arg (kapp->aboutData()->programName()).arg(kapp->aboutData()->programName()));
+
+ authIconBox->setMinimumSize (authIconBox->minimumSizeHint());
+ visBox->setMinimumSize (visBox->minimumSizeHint());
+
+ status->addWidget (authIconBox, 0, false);
+ status->insertItem ("", Status::Changed, 100);
+ status->addWidget (visBox, 0, true);
+
+ status->setItemAlignment (Status::Changed, AlignLeft|AlignVCenter);
+}
+
+void KSVTopLevel::slotShowConfig()
+{
+ if (!mPreferences)
+ {
+ mPreferences = KSVPreferences::self();
+
+ connect (mPreferences, SIGNAL (updateColors ()),
+ this, SLOT (updateColors ()));
+
+ connect (mPreferences, SIGNAL (updateServicesPath ()),
+ this, SLOT (updateServicesPath ()));
+
+ connect (mPreferences, SIGNAL (updateRunlevelsPath ()),
+ this, SLOT (updateRunlevelsPath ()));
+
+ connect (mPreferences, SIGNAL (updateFonts ()),
+ mView, SLOT (repaintRunlevels ()));
+ }
+
+// mPreferences->setInitialSize (QSize (400,300), true);
+ mPreferences->exec();
+}
+
+void KSVTopLevel::updateColors ()
+{
+ ksv::serviceCompletion ()->clear ();
+
+ mView->setColors (mConfig->newNormalColor(),
+ mConfig->newSelectedColor(),
+ mConfig->changedNormalColor(),
+ mConfig->changedSelectedColor());
+}
+
+void KSVTopLevel::updateServicesPath ()
+{
+ mView->updateServicesAfterChange (mConfig->scriptPath());
+ mAuth->setServicesPath (mConfig->scriptPath());
+}
+
+void KSVTopLevel::updateRunlevelsPath ()
+{
+ mView->updateRunlevelsAfterChange ();
+ mAuth->setRunlevelPath (mConfig->runlevelPath());
+}
+
+void KSVTopLevel::slotReadConfig() {
+ setLog(mConfig->showLog());
+}
+
+void KSVTopLevel::toggleLog() {
+ const bool value = !mConfig->showLog();
+ setLog(value);
+}
+
+void KSVTopLevel::saveOptions()
+{
+ mConfig->writeSettings();
+}
+
+void KSVTopLevel::slotUpdateRunning (const QString& text)
+{
+ statusBar()->changeItem(text, Status::Changed);
+}
+
+void KSVTopLevel::editCut() {
+ KSVDragList* list = mView->getOrigin();
+
+ if (list && list->currentItem())
+ {
+ KSVDrag* mime = new KSVDrag (*list->currentItem()->data(), 0L, 0L);
+ kapp->clipboard()->setData (mime);
+
+ KSVData data = *list->currentItem()->data();
+ delete list->currentItem();
+
+ mUndoList->push (new RemoveAction (list, &data));
+ setChanged (true);
+ }
+}
+
+void KSVTopLevel::editCopy()
+{
+ KSVDragList* list = mView->getOrigin();
+
+ if (list)
+ {
+ KSVDrag* mime = new KSVDrag (*static_cast<KSVItem*> (list->currentItem()), 0L, 0L);
+ kapp->clipboard()->setData (mime);
+ }
+}
+
+void KSVTopLevel::editPaste()
+{
+ KSVDragList* list = mView->getOrigin();
+
+ if (list)
+ {
+ KSVData data;
+
+ if (KSVDrag::decodeNative (kapp->clipboard()->data(), data))
+ {
+ KSVAction* action = 0L;
+
+ if (list->insert (data, list->currentItem(), action))
+ {
+ setChanged (true);
+ mUndoList->push (new AddAction (list, list->match (data)->data()));
+ }
+ }
+ }
+ else
+ qFatal("Bug: could not get origin of \"Paste\" event.\n" \
+ "Please notify the maintainer of this program,\n" \
+ "Peter Putzer <putzer@kde.org>.");
+}
+
+void KSVTopLevel::setChanged (bool val)
+{
+ mChanged = val;
+ setCaption(val);
+
+ mFileRevert->setEnabled (val);
+ mFileSave->setEnabled (val);
+
+ // update statusbar
+ statusBar()->changeItem(val ? i18n(" Changed") : QString::null, Status::Changed);
+
+ // clear messages
+ statusBar()->clear();
+}
+
+void KSVTopLevel::properties()
+{
+ KSVDragList* list = mView->getOrigin();
+
+ if (list)
+ mView->infoOnData(list->currentItem());
+}
+
+void KSVTopLevel::scriptProperties()
+{
+ KSVDragList* list = mView->getOrigin();
+
+ if (list)
+ mView->slotScriptProperties(list->currentItem());
+}
+
+void KSVTopLevel::editUndo ()
+{
+ KSVAction* action = mUndoList->top();
+
+ mUndoList->undoLast();
+
+ mRedoList->push (action);
+}
+
+void KSVTopLevel::editRedo ()
+{
+ KSVAction* action = mRedoList->top();
+
+ mRedoList->redoLast();
+
+ setChanged (true);
+ mUndoList->push (action);
+}
+
+void KSVTopLevel::setPaste (bool val)
+{
+ mEditPaste->setEnabled (val);
+ mPasteAppend->setEnabled (val);
+}
+
+void KSVTopLevel::setLog (bool val)
+{
+ mConfig->setShowLog(val);
+
+ mOptionsToggleLog->setChecked (val);
+
+ mView->setDisplayScriptOutput(val);
+}
+
+void KSVTopLevel::writingEnabled (bool on)
+{
+ mFileLoad->setEnabled(on);
+}
+
+void KSVTopLevel::print()
+{
+// #define checkPage if (metrics.height() - y < fm.lineSpacing()) prt.newPage();
+
+// static KPrinter prt;
+// prt.setDocName(kapp->aboutData()->programName() + " Configuration");
+// prt.setCreator(kapp->aboutData()->programName());
+
+// static QPrintDialog* dlg = new QPrintDialog (&prt, this, "KSysV Print Dialog");
+// dlg->setCaption(kapp->makeStdCaption (i18n("Print")));
+
+// if (dlg->exec() == QDialog::Accepted)
+// {
+// int y = 10;
+// QPainter p;
+// p.begin( &prt );
+
+// QPaintDeviceMetrics metrics (&prt);
+
+// p.setFont (QFont("courier", 20, QFont::Bold));
+// QFontMetrics fm = p.fontMetrics();
+
+// p.drawText (10, y, i18n("%1 Configuration of %2")
+// .arg (kapp->aboutData()->programName())
+// .arg (ksv::hostname()));
+// y += fm.lineSpacing();
+
+// p.drawText (10, y, QDateTime::currentDateTime().toString());
+// y += fm.lineSpacing() * 2; // an extra empty line
+
+// for (int i = 0; i < ksv::runlevelNumber; ++i)
+// {
+// p.setFont (QFont("courier", 16, QFont::Bold));
+// QFontMetrics fm = p.fontMetrics();
+
+// p.drawText (10, y, i18n ("Runlevel %1").arg(i));
+// y += fm.lineSpacing();
+
+// checkPage
+
+// p.drawText (10, y, i18n ("Started Services"));
+// y += fm.lineSpacing() * 2; // an extra empty line
+
+// checkPage
+
+// p.setFont (QFont("courier", 10));
+// fm = p.fontMetrics();
+
+// for (QListViewItemIterator it (mView->startRL[i]);
+// it.current();
+// ++it)
+// {
+// KSVItem* item = static_cast<KSVItem*> (it.current());
+
+// y += fm.ascent();
+// p.drawText (10, y, item->toString());
+// y += fm.descent();
+
+// checkPage
+
+// }
+
+// p.setFont (QFont("courier", 16, QFont::Bold));
+// fm = p.fontMetrics();
+// y += fm.lineSpacing(); // an extra empty line
+// p.drawText (10, y, i18n ("Stopped Services"));
+// y += fm.lineSpacing() * 2; // an extra empty line
+
+// checkPage
+
+// p.setFont (QFont("courier", 10));
+// fm = p.fontMetrics();
+
+// for (QListViewItemIterator it (mView->stopRL[i]);
+// it.current();
+// ++it)
+// {
+// KSVItem* item = static_cast<KSVItem*> (it.current());
+// checkPage
+
+// y += fm.ascent();
+// p.drawText (10, y, item->toString());
+// y += fm.descent();
+// }
+// checkPage
+
+// p.setFont (QFont("courier", 16, QFont::Bold));
+// fm = p.fontMetrics();
+// y += fm.lineSpacing() * 3; // two extra empty line
+// }
+// // QStringList lines = QStringList::split ('\n', mView->log(), true);
+// // for(QStringList::Iterator it = lines.begin();
+// // it != lines.end();
+// // ++it)
+// // {
+// // y += fm.ascent();
+
+// // QString line = *it;
+// // if (line.isNull())
+// // line = " ";
+
+// // line.replace( QRegExp("\t"), " " );
+
+// // strncpy(buf,line.data(),160);
+
+// // for (int j = 0 ; j <150; j++)
+// // {
+// // if (!isprint(buf[j]))
+// // buf[j] = ' ';
+// // }
+
+// // buf[line.length()] = '\0';
+// // p.drawText( 10, y, buf );
+// // y += fm.descent();
+// // }
+
+// p.end();
+// }
+}
+
+void KSVTopLevel::printLog()
+{
+ KPrinter *prt = new KPrinter();
+ prt->setDocName(kapp->aboutData()->programName() + " Log File");
+ prt->setCreator(kapp->aboutData()->programName());
+
+ if (prt->setup(this, i18n("Print Log File")))
+ {
+ KBusyManager::self()->setBusy (true);
+
+ QPainter p (prt);
+ QPaintDeviceMetrics pm (prt);
+ const int height = pm.height();
+ const int width = pm.width();
+
+ QStringList lines = QStringList::split ('\n', mView->xmlLog(), true);
+ QStringList::Iterator line = lines.begin();
+
+ int y = 0;
+
+ {
+ QSimpleRichText rheading (i18n("<h1>KDE Sys-V Init Editor Log</h1>"),
+ QFont("times"), QString::null, ksv::styleSheet(),
+ QMimeSourceFactory::defaultFactory());
+ rheading.setWidth (&p, width);
+ int tmp_h = rheading.height();
+ QRegion region (0, y, width, tmp_h);
+ rheading.draw (&p, 0, y, region, colorGroup(), 0L);
+
+ y += tmp_h;
+
+ QSimpleRichText rdate (i18n("<h3>Printed on %1</h3><br/><br/>").arg(KGlobal::locale()->formatDateTime(QDateTime::currentDateTime())),
+ QFont("times"), QString::null, ksv::styleSheet(),
+ QMimeSourceFactory::defaultFactory());
+ rdate.setWidth (&p, width);
+ tmp_h = rdate.height();
+ QRegion r2 (0, y, width, tmp_h);
+ rdate.draw (&p, 0, y, r2, colorGroup(), 0L);
+
+ y += tmp_h;
+ }
+
+ while (line != lines.end())
+ {
+ while (y < height)
+ {
+ QSimpleRichText rich (*line, QFont("times"), QString::null, ksv::styleSheet(),
+ QMimeSourceFactory::defaultFactory());
+ rich.setWidth (&p, width);
+
+ int tmp_h = rich.height();
+ if (y + tmp_h > height)
+ break;
+
+ QRegion region (0, y, width, tmp_h);
+ rich.draw (&p, 0, y, region, colorGroup(), 0L);
+
+ y += tmp_h;
+ ++line;
+
+ if (line == lines.end())
+ goto printing_finished;
+
+ kapp->processEvents();
+ }
+
+ prt->newPage();
+ y = 0;
+ }
+
+ printing_finished:
+
+ p.end();
+
+ KBusyManager::self()->restore();
+ delete prt;
+ }
+}
+
+void KSVTopLevel::catchCannotGenerateNumber()
+{
+ if (mConfig->showMessage (ksv::CouldNotGenerateSortingNumber)) {
+ KMessageBox::information (kapp->mainWidget(),
+ i18n ("<p>Unable to generate a valid " \
+ "sorting number for this position. This means " \
+ "that there was no number available between "\
+ "the two adjacent services, and the service " \
+ "did not fit in lexically.</p>" \
+ "<p>Please adjust the sorting numbers manually "\
+ "via the <strong>Properties dialog box</strong>.</p>"),
+ i18n ("Unable to Generate Sorting Number"),
+ ksv::notifications[ksv::CouldNotGenerateSortingNumber]);
+ }
+
+ statusBar()->message (i18n ("Unable to generate sorting number. Please change manually."),
+ 5000);
+}
+
+void KSVTopLevel::closeEvent (QCloseEvent* e)
+{
+ if (KBusyManager::self()->isBusy())
+ {
+ // do not allow a close during clearing => otherwise we get a segfault
+ e->ignore();
+ return;
+ }
+
+ KMainWindow::closeEvent (e);
+}
+
+void KSVTopLevel::dispatchEdit ()
+{
+ KSVDragList* list = mView->getOrigin();
+
+ if (!list)
+ {
+ mEditCopy->setEnabled (false);
+ mEditCut->setEnabled (false);
+ mEditProperties->setEnabled (false);
+ setPaste (false);
+
+ return;
+ }
+
+ KSVItem* current = list->currentItem();
+
+ if (current) // there's a list, and it's got items...
+ {
+ mEditCopy->setEnabled (true);
+ mEditCut->setEnabled (true);
+ mEditProperties->setEnabled (true);
+ }
+ else // no current item
+ {
+ mEditCopy->setEnabled (false);
+ mEditCut->setEnabled (false);
+ mEditProperties->setEnabled (false);
+ }
+
+ if (mView->scripts == list)
+ {
+ mEditCut->setEnabled (false);
+ setPaste (false);
+ }
+ else
+ {
+ QMimeSource* mime = kapp->clipboard()->data();
+
+ if (mime && mime->provides ("application/x-ksysv"))
+ setPaste (true);
+ else
+ setPaste (false);
+ }
+}
+
+void KSVTopLevel::enableUndo()
+{
+ mEditUndo->setEnabled (true);
+}
+
+void KSVTopLevel::disableUndo()
+{
+ mEditUndo->setEnabled (false);
+ setChanged(false);
+}
+
+void KSVTopLevel::enableRedo()
+{
+ mEditRedo->setEnabled (true);
+}
+
+void KSVTopLevel::disableRedo ()
+{
+ mEditRedo->setEnabled (false);
+}
+
+void KSVTopLevel::slotSaveLog()
+{
+ static const QString& filter = ksv::logFileFilter();
+ static const QString& ext = ksv::logFileExtension();
+ QString filename = KFileDialog::getSaveFileName(0L, filter, this);
+
+ if (filename.isEmpty())
+ return;
+ else if (filename.right(ext.length()) != ext)
+ filename += ext;
+
+ QFile file(filename);
+
+ file.open( IO_WriteOnly | IO_Raw );
+ QTextStream s(&file);
+
+ s << "KDE System V Init Editor"
+ << endl
+ << QDateTime::currentDateTime().toString()
+ << endl << endl
+ << mView->log()
+ << endl;
+
+ file.close();
+}
+
+void KSVTopLevel::enableLogActions ()
+{
+ mFileSaveLog->setEnabled (true);
+ mFilePrintLog->setEnabled (true); // disabled due to complexity
+}
+
+void KSVTopLevel::setCaption (bool changed)
+{
+ setPlainCaption (kapp->makeStdCaption(KNetwork::KResolver::localHostName(), true, changed));
+}
+
+KActionCollection* KSVTopLevel::filteredActions ()
+{
+ // remove unwanted (internal) actions
+ static KActionCollection coll = *actionCollection();
+ static bool initialized = false;
+
+ if (!initialized)
+ {
+ coll.take(mPasteAppend);
+ coll.take(mOpenDefault);
+ initialized = true;
+ }
+
+ return &coll;
+}
+
+void KSVTopLevel::configureKeys ()
+{
+ KKeyDialog::configure (filteredActions(), this, true);
+}
+
+void KSVTopLevel::configureToolbars ()
+{
+ KEditToolbar dlg(filteredActions(), xmlFile(), true, this);
+ connect(&dlg, SIGNAL( newToolbarConfig() ), this, SLOT( slotNewToolbarConfig() ));
+ dlg.exec();
+}
+
+void KSVTopLevel::slotNewToolbarConfig()
+{
+ createGUI (xmlFile());
+}
+
+void KSVTopLevel::dispatchEditService (bool val)
+{
+ mToolsEditService->setChecked (val);
+}
+
+void KSVTopLevel::dispatchStartService (bool val)
+{
+ mToolsStartService->setChecked (val);
+}
+
+void KSVTopLevel::dispatchStopService (bool val)
+{
+ mToolsStopService->setChecked (val);
+}
+
+void KSVTopLevel::dispatchRestartService (bool val)
+{
+ mToolsRestartService->setChecked (val);
+}
+
+void KSVTopLevel::pasteAppend ()
+{
+ mView->pasteAppend ();
+}
+
+void KSVTopLevel::editService ()
+{
+ mView->editService ();
+}
+
+void KSVTopLevel::toggleRunlevel (int index)
+{
+ bool state = mVisible[index]->isChecked();
+
+ if (state)
+ mView->showRunlevel (index);
+ else
+ mView->hideRunlevel (index);
+
+ mConfig->setShowRunlevel (index, state);
+}
+
+void KSVTopLevel::saveAs ()
+{
+ static const QString& filter = ksv::nativeFileFilter();
+ static const QString& ext = ksv::nativeFileExtension();
+ QString filename = KFileDialog::getSaveFileName(0L, filter, this);
+
+ if (filename.isEmpty())
+ return;
+ else if (filename.right(ext.length()) != ext)
+ filename += ext;
+
+ QFile file(filename);
+ // we're busy
+ KBusyManager::self()->setBusy (true);
+
+ file.open (IO_WriteOnly | IO_Raw);
+ QDataStream s (&file);
+
+ if (ksv::IO::saveConfiguration (s, mView->startRL, mView->stopRL))
+ {
+ statusBar()->message(i18n("Configuration package saved successfully."), 5000);
+ }
+ else
+ {
+ kdDebug(3000) << "ERROR saving file" << endl;
+ }
+
+ file.close();
+
+ KBusyManager::self()->restore();
+}
+
+void KSVTopLevel::load ()
+{
+ static const QString& filter = ksv::nativeFileFilter();
+ QString filename = KFileDialog::getOpenFileName(0L, filter, this);
+
+ if (filename.isEmpty())
+ return;
+
+ QFile file(filename);
+ KBusyManager::self()->setBusy (true);
+
+ file.open (IO_ReadOnly | IO_Raw);
+ QDataStream s (&file);
+ QValueList<KSVData>* startLists = new QValueList<KSVData>[ksv::runlevelNumber];
+ QValueList<KSVData>* stopLists = new QValueList<KSVData>[ksv::runlevelNumber];
+
+ if (ksv::IO::loadSavedConfiguration (s, startLists, stopLists))
+ {
+ statusBar()->message(i18n("Configuration package loaded successfully."), 5000);
+ mView->mergeLoadedPackage (startLists, stopLists);
+ }
+ else
+ {
+ kdDebug (3000) << "ERROR loading file" << endl;
+ }
+
+ file.close();
+
+ delete[] startLists;
+ delete[] stopLists;
+
+ KBusyManager::self()->restore();
+}
+
+void KSVTopLevel::pushUndoAction (KSVAction* action)
+{
+ mRedoList->clear();
+ mUndoList->push (action);
+
+ setChanged(true);
+}
+
+#include "TopWidget.moc"