kxmlcommand.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., 51 Franklin Street, Fifth Floor,
00017  *  Boston, MA 02110-1301, USA.
00018  **/
00019 
00020 #include "kxmlcommand.h"
00021 #include "driver.h"
00022 #include "kmfactory.h"
00023 #include "kdeprintcheck.h"
00024 #include "driverview.h"
00025 
00026 #include <qfile.h>
00027 #include <qregexp.h>
00028 #include <qdir.h>
00029 #include <qinputdialog.h>
00030 #include <qmap.h>
00031 #include <qvaluelist.h>
00032 #include <kstandarddirs.h>
00033 #include <klocale.h>
00034 #include <ksimpleconfig.h>
00035 #include <kdialogbase.h>
00036 #include <kdebug.h>
00037 #include <kprocess.h>
00038 #include <klibloader.h>
00039 #include <kmessagebox.h>
00040 
00041 static void setOptionText(DrBase *opt, const QString& s)
00042 {
00043     if (s.isEmpty())
00044         opt->set("text", opt->name());
00045     else
00046         opt->set("text", i18n(s.utf8()));
00047 }
00048 
00049 class KXmlCommand::KXmlCommandPrivate
00050 {
00051 public:
00052     QString m_name;
00053     QString m_command;
00054     DrMain  *m_driver;
00055     struct
00056     {
00057         QString m_format[2];    // 0 -> file, 1 -> pipe
00058     }   m_io[2];                // 0 -> input, 1 -> output
00059     QString m_description;
00060     QString m_outputMime;
00061     QStringList m_inputMime;
00062     QStringList m_requirements;
00063     bool    m_loaded[2];    // 0 -> Desktop, 1 -> XML
00064     QString m_comment;
00065 };
00066 
00067 KXmlCommand::KXmlCommand(const QString& xmlId)
00068 : QObject(KXmlCommandManager::self(), "XmlCommand")
00069 {
00070     init();
00071     d->m_name = xmlId;
00072 }
00073 
00074 KXmlCommand::~KXmlCommand()
00075 {
00076     //kdDebug(500) << "deleting driver" << endl;
00077     delete d->m_driver;
00078     //kdDebug(500) << "deleting private data" << endl;
00079     delete d;
00080     //kdDebug(500) << "finished" << endl;
00081 }
00082 
00083 void KXmlCommand::init()
00084 {
00085     d = new KXmlCommandPrivate;
00086     d->m_driver = 0;
00087     d->m_loaded[0] = d->m_loaded[1] = false;
00088 }
00089 
00090 QString KXmlCommand::name() const
00091 { return d->m_name; }
00092 
00093 void KXmlCommand::setName(const QString& s)
00094 { d->m_name = s; }
00095 
00096 QString KXmlCommand::command()
00097 {
00098     check(true);
00099     return d->m_command;
00100 }
00101 
00102 void KXmlCommand::setCommand(const QString& s)
00103 {
00104     d->m_command = s;
00105 }
00106 
00107 DrMain* KXmlCommand::driver()
00108 {
00109     check(true);
00110     return d->m_driver;
00111 }
00112 
00113 DrMain* KXmlCommand::takeDriver()
00114 {
00115     check(true);
00116     DrMain  *dr = d->m_driver;
00117     d->m_driver = 0;
00118     d->m_loaded[1] = false;
00119     return dr;
00120 }
00121 
00122 void KXmlCommand::setDriver(DrMain *driver)
00123 {
00124     delete d->m_driver;
00125     d->m_driver = driver;
00126 }
00127 
00128 QString KXmlCommand::io(bool io_input, bool io_pipe)
00129 {
00130     check(true);
00131     return d->m_io[(io_input?0:1)].m_format[(io_pipe?1:0)];
00132 }
00133 
00134 void KXmlCommand::setIo(const QString& s, bool io_input, bool io_pipe)
00135 {
00136     d->m_io[(io_input?0:1)].m_format[(io_pipe?1:0)] = s;
00137 }
00138 
00139 QString KXmlCommand::description()
00140 {
00141     check();
00142     return d->m_description;
00143 }
00144 
00145 void KXmlCommand::setDescription(const QString& s)
00146 {
00147     d->m_description = s;
00148 }
00149 
00150 QString KXmlCommand::mimeType()
00151 {
00152     check();
00153     return d->m_outputMime;
00154 }
00155 
00156 void KXmlCommand::setMimeType(const QString& s)
00157 {
00158     d->m_outputMime = s;
00159 }
00160 
00161 bool KXmlCommand::acceptMimeType(const QString& s)
00162 {
00163     check();
00164     return (d->m_inputMime.find(s) != d->m_inputMime.end());
00165 }
00166 
00167 QStringList KXmlCommand::inputMimeTypes()
00168 {
00169     check();
00170     return d->m_inputMime;
00171 }
00172 
00173 void KXmlCommand::setInputMimeTypes(const QStringList& l)
00174 {
00175     d->m_inputMime = l;
00176 }
00177 
00178 QStringList KXmlCommand::requirements()
00179 {
00180     check();
00181     return d->m_requirements;
00182 }
00183 
00184 void KXmlCommand::setRequirements(const QStringList& l)
00185 {
00186     d->m_requirements = l;
00187 }
00188 
00189 QString KXmlCommand::comment()
00190 {
00191     check();
00192     return d->m_comment;
00193 }
00194 
00195 void KXmlCommand::setComment( const QString& s )
00196 {
00197     d->m_comment = s;
00198 }
00199 
00200 bool KXmlCommand::isValid()
00201 {
00202     return (!locate("data", "kdeprint/filters/"+name()+".desktop").isEmpty());
00203 }
00204 
00205 void KXmlCommand::check(bool use_xml)
00206 {
00207     if (!d->m_loaded[0])
00208     {
00209         loadDesktop();
00210         d->m_loaded[0] = true;
00211     }
00212     if (use_xml && !d->m_loaded[1])
00213     {
00214         loadXml();
00215         d->m_loaded[1] = true;
00216     }
00217 }
00218 
00219 void KXmlCommand::loadDesktop()
00220 {
00221     KSimpleConfig   conf(locate("data", "kdeprint/filters/"+name()+".desktop"));
00222     conf.setGroup("KDE Print Filter Entry");
00223     d->m_description = conf.readEntry("Comment");
00224     d->m_outputMime = conf.readEntry("MimeTypeOut");
00225     d->m_inputMime = conf.readListEntry("MimeTypeIn");
00226     d->m_requirements = conf.readListEntry("Require");
00227     d->m_comment = conf.readEntry( "Description" );
00228 }
00229 
00230 void KXmlCommand::saveDesktop()
00231 {
00232     KSimpleConfig   conf(locateLocal("data", "kdeprint/filters/"+name()+".desktop"));
00233     conf.setGroup("KDE Print Filter Entry");
00234     conf.writeEntry("Comment", d->m_description);
00235     conf.writeEntry("MimeTypeIn", d->m_inputMime);
00236     conf.writeEntry("MimeTypeOut", d->m_outputMime);
00237     conf.writeEntry("Require", d->m_requirements);
00238     conf.writeEntry( "Description", d->m_comment );
00239 }
00240 
00241 void KXmlCommand::loadXml()
00242 {
00243     QFile   f(locate("data", "kdeprint/filters/"+name()+".xml"));
00244     QDomDocument    doc;
00245     if (f.open(IO_ReadOnly) && doc.setContent(&f) && doc.documentElement().tagName() == "kprintfilter")
00246     {
00247         QDomElement e, docElem = doc.documentElement();
00248         d->m_name = docElem.attribute("name");
00249 
00250         // command
00251         e = docElem.namedItem("filtercommand").toElement();
00252         if (!e.isNull())
00253             d->m_command = e.attribute("data");
00254 
00255         // arguments
00256         e = docElem.namedItem("filterargs").toElement();
00257         if (!e.isNull())
00258         {
00259             d->m_driver = new DrMain;
00260             d->m_driver->setName(d->m_name);
00261             parseGroup(e, d->m_driver);
00262             setOptionText(d->m_driver, d->m_description);
00263         }
00264 
00265         // input/output
00266         e = docElem.namedItem("filterinput").toElement();
00267         if (!e.isNull())
00268             parseIO(e, 0);
00269         e = docElem.namedItem("filteroutput").toElement();
00270         if (!e.isNull())
00271             parseIO(e, 1);
00272     }
00273 }
00274 
00275 void KXmlCommand::parseIO(const QDomElement& e, int n)
00276 {
00277     QDomElement elem = e.firstChild().toElement();
00278     while (!elem.isNull())
00279     {
00280         if (elem.tagName() == "filterarg")
00281         {
00282             int format = (elem.attribute("name") == "file" ? 0 : 1);
00283             d->m_io[n].m_format[format] = elem.attribute("format");
00284         }
00285         elem = elem.nextSibling().toElement();
00286     }
00287 }
00288 
00289 DrGroup* KXmlCommand::parseGroup(const QDomElement& e, DrGroup *grp)
00290 {
00291     if (!grp)
00292         grp = new DrGroup;
00293     grp->setName(e.attribute("name"));
00294     setOptionText(grp, e.attribute("description"));
00295 
00296     QDomElement elem = e.firstChild().toElement();
00297     while (!elem.isNull())
00298     {
00299         if (elem.tagName() == "filterarg")
00300         {
00301             DrBase  *opt = parseArgument(elem);
00302             if (opt)
00303                 grp->addOption(opt);
00304         }
00305         else if (elem.tagName() == "filtergroup")
00306         {
00307             DrGroup *group = parseGroup(elem, 0);
00308             if (group)
00309                 grp->addGroup(group);
00310         }
00311         elem = elem.nextSibling().toElement();
00312     }
00313 
00314     return grp;
00315 }
00316 
00317 DrBase* KXmlCommand::parseArgument(const QDomElement& e)
00318 {
00319     DrBase  *opt(0);
00320     QString type = e.attribute("type");
00321 
00322     if (type == "int" || type == "float")
00323     {
00324         if (type == "int")
00325             opt = new DrIntegerOption;
00326         else
00327             opt = new DrFloatOption;
00328         opt->set("minval", e.attribute("min"));
00329         opt->set("maxval", e.attribute("max"));
00330     }
00331     else if (type == "string")
00332         opt = new DrStringOption;
00333     else if (type == "list" || type == "bool")
00334     {
00335         if (type == "list")
00336             opt = new DrListOption;
00337         else
00338             opt = new DrBooleanOption;
00339         DrListOption    *lopt = static_cast<DrListOption*>(opt);
00340         QDomElement elem = e.firstChild().toElement();
00341         while (!elem.isNull())
00342         {
00343             if (elem.tagName() == "value")
00344             {
00345                 DrBase  *choice = new DrBase;
00346                 choice->setName(elem.attribute("name"));
00347                 setOptionText(choice, elem.attribute("description"));
00348                 lopt->addChoice(choice);
00349             }
00350             elem = elem.nextSibling().toElement();
00351         }
00352     }
00353     else
00354         return 0;
00355 
00356     opt->setName("_kde-" + d->m_name + "-" + e.attribute("name"));
00357     setOptionText(opt, e.attribute("description"));
00358     opt->set("format", e.attribute("format"));
00359     opt->set("default", e.attribute("default"));
00360     opt->set( "persistent", e.attribute( "persistent" ) );
00361     opt->setValueText(opt->get("default"));
00362 
00363     return opt;
00364 }
00365 
00366 QString KXmlCommand::buildCommand(const QMap<QString,QString>& opts, bool pipein, bool pipeout)
00367 {
00368     check(true);
00369 
00370     QString     str, cmd = d->m_command;
00371     QString re( "%value" ), quotedRe( "'%value'" );
00372 
00373     if (d->m_driver)
00374     {
00375         QMap<QString,QString>   fopts;
00376 
00377         d->m_driver->setOptions(opts);
00378         d->m_driver->getOptions(fopts, false);
00379         for (QMap<QString,QString>::ConstIterator it=fopts.begin(); it!=fopts.end(); ++it)
00380         {
00381             DrBase  *dopt = d->m_driver->findOption(it.key());
00382             if (dopt)
00383             {
00384                 QString format = dopt->get("format");
00385                 QString value = dopt->valueText();
00386                 if ( format.find( quotedRe ) != -1 )
00387                 {
00388                     if ( ( value.right( 1 ) == "'" && value.left( 1 ) == "'" )  ||
00389                          ( value.right( 1 ) == "\"" && value.left( 1 ) == "\"" ) )
00390                         format.replace( quotedRe, value );
00391                     else
00392                         format.replace( re, value );
00393                 }
00394                 else if ( value == "" ) 
00395                 {
00396                     format.replace( re, "" );
00397                 }
00398                 else    
00399                 {
00400                     format.replace( re, KProcess::quote( value ) );
00401                 }
00402                 str.append(format).append(" ");
00403             }
00404         }
00405         cmd.replace("%filterargs", str);
00406     }
00407 
00408     cmd.replace("%filterinput", d->m_io[0].m_format[(pipein?1:0)]);
00409     cmd.replace("%filteroutput", d->m_io[1].m_format[(pipeout?1:0)]);
00410 
00411     return cmd;
00412 }
00413 
00414 void KXmlCommand::setOptions(const QMap<QString,QString>& opts)
00415 {
00416     if (opts.count() == 0)
00417         return;
00418     // force loading the driver if needed
00419     if (driver())
00420         d->m_driver->setOptions(opts);
00421 }
00422 
00423 void KXmlCommand::getOptions(QMap<QString,QString>& opts, bool incldef)
00424 {
00425     // force loading the driver
00426     if (driver())
00427         d->m_driver->getOptions(opts, incldef);
00428 }
00429 
00430 void KXmlCommand::saveXml()
00431 {
00432     QFile   f(locateLocal("data", "kdeprint/filters/"+name()+".xml"));
00433     if (!f.open(IO_WriteOnly))
00434         return;
00435 
00436     QDomDocument    doc("kprintfilter");
00437     QDomElement root = doc.createElement("kprintfilter"), elem;
00438 
00439     root.setAttribute("name", d->m_name);
00440     doc.appendChild(root);
00441 
00442     // command
00443     elem = doc.createElement("filtercommand");
00444     elem.setAttribute("data", d->m_command);
00445     root.appendChild(elem);
00446 
00447     // options
00448     if (d->m_driver)
00449     {
00450         elem = createGroup(doc, d->m_driver);
00451         elem.setTagName("filterargs");
00452         root.appendChild(elem);
00453     }
00454 
00455     // IO
00456     if (!(elem=createIO(doc, 0, "filterinput")).isNull())
00457         root.appendChild(elem);
00458     if (!(elem=createIO(doc, 1, "filteroutput")).isNull())
00459         root.appendChild(elem);
00460 
00461     // save to file (and close it)
00462     QTextStream t(&f);
00463     t << doc.toString();
00464     f.close();
00465 }
00466 
00467 QDomElement KXmlCommand::createIO(QDomDocument& doc, int n, const QString& tag)
00468 {
00469     QDomElement elem = doc.createElement(tag);
00470     if (d->m_command.find("%"+tag) != -1)
00471     {
00472         for (int i=0; i<2; i++)
00473         {
00474             QDomElement io = doc.createElement("filterarg");
00475             io.setAttribute("name", (i ? "pipe" : "file"));
00476             io.setAttribute("format", d->m_io[n].m_format[i]);
00477             elem.appendChild(io);
00478         }
00479     }
00480 
00481     return elem;
00482 }
00483 
00484 QDomElement KXmlCommand::createGroup(QDomDocument& doc, DrGroup *group)
00485 {
00486     QDomElement elem = doc.createElement("filtergroup");
00487     elem.setAttribute("name", group->name());
00488     elem.setAttribute("description", group->get("text"));
00489 
00490     QPtrListIterator<DrGroup>   git(group->groups());
00491     for (; git.current(); ++git)
00492         elem.appendChild(createGroup(doc, git.current()));
00493 
00494     QPtrListIterator<DrBase>    oit(group->options());
00495     for (; oit.current(); ++oit)
00496         elem.appendChild(createElement(doc, oit.current()));
00497 
00498     return elem;
00499 }
00500 
00501 QDomElement KXmlCommand::createElement(QDomDocument& doc, DrBase *opt)
00502 {
00503     QDomElement elem = doc.createElement("filterarg");
00504     QString elemName = opt->name();
00505     if (elemName.startsWith("_kde-"))
00506         elemName.replace(0, name().length()+6, "");
00507     elem.setAttribute("name", elemName);
00508     elem.setAttribute("format", opt->get("format"));
00509     elem.setAttribute("description", opt->get("text"));
00510     elem.setAttribute("default", opt->get("default"));
00511     elem.setAttribute( "persistent", opt->get( "persistent" ) == "1" ? "1" : "0");
00512 
00513     switch (opt->type())
00514     {
00515         case DrBase::String:
00516             elem.setAttribute("type", "string");
00517             break;
00518         case DrBase::Integer:
00519         case DrBase::Float:
00520             elem.setAttribute("type", (opt->type() == DrBase::Integer ? "int" : "float"));
00521             elem.setAttribute("min", opt->get("minval"));
00522             elem.setAttribute("max", opt->get("maxval"));
00523             break;
00524         case DrBase::Boolean:
00525         case DrBase::List:
00526             elem.setAttribute("type", (opt->type() == DrBase::List ? "list" : "bool"));
00527             {
00528                 QPtrListIterator<DrBase>    it(*(static_cast<DrListOption*>(opt)->choices()));
00529                 for (; it.current(); ++it)
00530                 {
00531                     QDomElement chElem = doc.createElement("value");
00532                     chElem.setAttribute("name", it.current()->name());
00533                     chElem.setAttribute("description", it.current()->get("text"));
00534                     elem.appendChild(chElem);
00535                 }
00536             }
00537             break;
00538         default:
00539             break;
00540     }
00541 
00542     return elem;
00543 }
00544 
00545 //---------------------------------------------------------------------------------------------------
00546 
00547 class KXmlCommandManager::KXmlCommandManagerPrivate
00548 {
00549 public:
00550     QStringList m_cmdlist;
00551     QMap<QString, QValueList<KXmlCommand*> >    m_mimemap;
00552     QMap<QString, KXmlCommand*> m_cmdmap;
00553 };
00554 
00555 KXmlCommandManager* KXmlCommandManager::m_self = 0;
00556 
00557 KXmlCommandManager* KXmlCommandManager::self()
00558 {
00559     if (!m_self)
00560     {
00561         m_self = new KXmlCommandManager;
00562         Q_CHECK_PTR(m_self);
00563     }
00564     return m_self;
00565 }
00566 
00567 KXmlCommandManager::KXmlCommandManager()
00568 : QObject(KMFactory::self(), "XmlCommandManager")
00569 {
00570     d = new KXmlCommandManagerPrivate;
00571 }
00572 
00573 KXmlCommandManager::~KXmlCommandManager()
00574 {
00575     cleanUp();
00576     delete d;
00577 }
00578 
00579 KXmlCommand* KXmlCommandManager::loadCommand(const QString& xmlId, bool check)
00580 {
00581     if (check)
00582     {
00583         QString desktopFile = locate("data", "kdeprint/filters/"+xmlId+".desktop");
00584         if (desktopFile.isEmpty())
00585             return 0;
00586     }
00587     return new KXmlCommand(xmlId);
00588 }
00589 
00590 void KXmlCommandManager::saveCommand(KXmlCommand *xmlCmd)
00591 {
00592     xmlCmd->saveDesktop();
00593     xmlCmd->saveXml();
00594 
00595     cleanUp();
00596 }
00597 
00598 void KXmlCommandManager::cleanUp()
00599 {
00600     for (QMap<QString, KXmlCommand*>::ConstIterator it=d->m_cmdmap.begin(); it!=d->m_cmdmap.end(); ++it)
00601         delete (*it);
00602     d->m_cmdmap.clear();
00603     d->m_mimemap.clear();
00604     d->m_cmdlist.clear();
00605 }
00606 
00607 void KXmlCommandManager::preload()
00608 {
00609     if (d->m_cmdmap.count() == 0)
00610     {
00611         commandList();
00612         for (QStringList::Iterator it=d->m_cmdlist.begin(); it!=d->m_cmdlist.end(); ++it)
00613         {
00614             KXmlCommand *xmlCmd = loadCommand(*it);
00615             if (!xmlCmd) continue; // Error!
00616 
00617             QStringList inputMime = xmlCmd->inputMimeTypes();
00618             for (QStringList::ConstIterator mime=inputMime.begin(); mime!=inputMime.end(); ++mime)
00619             {
00620                 d->m_mimemap[*mime].append(xmlCmd);
00621                 d->m_cmdmap[*it] = xmlCmd;
00622             }
00623         }
00624     }
00625 }
00626 
00627 QStringList KXmlCommandManager::commandList()
00628 {
00629     if (d->m_cmdlist.isEmpty())
00630     {
00631         QStringList dirs = KGlobal::dirs()->findDirs("data", "kdeprint/filters/");
00632 
00633         for (QStringList::ConstIterator it=dirs.begin(); it!=dirs.end(); ++it)
00634         {
00635             QStringList list = QDir(*it).entryList("*.desktop", QDir::Files, QDir::Unsorted);
00636             for (QStringList::ConstIterator it2=list.begin(); it2!=list.end(); ++it2)
00637             {
00638                 QString cmdName = (*it2).left((*it2).length()-8);
00639                 if (d->m_cmdlist.find(cmdName) == d->m_cmdlist.end())
00640                     d->m_cmdlist.append(cmdName);
00641             }
00642         }
00643 
00644         d->m_cmdlist.sort();
00645     }
00646 
00647     return d->m_cmdlist;
00648 }
00649 
00650 QStringList KXmlCommandManager::commandListWithDescription()
00651 {
00652     preload();
00653     QStringList l;
00654     for (QMap<QString,KXmlCommand*>::ConstIterator it=d->m_cmdmap.begin(); it!=d->m_cmdmap.end(); ++it)
00655         l << (*it)->name() << (*it)->description();
00656 
00657     return l;
00658 }
00659 
00660 QString KXmlCommandManager::selectCommand(QWidget *parent)
00661 {
00662     KLibrary *lib = KLibLoader::self()->library( "libkdeprint_management_module" );
00663     if ( !lib )
00664     {
00665         KMessageBox::error( parent, i18n( "Unable to load KDE print management library: %1" ).arg( KLibLoader::self()->lastErrorMessage() ) );
00666         return QString::null;
00667     }
00668     else
00669     {
00670         QString ( *func )( QWidget* ) = ( QString( * )( QWidget* ) )lib->symbol( "select_command" );
00671         if ( !func )
00672         {
00673             KMessageBox::error( parent, i18n( "Unable to find wizard object in management library." ) );
00674             return QString::null;
00675         }
00676         else
00677             return func( parent );
00678     }
00679 }
00680 
00681 KXmlCommand* KXmlCommandManager::command(const QString& xmlId) const
00682 {
00683     return (d->m_cmdmap.contains(xmlId) ? d->m_cmdmap[xmlId] : 0);
00684 }
00685 
00686 int KXmlCommandManager::insertCommand(QStringList& list, const QString& filtername, bool defaultToStart)
00687 {
00688     preload();
00689 
00690     int pos(0);
00691     KXmlCommand *f1 = command(filtername), *f2 = 0;
00692     if (f1 && f1->inputMimeTypes().count() > 0)
00693     {
00694         QString mimetype = f1->inputMimeTypes()[0];
00695         for (QStringList::Iterator it=list.begin(); it!=list.end(); ++it, pos++)
00696         {
00697             f2 = command(*it);
00698             if (!f2)
00699                 return -1; // Shouldn't happen
00700 
00701             if (f2->acceptMimeType(f1->mimeType()) && f1->acceptMimeType(mimetype))
00702             {
00703                 list.insert(it, filtername);
00704                 break;
00705             }
00706             else
00707             {
00708                 mimetype = f2->mimeType();
00709                 f2 = 0;
00710             }
00711         }
00712         if (pos == (int)(list.count()))
00713         {
00714             if (list.count() == 0 || f1->acceptMimeType(mimetype))
00715                 list.append(filtername);
00716             else if (defaultToStart)
00717             {
00718                 pos = 0;
00719                 list.prepend(filtername);
00720             }
00721             else
00722                 pos = -1;
00723         }
00724     }
00725     return pos;
00726 }
00727 
00728 QStringList KXmlCommandManager::autoConvert(const QString& mimesrc, const QString& mimedest)
00729 {
00730     QStringList chain;
00731     uint        score(0);
00732 
00733     preload();
00734 
00735     if (d->m_mimemap.contains(mimesrc))
00736     {
00737         const QValueList<KXmlCommand*>  l = d->m_mimemap[mimesrc];
00738         for (QValueList<KXmlCommand*>::ConstIterator it=l.begin(); it!=l.end(); ++it)
00739         {
00740             // check filter availability
00741             if (!KdeprintChecker::check((*it)->requirements()))
00742                 continue;
00743 
00744             // direct filter: shortest path => return immediately
00745             if ((*it)->mimeType() == mimedest)
00746             {
00747                 chain = QStringList((*it)->name());
00748                 break;
00749             }
00750             // non direct filter: find the shortest way between
00751             // its output and mimedest (do not consider cyling filters)
00752             else if ((*it)->mimeType() != mimesrc)
00753             {
00754                 QStringList subchain = autoConvert((*it)->mimeType(), mimedest);
00755                 // If chain length is 0, then there's no possible filter between those 2
00756                 // mime types. Just discard it. If the subchain contains also the current
00757                 // considered filter, then discard it: it denotes of a cycle in filter
00758                 // chain.
00759                 if (subchain.count() > 0 && subchain.findIndex((*it)->name()) == -1)
00760                 {
00761                     subchain.prepend((*it)->name());
00762                     if (subchain.count() < score || score == 0)
00763                     {
00764                         chain = subchain;
00765                         score = subchain.count();
00766                     }
00767                 }
00768             }
00769         }
00770     }
00771     // At this point, either we have the shortest path, or empty
00772     // list if nothing could be found
00773     return chain;
00774 }
00775 
00776 bool KXmlCommandManager::checkCommand(const QString& xmlId, int inputCheck, int outputCheck, QString *msg)
00777 {
00778     KXmlCommand *xmlCmd = command(xmlId);
00779     QString errmsg;
00780     bool    needDestroy(false);
00781     //kdDebug(500) << "checking command: " << xmlId << " (" << (xmlCmd != NULL) << ")" << endl;
00782     if (!xmlCmd)
00783     {
00784         xmlCmd = loadCommand(xmlId, true);
00785         needDestroy = (xmlCmd != 0);
00786     }
00787 
00788     bool    status(true);
00789     if (xmlCmd)
00790     {
00791         status = (xmlCmd->isValid() && KdeprintChecker::check(xmlCmd->requirements()));
00792         if (!status)
00793             errmsg = i18n("One of the command object's requirements is not met.");
00794     }
00795     QString cmd = (xmlCmd ? xmlCmd->command() : xmlId);
00796     if (status && !cmd.isEmpty() && (inputCheck > None || outputCheck > None))
00797     {
00798         if (inputCheck > None && (cmd.find("%in") == -1 || inputCheck == Advanced) && cmd.find("%filterinput") == -1)
00799         {
00800             status = false;
00801             errmsg = i18n("The command does not contain the required tag %1.").arg(inputCheck == Advanced ? "%filterinput" : "{%in,%filterinput}");
00802         }
00803         if (status && outputCheck > None && (cmd.find("%out") == -1 || outputCheck == Advanced) && cmd.find("filteroutput") == -1)
00804         {
00805             status = false;
00806             errmsg = i18n("The command does not contain the required tag %1.").arg(outputCheck == Advanced ? "%filteroutput" : "{%out,%filteroutput}");
00807         }
00808     }
00809 
00810     if (needDestroy)
00811         delete xmlCmd;
00812 
00813     if (msg)
00814         *msg = errmsg;
00815 
00816     return status;
00817 }
00818 
00819 bool KXmlCommandManager::configure(KXmlCommand *xmlCmd, QWidget *parent)
00820 {
00821     if (xmlCmd->driver())
00822     {
00823         KDialogBase dlg(parent, 0, true, xmlCmd->description(), KDialogBase::Ok);
00824         DriverView  view(&dlg);
00825 
00826         dlg.setMainWidget(&view);
00827         view.setDriver(xmlCmd->driver());
00828         dlg.resize(350,400);
00829         dlg.exec();
00830 
00831         return true;
00832     }
00833     return false;
00834 }
KDE Home | KDE Accessibility Home | Description of Access Keys