From 691ae4d68064c74670f62656e8b87ae9f5809ff9 Mon Sep 17 00:00:00 2001 From: Ivailo Monev Date: Tue, 6 Jun 2023 19:36:17 +0300 Subject: [PATCH] kprintjobs: new KDED module to track and control print jobs requires 4ba42b20e15606db9048f8d583e0dd368b444d1b from kdelibs Signed-off-by: Ivailo Monev --- CMakeLists.txt | 1 + kprintjobs/CMakeLists.txt | 44 +++++++++++++ kprintjobs/kded_kprintjobs.cpp | 69 +++++++++++++++++++++ kprintjobs/kded_kprintjobs.h | 46 ++++++++++++++ kprintjobs/kprintjobs.desktop | 11 ++++ kprintjobs/kprintjobsimpl.cpp | 110 +++++++++++++++++++++++++++++++++ kprintjobs/kprintjobsimpl.h | 50 +++++++++++++++ 7 files changed, 331 insertions(+) create mode 100644 kprintjobs/CMakeLists.txt create mode 100644 kprintjobs/kded_kprintjobs.cpp create mode 100644 kprintjobs/kded_kprintjobs.h create mode 100644 kprintjobs/kprintjobs.desktop create mode 100644 kprintjobs/kprintjobsimpl.cpp create mode 100644 kprintjobs/kprintjobsimpl.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ad0186b..d33e1ee2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,3 +30,4 @@ macro_optional_add_subdirectory (kupdatenotifier) macro_optional_add_subdirectory (knetpkg) macro_optional_add_subdirectory (kfirewall) macro_optional_add_subdirectory (khash) +macro_optional_add_subdirectory (kprintjobs) diff --git a/kprintjobs/CMakeLists.txt b/kprintjobs/CMakeLists.txt new file mode 100644 index 00000000..8d6a3c06 --- /dev/null +++ b/kprintjobs/CMakeLists.txt @@ -0,0 +1,44 @@ +project(kprintjobs) + +if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}) + include(FeatureSummary) + + find_package(KDE4 4.23.0 REQUIRED) + include(KDE4Defaults) + include_directories(${KDE4_INCLUDES}) + add_definitions(${QT_DEFINITIONS} ${KDE4_DEFINITIONS}) +endif() + +########### next target ############### + +set(kded_kprintjobs_SRCS + kded_kprintjobs.cpp + kprintjobsimpl.cpp + ${CMAKE_CURRENT_BINARY_DIR}/org.kde.kprintjobs.xml +) + +qt4_generate_dbus_interface(kded_kprintjobs.h org.kde.kprintjobs.xml) + +kde4_add_plugin(kded_kprintjobs ${kded_kprintjobs_SRCS}) +target_link_libraries(kded_kprintjobs PRIVATE + ${KDE4_KDECORE_LIBS} + ${QT_QTDBUS_LIBRARY} + cups +) + +install( + TARGETS kded_kprintjobs + DESTINATION ${KDE4_PLUGIN_INSTALL_DIR} +) + +install( + FILES kprintjobs.desktop + DESTINATION ${KDE4_SERVICES_INSTALL_DIR}/kded +) + +install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/org.kde.kprintjobs.xml + DESTINATION ${KDE4_DBUS_INTERFACES_INSTALL_DIR} +) + + diff --git a/kprintjobs/kded_kprintjobs.cpp b/kprintjobs/kded_kprintjobs.cpp new file mode 100644 index 00000000..a0df2935 --- /dev/null +++ b/kprintjobs/kded_kprintjobs.cpp @@ -0,0 +1,69 @@ +/* This file is part of the KDE libraries + Copyright (C) 2023 Ivailo Monev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2, as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kded_kprintjobs.h" +#include "kpluginfactory.h" +#include "kdebug.h" + +#include + +K_PLUGIN_FACTORY(KPrintJobsModuleFactory, registerPlugin();) +K_EXPORT_PLUGIN(KPrintJobsModuleFactory("kprintjobs")) + +KPrintJobsModule::KPrintJobsModule(QObject *parent, const QList &args) + : KDEDModule(parent), + m_statetimer(this), + m_printjobstracker(nullptr) +{ + Q_UNUSED(args); + + connect(&m_statetimer, SIGNAL(timeout()), this, SLOT(slotCheckState())); + m_statetimer.start(500); +} + +KPrintJobsModule::~KPrintJobsModule() +{ + delete m_printjobstracker; +} + +void KPrintJobsModule::slotCheckState() +{ + cups_job_t* cupsjobs = nullptr; + int cupsjobscount = cupsGetJobs(&cupsjobs, NULL, 0, CUPS_WHICHJOBS_ACTIVE); + // qDebug() << Q_FUNC_INFO << cupsjobscount; + for (int i = 0; i < cupsjobscount; i++) { + // qDebug() << Q_FUNC_INFO << cupsjobs[i].id << cupsjobs[i].dest << cupsjobs[i].title << cupsjobs[i].user << cupsjobs[i].state; + const int cupsjobid = cupsjobs[i].id; + const int cupsjobstate = static_cast(cupsjobs[i].state); + KPrintJobsImpl* kprintjobsimpl = m_printjobs.value(cupsjobid, nullptr); + if (kprintjobsimpl) { + continue; + } + kprintjobsimpl = new KPrintJobsImpl(this, cupsjobid, cupsjobstate, cupsjobs[i].dest); + if (!m_printjobstracker) { + m_printjobstracker = new KUiServerJobTracker(this); + } + // TODO: connect to destroyed() and update m_printjobs + m_printjobs.insert(cupsjobid, kprintjobsimpl); + m_printjobstracker->registerJob(kprintjobsimpl); + kprintjobsimpl->start(); + } + cupsFreeJobs(cupsjobscount, cupsjobs); +} + +#include "moc_kded_kprintjobs.cpp" diff --git a/kprintjobs/kded_kprintjobs.h b/kprintjobs/kded_kprintjobs.h new file mode 100644 index 00000000..b422db4e --- /dev/null +++ b/kprintjobs/kded_kprintjobs.h @@ -0,0 +1,46 @@ +/* This file is part of the KDE libraries + Copyright (C) 2023 Ivailo Monev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2, as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KPRINTJOBS_KDED_H +#define KPRINTJOBS_KDED_H + +#include "kdedmodule.h" +#include "kprintjobsimpl.h" + +#include +#include +#include + +class KPrintJobsModule: public KDEDModule +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.kde.kprintjobs") +public: + KPrintJobsModule(QObject *parent, const QList &args); + ~KPrintJobsModule(); + +private Q_SLOTS: + void slotCheckState(); + +private: + QTimer m_statetimer; + QMap m_printjobs; + KUiServerJobTracker *m_printjobstracker; +}; + +#endif // KPRINTJOBS_KDED_H diff --git a/kprintjobs/kprintjobs.desktop b/kprintjobs/kprintjobs.desktop new file mode 100644 index 00000000..8f488865 --- /dev/null +++ b/kprintjobs/kprintjobs.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Icon=document-print +Name=Print Jobs +Comment=Notifies about and allows to control print jobs +Type=Service +X-KDE-ServiceTypes=KDEDModule +X-KDE-Library=kprintjobs +X-KDE-DBus-ModuleName=kprintjobs +X-KDE-Kded-autoload=true +X-KDE-Kded-load-on-demand=true +OnlyShowIn=KDE; diff --git a/kprintjobs/kprintjobsimpl.cpp b/kprintjobs/kprintjobsimpl.cpp new file mode 100644 index 00000000..00a3af49 --- /dev/null +++ b/kprintjobs/kprintjobsimpl.cpp @@ -0,0 +1,110 @@ +/* This file is part of the KDE libraries + Copyright (C) 2023 Ivailo Monev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2, as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kprintjobsimpl.h" +#include "klocale.h" +#include "kdebug.h" + +#include +#include + +KPrintJobsImpl::KPrintJobsImpl(QObject *parent, const int cupsjobid, const int cupsjobstate, const char* const cupsjobdest) + : KJob(parent), + m_cupsjobid(cupsjobid), + m_cupsjobstate(cupsjobstate), + m_cupsjobdestination(cupsjobdest), + m_emitdescription(true), + m_statetimer(this) +{ + setProperty("appName", QString::fromLatin1("kprintjobs")); + setProperty("appIconName", QString::fromLatin1("document-print")); + + setCapabilities(KJob::Killable); + + connect(&m_statetimer, SIGNAL(timeout()), this, SLOT(slotCheckState())); + + kDebug() << "Tracking print job" << m_cupsjobid; +} + +KPrintJobsImpl::~KPrintJobsImpl() +{ + kDebug() << "No longer tracking print job" << m_cupsjobid; +} + +void KPrintJobsImpl::start() +{ + m_statetimer.start(500); +} + +int KPrintJobsImpl::printState() const +{ + return m_cupsjobstate; +} + +bool KPrintJobsImpl::doKill() +{ + const int cupsresult = cupsCancelJob(m_cupsjobdestination.constData(), m_cupsjobid); + return (cupsresult == 1); +} + +void KPrintJobsImpl::slotCheckState() +{ + cups_job_t* cupsjobs = nullptr; + int cupsjobscount = cupsGetJobs(&cupsjobs, NULL, 0, CUPS_WHICHJOBS_ALL); + // qDebug() << Q_FUNC_INFO << cupsjobscount; + for (int i = 0; i < cupsjobscount; i++) { + const int cupsjobid = cupsjobs[i].id; + const int cupsjobstate = static_cast(cupsjobs[i].state); + if (cupsjobid != m_cupsjobid) { + continue; + } + // qDebug() << Q_FUNC_INFO << cupsjobs[i].id << cupsjobs[i].dest << cupsjobs[i].title << cupsjobs[i].user << cupsjobs[i].state; + if (m_emitdescription) { + m_emitdescription = false; + emit description(this, + QString::fromLocal8Bit(cupsjobs[i].title), + qMakePair(i18nc("The destination of a print operation", "Destination"), QFile::decodeName(cupsjobs[i].dest)) + ); + } + if (cupsjobstate == static_cast(IPP_JSTATE_HELD) && cupsjobstate != m_cupsjobstate) { + kDebug() << "Print job suspended" << m_cupsjobid; + m_cupsjobstate = cupsjobstate; + suspend(); + continue; + } else if (cupsjobstate == static_cast(IPP_JSTATE_PROCESSING) && cupsjobstate != m_cupsjobstate) { + kDebug() << "Print job resumed" << m_cupsjobid; + m_cupsjobstate = cupsjobstate; + resume(); + continue; + } else if (cupsjobstate == static_cast(IPP_JSTATE_CANCELED) || cupsjobstate == static_cast(IPP_JSTATE_ABORTED)) { + kDebug() << "Print job canceled/aborted" << m_cupsjobid; + m_statetimer.stop(); + setErrorText(i18n("Aborted")); + emitResult(); + break; + } else if (cupsjobstate == static_cast(IPP_JSTATE_COMPLETED)) { + kDebug() << "Print job completed" << m_cupsjobid; + m_statetimer.stop(); + emitResult(); + break; + } + } + cupsFreeJobs(cupsjobscount, cupsjobs); +} + +#include "moc_kprintjobsimpl.cpp" diff --git a/kprintjobs/kprintjobsimpl.h b/kprintjobs/kprintjobsimpl.h new file mode 100644 index 00000000..08859051 --- /dev/null +++ b/kprintjobs/kprintjobsimpl.h @@ -0,0 +1,50 @@ +/* This file is part of the KDE libraries + Copyright (C) 2023 Ivailo Monev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2, as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KPRINTJOBSIMPL_H +#define KPRINTJOBSIMPL_H + +#include +#include + +class KPrintJobsImpl: public KJob +{ + Q_OBJECT +public: + KPrintJobsImpl(QObject *parent, const int cupsjobid, const int cupsjobstate, const char* const cupsjobdest); + ~KPrintJobsImpl(); + + void start() final; + + int printState() const; + +protected: + bool doKill() final; + +private Q_SLOTS: + void slotCheckState(); + +private: + int m_cupsjobid; + int m_cupsjobstate; + QByteArray m_cupsjobdestination; + bool m_emitdescription; + QTimer m_statetimer; +}; + +#endif // KPRINTJOBSIMPL_H