File indexing completed on 2025-01-19 05:06:22

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 <QDebug>
0023 #include <QItemSelectionModel>
0024 
0025 // system-config-printer --setup-printer='file:/tmp/printout' --devid='MFG:Ricoh;MDL:Aficio SP C820DN'
0026 PageDestinations::PageDestinations(const QVariantMap &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 QVariantMap &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 QVariantMap PageDestinations::values() const
0125 {
0126     QVariantMap 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() && selection->selectedIndexes().size() == 1) {
0152         QModelIndex index = selection->selectedIndexes().first();
0153         QVariant uris = index.data(DevicesModel::DeviceUris);
0154         if (uris.isNull()) {
0155             ui->connectionsGB->setVisible(false);
0156         } else if (uris.type() == QVariant::StringList) {
0157             ui->connectionsCB->clear();
0158             for (const QString &uri : uris.toStringList()) {
0159                 ui->connectionsCB->addItem(m_model->uriDevice(uri), uri);
0160             }
0161             ui->connectionsGB->setVisible(true);
0162         } else {
0163             ui->connectionsCB->clear();
0164             const auto printers = uris.value<KCupsPrinters>();
0165             for (const KCupsPrinter &printer : printers) {
0166                 ui->connectionsCB->addItem(printer.name(), QVariant::fromValue(printer));
0167             }
0168             ui->connectionsGB->setVisible(true);
0169         }
0170     } else {
0171         ui->connectionsGB->setVisible(false);
0172         setCurrentPage(nullptr, selectedItemValues());
0173         return;
0174     }
0175 
0176     deviceUriChanged();
0177 }
0178 
0179 void PageDestinations::deviceUriChanged()
0180 {
0181     // Get the selected values
0182     QVariantMap args = selectedItemValues();
0183 
0184     // "beh" is excluded from the list
0185     QString deviceUri = args[KCUPS_DEVICE_URI].toString();
0186     qDebug() << deviceUri;
0187     if (deviceUri.startsWith(QLatin1String("parallel"))) {
0188         m_chooseLabel->setText(i18n("A printer connected to the parallel port."));
0189         setCurrentPage(m_chooseLabel, args);
0190     } else if (deviceUri.startsWith(QLatin1String("usb"))) {
0191         m_chooseLabel->setText(i18n("A printer connected to a USB port."));
0192         setCurrentPage(m_chooseLabel, args);
0193     } else if (deviceUri.startsWith(QLatin1String("bluetooth"))) {
0194         m_chooseLabel->setText(i18n("A printer connected via Bluetooth."));
0195         setCurrentPage(m_chooseLabel, args);
0196     } else if (deviceUri.startsWith(QLatin1String("hal"))) {
0197         m_chooseLabel->setText(
0198             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(
0203             i18n("HPLIP software driving a printer, "
0204                  "or the printer function of a multi-function device."));
0205         setCurrentPage(m_chooseLabel, args);
0206     } else if (deviceUri.startsWith(QLatin1String("hpfax"))) {
0207         m_chooseLabel->setText(
0208             i18n("HPLIP software driving a fax machine, "
0209                  "or the fax function of a multi-function device."));
0210         setCurrentPage(m_chooseLabel, args);
0211     } else if (deviceUri.startsWith(QLatin1String("dnssd")) || deviceUri.startsWith(QLatin1String("mdns"))) {
0212         // TODO this needs testing...
0213         QString text;
0214         if (deviceUri.contains(QLatin1String("cups"))) {
0215             text = i18n("Remote CUPS printer via DNS-SD");
0216         } else {
0217             QString protocol;
0218             if (deviceUri.contains(QLatin1String("._ipp"))) {
0219                 protocol = QLatin1String("IPP");
0220             } else if (deviceUri.contains(QLatin1String("._printer"))) {
0221                 protocol = QLatin1String("LPD");
0222             } else if (deviceUri.contains(QLatin1String("._pdl-datastream"))) {
0223                 protocol = QLatin1String("AppSocket/JetDirect");
0224             }
0225 
0226             if (protocol.isNull()) {
0227                 text = i18n("Network printer via DNS-SD");
0228             } else {
0229                 text = i18n("%1 network printer via DNS-SD", protocol);
0230             }
0231         }
0232         m_chooseLabel->setText(text);
0233         setCurrentPage(m_chooseLabel, args);
0234     } else if (deviceUri.startsWith(QLatin1String("socket"))) {
0235         qDebug() << "SOCKET";
0236         setCurrentPage(m_chooseSocket, args);
0237     } else if (deviceUri.startsWith(QLatin1String("ipp")) || deviceUri.startsWith(QLatin1String("ipps")) || deviceUri.startsWith(QLatin1String("http"))
0238                || deviceUri.startsWith(QLatin1String("https"))) {
0239         setCurrentPage(m_chooseUri, args);
0240     } else if (deviceUri.startsWith(QLatin1String("lpd"))) {
0241         setCurrentPage(m_chooseLpd, args);
0242     } else if (deviceUri.startsWith(QLatin1String("scsi"))) {
0243         // TODO
0244         setCurrentPage(m_chooseUri, args);
0245     } else if (deviceUri.startsWith(QLatin1String("serial"))) {
0246         setCurrentPage(m_chooseSerial, args);
0247     } else if (deviceUri.startsWith(QLatin1String("smb"))) {
0248         setCurrentPage(m_chooseSamba, args);
0249     } else if (deviceUri.startsWith(QLatin1String("network"))) {
0250         setCurrentPage(m_chooseUri, args);
0251     } else {
0252         setCurrentPage(m_chooseUri, args);
0253     }
0254 
0255     Q_EMIT allowProceed(canProceed());
0256 }
0257 
0258 void PageDestinations::insertDevice(const QString &device_class,
0259                                     const QString &device_id,
0260                                     const QString &device_info,
0261                                     const QString &device_make_and_model,
0262                                     const QString &device_uri,
0263                                     const QString &device_location,
0264                                     const KCupsPrinters &grouped_printers)
0265 {
0266     m_model->insertDevice(device_class, device_id, device_info, device_make_and_model, device_uri, device_location, grouped_printers);
0267 }
0268 
0269 QVariantMap PageDestinations::selectedItemValues() const
0270 {
0271     QVariantMap ret = m_args;
0272     if (!ui->devicesTV->selectionModel()->selectedIndexes().isEmpty() && ui->devicesTV->selectionModel()->selectedIndexes().size() == 1) {
0273         QModelIndex index = ui->devicesTV->selectionModel()->selectedIndexes().first();
0274         QVariant uri = index.data(DevicesModel::DeviceUri);
0275         QVariant uris = index.data(DevicesModel::DeviceUris);
0276         // if the devicesTV holds an item with grouped URIs
0277         // get the selected value from the connections combo box
0278         if (uris.isNull() || uris.type() == QVariant::StringList) {
0279             if (uris.type() == QVariant::StringList) {
0280                 uri = ui->connectionsCB->itemData(ui->connectionsCB->currentIndex());
0281             }
0282             ret[KCUPS_DEVICE_URI] = uri;
0283             ret[KCUPS_DEVICE_ID] = index.data(DevicesModel::DeviceId);
0284             ret[KCUPS_DEVICE_MAKE_AND_MODEL] = index.data(DevicesModel::DeviceMakeAndModel);
0285             ret[KCUPS_DEVICE_INFO] = index.data(DevicesModel::DeviceInfo);
0286             ret[KCUPS_DEVICE_LOCATION] = index.data(DevicesModel::DeviceLocation);
0287         } else {
0288             QVariant aux = ui->connectionsCB->itemData(ui->connectionsCB->currentIndex());
0289             KCupsPrinter printer = aux.value<KCupsPrinter>();
0290             QUrl url(uri.toString());
0291             url.setPath(QLatin1String("printers/") + printer.name());
0292             ret[KCUPS_DEVICE_URI] = url.url();
0293             ret[KCUPS_DEVICE_ID] = index.data(DevicesModel::DeviceId);
0294             ret[KCUPS_PRINTER_INFO] = printer.info();
0295             qDebug() << KCUPS_PRINTER_INFO << printer.info();
0296             ret[KCUPS_PRINTER_NAME] = printer.name();
0297             ret[KCUPS_DEVICE_LOCATION] = printer.location();
0298         }
0299         qDebug() << uri << ret;
0300     }
0301     return ret;
0302 }
0303 
0304 void PageDestinations::setCurrentPage(QWidget *widget, const QVariantMap &args)
0305 {
0306     auto page = qobject_cast<GenericPage *>(widget);
0307     if (page) {
0308         page->setValues(args);
0309         if (ui->stackedWidget->currentWidget() != page) {
0310             ui->stackedWidget->setCurrentWidget(page);
0311         }
0312     } else if (qobject_cast<QLabel *>(widget)) {
0313         if (ui->connectionsGB->isVisible() && ui->connectionsCB->currentText() == m_chooseLabel->text()) {
0314             // Don't show duplicated text for the user
0315             m_chooseLabel->clear();
0316         }
0317 
0318         if (ui->stackedWidget->currentWidget() != widget) {
0319             ui->stackedWidget->setCurrentWidget(widget);
0320         }
0321     } else {
0322         ui->stackedWidget->setCurrentIndex(0);
0323     }
0324 }
0325 
0326 #include "moc_PageDestinations.cpp"