kmvirtualmanager.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 "kmvirtualmanager.h" 00021 #include "kmprinter.h" 00022 #include "kmfactory.h" 00023 #include "kmmanager.h" 00024 #include "kprinter.h" 00025 00026 #include <stdlib.h> 00027 #include <qfile.h> 00028 #include <qtextstream.h> 00029 #include <qdir.h> 00030 #include <qfileinfo.h> 00031 #include <klocale.h> 00032 #include <kstandarddirs.h> 00033 #include <kurl.h> 00034 #include <kdebug.h> 00035 #include <kmessagebox.h> 00036 00037 #include <unistd.h> 00038 00039 static QString instanceName(const QString& prname, const QString& instname) 00040 { 00041 QString str(prname); 00042 if (!instname.isEmpty()) 00043 str.append("/"+instname); 00044 return str; 00045 } 00046 00047 KMVirtualManager::KMVirtualManager(KMManager *parent, const char *name) 00048 : QObject(parent,name), m_manager(parent) 00049 { 00050 } 00051 00052 KMVirtualManager::~KMVirtualManager() 00053 { 00054 } 00055 00056 KMPrinter* KMVirtualManager::findPrinter(const QString& name) 00057 { 00058 return m_manager->findPrinter(name); 00059 } 00060 00061 KMPrinter* KMVirtualManager::findInstance(KMPrinter *p, const QString& name) 00062 { 00063 QString instname(instanceName(p->printerName(),name)); 00064 return findPrinter(instname); 00065 } 00066 00067 void KMVirtualManager::addPrinter(KMPrinter *p) 00068 { 00069 if (p && p->isValid()) 00070 { 00071 KMPrinter *other = findPrinter(p->name()); 00072 if (other) 00073 { 00074 other->copy(*p); 00075 // Replace default options with the new loaded ones: this is needed 00076 // if we want to handle 2 lpoptions correctly (system-wide and local). 00077 // Anyway, the virtual printers will be reloaded only if something has 00078 // changed in one of the files, so it's better to reset everything, to 00079 // be sure to use the new changes. Edited options will be left unchanged. 00080 other->setDefaultOptions(p->defaultOptions()); 00081 delete p; 00082 } 00083 else 00084 m_manager->addPrinter(p); 00085 } 00086 else 00087 delete p; 00088 } 00089 00090 void KMVirtualManager::setDefault(KMPrinter *p, bool saveflag) 00091 { 00092 m_manager->setSoftDefault(p); 00093 m_defaultprinter = (p ? p->printerName() : QString::null); 00094 if (saveflag) triggerSave(); 00095 } 00096 00097 bool KMVirtualManager::isDefault(KMPrinter *p, const QString& name) 00098 { 00099 QString instname(instanceName(p->printerName(),name)); 00100 KMPrinter *printer = findPrinter(instname); 00101 if (printer) 00102 return printer->isSoftDefault(); 00103 else 00104 return false; 00105 } 00106 00107 void KMVirtualManager::create(KMPrinter *p, const QString& name) 00108 { 00109 QString instname = instanceName(p->printerName(),name); 00110 if (findPrinter(instname) != NULL) return; 00111 KMPrinter *printer = new KMPrinter; 00112 printer->setName(instname); 00113 printer->setPrinterName(p->printerName()); 00114 printer->setInstanceName(name); 00115 if (!name.isEmpty()) 00116 printer->setType(p->type()|KMPrinter::Virtual); 00117 // we need some options to know how to load the driver 00118 if (p->isSpecial()) 00119 printer->setOptions(p->options()); 00120 m_manager->addPrinter(printer); 00121 triggerSave(); 00122 } 00123 00124 void KMVirtualManager::copy(KMPrinter *p, const QString& src, const QString& name) 00125 { 00126 QString instsrc(instanceName(p->printerName(),src)), instname(instanceName(p->printerName(),name)); 00127 KMPrinter *prsrc = findPrinter(instsrc); 00128 if (!prsrc || findPrinter(instname) != NULL) return; 00129 KMPrinter *printer = new KMPrinter; 00130 printer->copy(*prsrc); 00131 printer->setName(instname); 00132 printer->setInstanceName(name); 00133 printer->setDefaultOptions(prsrc->defaultOptions()); 00134 m_manager->addPrinter(printer); 00135 triggerSave(); 00136 } 00137 00138 void KMVirtualManager::remove(KMPrinter *p, const QString& name) 00139 { 00140 QString instname = instanceName(p->printerName(),name); 00141 KMPrinter *printer = findPrinter(instname); 00142 if (!printer) return; 00143 if (name.isEmpty()) 00144 { // remove default instance => only remove options, keep the KMPrinter object 00145 printer->setDefaultOptions(QMap<QString,QString>()); 00146 printer->setEditedOptions(QMap<QString,QString>()); 00147 printer->setEdited(false); 00148 } 00149 else 00150 m_manager->m_printers.removeRef(printer); 00151 triggerSave(); 00152 } 00153 00154 void KMVirtualManager::setAsDefault(KMPrinter *p, const QString& name, QWidget *parent) 00155 { 00156 QString instname(instanceName(p->printerName(),name)); 00157 00158 if ( p->isSpecial() ) 00159 { 00160 if ( KMessageBox::warningContinueCancel( parent, 00161 i18n( "<qt>You are about to set a pseudo-printer as your personal default. " 00162 "This setting is specific to KDE and will not be available outside KDE " 00163 "applications. Note that this will only make your personal default printer " 00164 "as undefined for non-KDE applications and should not prevent you from " 00165 "printing normally. Do you really want to set <b>%1</b> as your personal default?</qt>" ).arg( instname ), 00166 QString::null, i18n("Set as Default"), "setSpecialAsDefault" ) == KMessageBox::No ) 00167 return; 00168 } 00169 00170 KMPrinter *printer = findPrinter(instname); 00171 if (!printer) 00172 { // create it if necessary 00173 create(p,name); 00174 printer = findPrinter(instname); 00175 } 00176 if (printer) 00177 setDefault(printer,true); 00178 } 00179 00180 void KMVirtualManager::refresh() 00181 { 00182 QFileInfo fi(QDir::homeDirPath() + QFile::decodeName("/.lpoptions")); 00183 QFileInfo fi2(QFile::decodeName("/etc/cups/lpoptions")); 00184 00185 // if root, then only use global file: trick -> use twice the same file 00186 if (getuid() == 0) 00187 fi.setFile(fi2.absFilePath()); 00188 00189 if (!m_checktime.isValid() || m_checktime < QMAX(fi.lastModified(),fi2.lastModified())) 00190 { 00191 m_defaultprinter = QString::null; 00192 if (fi2.exists()) 00193 loadFile(fi2.absFilePath()); 00194 if (fi.exists() && fi.absFilePath() != fi2.absFilePath()) 00195 loadFile(fi.absFilePath()); 00196 m_checktime = QMAX(fi.lastModified(),fi2.lastModified()); 00197 } 00198 else 00199 { // parse printers looking for instances -> undiscarded them, real printers 00200 // are undiscarded by the manager itself. Also update printer status. 00201 QPtrListIterator<KMPrinter> it(m_manager->m_printers); 00202 for (;it.current();++it) 00203 if (!it.current()->instanceName().isEmpty()) 00204 { 00205 checkPrinter(it.current()); 00206 if (it.current()->isValid()) it.current()->setDiscarded(false); 00207 } 00208 } 00209 } 00210 00211 void KMVirtualManager::checkPrinter(KMPrinter *p) 00212 { 00213 KMPrinter *realprinter = m_manager->findPrinter(p->printerName()); 00214 if (!realprinter || realprinter->isDiscarded()) 00215 { 00216 p->setType(KMPrinter::Invalid); 00217 p->setState(KMPrinter::Unknown); 00218 } 00219 else 00220 { 00221 if (!p->instanceName().isEmpty()) 00222 p->setType(realprinter->type()|KMPrinter::Virtual); 00223 p->setState(realprinter->state()); 00224 } 00225 } 00226 00227 QString KMVirtualManager::defaultPrinterName() 00228 { 00229 return m_defaultprinter; 00230 } 00231 00232 void KMVirtualManager::virtualList(QPtrList<KMPrinter>& list, const QString& prname) 00233 { 00234 // load printers if necessary 00235 refresh(); 00236 00237 // then look for instances 00238 list.setAutoDelete(false); 00239 list.clear(); 00240 kdDebug(500) << "KMVirtualManager::virtualList() prname=" << prname << endl; 00241 QPtrListIterator<KMPrinter> it(m_manager->m_printers); 00242 for (;it.current();++it) 00243 if (it.current()->printerName() == prname) 00244 list.append(it.current()); 00245 } 00246 00247 void KMVirtualManager::loadFile(const QString& filename) 00248 { 00249 QFile f(filename); 00250 if (f.exists() && f.open(IO_ReadOnly)) 00251 { 00252 QTextStream t(&f); 00253 00254 QString line; 00255 QStringList words; 00256 QStringList pair; 00257 KMPrinter *printer, *realprinter; 00258 00259 while (!t.eof()) 00260 { 00261 line = t.readLine().stripWhiteSpace(); 00262 if (line.isEmpty()) continue; 00263 words = QStringList::split(' ',line,false); 00264 if (words.count() < 2) continue; 00265 pair = QStringList::split('/',words[1],false); 00266 realprinter = m_manager->findPrinter(KURL::decode_string(pair[0])); 00267 if (realprinter && !realprinter->isDiscarded()) 00268 { // keep only instances corresponding to an existing and 00269 // non discarded printer. 00270 // "clone" the real printer and modify settings as needed 00271 printer = new KMPrinter(*realprinter); 00272 printer->setName(KURL::decode_string(words[1])); 00273 printer->setPrinterName(KURL::decode_string(pair[0])); 00274 if (pair.count() > 1) 00275 { 00276 printer->setInstanceName(KURL::decode_string(pair[1])); 00277 printer->addType(KMPrinter::Virtual); 00278 } 00279 // parse options 00280 for (uint i=2; i<words.count(); i++) 00281 { 00282 pair = QStringList::split('=',words[i],false); 00283 printer->setDefaultOption(pair[0],(pair.count() > 1 ? pair[1] : QString::null)); 00284 } 00285 // add printer to the manager 00286 addPrinter(printer); // don't use "printer" after this point !!! 00287 // check default state 00288 if (words[0].lower().startsWith("default")) 00289 setDefault(findPrinter(KURL::decode_string(words[1])),false); 00290 } 00291 } 00292 } 00293 } 00294 00295 void KMVirtualManager::triggerSave() 00296 { 00297 QString filename; 00298 if (getuid() == 0) 00299 { 00300 if (KStandardDirs::makeDir(QFile::decodeName("/etc/cups"))) 00301 filename = QFile::decodeName("/etc/cups/lpoptions"); 00302 } 00303 else 00304 filename = QDir::homeDirPath() + QFile::decodeName("/.lpoptions"); 00305 if (!filename.isEmpty()) 00306 { 00307 saveFile(filename); 00308 m_checktime = QFileInfo(filename).lastModified(); 00309 } 00310 } 00311 00312 void KMVirtualManager::saveFile(const QString& filename) 00313 { 00314 QFile f(filename); 00315 if (f.open(IO_WriteOnly)) 00316 { 00317 QTextStream t(&f); 00318 QPtrListIterator<KMPrinter> it(m_manager->m_printers); 00319 for (;it.current();++it) 00320 { 00321 if (it.current()->isSpecial()) 00322 { 00323 t << ( it.current()->isSoftDefault() ? "DefaultSpecial " : "Special " ); 00324 t << KURL::encode_string_no_slash( it.current()->printerName() ); 00325 if ( !it.current()->instanceName().isEmpty() ) 00326 t << "/" << KURL::encode_string_no_slash( it.current()->instanceName() ); 00327 } 00328 else 00329 t << (it.current()->isSoftDefault() ? "Default " : "Dest ") << it.current()->name(); 00330 QMap<QString,QString> opts = it.current()->defaultOptions(); 00331 for (QMap<QString,QString>::ConstIterator oit=opts.begin(); oit!=opts.end(); ++oit) 00332 { 00333 t << ' ' << oit.key(); 00334 if (!oit.data().isEmpty()) 00335 t << '=' << oit.data(); 00336 } 00337 t << endl; 00338 } 00339 } 00340 } 00341 00342 bool KMVirtualManager::testInstance(KMPrinter *p) 00343 { 00344 QString testpage = KMManager::self()->testPage(); 00345 if (testpage.isEmpty()) 00346 return false; 00347 else 00348 { 00349 KPrinter pr; 00350 pr.setPrinterName(p->printerName()); 00351 pr.setSearchName(p->name()); 00352 pr.setOptions(p->defaultOptions()); 00353 return (pr.printFiles(testpage)); 00354 } 00355 } 00356 00357 void KMVirtualManager::reload() 00358 { 00359 reset(); 00360 } 00361 00362 void KMVirtualManager::configChanged() 00363 { 00364 reset(); 00365 }