File indexing completed on 2023-10-01 09:38:09

0001 /*
0002     SPDX-FileCopyrightText: 2010-2018 Daniel Nicoletti <dantti12@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "PageDestinations.h"
0008 #include "ui_PageDestinations.h"
0009 
0010 #include "DevicesModel.h"
0011 
0012 #include "ChooseLpd.h"
0013 #include "ChooseSamba.h"
0014 #include "ChooseSerial.h"
0015 #include "ChooseSocket.h"
0016 #include "ChooseUri.h"
0017 
0018 #include <KCupsRequest.h>
0019 #include <KLocalizedString>
0020 #include <NoSelectionRectDelegate.h>
0021 
0022 #include <QItemSelectionModel>
0023 #include <QDebug>
0024 
0025 // system-config-printer --setup-printer='file:/tmp/printout' --devid='MFG:Ricoh;MDL:Aficio SP C820DN'
0026 PageDestinations::PageDestinations(const QVariantHash &args, QWidget *parent) :
0027     GenericPage(parent),
0028     ui(new Ui::PageDestinations),
0029     m_chooseLpd(new ChooseLpd(this)),
0030     m_chooseSamba(new ChooseSamba(this)),
0031     m_chooseSerial(new ChooseSerial(this)),
0032     m_chooseSocket(new ChooseSocket(this)),
0033     m_chooseUri(new ChooseUri(this)),
0034     m_chooseLabel(new QLabel(this))
0035 {
0036     ui->setupUi(this);
0037     setAttribute(Qt::WA_DeleteOnClose);
0038 
0039     ui->stackedWidget->addWidget(m_chooseLpd);
0040     connect(m_chooseLpd, &ChooseLpd::allowProceed, this, &PageDestinations::allowProceed);
0041     connect(m_chooseLpd, &ChooseLpd::startWorking, this, &PageDestinations::working);
0042     connect(m_chooseLpd, &ChooseLpd::stopWorking, this, &PageDestinations::notWorking);
0043 
0044     ui->stackedWidget->addWidget(m_chooseSamba);
0045     connect(m_chooseSamba, &ChooseSamba::allowProceed, this, &PageDestinations::allowProceed);
0046     connect(m_chooseSamba, &ChooseSamba::startWorking, this, &PageDestinations::working);
0047     connect(m_chooseSamba, &ChooseSamba::stopWorking, this, &PageDestinations::notWorking);
0048 
0049     ui->stackedWidget->addWidget(m_chooseSerial);
0050     connect(m_chooseSerial, &ChooseSerial::allowProceed, this, &PageDestinations::allowProceed);
0051     connect(m_chooseSerial, &ChooseSerial::startWorking, this, &PageDestinations::working);
0052     connect(m_chooseSerial, &ChooseSerial::stopWorking, this, &PageDestinations::notWorking);
0053 
0054     ui->stackedWidget->addWidget(m_chooseSocket);
0055     connect(m_chooseSocket, &ChooseSocket::allowProceed, this, &PageDestinations::allowProceed);
0056     connect(m_chooseSocket, &ChooseSocket::startWorking, this, &PageDestinations::working);
0057     connect(m_chooseSocket, &ChooseSocket::stopWorking, this, &PageDestinations::notWorking);
0058 
0059     ui->stackedWidget->addWidget(m_chooseUri);
0060     connect(m_chooseUri, &ChooseUri::allowProceed, this, &PageDestinations::allowProceed);
0061     connect(m_chooseUri, &ChooseUri::startWorking, this, &PageDestinations::working);
0062     connect(m_chooseUri, &ChooseUri::stopWorking, this, &PageDestinations::notWorking);
0063     ui->messageWidget->setWordWrap(true);
0064     connect(m_chooseUri, &ChooseUri::errorMessage, ui->messageWidget, &KMessageWidget::setText);
0065     connect(m_chooseUri, &ChooseUri::errorMessage, ui->messageWidget, &KMessageWidget::animatedShow);
0066     connect(m_chooseUri, &ChooseUri::insertDevice, this, &PageDestinations::insertDevice);
0067 
0068     m_chooseLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
0069     ui->stackedWidget->addWidget(m_chooseLabel);
0070 
0071     // Hide the message widget
0072     ui->messageWidget->setWordWrap(true);
0073     ui->messageWidget->setMessageType(KMessageWidget::Error);
0074     ui->messageWidget->hide();
0075 
0076     // setup default options
0077     setWindowTitle(i18nc("@title:window", "Select a Printer to Add"));
0078     m_model = new DevicesModel(this);
0079     ui->devicesTV->setModel(m_model);
0080     ui->devicesTV->setItemDelegate(new NoSelectionRectDelegate(this));
0081     connect(ui->devicesTV->selectionModel(), &QItemSelectionModel::selectionChanged, this, &PageDestinations::deviceChanged);
0082     connect(m_model, &DevicesModel::errorMessage, ui->messageWidget, &KMessageWidget::setText);
0083     connect(m_model, &DevicesModel::errorMessage, ui->messageWidget, &KMessageWidget::animatedShow);
0084 
0085     // Expand when a parent is added
0086     connect(m_model, &DevicesModel::parentAdded, ui->devicesTV, &QTreeView::expand);
0087 
0088     // Update the view when the device URI combo box changed
0089     connect(ui->connectionsCB, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &PageDestinations::deviceUriChanged);
0090     ui->connectionsGB->setVisible(false);
0091 
0092     // Setup the busy cursor
0093     working();
0094     connect(m_model, &DevicesModel::loaded, this, &PageDestinations::notWorking);
0095 
0096     if (!args.isEmpty()) {
0097         // set our args
0098         setValues(args);
0099     }
0100 }
0101 
0102 PageDestinations::~PageDestinations()
0103 {
0104     delete ui;
0105 }
0106 
0107 void PageDestinations::setValues(const QVariantHash &args)
0108 {
0109     m_args = args;
0110     if (args[ADDING_PRINTER].toBool()) {
0111 //        m_isValid = true;
0112         m_model->update();
0113 //        m_busySeq->start();
0114     } else {
0115 //        m_isValid = false;
0116     }
0117 }
0118 
0119 bool PageDestinations::isValid() const
0120 {
0121     return true;
0122 }
0123 
0124 QVariantHash PageDestinations::values() const
0125 {
0126     QVariantHash ret = m_args;
0127     auto page = qobject_cast<GenericPage*>(ui->stackedWidget->currentWidget());
0128     if (page) {
0129         ret = page->values();
0130     } else if (canProceed()) {
0131         ret = selectedItemValues();
0132     }
0133     return ret;
0134 }
0135 
0136 bool PageDestinations::canProceed() const
0137 {
0138     bool ret = ui->stackedWidget->currentIndex() != 0;
0139 
0140     auto page = qobject_cast<GenericPage*>(ui->stackedWidget->currentWidget());
0141     if (page) {
0142         ret = page->canProceed();
0143     }
0144 
0145     return ret;
0146 }
0147 
0148 void PageDestinations::deviceChanged()
0149 {
0150     QItemSelectionModel *selection = ui->devicesTV->selectionModel();
0151     if (!selection->selectedIndexes().isEmpty() &&
0152             selection->selectedIndexes().size() == 1) {
0153         QModelIndex index = selection->selectedIndexes().first();
0154         QVariant uris = index.data(DevicesModel::DeviceUris);
0155         if (uris.isNull()) {
0156             ui->connectionsGB->setVisible(false);
0157         } else if (uris.type() == QVariant::StringList) {
0158             ui->connectionsCB->clear();
0159             for (const QString &uri : uris.toStringList()) {
0160                 ui->connectionsCB->addItem(uriText(uri), uri);
0161             }
0162             ui->connectionsGB->setVisible(true);
0163         } else {
0164             ui->connectionsCB->clear();
0165             const auto printers = uris.value<KCupsPrinters>();
0166             for (const KCupsPrinter &printer : printers) {
0167                 ui->connectionsCB->addItem(printer.name(), QVariant::fromValue(printer));
0168             }
0169             ui->connectionsGB->setVisible(true);
0170         }
0171     } else {
0172         ui->connectionsGB->setVisible(false);
0173         setCurrentPage(nullptr, selectedItemValues());
0174         return;
0175     }
0176 
0177     deviceUriChanged();
0178 }
0179 
0180 void PageDestinations::deviceUriChanged()
0181 {
0182     // Get the selected values
0183     QVariantHash args = selectedItemValues();
0184 
0185     // "beh" is excluded from the list
0186     QString deviceUri = args[KCUPS_DEVICE_URI].toString();
0187     qDebug() << deviceUri;
0188     if (deviceUri.startsWith(QLatin1String("parallel"))) {
0189         m_chooseLabel->setText(i18n("A printer connected to the parallel port."));
0190         setCurrentPage(m_chooseLabel, args);
0191     } else if (deviceUri.startsWith(QLatin1String("usb"))) {
0192         m_chooseLabel->setText(i18n("A printer connected to a USB port."));
0193         setCurrentPage(m_chooseLabel, args);
0194     } else if (deviceUri.startsWith(QLatin1String("bluetooth"))) {
0195         m_chooseLabel->setText(i18n("A printer connected via Bluetooth."));
0196         setCurrentPage(m_chooseLabel, args);
0197     } else if (deviceUri.startsWith(QLatin1String("hal"))) {
0198         m_chooseLabel->setText(i18n("Local printer detected by the "
0199                                     "Hardware Abstraction Layer (HAL)."));
0200         setCurrentPage(m_chooseLabel, args);
0201     } else if (deviceUri.startsWith(QLatin1String("hp"))) {
0202         m_chooseLabel->setText(i18n("HPLIP software driving a printer, "
0203                                     "or the printer function of a multi-function device."));
0204         setCurrentPage(m_chooseLabel, args);
0205     } else if (deviceUri.startsWith(QLatin1String("hpfax"))) {
0206         m_chooseLabel->setText(i18n("HPLIP software driving a fax machine, "
0207                                     "or the fax function of a multi-function device."));
0208         setCurrentPage(m_chooseLabel, args);
0209     } else if (deviceUri.startsWith(QLatin1String("dnssd")) ||
0210                deviceUri.startsWith(QLatin1String("mdns"))) {
0211         // TODO this needs testing...
0212         QString text;
0213         if (deviceUri.contains(QLatin1String("cups"))) {
0214             text = i18n("Remote CUPS printer via DNS-SD");
0215         } else {
0216             QString protocol;
0217             if (deviceUri.contains(QLatin1String("._ipp"))) {
0218                 protocol = QLatin1String("IPP");
0219             } else if (deviceUri.contains(QLatin1String("._printer"))) {
0220                 protocol = QLatin1String("LPD");
0221             } else if (deviceUri.contains(QLatin1String("._pdl-datastream"))) {
0222                 protocol = QLatin1String("AppSocket/JetDirect");
0223             }
0224 
0225             if (protocol.isNull()) {
0226                 text = i18n("Network printer via DNS-SD");
0227             } else {
0228                 text = i18n("%1 network printer via DNS-SD", protocol);
0229             }
0230         }
0231         m_chooseLabel->setText(text);
0232         setCurrentPage(m_chooseLabel, args);
0233     } else if (deviceUri.startsWith(QLatin1String("socket"))) {
0234         qDebug() << "SOCKET";
0235         setCurrentPage(m_chooseSocket, args);
0236     } else if (deviceUri.startsWith(QLatin1String("ipp")) ||
0237                deviceUri.startsWith(QLatin1String("ipps")) ||
0238                deviceUri.startsWith(QLatin1String("http")) ||
0239                deviceUri.startsWith(QLatin1String("https"))) {
0240         setCurrentPage(m_chooseUri, args);
0241     } else if (deviceUri.startsWith(QLatin1String("lpd"))) {
0242         setCurrentPage(m_chooseLpd, args);
0243     } else if (deviceUri.startsWith(QLatin1String("scsi"))) {
0244         // TODO
0245         setCurrentPage(m_chooseUri, args);
0246     } else if (deviceUri.startsWith(QLatin1String("serial"))) {
0247         setCurrentPage(m_chooseSerial, args);
0248     } else if (deviceUri.startsWith(QLatin1String("smb"))) {
0249         setCurrentPage(m_chooseSamba, args);
0250     } else if (deviceUri.startsWith(QLatin1String("network"))) {
0251         setCurrentPage(m_chooseUri, args);
0252     } else {
0253         setCurrentPage(m_chooseUri, args);
0254     }
0255 
0256     Q_EMIT allowProceed(canProceed());
0257 }
0258 
0259 void PageDestinations::insertDevice(const QString &device_class, const QString &device_id, const QString &device_info, const QString &device_make_and_model, const QString &device_uri, const QString &device_location, const KCupsPrinters &grouped_printers)
0260 {
0261     m_model->insertDevice(device_class,
0262                           device_id,
0263                           device_info,
0264                           device_make_and_model,
0265                           device_uri,
0266                           device_location,
0267                           grouped_printers);
0268 }
0269 
0270 QVariantHash PageDestinations::selectedItemValues() const
0271 {
0272     QVariantHash ret = m_args;
0273     if (!ui->devicesTV->selectionModel()->selectedIndexes().isEmpty() &&
0274             ui->devicesTV->selectionModel()->selectedIndexes().size() == 1) {
0275         QModelIndex index = ui->devicesTV->selectionModel()->selectedIndexes().first();
0276         QVariant uri = index.data(DevicesModel::DeviceUri);
0277         QVariant uris = index.data(DevicesModel::DeviceUris);
0278         // if the devicesTV holds an item with grouped URIs
0279         // get the selected value from the connections combo box
0280         if (uris.isNull() || uris.type() == QVariant::StringList) {
0281             if (uris.type() == QVariant::StringList) {
0282                 uri = ui->connectionsCB->itemData(ui->connectionsCB->currentIndex());
0283             }
0284             ret[KCUPS_DEVICE_URI] = uri;
0285             ret[KCUPS_DEVICE_ID] = index.data(DevicesModel::DeviceId);
0286             ret[KCUPS_DEVICE_MAKE_AND_MODEL] = index.data(DevicesModel::DeviceMakeAndModel);
0287             ret[KCUPS_DEVICE_INFO] = index.data(DevicesModel::DeviceInfo);
0288             ret[KCUPS_DEVICE_LOCATION] = index.data(DevicesModel::DeviceLocation);
0289         } else {
0290             QVariant aux = ui->connectionsCB->itemData(ui->connectionsCB->currentIndex());
0291             KCupsPrinter printer = aux.value<KCupsPrinter>();
0292             QUrl url(uri.toString());
0293             url.setPath(QLatin1String("printers/") + printer.name());
0294             ret[KCUPS_DEVICE_URI] = url.url();
0295             ret[KCUPS_DEVICE_ID] = index.data(DevicesModel::DeviceId);
0296             ret[KCUPS_PRINTER_INFO] = printer.info();
0297             qDebug() << KCUPS_PRINTER_INFO << printer.info();
0298             ret[KCUPS_PRINTER_NAME] = printer.name();
0299             ret[KCUPS_DEVICE_LOCATION] = printer.location();
0300         }
0301         qDebug() << uri << ret;
0302     }
0303     return ret;
0304 }
0305 
0306 void PageDestinations::setCurrentPage(QWidget *widget, const QVariantHash &args)
0307 {
0308     auto page = qobject_cast<GenericPage*>(widget);
0309     if (page) {
0310         page->setValues(args);
0311         if (ui->stackedWidget->currentWidget() != page) {
0312             ui->stackedWidget->setCurrentWidget(page);
0313         }
0314     } else if (qobject_cast<QLabel*>(widget)) {
0315         if (ui->connectionsGB->isVisible() &&
0316                 ui->connectionsCB->currentText() == m_chooseLabel->text()) {
0317             // Don't show duplicated text for the user
0318             m_chooseLabel->clear();
0319         }
0320 
0321         if (ui->stackedWidget->currentWidget() != widget) {
0322             ui->stackedWidget->setCurrentWidget(widget);
0323         }
0324     } else {
0325         ui->stackedWidget->setCurrentIndex(0);
0326     }
0327 }
0328 
0329 QString PageDestinations::uriText(const QString &uri) const
0330 {
0331     QString ret;
0332     if (uri.startsWith(QLatin1String("parallel"))) {
0333         ret = i18n("Parallel Port");
0334     } else if (uri.startsWith(QLatin1String("serial"))) {
0335         ret = i18n("Serial Port");
0336     } else if (uri.startsWith(QLatin1String("usb"))) {
0337         ret = i18n("USB");
0338     } else if (uri.startsWith(QLatin1String("bluetooth")) ){
0339         ret = i18n("Bluetooth");
0340     } else if (uri.startsWith(QLatin1String("hpfax"))) {
0341         ret = i18n("Fax - HP Linux Imaging and Printing (HPLIP)");
0342     } else if (uri.startsWith(QLatin1String("hp"))) {
0343         ret = i18n("HP Linux Imaging and Printing (HPLIP)");
0344     } else if (uri.startsWith(QLatin1String("hal"))) {
0345         ret = i18n("Hardware Abstraction Layer (HAL)");
0346     } else if (uri.startsWith(QLatin1String("socket"))) {
0347         ret = i18n("AppSocket/HP JetDirect");
0348     } else if (uri.startsWith(QLatin1String("lpd"))) {
0349         // Check if the queue name is defined
0350         const QString queue = uri.section(QLatin1Char('/'), -1, -1);
0351         if (queue.isEmpty()) {
0352             ret = i18n("LPD/LPR queue");
0353         } else {
0354             ret = i18n("LPD/LPR queue %1", queue);
0355         }
0356     } else if (uri.startsWith(QLatin1String("smb"))) {
0357         ret = i18n("Windows Printer via SAMBA");
0358     } else if (uri.startsWith(QLatin1String("ipp"))) {
0359         // Check if the queue name (fileName) is defined
0360         const QString queue = uri.section(QLatin1Char('/'), -1, -1);
0361         if (queue.isEmpty()) {
0362             ret = i18n("IPP");
0363         } else {
0364             ret = i18n("IPP %1", queue);
0365         }
0366     } else if (uri.startsWith(QLatin1String("https"))) {
0367         ret = i18n("HTTP");
0368     } else if (uri.startsWith(QLatin1String("dnssd")) ||
0369                uri.startsWith(QLatin1String("mdns"))) {
0370         // TODO this needs testing...
0371         QString text;
0372         if (uri.contains(QLatin1String("cups"))) {
0373             text = i18n("Remote CUPS printer via DNS-SD");
0374         } else {
0375             if (uri.contains(QLatin1String("._ipp"))) {
0376                 ret = i18n("IPP network printer via DNS-SD");
0377             } else if (uri.contains(QLatin1String("._printer"))) {
0378                 ret = i18n("LPD network printer via DNS-SD");
0379             } else if (uri.contains(QLatin1String("._pdl-datastream"))) {
0380                 ret = i18n("AppSocket/JetDirect network printer via DNS-SD");
0381             } else {
0382                 ret = i18n("Network printer via DNS-SD");
0383             }
0384         }
0385     } else {
0386         ret = uri;
0387     }
0388     return ret;
0389 }
0390 
0391 #include "moc_PageDestinations.cpp"