diff options
Diffstat (limited to 'kdeprint/lpr')
39 files changed, 4838 insertions, 0 deletions
diff --git a/kdeprint/lpr/Makefile.am b/kdeprint/lpr/Makefile.am new file mode 100644 index 000000000..4ee2545ca --- /dev/null +++ b/kdeprint/lpr/Makefile.am @@ -0,0 +1,39 @@ +AM_CPPFLAGS = -D_KDEPRINT_COMPILE + +INCLUDES= -I$(top_srcdir) -I$(top_srcdir)/kdeprint -I$(top_srcdir)/kdeprint/management $(all_includes) + +kde_module_LTLIBRARIES = kdeprint_lpr.la + +kdeprint_lpr_la_SOURCES = printcapreader.cpp lprhandler.cpp \ + matichandler.cpp klprfactory.cpp kmlprmanager.cpp \ + kmlpruimanager.cpp lpchelper.cpp lpqhelper.cpp \ + kmlprjobmanager.cpp matichelper.cpp \ + klprprinterimpl.cpp printcapentry.cpp \ + lprsettings.cpp kmconfiglpr.cpp apshandler.cpp \ + lprngtoolhandler.cpp \ + editentrydialog.cpp +kdeprint_lpr_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined +kdeprint_lpr_la_LIBADD = $(top_builddir)/kdeprint/management/libkdeprint_management.la $(top_builddir)/kdecore/libkdefakes.la +kdeprint_lpr_la_METASOURCES = AUTO + +noinst_HEADERS = printcapreader.h \ + matichandler.h kmlprmanager.h \ + kmlpruimanager.h lpchelper.h lpqhelper.h \ + kmlprjobmanager.h matichelper.h klprprinterimpl.h \ + kmconfiglpr.h apshandler.h \ + lprngtoolhandler.h \ + editentrydialog.h + +kdeprintlpr_HEADERS = printcapentry.h lprhandler.h lprsettings.h +kdeprintlprdir = $(includedir)/kdeprint/lpr + +bin_PROGRAMS = make_driver_db_lpr +make_driver_db_lpr_SOURCES = make_driver_db_lpr.c +make_driver_db_lpr_LDFLAGS = $(all_libraries) +make_driver_db_lpr_LDADD = $(top_builddir)/kdecore/libkdefakes.la ../libdriverparse.a $(LIBDL) + +entry_DATA = lpr.print +entrydir = $(kde_datadir)/kdeprint/plugins + +miscdata_DATA = apsdriver1 apsdriver2 lprngtooldriver1 +miscdatadir = $(kde_datadir)/kdeprint diff --git a/kdeprint/lpr/apsdriver1 b/kdeprint/lpr/apsdriver1 new file mode 100644 index 000000000..fa6bbde0e --- /dev/null +++ b/kdeprint/lpr/apsdriver1 @@ -0,0 +1,84 @@ +GROUP|general|General +OPTION|PAPERSIZE|Page Size +CHOICE|a3|A3 +CHOICE|a4|A4 +CHOICE|legal|US Legal +CHOICE|letter|US Letter +CHOICE|ledger|Ledger +CHOICE|tabloid|Tabloid +DEFAULT|a4 +OPTION|COLOR|Color Mode +CHOICE|full|Color +CHOICE|gray|Grayscale +CHOICE|mono|Monochrome +DEFAULT|full +OPTION|QUALITY|Print Quality +CHOICE|draft|Draft +CHOICE|low|Low +CHOICE|medium|Medium +CHOICE|high|High +CHOICE|photo|Photo +DEFAULT|medium +OPTION|RESOLUTION|Print Resolution +CHOICE|150x150|150 DPI +CHOICE|180x180|180 DPI +CHOICE|300x300|300 DPI +CHOICE|360x180|360x180 DPI +CHOICE|360x360|360 DPI +CHOICE|600x600|600 DPI +CHOICE|720x720|720 DPI +CHOICE|1200x1200|1200 DPI +DEFAULT|300x300 +OPTION|METHOD|Print Method +CHOICE|auto|Automatic file conversion +CHOICE|ascii|Treat everything as text +CHOICE|raw|Pass-through mode +DEFAULT|auto +ENDGROUP| +GROUP|advanced|Advanced Settings +GROUP|paper|Paper Settings +OPTION|MEDIA|paper Type +CHOICE|plain|Plain paper +CHOICE|coated|Coated (InkJet) paper +CHOICE|glossy|Glossy paper +CHOICE|premium|Premium (Photo) paper +CHOICE|trans|Transparencies +CHOICE|(empty)|Default printer setting +DEFAULT|(empty) +OPTION|PAPERTRAY|Input Slot +CHOICE|tray0|Tray 0 +CHOICE|tray1|Tray 1 +CHOICE|tray2|Tray 2 +CHOICE|tray3|Tray 3 +CHOICE|tray4|Tray 4 +CHOICE|tray5|Tray 5 +CHOICE|(empty)|Default printer setting +DEFAULT|(empty) +OPTION|DUPLEX|Duplex Printing|BOOLEAN +CHOICE|true|Enabled +CHOICE|false|Disabled +DEFAULT|false +OPTION|BINDING|Paper Binding Edge +CHOICE|short|Short edge +CHOICE|long|Long edge +CHOICE|(empty)|Default printer setting +DEFAULT|(empty) +ENDGROUP| +GROUP|text|File Conversion Settings +OPTION|ASCII_HEADER|Text Header|BOOLEAN +CHOICE|true|Enabled +CHOICE|false|Disabled +DEFAULT|false +OPTION|ASCII_BORDER|Text Border|BOOLEAN +CHOICE|true|Enabled +CHOICE|false|Disabled +DEFAULT|false +OPTION|PRINT_DVI|DVI file converter|STRING +ENDGROUP| +GROUP|gs|Ghostscript Settings +OPTION|GS_FEATURES|Ghostscript options|STRING +OPTION|PS_INIT|Initialisation file|STRING +OPTION|PS_EXIT|Cleanup file|STRING +OPTION|POST_FILTER_OPTS|Post-Ghostscript filter options|STRING +ENDGROUP| +ENDGROUP| diff --git a/kdeprint/lpr/apsdriver2 b/kdeprint/lpr/apsdriver2 new file mode 100644 index 000000000..69d355f6c --- /dev/null +++ b/kdeprint/lpr/apsdriver2 @@ -0,0 +1,83 @@ +GROUP|general|General +OPTION|PageSize|Page Size +CHOICE|a3|A3 +CHOICE|a4|A4 +CHOICE|legal|US Legal +CHOICE|letter|US Letter +CHOICE|ledger|Ledger +CHOICE|tabloid|Tabloid +DEFAULT|a4 +OPTION|MEDIA|Paper Type +CHOICE|plain|Plain paper +CHOICE|coated|Coated (InkJet) paper +CHOICE|glossy|Glossy paper +CHOICE|premium|Premium (Photo) paper +CHOICE|trans|Transparencies +CHOICE|(empty)|Default setting +DEFAULT|(empty) +OPTION|PAPERTRAY|Input Tray +CHOICE|tray0|Tray 0 +CHOICE|tray1|Tray 1 +CHOICE|tray2|Tray 2 +CHOICE|tray3|Tray 3 +CHOICE|tray4|Tray 4 +CHOICE|tray5|Tray 5 +CHOICE|(empty)|Default setting +DEFAULT|(empty) +ENDGROUP| +GROUP|others|Others +OPTION|COLOR|Color Mode +CHOICE|color|Color +CHOICE|gray|Grayscale +CHOICE|mono|Monochrome +CHOICE|(empty)|Default setting +DEFAULT|(empty) +OPTION|DUPLEX|Duplex Printing +CHOICE|duplex|Enabled +CHOICE|simplex|Disabled +CHOICE|(empty)|Default setting +DEFAULT|(empty) +OPTION|BINDING|Paper Binding Edge +CHOICE|shortbind|Short edge +CHOICE|longbind|Long edge +CHOICE|(empty)|Default setting +DEFAULT|(empty) +OPTION|QUALITY|Printing Quality +CHOICE|draft|Draft +CHOICE|low|Low +CHOICE|medium|Medium +CHOICE|high|High +CHOICE|photo|Photo +CHOICE|(empty)|Default setting +DEFAULT|(empty) +OPTION|PS_NUP|Pages per Sheet +CHOICE|1pps|1 +CHOICE|2pps|2 +CHOICE|4pps|4 +CHOICE|8pps|8 +DEFAULT|1pps +OPTION|SWEEP|Communication Type +CHOICE|uni|Unidirectional +CHOICE|bi|Bidirectional +CHOICE|(empty)|Default setting +DEFAULT|(empty) +ENDGROUP| +GROUP|text|Text Printing +OPTION|ASCII_FILTER|Text Converter +CHOICE|a2ps|a2ps +CHOICE|mpage|mpage +CHOICE|enscript|enscript +CHOICE|recode|recode +CHOICE|(empty)|Default setting +DEFAULT|(empty) +OPTION|ASCII_HEADER|Header +CHOICE|header|Enabled +CHOICE|noheader|Disabled +CHOICE|(empty)|Default setting +DEFAULT|(empty) +OPTION|ASCII_BORDER|Border +CHOICE|border|Enabled +CHOICE|noborder|Disabled +CHOICE|(empty)|Default setting +DEFAULT|(empty) +ENDGROUP| diff --git a/kdeprint/lpr/apshandler.cpp b/kdeprint/lpr/apshandler.cpp new file mode 100644 index 000000000..5b7bef943 --- /dev/null +++ b/kdeprint/lpr/apshandler.cpp @@ -0,0 +1,405 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "apshandler.h" +#include "driver.h" +#include "printcapentry.h" +#include "kmprinter.h" +#include "lprsettings.h" +#include "kmmanager.h" +#include "util.h" +#include "kprinter.h" + +#include <qfile.h> +#include <qdir.h> +#include <qtextstream.h> +#include <qvaluestack.h> +#include <kstandarddirs.h> +#include <klocale.h> +#include <kdebug.h> + +#include <sys/types.h> +#include <sys/stat.h> + +ApsHandler::ApsHandler(KMManager *mgr) +: LprHandler("apsfilter", mgr) +{ + m_counter = 1; +} + +bool ApsHandler::validate(PrintcapEntry *entry) +{ + return (entry->field("if").right(9) == "apsfilter"); +} + +KMPrinter* ApsHandler::createPrinter(PrintcapEntry *entry) +{ + entry->comment = QString::fromLatin1("# APS%1_BEGIN:printer%2").arg(m_counter).arg(m_counter); + entry->postcomment = QString::fromLatin1("# APS%1_END - don't delete this").arg(m_counter); + m_counter++; + return LprHandler::createPrinter(entry); +} + +bool ApsHandler::completePrinter(KMPrinter *prt, PrintcapEntry *entry, bool shortmode) +{ + if (LprHandler::completePrinter(prt, entry, shortmode)) + { + if (!shortmode) + { + QMap<QString,QString> opts = loadResources(entry); + if (opts.contains("PRINTER")) + { + prt->setDescription(i18n("APS Driver (%1)").arg(opts["PRINTER"])); + prt->setDriverInfo(prt->description()); + } + } + if (prt->device().isEmpty()) + { + QString prot; + QString smbname(sysconfDir() + "/" + prt->printerName() + "/smbclient.conf"); + QString ncpname(sysconfDir() + "/" + prt->printerName() + "/netware.conf"); + if (QFile::exists(smbname)) + { + QMap<QString,QString> opts = loadVarFile(smbname); + if (opts.count() == 0) + prt->setDevice("smb://<unknown>/<unknown>"); + else + { + prt->setDevice(buildSmbURI( + opts[ "SMB_WORKGROUP" ], + opts[ "SMB_SERVER" ], + opts[ "SMB_PRINTER" ], + opts[ "SMB_USER" ], + opts[ "SMB_PASSWD" ] ) ); + } + prot = "smb"; + } + else if (QFile::exists(ncpname)) + { + QMap<QString,QString> opts = loadVarFile(ncpname); + if (opts.count() == 0) + prt->setDevice("ncp://<unknown>/<unknown>"); + else + { + QString uri = buildSmbURI( + QString::null, + opts[ "NCP_SERVER" ], + opts[ "NCP_PRINTER" ], + opts[ "NCP_USER" ], + opts[ "NCP_PASSWD" ] ); + uri.replace( 0, 3, "ncp" ); + prt->setDevice(uri); + } + prot = "ncp"; + } + if (!prt->device().isEmpty()) + prt->setLocation(i18n("Network printer (%1)").arg(prot)); + } + return true; + } + return false; +} + +QString ApsHandler::sysconfDir() +{ + return QFile::encodeName("/etc/apsfilter"); +} + +QString ApsHandler::shareDir() +{ + return driverDirectory(); +} + +QString ApsHandler::driverDirInternal() +{ + return locateDir("apsfilter/setup", "/usr/share:/usr/local/share:/opt/share"); +} + +QMap<QString,QString> ApsHandler::loadResources(PrintcapEntry *entry) +{ + return loadVarFile(sysconfDir() + "/" + (entry ? entry->name : QString::null) + "/apsfilterrc"); +} + +QMap<QString,QString> ApsHandler::loadVarFile(const QString& filename) +{ + QMap<QString,QString> opts; + QFile f(filename); + if (f.open(IO_ReadOnly)) + { + QTextStream t(&f); + QString line; + int p(-1); + while (!t.atEnd()) + { + line = t.readLine().stripWhiteSpace(); + if (line.isEmpty() || line[0] == '#' || (p = line.find('=')) == -1) + continue; + QString variable = line.left(p).stripWhiteSpace(); + QString value = line.mid(p+1).stripWhiteSpace(); + if (!value.isEmpty() && value[0] == '\'') + value = value.mid(1, value.length()-2); + opts[variable] = value; + } + } + return opts; +} + +DrMain* ApsHandler::loadDriver(KMPrinter *prt, PrintcapEntry *entry, bool config) +{ + DrMain *driver = loadApsDriver(config); + if (driver /* && config */ ) // Load resources in all case, to get the correct page size + { + QMap<QString,QString> opts = loadResources(entry); + if ( !config && opts.contains( "PAPERSIZE" ) ) + { + // this is needed to keep applications informed + // about the current selected page size + opts[ "PageSize" ] = opts[ "PAPERSIZE" ]; + + // default page size needs to be set to the actual + // value of the printer driver, otherwise it's blocked + // to A4 + DrBase *opt = driver->findOption( "PageSize" ); + if ( opt ) + opt->set( "default", opts[ "PageSize" ] ); + } + driver->setOptions(opts); + driver->set("gsdriver", opts["PRINTER"]); + } + return driver; +} + +DrMain* ApsHandler::loadDbDriver(const QString& s) +{ + int p = s.find('/'); + DrMain *driver = loadApsDriver(true); + if (driver) + driver->set("gsdriver", s.mid(p+1)); + return driver; +} + +DrMain* ApsHandler::loadApsDriver(bool config) +{ + DrMain *driver = loadToolDriver(locate("data", (config ? "kdeprint/apsdriver1" : "kdeprint/apsdriver2"))); + if (driver) + driver->set("text", "APS Common Driver"); + return driver; +} + +void ApsHandler::reset() +{ + m_counter = 1; +} + +PrintcapEntry* ApsHandler::createEntry(KMPrinter *prt) +{ + QString prot = prt->deviceProtocol(); + if (prot != "parallel" && prot != "lpd" && prot != "smb" && prot != "ncp") + { + manager()->setErrorMsg(i18n("Unsupported backend: %1.").arg(prot)); + return NULL; + } + QString path = sysconfDir() + "/" + prt->printerName(); + if (!KStandardDirs::makeDir(path, 0755)) + { + manager()->setErrorMsg(i18n("Unable to create directory %1.").arg(path)); + return NULL; + } + if (prot == "smb" || prot == "ncp") + { + // either "smb" or "ncp" + QFile::remove(path + "/smbclient.conf"); + QFile::remove(path + "/netware.conf"); + QFile f; + if (prot == "smb") + { + f.setName(path + "/smbclient.conf"); + if (f.open(IO_WriteOnly)) + { + QTextStream t(&f); + QString work, server, printer, user, passwd; + if ( splitSmbURI( prt->device(), work, server, printer, user, passwd ) ) + { + if (work.isEmpty()) + { + manager()->setErrorMsg(i18n("Missing element: %1.").arg("Workgroup")); + return NULL; + } + t << "SMB_SERVER='" << server << "'" << endl; + t << "SMB_PRINTER='" << printer << "'" << endl; + t << "SMB_IP=''" << endl; + t << "SMB_WORKGROUP='" << work << "'" << endl; + t << "SMB_BUFFER=1400" << endl; + t << "SMB_FLAGS='-N'" << endl; + if (!user.isEmpty()) + { + t << "SMB_USER='" << user << "'" << endl; + t << "SMB_PASSWD='" << passwd << "'" << endl; + } + } + else + { + manager()->setErrorMsg( i18n( "Invalid printer backend specification: %1" ).arg( prt->device() ) ); + return NULL; + } + } + else + { + manager()->setErrorMsg(i18n("Unable to create the file %1.").arg(f.name())); + return NULL; + } + } + else + { + f.setName(path + "/netware.conf"); + if (f.open(IO_WriteOnly)) + { + QString work, server, printer, user, passwd; + QString uri = prt->device(); + uri.replace( 0, 3, "smb" ); + if ( splitSmbURI( uri, work, server, printer, user, passwd ) ) + { + QTextStream t(&f); + t << "NCP_SERVER='" << server << "'" << endl; + t << "NCP_PRINTER='" << printer << "'" << endl; + if (!user.isEmpty()) + { + t << "NCP_USER='" << user << "'" << endl; + t << "NCP_PASSWD='" << passwd << "'" << endl; + } + } + else + { + manager()->setErrorMsg( i18n( "Invalid printer backend specification: %1" ).arg( prt->device() ) ); + return NULL; + } + } + else + { + manager()->setErrorMsg(i18n("Unable to create the file %1.").arg(f.name())); + return NULL; + } + } + // change file permissions + ::chmod(QFile::encodeName(f.name()).data(), S_IRUSR|S_IWUSR); + } + PrintcapEntry *entry = LprHandler::createEntry(prt); + if (!entry) + { + entry = new PrintcapEntry; + entry->addField("lp", Field::String, "/dev/null"); + } + QString sd = LprSettings::self()->baseSpoolDir() + "/" + prt->printerName(); + entry->addField("af", Field::String, sd + "/acct"); + entry->addField("lf", Field::String, sd + "/log"); + entry->addField("if", Field::String, sysconfDir() + "/basedir/bin/apsfilter"); + entry->comment = QString::fromLatin1("# APS%1_BEGIN:printer%2").arg(m_counter).arg(m_counter); + entry->postcomment = QString::fromLatin1("# APS%1_END").arg(m_counter); + m_counter++; + return entry; +} + +bool ApsHandler::savePrinterDriver(KMPrinter *prt, PrintcapEntry *entry, DrMain *driver, bool*) +{ + if (driver->get("gsdriver").isEmpty()) + { + manager()->setErrorMsg(i18n("The APS driver is not defined.")); + return false; + } + QFile f(sysconfDir() + "/" + prt->printerName() + "/apsfilterrc"); + if (f.open(IO_WriteOnly)) + { + QTextStream t(&f); + t << "# File generated by KDEPrint" << endl; + t << "PRINTER='" << driver->get("gsdriver") << "'" << endl; + QValueStack<DrGroup*> stack; + stack.push(driver); + while (stack.count() > 0) + { + DrGroup *grp = stack.pop(); + QPtrListIterator<DrGroup> git(grp->groups()); + for (; git.current(); ++git) + stack.push(git.current()); + QPtrListIterator<DrBase> oit(grp->options()); + QString value; + for (; oit.current(); ++oit) + { + value = oit.current()->valueText(); + switch (oit.current()->type()) + { + case DrBase::Boolean: + if (value == "true") + t << oit.current()->name() << "='" << value << "'" << endl; + break; + case DrBase::List: + if (value != "(empty)") + t << oit.current()->name() << "='" << value << "'" << endl; + break; + case DrBase::String: + if (!value.isEmpty()) + t << oit.current()->name() << "='" << value << "'" << endl; + break; + default: + break; + } + } + } + return true; + } + else + { + manager()->setErrorMsg(i18n("Unable to create the file %1.").arg(f.name())); + return false; + } +} + +bool ApsHandler::removePrinter(KMPrinter*, PrintcapEntry *entry) +{ + QString path(sysconfDir() + "/" + entry->name); + QFile::remove(path + "/smbclient.conf"); + QFile::remove(path + "/netware.conf"); + QFile::remove(path + "/apsfilterrc"); + if (!QDir(path).rmdir(path)) + { + manager()->setErrorMsg(i18n("Unable to remove directory %1.").arg(path)); + return false; + } + return true; +} + +QString ApsHandler::printOptions(KPrinter *printer) +{ + QString optstr; + QMap<QString,QString> opts = printer->options(); + for (QMap<QString,QString>::ConstIterator it=opts.begin(); it!=opts.end(); ++it) + { + if (it.key().startsWith("kde-") || it.key().startsWith("_kde-") || it.key().startsWith( "app-" )) + continue; + optstr.append((*it)).append(":"); + } + if (!optstr.isEmpty()) + { + optstr = optstr.left(optstr.length()-1); + if (LprSettings::self()->mode() == LprSettings::LPR) + optstr.prepend("-C '").append("'"); + else + optstr.prepend("-Z '").append("'"); + } + return optstr; +} diff --git a/kdeprint/lpr/apshandler.h b/kdeprint/lpr/apshandler.h new file mode 100644 index 000000000..58e6b8878 --- /dev/null +++ b/kdeprint/lpr/apshandler.h @@ -0,0 +1,57 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef APSHANDLER_H +#define APSHANDLER_H + +#include "lprhandler.h" + +#include <qmap.h> + +class ApsHandler : public LprHandler +{ +public: + ApsHandler(KMManager*); + + bool validate(PrintcapEntry*); + KMPrinter* createPrinter(PrintcapEntry*); + bool completePrinter(KMPrinter*, PrintcapEntry*, bool = true); + DrMain* loadDriver(KMPrinter*, PrintcapEntry*, bool = false); + DrMain* loadDbDriver(const QString&); + void reset(); + PrintcapEntry* createEntry(KMPrinter*); + bool savePrinterDriver(KMPrinter*, PrintcapEntry*, DrMain*, bool* = 0); + bool removePrinter(KMPrinter*, PrintcapEntry*); + QString printOptions(KPrinter*); + +protected: + QString driverDirInternal(); + +private: + QMap<QString,QString> loadResources(PrintcapEntry*); + QMap<QString,QString> loadVarFile(const QString&); + QString sysconfDir(); + QString shareDir(); + DrMain* loadApsDriver(bool = false); + +private: + int m_counter; +}; + +#endif diff --git a/kdeprint/lpr/editentrydialog.cpp b/kdeprint/lpr/editentrydialog.cpp new file mode 100644 index 000000000..270b58235 --- /dev/null +++ b/kdeprint/lpr/editentrydialog.cpp @@ -0,0 +1,157 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "editentrydialog.h" + +#include <qlineedit.h> +#include <qcheckbox.h> +#include <qspinbox.h> +#include <qcombobox.h> +#include <qlabel.h> +#include <qheader.h> +#include <klistview.h> +#include <qlayout.h> +#include <qwidgetstack.h> +#include <klocale.h> +#include <kiconloader.h> + +EditEntryDialog::EditEntryDialog(PrintcapEntry *entry, QWidget *parent, const char *name) +: KDialogBase(parent, name, true, QString::null, Ok|Cancel) +{ + QWidget *w = new QWidget(this); + setMainWidget(w); + + QLabel *lab0 = new QLabel(i18n("Aliases:"), w); + m_aliases = new QLineEdit(w); + m_view = new KListView(w); + m_view->addColumn(""); + m_view->header()->hide(); + m_type = new QComboBox(w); + m_type->insertItem(i18n("String")); + m_type->insertItem(i18n("Number")); + m_type->insertItem(i18n("Boolean")); + m_stack = new QWidgetStack(w); + m_boolean = new QCheckBox(i18n("Enabled"), m_stack); + m_string = new QLineEdit(m_stack); + m_number = new QSpinBox(0, 9999, 1, m_stack); + m_stack->addWidget(m_string, 0); + m_stack->addWidget(m_boolean, 2); + m_stack->addWidget(m_number, 1); + m_name = new QLineEdit(w); + + QVBoxLayout *l0 = new QVBoxLayout(w, 0, 10); + QHBoxLayout *l1 = new QHBoxLayout(0, 0, 10); + QHBoxLayout *l2 = new QHBoxLayout(0, 0, 5); + l0->addLayout(l1); + l1->addWidget(lab0); + l1->addWidget(m_aliases); + l0->addWidget(m_view); + l0->addLayout(l2); + l2->addWidget(m_name, 0); + l2->addWidget(m_type, 0); + l2->addWidget(m_stack, 1); + + if (entry) + { + setCaption(i18n("Printcap Entry: %1").arg(entry->name)); + m_fields = entry->fields; + m_aliases->setText(entry->aliases.join("|")); + QListViewItem *root = new QListViewItem(m_view, entry->name), *item = 0; + root->setSelectable(false); + root->setOpen(true); + root->setPixmap(0, SmallIcon("fileprint")); + for (QMap<QString,Field>::ConstIterator it=m_fields.begin(); it!=m_fields.end(); ++it) + item = new QListViewItem(root, item, (*it).toString(), it.key()); + } + + m_block = true; + enableButton(Ok, false); + slotItemSelected(NULL); + slotTypeChanged(0); + m_block = false; + + connect(m_view, SIGNAL(selectionChanged(QListViewItem*)), SLOT(slotItemSelected(QListViewItem*))); + connect(m_string, SIGNAL(textChanged(const QString&)), SLOT(slotChanged())); + connect(m_boolean, SIGNAL(toggled(bool)), SLOT(slotChanged())); + connect(m_number, SIGNAL(valueChanged(int)), SLOT(slotChanged())); + connect(m_type, SIGNAL(activated(int)), SLOT(slotTypeChanged(int))); + connect(m_name, SIGNAL(textChanged(const QString&)), SLOT(slotChanged())); + + resize(500,400); +} + +Field EditEntryDialog::createField() +{ + Field f; + f.name = m_name->text(); + f.type = (Field::Type)(m_type->currentItem()); + switch (f.type) + { + case Field::String: f.value = m_string->text(); break; + case Field::Integer: f.value = m_number->cleanText(); break; + case Field::Boolean: f.value = (m_boolean->isChecked() ? "1" : "0"); break; + } + return f; +} + +void EditEntryDialog::slotChanged() +{ + if (!m_block && m_view->currentItem()) + { + Field f = createField(); + if (f.name != m_current) + m_fields.remove(m_current); + m_fields[f.name] = f; + m_view->currentItem()->setText(0, f.toString()); + } +} + +void EditEntryDialog::slotItemSelected(QListViewItem *item) +{ + m_stack->setEnabled(item); + m_name->setEnabled(item); + m_type->setEnabled(item); + if (item) + { + m_block = true; + m_current = item->text(1); + Field f = m_fields[m_current]; + m_name->setText(f.name); + m_type->setCurrentItem(f.type); + slotTypeChanged(f.type); + m_string->setText(f.value); + m_number->setValue(f.value.toInt()); + m_boolean->setChecked(f.value.toInt() == 1); + m_block = false; + } +} + +void EditEntryDialog::fillEntry(PrintcapEntry *entry) +{ + entry->aliases = QStringList::split('|', m_aliases->text(), false); + entry->fields = m_fields; +} + +void EditEntryDialog::slotTypeChanged(int ID) +{ + m_stack->raiseWidget(ID); + slotChanged(); +} + +#include "editentrydialog.moc" diff --git a/kdeprint/lpr/editentrydialog.h b/kdeprint/lpr/editentrydialog.h new file mode 100644 index 000000000..906bc45db --- /dev/null +++ b/kdeprint/lpr/editentrydialog.h @@ -0,0 +1,62 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef EDITENTRYDIALOG_H +#define EDITENTRYDIALOG_H + +#include <kdialogbase.h> +#include "printcapentry.h" + +class QLineEdit; +class QCheckBox; +class QSpinBox; +class QComboBox; +class QListView; +class QListviewItem; +class QWidgetStack; + +class EditEntryDialog : public KDialogBase +{ + Q_OBJECT +public: + EditEntryDialog(PrintcapEntry *entry, QWidget *parent = 0, const char *name = 0); + + void fillEntry(PrintcapEntry *entry); + +protected slots: + void slotItemSelected(QListViewItem*); + void slotChanged(); + void slotTypeChanged(int); + +protected: + Field createField(); + +private: + QMap<QString,Field> m_fields; + QLineEdit *m_name, *m_string, *m_aliases; + QCheckBox *m_boolean; + QComboBox *m_type; + QSpinBox *m_number; + QListView *m_view; + QWidgetStack *m_stack; + QString m_current; + bool m_block; +}; + +#endif diff --git a/kdeprint/lpr/klprfactory.cpp b/kdeprint/lpr/klprfactory.cpp new file mode 100644 index 000000000..86666981e --- /dev/null +++ b/kdeprint/lpr/klprfactory.cpp @@ -0,0 +1,29 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "kmlprmanager.h" +#include "kmlpruimanager.h" +#include "kmlprjobmanager.h" +#include "klprprinterimpl.h" + +#include <kgenericfactory.h> + +typedef K_TYPELIST_4( KMLprManager, KMLprUiManager, KMLprJobManager, KLprPrinterImpl ) Products; +K_EXPORT_COMPONENT_FACTORY( kdeprint_lpr, KGenericFactory< Products > ) + diff --git a/kdeprint/lpr/klprprinterimpl.cpp b/kdeprint/lpr/klprprinterimpl.cpp new file mode 100644 index 000000000..f6f416376 --- /dev/null +++ b/kdeprint/lpr/klprprinterimpl.cpp @@ -0,0 +1,59 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "klprprinterimpl.h" +#include "kprinter.h" +#include "kmlprmanager.h" + +#include <kstandarddirs.h> +#include <qfile.h> +#include <stdlib.h> + +KLprPrinterImpl::KLprPrinterImpl(QObject *parent, const char *name, const QStringList & /*args*/) +: KPrinterImpl(parent,name) +{ + m_exepath = KStandardDirs::findExe("lpr"); +} + +KLprPrinterImpl::~KLprPrinterImpl() +{ +} + +bool KLprPrinterImpl::setupCommand(QString& cmd, KPrinter *printer) +{ + // check printer object + if (!printer || m_exepath.isEmpty()) + return false; + + cmd = QString::fromLatin1("%1 -P %1 '-#%1'").arg(m_exepath).arg(quote(printer->printerName())).arg( printer->numCopies() ); + QString opts = static_cast<KMLprManager*>(KMManager::self())->printOptions(printer); + if (!opts.isEmpty()) + cmd += (" " + opts); + return true; +} + +void KLprPrinterImpl::broadcastOption(const QString& key, const QString& value) +{ + KPrinterImpl::broadcastOption(key,value); + if (key == "kde-pagesize") + { + QString pagename = QString::fromLatin1(pageSizeToPageName((KPrinter::PageSize)value.toInt())); + KPrinterImpl::broadcastOption("PageSize",pagename); + } +} diff --git a/kdeprint/lpr/klprprinterimpl.h b/kdeprint/lpr/klprprinterimpl.h new file mode 100644 index 000000000..e603e9396 --- /dev/null +++ b/kdeprint/lpr/klprprinterimpl.h @@ -0,0 +1,38 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef KLPRPRINTERIMPL_H +#define KLPRPRINTERIMPL_H + +#include "kprinterimpl.h" + +class KLprPrinterImpl : public KPrinterImpl +{ +public: + KLprPrinterImpl(QObject *parent, const char *name, const QStringList & /*args*/); + ~KLprPrinterImpl(); + + bool setupCommand(QString&, KPrinter*); + void broadcastOption(const QString& key, const QString& value); + +private: + QString m_exepath; +}; + +#endif diff --git a/kdeprint/lpr/kmconfiglpr.cpp b/kdeprint/lpr/kmconfiglpr.cpp new file mode 100644 index 000000000..ccf6a71a1 --- /dev/null +++ b/kdeprint/lpr/kmconfiglpr.cpp @@ -0,0 +1,66 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "kmconfiglpr.h" +#include "lprsettings.h" + +#include <qcombobox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qgroupbox.h> +#include <klocale.h> +#include <kconfig.h> + +KMConfigLpr::KMConfigLpr(QWidget *parent, const char *name) +: KMConfigPage(parent, name) +{ + setPageName(i18n("Spooler")); + setPageHeader(i18n("Spooler Settings")); + setPagePixmap("gear"); + + QGroupBox *m_modebox = new QGroupBox(1, Qt::Vertical, i18n("Spooler"), this); + + m_mode = new QComboBox(m_modebox); + m_mode->insertItem("LPR (BSD compatible)"); + m_mode->insertItem("LPRng"); + + QVBoxLayout *l0 = new QVBoxLayout(this, 5, 10); + l0->addWidget(m_modebox); + l0->addStretch(1); +} + +void KMConfigLpr::loadConfig(KConfig*) +{ + m_mode->setCurrentItem(LprSettings::self()->mode()); +} + +void KMConfigLpr::saveConfig(KConfig *conf) +{ + LprSettings::self()->setMode((LprSettings::Mode)(m_mode->currentItem())); + + QString modestr; + switch (m_mode->currentItem()) + { + default: + case 0: modestr = "LPR"; break; + case 1: modestr = "LPRng"; break; + } + conf->setGroup("LPR"); + conf->writeEntry("Mode", modestr); +} diff --git a/kdeprint/lpr/kmconfiglpr.h b/kdeprint/lpr/kmconfiglpr.h new file mode 100644 index 000000000..26538eb8f --- /dev/null +++ b/kdeprint/lpr/kmconfiglpr.h @@ -0,0 +1,39 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef KMCONFIGLPR_H +#define KMCONFIGLPR_H + +#include "kmconfigpage.h" + +class QComboBox; + +class KMConfigLpr : public KMConfigPage +{ +public: + KMConfigLpr(QWidget *parent = 0, const char *name = 0); + + void loadConfig(KConfig*); + void saveConfig(KConfig*); + +private: + QComboBox *m_mode; +}; + +#endif diff --git a/kdeprint/lpr/kmlprjobmanager.cpp b/kdeprint/lpr/kmlprjobmanager.cpp new file mode 100644 index 000000000..d60a41020 --- /dev/null +++ b/kdeprint/lpr/kmlprjobmanager.cpp @@ -0,0 +1,90 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "kmlprjobmanager.h" +#include "kmlprmanager.h" +#include "lpqhelper.h" +#include "lpchelper.h" +#include "kmjob.h" +#include "lprsettings.h" + +#include <qptrlist.h> +#include <klocale.h> + +KMLprJobManager::KMLprJobManager(QObject *parent, const char *name, const QStringList & /*args*/) +: KMJobManager(parent, name) +{ + m_lpqhelper = new LpqHelper(this, "LpqHelper"); +} + +bool KMLprJobManager::listJobs(const QString& prname, JobType, int limit) +{ + QPtrList<KMJob> jobList; + jobList.setAutoDelete(false); + m_lpqhelper->listJobs(jobList, prname, limit); + QPtrListIterator<KMJob> it(jobList); + for (; it.current(); ++it) + addJob(it.current()); + return false; +} + +LpcHelper* KMLprJobManager::lpcHelper() +{ + return static_cast<KMLprManager*>(KMManager::self())->lpcHelper(); +} + +int KMLprJobManager::actions() +{ + if (LprSettings::self()->mode() == LprSettings::LPR) + return KMJob::Remove; + else + // some additional actions to be added here + return (KMJob::Remove | KMJob::Hold | KMJob::Resume); +} + +bool KMLprJobManager::sendCommandSystemJob(const QPtrList<KMJob>& jobs, int action, const QString& arg) +{ + QString msg; + QPtrListIterator<KMJob> it(jobs); + bool status(true); + LpcHelper *helper = lpcHelper(); + + for (; it.current() && status; ++it) + { + switch (action) + { + case KMJob::Remove: + status = helper->removeJob(it.current(), msg); + break; + case KMJob::Hold: + status = helper->changeJobState(it.current(), KMJob::Held, msg); + break; + case KMJob::Resume: + status = helper->changeJobState(it.current(), KMJob::Queued, msg); + break; + default: + status = false; + msg = i18n("Unsupported operation."); + break; + } + } + if (!status && !msg.isEmpty()) + KMManager::self()->setErrorMsg(msg); + return status; +} diff --git a/kdeprint/lpr/kmlprjobmanager.h b/kdeprint/lpr/kmlprjobmanager.h new file mode 100644 index 000000000..555b5e75b --- /dev/null +++ b/kdeprint/lpr/kmlprjobmanager.h @@ -0,0 +1,44 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef KMLPRJOBMANAGER_H +#define KMLPRJOBMANAGER_H + +#include "kmjobmanager.h" + +class LpqHelper; +class LpcHelper; + +class KMLprJobManager : public KMJobManager +{ +public: + KMLprJobManager(QObject *parent, const char *name, const QStringList & /*args*/); + + int actions(); + +protected: + bool listJobs(const QString&, JobType, int = 0); + LpcHelper* lpcHelper(); + bool sendCommandSystemJob(const QPtrList<KMJob>&, int, const QString& = QString::null); + +private: + LpqHelper *m_lpqhelper; +}; + +#endif diff --git a/kdeprint/lpr/kmlprmanager.cpp b/kdeprint/lpr/kmlprmanager.cpp new file mode 100644 index 000000000..e383bca2f --- /dev/null +++ b/kdeprint/lpr/kmlprmanager.cpp @@ -0,0 +1,492 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "kmlprmanager.h" +#include "printcapreader.h" +#include "printcapentry.h" +#include "lpchelper.h" +#include "matichandler.h" +#include "apshandler.h" +#include "lprngtoolhandler.h" +#include "lprsettings.h" +#include "driver.h" +#include "editentrydialog.h" + +#include <qfileinfo.h> +#include <qptrlist.h> +#include <klocale.h> +#include <kstandarddirs.h> +#include <kdebug.h> +#include <kprinter.h> +#include <kprocess.h> +#include <kaction.h> +#include <kmessagebox.h> +#include <klibloader.h> + +#include <stdlib.h> +#include <unistd.h> + +KMLprManager::KMLprManager(QObject *parent, const char *name, const QStringList & /*args*/) +: KMManager(parent,name) +{ + m_handlers.setAutoDelete(true); + m_handlerlist.setAutoDelete(false); + m_entries.setAutoDelete(true); + + m_lpchelper = new LpcHelper(this); + m_currentprinter = 0; + + setHasManagement(getuid() == 0); + setPrinterOperationMask( + KMManager::PrinterEnabling | + KMManager::PrinterConfigure | + KMManager::PrinterTesting | + KMManager::PrinterCreation | + KMManager::PrinterRemoval | + KMManager::PrinterTesting + ); + + initHandlers(); +} + +void KMLprManager::listPrinters() +{ + QFileInfo fi(LprSettings::self()->printcapFile()); + + if (m_lpchelper) + m_lpchelper->updateStates(); + + // update only if needed + if (!m_updtime.isValid() || m_updtime < fi.lastModified()) + { + // cleanup previous entries + m_entries.clear(); + // notify handlers + QPtrListIterator<LprHandler> hit(m_handlerlist); + for (; hit.current(); ++hit) + hit.current()->reset(); + + // try to open the printcap file and parse it + PrintcapReader reader; + QFile f(fi.absFilePath()); + PrintcapEntry *entry; + if (f.exists() && f.open(IO_ReadOnly)) + { + reader.setPrintcapFile(&f); + while ((entry = reader.nextEntry()) != NULL) + { + QPtrListIterator<LprHandler> it(m_handlerlist); + for (; it.current(); ++it) + if (it.current()->validate(entry)) + { + KMPrinter *prt = it.current()->createPrinter(entry); + checkPrinterState(prt); + prt->setOption("kde-lpr-handler", it.current()->name()); + addPrinter(prt); + break; + } + m_entries.insert(entry->name, entry); + } + } + + // save update time + m_updtime = fi.lastModified(); + } + else + { + QPtrListIterator<KMPrinter> it(m_printers); + for (; it.current(); ++it) + if (!it.current()->isSpecial()) + { + it.current()->setDiscarded(false); + checkPrinterState(it.current()); + } + } +} + +void KMLprManager::insertHandler(LprHandler *handler) +{ + m_handlers.insert(handler->name(), handler); + m_handlerlist.append(handler); + kdDebug() << "Handler: " << handler->name() << endl; +} + +void KMLprManager::initHandlers() +{ + m_handlers.clear(); + m_handlerlist.clear(); + + insertHandler(new MaticHandler(this)); + insertHandler(new ApsHandler(this)); + insertHandler(new LPRngToolHandler(this)); + + // now load external handlers + QStringList l = KGlobal::dirs()->findAllResources("data", "kdeprint/lpr/*.la"); + for (QStringList::ConstIterator it=l.begin(); it!=l.end(); ++it) + { + KLibrary *library = KLibLoader::self()->library(QFile::encodeName(*it)); + if (library) + { + kdDebug() << "loading external handler from " << *it << endl; + LprHandler*(*func)(KMManager*) = (LprHandler*(*)(KMManager*))(library->symbol("create_handler")); + if (func) + insertHandler(func(this)); + else + kdDebug() << "couldn't find the symbol 'create_handler'" << endl; + } + } + + // default handler + insertHandler(new LprHandler("default", this)); +} + +LprHandler* KMLprManager::findHandler(KMPrinter *prt) +{ + QString handlerstr(prt->option("kde-lpr-handler")); + LprHandler *handler(0); + if (handlerstr.isEmpty() || (handler = m_handlers.find(handlerstr)) == NULL) + { + return NULL; + } + return handler; +} + +PrintcapEntry* KMLprManager::findEntry(KMPrinter *prt) +{ + PrintcapEntry *entry = m_entries.find(prt->printerName()); + if (!entry) + { + return NULL; + } + return entry; +} + +bool KMLprManager::completePrinter(KMPrinter *prt) +{ + LprHandler *handler = findHandler(prt); + PrintcapEntry *entry = findEntry(prt); + if (handler && entry) + return handler->completePrinter(prt, entry, false); + return false; +} + +bool KMLprManager::completePrinterShort(KMPrinter *prt) +{ + LprHandler *handler = findHandler(prt); + PrintcapEntry *entry = findEntry(prt); + if (!handler || !entry) + return false; + + return handler->completePrinter(prt, entry, true); +} + +void KMLprManager::checkPrinterState(KMPrinter *prt) +{ + if (m_lpchelper) + { + KMPrinter::PrinterState st = m_lpchelper->state(prt); + prt->setState(st); + prt->setAcceptJobs(!(st & KMPrinter::Rejecting)); + } + else + { + prt->setState(KMPrinter::Idle); + prt->setAcceptJobs(true); + } +} + +DrMain* KMLprManager::loadPrinterDriver(KMPrinter *prt, bool config) +{ + if (!prt) + return NULL; + + LprHandler *handler = findHandler(prt); + PrintcapEntry *entry = findEntry(prt); + if (handler && entry) + { + DrMain *driver = handler->loadDriver(prt, entry, config); + if (driver) + driver->set("handler", handler->name()); + return driver; + } + return NULL; +} + +DrMain* KMLprManager::loadFileDriver(const QString& filename) +{ + int p = filename.find('/'); + QString handler_str = (p != -1 ? filename.left(p) : QString::fromLatin1("default")); + LprHandler *handler = m_handlers.find(handler_str); + if (handler) + { + DrMain *driver = handler->loadDbDriver(filename); + if (driver) + driver->set("handler", handler->name()); + return driver; + } + return NULL; +} + +bool KMLprManager::enablePrinter(KMPrinter *prt, bool state) +{ + QString msg; + if (!m_lpchelper->enable(prt, state, msg)) + { + setErrorMsg(msg); + return false; + } + return true; +} + +bool KMLprManager::startPrinter(KMPrinter *prt, bool state) +{ + QString msg; + if (!m_lpchelper->start(prt, state, msg)) + { + setErrorMsg(msg); + return false; + } + return true; +} + +bool KMLprManager::savePrinterDriver(KMPrinter *prt, DrMain *driver) +{ + LprHandler *handler = findHandler(prt); + PrintcapEntry *entry = findEntry(prt); + if (handler && entry) + { + bool mustSave(false); + if (handler->savePrinterDriver(prt, entry, driver, &mustSave)) + { + if (mustSave) + return savePrintcapFile(); + return true; + } + } + return false; +} + +bool KMLprManager::savePrintcapFile() +{ + if (!LprSettings::self()->isLocalPrintcap()) + { + setErrorMsg(i18n("The printcap file is a remote file (NIS). It cannot be written.")); + return false; + } + QFile f(LprSettings::self()->printcapFile()); + if (f.open(IO_WriteOnly)) + { + QTextStream t(&f); + QDictIterator<PrintcapEntry> it(m_entries); + for (; it.current(); ++it) + { + it.current()->writeEntry(t); + } + return true; + } + else + { + setErrorMsg(i18n("Unable to save printcap file. Check that " + "you have write permissions for that file.")); + return false; + } +} + +bool KMLprManager::createPrinter(KMPrinter *prt) +{ + // remove existing printcap entry + PrintcapEntry *oldEntry = m_entries.find(prt->printerName()); + + // look for the handler and re-create entry + LprHandler *handler(0); + // To look for the handler, either we base ourselves + // on the driver (1: new printer, 2: modifying driver) + // or we use the handler of the existing printer + // (modifying something else, handler stays the same) + if (prt->driver()) + handler = m_handlers.find(prt->driver()->get("handler")); + else if (oldEntry) + handler = findHandler(prt); + else + handler = m_handlers.find("default"); + if (!handler) + { + setErrorMsg(i18n("Internal error: no handler defined.")); + return false; + } + prt->setOption("kde-lpr-handler", handler->name()); + + // we reload the driver if the printer object doesn't have one + // and there's an old entry (sometimes needed to keep the backend + // like in Foomatic) + if (!prt->driver() && oldEntry) + prt->setDriver(handler->loadDriver(prt, oldEntry, true)); + + QString sd = LprSettings::self()->baseSpoolDir(); + if (sd.isEmpty()) + { + setErrorMsg(i18n("Couldn't determine spool directory. See options dialog.")); + return false; + } + sd.append("/").append(prt->printerName()); + if (!KStandardDirs::makeDir(sd, 0755)) + { + setErrorMsg(i18n("Unable to create the spool directory %1. Check that you " + "have the required permissions for that operation.").arg(sd)); + return false; + } + PrintcapEntry *entry = handler->createEntry(prt); + if (!entry) + return false; // error should be set in the handler + // old entry can be removed now + m_entries.remove(prt->printerName()); + entry->name = prt->printerName(); + entry->addField("sh", Field::Boolean); + entry->addField("mx", Field::Integer, "0"); + entry->addField("sd", Field::String, sd); + if (!prt->option("kde-aliases").isEmpty()) + entry->aliases += QStringList::split("|", prt->option("kde-aliases"), false); + + // insert the new entry and save printcap file + m_entries.insert(prt->printerName(), entry); + bool result = savePrintcapFile(); + if (result) + { + if (prt->driver()) + { + result = handler->savePrinterDriver(prt, entry, prt->driver()); + } + + // in case of LPRng, we need to tell the daemon about new printer + if (LprSettings::self()->mode() == LprSettings::LPRng) + { + QString msg; + if (!m_lpchelper->restart(msg)) + { + setErrorMsg(i18n("The printer has been created but the print daemon " + "could not be restarted. %1").arg(msg)); + return false; + } + } + } + return result; +} + +bool KMLprManager::removePrinter(KMPrinter *prt) +{ + LprHandler *handler = findHandler(prt); + PrintcapEntry *entry = findEntry(prt); + if (handler && entry) + { + if (handler->removePrinter(prt, entry)) + { + QString sd = entry->field("sd"); + // first try to save the printcap file, and if + // successful, remove the spool directory + m_entries.take(prt->printerName()); + bool status = savePrintcapFile(); + if (status) + { + // printcap file saved, entry can be deleted now + delete entry; + status = (::system(QFile::encodeName("rm -rf " + KProcess::quote(sd))) == 0); + if (!status) + setErrorMsg(i18n("Unable to remove spool directory %1. " + "Check that you have write permissions " + "for that directory.").arg(sd)); + return status; + } + else + // push back the non-removed entry + m_entries.insert(prt->printerName(), entry); + } + } + return false; +} + +QString KMLprManager::driverDbCreationProgram() +{ + return QString::fromLatin1("make_driver_db_lpr"); +} + +QString KMLprManager::driverDirectory() +{ + QPtrListIterator<LprHandler> it(m_handlerlist); + QString dbDirs; + for (; it.current(); ++it) + { + QString dir = it.current()->driverDirectory(); + if (!dir.isEmpty()) + dbDirs.append(dir).append(":"); + } + if (!dbDirs.isEmpty()) + dbDirs.truncate(dbDirs.length()-1); + return dbDirs; +} + +QString KMLprManager::printOptions(KPrinter *prt) +{ + KMPrinter *mprt = findPrinter(prt->printerName()); + QString opts; + if (mprt) + { + LprHandler *handler = findHandler(mprt); + if (handler) + return handler->printOptions(prt); + } + return QString::null; +} + +void KMLprManager::createPluginActions(KActionCollection *coll) +{ + KAction *act = new KAction(i18n("&Edit printcap Entry..."), "kdeprint_report", 0, this, SLOT(slotEditPrintcap()), coll, "plugin_editprintcap"); + act->setGroup("plugin"); +} + +void KMLprManager::validatePluginActions(KActionCollection *coll, KMPrinter *prt) +{ + m_currentprinter = prt; + // FIXME: disabled until completion + coll->action("plugin_editprintcap")->setEnabled(0 && hasManagement() && prt && !prt->isSpecial()); +} + +void KMLprManager::slotEditPrintcap() +{ + if (!m_currentprinter || + KMessageBox::warningContinueCancel(NULL, + i18n("Editing a printcap entry manually should only be " + "done by confirmed system administrator. This may " + "prevent your printer from working. Do you want to " + "continue?"), QString::null, KStdGuiItem::cont(), + "editPrintcap") == KMessageBox::Cancel) + return; + + PrintcapEntry *entry = findEntry(m_currentprinter); + EditEntryDialog dlg(entry, NULL); + if (dlg.exec()) + { + } +} + +QString KMLprManager::stateInformation() +{ + return i18n("Spooler type: %1").arg(LprSettings::self()->mode() == LprSettings::LPR ? "LPR (BSD compatible)" : "LPRng"); +} + +#include "kmlprmanager.moc" diff --git a/kdeprint/lpr/kmlprmanager.h b/kdeprint/lpr/kmlprmanager.h new file mode 100644 index 000000000..5a7612e38 --- /dev/null +++ b/kdeprint/lpr/kmlprmanager.h @@ -0,0 +1,82 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef KMLRMANAGER_H +#define KMLRMANAGER_H + +#include "kmmanager.h" + +#include <qdict.h> +#include <qptrlist.h> +#include <qdatetime.h> +#include <kurl.h> + +class LprHandler; +class PrintcapEntry; +class LpcHelper; +class KPrinter; + +class KMLprManager : public KMManager +{ + Q_OBJECT +public: + KMLprManager(QObject *parent, const char *name, const QStringList & /*args*/); + + bool completePrinter(KMPrinter*); + bool completePrinterShort(KMPrinter*); + bool enablePrinter(KMPrinter*, bool); + bool startPrinter(KMPrinter*, bool); + bool savePrinterDriver(KMPrinter*, DrMain*); + DrMain* loadPrinterDriver(KMPrinter*, bool = false); + DrMain* loadFileDriver(const QString&); + bool createPrinter(KMPrinter*); + bool removePrinter(KMPrinter*); + + QString driverDbCreationProgram(); + QString driverDirectory(); + + LpcHelper* lpcHelper() { return m_lpchelper; } + QString printOptions(KPrinter*); + + void createPluginActions(KActionCollection*); + void validatePluginActions(KActionCollection*, KMPrinter*); + QString stateInformation(); + +protected slots: + void slotEditPrintcap(); + +protected: + void listPrinters(); + void initHandlers(); + void insertHandler(LprHandler*); + PrintcapEntry* findEntry(KMPrinter*); + LprHandler* findHandler(KMPrinter*); + void checkPrinterState(KMPrinter*); + bool savePrintcapFile(); + +private: + QDict<LprHandler> m_handlers; + QPtrList<LprHandler> m_handlerlist; + QDict<PrintcapEntry> m_entries; + QDateTime m_updtime; + LpcHelper *m_lpchelper; + KMPrinter *m_currentprinter; +}; + +#endif diff --git a/kdeprint/lpr/kmlpruimanager.cpp b/kdeprint/lpr/kmlpruimanager.cpp new file mode 100644 index 000000000..7b621d66f --- /dev/null +++ b/kdeprint/lpr/kmlpruimanager.cpp @@ -0,0 +1,67 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "kmlpruimanager.h" +#include "kmpropertypage.h" +#include "kprinterpropertydialog.h" +#include "kpqtpage.h" +#include "kmconfigdialog.h" + +#include "kmpropdriver.h" +#include "kmpropbackend.h" +#include "kmwizard.h" +#include "kmwbackend.h" +#include "kmconfiglpr.h" + +#include <klocale.h> + +KMLprUiManager::KMLprUiManager(QObject *parent, const char *name, const QStringList & /*args*/) +: KMUiManager(parent,name) +{ +} + +KMLprUiManager::~KMLprUiManager() +{ +} + +void KMLprUiManager::setupPropertyPages(KMPropertyPage *pages) +{ + pages->addPropPage(new KMPropBackend(pages, "Backend")); + pages->addPropPage(new KMPropDriver(pages, "Driver")); +} + +void KMLprUiManager::setupPrinterPropertyDialog(KPrinterPropertyDialog *dlg) +{ + dlg->addPage(new KPQtPage(dlg->driver(), dlg, "QtPage")); +} + +void KMLprUiManager::setupWizard(KMWizard *wizard) +{ + KMWBackend *backend = wizard->backendPage(); + + backend->addBackend(KMWizard::Local, true); + backend->addBackend(KMWizard::LPD, true); + backend->addBackend(KMWizard::TCP, true); + backend->addBackend(KMWizard::SMB, true, KMWizard::Password); +} + +void KMLprUiManager::setupConfigDialog(KMConfigDialog *dlg) +{ + dlg->addConfigPage(new KMConfigLpr(dlg)); +} diff --git a/kdeprint/lpr/kmlpruimanager.h b/kdeprint/lpr/kmlpruimanager.h new file mode 100644 index 000000000..46eedb189 --- /dev/null +++ b/kdeprint/lpr/kmlpruimanager.h @@ -0,0 +1,37 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef KMLPRUIMANAGER_H +#define KMLPRUIMANAGER_H + +#include "kmuimanager.h" + +class KMLprUiManager : public KMUiManager +{ +public: + KMLprUiManager(QObject *parent, const char *name, const QStringList & /*args*/); + ~KMLprUiManager(); + + void setupPropertyPages(KMPropertyPage*); + void setupPrinterPropertyDialog(KPrinterPropertyDialog*); + void setupWizard(KMWizard*); + void setupConfigDialog(KMConfigDialog*); +}; + +#endif diff --git a/kdeprint/lpr/lpchelper.cpp b/kdeprint/lpr/lpchelper.cpp new file mode 100644 index 000000000..b4cd6f9e1 --- /dev/null +++ b/kdeprint/lpr/lpchelper.cpp @@ -0,0 +1,320 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "lpchelper.h" +#include "kpipeprocess.h" +#include "kmjob.h" +#include "lprsettings.h" + +#include <kstandarddirs.h> +#include <qtextstream.h> +#include <qregexp.h> +#include <kdebug.h> +#include <klocale.h> +#include <kprocess.h> +#include <stdlib.h> + +static QString execute(const QString& cmd) +{ + KPipeProcess proc; + QString output; + if (proc.open(cmd)) + { + QTextStream t(&proc); + while (!t.atEnd()) + output.append(t.readLine()).append("\n"); + proc.close(); + } + return output; +} + +LpcHelper::LpcHelper(QObject *parent, const char *name) +: QObject(parent, name) +{ + // look for the "lpc" executable. Use the PATH variable and + // add some specific dirs. + QString PATH = getenv("PATH"); + PATH.append(":/usr/sbin:/usr/local/sbin:/sbin:/opt/sbin:/opt/local/sbin"); + m_exepath = KStandardDirs::findExe("lpc", PATH); + m_checkpcpath = KStandardDirs::findExe("checkpc", PATH); + m_lprmpath = KStandardDirs::findExe("lprm"); +} + +LpcHelper::~LpcHelper() +{ +} + +KMPrinter::PrinterState LpcHelper::state(const QString& prname) const +{ + if (m_state.contains(prname)) + return m_state[prname]; + return KMPrinter::Unknown; +} + +KMPrinter::PrinterState LpcHelper::state(KMPrinter *prt) const +{ + return state(prt->printerName()); +} + +void LpcHelper::parseStatusLPR(QTextStream &t) +{ + QString printer, line; + int p(-1); + + while (!t.atEnd()) + { + line = t.readLine(); + if (line.isEmpty()) + continue; + else if (!line[0].isSpace() && (p = line.find(':')) != -1) + { + printer = line.left(p); + m_state[printer] = KMPrinter::Idle; + } + else if (line.find("printing is disabled") != -1) + { + if (!printer.isEmpty()) + m_state[printer] = KMPrinter::PrinterState((KMPrinter::Stopped) | (m_state[printer] & ~KMPrinter::StateMask)); + } + else if (line.find("queuing is disabled") != -1) + { + if (!printer.isEmpty()) + m_state[printer] = KMPrinter::PrinterState((KMPrinter::Rejecting) | (m_state[printer] & KMPrinter::StateMask)); + } + else if (line.find("entries") != -1) + { + if (!printer.isEmpty() && + (m_state[printer] & KMPrinter::StateMask) != KMPrinter::Stopped && + line.find("no entries") == -1) + m_state[printer] = KMPrinter::PrinterState((m_state[printer] & ~KMPrinter::StateMask) | KMPrinter::Processing); + } + } +} + +void LpcHelper::parseStatusLPRng(QTextStream& t) +{ + QStringList l; + int p(-1); + QString printer; + + while (!t.atEnd()) + if (t.readLine().stripWhiteSpace().startsWith("Printer")) + break; + while (!t.atEnd()) + { + l = QStringList::split(QRegExp("\\s"), t.readLine(), false); + if (l.count() < 4) + continue; + p = l[0].find('@'); + if (p == 0) + printer = l[0]; + else + printer = l[0].left(p); + int st(0); + if (l[1] == "disabled") + st = KMPrinter::Stopped; + else if (l[3] != "0") + st = KMPrinter::Processing; + else + st = KMPrinter::Idle; + if (l[2] == "disabled") + st |= KMPrinter::Rejecting; + m_state[printer] = KMPrinter::PrinterState(st); + } +} + +void LpcHelper::updateStates() +{ + KPipeProcess proc; + + m_state.clear(); + if (!m_exepath.isEmpty() && proc.open(m_exepath + " status all")) + { + QTextStream t(&proc); + + switch (LprSettings::self()->mode()) + { + default: + case LprSettings::LPR: + parseStatusLPR(t); + break; + case LprSettings::LPRng: + parseStatusLPRng(t); + break; + } + proc.close(); + } + +} + +bool LpcHelper::enable(KMPrinter *prt, bool state, QString& msg) +{ + int st = m_state[prt->printerName()] & KMPrinter::StateMask; + if (changeState(prt->printerName(), (state ? "enable" : "disable"), msg)) + { + m_state[prt->printerName()] = KMPrinter::PrinterState((state ? KMPrinter::Rejecting : 0) | st); + return true; + } + return false; +} + +bool LpcHelper::start(KMPrinter *prt, bool state, QString& msg) +{ + int rej = m_state[prt->printerName()] & ~KMPrinter::StateMask; + if (changeState(prt->printerName(), (state ? "start" : "stop"), msg)) + { + m_state[prt->printerName()] = KMPrinter::PrinterState((state ? KMPrinter::Idle : KMPrinter::Stopped) | rej); + return true; + } + return false; +} + +// status +// 0 : success +// -1 : permission denied +// -2 : unknown printer +// 1 : unknown error +int LpcHelper::parseStateChangeLPR(const QString& result, const QString& printer) +{ + if (result.startsWith(printer + ":")) + return 0; + else if (result.startsWith("?Privileged")) + return -1; + else if (result.startsWith("unknown")) + return -2; + else + return 1; +} + +static QString lprngAnswer(const QString& result, const QString& printer) +{ + int p, q; + + p = result.find("\n" + printer); + if (p != -1) + { + q = result.find(':', p)+2; + p = result.find('\n', q); + QString answer = result.mid(q, p-q).stripWhiteSpace(); + return answer; + } + return QString::null; +} + +int LpcHelper::parseStateChangeLPRng(const QString& result, const QString& printer) +{ + QString answer = lprngAnswer(result, printer); + if (answer == "no") + return -1; + else if (answer == "disabled" || answer == "enabled" || answer == "started" || answer == "stopped") + return 0; + else + return 1; +} + +bool LpcHelper::changeState(const QString& printer, const QString& op, QString& msg) +{ + if (m_exepath.isEmpty()) + { + msg = i18n("The executable %1 couldn't be found in your PATH.").arg("lpc"); + return false; + } + QString result = execute(m_exepath + " " + op + " " + KProcess::quote(printer)); + int status; + + switch (LprSettings::self()->mode()) + { + default: + case LprSettings::LPR: + status = parseStateChangeLPR(result, printer); + break; + case LprSettings::LPRng: + status = parseStateChangeLPRng(result, printer); + break; + } + switch (status) + { + case 0: + break; + case -1: + msg = i18n("Permission denied."); + break; + case -2: + msg = i18n("Printer %1 does not exist.").arg(printer); + break; + default: + case 1: + msg = i18n("Unknown error: %1").arg(result.replace(QRegExp("\\n"), " ")); + break; + } + return (status == 0); +} + +bool LpcHelper::removeJob(KMJob *job, QString& msg) +{ + if (m_lprmpath.isEmpty()) + { + msg = i18n("The executable %1 couldn't be found in your PATH.").arg("lprm"); + return false; + } + QString result = execute(m_lprmpath + " -P " + KProcess::quote(job->printer()) + " " + QString::number(job->id())); + if (result.find("dequeued") != -1) + return true; + else if (result.find("Permission denied") != -1 || result.find("no permissions") != -1) + msg = i18n("Permission denied."); + else + msg = i18n("Execution of lprm failed: %1").arg(result); + return false; +} + +// LPRng only +bool LpcHelper::changeJobState(KMJob *job, int state, QString& msg) +{ + if (m_lprmpath.isEmpty()) + { + msg = i18n("The executable %1 couldn't be found in your PATH.").arg("lpc"); + return false; + } + QString result = execute(m_exepath + (state == KMJob::Held ? " hold " : " release ") + KProcess::quote(job->printer()) + " " + QString::number(job->id())); + QString answer = lprngAnswer(result, job->printer()); + if (answer == "no") + { + msg = i18n("Permission denied."); + return false; + } + else + return true; +} + +bool LpcHelper::restart(QString& msg) +{ + QString s; + if (m_exepath.isEmpty()) + s = "lpc"; + else if (m_checkpcpath.isEmpty()) + s = "checkpc"; + if (!s.isEmpty()) + { + msg = i18n("The executable %1 couldn't be found in your PATH.").arg(s); + return false; + } + ::system(QFile::encodeName(m_exepath + " reread")); + ::system(QFile::encodeName(m_checkpcpath + " -f")); + return true; +} diff --git a/kdeprint/lpr/lpchelper.h b/kdeprint/lpr/lpchelper.h new file mode 100644 index 000000000..a4474354d --- /dev/null +++ b/kdeprint/lpr/lpchelper.h @@ -0,0 +1,59 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef LPCHELPER_H +#define LPCHELPER_H + +#include <qobject.h> +#include <qmap.h> +#include <qtextstream.h> +#include "kmprinter.h" + +class KMJob; + +class LpcHelper : public QObject +{ +public: + LpcHelper(QObject *parent = 0, const char *name = 0); + ~LpcHelper(); + + KMPrinter::PrinterState state(const QString&) const; + KMPrinter::PrinterState state(KMPrinter*) const; + void updateStates(); + + bool enable(KMPrinter*, bool, QString&); + bool start(KMPrinter*, bool, QString&); + bool removeJob(KMJob*, QString&); + bool changeJobState(KMJob*, int, QString&); + + bool restart(QString&); + +protected: + bool changeState(const QString&, const QString&, QString&); + void parseStatusLPR(QTextStream&); + void parseStatusLPRng(QTextStream&); + int parseStateChangeLPR(const QString&, const QString&); + int parseStateChangeLPRng(const QString&, const QString&); + +private: + QMap<QString, KMPrinter::PrinterState> m_state; + QString m_exepath, m_lprmpath, m_checkpcpath; +}; + +#endif diff --git a/kdeprint/lpr/lpqhelper.cpp b/kdeprint/lpr/lpqhelper.cpp new file mode 100644 index 000000000..c9f26174b --- /dev/null +++ b/kdeprint/lpr/lpqhelper.cpp @@ -0,0 +1,117 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "lpqhelper.h" +#include "kmjob.h" +#include "kpipeprocess.h" +#include "lprsettings.h" + +#include <kstandarddirs.h> +#include <kprocess.h> +#include <kdebug.h> + +LpqHelper::LpqHelper(QObject *parent, const char *name) +: QObject(parent, name) +{ + m_exepath = KStandardDirs::findExe("lpq"); +} + +LpqHelper::~LpqHelper() +{ +} + +KMJob* LpqHelper::parseLineLpr(const QString& line) +{ + QString rank = line.left(7); + if (!rank[0].isDigit() && rank != "active") + return NULL; + KMJob *job = new KMJob; + job->setState((rank[0].isDigit() ? KMJob::Queued : KMJob::Printing)); + job->setOwner(line.mid(7, 11).stripWhiteSpace()); + job->setId(line.mid(18, 5).toInt()); + job->setName(line.mid(23, 38).stripWhiteSpace()); + int p = line.find(' ', 61); + if (p != -1) + { + job->setSize(line.mid(61, p-61).toInt() / 1000); + } + return job; +} + +KMJob* LpqHelper::parseLineLPRng(const QString& line) +{ + QString rank = line.left(7).stripWhiteSpace(); + if (!rank[0].isDigit() && rank != "active" && rank != "hold") + return NULL; + KMJob *job = new KMJob; + job->setState((rank[0].isDigit() ? KMJob::Queued : (rank == "hold" ? KMJob::Held : KMJob::Printing))); + int p = line.find('@', 7), q = line.find(' ', 7); + job->setOwner(line.mid(7, QMIN(p,q)-7)); + while (line[q].isSpace()) + q++; + q++; + while (line[q].isSpace()) + q++; + p = line.find(' ', q); + job->setId(line.mid(q, p-q).toInt()); + while (line[p].isSpace()) + p++; + q = p+25; + while (line[q].isDigit()) + q--; + job->setName(line.mid(p, q-p).stripWhiteSpace()); + job->setSize(line.mid(q+1, p+26-q).toInt() / 1000); + return job; +} + +void LpqHelper::listJobs(QPtrList<KMJob>& jobs, const QString& prname, int limit) +{ + KPipeProcess proc; + if (!m_exepath.isEmpty() && proc.open(m_exepath + " -P " + KProcess::quote(prname))) + { + QTextStream t(&proc); + QString line; + bool lprng = (LprSettings::self()->mode() == LprSettings::LPRng); + int count = 0; + + while (!t.atEnd()) + { + line = t.readLine().stripWhiteSpace(); + if (line.startsWith("Rank")) + break; + } + while (!t.atEnd()) + { + line = t.readLine(); + if ( limit > 0 && count >= limit ) + continue; + KMJob *job = (lprng ? parseLineLPRng(line) : parseLineLpr(line)); + if (job) + { + job->setPrinter(prname); + job->setUri("lpd://"+prname+"/"+QString::number(job->id())); + jobs.append(job); + count++; + } + else + break; + } + proc.close(); + } +} diff --git a/kdeprint/lpr/lpqhelper.h b/kdeprint/lpr/lpqhelper.h new file mode 100644 index 000000000..1c9af35a6 --- /dev/null +++ b/kdeprint/lpr/lpqhelper.h @@ -0,0 +1,44 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef LPQHELPER_H +#define LPQHELPER_H + +#include <qobject.h> +#include <qptrlist.h> + +class KMJob; + +class LpqHelper : public QObject +{ +public: + LpqHelper(QObject *parent = 0, const char *name = 0); + ~LpqHelper(); + + void listJobs(QPtrList<KMJob>& jobs, const QString& prname, int limit = 0); + +protected: + KMJob* parseLineLpr(const QString&); + KMJob* parseLineLPRng(const QString&); + +private: + QString m_exepath; +}; + +#endif diff --git a/kdeprint/lpr/lpr.print b/kdeprint/lpr/lpr.print new file mode 100644 index 000000000..e8cd8a3d7 --- /dev/null +++ b/kdeprint/lpr/lpr.print @@ -0,0 +1,86 @@ +[KDE Print Entry] +PrintSystem=lpr +Comment=LPR/LPRng Print System +Comment[af]= lpr /Lprng Druk Stelsel +Comment[ar]=نظام طباعة LPR/LPRng +Comment[az]=LPR/LPRng Çap Sistemi +Comment[be]=Сістэма друку LPR/LPRng +Comment[bn]=এল-পি-আর/এল-পি-আর-এন-জি মুদ্রণ ব্যবস্থা +Comment[br]=Reizhiad moulañ LPR/LPRng +Comment[bs]=LPR/LPRng sistem štampe +Comment[ca]=Sistema d'impressió LPR/LPRng +Comment[cs]=Tiskový systém LPR/LPRng +Comment[csb]=Systema drëkù LPR/LPRng +Comment[cy]=Cysawd Argraffu LPR/LPRng +Comment[da]=LPR/LPRng-udskriftssystem +Comment[de]=LPR/LPRng-Drucksystem +Comment[el]=LPR/LPRng σύστημα εκτύπωσης +Comment[eo]=LPR/LPRng-presosistemo +Comment[es]=Sistema de impresión LPR/LPRNg +Comment[et]=LPR/LPRng trükkimise süsteem +Comment[eu]=LPR/LPRng inprimatze-sistema +Comment[fa]=سیستم چاپ LPR/LPRng +Comment[fi]=LPR/LPRng-tulostusjärjestelmä +Comment[fr]=Système d'impression LPR / LPRng +Comment[fy]=LPR-/LPRNG-ôfdruksysteem +Comment[ga]=Córas Priontála LPR/LPRng +Comment[gl]=Sistema de Impresión LPR/LPRng +Comment[he]=מערכת ההדפסה LPR/LPRng +Comment[hi]=LPR/LPRng छपाई पद्धत्ति +Comment[hr]=LPR/LPRng sustav za ispis +Comment[hu]=LPR/LPRng +Comment[id]=Sistem Pencetakan LPR/LPRng +Comment[is]=LPR/LPRng prentkerfið +Comment[it]=Sistema di stampa LPR/LPRng +Comment[ja]=LPR/LPRng 印刷システム +Comment[ka]=LPR/LPRng ბეჭდვის სისტემა +Comment[kk]=LPR/LPRng басып шығару жүйесі +Comment[km]=ប្រព័ន្ធបោះពុម្ព LPR/LPRng +Comment[ko]=LPR/LPRng 인쇄 시스템 +Comment[lb]=LPR/LPRng-Drécksystem +Comment[lt]=LPR/LPRng spausdinimo sistema +Comment[lv]=LPR/LPRng drukas sistēma +Comment[mk]=LPR/LPRng системот за печатење +Comment[mn]=LPR/LPRng-Хэвлэх систем +Comment[ms]=Sistem Cetak LPR/LPRng +Comment[mt]=Sistema tal-ipprintjar LPR/LPRng +Comment[nb]=Utskriftssystemet LPR/LPRng +Comment[nds]=Dat Drucksysteem LPR/LPRng +Comment[ne]=LPR/LPRng मुद्रण प्रणाली +Comment[nl]=LPR-/LPRNG-afdruksysteem +Comment[nn]=Utskriftssystemet LPR/LPRng +Comment[nso]=System ya Kgatiso ya LPR/LPRng +Comment[pa]=LPR/LPRng ਪ੍ਰਿੰਟਰ ਸਿਸਟਮ +Comment[pl]=System druku LPR/LPRng +Comment[pt]=O sistema de impressão LPR/LPRng +Comment[pt_BR]=Sistema de Impressão LPR/LPRng +Comment[ro]=Sistem de tipărire LPR/LPRng +Comment[ru]=Система печати LPR/LPRng +Comment[rw]=Sisitemu yo Gucapa LPR/LPRng +Comment[se]=LPR/LPRng čálihanvuogádat +Comment[sk]=Tlačový systém LPR/LPRng +Comment[sl]=Tiskalniški sistem za LPR/LPRng +Comment[sq]=Sistem Shtypi për LPR/LPRng +Comment[sr]=LPR/LPRng систем за штампање +Comment[sr@Latn]=LPR/LPRng sistem za štampanje +Comment[ss]=LPR/LPRng umhini wekushivelela +Comment[sv]=LPR/LPRNG-skrivarsystem +Comment[ta]=LPR/LPRng அச்சுத் தொகுதி +Comment[te]=ఎల్ పి ఆర్/ఎల్ పి ఆర్ ఎన్ జి ప్రచురణ వ్యవస్థ +Comment[tg]=Системаи чопи LPR/LPRng +Comment[th]=ระบบการพิมพ์ LPR/LPRng +Comment[tr]=LPR/LPRng Yazdırma Sistemi +Comment[tt]=LPR/LPRng Bastıru Sisteme +Comment[uk]=Система друку LPR/LPRng +Comment[uz]=LPR/LPRng bosib chiqarish tizimi +Comment[uz@cyrillic]=LPR/LPRng босиб чиқариш тизими +Comment[ven]=LPR/Maitele au phirintha a LPRng +Comment[vi]=Hệ thống in LPR/LPRng +Comment[wa]=Sistinme d' imprimaedje LPR/LPRng +Comment[xh]=LPR/LPRng Indlela Yokushicilela +Comment[zh_CN]=LPR/LPRng 打印系统 +Comment[zh_HK]=LPR/LPRng 列印系統 +Comment[zh_TW]=LPR/LPRng 列印系統 +Comment[zu]=Isistimu Yokushicilela ye-LPR/LRng +DetectUris=service:/printer +DetectPrecedence=0 diff --git a/kdeprint/lpr/lprhandler.cpp b/kdeprint/lpr/lprhandler.cpp new file mode 100644 index 000000000..396562691 --- /dev/null +++ b/kdeprint/lpr/lprhandler.cpp @@ -0,0 +1,270 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "lprhandler.h" +#include "kmprinter.h" +#include "printcapentry.h" +#include "kmmanager.h" +#include "lprsettings.h" +#include "driver.h" + +#include <qfile.h> +#include <qtextstream.h> +#include <qvaluestack.h> +#include <klocale.h> + +#include <unistd.h> + +LprHandler::LprHandler(const QString& name, KMManager *mgr) +: m_name(name), m_manager(mgr) +{ +} + +LprHandler::~LprHandler() +{ +} + +bool LprHandler::validate(PrintcapEntry*) +{ + return true; +} + +KMPrinter* LprHandler::createPrinter(PrintcapEntry *entry) +{ + KMPrinter *prt = new KMPrinter; + prt->setPrinterName(entry->name); + prt->setName(entry->name); + prt->setType(KMPrinter::Printer); + return prt; +} + +bool LprHandler::completePrinter(KMPrinter *prt, PrintcapEntry *entry, bool) +{ + prt->setDescription(i18n("Unknown (unrecognized entry)")); + QString val = entry->field("lp"); + KURL uri; + if (!val.isEmpty() && val != "/dev/null") + { + int p = val.find('@'); + if (p != -1) + { + prt->setLocation(i18n("Remote queue (%1) on %2").arg(val.left(p)).arg(val.mid(p+1))); + uri.setProtocol("lpd"); + uri.setHost(val.mid(p+1)); + uri.setPath("/" + val.left(p)); + } + else if ((p = val.find('%')) != -1) + { + prt->setLocation(i18n("Network printer (%1)").arg("socket")); + uri.setProtocol("socket"); + uri.setHost(val.left(p)); + uri.setPort(val.mid(p+1).toInt()); + } + else + { + prt->setLocation(i18n("Local printer on %1").arg(val)); + uri.setProtocol("parallel"); + uri.setPath(val); + } + } + else if (!(val = entry->field("rp")).isEmpty()) + { + QString rm = entry->has("rm") ? + entry->field("rm") : + LprSettings::self()->defaultRemoteHost(); + prt->setLocation(i18n("Remote queue (%1) on %2").arg(val).arg(rm)); + uri.setProtocol("lpd"); + uri.setHost(rm); + uri.setPath("/" + val); + } + else + prt->setLocation(i18n("Unknown (unrecognized entry)")); + prt->setDevice(uri.url()); + return true; +} + +DrMain* LprHandler::loadDriver(KMPrinter*, PrintcapEntry*, bool) +{ + manager()->setErrorMsg(i18n("Unrecognized entry.")); + return NULL; +} + +bool LprHandler::savePrinterDriver(KMPrinter*, PrintcapEntry*, DrMain*, bool*) +{ + manager()->setErrorMsg(i18n("Unrecognized entry.")); + return false; +} + +DrMain* LprHandler::loadDbDriver(const QString&) +{ + manager()->setErrorMsg(i18n("Unrecognized entry.")); + return NULL; +} + +PrintcapEntry* LprHandler::createEntry(KMPrinter *prt) +{ + // this default handler only supports local parallel and remote lpd URIs + KURL uri ( prt->device() ); + QString prot = uri.protocol(); + if (!prot.isEmpty() && prot != "parallel" && prot != "file" && prot != "lpd" && prot != "socket") + { + manager()->setErrorMsg(i18n("Unsupported backend: %1.").arg(prot)); + return NULL; + } + PrintcapEntry *entry = new PrintcapEntry; + entry->comment = "# Default handler"; + if (prot == "lpd") + { + entry->addField("rm", Field::String, uri.host()); + QString rp = uri.path(); + if (rp[0] == '/') + rp = rp.mid(1); + entry->addField("rp", Field::String, rp); + // force this entry to null (otherwise it seems it's redirected + // to /dev/lp0 by default) + entry->addField("lp", Field::String, QString::null); + } + else if ( prot == "socket" ) + { + QString lp = uri.host(); + if ( uri.port() == 0 ) + lp.append( "%9100" ); + else + lp.append( "%" ).append( QString::number( uri.port() ) ); + entry->addField("lp", Field::String, lp); + } + else + { + entry->addField("lp", Field::String, uri.path()); + } + return entry; +} + +bool LprHandler::removePrinter(KMPrinter*, PrintcapEntry*) +{ + return true; +} + +QString LprHandler::printOptions(KPrinter*) +{ + return QString::null; +} + +void LprHandler::reset() +{ +} + +DrMain* LprHandler::loadToolDriver(const QString& filename) +{ + QFile f(filename); + if (f.open(IO_ReadOnly)) + { + DrMain *driver = new DrMain; + QValueStack<DrGroup*> groups; + QTextStream t(&f); + QStringList l; + DrListOption *lopt(0); + DrBase *opt(0); + + groups.push(driver); + driver->set("text", "Tool Driver"); + while (!t.atEnd()) + { + l = QStringList::split('|', t.readLine().stripWhiteSpace(), false); + if (l.count() == 0) + continue; + if (l[0] == "GROUP") + { + DrGroup *grp = new DrGroup; + grp->setName(l[1]); + grp->set("text", l[2]); + groups.top()->addGroup(grp); + groups.push(grp); + } + else if (l[0] == "ENDGROUP") + { + groups.pop(); + } + else if (l[0] == "OPTION") + { + opt = 0; + lopt = 0; + if (l.count() > 3) + { + if (l[3] == "STRING") + opt = new DrStringOption; + else if (l[3] == "BOOLEAN") + { + lopt = new DrBooleanOption; + opt = lopt; + } + } + else + { + lopt = new DrListOption; + opt = lopt; + } + if (opt) + { + opt->setName(l[1]); + opt->set("text", l[2]); + groups.top()->addOption(opt); + } + } + else if (l[0] == "CHOICE" && lopt) + { + DrBase *ch = new DrBase; + ch->setName(l[1]); + ch->set("text", l[2]); + lopt->addChoice(ch); + } + else if (l[0] == "DEFAULT" && opt) + { + opt->setValueText(l[1]); + opt->set("default", l[1]); + } + } + return driver; + } + return NULL; +} + +QString LprHandler::driverDirectory() +{ + if (m_cacheddriverdir.isEmpty()) + m_cacheddriverdir = driverDirInternal(); + return m_cacheddriverdir; +} + +QString LprHandler::driverDirInternal() +{ + return QString::null; +} + +QString LprHandler::locateDir(const QString& dirname, const QString& paths) +{ + QStringList pathlist = QStringList::split(':', paths, false); + for (QStringList::ConstIterator it=pathlist.begin(); it!=pathlist.end(); ++it) + { + QString testpath = *it + "/" + dirname; + if (::access(QFile::encodeName(testpath), F_OK) == 0) + return testpath; + } + return QString::null; +} diff --git a/kdeprint/lpr/lprhandler.h b/kdeprint/lpr/lprhandler.h new file mode 100644 index 000000000..49b9c6236 --- /dev/null +++ b/kdeprint/lpr/lprhandler.h @@ -0,0 +1,88 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef LPRHANDLER_H +#define LPRHANDLER_H + +#if !defined( _KDEPRINT_COMPILE ) && defined( __GNUC__ ) +#warning internal header, do not use except if you are a KDEPrint developer +#endif + +#include <qstring.h> + +class PrintcapEntry; +class KMPrinter; +class DrMain; +class KMManager; +class KPrinter; + +/** + * @internal + * This class is internal to KDEPrint and is not intended to be + * used outside it. Please do not make use of this header, except + * if you're a KDEPrint developer. The API might change in the + * future and binary compatibility might be broken. + */ +class LprHandler +{ +public: + LprHandler(const QString& name, KMManager *mgr = 0); + virtual ~LprHandler(); + + virtual bool validate(PrintcapEntry*); + virtual KMPrinter* createPrinter(PrintcapEntry*); + virtual bool completePrinter(KMPrinter*, PrintcapEntry*, bool shortmode = true); + virtual DrMain* loadDriver(KMPrinter*, PrintcapEntry*, bool = false); + virtual DrMain* loadDbDriver(const QString&); + virtual bool savePrinterDriver(KMPrinter*, PrintcapEntry*, DrMain*, bool* = 0); + virtual PrintcapEntry* createEntry(KMPrinter*); + virtual bool removePrinter(KMPrinter*, PrintcapEntry*); + virtual QString printOptions(KPrinter*); + virtual void reset(); + + QString name() const; + KMManager* manager() const; + QString driverDirectory(); + +protected: + DrMain* loadToolDriver(const QString&); + QString locateDir(const QString& dirname, const QString& paths); + QString cachedDriverDir() const; + void setCachedDriverDir(const QString&); + virtual QString driverDirInternal(); + +protected: + QString m_name; + KMManager *m_manager; + QString m_cacheddriverdir; +}; + +inline QString LprHandler::name() const +{ return m_name; } + +inline KMManager* LprHandler::manager() const +{ return m_manager; } + +inline QString LprHandler::cachedDriverDir() const +{ return m_cacheddriverdir; } + +inline void LprHandler::setCachedDriverDir(const QString& s) +{ m_cacheddriverdir = s; } + +#endif diff --git a/kdeprint/lpr/lprngtooldriver1 b/kdeprint/lpr/lprngtooldriver1 new file mode 100644 index 000000000..11636403c --- /dev/null +++ b/kdeprint/lpr/lprngtooldriver1 @@ -0,0 +1,85 @@ +GROUP|general|General +OPTION|PageSize|Page Size +CHOICE|letter|US Letter +CHOICE|legal|US Legal +CHOICE|ledger|Ledger +CHOICE|11x17|11x17 +CHOICE|tabloid|Tabloid +CHOICE|oversize|Oversize +CHOICE|executive|Executive +CHOICE|envelope|Envelope +CHOICE|a0|A0 +CHOICE|a1|A1 +CHOICE|a2|A2 +CHOICE|a3|A3 +CHOICE|a4|A4 +DEFAULT|a4 +OPTION|MediaType|Media Type +CHOICE|bond|Bond paper +CHOICE|cardstock|Card stock +CHOICE|color|Color paper +CHOICE|glossy|Glossy paper +CHOICE|heavy|Heavy paper +CHOICE|labels|Labels +CHOICE|letterhead|Letter head +CHOICE|plain|Plain paper +CHOICE|preprinted|Preprinted paper +CHOICE|prepunched|Prepunched paper +CHOICE|recycle|Recycled paper +CHOICE|transparency|Transparencies +CHOICE|default|Default setting +DEFAULT|default +OPTION|InputSlot|Input Slot +CHOICE|manual|Manual tray +CHOICE|inupper|Upper tray +CHOICE|inmiddle|Middle tray +CHOICE|inlower|Lower tray +CHOICE|inlarge|Large tray +CHOICE|inright|Right tray +CHOICE|intray1|Tray 1 +CHOICE|intray2|Tray 2 +CHOICE|intray3|Tray 3 +CHOICE|intray4|Tray 4 +CHOICE|intray5|Tray 5 +CHOICE|intray6|Tray 6 +CHOICE|intray7|Tray 7 +CHOICE|intray8|Tray 8 +CHOICE|intray9|Tray 9 +CHOICE|intray10|Tray 10 +CHOICE|inlargecapacity|Large capacity tray +CHOICE|inhighcapacity|High capacity tray +CHOICE|default|Default setting +DEFAULT|default +OPTION|OutputBin|Output Tray +CHOICE|outupper|Upper tray +CHOICE|outlower|Lower tray +CHOICE|outbin2|Tray 2 +CHOICE|outbin3|Tray 3 +CHOICE|outbin4|Tray 4 +CHOICE|outbin5|Tray 5 +CHOICE|outbin6|Tray 6 +CHOICE|outbin7|Tray 7 +CHOICE|outbin8|Tray 8 +CHOICE|outbin9|Tray 9 +CHOICE|default|Default setting +DEFAULT|default +ENDGROUP +GROUP|others|Others +OPTION|Duplex|Duplex +CHOICE|simplex|Simplex +CHOICE|duplex|Duplex +CHOICE|duplexshort|Duplex (short edge) +CHOICE|tumble|Tumble +CHOICE|default|Default setting +DEFAULT|default +OPTION|Resolution|Printing Resolution +CHOICE|300|300 DPI +CHOICE|600|600 DPI +CHOICE|1200|1200 DPI +CHOICE|default|Default setting +DEFAULT|default +ENDGROUP +GROUP|advanced|Advanced Settings +OPTION|filter|Filter options (comma sepatared)|STRING +OPTION|lpr|LPR options (comma separated)|STRING +ENDGROUP diff --git a/kdeprint/lpr/lprngtoolhandler.cpp b/kdeprint/lpr/lprngtoolhandler.cpp new file mode 100644 index 000000000..1b08d70b9 --- /dev/null +++ b/kdeprint/lpr/lprngtoolhandler.cpp @@ -0,0 +1,393 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "lprngtoolhandler.h" +#include "printcapentry.h" +#include "kmprinter.h" +#include "util.h" +#include "lprsettings.h" +#include "driver.h" +#include "kmmanager.h" +#include "kprinter.h" + +#include <qfile.h> +#include <qtextstream.h> +#include <klocale.h> +#include <kdebug.h> +#include <kstandarddirs.h> + +LPRngToolHandler::LPRngToolHandler(KMManager *mgr) +: LprHandler("lprngtool", mgr) +{ +} + +bool LPRngToolHandler::validate(PrintcapEntry *entry) +{ + if (entry->comment.startsWith("##LPRNGTOOL##") && + entry->comment.find("UNKNOWN") == -1) + return true; + return false; +} + +bool LPRngToolHandler::completePrinter(KMPrinter *prt, PrintcapEntry *entry, bool shortmode) +{ + QString str, lp; + + // look for type in comment + QStringList l = QStringList::split(' ', entry->comment, false); + lp = entry->field("lp"); + if (l.count() < 1) + return false; + + if (l[1] == "DEVICE" || l[1] == "SOCKET" || l[1] == "QUEUE") + LprHandler::completePrinter(prt, entry, shortmode); + else if (l[1] == "SMB") + { + QMap<QString,QString> opts = parseXferOptions(entry->field("xfer_options")); + QString user, pass; + loadAuthFile(LprSettings::self()->baseSpoolDir() + "/" + entry->name + "/" + opts["authfile"], user, pass); + QString uri = buildSmbURI( + opts[ "workgroup" ], + opts[ "host" ], + opts[ "printer" ], + user, + pass ); + prt->setDevice( uri ); + prt->setLocation(i18n("Network printer (%1)").arg("smb")); + } + + // look for comment + if (!(str=entry->field("cm")).isEmpty()) + prt->setDescription(str); + + // driver + //if (!shortmode) + //{ + if (!(str=entry->field("ifhp")).isEmpty()) + { + QString model; + int p = str.find("model"); + if (p != -1) + { + p = str.find('=', p); + if (p != -1) + { + p++; + int q = str.find(',', p); + if (q == -1) + model = str.mid(p); + else + model = str.mid(p, q-p); + } + } + prt->setDriverInfo(i18n("IFHP Driver (%1)").arg((model.isEmpty() ? i18n("unknown") : model))); + prt->setOption("driverID", model); + } + //} + return true; +} + +QMap<QString,QString> LPRngToolHandler::parseXferOptions(const QString& str) +{ + uint p(0), q; + QMap<QString,QString> opts; + QString key, val; + + while (p < str.length()) + { + key = val = QString::null; + // skip spaces + while (p < str.length() && str[p].isSpace()) + p++; + q = p; + while (q < str.length() && str[q] != '=') + q++; + key = str.mid(p, q-p); + p = q+2; + while (p < str.length() && str[p] != '"') + p++; + val = str.mid(q+2, p-q-2); + if (!key.isEmpty()) + opts[key] = val; + p++; + } + return opts; +} + +void LPRngToolHandler::loadAuthFile(const QString& filename, QString& user, QString& pass) +{ + QFile f(filename); + if (f.open(IO_ReadOnly)) + { + QTextStream t(&f); + QString line; + while (!t.atEnd()) + { + line = t.readLine().stripWhiteSpace(); + if (line.isEmpty()) + continue; + int p = line.find('='); + if (p != -1) + { + QString key = line.left(p); + if (key == "username") + user = line.mid(p+1); + else if (key == "password") + pass = line.mid(p+1); + } + } + } +} + +DrMain* LPRngToolHandler::loadDriver(KMPrinter *prt, PrintcapEntry *entry, bool config) +{ + if (entry->field("lprngtooloptions").isEmpty()) + { + manager()->setErrorMsg(i18n("No driver defined for that printer. It might be a raw printer.")); + return NULL; + } + + DrMain* driver = loadToolDriver(locate("data", "kdeprint/lprngtooldriver1")); + if (driver) + { + QString model = prt->option("driverID"); + driver->set("text", i18n("LPRngTool Common Driver (%1)").arg((model.isEmpty() ? i18n("unknown") : model))); + if (!model.isEmpty()) + driver->set("driverID", model); + QMap<QString,QString> opts = parseZOptions(entry->field("prefix_z")); + opts["lpr"] = entry->field("lpr"); + driver->setOptions(opts); + // if not configuring, don't show the "lpr" options + if (!config) + driver->removeOptionGlobally("lpr"); + } + return driver; +} + +DrMain* LPRngToolHandler::loadDbDriver(const QString& s) +{ + int p = s.find('/'); + DrMain* driver = loadToolDriver(locate("data", "kdeprint/lprngtooldriver1")); + if (driver) + driver->set("driverID", s.mid(p+1)); + return driver; +} + +QValueList< QPair<QString,QStringList> > LPRngToolHandler::loadChoiceDict(const QString& filename) +{ + QFile f(filename); + QValueList< QPair<QString,QStringList> > dict; + if (f.open(IO_ReadOnly)) + { + QTextStream t(&f); + QString line, key; + QStringList l; + while (!t.atEnd()) + { + line = t.readLine().stripWhiteSpace(); + if (line.startsWith("OPTION")) + { + if (l.count() > 0 && !key.isEmpty()) + dict << QPair<QString,QStringList>(key, l); + l.clear(); + key = QString::null; + if (line.contains('|') == 2 || line.right(7) == "BOOLEAN") + { + int p = line.find('|', 7); + key = line.mid(7, p-7); + } + } + else if (line.startsWith("CHOICE")) + { + int p = line.find('|', 7); + l << line.mid(7, p-7); + } + } + } + return dict; +} + +QMap<QString,QString> LPRngToolHandler::parseZOptions(const QString& optstr) +{ + QMap<QString,QString> opts; + QStringList l = QStringList::split(',', optstr, false); + if (l.count() == 0) + return opts; + + if (m_dict.count() == 0) + m_dict = loadChoiceDict(locate("data", "kdeprint/lprngtooldriver1")); + + QString unknown; + for (QStringList::ConstIterator it=l.begin(); it!=l.end(); ++it) + { + bool found(false); + for (QValueList< QPair<QString,QStringList> >::ConstIterator p=m_dict.begin(); p!=m_dict.end() && !found; ++p) + { + if ((*p).second.find(*it) != (*p).second.end()) + { + opts[(*p).first] = (*it); + found = true; + } + } + if (!found) + { + unknown.append(*it).append(','); + } + } + if (!unknown.isEmpty()) + { + unknown.truncate(unknown.length()-1); + opts["filter"] = unknown; + } + return opts; +} + +QString LPRngToolHandler::filterDir() +{ + return driverDirectory(); +} + +QString LPRngToolHandler::driverDirInternal() +{ + return locateDir("filters", "/usr/lib:/usr/local/lib:/opt/lib:/usr/libexec:/usr/local/libexec:/opt/libexec"); +} + +PrintcapEntry* LPRngToolHandler::createEntry(KMPrinter *prt) +{ + QString prot = prt->deviceProtocol(); + if (prot != "parallel" && prot != "lpd" && prot != "smb" && prot != "socket") + { + manager()->setErrorMsg(i18n("Unsupported backend: %1.").arg(prot)); + return NULL; + } + PrintcapEntry *entry = new PrintcapEntry; + entry->addField("cm", Field::String, prt->description()); + QString lp, comment("##LPRNGTOOL## "); + if (prot == "parallel") + { + comment.append("DEVICE "); + lp = prt->device().mid( 9 ); + entry->addField("rw@", Field::Boolean); + } + else if (prot == "socket") + { + comment.append("SOCKET "); + KURL url( prt->device() ); + lp = url.host(); + if (url.port() == 0) + lp.append("%9100"); + else + lp.append("%").append(QString::number(url.port())); + } + else if (prot == "lpd") + { + comment.append("QUEUE "); + KURL url( prt->device() ); + lp = url.path().mid(1) + "@" + url.host(); + } + else if (prot == "smb") + { + comment.append("SMB "); + lp = "| " + filterDir() + "/smbprint"; + QString work, server, printer, user, passwd; + if ( splitSmbURI( prt->device(), work, server, printer, user, passwd ) ) + { + entry->addField("xfer_options", Field::String, QString::fromLatin1("authfile=\"auth\" crlf=\"0\" hostip=\"\" host=\"%1\" printer=\"%2\" remote_mode=\"SMB\" share=\"//%3/%4\" workgroup=\"%5\"").arg(server).arg(printer).arg(server).arg(printer).arg(work)); + QFile authfile(LprSettings::self()->baseSpoolDir() + "/" + prt->printerName() + "/auth"); + if (authfile.open(IO_WriteOnly)) + { + QTextStream t(&authfile); + t << "username=" << user << endl; + t << "password=" << passwd << endl; + authfile.close(); + } + } + else + { + manager()->setErrorMsg( i18n( "Invalid printer backend specification: %1" ).arg( prt->device() ) ); + delete entry; + return NULL; + } + } + + if (prt->driver()) + { + DrMain *driver = prt->driver(); + comment.append("filtertype=IFHP ifhp_options=status@,sync@,pagecount@,waitend@ printerdb_entry="); + comment.append(driver->get("driverID")); + entry->addField("ifhp", Field::String, QString::fromLatin1("model=%1,status@,sync@,pagecount@,waitend@").arg(driver->get("driverID"))); + entry->addField("lprngtooloptions", Field::String, QString::fromLatin1("FILTERTYPE=\"IFHP\" IFHP_OPTIONS=\"status@,sync@,pagecount@,waitend@\" PRINTERDB_ENTRY=\"%1\"").arg(driver->get("driverID"))); + QMap<QString,QString> opts; + QString optstr; + driver->getOptions(opts, false); + for (QMap<QString,QString>::ConstIterator it=opts.begin(); it!=opts.end(); ++it) + if (it.key() != "lpr") + optstr.append(*it).append(","); + if (!optstr.isEmpty()) + { + optstr.truncate(optstr.length()-1); + entry->addField("prefix_z", Field::String, optstr); + } + if (!opts["lpr"].isEmpty()) + entry->addField("lpr", Field::String, opts["lpr"]); + } + + entry->addField("lp", Field::String, lp); + entry->comment = comment; + + return entry; +} + +bool LPRngToolHandler::savePrinterDriver(KMPrinter*, PrintcapEntry *entry, DrMain *driver, bool *mustSave) +{ + // save options in the "prefix_z" field and tell the manager to save the printcap file + QMap<QString,QString> opts; + QString optstr; + driver->getOptions(opts, false); + for (QMap<QString,QString>::ConstIterator it=opts.begin(); it!=opts.end(); ++it) + if (it.key() != "lpr") + optstr.append(*it).append(","); + if (!optstr.isEmpty()) + optstr.truncate(optstr.length()-1); + // save options in any case, otherwise nothing will happen whn + // options are reset to their default value + entry->addField("prefix_z", Field::String, optstr); + entry->addField("lpr", Field::String, opts["lpr"]); + if (mustSave) + *mustSave = true; + return true; +} + +QString LPRngToolHandler::printOptions(KPrinter *printer) +{ + QString optstr; + QMap<QString,QString> opts = printer->options(); + for (QMap<QString,QString>::ConstIterator it=opts.begin(); it!=opts.end(); ++it) + { + if (it.key().startsWith("kde-") || it.key().startsWith("_kde-") || it.key() == "lpr" || it.key().startsWith( "app-" )) + continue; + optstr.append(*it).append(","); + } + if (!optstr.isEmpty()) + { + optstr.truncate(optstr.length()-1); + optstr.prepend("-Z '").append("'"); + } + return optstr; +} diff --git a/kdeprint/lpr/lprngtoolhandler.h b/kdeprint/lpr/lprngtoolhandler.h new file mode 100644 index 000000000..ceff82393 --- /dev/null +++ b/kdeprint/lpr/lprngtoolhandler.h @@ -0,0 +1,54 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef LPRNGTOOLHANDLER_H +#define LPRNGTOOLHANDLER_H + +#include "lprhandler.h" +#include <qmap.h> +#include <qstringlist.h> +#include <qpair.h> + +class LPRngToolHandler : public LprHandler +{ +public: + LPRngToolHandler(KMManager *mgr = 0); + + bool validate(PrintcapEntry*); + bool completePrinter(KMPrinter*, PrintcapEntry*, bool = true); + DrMain* loadDriver(KMPrinter*, PrintcapEntry*, bool = false); + DrMain* loadDbDriver(const QString&); + PrintcapEntry* createEntry(KMPrinter*); + bool savePrinterDriver(KMPrinter*, PrintcapEntry*, DrMain*, bool* = 0); + QString printOptions(KPrinter*); + +protected: + QMap<QString,QString> parseXferOptions(const QString&); + void loadAuthFile(const QString&, QString&, QString&); + QValueList< QPair<QString,QStringList> > loadChoiceDict(const QString&); + QMap<QString,QString> parseZOptions(const QString&); + QString filterDir(); + QString driverDirInternal(); + + +private: + QValueList< QPair<QString,QStringList> > m_dict; +}; + +#endif diff --git a/kdeprint/lpr/lprsettings.cpp b/kdeprint/lpr/lprsettings.cpp new file mode 100644 index 000000000..90662a94c --- /dev/null +++ b/kdeprint/lpr/lprsettings.cpp @@ -0,0 +1,146 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001,2002 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "lprsettings.h" +#include "kmmanager.h" +#include "kmfactory.h" + +#include <kconfig.h> +#include <qfile.h> +#include <qtextstream.h> + +#define LPDCONF "/etc/lpd.conf" +#define PRINTCAP "/etc/printcap" + +LprSettings* LprSettings::m_self = 0; + +LprSettings::LprSettings(QObject *parent, const char *name) +: QObject(parent, name), KPReloadObject(true) +{ + init(); +} + +LprSettings::~LprSettings() +{ + m_self = 0; +} + +LprSettings* LprSettings::self() +{ + if (!m_self) + { + m_self = new LprSettings(KMManager::self(), "LprSettings"); + } + return m_self; +} + +void LprSettings::init() +{ + // LPR/LPRng mode + KConfig *conf = KMFactory::self()->printConfig(); + conf->setGroup("LPR"); + QString modestr = conf->readEntry("Mode"); + if (modestr == "LPRng") + m_mode = LPRng; + else if (modestr == "LPR") + m_mode = LPR; + else + { + // try to guess + if (QFile::exists(LPDCONF)) + m_mode = LPRng; + else + m_mode = LPR; + } + + // Printcap file + m_printcapfile = QString::null; + m_local = true; + + // Spool directory + m_spooldir = "/var/spool/lpd"; +} + +QString LprSettings::printcapFile() +{ + if (m_printcapfile.isEmpty()) + { + // default value + m_printcapfile = PRINTCAP; + if (m_mode == LPRng) + { + // look into /etc/lpd/conf file + QFile cf(LPDCONF); + if (cf.open(IO_ReadOnly)) + { + QTextStream t(&cf); + QString line; + while (!t.atEnd()) + { + line = t.readLine().stripWhiteSpace(); + if (line.startsWith("printcap_path")) + { + QString filename = line.mid(14).stripWhiteSpace(); + if (filename[0] != '|') + m_printcapfile = filename; + else + { + // should download the printcap file + // and set m_local to false + } + } + } + } + } + } + return m_printcapfile; +} + +QString LprSettings::defaultRemoteHost() +{ + if (m_defaultremotehost.isEmpty()) + { + m_defaultremotehost = "localhost"; + QFile cf(LPDCONF); + if (cf.open(IO_ReadOnly)) + { + QTextStream t(&cf); + QString line; + while (!t.atEnd()) + { + line = t.readLine().stripWhiteSpace(); + if (line.startsWith("default_remote_host")) + { + QString hostname = line.mid(20).stripWhiteSpace(); + m_defaultremotehost = hostname; + } + } + } + } + return m_defaultremotehost; +} + +void LprSettings::reload() +{ +} + +void LprSettings::configChanged() +{ + init(); +} diff --git a/kdeprint/lpr/lprsettings.h b/kdeprint/lpr/lprsettings.h new file mode 100644 index 000000000..c6d6fe64f --- /dev/null +++ b/kdeprint/lpr/lprsettings.h @@ -0,0 +1,67 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001,2002 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef LPRSETTINGS_H +#define LPRSETTINGS_H + +#if !defined( _KDEPRINT_COMPILE ) && defined( __GNUC__ ) +#warning internal header, do not use except if you are a KDEPrint developer +#endif + +#include <qobject.h> +#include <kdeprint/kpreloadobject.h> + +/** + * @internal + * This class is internal to KDEPrint and is not intended to be + * used outside it. Please do not make use of this header, except + * if you're a KDEPrint developer. The API might change in the + * future and binary compatibility might be broken. + */ +class LprSettings : public QObject, public KPReloadObject +{ +public: + LprSettings(QObject *parent = 0, const char *name = 0); + ~LprSettings(); + + static LprSettings* self(); + + enum Mode { LPR, LPRng }; + Mode mode() const { return m_mode; } + void setMode(Mode m) { m_mode = m; } + QString printcapFile(); + QString defaultRemoteHost(); + bool isLocalPrintcap() { return m_local; } + QString baseSpoolDir() { return m_spooldir; } + +protected: + void init(); + void reload(); + void configChanged(); + +private: + static LprSettings* m_self; + Mode m_mode; + QString m_printcapfile; + bool m_local; + QString m_spooldir; + QString m_defaultremotehost; +}; + +#endif diff --git a/kdeprint/lpr/make_driver_db_lpr.c b/kdeprint/lpr/make_driver_db_lpr.c new file mode 100644 index 000000000..fabbcb2fe --- /dev/null +++ b/kdeprint/lpr/make_driver_db_lpr.c @@ -0,0 +1,192 @@ +#include <config.h> +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <dirent.h> +#include <stdlib.h> +#include <unistd.h> +#include <ctype.h> + +#include "driverparse.h" + +void simplifyModel(const char *modelname) +{ + char *g; + + if ((g=strchr(modelname, ',')) != NULL) + *g = 0; + else if ((g=strchr(modelname, '(')) != NULL || (g=strchr(modelname, '{')) != NULL) + { + if (g != modelname) + { + if (isspace(*(g-1))) + g--; + *g = 0; + } + } +} + +int parseApsFile(const char *filename, FILE *output) +{ + FILE *apsfile; + char buf[256], modelname[256]; + char *c, *d; + + apsfile = fopen(filename, "r"); + if (apsfile == NULL) + return 0; + while (fgets(buf, 255, apsfile) != NULL) + { + if ((c = strchr(buf, '\n')) != NULL) + *c = 0; + if (strlen(buf) == 0 || buf[0] == '#' || (c = strchr(buf, '|')) == NULL) + continue; + *c = 0; + fprintf(output, "FILE=apsfilter/%s\n", c+1); + d = strchr(buf, ' '); + if (d) + { + *d = 0; + strlcpy(modelname, d+1, 255); + simplifyModel(modelname); + fprintf(output, "MANUFACTURER=%s\n", buf); + fprintf(output, "MODELNAME=%s\n", modelname); + fprintf(output, "MODEL=%s\n", modelname); + fprintf(output, "DESCRIPTION=%s %s (APSFilter + %s)\n", buf, d+1, c+1); + } + else + { + strlcpy(modelname, buf, 255); + simplifyModel(modelname); + fprintf(output, "MANUFACTURER=Unknown\n"); + fprintf(output, "MODELNAME=%s\n", modelname); + fprintf(output, "MODEL=%s\n", modelname); + fprintf(output, "DESCRIPTION=%s (APSFilter + %s)\n", buf, c+1); + } + fprintf(output, "\n"); + } + fclose(apsfile); + return 1; +} + +void initAps(const char *base) +{ + char drFile[256]; + DIR *apsdir; + struct dirent *d; + int gsversion = 0; + + if (strstr(base, "apsfilter") == NULL) + return; + + apsdir = opendir(base); + if (apsdir == NULL) + return; + while ((d = readdir(apsdir)) != NULL) + { + if (strncmp(d->d_name, "printer-", 8) != 0) + continue; + if (isdigit(d->d_name[8])) + { + if (gsversion) + continue; + gsversion = 1; + } + snprintf(drFile, 256, "apsfilter:%s/%s", base, d->d_name); + addFile(drFile); + } + closedir(apsdir); +} + +char* nextWord(char *c) +{ + char *d = c; + while (*d && isspace(*d)) + d++; + return d; +} + +int parseIfhpFile(const char *filename, FILE *output) +{ + char buf[1024]; + FILE *in; + char model[32], desc[256]; + + in = fopen(filename, "r"); + if (in == NULL) + return 0; + while (fgets(buf, 1023, in)) + { + char *c; + if ((c = strchr(buf, '\n')) != NULL) + *c = 0; + c = buf; + while (*c && isspace(*c)) + c++; + if (*c == '#') + continue; + if (strncmp(c, "IfhpModel:", 10) == 0) + strlcpy(model, nextWord(c+11), 31); + else if (strncmp(c, "Description:", 12) == 0) + strlcpy(desc, nextWord(c+13), 255); + else if (strncmp(c, "EndEntry", 8) == 0) + { + char *d = desc, *e, make[32] = {0}; + int first_time = 1; + do + { + e = strchr(d, ','); + if (e) + *e = 0; + if (first_time) + { + char *f = strchr(d, ' '); + if (f) + strlcpy(make, d, f-d); + first_time = 0; + } + if (strstr(d, "Family") == NULL) + { + char modelname[256] = {0}; + + strlcpy(modelname, d, 255); + simplifyModel(modelname); + fprintf(output, "FILE=lprngtool/%s\n", model); + fprintf(output, "MANUFACTURER=%s\n", make); + fprintf(output, "MODEL=%s\n", modelname); + fprintf(output, "MODELNAME=%s\n", modelname); + fprintf(output, "DESCRIPTION=%s (IFHP + %s)\n", d, model); + fprintf(output, "\n"); + } + if (e) + { + d = e+1; + while (*d && isspace(*d)) + d++; + } + } while (e); + } + } + fclose(in); + return 1; +} + +void initIfhp(const char *base) +{ + char path[256]; + + snprintf(path, 255, "lprngtool:%s/printerdb", base); + if (access(path+10, R_OK) == 0) + { + addFile(path); + } +} + +int main(int argc, char **argv) +{ + initFoomatic(); + registerHandler("apsfilter:", initAps, parseApsFile); + registerHandler("lprngtool:", initIfhp, parseIfhpFile); + return execute(argc, argv); +} diff --git a/kdeprint/lpr/matichandler.cpp b/kdeprint/lpr/matichandler.cpp new file mode 100644 index 000000000..a4b0d39a6 --- /dev/null +++ b/kdeprint/lpr/matichandler.cpp @@ -0,0 +1,481 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "matichandler.h" +#include "printcapentry.h" +#include "kmprinter.h" +#include "matichelper.h" +#include "driver.h" +#include "kpipeprocess.h" +#include "kmmanager.h" +#include "kprinter.h" +#include "lprsettings.h" +#include "util.h" +#include "foomatic2loader.h" + +#include <klocale.h> +#include <kstandarddirs.h> +#include <kapplication.h> +#include <kdebug.h> +#include <kprocess.h> +#include <qfile.h> +#include <qtextstream.h> +#include <qregexp.h> + +#include <stdlib.h> +#include <sys/wait.h> + +MaticHandler::MaticHandler(KMManager *mgr) +: LprHandler("foomatic", mgr) +{ + QString PATH = getenv("PATH"); + PATH.append(":/usr/sbin:/usr/local/sbin:/opt/sbin:/opt/local/sbin"); + m_exematicpath = KStandardDirs::findExe("lpdomatic", PATH); + m_ncpath = KStandardDirs::findExe("nc"); + m_smbpath = KStandardDirs::findExe("smbclient"); + m_rlprpath = KStandardDirs::findExe("rlpr"); +} + +bool MaticHandler::validate(PrintcapEntry *entry) +{ + if (entry) + return (entry->field("if").right(9) == "lpdomatic"); + return false; +} + +KMPrinter* MaticHandler::createPrinter(PrintcapEntry *entry) +{ + if (entry && validate(entry)) + { + KMPrinter *prt = new KMPrinter; + prt->setName(entry->name); + prt->setPrinterName(entry->name); + prt->setType(KMPrinter::Printer); + //if (entry->field("lp") == "/dev/null" || entry->field("lp").isEmpty()) + // prt->addType(KMPrinter::Remote); + return prt; + } + return NULL; +} + +bool MaticHandler::completePrinter(KMPrinter *prt, PrintcapEntry *entry, bool shortmode) +{ + QString val = entry->field("lp"); + if (val == "/dev/null" || val.isEmpty()) + { + prt->setLocation(i18n("Network printer")); + } + else + { + prt->setLocation(i18n("Local printer on %1").arg(val)); + KURL url(val); + if (val.find("usb") != -1) + url.setProtocol("usb"); + else + url.setProtocol("parallel"); + prt->setDevice(url.url()); + } + prt->setDescription(entry->aliases.join(", ")); + + if (!shortmode) + { + Foomatic2Loader loader; + if ( loader.readFromFile( maticFile( entry ) ) ) + { + QString postpipe = loader.data()[ "POSTPIPE" ].toString(); + if (!postpipe.isEmpty()) + { + KURL url ( parsePostpipe(postpipe) ); + if (!url.isEmpty()) + { + QString ds = QString::fromLatin1("%1 (%2)").arg(prt->location()).arg(url.protocol()); + prt->setDevice(url.url()); + prt->setLocation(ds); + } + } + + QMap<QString,QVariant> m = loader.data()[ "VAR" ].toMap(); + if ( !m.isEmpty() ) + { + prt->setManufacturer(m["make"].toString()); + prt->setModel(m["model"].toString()); + prt->setDriverInfo(QString::fromLatin1("%1 %2 (%3)").arg(prt->manufacturer()).arg(prt->model()).arg(m["driver"].toString())); + } + } + } + + return true; +} + +QString MaticHandler::parsePostpipe(const QString& s) +{ + QString url; + int p = s.findRev('|'); + QStringList args = QStringList::split(" ", s.right(s.length()-p-1)); + + if (args.count() != 0) + { + // socket printer + if (args[0].right(3) == "/nc") + { + url = "socket://" + args[ 1 ]; + if ( args.count() > 2 ) + url += ":" + args[ 2 ]; + else + url += ":9100"; + } + // smb printer + else if (args[0].right(10) == "/smbclient") + { + QStringList host_components = QStringList::split(QRegExp("/|\\\\\""), args[1], false); + QString workgrp, user, pass; + for (uint i=2; i<args.count(); i++) + { + if (args[i] == "-U") + user = args[++i]; + else if (args[i] == "-W") + workgrp = args[++i]; + else if (args[i][0] != '-' && i == 2) + pass = args[i]; + } + url = buildSmbURI( workgrp, host_components[ 0 ], host_components[ 1 ], user, pass ); + } + // remote printer + else if (args[0].right(5) == "/rlpr") + { + uint i=1; + while (i < args.count()) + { + if (args[i].left(2) != "-P") + i++; + else + { + QString host = (args[i].length() == 2 ? args[i+1] : args[i].right(args[i].length()-2)); + int p = host.find("\\@"); + if (p != -1) + { + url = "lpd://" + host.right(host.length()-p-2) + "/" + host.left(p); + } + break; + } + } + } + } + + return url; +} + +QString MaticHandler::createPostpipe(const QString& _url) +{ + KURL url( _url ); + QString prot = url.protocol(); + QString str; + if (prot == "socket") + { + str += ("| " + m_ncpath); + str += (" " + url.host()); + if (url.port() != 0) + str += (" " + QString::number(url.port())); + } + else if (prot == "lpd") + { + str += ("| " + m_rlprpath + " -q -h"); + QString h = url.host(), p = url.path().mid(1); + str += (" -P " + p + "\\@" + h); + } + else if (prot == "smb") + { + QString work, server, printer, user, passwd; + if ( splitSmbURI( _url, work, server, printer, user, passwd ) ) + { + str += ("| (\\n echo \\\"print -\\\"\\n cat \\n) | " + m_smbpath); + str += (" \\\"//" + server + "/" + printer + "\\\""); + if (!passwd.isEmpty()) + str += (" " + passwd); + if (!user.isEmpty()) + str += (" -U " + user); + if (!work.isEmpty()) + str += (" -W " + work); + str += " -N -P"; + } + } + return str; +} + +DrMain* MaticHandler::loadDriver(KMPrinter*, PrintcapEntry *entry, bool) +{ + // we need to use a copy of the driver, as the driver + // is not self-contained. If the printer is removed (when + // changing printer name), the template would be also removed + QString origfilename = maticFile(entry); + QString filename = locateLocal("tmp", "foomatic_" + kapp->randomString(8)); + ::system(QFile::encodeName("cp " + KProcess::quote(origfilename) + " " + KProcess::quote(filename))); + DrMain *driver = Foomatic2Loader::loadDriver(filename); + if (driver) + { + driver->set("template", filename); + driver->set("temporary", "true"); + return driver; + } + else + return NULL; +} + +DrMain* MaticHandler::loadDbDriver(const QString& path) +{ + QStringList comps = QStringList::split('/', path, false); + if (comps.count() < 3 || comps[0] != "foomatic") + { + manager()->setErrorMsg(i18n("Internal error.")); + return NULL; + } + + QString tmpFile = locateLocal("tmp", "foomatic_" + kapp->randomString(8)); + QString PATH = getenv("PATH") + QString::fromLatin1(":/usr/sbin:/usr/local/sbin:/opt/sbin:/opt/local/sbin"); + QString exe = KStandardDirs::findExe("foomatic-datafile", PATH); + if (exe.isEmpty()) + { + manager()->setErrorMsg(i18n("Unable to find the executable foomatic-datafile " + "in your PATH. Check that Foomatic is correctly installed.")); + return NULL; + } + + KPipeProcess in; + QFile out(tmpFile); + QString cmd = KProcess::quote(exe); + cmd += " -t lpd -d "; + cmd += KProcess::quote(comps[2]); + cmd += " -p "; + cmd += KProcess::quote(comps[1]); + if (in.open(cmd) && out.open(IO_WriteOnly)) + { + QTextStream tin(&in), tout(&out); + QString line; + while (!tin.atEnd()) + { + line = tin.readLine(); + tout << line << endl; + } + in.close(); + out.close(); + + DrMain *driver = Foomatic2Loader::loadDriver(tmpFile); + if (driver) + { + driver->set("template", tmpFile); + driver->set("temporary", tmpFile); + return driver; + } + } + manager()->setErrorMsg(i18n("Unable to create the Foomatic driver [%1,%2]. " + "Either that driver does not exist, or you don't have " + "the required permissions to perform that operation.").arg(comps[1]).arg(comps[2])); + return NULL; +} + +bool MaticHandler::savePrinterDriver(KMPrinter *prt, PrintcapEntry *entry, DrMain *driver, bool*) +{ + QFile tmpFile(locateLocal("tmp", "foomatic_" + kapp->randomString(8))); + QFile inFile(driver->get("template")); + QString outFile = maticFile(entry); + bool result(false); + QString postpipe = createPostpipe(prt->device()); + + if (inFile.open(IO_ReadOnly) && tmpFile.open(IO_WriteOnly)) + { + QTextStream tin(&inFile), tout(&tmpFile); + QString line, optname; + int p(-1), q(-1); + if (!postpipe.isEmpty()) + tout << "$postpipe = \"" << postpipe << "\";" << endl; + while (!tin.atEnd()) + { + line = tin.readLine(); + if (line.stripWhiteSpace().startsWith("$postpipe")) + continue; + else if ((p = line.find("'name'")) != -1) + { + p = line.find('\'', p+6)+1; + q = line.find('\'', p); + optname = line.mid(p, q-p); + } + else if ((p = line.find("'default'")) != -1) + { + DrBase *opt = driver->findOption(optname); + if (opt) + { + tout << line.left(p+9) << " => '" << opt->valueText() << "'," << endl; + continue; + } + } + tout << line << endl; + } + inFile.close(); + tmpFile.close(); + + QString cmd = "mv " + KProcess::quote(tmpFile.name()) + " " + KProcess::quote(outFile); + int status = ::system(QFile::encodeName(cmd).data()); + QFile::remove(tmpFile.name()); + result = (status != -1 && WEXITSTATUS(status) == 0); + } + + if (!result) + manager()->setErrorMsg(i18n("You probably don't have the required permissions " + "to perform that operation.")); + QFile::remove(tmpFile.name()); + if (!result || entry->field("ppdfile").isEmpty()) + return result; + else + return savePpdFile(driver, entry->field("ppdfile")); +} + +bool MaticHandler::savePpdFile(DrMain *driver, const QString& filename) +{ + QString mdriver(driver->get("matic_driver")), mprinter(driver->get("matic_printer")); + if (mdriver.isEmpty() || mprinter.isEmpty()) + return true; + + QString PATH = getenv("PATH") + QString::fromLatin1(":/usr/sbin:/usr/local/sbin:/opt/sbin:/opt/local/sbin"); + QString exe = KStandardDirs::findExe("foomatic-datafile", PATH); + if (exe.isEmpty()) + { + manager()->setErrorMsg(i18n("Unable to find the executable foomatic-datafile " + "in your PATH. Check that Foomatic is correctly installed.")); + return false; + } + + KPipeProcess in; + QFile out(filename); + if (in.open(exe + " -t cups -d " + mdriver + " -p " + mprinter) && out.open(IO_WriteOnly)) + { + QTextStream tin(&in), tout(&out); + QString line, optname; + QRegExp re("^\\*Default(\\w+):"), foo("'name'\\s+=>\\s+'(\\w+)'"), foo2("'\\w+'\\s*,\\s*$"); + while (!tin.atEnd()) + { + line = tin.readLine(); + if (line.startsWith("*% COMDATA #")) + { + if (line.find("'default'") != -1) + { + DrBase *opt = (optname.isEmpty() ? NULL : driver->findOption(optname)); + if (opt) + { + line.replace(foo2, "'"+opt->valueText()+"',"); + } + } + else if (foo.search(line) != -1) + optname = foo.cap(1); + } + else if (re.search(line) != -1) + { + DrBase *opt = driver->findOption(re.cap(1)); + if (opt) + { + QString val = opt->valueText(); + if (opt->type() == DrBase::Boolean) + val = (val == "1" ? "True" : "False"); + tout << "*Default" << opt->name() << ": " << val << endl; + continue; + } + } + tout << line << endl; + } + in.close(); + out.close(); + + return true; + } + manager()->setErrorMsg(i18n("Unable to create the Foomatic driver [%1,%2]. " + "Either that driver does not exist, or you don't have " + "the required permissions to perform that operation.").arg(mdriver).arg(mprinter)); + + return false; +} + +PrintcapEntry* MaticHandler::createEntry(KMPrinter *prt) +{ + KURL url( prt->device() ); + QString prot = url.protocol(); + if ((prot != "lpd" || m_rlprpath.isEmpty()) && + (prot != "socket" || m_ncpath.isEmpty()) && + (prot != "smb" || m_smbpath.isEmpty()) && + prot != "parallel") + { + manager()->setErrorMsg(i18n("Unsupported backend: %1.").arg(prot)); + return NULL; + } + if (m_exematicpath.isEmpty()) + { + manager()->setErrorMsg(i18n("Unable to find executable lpdomatic. " + "Check that Foomatic is correctly installed " + "and that lpdomatic is installed in a standard " + "location.")); + return NULL; + } + PrintcapEntry *entry = new PrintcapEntry; + entry->addField("lf", Field::String, "/var/log/lp-errs"); + entry->addField("lp", Field::String, (prot != "parallel" ? "/dev/null" : url.path())); + entry->addField("if", Field::String, m_exematicpath); + if (LprSettings::self()->mode() == LprSettings::LPRng) + { + entry->addField("filter_options", Field::String, " --lprng $Z /etc/foomatic/lpd/"+prt->printerName()+".lom"); + entry->addField("force_localhost", Field::Boolean); + entry->addField("ppdfile", Field::String, "/etc/foomatic/"+prt->printerName()+".ppd"); + } + else + entry->addField("af", Field::String, "/etc/foomatic/lpd/"+prt->printerName()+".lom"); + if (!prt->description().isEmpty()) + entry->aliases << prt->description(); + return entry; +} + +bool MaticHandler::removePrinter(KMPrinter *prt, PrintcapEntry *entry) +{ + // remove Foomatic driver + QString af = entry->field("af"); + if (af.isEmpty()) + return true; + if (!QFile::remove(af)) + { + manager()->setErrorMsg(i18n("Unable to remove driver file %1.").arg(af)); + return false; + } + return true; +} + +QString MaticHandler::printOptions(KPrinter *printer) +{ + QMap<QString,QString> opts = printer->options(); + QString str; + for (QMap<QString,QString>::Iterator it=opts.begin(); it!=opts.end(); ++it) + { + if (it.key().startsWith("kde-") || it.key().startsWith("_kde-") || it.key().startsWith( "app-" )) + continue; + str += (" " + it.key() + "=" + (*it)); + } + if (!str.isEmpty()) + str.prepend("-J '").append("'"); + return str; +} + +QString MaticHandler::driverDirInternal() +{ + return locateDir("foomatic/db/source", "/usr/share:/usr/local/share:/opt/share"); +} diff --git a/kdeprint/lpr/matichandler.h b/kdeprint/lpr/matichandler.h new file mode 100644 index 000000000..1cbcc9941 --- /dev/null +++ b/kdeprint/lpr/matichandler.h @@ -0,0 +1,57 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef MATICHANDLER_H +#define MATICHANDLER_H + +#include "lprhandler.h" + +#include <kurl.h> + +class MaticBlock; + +class MaticHandler : public LprHandler +{ +public: + MaticHandler(KMManager *mgr = 0); + + bool validate(PrintcapEntry*); + KMPrinter* createPrinter(PrintcapEntry*); + bool completePrinter(KMPrinter*, PrintcapEntry*, bool = true); + DrMain* loadDriver(KMPrinter*, PrintcapEntry*, bool = false); + DrMain* loadDbDriver(const QString&); + bool savePrinterDriver(KMPrinter*, PrintcapEntry*, DrMain*, bool* = 0); + PrintcapEntry* createEntry(KMPrinter*); + bool removePrinter(KMPrinter*, PrintcapEntry*); + QString printOptions(KPrinter*); + +protected: + QString driverDirInternal(); + +private: + QString parsePostpipe(const QString&); + QString createPostpipe(const QString&); + bool savePpdFile(DrMain*, const QString&); + +private: + QString m_exematicpath; + QString m_ncpath, m_smbpath, m_rlprpath; +}; + +#endif diff --git a/kdeprint/lpr/matichelper.cpp b/kdeprint/lpr/matichelper.cpp new file mode 100644 index 000000000..230bcd55b --- /dev/null +++ b/kdeprint/lpr/matichelper.cpp @@ -0,0 +1,38 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2002 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "matichelper.h" +#include "printcapentry.h" +#include "driver.h" + +QString maticFile(PrintcapEntry *entry) +{ + QString s(entry->field("af")); + if (s.isEmpty()) + { + s = entry->field("filter_options"); + if (!s.isEmpty()) + { + int p = s.findRev(' '); + if (p != -1) + s = s.mid(p+1); + } + } + return s; +} diff --git a/kdeprint/lpr/matichelper.h b/kdeprint/lpr/matichelper.h new file mode 100644 index 000000000..8d78d57e7 --- /dev/null +++ b/kdeprint/lpr/matichelper.h @@ -0,0 +1,29 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2002 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef MATICHELPER_H +#define MATICHELPER_H + +#include <qstring.h> + +class PrintcapEntry; + +QString maticFile(PrintcapEntry*); + +#endif diff --git a/kdeprint/lpr/printcapentry.cpp b/kdeprint/lpr/printcapentry.cpp new file mode 100644 index 000000000..0a8d79ce4 --- /dev/null +++ b/kdeprint/lpr/printcapentry.cpp @@ -0,0 +1,82 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001,2002 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "printcapentry.h" + +QString Field::toString() const +{ + QString s = name; + switch (type) + { + case String: + s += ("=" + value); + break; + case Integer: + s += ("#" + value); + break; + case Boolean: + if (!value.toInt()) + s += "@"; + break; + } + return s; +} + +bool PrintcapEntry::writeEntry(QTextStream& t) +{ + t << comment << endl; + t << name; + if (aliases.count() > 0) + t << '|' << aliases.join("|"); + t << ':'; + for (QMap<QString,Field>::ConstIterator it=fields.begin(); it!=fields.end(); ++it) + { + t << '\\' << endl << " :"; + t << (*it).name; + switch ((*it).type) + { + case Field::String: + t << '=' << (*it).value << ':'; + break; + case Field::Integer: + t << '#' << (*it).value << ':'; + break; + case Field::Boolean: + t << ':'; + break; + default: + t << endl << endl; + return false; + } + } + t << endl; + if (!postcomment.isEmpty()) + t << postcomment << endl; + t << endl; + return true; +} + +void PrintcapEntry::addField(const QString& name, Field::Type type, const QString& value) +{ + Field f; + f.name = name; + f.type = type; + f.value = value; + fields[name] = f; +} diff --git a/kdeprint/lpr/printcapentry.h b/kdeprint/lpr/printcapentry.h new file mode 100644 index 000000000..17dbb9275 --- /dev/null +++ b/kdeprint/lpr/printcapentry.h @@ -0,0 +1,81 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef PRINTCAPENTRY_H +#define PRINTCAPENTRY_H + +#if !defined( _KDEPRINT_COMPILE ) && defined( __GNUC__ ) +#warning internal header, do not use except if you are a KDEPrint developer +#endif + +#include <qstring.h> +#include <qmap.h> +#include <qstringlist.h> +#include <qtextstream.h> + +/** + * @internal + * This class is internal to KDEPrint and is not intended to be + * used outside it. Please do not make use of this header, except + * if you're a KDEPrint developer. The API might change in the + * future and binary compatibility might be broken. + */ +class Field +{ +public: + enum Type { String, Integer, Boolean }; + Field() : type(String) {} + Field(const Field &f) : type(f.type), name(f.name), value(f.value) {} + Field& operator= (const Field& f) + { + type = f.type; + name = f.name; + value = f.value; + return (*this); + } + QString toString() const; + + Type type; + QString name; + QString value; +}; + +/** + * @internal + * This class is internal to KDEPrint and is not intended to be + * used outside it. Please do not make use of this header, except + * if you're a KDEPrint developer. The API might change in the + * future and binary compatibility might be broken. + */ +class PrintcapEntry +{ +public: + QString name; + QStringList aliases; + QString comment; + QMap<QString,Field> fields; + QString postcomment; + + bool has(const QString& f) const { return fields.contains(f); } + QString field(const QString& f) const { return fields[f].value; } + bool writeEntry(QTextStream&); + void addField(const QString& name, Field::Type type = Field::Boolean, const QString& value = QString::null); +}; + +#endif diff --git a/kdeprint/lpr/printcapreader.cpp b/kdeprint/lpr/printcapreader.cpp new file mode 100644 index 000000000..b57d33ba0 --- /dev/null +++ b/kdeprint/lpr/printcapreader.cpp @@ -0,0 +1,176 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "printcapreader.h" +#include "printcapentry.h" + +#include <qfile.h> +#include <kdebug.h> + +void PrintcapReader::setPrintcapFile(QFile *f) +{ + if (f->isOpen()) + { + m_stream.setDevice(f); + m_buffer = QString::null; + } +} + +bool PrintcapReader::nextLine(QString& line) +{ + if (m_stream.atEnd() && m_buffer.isEmpty()) + return false; + else if (!m_buffer.isEmpty()) + { + line = m_buffer; + m_buffer = QString::null; + } + else + line = m_stream.readLine().stripWhiteSpace(); + // strip any '\' at the end + if (line[line.length()-1] == '\\') + line = line.left(line.length()-1).stripWhiteSpace(); + return true; +} + +void PrintcapReader::unputLine(const QString& s) +{ + m_buffer = s; +} + +PrintcapEntry* PrintcapReader::nextEntry() +{ + if (!m_stream.device()) + return NULL; + + QString line, comment, name, fields, buf; + // skip comments, keep last one + while (1) + { + if (!nextLine(line)) + return NULL; + else if (line.isEmpty()) + continue; + else if (line[0] == '#') + comment = line; + else + { + buf = line; + break; + } + } + + // look for the complete entry + while (1) + { + // we found the entry if we reached the end of file or + // found an empty line + if (!nextLine(line) || line.isEmpty()) + break; + // just skip comments + else if (line[0] == '#') + continue; + // lines starting with ':' or '|' are appended + else if (line[0] == ':' || line[0] == '|') + buf += line; + // otherwise it's another entry, put it back in the + // buffer + else + { + unputLine(line); + break; + } + } + + // now parse the entry + kdDebug() << "COMMENT: " << comment << endl; + kdDebug() << "LINE: " << buf << endl; + int p = buf.find(':'); + if (p == -1) + name = buf; + else + { + name = buf.left(p); + fields = buf.right(buf.length()-p-1); + } + + // construct the printcap entry + if (!name.isEmpty()) + { + PrintcapEntry *entry = new PrintcapEntry; + QStringList l = QStringList::split('|', name, false); + entry->name = l[0]; + entry->comment = comment; + // kdDebug() << "Printer: " << entry->name << endl; + // kdDebug() << "Aliases:" << endl; + for (uint i=1; i<l.count(); i++) + { + entry->aliases << l[i]; + // kdDebug() << " " << l[i] << endl; + } + if (!fields.isEmpty()) + { + // kdDebug() << "Fields:" << endl; + // kdDebug() << "(" << fields << ")" << endl; + l = QStringList::split(':', fields, false); + for (QStringList::ConstIterator it=l.begin(); it!=l.end(); ++it) + { + Field f; + int p = (*it).find('='); + if (p == -1) + { + p = (*it).find('#'); + if (p == -1) + { + f.type = Field::Boolean; + p = (*it).find('@'); + if (p == -1) + { + f.name = (*it); + f.value = "1"; + } + else + { + f.name = (*it).left(p); + f.value = "0"; + } + } + else + { + f.type = Field::Integer; + f.name = (*it).left(p); + f.value = (*it).mid(p+1); + } + } + else + { + f.type = Field::String; + f.name = (*it).left(p); + f.value = (*it).mid(p+1); + if (f.value.startsWith("\"")) + f.value = f.value.mid(1, f.value.length()-2); + } + entry->fields[f.name] = f; + } + } + // kdDebug() << endl; + return entry; + } + return NULL; +} diff --git a/kdeprint/lpr/printcapreader.h b/kdeprint/lpr/printcapreader.h new file mode 100644 index 000000000..4741f2520 --- /dev/null +++ b/kdeprint/lpr/printcapreader.h @@ -0,0 +1,43 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef PRINTCAPREADER_H +#define PRINTCAPREADER_H + +#include <qstring.h> +#include <qtextstream.h> + +class QFile; +class PrintcapEntry; + +class PrintcapReader +{ +public: + void setPrintcapFile(QFile*); + PrintcapEntry* nextEntry(); + +private: + QString m_buffer; + QTextStream m_stream; + + bool nextLine(QString&); + void unputLine(const QString&); +}; + +#endif |