diff options
Diffstat (limited to 'ksysv/TopWidget.cpp')
-rw-r--r-- | ksysv/TopWidget.cpp | 1109 |
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" |