summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYash Srivastav <yash111998@gmail.com>2017-07-27 08:11:34 +0530
committerCaolán McNamara <caolanm@redhat.com>2017-09-12 10:54:52 +0200
commit7fbf98d99737ac916cc2dc374f3139e2ea81e47b (patch)
treef67793fd3d086d0a5c39ad45cc3b510ce1dffb6d
parentd2335e83c3e798cc72a9cf3b3e31eeefe4b5a39c (diff)
Add Common Printing Dialog Functionality
Summary: These set of commits add support for the Common Printing Dialog Backends being developed as part of GSoC'17. All backends exist as dbus-services which can be queried for printers, their options, etc. Test Plan: Firstly, without adding any CPD backend, LO printing should work as it works now with graceful fallback to CUPS. Next, we need to install a backend. The backend providing CUPS interface is at git@github.com:NilanjanaLodh/PrintDialog_Backend.git See README.md for installation instructions. After this, run LO and existing CUPS Printers should show up. Also printing does send a job to cups which can be seen at: http://localhost:631/jobs?which_jobs=completed Due to LO shutdown not being handled properly currently, the backend might need to be killed via `pkill print_backend_cups` Future Plans: * Fix shutdown actions. Change-Id: I3bdea5d3272ec4c9c0dfe510f5848fcb398b4b14 Reviewed-on: https://gerrit.libreoffice.org/40565 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Caolán McNamara <caolanm@redhat.com> Tested-by: Caolán McNamara <caolanm@redhat.com>
-rw-r--r--include/vcl/ppdparser.hxx3
-rw-r--r--vcl/inc/unx/cpdmgr.hxx78
-rw-r--r--vcl/unx/generic/printer/cpdmgr.cxx654
-rw-r--r--vcl/unx/generic/printer/ppdparser.cxx124
4 files changed, 698 insertions, 161 deletions
diff --git a/include/vcl/ppdparser.hxx b/include/vcl/ppdparser.hxx
index 9212516fc8e5..ecbda153af79 100644
--- a/include/vcl/ppdparser.hxx
+++ b/include/vcl/ppdparser.hxx
@@ -60,6 +60,7 @@ struct VCL_DLLPUBLIC PPDValue
class VCL_DLLPUBLIC PPDKey
{
friend class PPDParser;
+ friend class CPDManager;
typedef std::unordered_map< OUString, PPDValue, OUStringHash > hash_type;
typedef std::vector< PPDValue* > value_type;
@@ -120,6 +121,7 @@ class VCL_DLLPUBLIC PPDParser
{
friend class PPDContext;
friend class CUPSManager;
+ friend class CPDManager;
friend class PPDCache;
typedef std::unordered_map< OUString, PPDKey*, OUStringHash > hash_type;
@@ -174,6 +176,7 @@ private:
PPDTranslator* m_pTranslator;
PPDParser( const OUString& rFile );
+ PPDParser( const OUString& rFile, std::vector<PPDKey*> keys );
~PPDParser();
void parseOrderDependency(const OString& rLine);
diff --git a/vcl/inc/unx/cpdmgr.hxx b/vcl/inc/unx/cpdmgr.hxx
index d60f098435fb..48fb02ab3a2a 100644
--- a/vcl/inc/unx/cpdmgr.hxx
+++ b/vcl/inc/unx/cpdmgr.hxx
@@ -30,52 +30,100 @@
#include "printerinfomanager.hxx"
#include "cupsmgr.hxx"
+#define BACKEND_DIR "/usr/share/print-backends"
+#define FRONTEND_INTERFACE "/usr/share/dbus-1/interfaces/org.openprinting.Frontend.xml"
+#define BACKEND_INTERFACE "/usr/share/dbus-1/interfaces/org.openprinting.Backend.xml"
+
namespace psp
{
+class PPDParser;
+
struct CPDPrinter
{
- std::string name;
- std::string info;
- std::string location;
- std::string make_and_model;
- std::string printer_state;
+ const char* id;
+ const char* name;
+ const char* info;
+ const char* location;
+ const char* make_and_model;
+ const char* printer_state;
+ const char* backend_name;
bool is_accepting_jobs;
GDBusProxy* backend;
};
+struct CPDPrinterOption
+{
+ OUString name;
+ OUString default_value;
+ int num_supported_values;
+ std::vector<OUString> supported_values;
+};
+
class CPDManager : public PrinterInfoManager
{
#if ENABLE_DBUS && ENABLE_GIO
GDBusConnection * m_pConnection = nullptr;
bool m_aPrintersChanged = true;
+ std::vector<std::pair<std::string, gchar*>> m_tBackends;
std::unordered_map< std::string, GDBusProxy * > m_pBackends;
std::unordered_map< FILE*, OString, FPtrHash > m_aSpoolFiles;
std::unordered_map< OUString, CPDPrinter *, OUStringHash > m_aCPDDestMap;
+ std::unordered_map< OUString, PPDContext, OUStringHash > m_aDefaultContexts;
#endif
CPDManager();
+ // Function called when CPDManager is destroyed
+ virtual ~CPDManager() override;
+
+ static void onNameAcquired(GDBusConnection *connection, const char* name, void* user_data);
+ static void onNameLost (GDBusConnection *, const char *name, void*);
+ static void printerAdded (GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data);
+ static void printerRemoved (GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data);
+
virtual void initialize() override;
+ static void getOptionsFromDocumentSetup( const JobData& rJob, bool bBanner, const OString& rJobName, int& rNumOptions, GVariant **arr );
+
+
public:
+ // Functions involved in initialization
GDBusProxy * getProxy( std::string target );
void addBackend( std::pair< std::string, GDBusProxy * > pair );
- void addDestination( std::pair< OUString, CPDPrinter * > pair );
+ void addTempBackend( std::pair< std::string, gchar* > pair );
+ std::vector<std::pair<std::string, gchar*>> getTempBackends();
+ void addNewPrinter( const OUString&, const OUString&, CPDPrinter * );
+
+ // Create CPDManager
static CPDManager* tryLoadCPD();
- virtual ~CPDManager() override;
+
+ // Create a PPDParser for CPD Printers
+ const PPDParser* createCPDParser( const OUString& rPrinter );
+
+ // Functions related to printing
+ virtual FILE* startSpool( const OUString& rPrinterName, bool bQuickCommand ) override;
+ virtual bool endSpool( const OUString& rPrinterName, const OUString& rJobTitle, FILE* pFile, const JobData& rDocumentJobData, bool bBanner, const OUString& rFaxNumber ) override;
virtual void setupJobContextData( JobData& rData ) override;
- /// check if the printer configuration has changed
+
+ // check if the printer configuration has changed
virtual bool checkPrintersChanged( bool bWait ) override;
+
// members for administration
- // disable for CUPS
+ // disable for CPD
virtual bool addPrinter( const OUString& rPrinterName, const OUString& rDriverName ) override;
virtual bool removePrinter( const OUString& rPrinterName, bool bCheckOnly ) override;
- virtual bool writePrinterConfig() override;
virtual bool setDefaultPrinter( const OUString& rPrinterName ) override;
-
- virtual FILE* startSpool( const OUString& rPrinterName, bool bQuickCommand ) override;
- virtual bool endSpool( const OUString& rPrinterName, const OUString& rJobTitle, FILE* pFile, const JobData& rDocumentJobData, bool bBanner, const OUString& rFaxNumber ) override;
-
-
};
} // namespace psp
diff --git a/vcl/unx/generic/printer/cpdmgr.cxx b/vcl/unx/generic/printer/cpdmgr.cxx
index 1dbdc45eab6c..1cd48e626351 100644
--- a/vcl/unx/generic/printer/cpdmgr.cxx
+++ b/vcl/unx/generic/printer/cpdmgr.cxx
@@ -35,18 +35,15 @@ using namespace psp;
using namespace osl;
// Function to execute when name is acquired on the bus
-static void on_name_acquired (GDBusConnection *connection,
- const gchar *name,
- gpointer)
+void CPDManager::onNameAcquired (GDBusConnection *connection,
+ const gchar *,
+ gpointer user_data)
{
- g_message("Name Acquired %s", name);
-
- GError *local_error, *error;
gchar* contents;
- GDBusNodeInfo *introspection_data = nullptr;
+ GDBusNodeInfo *introspection_data;
// Get Interface for introspection
- g_file_get_contents ("/home/yash/bigGit/PrintDialog_Backend/org.openprinting.Frontend.xml", &contents, nullptr, &error);
+ g_file_get_contents (FRONTEND_INTERFACE, &contents, nullptr, nullptr);
introspection_data = g_dbus_node_info_new_for_xml (contents, nullptr);
g_dbus_connection_register_object (connection,
@@ -56,72 +53,118 @@ static void on_name_acquired (GDBusConnection *connection,
nullptr, /* user_data */
nullptr, /* user_data_free_func */
nullptr); /* GError** */
- local_error = nullptr;
- g_dbus_connection_emit_signal (connection,
- nullptr,
- "/org/libreoffice/PrintDialog",
- "org.openprinting.PrintFrontend",
- "GetBackend",
- nullptr,
- &local_error);
- g_assert_no_error (local_error);
- g_message("Emitted Signal GetBackend");
+ g_free(contents);
+ g_dbus_node_info_unref(introspection_data);
+
+ CPDManager* current = static_cast<CPDManager*>(user_data);
+ std::vector<std::pair<std::string, gchar*>> backends = current -> getTempBackends();
+ for (std::vector<std::pair<std::string, gchar*>>::iterator it = backends.begin(); it != backends.end(); ++it) {
+ GDBusProxy *proxy;
+ // Get Interface for introspection
+ g_file_get_contents (BACKEND_INTERFACE, &contents, nullptr, nullptr);
+ introspection_data = g_dbus_node_info_new_for_xml (contents, nullptr);
+ proxy = g_dbus_proxy_new_sync (connection,
+ G_DBUS_PROXY_FLAGS_NONE,
+ introspection_data->interfaces[0],
+ it -> first.c_str(),
+ it -> second,
+ "org.openprinting.PrintBackend",
+ nullptr,
+ nullptr);
+ g_free(it -> second);
+ g_assert (proxy != nullptr);
+ g_dbus_proxy_call(proxy, "ActivateBackend",
+ nullptr,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, nullptr, nullptr, nullptr);
+
+ g_free(contents);
+ g_object_unref(proxy);
+ g_dbus_node_info_unref(introspection_data);
+ }
}
-static void on_name_lost (GDBusConnection *,
- const gchar *name,
- gpointer)
+void CPDManager::onNameLost (GDBusConnection *,
+ const gchar *name,
+ gpointer)
{
g_message("Name Lost: %s", name);
}
-static void got_signal (GDBusConnection *connection,
- const gchar *sender_name,
- const gchar *object_path,
- const gchar *interface_name,
- const gchar *signal_name,
- GVariant *parameters,
- gpointer user_data)
+void CPDManager::printerAdded (GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *,
+ GVariant *parameters,
+ gpointer user_data)
{
CPDManager* current = static_cast<CPDManager*>(user_data);
- g_message("Received %s from %s at %s", signal_name, sender_name, object_path);
- if (g_strcmp0 (signal_name, "PrinterAdded") == 0)
- {
- GDBusProxy *proxy;
- proxy = current -> getProxy(sender_name);
- if (proxy == nullptr) {
- gchar* contents;
- GDBusNodeInfo *introspection_data = nullptr;
-
- // Get Interface for introspection
- g_file_get_contents ("/home/yash/bigGit/PrintDialog_Backend/org.openprinting.Backend.xml", &contents, nullptr, nullptr);
- introspection_data = g_dbus_node_info_new_for_xml (contents, nullptr);
- proxy = g_dbus_proxy_new_sync (connection,
- G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
- introspection_data->interfaces[0],
- sender_name,
- object_path,
- interface_name,
- nullptr,
- nullptr);
- std::pair<std::string, GDBusProxy *> new_backend (sender_name, proxy);
- current -> addBackend(new_backend);
- }
- CPDPrinter *pDest = static_cast<CPDPrinter *>(malloc(sizeof(CPDPrinter)));
- // const gchar *name, *info, *location, *make_and_model, *state;
- // gboolean is_accepting_jobs;
- g_variant_get (parameters, "(ssssbs)", &(pDest -> name), &(pDest -> info), &(pDest -> location), &(pDest -> make_and_model), &(pDest -> is_accepting_jobs), &(pDest -> printer_state));
- g_message("State: %s", (pDest -> printer_state).c_str());
- const char *pName = (pDest -> name).c_str();
- rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
- OUString aPrinterName = OStringToOUString( pName, aEncoding );
- std::pair<OUString, CPDPrinter *> newDest (aPrinterName, pDest);
- current -> addDestination(newDest);
- } else if (g_strcmp0 (signal_name, "UpdatePrinter") == 0)
- {
- } else if (g_strcmp0 (signal_name, "DeletePrinter") == 0)
- {
- }
+ GDBusProxy *proxy;
+ proxy = current -> getProxy(sender_name);
+ if (proxy == nullptr) {
+ gchar* contents;
+ GDBusNodeInfo *introspection_data;
+
+ // Get Interface for introspection
+ g_file_get_contents ("/usr/share/dbus-1/interfaces/org.openprinting.Backend.xml", &contents, nullptr, nullptr);
+ introspection_data = g_dbus_node_info_new_for_xml (contents, nullptr);
+ proxy = g_dbus_proxy_new_sync (connection,
+ G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+ introspection_data->interfaces[0],
+ sender_name,
+ object_path,
+ interface_name,
+ nullptr,
+ nullptr);
+
+ g_free(contents);
+ g_dbus_node_info_unref(introspection_data);
+ std::pair<std::string, GDBusProxy *> new_backend (sender_name, proxy);
+ current -> addBackend(new_backend);
+ }
+ CPDPrinter *pDest = static_cast<CPDPrinter *>(malloc(sizeof(CPDPrinter)));
+ pDest -> backend = proxy;
+ g_variant_get (parameters, "(sssssbss)", &(pDest -> id), &(pDest -> name), &(pDest -> info), &(pDest -> location), &(pDest -> make_and_model), &(pDest -> is_accepting_jobs), &(pDest -> printer_state), &(pDest -> backend_name));
+ std::stringstream printerName;
+ printerName << pDest -> name << ", " << pDest -> backend_name;
+ std::stringstream uniqueName;
+ uniqueName << pDest -> id << ", " << pDest -> backend_name;
+ rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
+ OUString aPrinterName = OStringToOUString( printerName.str().c_str(), aEncoding );
+ OUString aUniqueName = OStringToOUString( uniqueName.str().c_str(), aEncoding );
+ current -> addNewPrinter(aPrinterName, aUniqueName, pDest);
+}
+
+void CPDManager::printerRemoved (GDBusConnection *,
+ const gchar *,
+ const gchar *,
+ const gchar *,
+ const gchar *,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ // TODO: Remove every data linked to this particular printer.
+ CPDManager* pManager = static_cast<CPDManager*>(user_data);
+ char* id;
+ char* backend_name;
+ g_variant_get (parameters, "(ss)", &id, &backend_name);
+ std::stringstream uniqueName;
+ uniqueName << id << ", " << backend_name;
+ rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
+ OUString aUniqueName = OStringToOUString( uniqueName.str().c_str(), aEncoding );
+ std::unordered_map<OUString, CPDPrinter *, OUStringHash>::iterator it = pManager->m_aCPDDestMap.find( aUniqueName );
+ if (it == pManager->m_aCPDDestMap.end()) {
+ SAL_WARN("vcl.unx.print", "CPD trying to remove non-existent printer from list");
+ return;
+ }
+ pManager->m_aCPDDestMap.erase(it);
+ std::unordered_map<OUString, Printer, OUStringHash>::iterator printersIt = pManager->m_aPrinters.find( aUniqueName );
+ if (printersIt == pManager->m_aPrinters.end()) {
+ SAL_WARN("vcl.unx.print", "CPD trying to remove non-existent printer from m_aPrinters");
+ return;
+ }
+ pManager->m_aPrinters.erase(printersIt);
}
GDBusProxy * CPDManager::getProxy(std::string target) {
@@ -134,50 +177,61 @@ GDBusProxy * CPDManager::getProxy(std::string target) {
void CPDManager::addBackend(std::pair<std::string, GDBusProxy *> pair) {
this -> m_pBackends.insert(pair);
- g_message("Add new backend");
}
-void CPDManager::addDestination(std::pair<OUString, CPDPrinter * > pair) {
- // initialize printer with possible configuration from psprint.conf
- OUString aPrinterName = pair.first;
- CPDPrinter *pDest = pair.second;
- std::unordered_map<OUString, CPDPrinter *, OUStringHash>::iterator it = m_aCPDDestMap.find( aPrinterName );
+void CPDManager::addTempBackend(std::pair<std::string, gchar*> pair) {
+ this -> m_tBackends.push_back(pair);
+}
+
+std::vector<std::pair<std::string, gchar*>> CPDManager::getTempBackends() {
+ return this -> m_tBackends;
+}
+
+void CPDManager::addNewPrinter(const OUString& aPrinterName, const OUString& aUniqueName, CPDPrinter *pDest) {
+ std::pair<OUString, CPDPrinter *> newPrinter (aUniqueName, pDest);
+ std::unordered_map<OUString, CPDPrinter *, OUStringHash>::iterator it = m_aCPDDestMap.find( aUniqueName );
if (it == m_aCPDDestMap.end()) {
- m_aCPDDestMap.insert(pair);
+ m_aCPDDestMap.insert(newPrinter);
} else {
m_aCPDDestMap.erase(it);
- m_aCPDDestMap.insert(pair);
+ m_aCPDDestMap.insert(newPrinter);
}
- bool bSetToGlobalDefaults = m_aPrinters.find( aPrinterName ) == m_aPrinters.end();
- Printer aPrinter = m_aPrinters[ aPrinterName ];
+ bool bSetToGlobalDefaults = m_aPrinters.find( aUniqueName ) == m_aPrinters.end();
+ Printer aPrinter = m_aPrinters[ aUniqueName ];
if( bSetToGlobalDefaults )
aPrinter.m_aInfo = m_aGlobalDefaults;
aPrinter.m_aInfo.m_aPrinterName = aPrinterName;
+
+ // TODO: I don't know how this should work when we have multiple
+ // sources with multiple possible defaults for each
// if( pDest->is_default )
// m_aDefaultPrinter = aPrinterName;
rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
- const char *pInfo = (pDest -> info).c_str();
- aPrinter.m_aInfo.m_aComment = OStringToOUString(pInfo, aEncoding);
- const char *pLocation = (pDest -> location).c_str();
- aPrinter.m_aInfo.m_aLocation = OStringToOUString(pLocation, aEncoding);
+ aPrinter.m_aInfo.m_aComment = OStringToOUString(pDest -> info, aEncoding);
+ aPrinter.m_aInfo.m_aLocation = OStringToOUString(pDest -> location, aEncoding);
OUStringBuffer aBuf( 256 );
aBuf.append( "CPD:" );
- aBuf.append( aPrinterName );
+ aBuf.append( aUniqueName );
// note: the parser that goes with the PrinterInfo
// is created implicitly by the JobData::operator=()
// when it detects the NULL ptr m_pParser.
// if we wanted to fill in the parser here this
- // would mean we'd have to download PPDs for each and
+ // would mean we'd have to send a dbus message for each and
// every printer - which would be really bad runtime
// behaviour
aPrinter.m_aInfo.m_pParser = nullptr;
aPrinter.m_aInfo.m_aContext.setParser( nullptr );
+ std::unordered_map< OUString, PPDContext, OUStringHash >::const_iterator c_it = m_aDefaultContexts.find( aUniqueName );
+ if( c_it != m_aDefaultContexts.end() )
+ {
+ aPrinter.m_aInfo.m_pParser = c_it->second.getParser();
+ aPrinter.m_aInfo.m_aContext = c_it->second;
+ }
aPrinter.m_aInfo.setDefaultBackend(true);
aPrinter.m_aInfo.m_aDriverName = aBuf.makeStringAndClear();
aPrinter.m_bModified = false;
- m_aPrinters[ aPrinter.m_aInfo.m_aPrinterName ] = aPrinter;
- g_message("Add new Printer");
+ m_aPrinters[ aUniqueName ] = aPrinter;
}
/*
@@ -190,9 +244,26 @@ CPDManager* CPDManager::tryLoadCPD()
#if ENABLE_DBUS && ENABLE_GIO
static const char* pEnv = getenv("SAL_DISABLE_CPD");
- if (!pEnv || !*pEnv)
- pManager = new CPDManager();
- g_message("Loaded CPD\n");
+ if (!pEnv || !*pEnv) {
+ GDir *dir;
+ GError *error = nullptr;
+ const gchar *filename;
+ dir = g_dir_open(BACKEND_DIR, 0, &error);
+ if (dir != nullptr) {
+ while ((filename = g_dir_read_name(dir))) {
+ if (pManager == nullptr) {
+ pManager = new CPDManager();
+ }
+ gchar* contents;
+ std::stringstream filepath;
+ filepath << BACKEND_DIR << '/' << filename;
+ g_file_get_contents(filepath.str().c_str(), &contents, nullptr, nullptr);
+ std::pair<std::string, gchar*> new_tbackend (filename, contents);
+ pManager -> addTempBackend(new_tbackend);
+ }
+ g_dir_close(dir);
+ }
+ }
#endif
return pManager;
}
@@ -202,7 +273,6 @@ CPDManager::CPDManager() :
{
// Get Destinations number and pointers
GError *error = nullptr;
- g_message("Created CPDManager\n");
m_pConnection = g_bus_get_sync (G_BUS_TYPE_SESSION, nullptr, &error);
g_assert_no_error (error);
}
@@ -216,51 +286,245 @@ CPDManager::~CPDManager()
"StopListing",
nullptr,
nullptr);
- g_message("Sent StopListing\n");
g_dbus_connection_flush_sync (m_pConnection,
nullptr,
nullptr);
g_dbus_connection_close_sync (m_pConnection,
nullptr,
nullptr);
- // Free pointers to destinations in cpd
- fprintf( stderr, "Destroyed CPDManager\n");
+ std::unordered_map<std::string, GDBusProxy *>::iterator it = this -> m_pBackends.begin();
+ for(; it != m_pBackends.end(); ++it)
+ {
+ g_object_unref(it->second);
+ }
+ std::unordered_map<OUString, CPDPrinter *, OUStringHash>::iterator dest_it =
+ m_aCPDDestMap.begin();
+ for(; dest_it != m_aCPDDestMap.end(); ++dest_it)
+ {
+ free(dest_it->second);
+ }
}
+const PPDParser* CPDManager::createCPDParser( const OUString& rPrinter )
+{
+ const PPDParser* pNewParser = nullptr;
+ OUString aPrinter;
+
+ if( rPrinter.startsWith("CPD:") )
+ aPrinter = rPrinter.copy( 4 );
+ else
+ aPrinter = rPrinter;
+
+ std::unordered_map< OUString, CPDPrinter *, OUStringHash >::iterator dest_it =
+ m_aCPDDestMap.find( aPrinter );
+
+ if( dest_it != m_aCPDDestMap.end() )
+ {
+
+ CPDPrinter* pDest = dest_it->second;
+ GVariant* ret = nullptr;
+ GError* error = nullptr;
+ ret = g_dbus_proxy_call_sync (pDest -> backend, "GetAllOptions",
+ g_variant_new("(s)", (pDest -> id)),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, nullptr, &error);
+ if (ret != nullptr && error == nullptr)
+ {
+ // TODO: These keys need to be redefined to preserve usage across libreoffice
+ // InputSlot - media-col.media-source?
+ // Font - not needed now as it is required only for ps and we are using pdf
+ // Dial? - for FAX (need to look up PWG spec)
+
+ int num_attribute;
+ GVariantIter *iter_attr, *iter_supported_values;
+ g_variant_get (ret, "(ia(ssia(s)))", &num_attribute, &iter_attr);
+ rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
+ PPDKey *pKey = nullptr;
+ OUString aValueName;
+ PPDValue* pValue;
+ std::vector<PPDKey*> keys;
+ std::vector<OUString> default_values;
+ for (int i = 0; i < num_attribute; i++) {
+ char *name, *default_value;
+ int num_supported_values;
+ g_variant_iter_loop(iter_attr, "(ssia(s))",
+ &name, &default_value,
+ &num_supported_values, &iter_supported_values);
+ OUString aOptionName = OStringToOUString( name, aEncoding );
+ OUString aDefaultValue = OStringToOUString( default_value, aEncoding );
+ if (aOptionName == "sides") {
+ // Duplex key is used throughout for checking Duplex Support
+ aOptionName = OUString("Duplex");
+ } else if (aOptionName == "printer-resolution") {
+ // Resolution key is used in places
+ aOptionName = OUString("Resolution");
+ } else if (aOptionName == "media") {
+ // PageSize key is used in many places
+ aOptionName = OUString("PageSize");
+ }
+ default_values.push_back(aDefaultValue);
+ pKey = new PPDKey( aOptionName );
+
+ // If number of values are 0, this is not settable via UI
+ if (num_supported_values > 0 && aDefaultValue != "NA")
+ pKey->m_bUIOption = true;
+
+ bool bDefaultFound = false;
+
+ for (int j = 0; j < num_supported_values; j++) {
+ char* value;
+ g_variant_iter_loop(iter_supported_values, "(s)", &value);
+ aValueName = OStringToOUString( value, aEncoding );
+ if (aOptionName == "Duplex") {
+ // Duplex key matches against very specific Values
+ if (aValueName == "one-sided") {
+ aValueName = OUString("None");
+ } else if (aValueName == "two-sided-long-edge") {
+ aValueName = OUString("DuplexNoTumble");
+ } else if (aValueName == "two-sided-short-edge") {
+ aValueName = OUString("DuplexTumble");
+ }
+ }
+
+ pValue = pKey->insertValue( aValueName, eQuoted );
+ if( ! pValue )
+ continue;
+ pValue->m_aValue = aValueName;
+
+ if (aValueName.equals(aDefaultValue)) {
+ pKey -> m_pDefaultValue = pValue;
+ bDefaultFound = true;
+ }
+
+ }
+ // This could be done to ensure default values also appear as options:
+ if (!bDefaultFound && pKey->m_bUIOption) {
+ // pValue = pKey->insertValue( aDefaultValue, eQuoted );
+ // if( pValue )
+ // pValue->m_aValue = aDefaultValue;
+ }
+ keys.push_back(pKey);
+ }
+
+ pKey = new PPDKey("ModelName");
+ aValueName = OStringToOUString( "", aEncoding );
+ pValue = pKey->insertValue( aValueName, eQuoted );
+ if( pValue )
+ pValue->m_aValue = aValueName;
+ pKey -> m_pDefaultValue = pValue;
+
+ pKey = new PPDKey("NickName");
+ aValueName = OStringToOUString( pDest -> name, aEncoding );
+ pValue = pKey->insertValue( aValueName, eQuoted );
+ if( pValue )
+ pValue->m_aValue = aValueName;
+ pKey -> m_pDefaultValue = pValue;
+
+ pNewParser = new PPDParser(aPrinter, keys);
+ PrinterInfo& rInfo = m_aPrinters[ aPrinter ].m_aInfo;
+ PPDContext& rContext = m_aDefaultContexts[ aPrinter ];
+ rContext.setParser( pNewParser );
+ setDefaultPaper( rContext );
+ std::vector<PPDKey*>::iterator keyit;
+ std::vector<OUString>::iterator defit;
+ for (keyit = keys.begin(), defit = default_values.begin(); keyit != keys.end(); keyit++, defit++ ) {
+ pKey = *keyit;
+ const PPDValue* p1Value = pKey->getValue( *defit );
+ if( p1Value )
+ {
+ if( p1Value != pKey->getDefaultValue() )
+ {
+ rContext.setValue( pKey, p1Value, true );
+ SAL_INFO("vcl.unx.print", "key " << pKey -> getKey() << " is set to " << *defit);
+ }
+ else
+ SAL_INFO("vcl.unx.print", "key " << pKey -> getKey() << " is defaulted to " << *defit);
+ }
+ }
+
+ rInfo.m_pParser = pNewParser;
+ rInfo.m_aContext = rContext;
+ g_variant_unref(ret);
+ }
+ else
+ SAL_INFO("vcl.unx.print", "CPD GetAllOptions failed, falling back to generic driver");
+ }
+ else
+ SAL_INFO("vcl.unx.print", "no dest found for printer " << aPrinter);
+
+ if( ! pNewParser )
+ {
+ // get the default PPD
+ pNewParser = PPDParser::getParser( "SGENPRT" );
+ SAL_WARN("vcl.unx.print", "Parsing default SGENPRT PPD" );
+ PrinterInfo& rInfo = m_aPrinters[ aPrinter ].m_aInfo;
+
+ rInfo.m_pParser = pNewParser;
+ rInfo.m_aContext.setParser( pNewParser );
+ }
+
+ return pNewParser;
+}
void CPDManager::initialize()
{
// get normal printers, clear printer list
PrinterInfoManager::initialize();
- g_message("Initialised CPDManager\n");
g_bus_own_name_on_connection (m_pConnection,
"org.libreoffice.print-dialog",
G_BUS_NAME_OWNER_FLAGS_NONE,
- on_name_acquired,
- on_name_lost,
- NULL,
- NULL);
+ onNameAcquired,
+ onNameLost,
+ this,
+ nullptr);
g_dbus_connection_signal_subscribe (m_pConnection, // DBus Connection
- NULL, // Sender Name
+ nullptr, // Sender Name
+ "org.openprinting.PrintBackend", // Sender Interface
+ "PrinterAdded", // Signal Name
+ nullptr, // Object Path
+ nullptr, // arg0 behaviour
+ G_DBUS_SIGNAL_FLAGS_NONE, // Signal Flags
+ printerAdded, // Callback Function
+ this,
+ nullptr);
+ g_dbus_connection_signal_subscribe (m_pConnection, // DBus Connection
+ nullptr, // Sender Name
"org.openprinting.PrintBackend", // Sender Interface
- NULL, // Signal Name
- NULL, // Object Path
- NULL, // arg0 behaviour
+ "PrinterRemoved", // Signal Name
+ nullptr, // Object Path
+ nullptr, // arg0 behaviour
G_DBUS_SIGNAL_FLAGS_NONE, // Signal Flags
- got_signal, // Callback Function
+ printerRemoved, // Callback Function
this,
- NULL);
- // If password CB is needed
- //cpdSetPasswordCB( setPasswordCallback );
+ nullptr);
+
+ // remove everything that is not a CUPS printer and not
+ // a special purpose printer (PDF, Fax)
+ std::list< OUString > aRemovePrinters;
+ for( std::unordered_map< OUString, Printer, OUStringHash >::iterator it = m_aPrinters.begin();
+ it != m_aPrinters.end(); ++it )
+ {
+ if( m_aCPDDestMap.find( it->first ) != m_aCPDDestMap.end() )
+ continue;
+
+ if( !it->second.m_aInfo.m_aFeatures.isEmpty() )
+ continue;
+ aRemovePrinters.push_back( it->first );
+ }
+ while( aRemovePrinters.begin() != aRemovePrinters.end() )
+ {
+ m_aPrinters.erase( aRemovePrinters.front() );
+ aRemovePrinters.pop_front();
+ }
}
void CPDManager::setupJobContextData( JobData& rData )
{
- std::unordered_map< OUString, CPDPrinter *, OUStringHash >::iterator dest_it =
+ std::unordered_map<OUString, CPDPrinter *, OUStringHash>::iterator dest_it =
m_aCPDDestMap.find( rData.m_aPrinterName );
if( dest_it == m_aCPDDestMap.end() )
@@ -269,22 +533,41 @@ void CPDManager::setupJobContextData( JobData& rData )
std::unordered_map< OUString, Printer, OUStringHash >::iterator p_it =
m_aPrinters.find( rData.m_aPrinterName );
if( p_it == m_aPrinters.end() ) // huh ?
- {
- SAL_WARN("vcl.unx.print", "CPD printer list in disorder, "
- "no dest for printer " << rData.m_aPrinterName);
- return;
- }
- g_message("Setup JobContextData called");
+ {
+ SAL_WARN("vcl.unx.print", "CPD printer list in disorder, "
+ "no dest for printer " << rData.m_aPrinterName);
+ return;
+ }
+
+ if( p_it->second.m_aInfo.m_pParser == nullptr )
+ {
+ // in turn calls createCPDParser
+ // which updates the printer info
+ p_it->second.m_aInfo.m_pParser = PPDParser::getParser( p_it->second.m_aInfo.m_aDriverName );
+ }
+ if( p_it->second.m_aInfo.m_aContext.getParser() == nullptr )
+ {
+ OUString aPrinter;
+ if( p_it->second.m_aInfo.m_aDriverName.startsWith("CPD:") )
+ aPrinter = p_it->second.m_aInfo.m_aDriverName.copy( 4 );
+ else
+ aPrinter = p_it->second.m_aInfo.m_aDriverName;
+
+ p_it->second.m_aInfo.m_aContext = m_aDefaultContexts[ aPrinter ];
+ }
+
+ rData.m_pParser = p_it->second.m_aInfo.m_pParser;
+ rData.m_aContext = p_it->second.m_aInfo.m_aContext;
}
FILE* CPDManager::startSpool( const OUString& rPrintername, bool bQuickCommand )
{
SAL_INFO( "vcl.unx.print", "startSpool: " << rPrintername << " " << (bQuickCommand ? "true" : "false") );
if( m_aCPDDestMap.find( rPrintername ) == m_aCPDDestMap.end() )
- {
- SAL_INFO( "vcl.unx.print", "defer to PrinterInfoManager::startSpool" );
- return PrinterInfoManager::startSpool( rPrintername, bQuickCommand );
- }
+ {
+ SAL_INFO( "vcl.unx.print", "defer to PrinterInfoManager::startSpool" );
+ return PrinterInfoManager::startSpool( rPrintername, bQuickCommand );
+ }
OUString aTmpURL, aTmpFile;
osl_createTempFile( nullptr, nullptr, &aTmpURL.pData );
osl_getSystemPathFromFileURL( aTmpURL.pData, &aTmpFile.pData );
@@ -296,38 +579,126 @@ FILE* CPDManager::startSpool( const OUString& rPrintername, bool bQuickCommand )
return fp;
}
+void CPDManager::getOptionsFromDocumentSetup( const JobData& rJob, bool bBanner, const OString& rJobName, int& rNumOptions, GVariant **arr )
+{
+ GVariantBuilder *builder;
+ builder = g_variant_builder_new(G_VARIANT_TYPE("a(ss)"));
+ g_variant_builder_add(builder, "(ss)", "job-name", rJobName.getStr());
+ if( rJob.m_pParser == rJob.m_aContext.getParser() && rJob.m_pParser ) {
+ int i;
+ int nKeys = rJob.m_aContext.countValuesModified();
+ ::std::vector< const PPDKey* > aKeys( nKeys );
+ for( i = 0; i < nKeys; i++ )
+ aKeys[i] = rJob.m_aContext.getModifiedKey( i );
+ for( i = 0; i < nKeys; i++ ) {
+ const PPDKey* pKey = aKeys[i];
+ const PPDValue* pValue = rJob.m_aContext.getValue( pKey );
+ OUString sPayLoad;
+ if (pValue) {
+ sPayLoad = pValue->m_bCustomOption ? pValue->m_aCustomOption : pValue->m_aOption;
+ }
+ if (!sPayLoad.isEmpty()) {
+ OString aKey = OUStringToOString( pKey->getKey(), RTL_TEXTENCODING_ASCII_US );
+ OString aValue = OUStringToOString( sPayLoad, RTL_TEXTENCODING_ASCII_US );
+ if (aKey.equals(OString("Duplex"))) {
+ aKey = OString("sides");
+ } else if (aKey.equals(OString("Resolution"))) {
+ aKey = OString("printer-resolution");
+ } else if (aKey.equals(OString("PageSize"))) {
+ aKey = OString("media");
+ }
+ if (aKey.equals(OString("sides"))) {
+ if (aValue.equals(OString("None"))) {
+ aValue = OString("one-sided");
+ } else if (aValue.equals(OString("DuplexNoTumble"))) {
+ aValue = OString("two-sided-long-edge");
+ } else if (aValue.equals(OString("DuplexTumble"))) {
+ aValue = OString("two-sided-short-edge");
+ }
+ }
+ g_variant_builder_add(builder, "(ss)", aKey.getStr(), aValue.getStr());
+ }
+ }
+ }
+ if( rJob.m_nPDFDevice > 0 && rJob.m_nCopies > 1 )
+ {
+ OString aVal( OString::number( rJob.m_nCopies ) );
+ g_variant_builder_add(builder, "(ss)", "copies", aVal.getStr());
+ rNumOptions++;
+ // TODO: something for collate
+ // Maybe this is the equivalent ipp attribute:
+ if (rJob.m_bCollate) {
+ g_variant_builder_add(builder, "(ss)", "multiple-document-handling", "separate-documents-collated-copies");
+ } else {
+ g_variant_builder_add(builder, "(ss)", "multiple-document-handling", "separate-documents-uncollated-copies");
+ }
+ rNumOptions++;
+ }
+ if( ! bBanner )
+ {
+ g_variant_builder_add(builder, "(ss)", "job-sheets", "none");
+ rNumOptions++;
+ }
+ if (rJob.m_eOrientation == orientation::Portrait) {
+ g_variant_builder_add(builder, "(ss)", "orientation-requested", "portrait");
+ rNumOptions++;
+ } else if (rJob.m_eOrientation == orientation::Landscape) {
+ g_variant_builder_add(builder, "(ss)", "orientation-requested", "landscape");
+ rNumOptions++;
+ }
+ (*arr) = g_variant_new("a(ss)", builder);
+ g_variant_builder_unref(builder);
+}
+
bool CPDManager::endSpool( const OUString& rPrintername, const OUString& rJobTitle, FILE* pFile, const JobData& rDocumentJobData, bool bBanner, const OUString& rFaxNumber )
{
+ bool success = false;
SAL_INFO( "vcl.unx.print", "endSpool: " << rPrintername << "," << rJobTitle << " copy count = " << rDocumentJobData.m_nCopies );
std::unordered_map< OUString, CPDPrinter *, OUStringHash >::iterator dest_it =
m_aCPDDestMap.find( rPrintername );
if( dest_it == m_aCPDDestMap.end() )
- {
- SAL_INFO( "vcl.unx.print", "defer to PrinterInfoManager::endSpool" );
- return PrinterInfoManager::endSpool( rPrintername, rJobTitle, pFile, rDocumentJobData, bBanner, rFaxNumber );
- }
+ {
+ SAL_INFO( "vcl.unx.print", "defer to PrinterInfoManager::endSpool" );
+ return PrinterInfoManager::endSpool( rPrintername, rJobTitle, pFile, rDocumentJobData, bBanner, rFaxNumber );
+ }
std::unordered_map< FILE*, OString, FPtrHash >::const_iterator it = m_aSpoolFiles.find( pFile );
if( it != m_aSpoolFiles.end() )
+ {
+ fclose( pFile );
+ rtl_TextEncoding aEnc = osl_getThreadTextEncoding();
+ OString sJobName(OUStringToOString(rJobTitle, aEnc));
+ if (!rFaxNumber.isEmpty())
{
- fclose( pFile );
- rtl_TextEncoding aEnc = osl_getThreadTextEncoding();
- OString sJobName(OUStringToOString(rJobTitle, aEnc));
- if (!rFaxNumber.isEmpty())
- {
- sJobName = OUStringToOString(rFaxNumber, aEnc);
- }
- CPDPrinter* pDest = dest_it->second;
- g_message("Printing");
- // g_dbus_proxy_call(pDest -> backend, "printJob",
- // g_variant_new("(s)", "yo"),
- // G_DBUS_CALL_FLAGS_NONE,
- // -1, nullptr, nullptr, nullptr);
- unlink( it->second.getStr() );
- m_aSpoolFiles.erase( pFile );
+ sJobName = OUStringToOString(rFaxNumber, aEnc);
+ }
+ OString aSysFile = it->second;
+ CPDPrinter* pDest = dest_it->second;
+ GVariant* ret;
+ gint job_id;
+ int nNumOptions = 0;
+ GVariant *pArr = nullptr;
+ getOptionsFromDocumentSetup( rDocumentJobData, bBanner, sJobName, nNumOptions, &pArr );
+ ret = g_dbus_proxy_call_sync (pDest -> backend, "printFile",
+ g_variant_new(
+ "(ssi@a(ss))",
+ (pDest -> id),
+ aSysFile.getStr(),
+ nNumOptions,
+ pArr
+ ),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, nullptr, nullptr);
+ g_variant_get (ret, "(i)", &job_id);
+ if (job_id != -1) {
+ success = true;
}
+ g_variant_unref(ret);
+ unlink( it->second.getStr() );
+ m_aSpoolFiles.erase( pFile );
+ }
- return true;
+ return success;
}
bool CPDManager::checkPrintersChanged( bool )
@@ -368,20 +739,15 @@ bool CPDManager::setDefaultPrinter( const OUString& rName )
std::unordered_map< OUString, CPDPrinter *, OUStringHash >::iterator nit =
m_aCPDDestMap.find( rName );
if( nit != m_aCPDDestMap.end())
- {
- m_aDefaultPrinter = rName;
- bSuccess = true;
- }
+ {
+ m_aDefaultPrinter = rName;
+ bSuccess = true;
+ }
else
bSuccess = PrinterInfoManager::setDefaultPrinter( rName );
return bSuccess;
}
-bool CPDManager::writePrinterConfig()
-{
- return PrinterInfoManager::writePrinterConfig();
-}
-
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/generic/printer/ppdparser.cxx b/vcl/unx/generic/printer/ppdparser.cxx
index 927e6a284d4a..97551db1983b 100644
--- a/vcl/unx/generic/printer/ppdparser.cxx
+++ b/vcl/unx/generic/printer/ppdparser.cxx
@@ -27,6 +27,7 @@
#include <unx/helper.hxx>
#include "unx/cupsmgr.hxx"
+#include "unx/cpdmgr.hxx"
#include "tools/urlobj.hxx"
#include "tools/stream.hxx"
@@ -45,6 +46,10 @@
#include <unordered_map>
+#ifdef ENABLE_CUPS
+#include <cups/cups.h>
+#endif
+
namespace psp
{
class PPDTranslator
@@ -539,7 +544,7 @@ const PPDParser* PPDParser::getParser( const OUString& rFile )
::osl::Guard< ::osl::Mutex > aGuard( aMutex );
OUString aFile = rFile;
- if( !rFile.startsWith( "CUPS:" ) )
+ if( !rFile.startsWith( "CUPS:" ) && !rFile.startsWith( "CPD:" ) )
aFile = getPPDFile( rFile );
if( aFile.isEmpty() )
{
@@ -558,7 +563,7 @@ const PPDParser* PPDParser::getParser( const OUString& rFile )
return *it;
PPDParser* pNewParser = nullptr;
- if( !aFile.startsWith( "CUPS:" ) )
+ if( !aFile.startsWith( "CUPS:" ) && !aFile.startsWith( "CPD:" ) )
pNewParser = new PPDParser( aFile );
else
{
@@ -568,6 +573,9 @@ const PPDParser* PPDParser::getParser( const OUString& rFile )
#ifdef ENABLE_CUPS
pNewParser = const_cast<PPDParser*>(static_cast<CUPSManager&>(rMgr).createCUPSParser( aFile ));
#endif
+ } else if ( rMgr.getType() == PrinterInfoManager::Type::CPD )
+ {
+ pNewParser = const_cast<PPDParser*>(static_cast<CPDManager&>(rMgr).createCPDParser( aFile ));
}
}
if( pNewParser )
@@ -581,6 +589,118 @@ const PPDParser* PPDParser::getParser( const OUString& rFile )
return pNewParser;
}
+PPDParser::PPDParser( const OUString& rFile, std::vector<PPDKey*> keys) :
+ m_aFile( rFile ),
+ m_bColorDevice( false ),
+ m_bType42Capable( false ),
+ m_nLanguageLevel( 0 ),
+ m_aFileEncoding( RTL_TEXTENCODING_MS_1252 ),
+ m_pDefaultImageableArea( nullptr ),
+ m_pImageableAreas( nullptr ),
+ m_pDefaultPaperDimension( nullptr ),
+ m_pPaperDimensions( nullptr ),
+ m_pDefaultInputSlot( nullptr ),
+ m_pInputSlots( nullptr ),
+ m_pDefaultResolution( nullptr ),
+ m_pResolutions( nullptr ),
+ m_pFontList( nullptr ),
+ m_pTranslator( new PPDTranslator() )
+{
+ for (PPDKey* key: keys)
+ {
+ insertKey( key -> getKey(), key );
+ }
+
+ // fill in shortcuts
+ const PPDKey* pKey;
+
+ pKey = getKey( OUString( "PageSize" ) );
+
+ if ( pKey ) {
+ PPDKey* pImageableAreas = new PPDKey("ImageableArea");
+ PPDKey* pPaperDimensions = new PPDKey("PaperDimension");
+#if (CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR >= 7) || CUPS_VERSION_MAJOR > 1
+ for (int i = 0; i < pKey->countValues(); i++) {
+ const PPDValue* pValue = pKey -> getValue(i);
+ OUString aValueName = pValue -> m_aOption;
+ PPDValue* pImageableAreaValue = pImageableAreas -> insertValue( aValueName, eQuoted );
+ PPDValue* pPaperDimensionValue = pPaperDimensions -> insertValue( aValueName, eQuoted );
+ rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
+ OString o = OUStringToOString( aValueName, aEncoding );
+ pwg_media_t *pPWGMedia = pwgMediaForPWG(o.pData->buffer);
+ if (pPWGMedia != nullptr) {
+ OUStringBuffer aBuf( 256 );
+ aBuf.append( "0 0 " );
+ aBuf.append( PWG_TO_POINTS(pPWGMedia -> width) );
+ aBuf.append( " " );
+ aBuf.append( PWG_TO_POINTS(pPWGMedia -> length) );
+ if ( pImageableAreaValue )
+ pImageableAreaValue->m_aValue = aBuf.makeStringAndClear();
+ aBuf.append( PWG_TO_POINTS(pPWGMedia -> width) );
+ aBuf.append( " " );
+ aBuf.append( PWG_TO_POINTS(pPWGMedia -> length) );
+ if ( pPaperDimensionValue )
+ pPaperDimensionValue->m_aValue = aBuf.makeStringAndClear();
+ if ((aValueName).equals(pKey -> getDefaultValue() -> m_aOption)) {
+ pImageableAreas -> m_pDefaultValue = pImageableAreaValue;
+ pPaperDimensions -> m_pDefaultValue = pPaperDimensionValue;
+ }
+ }
+ }
+#endif // HAVE_CUPS_API_1_7
+ insertKey("ImageableArea", pImageableAreas);
+ insertKey("PaperDimension", pPaperDimensions);
+ }
+
+ m_pImageableAreas = getKey( OUString( "ImageableArea" ) );
+ if( m_pImageableAreas )
+ m_pDefaultImageableArea = m_pImageableAreas->getDefaultValue();
+ if (m_pImageableAreas == nullptr) {
+ SAL_WARN( "vcl.unx.print", "no ImageableArea in " << m_aFile);
+ }
+ if (m_pDefaultImageableArea == nullptr) {
+ SAL_WARN( "vcl.unx.print", "no DefaultImageableArea in " << m_aFile);
+ }
+
+ m_pPaperDimensions = getKey( OUString( "PaperDimension" ) );
+ if( m_pPaperDimensions )
+ m_pDefaultPaperDimension = m_pPaperDimensions->getDefaultValue();
+ if (m_pPaperDimensions == nullptr) {
+ SAL_WARN( "vcl.unx.print", "no PaperDimensions in " << m_aFile);
+ }
+ if (m_pDefaultPaperDimension == nullptr) {
+ SAL_WARN( "vcl.unx.print", "no DefaultPaperDimensions in " << m_aFile);
+ }
+
+ m_pResolutions = getKey( OUString( "Resolution" ) );
+ if( m_pResolutions )
+ m_pDefaultResolution = m_pResolutions->getDefaultValue();
+ if (m_pResolutions == nullptr) {
+ SAL_WARN( "vcl.unx.print", "no Resolution in " << m_aFile);
+ }
+ SAL_INFO_IF(!m_pDefaultResolution, "vcl.unx.print", "no DefaultResolution in " + m_aFile);
+
+ m_pInputSlots = getKey( OUString( "InputSlot" ) );
+ if( m_pInputSlots )
+ m_pDefaultInputSlot = m_pInputSlots->getDefaultValue();
+ SAL_INFO_IF(!m_pInputSlots, "vcl.unx.print", "no InputSlot in " << m_aFile);
+ SAL_INFO_IF(!m_pDefaultInputSlot, "vcl.unx.print", "no DefaultInputSlot in " << m_aFile);
+
+ m_pFontList = getKey( OUString( "Font" ) );
+ if (m_pFontList == nullptr) {
+ SAL_WARN( "vcl.unx.print", "no Font in " << m_aFile);
+ }
+
+ // fill in direct values
+ if( (pKey = getKey( OUString( "ModelName" ) )) )
+ m_aPrinterName = pKey->getValue( 0 )->m_aValue;
+ if( (pKey = getKey( OUString( "NickName" ) )) )
+ m_aNickName = pKey->getValue( 0 )->m_aValue;
+ if( (pKey = getKey( OUString( "print-color-mode" ) )) )
+ m_bColorDevice = pKey->countValues() > 1;
+
+}
+
PPDParser::PPDParser( const OUString& rFile ) :
m_aFile( rFile ),
m_bColorDevice( false ),