[Libreoffice-commits] core.git: include/vcl vcl/inc vcl/unx

Yash Srivastav yash111998 at gmail.com
Tue Sep 12 08:55:16 UTC 2017


 include/vcl/ppdparser.hxx             |    3 
 vcl/inc/unx/cpdmgr.hxx                |   78 +++-
 vcl/unx/generic/printer/cpdmgr.cxx    |  654 ++++++++++++++++++++++++++--------
 vcl/unx/generic/printer/ppdparser.cxx |  124 ++++++
 4 files changed, 698 insertions(+), 161 deletions(-)

New commits:
commit 7fbf98d99737ac916cc2dc374f3139e2ea81e47b
Author: Yash Srivastav <yash111998 at gmail.com>
Date:   Thu Jul 27 08:11:34 2017 +0530

    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 at 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 at libreoffice.org>
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>

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 at 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 ),


More information about the Libreoffice-commits mailing list