mirror of
https://bitbucket.org/smil3y/kde-extraapps.git
synced 2025-02-24 19:02:53 +00:00
394 lines
17 KiB
C++
394 lines
17 KiB
C++
/***************************************************************************
|
|
* Copyright (C) 2010 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 "PrintKCM.h"
|
|
|
|
#include "ui_PrintKCM.h"
|
|
|
|
#include <config.h>
|
|
|
|
#include <PrinterModel.h>
|
|
#include <PrinterSortFilterModel.h>
|
|
#include "PrinterDelegate.h"
|
|
#include "PrinterDescription.h"
|
|
|
|
#include <KMessageBox>
|
|
#include <KPluginFactory>
|
|
#include <KAboutData>
|
|
#include <KToolInvocation>
|
|
#include <KIcon>
|
|
#include <KCupsRequest.h>
|
|
#include <KCupsServer.h>
|
|
#include <NoSelectionRectDelegate.h>
|
|
|
|
#include <QMenu>
|
|
|
|
#include <cups/cups.h>
|
|
|
|
K_PLUGIN_FACTORY(PrintKCMFactory, registerPlugin<PrintKCM>();)
|
|
K_EXPORT_PLUGIN(PrintKCMFactory("kcm_print", "print-manager"))
|
|
|
|
PrintKCM::PrintKCM(QWidget *parent, const QVariantList &args) :
|
|
KCModule(PrintKCMFactory::componentData(), parent, args),
|
|
ui(new Ui_PrintKCM),
|
|
m_lastError(-1), // Force the error to run on the first time
|
|
m_serverRequest(0)
|
|
{
|
|
KAboutData *aboutData;
|
|
aboutData = new KAboutData("kcm_print",
|
|
"print-manager",
|
|
ki18n("Print settings"),
|
|
PM_VERSION,
|
|
ki18n("Print settings"),
|
|
KAboutData::License_GPL,
|
|
ki18n("(C) 2010-2013 Daniel Nicoletti"));
|
|
setAboutData(aboutData);
|
|
setButtons(NoAdditionalButton);
|
|
|
|
ui->setupUi(this);
|
|
|
|
connect(ui->printerDesc, SIGNAL(updateNeeded()), SLOT(update()));
|
|
|
|
// The printer list needs to increase in width according to the icon sizes
|
|
// default dialog icon size is 32, this times 6 is 192 which is roughly the original width
|
|
ui->printersTV->setMinimumWidth(IconSize(KIconLoader::Dialog) * 6);
|
|
|
|
QMenu *addMenu = new QMenu(this);
|
|
addMenu->addAction(i18nc("@action:intoolbar","Add a Printer Class"),
|
|
this, SLOT(addClass()));
|
|
ui->addTB->setIcon(KIcon("list-add"));
|
|
ui->addTB->setToolTip(i18n("Add a new printer or a printer class"));
|
|
ui->addTB->setMenu(addMenu);
|
|
|
|
ui->removeTB->setIcon(KIcon("list-remove"));
|
|
ui->removeTB->setToolTip(i18n("Remove Printer"));
|
|
|
|
QMenu *systemMenu = new QMenu(this);
|
|
connect(systemMenu, SIGNAL(aboutToShow()), this, SLOT(getServerSettings()));
|
|
connect(systemMenu, SIGNAL(triggered(QAction*)), this, SLOT(systemPreferencesTriggered()));
|
|
#if CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR < 6
|
|
m_showSharedPrinters = systemMenu->addAction(i18nc("@action:intoolbar","Show printers shared by other systems"));
|
|
m_showSharedPrinters->setCheckable(true);
|
|
systemMenu->addSeparator();
|
|
#endif // CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR < 6
|
|
m_shareConnectedPrinters = systemMenu->addAction(i18nc("@action:intoolbar","Share printers connected to this system"));
|
|
m_shareConnectedPrinters->setCheckable(true);
|
|
m_allowPrintringFromInternet = systemMenu->addAction(i18nc("@action:intoolbar","Allow printing from the Internet"));
|
|
m_allowPrintringFromInternet->setCheckable(true);
|
|
m_allowPrintringFromInternet->setEnabled(false);
|
|
connect(m_shareConnectedPrinters, SIGNAL(toggled(bool)), m_allowPrintringFromInternet, SLOT(setEnabled(bool)));
|
|
connect(m_shareConnectedPrinters, SIGNAL(toggled(bool)), ui->printerDesc, SLOT(enableShareCheckBox(bool)));
|
|
systemMenu->addSeparator();
|
|
m_allowRemoteAdmin = systemMenu->addAction(i18nc("@action:intoolbar","Allow remote administration"));
|
|
m_allowRemoteAdmin->setCheckable(true);
|
|
m_allowUsersCancelAnyJob = systemMenu->addAction(i18nc("@action:intoolbar","Allow users to cancel any job (not just their own)"));
|
|
m_allowUsersCancelAnyJob->setCheckable(true);
|
|
|
|
ui->systemPreferencesTB->setIcon(KIcon("configure"));
|
|
ui->systemPreferencesTB->setToolTip(i18n("Configure the global preferences"));
|
|
ui->systemPreferencesTB->setMenu(systemMenu);
|
|
|
|
m_model = new PrinterModel(this);
|
|
PrinterSortFilterModel *sortModel = new PrinterSortFilterModel(this);
|
|
sortModel->setSourceModel(m_model);
|
|
ui->printersTV->setModel(sortModel);
|
|
ui->printersTV->setItemDelegate(new NoSelectionRectDelegate(this));
|
|
ui->printersTV->setItemDelegate(new PrinterDelegate(this));
|
|
connect(ui->printersTV->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
|
|
this, SLOT(update()));
|
|
connect(sortModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
|
|
this, SLOT(update()));
|
|
connect(sortModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
|
|
this, SLOT(update()));
|
|
connect(m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
|
|
this, SLOT(update()));
|
|
connect(m_model, SIGNAL(error(int,QString,QString)),
|
|
this, SLOT(error(int,QString,QString)));
|
|
|
|
ui->addPrinterBtn->setIcon(KIcon("list-add"));
|
|
connect(ui->addPrinterBtn, SIGNAL(clicked()), this, SLOT(on_addTB_clicked()));
|
|
|
|
// Force the model update AFTER we setup the error signal
|
|
m_model->update();
|
|
|
|
// Make sure we update our server settings if the user change it on
|
|
// another interface
|
|
connect(KCupsConnection::global(), SIGNAL(serverAudit(QString)), this, SLOT(getServerSettings()));
|
|
connect(KCupsConnection::global(), SIGNAL(serverRestarted(QString)), this, SLOT(getServerSettings()));
|
|
connect(KCupsConnection::global(), SIGNAL(serverStarted(QString)), this, SLOT(getServerSettings()));
|
|
connect(KCupsConnection::global(), SIGNAL(serverStopped(QString)), this, SLOT(getServerSettings()));
|
|
|
|
// We need to know the server settings so we disable the
|
|
// share printer checkbox if sharing is disabled on the server
|
|
getServerSettings();
|
|
}
|
|
|
|
PrintKCM::~PrintKCM()
|
|
{
|
|
delete ui;
|
|
}
|
|
|
|
void PrintKCM::error(int lastError, const QString &errorTitle, const QString &errorMsg)
|
|
{
|
|
if (lastError) {
|
|
// The user has no printer
|
|
// allow him to add a new one
|
|
if (lastError == IPP_NOT_FOUND) {
|
|
showInfo(KIcon("dialog-information"),
|
|
i18n("No printers have been configured or discovered"),
|
|
QString(),
|
|
true,
|
|
true);
|
|
} else {
|
|
showInfo(KIcon("printer", KIconLoader::global(), QStringList() << "" << "dialog-error"),
|
|
QString("<strong>%1</strong>").arg(errorTitle),
|
|
errorMsg,
|
|
false,
|
|
false);
|
|
}
|
|
}
|
|
|
|
if (m_lastError != lastError) {
|
|
// if no printer was found the server
|
|
// is still working
|
|
if (lastError == IPP_NOT_FOUND) {
|
|
ui->addTB->setEnabled(true);
|
|
ui->systemPreferencesTB->setEnabled(true);
|
|
} else {
|
|
ui->addTB->setEnabled(!lastError);
|
|
ui->systemPreferencesTB->setEnabled(!lastError);
|
|
}
|
|
|
|
m_lastError = lastError;
|
|
// Force an update
|
|
update();
|
|
}
|
|
}
|
|
|
|
void PrintKCM::showInfo(const KIcon &icon, const QString &title, const QString &comment, bool showAddPrinter, bool showToolButtons)
|
|
{
|
|
ui->hugeIcon->setPixmap(icon.pixmap(128, 128));
|
|
ui->errorText->setText(title);
|
|
ui->errorComment->setVisible(!comment.isEmpty());
|
|
ui->errorComment->setText(comment);
|
|
ui->addPrinterBtn->setVisible(showAddPrinter);
|
|
|
|
// Well, when there is no printer, there is nothing to add to a printer class
|
|
// so we can actually hide the Add button nontheless?
|
|
ui->addTB->setVisible(!showAddPrinter && showToolButtons);
|
|
ui->removeTB->setVisible(!showAddPrinter && showToolButtons);
|
|
ui->lineTB->setVisible(!showAddPrinter && showToolButtons);
|
|
ui->printersTV->setVisible(!showAddPrinter && showToolButtons);
|
|
|
|
// Make sure we are visible
|
|
ui->stackedWidget->setCurrentIndex(1);
|
|
}
|
|
|
|
void PrintKCM::update()
|
|
{
|
|
if (m_model->rowCount()) {
|
|
m_lastError = -1; // if the model has printers reset the error code
|
|
if (ui->stackedWidget->currentIndex() != 0) {
|
|
ui->stackedWidget->setCurrentIndex(0);
|
|
}
|
|
|
|
QItemSelection selection;
|
|
// we need to map the selection to source to get the real indexes
|
|
selection = ui->printersTV->selectionModel()->selection();
|
|
// select the first printer if there are printers
|
|
if (selection.indexes().isEmpty()) {
|
|
ui->printersTV->selectionModel()->select(m_model->index(0, 0), QItemSelectionModel::Select);
|
|
return;
|
|
}
|
|
|
|
QModelIndex index = selection.indexes().first();
|
|
QString destName = index.data(PrinterModel::DestName).toString();
|
|
if (ui->printerDesc->destName() != destName) {
|
|
ui->printerDesc->setPrinterIcon(index.data(Qt::DecorationRole).value<QIcon>());
|
|
int type = index.data(PrinterModel::DestType).toUInt();
|
|
// If we remove discovered printers, they will come
|
|
// back to hunt us a bit later
|
|
ui->removeTB->setEnabled(!(type & CUPS_PRINTER_DISCOVERED));
|
|
}
|
|
ui->printerDesc->setDestName(index.data(PrinterModel::DestName).toString(),
|
|
index.data(PrinterModel::DestDescription).toString(),
|
|
index.data(PrinterModel::DestIsClass).toBool(),
|
|
m_model->rowCount() == 1);
|
|
ui->printerDesc->setDestStatus(index.data(PrinterModel::DestStatus).toString());
|
|
ui->printerDesc->setLocation(index.data(PrinterModel::DestLocation).toString());
|
|
ui->printerDesc->setKind(index.data(PrinterModel::DestKind).toString());
|
|
ui->printerDesc->setIsShared(index.data(PrinterModel::DestIsShared).toBool());
|
|
ui->printerDesc->setAcceptingJobs(index.data(PrinterModel::DestIsAcceptingJobs).toBool());
|
|
ui->printerDesc->setIsDefault(index.data(PrinterModel::DestIsDefault).toBool());
|
|
ui->printerDesc->setCommands(index.data(PrinterModel::DestCommands).toStringList());
|
|
ui->printerDesc->setMarkers(index.data(PrinterModel::DestMarkers).value<QVariantHash>());
|
|
|
|
ui->addTB->show();
|
|
ui->removeTB->show();
|
|
ui->lineTB->show();
|
|
// Show the printer list only if there are more than 1 printer
|
|
ui->printersTV->setVisible(m_model->rowCount() > 1);
|
|
} else {
|
|
// disable the printer action buttons if there is nothing to selected
|
|
ui->removeTB->setEnabled(false);
|
|
|
|
if (m_lastError == IPP_OK) {
|
|
// the model is empty and no problem happened
|
|
showInfo(KIcon("dialog-information"),
|
|
i18n("No printers have been configured or discovered"),
|
|
QString(),
|
|
true,
|
|
true);
|
|
}
|
|
}
|
|
}
|
|
|
|
void PrintKCM::on_addTB_clicked()
|
|
{
|
|
QStringList args;
|
|
args << "--add-printer";
|
|
KToolInvocation::kdeinitExec(QLatin1String("kde-add-printer"), args);
|
|
}
|
|
|
|
void PrintKCM::addClass()
|
|
{
|
|
QStringList args;
|
|
args << "--add-class";
|
|
KToolInvocation::kdeinitExec(QLatin1String("kde-add-printer"), args);
|
|
}
|
|
|
|
void PrintKCM::on_removeTB_clicked()
|
|
{
|
|
QItemSelection selection;
|
|
// we need to map the selection to source to get the real indexes
|
|
selection = ui->printersTV->selectionModel()->selection();
|
|
// enable or disable the job action buttons if something is selected
|
|
if (!selection.indexes().isEmpty()) {
|
|
QModelIndex index = selection.indexes().first();
|
|
int resp;
|
|
QString msg, title;
|
|
if (index.data(PrinterModel::DestIsClass).toBool()) {
|
|
title = i18n("Remove class");
|
|
msg = i18n("Are you sure you want to remove the class '%1'?",
|
|
index.data(Qt::DisplayRole).toString());
|
|
} else {
|
|
title = i18n("Remove printer");
|
|
msg = i18n("Are you sure you want to remove the printer '%1'?",
|
|
index.data(Qt::DisplayRole).toString());
|
|
}
|
|
resp = KMessageBox::warningYesNo(this, msg, title);
|
|
if (resp == KMessageBox::Yes) {
|
|
QPointer<KCupsRequest> request = new KCupsRequest;
|
|
request->deletePrinter(index.data(PrinterModel::DestName).toString());
|
|
request->waitTillFinished();
|
|
if (request) {
|
|
request->deleteLater();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void PrintKCM::getServerSettings()
|
|
{
|
|
if (!m_serverRequest) {
|
|
QMenu *systemMenu = qobject_cast<QMenu*>(sender());
|
|
m_serverRequest = new KCupsRequest;
|
|
m_serverRequest->setProperty("interactive", static_cast<bool>(systemMenu));
|
|
connect(m_serverRequest, SIGNAL(finished()),
|
|
this, SLOT(getServerSettingsFinished()));
|
|
m_serverRequest->getServerSettings();
|
|
}
|
|
}
|
|
|
|
void PrintKCM::getServerSettingsFinished()
|
|
{
|
|
KCupsRequest *request = qobject_cast<KCupsRequest *>(sender());
|
|
|
|
// When we don't have any destinations error is set to IPP_NOT_FOUND
|
|
// we can safely ignore the error since it DOES bring the server settings
|
|
bool error = request->hasError() && request->error() != IPP_NOT_FOUND;
|
|
|
|
#if CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR < 6
|
|
m_showSharedPrinters->setEnabled(!error);
|
|
#endif // CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR < 6
|
|
m_shareConnectedPrinters->setEnabled(!error);
|
|
m_allowRemoteAdmin->setEnabled(!error);
|
|
m_allowUsersCancelAnyJob->setEnabled(!error);
|
|
|
|
if (error) {
|
|
if (request->property("interactive").toBool()) {
|
|
KMessageBox::detailedSorry(this,
|
|
i18nc("@info", "Failed to get server settings"),
|
|
request->errorMsg(),
|
|
i18nc("@title:window", "Failed"));
|
|
}
|
|
} else {
|
|
KCupsServer server = request->serverSettings();
|
|
|
|
#if CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR < 6
|
|
m_showSharedPrinters->setChecked(server.showSharedPrinters());
|
|
#endif // CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR < 6
|
|
m_shareConnectedPrinters->setChecked(server.sharePrinters());
|
|
m_allowPrintringFromInternet->setChecked(server.allowPrintingFromInternet());
|
|
m_allowRemoteAdmin->setChecked(server.allowRemoteAdmin());
|
|
m_allowUsersCancelAnyJob->setChecked(server.allowUserCancelAnyJobs());
|
|
}
|
|
|
|
request->deleteLater();
|
|
|
|
m_serverRequest = 0;
|
|
}
|
|
|
|
void PrintKCM::updateServerFinished()
|
|
{
|
|
KCupsRequest *request = qobject_cast<KCupsRequest *>(sender());
|
|
if (request->hasError()) {
|
|
if (request->error() == IPP_SERVICE_UNAVAILABLE ||
|
|
request->error() == IPP_INTERNAL_ERROR ||
|
|
request->error() == IPP_AUTHENTICATION_CANCELED) {
|
|
// Server is restarting, or auth was canceled, update the settings in one second
|
|
QTimer::singleShot(1000, this, SLOT(update()));
|
|
} else {
|
|
KMessageBox::detailedSorry(this,
|
|
i18nc("@info", "Failed to configure server settings"),
|
|
request->errorMsg(),
|
|
request->serverError());
|
|
|
|
// Force the settings to be retrieved again
|
|
update();
|
|
}
|
|
}
|
|
request->deleteLater();
|
|
}
|
|
|
|
void PrintKCM::systemPreferencesTriggered()
|
|
{
|
|
KCupsServer server;
|
|
#if CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR < 6
|
|
server.setShowSharedPrinters(m_showSharedPrinters->isChecked());
|
|
#endif // CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR < 6
|
|
server.setSharePrinters(m_shareConnectedPrinters->isChecked());
|
|
server.setAllowPrintingFromInternet(m_allowPrintringFromInternet->isChecked());
|
|
server.setAllowRemoteAdmin(m_allowRemoteAdmin->isChecked());
|
|
server.setAllowUserCancelAnyJobs(m_allowUsersCancelAnyJob->isChecked());
|
|
KCupsRequest *request = new KCupsRequest;
|
|
connect(request, SIGNAL(finished()), this, SLOT(updateServerFinished()));
|
|
request->setServerSettings(server);
|
|
}
|