# kdeprint Library API Documentation

Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# kmlprmanager.cpp

    00001 /*
    00002  *  This file is part of the KDE libraries
    00003  *  Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be>
    00004  *
    00005  *  This library is free software; you can redistribute it and/or
    00006  *  modify it under the terms of the GNU Library General Public
    00007  *  License version 2 as published by the Free Software Foundation.
    00008  *
    00009  *  This library is distributed in the hope that it will be useful,
    00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00012  *  Library General Public License for more details.
    00013  *
    00014  *  You should have received a copy of the GNU Library General Public License
    00015  *  along with this library; see the file COPYING.LIB.  If not, write to
    00016  *  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00017  *  Boston, MA 02111-1307, USA.
    00018  **/
    00019
    00020 #include "kmlprmanager.h"
    00021 #include "printcapreader.h"
    00022 #include "printcapentry.h"
    00023 #include "lpchelper.h"
    00024 #include "matichandler.h"
    00025 #include "apshandler.h"
    00026 #include "lprngtoolhandler.h"
    00027 #include "lprsettings.h"
    00028 #include "driver.h"
    00029 #include "editentrydialog.h"
    00030
    00031 #include <qfileinfo.h>
    00032 #include <qptrlist.h>
    00033 #include <klocale.h>
    00034 #include <kstandarddirs.h>
    00035 #include <kdebug.h>
    00036 #include <kprinter.h>
    00037 #include <kprocess.h>
    00038 #include <kaction.h>
    00039 #include <kmessagebox.h>
    00040 #include <klibloader.h>
    00041
    00042 #include <stdlib.h>
    00043 #include <unistd.h>
    00044
    00045 KMLprManager::KMLprManager(QObject *parent, const char *name, const QStringList & /*args*/)
    00046 : KMManager(parent,name)
    00047 {
    00048     m_handlers.setAutoDelete(true);
    00049     m_handlerlist.setAutoDelete(false);
    00050     m_entries.setAutoDelete(true);
    00051
    00052     m_lpchelper = new LpcHelper(this);
    00053     m_currentprinter = 0;
    00054
    00055     setHasManagement(getuid() == 0);
    00056     setPrinterOperationMask(
    00057         KMManager::PrinterEnabling |
    00058         KMManager::PrinterConfigure |
    00059         KMManager::PrinterTesting |
    00060         KMManager::PrinterCreation |
    00061         KMManager::PrinterRemoval |
    00062         KMManager::PrinterTesting
    00063     );
    00064
    00065     initHandlers();
    00066 }
    00067
    00068 void KMLprManager::listPrinters()
    00069 {
    00070     QFileInfo   fi(LprSettings::self()->printcapFile());
    00071
    00072     if (m_lpchelper)
    00073         m_lpchelper->updateStates();
    00074
    00075     // update only if needed
    00076     if (!m_updtime.isValid() || m_updtime < fi.lastModified())
    00077     {
    00078         // cleanup previous entries
    00079         m_entries.clear();
    00080         // notify handlers
    00081         QPtrListIterator<LprHandler>    hit(m_handlerlist);
    00082         for (; hit.current(); ++hit)
    00083             hit.current()->reset();
    00084
    00085         // try to open the printcap file and parse it
    00086         PrintcapReader  reader;
    00087         QFile   f(fi.absFilePath());
    00088         PrintcapEntry   *entry;
    00089         if (f.exists() && f.open(IO_ReadOnly))
    00090         {
    00091             reader.setPrintcapFile(&f);
    00092             while ((entry = reader.nextEntry()) != NULL)
    00093             {
    00094                 QPtrListIterator<LprHandler>    it(m_handlerlist);
    00095                 for (; it.current(); ++it)
    00096                     if (it.current()->validate(entry))
    00097                     {
    00098                         KMPrinter   *prt = it.current()->createPrinter(entry);
    00099                         checkPrinterState(prt);
    00100                         prt->setOption("kde-lpr-handler", it.current()->name());
    00101                         addPrinter(prt);
    00102                         break;
    00103                     }
    00104                 m_entries.insert(entry->name, entry);
    00105             }
    00106         }
    00107
    00108         // save update time
    00109         m_updtime = fi.lastModified();
    00110     }
    00111     else
    00112     {
    00113         QPtrListIterator<KMPrinter> it(m_printers);
    00114         for (; it.current(); ++it)
    00115             if (!it.current()->isSpecial())
    00116             {
    00117                 it.current()->setDiscarded(false);
    00118                 checkPrinterState(it.current());
    00119             }
    00120     }
    00121 }
    00122
    00123 void KMLprManager::insertHandler(LprHandler *handler)
    00124 {
    00125     m_handlers.insert(handler->name(), handler);
    00126     m_handlerlist.append(handler);
    00127     kdDebug() << "Handler: " << handler->name() << endl;
    00128 }
    00129
    00130 void KMLprManager::initHandlers()
    00131 {
    00132     m_handlers.clear();
    00133     m_handlerlist.clear();
    00134
    00135     insertHandler(new MaticHandler(this));
    00136     insertHandler(new ApsHandler(this));
    00137     insertHandler(new LPRngToolHandler(this));
    00138
    00139     // now load external handlers
    00140     QStringList l = KGlobal::dirs()->findAllResources("data", "kdeprint/lpr/*.la");
    00141     for (QStringList::ConstIterator it=l.begin(); it!=l.end(); ++it)
    00142     {
    00143         KLibrary    *library = KLibLoader::self()->library(QFile::encodeName(*it));
    00144         if (library)
    00145         {
    00146             kdDebug() << "loading external handler from " << *it << endl;
    00147             LprHandler*(*func)(KMManager*) = (LprHandler*(*)(KMManager*))(library->symbol("create_handler"));
    00148             if (func)
    00149                 insertHandler(func(this));
    00150             else
    00151                 kdDebug() << "couldn't find the symbol 'create_handler'" << endl;
    00152         }
    00153     }
    00154
    00155     // default handler
    00156     insertHandler(new LprHandler("default", this));
    00157 }
    00158
    00159 LprHandler* KMLprManager::findHandler(KMPrinter *prt)
    00160 {
    00161     QString handlerstr(prt->option("kde-lpr-handler"));
    00162     LprHandler  *handler(0);
    00163     if (handlerstr.isEmpty() || (handler = m_handlers.find(handlerstr)) == NULL)
    00164     {
    00165         return NULL;
    00166     }
    00167     return handler;
    00168 }
    00169
    00170 PrintcapEntry* KMLprManager::findEntry(KMPrinter *prt)
    00171 {
    00172     PrintcapEntry   *entry = m_entries.find(prt->printerName());
    00173     if (!entry)
    00174     {
    00175         return NULL;
    00176     }
    00177     return entry;
    00178 }
    00179
    00180 bool KMLprManager::completePrinter(KMPrinter *prt)
    00181 {
    00182     LprHandler  *handler = findHandler(prt);
    00183     PrintcapEntry   *entry = findEntry(prt);
    00184     if (handler && entry)
    00185         return handler->completePrinter(prt, entry, false);
    00186     return false;
    00187 }
    00188
    00189 bool KMLprManager::completePrinterShort(KMPrinter *prt)
    00190 {
    00191     LprHandler  *handler = findHandler(prt);
    00192     PrintcapEntry   *entry = findEntry(prt);
    00193     if (!handler || !entry)
    00194         return false;
    00195
    00196     return handler->completePrinter(prt, entry, true);
    00197 }
    00198
    00199 void KMLprManager::checkPrinterState(KMPrinter *prt)
    00200 {
    00201     if (m_lpchelper)
    00202     {
    00203         KMPrinter::PrinterState st = m_lpchelper->state(prt);
    00204         prt->setState(st);
    00205         prt->setAcceptJobs(!(st & KMPrinter::Rejecting));
    00206     }
    00207     else
    00208     {
    00209         prt->setState(KMPrinter::Idle);
    00210         prt->setAcceptJobs(true);
    00211     }
    00212 }
    00213
    00214 DrMain* KMLprManager::loadPrinterDriver(KMPrinter *prt, bool config)
    00215 {
    00216     if (!prt)
    00217         return NULL;
    00218
    00219     LprHandler  *handler = findHandler(prt);
    00220     PrintcapEntry   *entry = findEntry(prt);
    00221     if (handler && entry)
    00222     {
    00223         DrMain  *driver = handler->loadDriver(prt, entry, config);
    00224         if (driver)
    00225             driver->set("handler", handler->name());
    00226         return driver;
    00227     }
    00228     return NULL;
    00229 }
    00230
    00231 DrMain* KMLprManager::loadFileDriver(const QString& filename)
    00232 {
    00233     int p = filename.find('/');
    00234     QString handler_str = (p != -1 ? filename.left(p) : QString::fromLatin1("default"));
    00235     LprHandler  *handler = m_handlers.find(handler_str);
    00236     if (handler)
    00237     {
    00238         DrMain  *driver = handler->loadDbDriver(filename);
    00239         if (driver)
    00240             driver->set("handler", handler->name());
    00241         return driver;
    00242     }
    00243     return NULL;
    00244 }
    00245
    00246 bool KMLprManager::enablePrinter(KMPrinter *prt, bool state)
    00247 {
    00248     QString msg;
    00249     if (!m_lpchelper->enable(prt, state, msg))
    00250     {
    00251         setErrorMsg(msg);
    00252         return false;
    00253     }
    00254     return true;
    00255 }
    00256
    00257 bool KMLprManager::startPrinter(KMPrinter *prt, bool state)
    00258 {
    00259     QString msg;
    00260     if (!m_lpchelper->start(prt, state, msg))
    00261     {
    00262         setErrorMsg(msg);
    00263         return false;
    00264     }
    00265     return true;
    00266 }
    00267
    00268 bool KMLprManager::savePrinterDriver(KMPrinter *prt, DrMain *driver)
    00269 {
    00270     LprHandler  *handler = findHandler(prt);
    00271     PrintcapEntry   *entry = findEntry(prt);
    00272     if (handler && entry)
    00273     {
    00274         bool    mustSave(false);
    00275         if (handler->savePrinterDriver(prt, entry, driver, &mustSave))
    00276         {
    00277             if (mustSave)
    00278                 return savePrintcapFile();
    00279             return true;
    00280         }
    00281     }
    00282     return false;
    00283 }
    00284
    00285 bool KMLprManager::savePrintcapFile()
    00286 {
    00287     if (!LprSettings::self()->isLocalPrintcap())
    00288     {
    00289         setErrorMsg(i18n("The printcap file is a remote file (NIS). It cannot be written."));
    00290         return false;
    00291     }
    00292     QFile   f(LprSettings::self()->printcapFile());
    00293     if (f.open(IO_WriteOnly))
    00294     {
    00295         QTextStream t(&f);
    00296         QDictIterator<PrintcapEntry>    it(m_entries);
    00297         for (; it.current(); ++it)
    00298         {
    00299             it.current()->writeEntry(t);
    00300         }
    00301         return true;
    00302     }
    00303     else
    00304     {
    00305         setErrorMsg(i18n("Unable to save printcap file. Check that "
    00306                          "you have write permissions for that file."));
    00307         return false;
    00308     }
    00309 }
    00310
    00311 bool KMLprManager::createPrinter(KMPrinter *prt)
    00312 {
    00313     // remove existing printcap entry
    00314     PrintcapEntry   *oldEntry = m_entries.find(prt->printerName());
    00315
    00316     // look for the handler and re-create entry
    00317     LprHandler  *handler(0);
    00318     // To look for the handler, either we base ourselves
    00319     // on the driver (1: new printer, 2: modifying driver)
    00320     // or we use the handler of the existing printer
    00321     // (modifying something else, handler stays the same)
    00322     if (prt->driver())
    00323         handler = m_handlers.find(prt->driver()->get("handler"));
    00324     else if (oldEntry)
    00325         handler = findHandler(prt);
    00326     else
    00327         handler = m_handlers.find("default");
    00328     if (!handler)
    00329     {
    00330         setErrorMsg(i18n("Internal error: no handler defined."));
    00331         return false;
    00332     }
    00333     prt->setOption("kde-lpr-handler", handler->name());
    00334
    00335     // we reload the driver if the printer object doesn't have one
    00336     // and there's an old entry (sometimes needed to keep the backend
    00337     // like in Foomatic)
    00338     if (!prt->driver() && oldEntry)
    00339         prt->setDriver(handler->loadDriver(prt, oldEntry, true));
    00340
    00341     QString sd = LprSettings::self()->baseSpoolDir();
    00342     if (sd.isEmpty())
    00343     {
    00344         setErrorMsg(i18n("Couldn't determine spool directory. See options dialog."));
    00345         return false;
    00346     }
    00347     sd.append("/").append(prt->printerName());
    00348     if (!KStandardDirs::makeDir(sd, 0755))
    00349     {
    00350         setErrorMsg(i18n("Unable to create the spool directory %1. Check that you "
    00351                          "have the required permissions for that operation.").arg(sd));
    00352         return false;
    00353     }
    00354     PrintcapEntry   *entry = handler->createEntry(prt);
    00355     if (!entry)
    00356         return false;   // error should be set in the handler
    00357     // old entry can be removed now
    00358     m_entries.remove(prt->printerName());
    00359     entry->name = prt->printerName();
    00360     entry->addField("sh", Field::Boolean);
    00361     entry->addField("mx", Field::Integer, "0");
    00362     entry->addField("sd", Field::String, sd);
    00363     if (!prt->option("kde-aliases").isEmpty())
    00364         entry->aliases += QStringList::split("|", prt->option("kde-aliases"), false);
    00365
    00366     // insert the new entry and save printcap file
    00367     m_entries.insert(prt->printerName(), entry);
    00368     bool    result = savePrintcapFile();
    00369     if (result)
    00370     {
    00371         if (prt->driver())
    00372         {
    00373             result = handler->savePrinterDriver(prt, entry, prt->driver());
    00374         }
    00375
    00376         // in case of LPRng, we need to tell the daemon about new printer
    00377         if (LprSettings::self()->mode() == LprSettings::LPRng)
    00378         {
    00379             QString msg;
    00380             if (!m_lpchelper->restart(msg))
    00381             {
    00382                 setErrorMsg(i18n("The printer has been created but the print daemon "
    00383                                  "could not be restarted. %1").arg(msg));
    00384                 return false;
    00385             }
    00386         }
    00387     }
    00388     return result;
    00389 }
    00390
    00391 bool KMLprManager::removePrinter(KMPrinter *prt)
    00392 {
    00393     LprHandler  *handler = findHandler(prt);
    00394     PrintcapEntry   *entry = findEntry(prt);
    00395     if (handler && entry)
    00396     {
    00397         if (handler->removePrinter(prt, entry))
    00398         {
    00399             QString sd = entry->field("sd");
    00400             // first try to save the printcap file, and if
    00401             // successful, remove the spool directory
    00402             m_entries.take(prt->printerName());
    00403             bool    status = savePrintcapFile();
    00404             if (status)
    00405             {
    00406                 // printcap file saved, entry can be deleted now
    00407                 delete entry;
    00408                 status =  (::system(QFile::encodeName("rm -rf " + KProcess::quote(sd))) == 0);
    00409                 if (!status)
    00410                     setErrorMsg(i18n("Unable to remove spool directory %1. "
    00411                                      "Check that you have write permissions "
    00412                                      "for that directory.").arg(sd));
    00413                 return status;
    00414             }
    00415             else
    00416                 // push back the non-removed entry
    00417                 m_entries.insert(prt->printerName(), entry);
    00418         }
    00419     }
    00420     return false;
    00421 }
    00422
    00423 QString KMLprManager::driverDbCreationProgram()
    00424 {
    00425     return QString::fromLatin1("make_driver_db_lpr");
    00426 }
    00427
    00428 QString KMLprManager::driverDirectory()
    00429 {
    00430     QPtrListIterator<LprHandler>    it(m_handlerlist);
    00431     QString dbDirs;
    00432     for (; it.current(); ++it)
    00433     {
    00434         QString dir = it.current()->driverDirectory();
    00435         if (!dir.isEmpty())
    00436             dbDirs.append(dir).append(":");
    00437     }
    00438     if (!dbDirs.isEmpty())
    00439         dbDirs.truncate(dbDirs.length()-1);
    00440     return dbDirs;
    00441 }
    00442
    00443 QString KMLprManager::printOptions(KPrinter *prt)
    00444 {
    00445     KMPrinter   *mprt = findPrinter(prt->printerName());
    00446     QString opts;
    00447     if (mprt)
    00448     {
    00449         LprHandler  *handler = findHandler(mprt);
    00450         if (handler)
    00451             return handler->printOptions(prt);
    00452     }
    00453     return QString::null;
    00454 }
    00455
    00456 void KMLprManager::createPluginActions(KActionCollection *coll)
    00457 {
    00458     KAction *act = new KAction(i18n("&Edit printcap Entry..."), "kdeprint_report", 0, this, SLOT(slotEditPrintcap()), coll, "plugin_editprintcap");
    00459     act->setGroup("plugin");
    00460 }
    00461
    00462 void KMLprManager::validatePluginActions(KActionCollection *coll, KMPrinter *prt)
    00463 {
    00464     m_currentprinter = prt;
    00465     // FIXME: disabled until completion
    00466     coll->action("plugin_editprintcap")->setEnabled(0 && hasManagement() && prt && !prt->isSpecial());
    00467 }
    00468
    00469 void KMLprManager::slotEditPrintcap()
    00470 {
    00471     if (!m_currentprinter ||
    00472         KMessageBox::warningYesNo(NULL,
    00473         i18n("Editing a printcap entry manually should only be "
    00474          "done by confirmed system administrator. This may "
    00475          "prevent your printer from working. Do you want to "
    00476          "continue?"), QString::null, QString::null, QString::null,
    00477         "editPrintcap") == KMessageBox::No)
    00478         return;
    00479
    00480     PrintcapEntry   *entry = findEntry(m_currentprinter);
    00481     EditEntryDialog dlg(entry, NULL);
    00482     if (dlg.exec())
    00483     {
    00484     }
    00485 }
    00486
    00487 QString KMLprManager::stateInformation()
    00488 {
    00489     return i18n("Spooler type: %1").arg(LprSettings::self()->mode() == LprSettings::LPR ? "LPR (BSD compatible)" : "LPRng");
    00490 }
    00491
    00492 #include "kmlprmanager.moc"

This file is part of the documentation for kdeprint Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:31:02 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003