Main Page · Namespace List · Alphabetical List · Class List · File List · Namespace Members · Class Members · File Members · Related Pages

guiprinterdrivertoxml.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005-2006 by Konrad Wilhelm Kleine
00003  *   konrad@plothe-kleine.de
00004  *
00005  *   This file contains the "Printer Driver 2 XML" implementation.
00006  *
00007  *   PLEASE NOTICE: If not stated otherwise, whenever we speak of 'printer
00008  *                  drivers' or simply 'drivers', we mean the PPD files
00009  *                  and not the actual drivers.
00010  *
00011  *   STATUS: File has been reviewed and commented
00012  *
00013  *   $Id: guiprinterdrivertoxml.cpp,v 1.5 2006/04/18 19:35:03 hbci Exp $
00014  *
00015  *   This program is free software; you can redistribute it and/or modify
00016  *   it under the terms of the GNU General Public License as published by
00017  *   the Free Software Foundation; either version 2 of the License, or
00018  *   (at your option) any later version.
00019  *
00020  *   This program is distributed in the hope that it will be useful,
00021  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  *   GNU General Public License for more details.
00024  *
00025  *   You should have received a copy of the GNU General Public License
00026  *   along with this program; if not, write to the Free Software Foundation,
00027  *   Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00028  ***************************************************************************/
00029 
00030 // App includes
00031 #include "guiprinterdrivertoxml.h"
00032 #include <globals.h>
00033 using namespace LinuxPrinterSetup;
00034 
00035 // Qt-includes
00036 #include <qfiledialog.h>
00037 #include <qlineedit.h>
00038 #include <qpushbutton.h>
00039 #include <qlcdnumber.h>
00040 #include <qgroupbox.h>
00041 #include <qtextedit.h>
00042 #include <qdom.h>
00043 #include <qdir.h>
00044 #include <qprocess.h>
00045 #include <qlcdnumber.h>
00046 #include <qapplication.h>
00047 #include <qlabel.h>
00048 #include <qdatetime.h>
00049 #include <qtextstream.h>
00050 #include <qiodevice.h>
00051 
00052 // Includes for popen handling
00053 #include <errno.h>
00054 
00055 
00063 GuiPrinterDriverToXml::GuiPrinterDriverToXml( QWidget * parent,
00064                                               const char * name )
00065     : GuiPrinterDriverToXmlBase(parent,name)
00066 {
00067   m_domDoc        = NULL;
00068   m_CupsModelDir  = LPS_CUPS_MODEL_DIR_DEFAULT;
00069 
00070   enableWidgets(NoneFlag ^ BuildFlag);
00071 }
00072 
00073 
00077 GuiPrinterDriverToXml::~GuiPrinterDriverToXml()
00078 {
00079   qDebug("Destructor GuiPrinterDriverToXml");
00080 
00081   if ( m_domDoc )
00082     delete m_domDoc;
00083 
00084 }
00085 
00086 
00091 void GuiPrinterDriverToXml::show()
00092 {
00093   GuiPrinterDriverToXmlBase::show();
00094   setCaption("Cups Driver to XML");
00095   qApp->processEvents();
00096 
00097   lineEdit_savePath->setText(MP_DIR() + MONEYPENNY_DATA_DIR + LPS_DB_FILE);
00098   lineEdit_cupsModelDir->setText(m_CupsModelDir);
00099 
00100   logMessage("System startup ok.");
00101 }
00102 
00103 
00108 void GuiPrinterDriverToXml::closeEvent( QCloseEvent * e )
00109 {
00110   on_pushButton_abort_clicked();
00111   e->accept();
00112 }
00113 
00114 
00120 void GuiPrinterDriverToXml::on_pushButton_build_clicked()
00121 {
00122   enableWidgets(NoneFlag ^ ProgressFlag);
00123 
00124   m_buildCanceled = false;
00125 
00126   m_CupsModelDir = lineEdit_cupsModelDir->text();
00127 
00128   // make sure it ends with a "/"
00129   if ( m_CupsModelDir.right(1) != "/" )
00130     m_CupsModelDir += "/";
00131 
00132   logMessage(tr("Now building XML database from: %1 ...").arg(m_CupsModelDir));
00133 
00134   // until now, no drivers where found, so adjust the LCDs
00135   lCDNumber_manufacturers->display(0);
00136   lCDNumber_models->display(0);
00137   lCDNumber_drivers->display(0);
00138 
00139   // prevent the gui from hanging up
00140   qApp->processEvents();
00141 
00142   // Constrcut a "clean" DOMDocument with a root element
00143   if ( m_domDoc )
00144     delete m_domDoc;
00145 
00146   m_domDoc                = new PrinterSetupDb(LPS_DB_DOCUMENT_NAME);
00147   QDomElement rootElement = m_domDoc->createElement(LPS_DB_DOCUMENT_NAME);
00148   rootElement.setAttribute("path", m_CupsModelDir);
00149   m_domDoc->appendChild(rootElement);
00150 
00151   try
00152   {
00153     traverseDir(m_CupsModelDir);
00154     logMessage("Build process complete! You can now save the db to a xml file.");
00155     enableWidgets(AllFlag ^ ProgressFlag);
00156   }
00157   catch(LpsError msg)
00158   {
00159     logMessage("Build process exited with error: " + msg, true);
00160     enableWidgets(NoneFlag ^ BuildFlag);
00161     return;
00162   }
00163 }
00164 
00165 
00170 void GuiPrinterDriverToXml::on_pushButton_browseSavePath_clicked()
00171 {
00172   QString dir = lineEdit_savePath->text();
00173 
00174   if ( dir.length() <= 0 )
00175     dir = MONEYPENNY_DATA_DIR;
00176 
00177   QFileDialog* fd = new QFileDialog( this );
00178 
00179   fd->setDir(dir);
00180   fd->setMode( QFileDialog::AnyFile );
00181 
00182   if ( fd->exec() == QDialog::Accepted )
00183     lineEdit_savePath->setText( fd->selectedFile() );
00184 }
00185 
00195 void GuiPrinterDriverToXml::on_pushButton_browseCupsDir_clicked()
00196 {
00197   QString dir = lineEdit_cupsModelDir->text();
00198 
00199   if ( dir.length() <= 0 )
00200     dir = LPS_CUPS_MODEL_DIR_DEFAULT;
00201 
00202   QFileDialog* fd = new QFileDialog( this );
00203 
00204   fd->setDir(dir);
00205   fd->setMode( QFileDialog::Directory );
00206 
00207   if ( fd->exec() == QDialog::Accepted )
00208     lineEdit_cupsModelDir->setText( fd->selectedFile() );
00209 }
00210 
00215 void GuiPrinterDriverToXml::on_pushButton_abort_clicked()
00216 {
00217   m_buildCanceled = true;
00218   enableWidgets(NoneFlag ^ BuildFlag);
00219 }
00220 
00225 void GuiPrinterDriverToXml::on_pushButton_back_clicked()
00226 {
00227   on_pushButton_abort_clicked();
00228   emit back();
00229 }
00230 
00236 void GuiPrinterDriverToXml::on_pushButton_save_clicked()
00237 {
00238   //save result file
00239   QFile file( lineEdit_savePath->text() );
00240 
00241   if ( file.open( IO_WriteOnly ) )
00242   {
00243     QTextStream stream( &file );
00244     m_domDoc->save( stream, 2);
00245     file.close();
00246     logMessage( "Saving complete!" );
00247   }
00248   else
00249   {
00250     logMessage("Could not open file for writing: " + lineEdit_savePath->text(), true);
00251   }
00252 }
00253 
00254 
00262 void GuiPrinterDriverToXml::logMessage( const QString & msg,
00263                                         bool isError
00264                                       )
00265 {
00266   // prepend a nice time information infront of every log entry
00267   QString str = QTime::currentTime().toString("[hh:mm:ss] ") + msg;
00268 
00269   QString color = "darkgreen";
00270 
00271   // change the format, depending on if the message is an error message or not
00272   if ( isError )
00273     color = "red";
00274 
00275   textEdit_log->append( QString("<font color=\"%1\">%2</font>").arg(color, str) );
00276 }
00277 
00278 
00287 void GuiPrinterDriverToXml::traverseDir( const QString & dir )
00288 {
00289   // Due to some speed issues when stopping the build process, this string is used
00290   // at 3 different locations in this method. Therefore it is placed here once.
00291   QString buildCancelledString = tr("Build manually cancelled");
00292 
00293   // if canceled, abort this process by throwing a message as exception
00294   if ( m_buildCanceled )
00295     throw buildCancelledString;
00296 
00297   QDir currentDir( dir );
00298 
00299   if ( !currentDir.exists() || !currentDir.isReadable() )
00300   {
00301     throw LpsError(QString("The following directory could not be found or is not readable: ") + currentDir.dirName());
00302   }
00303 
00304   //======================================================================
00305   // Get all subdirs
00306   //======================================================================
00307 
00308   currentDir.setFilter( QDir::Dirs );
00309   QStringList subdirs = currentDir.entryList();
00310 
00311   for ( QStringList::Iterator subDirIt = subdirs.begin();
00312         subDirIt != subdirs.end();
00313         ++subDirIt
00314       )
00315   {
00316     if ( m_buildCanceled )
00317       throw LpsError(buildCancelledString);
00318 
00319     if ( subDirIt!=NULL )
00320     {
00321       QString name = *subDirIt;
00322 
00323       if ( name!="." && name!=".." )
00324       {
00325         QString absPath = currentDir.absPath() + "/" + name;
00326         QDir dirEntry( absPath );
00327         traverseDir(absPath);
00328       }
00329     }
00330   }
00331 
00332   //======================================================================
00333   // Get all files for "dir"
00334   //======================================================================
00335 
00336   currentDir.setFilter( QDir::Files );
00337   QStringList files = currentDir.entryList();
00338 
00339   for ( QStringList::Iterator fileIt = files.begin();
00340         fileIt != files.end();
00341         ++fileIt )
00342   {
00343     if (m_buildCanceled)
00344       throw LpsError(buildCancelledString);
00345 
00346     if ( fileIt!=NULL )
00347     {
00348       QString name = *fileIt;
00349 
00350       if ( name!="." && name!=".." )
00351       {
00352         QString absPath = currentDir.absPath() + "/" + name;
00353 
00354         try
00355         {
00356           parseFile(absPath);
00357         }
00358         catch( LpsError e )
00359         {
00360           logMessage(e, true);
00361         }
00362 
00363       }
00364     }
00365   }
00366 }
00367 
00377 void GuiPrinterDriverToXml::parseFile( const QString & filePath )
00378 {
00379   //======================================================================
00380   // Make sure the file ends with ".ppd" or ".ppd.gz"
00381   //======================================================================
00382 
00383   if ( !filePath.contains(".ppd",false) && !filePath.contains(".ppd.gz",false) )
00384   {
00385     logMessage("The following file has no valid PPD-file-signature: " + filePath, true);
00386     return;
00387   }
00388 
00389   //======================================================================
00390   // Read in the file (if compressed, decompress it first)
00391   //======================================================================
00392 
00393   QTextStream * reader = NULL;
00394   FILE        * pipe   = NULL; // used when opening with decompressing
00395   QFile       * file   = NULL; // used when opening without previous decompression
00396 
00397   if ( filePath.contains(".ppd.gz",false) )
00398   {
00399     // The command to be executed for decompressing the PPD file
00400     QString gzcmd = "gunzip -cdf " + filePath;
00401 
00402     // gunzip exits with 0 if everything was ok, with 1 if an error
00403     // occured and with 2 if a warning occured.
00404     //
00405     // WE WON'T TOLERATE ANYTHING EXCEPT 0 (=OK) !!!
00406     //
00407     pipe = popen(gzcmd.latin1(), "r");
00408 
00409     if ( !pipe || errno != 0 )
00410         throw LpsError(
00411                         QString("Error during gunzip execution! Could not execute process: <br>") +
00412                         gzcmd +
00413                         QString("Errormessage: ") +
00414                         (QString) strerror(errno)
00415                       );
00416 
00417     reader = new QTextStream(pipe, IO_ReadOnly);
00418   }
00419   else
00420   {
00421     file = new QFile(filePath);
00422     if ( !file->open(IO_ReadOnly) )
00423     {
00424       throw LpsError(
00425                       QString("Could not open the file for reading: <br>") +
00426                       filePath +
00427                       " <br>" +
00428                       "Errormessage: " +
00429                       (QString)strerror(errno)
00430                     );
00431     }
00432     reader = new QTextStream(file);
00433   }
00434   //======================================================================
00435   // Read in and parse the extracted information from pipe
00436   //======================================================================
00437 
00438   // Run through every line of the file until we have all needed information
00439   // (this is the tricky part, that costed much of brain corniness :))
00440 
00441   PpdInfo info;
00442 
00443   bool        done    = false;
00444   QString     line    = QString::null;
00445 
00446   while ( !done && !reader->atEnd() )
00447   {
00448     line = reader->readLine();
00449 
00450     line = line.simplifyWhiteSpace().remove("\"");
00451 
00452     if ( line.startsWith("*Product:") )
00453       info.product = line.remove("*Product:").remove( " (" ).remove(")" ).stripWhiteSpace();
00454 
00455     else if ( line.startsWith("*NickName:") )
00456     {
00457       info.nickName = line.remove("*NickName:");
00458       info.nickName = info.nickName.remove("\"").stripWhiteSpace();
00459     }
00460 
00461     else if ( line.startsWith("*ModelName:") )
00462       info.modelName = line.remove("*ModelName: ").stripWhiteSpace();
00463 
00464     else if ( line.startsWith("*Manufacturer:") )
00465       info.manufacturer = line.remove("*Manufacturer:").stripWhiteSpace();
00466 
00467     else if ( line.startsWith("*LanguageVersion:") )
00468       info.languageVersion = line.remove("*LanguageVersion:").stripWhiteSpace();
00469 
00470     if (  !info.product.isEmpty() && !info.nickName.isEmpty() &&
00471          !info.modelName.isEmpty() && !info.languageVersion.isEmpty() &&
00472          !info.manufacturer.isEmpty() )
00473       done = true;
00474   }
00475 
00476   //
00477   // Never change the order of the following deletions/closings!!!
00478   //
00479 
00480   // delete the stream that uses the pipe FIRST!!!
00481   if ( reader )
00482     delete reader;
00483 
00484   // SECONDLY, delete the pipe itself (otherwise you will get a segmentation fault)
00485   if ( pipe )
00486     pclose(pipe);
00487   if ( file )
00488     delete file;
00489 
00490   if (!done)
00491     throw LpsError( tr("PPD-file: %1 Not all neccessary informations were catched!").arg(filePath.latin1()) );
00492 
00493   QString ppdFilePath = filePath;
00494   info.ppdFilePath    = ppdFilePath.remove(m_CupsModelDir);
00495 
00496   addDriver(info);
00497 }
00498 
00504 void GuiPrinterDriverToXml::addDriver( const PpdInfo & drv )
00505 {
00506   QDomElement root = m_domDoc->documentElement();
00507 
00508   QDomElement manufacturerElement = m_domDoc->getManufacturer(drv.manufacturer);
00509 
00510   if ( manufacturerElement.isNull() )
00511   {
00512     manufacturerElement = m_domDoc->createElement("Manufacturer");
00513     manufacturerElement.setAttribute("name", drv.manufacturer);
00514     root.appendChild(manufacturerElement);
00515 
00516     // Update the manufacturer LCD
00517     lCDNumber_manufacturers->display(lCDNumber_manufacturers->intValue() + 1);
00518     qApp->processEvents();
00519   }
00520 
00521   QDomElement modelElement = m_domDoc->getModel(drv.manufacturer, drv.modelName, drv.product);
00522 
00523   if ( modelElement.isNull() )
00524   {
00525     modelElement = m_domDoc->createElement("Model");
00526     modelElement.setAttribute("name", drv.modelName);
00527     modelElement.setAttribute("product", drv.product);
00528     manufacturerElement.appendChild(modelElement);
00529 
00530     // Update the model LCD
00531     lCDNumber_models->display(lCDNumber_models->intValue() + 1);
00532     qApp->processEvents();
00533   }
00534 
00535   QDomElement driverEle = m_domDoc->getDriverByModel(drv.manufacturer, drv.modelName, drv.nickName);
00536 
00537   if ( driverEle.isNull() )
00538   {
00539     driverEle = m_domDoc->createElement("Driver");
00540     driverEle.setAttribute("nickName", drv.nickName);
00541     driverEle.setAttribute("languageVersion", drv.languageVersion);
00542     driverEle.setAttribute("ppdFilePath",  drv.ppdFilePath);
00543     modelElement.appendChild(driverEle);
00544 
00545     // Update the driver LCD
00546     lCDNumber_drivers->display(lCDNumber_drivers->intValue() + 1);
00547     qApp->processEvents();
00548   }
00549 
00550 }
00551 
00557 void GuiPrinterDriverToXml::enableWidgets( int wf )
00558 {
00559   groupBox_build->setEnabled(     wf & BuildFlag    );
00560   groupBox_progress->setEnabled(  wf & ProgressFlag );
00561   groupBox_save->setEnabled(      wf & SaveFlag     );
00562 }
00563 
00564 


To get more information, please visit our project site hosted at SourceForge.net Logo
To support this project, please click on this image: Support This Project

Copyright © 2005-2006 Linux Printer Setup Documentation generated by Doxygen 1.4.4 LPS 1.0 (Disclaimer)