diff --git a/print-manager-kded/Debug.cpp b/print-manager-kded/Debug.cpp index 3429bac..35e6c52 100644 --- a/print-manager-kded/Debug.cpp +++ b/print-manager-kded/Debug.cpp @@ -1,23 +1,23 @@ /* Copyright 2014 Jan Grulich This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "Debug.h" -Q_LOGGING_CATEGORY(PM_KDED, "pm.kded") +Q_LOGGING_CATEGORY(PM_KDED, "print-manager.kded") diff --git a/print-manager-kded/NewPrinterNotification.cpp b/print-manager-kded/NewPrinterNotification.cpp index 7921f3e..8e4d83e 100644 --- a/print-manager-kded/NewPrinterNotification.cpp +++ b/print-manager-kded/NewPrinterNotification.cpp @@ -1,290 +1,286 @@ /*************************************************************************** * Copyright (C) 2010-2018 by Daniel Nicoletti * * dantti12@gmail.com * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; see the file COPYING. If not, write to * * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "NewPrinterNotification.h" #include "newprinternotificationadaptor.h" #include "Debug.h" #include #include #include #include #include -#include #include #include #include #include +#include +#include #define STATUS_SUCCESS 0 #define STATUS_MODEL_MISMATCH 1 #define STATUS_GENERIC_DRIVER 2 #define STATUS_NO_DRIVER 3 #define PRINTER_NAME "PrinterName" -#define DEVICE_ID "DeviceId" -NewPrinterNotification::NewPrinterNotification() +NewPrinterNotification::NewPrinterNotification(QObject *parent) : QObject(parent) { - // Make sure the password dialog is created in the main thread - KCupsConnection::global(); - - // Make all our init code run on the thread since - // the DBus calls were made blocking - QTimer::singleShot(0, this, &NewPrinterNotification::init); + // Creates our new adaptor + (void) new NewPrinterNotificationAdaptor(this); - m_thread = new QThread(this); - moveToThread(m_thread); - m_thread->start(); + // Register the com.redhat.NewPrinterNotification interface + if (!registerService()) { + // in case registration fails due to another user or application running + // keep an eye on it so we can register when available + auto watcher = new QDBusServiceWatcher(QLatin1String("com.redhat.NewPrinterNotification"), + QDBusConnection::systemBus(), + QDBusServiceWatcher::WatchForUnregistration, + this); + connect(watcher, &QDBusServiceWatcher::serviceUnregistered, this, &NewPrinterNotification::registerService); + } } NewPrinterNotification::~NewPrinterNotification() { } void NewPrinterNotification::GetReady() { - qCDebug(PM_KDED); + qCDebug(PM_KDED) << "GetReady"; // This method is all about telling the user a new printer was detected auto notify = new KNotification(QLatin1String("GetReady")); notify->setComponentName(QLatin1String("printmanager")); notify->setIconName(QLatin1String("printer")); notify->setTitle(i18n("A New Printer was detected")); notify->setText(i18n("Configuring new printer...")); notify->sendEvent(); } //status: 0 //name: PSC_1400_series //mfg: HP //mdl: PSC 1400 series //des: //cmd: LDL,MLC,PML,DYN void NewPrinterNotification::NewPrinter(int status, const QString &name, const QString &make, const QString &model, const QString &description, const QString &cmd) { qCDebug(PM_KDED) << status << name << make << model << description << cmd; + // 1 // "usb://Samsung/SCX-3400%20Series?serial=Z6Y1BQAC500079K&interface=1" // mfg "Samsung" // mdl "SCX-3400 Series" "" "SPL,FWV,PIC,BDN,EXT" // This method is all about telling the user a new printer was detected auto notify = new KNotification(QLatin1String("NewPrinterNotification")); notify->setComponentName(QLatin1String("printmanager")); notify->setIconName(QLatin1String("printer")); notify->setFlags(KNotification::Persistent); - QString title; - QString text; - QString devid; - QStringList actions; - devid = QString::fromLatin1("MFG:%1;MDL:%2;DES:%3;CMD:%4;").arg(make, model, description, cmd); - if (name.contains(QLatin1Char('/'))) { - // name is a URI, no queue was generated, because no suitable - // driver was found - title = i18n("Missing printer driver"); - if (!make.isEmpty() && !model.isEmpty()) { - text = i18n("No printer driver for %1 %2.", make, model); - } else if (!description.isEmpty()) { - text = i18n("No printer driver for %1.", description); - } else { - text = i18n("No driver for this printer."); - } - - actions << i18n("Search"); - connect(notify, &KNotification::action1Activated, this, &NewPrinterNotification::setupPrinter); + const QString devid = QString::fromLatin1("MFG:%1;MDL:%2;DES:%3;CMD:%4;") + .arg(make, model, description, cmd); + setupPrinterNotification(notify, make, model, description, + name + QLatin1Char('/') + devid); } else { + notify->setProperty(PRINTER_NAME, name); // name is the name of the queue which hal_lpadmin has set up // automatically. if (status < STATUS_GENERIC_DRIVER) { - title = i18n("The New Printer was Added"); + notify->setTitle(i18n("The New Printer was Added")); } else { - title = i18n("The New Printer is Missing Drivers"); + notify->setTitle(i18n("The New Printer is Missing Drivers")); } - // Get the new printer attributes - QPointer request = new KCupsRequest; - request->getPrinterAttributes(name, false, { KCUPS_PRINTER_MAKE_AND_MODEL }); - request->waitTillFinished(); - if (!request) { - return; - } - - QString driver; - // Get the new printer driver - if (!request->printers().isEmpty()){ - KCupsPrinter printer = request->printers().first(); - driver = printer.makeAndModel(); - } - request->deleteLater(); - - QString ppdFileName; - request = new KCupsRequest; - request->getPrinterPPD(name); - request->waitTillFinished(); - if (!request) { - return; - } - ppdFileName = request->printerPPD(); - request->deleteLater(); - - // Get a list of missing executables - QStringList missingExecutables = getMissingExecutables(ppdFileName); - - if (!missingExecutables.isEmpty()) { - // TODO check with PackageKit about missing drivers - qCWarning(PM_KDED) << "Missing executables:" << missingExecutables; - } else if (status == STATUS_SUCCESS) { - text = i18n("'%1' is ready for printing.", name); - actions << i18n("Print test page"); - connect(notify, &KNotification::action1Activated, this, &NewPrinterNotification::printTestPage); - actions << i18n("Configure"); - connect(notify, &KNotification::action2Activated, this, &NewPrinterNotification::configurePrinter); - } else { - // Model mismatch - - // The cups request might have failed - if (driver.isEmpty()) { - text = i18n("'%1' has been added, please check its driver.", name); - actions << i18n("Configure"); - connect(notify, &KNotification::action1Activated, this, &NewPrinterNotification::configurePrinter); - } else { - text = i18n("'%1' has been added, using the '%2' driver.", name, driver); - actions << i18n("Print test page"); - connect(notify, &KNotification::action1Activated, this, &NewPrinterNotification::printTestPage); - actions << i18n("Find driver"); - connect(notify, &KNotification::action2Activated, this, &NewPrinterNotification::findDriver); - } - } - } - notify->setTitle(title); - notify->setText(text); - notify->setProperty(PRINTER_NAME, name); - notify->setProperty(DEVICE_ID, devid); - notify->setActions(actions); - notify->sendEvent(); -} - -void NewPrinterNotification::init() -{ - // Creates our new adaptor - (void) new NewPrinterNotificationAdaptor(this); - - // Register the com.redhat.NewPrinterNotification interface - if (!registerService()) { - // in case registration fails due to another user or application running - // keep an eye on it so we can register when available - auto watcher = new QDBusServiceWatcher(QLatin1String("com.redhat.NewPrinterNotification"), - QDBusConnection::systemBus(), - QDBusServiceWatcher::WatchForUnregistration, - this); - connect(watcher, &QDBusServiceWatcher::serviceUnregistered, this, &NewPrinterNotification::registerService); + auto request = new KCupsRequest; + connect(request, &KCupsRequest::finished, this, [this, notify, status, name] (KCupsRequest *request) { + const QString ppdFileName = request->printerPPD(); + // Get a list of missing executables + getMissingExecutables(notify, status, name, ppdFileName); + request->deleteLater(); + }); + request->getPrinterPPD(name); } } bool NewPrinterNotification::registerService() { if (!QDBusConnection::systemBus().registerService(QLatin1String("com.redhat.NewPrinterNotification"))) { qCWarning(PM_KDED) << "unable to register service to dbus"; return false; } if (!QDBusConnection::systemBus().registerObject(QLatin1String("/com/redhat/NewPrinterNotification"), this)) { qCWarning(PM_KDED) << "unable to register object to dbus"; return false; } return true; } void NewPrinterNotification::configurePrinter() { QProcess::startDetached(QLatin1String("configure-printer"), { QLatin1String(PRINTER_NAME) }); } void NewPrinterNotification::searchDrivers() { } void NewPrinterNotification::printTestPage() { qCDebug(PM_KDED); QPointer request = new KCupsRequest; request->printTestPage(sender()->property(PRINTER_NAME).toString(), false); request->waitTillFinished(); if (request) { request->deleteLater(); } } void NewPrinterNotification::findDriver() { qCDebug(PM_KDED); // This function will show the PPD browser dialog // to choose a better PPD to the already added printer KToolInvocation::kdeinitExec(QLatin1String("kde-add-printer"), { QLatin1String("--change-ppd"), sender()->property(PRINTER_NAME).toString() }); } void NewPrinterNotification::installDriver() { qCDebug(PM_KDED); } -void NewPrinterNotification::setupPrinter() + +void NewPrinterNotification::setupPrinterNotification(KNotification *notify, const QString &make, const QString &model, const QString &description, const QString &arg) { - qCDebug(PM_KDED); - QObject *obj = sender(); - // This function will show the PPD browser dialog - // to choose a better PPD, queue name, location - // in this case the printer was not added - KToolInvocation::kdeinitExec(QLatin1String("kde-add-printer"), { - QLatin1String("--new-printer-from-device"), - obj->property(PRINTER_NAME).toString() + QLatin1Char('/') + obj->property(DEVICE_ID).toString() - }); + // name is a URI, no queue was generated, because no suitable + // driver was found + notify->setTitle(i18n("Missing printer driver")); + if (!make.isEmpty() && !model.isEmpty()) { + notify->setText(i18n("No printer driver for %1 %2.", make, model)); + } else if (!description.isEmpty()) { + notify->setText(i18n("No printer driver for %1.", description)); + } else { + notify->setText(i18n("No driver for this printer.")); + } + + notify->setActions({ i18n("Search") }); + connect(notify, &KNotification::action1Activated, this, [notify, arg] () { + qCDebug(PM_KDED); + // This function will show the PPD browser dialog + // to choose a better PPD, queue name, location + // in this case the printer was not added + KToolInvocation::kdeinitExec(QLatin1String("kde-add-printer"), { + QLatin1String("--new-printer-from-device"), + arg + }); + }); + + notify->sendEvent(); } -QStringList NewPrinterNotification::getMissingExecutables(const QString &ppdFileName) const +void NewPrinterNotification::getMissingExecutables(KNotification *notify, int status, const QString &name, const QString &ppdFileName) { - qCDebug(PM_KDED); - QDBusMessage message; - message = QDBusMessage::createMethodCall(QLatin1String("org.fedoraproject.Config.Printing"), - QLatin1String("/org/fedoraproject/Config/Printing"), - QLatin1String("org.fedoraproject.Config.Printing"), - QLatin1String("MissingExecutables")); + qCDebug(PM_KDED) << "get missing executables" << ppdFileName; + QDBusMessage message = QDBusMessage::createMethodCall( + QLatin1String("org.fedoraproject.Config.Printing"), + QLatin1String("/org/fedoraproject/Config/Printing"), + QLatin1String("org.fedoraproject.Config.Printing"), + QLatin1String("MissingExecutables")); message << ppdFileName; - QDBusReply reply = QDBusConnection::sessionBus().call(message); - if (!reply.isValid()) { - qCWarning(PM_KDED) << "Invalid reply" << reply.error(); - } - return reply; + + QDBusPendingReply reply = QDBusConnection::sessionBus().asyncCall(message); + auto watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, watcher, notify, status, name] () { + watcher->deleteLater(); + QDBusPendingReply reply = *watcher; + if (!reply.isValid()) { + qCWarning(PM_KDED) << "Invalid reply" << reply.error(); + notify->deleteLater(); + return; + } + + const QStringList missingExecutables = reply; + if (!missingExecutables.isEmpty()) { + // TODO check with PackageKit about missing drivers + qCWarning(PM_KDED) << "Missing executables:" << missingExecutables; + notify->deleteLater(); + return; + } else if (status == STATUS_SUCCESS) { + printerReadyNotification(notify, name); + } else { + // Model mismatch + checkPrinterCurrentDriver(notify, name); + } + }); +} + +void NewPrinterNotification::checkPrinterCurrentDriver(KNotification *notify, const QString &name) +{ + // Get the new printer attributes + auto request = new KCupsRequest; + connect(request, &KCupsRequest::finished, this, [this, notify, name] (KCupsRequest *request) { + request->deleteLater(); + + QString driver; + // Get the new printer driver + if (!request->printers().isEmpty()){ + const KCupsPrinter &printer = request->printers().first(); + driver = printer.makeAndModel(); + } + + // The cups request might have failed + if (driver.isEmpty()) { + notify->setText(i18n("'%1' has been added, please check its driver.", name)); + notify->setActions({ i18n("Configure") }); + connect(notify, &KNotification::action1Activated, this, &NewPrinterNotification::configurePrinter); + } else { + notify->setText(i18n("'%1' has been added, using the '%2' driver.", name, driver)); + notify->setActions({ i18n("Print test page"), i18n("Find driver") }); + connect(notify, &KNotification::action1Activated, this, &NewPrinterNotification::printTestPage); + connect(notify, &KNotification::action2Activated, this, &NewPrinterNotification::findDriver); + } + notify->sendEvent(); + }); + request->getPrinterAttributes(name, false, { KCUPS_PRINTER_MAKE_AND_MODEL }); +} + +void NewPrinterNotification::printerReadyNotification(KNotification *notify, const QString &name) +{ + notify->setText(i18n("'%1' is ready for printing.", name)); + notify->setActions({ i18n("Print test page"), i18n("Configure") }); + connect(notify, &KNotification::action1Activated, this, &NewPrinterNotification::printTestPage); + connect(notify, &KNotification::action2Activated, this, &NewPrinterNotification::configurePrinter); + notify->sendEvent(); } #include "moc_NewPrinterNotification.cpp" diff --git a/print-manager-kded/NewPrinterNotification.h b/print-manager-kded/NewPrinterNotification.h index 643ff4c..609ed0f 100644 --- a/print-manager-kded/NewPrinterNotification.h +++ b/print-manager-kded/NewPrinterNotification.h @@ -1,55 +1,57 @@ /*************************************************************************** * Copyright (C) 2010-2012 by Daniel Nicoletti * * dantti12@gmail.com * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; see the file COPYING. If not, write to * * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef NEW_PRINTER_NOTIFICATION_H #define NEW_PRINTER_NOTIFICATION_H #include #include +class KNotification; class NewPrinterNotification : public QObject, protected QDBusContext { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "com.redhat.NewPrinterNotification") public: - NewPrinterNotification(); + NewPrinterNotification(QObject *parent); ~NewPrinterNotification(); public slots: void GetReady(); void NewPrinter(int status, const QString &name, const QString &make, const QString &model, const QString &des, const QString &cmd); private slots: - void init(); bool registerService(); void configurePrinter(); void searchDrivers(); void printTestPage(); void findDriver(); void installDriver(); - void setupPrinter(); private: - QStringList getMissingExecutables(const QString &ppdFileName) const; + void setupPrinterNotification(KNotification *notify, const QString &make, const QString &model, const QString &description, const QString &arg); + void getMissingExecutables(KNotification *notify, int status, const QString &name, const QString &ppdFileName); + void checkPrinterCurrentDriver(KNotification *notify, const QString &name); + void printerReadyNotification(KNotification *notify, const QString &name); QThread *m_thread; QString m_destName; }; #endif // NEW_PRINTER_NOTIFICATION_H diff --git a/print-manager-kded/PrintManagerKded.cpp b/print-manager-kded/PrintManagerKded.cpp index 54a3400..b76998c 100644 --- a/print-manager-kded/PrintManagerKded.cpp +++ b/print-manager-kded/PrintManagerKded.cpp @@ -1,47 +1,42 @@ /*************************************************************************** * Copyright (C) 2010-2018 by Daniel Nicoletti * * dantti12@gmail.com * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; see the file COPYING. If not, write to * * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "PrintManagerKded.h" #include "NewPrinterNotification.h" #include PrintManagerKded::PrintManagerKded(QObject *parent, const QVariantList &args) : KDEDModule(parent) { Q_UNUSED(args) - QTimer::singleShot(0, this, &PrintManagerKded::loadThread); + QTimer::singleShot(0, this, [this] () { + new NewPrinterNotification(this); + }); } PrintManagerKded::~PrintManagerKded() { - if (m_newPrinterNotification) { - m_newPrinterNotification->deleteLater(); - } } -void PrintManagerKded::loadThread() -{ - m_newPrinterNotification = new NewPrinterNotification; -} #include "moc_PrintManagerKded.cpp" diff --git a/print-manager-kded/PrintManagerKded.h b/print-manager-kded/PrintManagerKded.h index feb04d3..878172b 100644 --- a/print-manager-kded/PrintManagerKded.h +++ b/print-manager-kded/PrintManagerKded.h @@ -1,45 +1,39 @@ /*************************************************************************** * Copyright (C) 2010-2018 by Daniel Nicoletti * * dantti12@gmail.com * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; see the file COPYING. If not, write to * * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef PRINTMANAGERKDED_H #define PRINTMANAGERKDED_H #include #include #include -class NewPrinterNotification; class PrintManagerKded : public KDEDModule { Q_OBJECT public: PrintManagerKded(QObject *parent, const QVariantList &args); ~PrintManagerKded(); - -private: - void loadThread(); - - NewPrinterNotification *m_newPrinterNotification = nullptr; }; K_PLUGIN_FACTORY(PrintDFactory, registerPlugin();) #endif // PRINTMANAGERKDED_H