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 <tqfile.h> 00028 #include <tqtextstream.h> 00029 #include <tqdir.h> 00030 #include <tqfileinfo.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 TQString instanceName(const TQString& prname, const TQString& 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 : TQObject(parent,name), m_manager(parent) 00049 { 00050 } 00051 00052 KMVirtualManager::~KMVirtualManager() 00053 { 00054 } 00055 00056 KMPrinter* KMVirtualManager::findPrinter(const TQString& name) 00057 { 00058 return m_manager->findPrinter(name); 00059 } 00060 00061 KMPrinter* KMVirtualManager::findInstance(KMPrinter *p, const TQString& 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() : TQString::null); 00094 if (saveflag) triggerSave(); 00095 } 00096 00097 bool KMVirtualManager::isDefault(KMPrinter *p, const TQString& 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 TQString& 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 TQString& src, const TQString& 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 TQString& 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(TQMap<TQString,TQString>()); 00146 printer->setEditedOptions(TQMap<TQString,TQString>()); 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 TQString& name, TQWidget *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 TQString::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 TQFileInfo fi(TQDir::homeDirPath() + TQFile::decodeName("/.cups/lpoptions")); 00183 TQFileInfo fi2(TQFile::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 = TQString::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 TQPtrListIterator<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 TQString KMVirtualManager::defaultPrinterName() 00228 { 00229 return m_defaultprinter; 00230 } 00231 00232 void KMVirtualManager::virtualList(TQPtrList<KMPrinter>& list, const TQString& 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 TQPtrListIterator<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 TQString& filename) 00248 { 00249 TQFile f(filename); 00250 if (f.exists() && f.open(IO_ReadOnly)) 00251 { 00252 TQTextStream t(&f); 00253 00254 TQString line; 00255 TQStringList words; 00256 TQStringList pair; 00257 KMPrinter *printer, *realprinter; 00258 00259 while (!t.eof()) 00260 { 00261 line = t.readLine().stripWhiteSpace(); 00262 if (line.isEmpty()) continue; 00263 words = TQStringList::split(' ',line,false); 00264 if (words.count() < 2) continue; 00265 pair = TQStringList::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 = TQStringList::split('=',words[i],false); 00283 printer->setDefaultOption(pair[0],(pair.count() > 1 ? pair[1] : TQString::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(TQFile::decodeName("/etc/cups"))) 00301 filename = TQFile::decodeName("/etc/cups/lpoptions"); 00302 } 00303 else 00304 { 00305 TQDir cupsDir(TQDir::home().absPath()+"/.cups"); 00306 if (!cupsDir.exists()) 00307 cupsDir.mkdir(TQDir::home().absPath()+"/.cups"); 00308 filename = TQDir::homeDirPath() + TQFile::decodeName("/.cups/lpoptions"); 00309 } 00310 00311 if (!filename.isEmpty()) 00312 { 00313 saveFile(filename); 00314 m_checktime = TQFileInfo(filename).lastModified(); 00315 } 00316 } 00317 00318 void KMVirtualManager::saveFile(const TQString& filename) 00319 { 00320 TQFile f(filename); 00321 if (f.open(IO_WriteOnly)) 00322 { 00323 TQTextStream t(&f); 00324 TQPtrListIterator<KMPrinter> it(m_manager->m_printers); 00325 for (;it.current();++it) 00326 { 00327 if (it.current()->isSpecial()) 00328 { 00329 t << ( it.current()->isSoftDefault() ? "DefaultSpecial " : "Special " ); 00330 t << KURL::encode_string_no_slash( it.current()->printerName() ); 00331 if ( !it.current()->instanceName().isEmpty() ) 00332 t << "/" << KURL::encode_string_no_slash( it.current()->instanceName() ); 00333 } 00334 else 00335 t << (it.current()->isSoftDefault() ? "Default " : "Dest ") << it.current()->name(); 00336 TQMap<TQString,TQString> opts = it.current()->defaultOptions(); 00337 for (TQMap<TQString,TQString>::ConstIterator oit=opts.begin(); oit!=opts.end(); ++oit) 00338 { 00339 t << ' ' << oit.key(); 00340 if (!oit.data().isEmpty()) 00341 t << '=' << oit.data(); 00342 } 00343 t << endl; 00344 } 00345 } 00346 } 00347 00348 bool KMVirtualManager::testInstance(KMPrinter *p) 00349 { 00350 TQString testpage = KMManager::self()->testPage(); 00351 if (testpage.isEmpty()) 00352 return false; 00353 else 00354 { 00355 KPrinter pr; 00356 pr.setPrinterName(p->printerName()); 00357 pr.setSearchName(p->name()); 00358 pr.setOptions(p->defaultOptions()); 00359 return (pr.printFiles(testpage)); 00360 } 00361 } 00362 00363 void KMVirtualManager::reload() 00364 { 00365 reset(); 00366 } 00367 00368 void KMVirtualManager::configChanged() 00369 { 00370 reset(); 00371 }