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
00395                 {
00396                     format.replace( re, KProcess::quote( dopt->valueText() ) );
00397                 }
00398                 str.append(format).append(" ");
00399             }
00400         }
00401         cmd.replace("%filterargs", str);
00402     }
00403 
00404     cmd.replace("%filterinput", d->m_io[0].m_format[(pipein?1:0)]);
00405     cmd.replace("%filteroutput", d->m_io[1].m_format[(pipeout?1:0)]);
00406 
00407     return cmd;
00408 }
00409 
00410 void KXmlCommand::setOptions(const QMap<QString,QString>& opts)
00411 {
00412     if (opts.count() == 0)
00413         return;
00414     // force loading the driver if needed
00415     if (driver())
00416         d->m_driver->setOptions(opts);
00417 }
00418 
00419 void KXmlCommand::getOptions(QMap<QString,QString>& opts, bool incldef)
00420 {
00421     // force loading the driver
00422     if (driver())
00423         d->m_driver->getOptions(opts, incldef);
00424 }
00425 
00426 void KXmlCommand::saveXml()
00427 {
00428     QFile   f(locateLocal("data", "kdeprint/filters/"+name()+".xml"));
00429     if (!f.open(IO_WriteOnly))
00430         return;
00431 
00432     QDomDocument    doc("kprintfilter");
00433     QDomElement root = doc.createElement("kprintfilter"), elem;
00434 
00435     root.setAttribute("name", d->m_name);
00436     doc.appendChild(root);
00437 
00438     // command
00439     elem = doc.createElement("filtercommand");
00440     elem.setAttribute("data", d->m_command);
00441     root.appendChild(elem);
00442 
00443     // options
00444     if (d->m_driver)
00445     {
00446         elem = createGroup(doc, d->m_driver);
00447         elem.setTagName("filterargs");
00448         root.appendChild(elem);
00449     }
00450 
00451     // IO
00452     if (!(elem=createIO(doc, 0, "filterinput")).isNull())
00453         root.appendChild(elem);
00454     if (!(elem=createIO(doc, 1, "filteroutput")).isNull())
00455         root.appendChild(elem);
00456 
00457     // save to file (and close it)
00458     QTextStream t(&f);
00459     t << doc.toString();
00460     f.close();
00461 }
00462 
00463 QDomElement KXmlCommand::createIO(QDomDocument& doc, int n, const QString& tag)
00464 {
00465     QDomElement elem = doc.createElement(tag);
00466     if (d->m_command.find("%"+tag) != -1)
00467     {
00468         for (int i=0; i<2; i++)
00469         {
00470             QDomElement io = doc.createElement("filterarg");
00471             io.setAttribute("name", (i ? "pipe" : "file"));
00472             io.setAttribute("format", d->m_io[n].m_format[i]);
00473             elem.appendChild(io);
00474         }
00475     }
00476 
00477     return elem;
00478 }
00479 
00480 QDomElement KXmlCommand::createGroup(QDomDocument& doc, DrGroup *group)
00481 {
00482     QDomElement elem = doc.createElement("filtergroup");
00483     elem.setAttribute("name", group->name());
00484     elem.setAttribute("description", group->get("text"));
00485 
00486     QPtrListIterator<DrGroup>   git(group->groups());
00487     for (; git.current(); ++git)
00488         elem.appendChild(createGroup(doc, git.current()));
00489 
00490     QPtrListIterator<DrBase>    oit(group->options());
00491     for (; oit.current(); ++oit)
00492         elem.appendChild(createElement(doc, oit.current()));
00493 
00494     return elem;
00495 }
00496 
00497 QDomElement KXmlCommand::createElement(QDomDocument& doc, DrBase *opt)
00498 {
00499     QDomElement elem = doc.createElement("filterarg");
00500     QString elemName = opt->name();
00501     if (elemName.startsWith("_kde-"))
00502         elemName.replace(0, name().length()+6, "");
00503     elem.setAttribute("name", elemName);
00504     elem.setAttribute("format", opt->get("format"));
00505     elem.setAttribute("description", opt->get("text"));
00506     elem.setAttribute("default", opt->get("default"));
00507     elem.setAttribute( "persistent", opt->get( "persistent" ) == "1" ? "1" : "0");
00508 
00509     switch (opt->type())
00510     {
00511         case DrBase::String:
00512             elem.setAttribute("type", "string");
00513             break;
00514         case DrBase::Integer:
00515         case DrBase::Float:
00516             elem.setAttribute("type", (opt->type() == DrBase::Integer ? "int" : "float"));
00517             elem.setAttribute("min", opt->get("minval"));
00518             elem.setAttribute("max", opt->get("maxval"));
00519             break;
00520         case DrBase::Boolean:
00521         case DrBase::List:
00522             elem.setAttribute("type", (opt->type() == DrBase::List ? "list" : "bool"));
00523             {
00524                 QPtrListIterator<DrBase>    it(*(static_cast<DrListOption*>(opt)->choices()));
00525                 for (; it.current(); ++it)
00526                 {
00527                     QDomElement chElem = doc.createElement("value");
00528                     chElem.setAttribute("name", it.current()->name());
00529                     chElem.setAttribute("description", it.current()->get("text"));
00530                     elem.appendChild(chElem);
00531                 }
00532             }
00533             break;
00534         default:
00535             break;
00536     }
00537 
00538     return elem;
00539 }
00540 
00541 //---------------------------------------------------------------------------------------------------
00542 
00543 class KXmlCommandManager::KXmlCommandManagerPrivate
00544 {
00545 public:
00546     QStringList m_cmdlist;
00547     QMap<QString, QValueList<KXmlCommand*> >    m_mimemap;
00548     QMap<QString, KXmlCommand*> m_cmdmap;
00549 };
00550 
00551 KXmlCommandManager* KXmlCommandManager::m_self = 0;
00552 
00553 KXmlCommandManager* KXmlCommandManager::self()
00554 {
00555     if (!m_self)
00556     {
00557         m_self = new KXmlCommandManager;
00558         Q_CHECK_PTR(m_self);
00559     }
00560     return m_self;
00561 }
00562 
00563 KXmlCommandManager::KXmlCommandManager()
00564 : QObject(KMFactory::self(), "XmlCommandManager")
00565 {
00566     d = new KXmlCommandManagerPrivate;
00567 }
00568 
00569 KXmlCommandManager::~KXmlCommandManager()
00570 {
00571     cleanUp();
00572     delete d;
00573 }
00574 
00575 KXmlCommand* KXmlCommandManager::loadCommand(const QString& xmlId, bool check)
00576 {
00577     if (check)
00578     {
00579         QString desktopFile = locate("data", "kdeprint/filters/"+xmlId+".desktop");
00580         if (desktopFile.isEmpty())
00581             return 0;
00582     }
00583     return new KXmlCommand(xmlId);
00584 }
00585 
00586 void KXmlCommandManager::saveCommand(KXmlCommand *xmlCmd)
00587 {
00588     xmlCmd->saveDesktop();
00589     xmlCmd->saveXml();
00590 
00591     cleanUp();
00592 }
00593 
00594 void KXmlCommandManager::cleanUp()
00595 {
00596     for (QMap<QString, KXmlCommand*>::ConstIterator it=d->m_cmdmap.begin(); it!=d->m_cmdmap.end(); ++it)
00597         delete (*it);
00598     d->m_cmdmap.clear();
00599     d->m_mimemap.clear();
00600     d->m_cmdlist.clear();
00601 }
00602 
00603 void KXmlCommandManager::preload()
00604 {
00605     if (d->m_cmdmap.count() == 0)
00606     {
00607         commandList();
00608         for (QStringList::Iterator it=d->m_cmdlist.begin(); it!=d->m_cmdlist.end(); ++it)
00609         {
00610             KXmlCommand *xmlCmd = loadCommand(*it);
00611             if (!xmlCmd) continue; // Error!
00612 
00613             QStringList inputMime = xmlCmd->inputMimeTypes();
00614             for (QStringList::ConstIterator mime=inputMime.begin(); mime!=inputMime.end(); ++mime)
00615             {
00616                 d->m_mimemap[*mime].append(xmlCmd);
00617                 d->m_cmdmap[*it] = xmlCmd;
00618             }
00619         }
00620     }
00621 }
00622 
00623 QStringList KXmlCommandManager::commandList()
00624 {
00625     if (d->m_cmdlist.isEmpty())
00626     {
00627         QStringList dirs = KGlobal::dirs()->findDirs("data", "kdeprint/filters/");
00628 
00629         for (QStringList::ConstIterator it=dirs.begin(); it!=dirs.end(); ++it)
00630         {
00631             QStringList list = QDir(*it).entryList("*.desktop", QDir::Files, QDir::Unsorted);
00632             for (QStringList::ConstIterator it2=list.begin(); it2!=list.end(); ++it2)
00633             {
00634                 QString cmdName = (*it2).left((*it2).length()-8);
00635                 if (d->m_cmdlist.find(cmdName) == d->m_cmdlist.end())
00636                     d->m_cmdlist.append(cmdName);
00637             }
00638         }
00639 
00640         d->m_cmdlist.sort();
00641     }
00642 
00643     return d->m_cmdlist;
00644 }
00645 
00646 QStringList KXmlCommandManager::commandListWithDescription()
00647 {
00648     preload();
00649     QStringList l;
00650     for (QMap<QString,KXmlCommand*>::ConstIterator it=d->m_cmdmap.begin(); it!=d->m_cmdmap.end(); ++it)
00651         l << (*it)->name() << (*it)->description();
00652 
00653     return l;
00654 }
00655 
00656 QString KXmlCommandManager::selectCommand(QWidget *parent)
00657 {
00658     KLibrary *lib = KLibLoader::self()->library( "libkdeprint_management_module" );
00659     if ( !lib )
00660     {
00661         KMessageBox::error( parent, i18n( "Unable to load KDE print management library: %1" ).arg( KLibLoader::self()->lastErrorMessage() ) );
00662         return QString::null;
00663     }
00664     else
00665     {
00666         QString ( *func )( QWidget* ) = ( QString( * )( QWidget* ) )lib->symbol( "select_command" );
00667         if ( !func )
00668         {
00669             KMessageBox::error( parent, i18n( "Unable to find wizard object in management library." ) );
00670             return QString::null;
00671         }
00672         else
00673             return func( parent );
00674     }
00675 }
00676 
00677 KXmlCommand* KXmlCommandManager::command(const QString& xmlId) const
00678 {
00679     return (d->m_cmdmap.contains(xmlId) ? d->m_cmdmap[xmlId] : 0);
00680 }
00681 
00682 int KXmlCommandManager::insertCommand(QStringList& list, const QString& filtername, bool defaultToStart)
00683 {
00684     preload();
00685 
00686     int pos(0);
00687     KXmlCommand *f1 = command(filtername), *f2 = 0;
00688     if (f1 && f1->inputMimeTypes().count() > 0)
00689     {
00690         QString mimetype = f1->inputMimeTypes()[0];
00691         for (QStringList::Iterator it=list.begin(); it!=list.end(); ++it, pos++)
00692         {
00693             f2 = command(*it);
00694             if (!f2)
00695                 return -1; // Shouldn't happen
00696 
00697             if (f2->acceptMimeType(f1->mimeType()) && f1->acceptMimeType(mimetype))
00698             {
00699                 list.insert(it, filtername);
00700                 break;
00701             }
00702             else
00703             {
00704                 mimetype = f2->mimeType();
00705                 f2 = 0;
00706             }
00707         }
00708         if (pos == (int)(list.count()))
00709         {
00710             if (list.count() == 0 || f1->acceptMimeType(mimetype))
00711                 list.append(filtername);
00712             else if (defaultToStart)
00713             {
00714                 pos = 0;
00715                 list.prepend(filtername);
00716             }
00717             else
00718                 pos = -1;
00719         }
00720     }
00721     return pos;
00722 }
00723 
00724 QStringList KXmlCommandManager::autoConvert(const QString& mimesrc, const QString& mimedest)
00725 {
00726     QStringList chain;
00727     uint        score(0);
00728 
00729     preload();
00730 
00731     if (d->m_mimemap.contains(mimesrc))
00732     {
00733         const QValueList<KXmlCommand*>  l = d->m_mimemap[mimesrc];
00734         for (QValueList<KXmlCommand*>::ConstIterator it=l.begin(); it!=l.end(); ++it)
00735         {
00736             // check filter availability
00737             if (!KdeprintChecker::check((*it)->requirements()))
00738                 continue;
00739 
00740             // direct filter: shortest path => return immediately
00741             if ((*it)->mimeType() == mimedest)
00742             {
00743                 chain = QStringList((*it)->name());
00744                 break;
00745             }
00746             // non direct filter: find the shortest way between
00747             // its output and mimedest (do not consider cyling filters)
00748             else if ((*it)->mimeType() != mimesrc)
00749             {
00750                 QStringList subchain = autoConvert((*it)->mimeType(), mimedest);
00751                 // If chain length is 0, then there's no possible filter between those 2
00752                 // mime types. Just discard it. If the subchain contains also the current
00753                 // considered filter, then discard it: it denotes of a cycle in filter
00754                 // chain.
00755                 if (subchain.count() > 0 && subchain.findIndex((*it)->name()) == -1)
00756                 {
00757                     subchain.prepend((*it)->name());
00758                     if (subchain.count() < score || score == 0)
00759                     {
00760                         chain = subchain;
00761                         score = subchain.count();
00762                     }
00763                 }
00764             }
00765         }
00766     }
00767     // At this point, either we have the shortest path, or empty
00768     // list if nothing could be found
00769     return chain;
00770 }
00771 
00772 bool KXmlCommandManager::checkCommand(const QString& xmlId, int inputCheck, int outputCheck, QString *msg)
00773 {
00774     KXmlCommand *xmlCmd = command(xmlId);
00775     QString errmsg;
00776     bool    needDestroy(false);
00777     //kdDebug(500) << "checking command: " << xmlId << " (" << (xmlCmd != NULL) << ")" << endl;
00778     if (!xmlCmd)
00779     {
00780         xmlCmd = loadCommand(xmlId, true);
00781         needDestroy = (xmlCmd != 0);
00782     }
00783 
00784     bool    status(true);
00785     if (xmlCmd)
00786     {
00787         status = (xmlCmd->isValid() && KdeprintChecker::check(xmlCmd->requirements()));
00788         if (!status)
00789             errmsg = i18n("One of the command object's requirements is not met.");
00790     }
00791     QString cmd = (xmlCmd ? xmlCmd->command() : xmlId);
00792     if (status && !cmd.isEmpty() && (inputCheck > None || outputCheck > None))
00793     {
00794         if (inputCheck > None && (cmd.find("%in") == -1 || inputCheck == Advanced) && cmd.find("%filterinput") == -1)
00795         {
00796             status = false;
00797             errmsg = i18n("The command does not contain the required tag %1.").arg(inputCheck == Advanced ? "%filterinput" : "{%in,%filterinput}");
00798         }
00799         if (status && outputCheck > None && (cmd.find("%out") == -1 || outputCheck == Advanced) && cmd.find("filteroutput") == -1)
00800         {
00801             status = false;
00802             errmsg = i18n("The command does not contain the required tag %1.").arg(outputCheck == Advanced ? "%filteroutput" : "{%out,%filteroutput}");
00803         }
00804     }
00805 
00806     if (needDestroy)
00807         delete xmlCmd;
00808 
00809     if (msg)
00810         *msg = errmsg;
00811 
00812     return status;
00813 }
00814 
00815 bool KXmlCommandManager::configure(KXmlCommand *xmlCmd, QWidget *parent)
00816 {
00817     if (xmlCmd->driver())
00818     {
00819         KDialogBase dlg(parent, 0, true, xmlCmd->description(), KDialogBase::Ok);
00820         DriverView  view(&dlg);
00821 
00822         dlg.setMainWidget(&view);
00823         view.setDriver(xmlCmd->driver());
00824         dlg.resize(350,400);
00825         dlg.exec();
00826 
00827         return true;
00828     }
00829     return false;
00830 }
KDE Home | KDE Accessibility Home | Description of Access Keys