1 /*
2     SPDX-FileCopyrightText: 2010-2018 Daniel Nicoletti <dantti12@gmail.com>
3 
4     SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "PageChoosePPD.h"
8 #include "ui_PageChoosePPD.h"
9 
10 #include "DevicesModel.h"
11 
12 #include <SelectMakeModel.h>
13 #include <KCupsRequest.h>
14 #include <KLocalizedString>
15 
16 #include <QFileInfo>
17 #include <QFile>
18 #include <QDebug>
19 #include <QUrl>
20 #include <QTemporaryFile>
21 
PageChoosePPD(const QVariantHash & args,QWidget * parent)22 PageChoosePPD::PageChoosePPD(const QVariantHash &args, QWidget *parent) :
23     GenericPage(parent),
24     ui(new Ui::PageChoosePPD)
25 {
26     ui->setupUi(this);
27     setAttribute(Qt::WA_DeleteOnClose);
28 
29     // setup default options
30     setWindowTitle(i18nc("@title:window", "Select a Printer to Add"));
31 
32     m_layout = new QStackedLayout;
33     m_layout->setContentsMargins(0, 0, 0, 0);
34     ui->gridLayout->addLayout(m_layout, 1, 3);
35     m_selectMM = new SelectMakeModel(this);
36     connect(m_selectMM, &SelectMakeModel::changed, this, &PageChoosePPD::checkSelected);
37     m_layout->addWidget(m_selectMM);
38 
39     // Setup the busy cursor
40     connect(m_selectMM, &SelectMakeModel::changed, this, &PageChoosePPD::notWorking);
41 
42     if (!args.isEmpty()) {
43         // set our args
44         setValues(args);
45     }
46 }
47 
~PageChoosePPD()48 PageChoosePPD::~PageChoosePPD()
49 {
50     removeTempPPD();
51 
52     delete ui;
53 }
54 
setValues(const QVariantHash & args)55 void PageChoosePPD::setValues(const QVariantHash &args)
56 {
57     m_args = args;
58 
59     if (args[ADDING_PRINTER].toBool()) {
60 
61         qDebug() << args;
62         working();
63         removeTempPPD();
64         const QString deviceId = args[KCUPS_DEVICE_ID].toString();
65         QString make;
66         QString makeAndModel = args[KCUPS_DEVICE_MAKE_AND_MODEL].toString();
67         const QString deviceURI = args[KCUPS_DEVICE_URI].toString();
68 
69         // If
70         QUrl url(deviceURI + QLatin1String(".ppd"));
71         if (url.scheme() == QLatin1String("ipp")) {
72             auto tempFile = new QTemporaryFile;
73             tempFile->setFileTemplate(QLatin1String("print-manager-XXXXXX.ppd"));
74             tempFile->open();
75             url.setScheme(QLatin1String("http"));
76             if (url.port() < 0) {
77                 url.setPort(631);
78             }
79             qDebug() << deviceURI << url;
80             KJob *job = KIO::file_copy(url,
81                                       QUrl::fromLocalFile(tempFile->fileName()),
82                                       -1,
83                                       KIO::Overwrite | KIO::HideProgressInfo);
84             job->setProperty("URI", deviceURI);
85             connect(job, &KJob::result, this, &PageChoosePPD::resultJob);
86         }
87 
88         // Get the make from the device id
89         for (const QString &pair : deviceId.split(QLatin1Char(';'))) {
90             if (pair.startsWith(QLatin1String("MFG:"))) {
91                 make = pair.section(QLatin1Char(':'), 1);
92                 break;
93             }
94         }
95 
96         if (makeAndModel.isEmpty()) {
97             // Get the model  from the device id
98             for (const QString &pair : deviceId.split(QLatin1Char(';'))) {
99                 if (pair.startsWith(QLatin1String("MDL:"))) {
100                     // Build the make and model string
101                     if (make.isNull()) {
102                         makeAndModel = pair.section(QLatin1Char(':'), 1);
103                     } else {
104                         makeAndModel = make + QLatin1Char(' ') + pair.section(QLatin1Char(':'), 1);
105                     }
106                     break;
107                 }
108             }
109         }
110 
111         // if the device info is empty use the make and model
112         // so we can have a nice name for the new printer on the next page
113         if (!args.contains(KCUPS_DEVICE_INFO) && !makeAndModel.isEmpty()) {
114             m_args[KCUPS_DEVICE_INFO] = makeAndModel;
115         }
116 
117         m_selectMM->setDeviceInfo(deviceId, make, makeAndModel, deviceURI);
118         m_isValid = true;
119     } else {
120         m_isValid = false;
121     }
122 }
123 
isValid() const124 bool PageChoosePPD::isValid() const
125 {
126     return m_isValid;
127 }
128 
values() const129 QVariantHash PageChoosePPD::values() const
130 {
131     if (!isValid()) {
132         return m_args;
133     }
134 
135     QVariantHash ret = m_args;
136     if (canProceed()) {
137         if (!m_ppdFile.isNull()) {
138             ret[FILENAME] = m_ppdFile;
139         } else if (m_selectMM->isFileSelected()) {
140             ret[FILENAME] = m_selectMM->selectedPPDFileName();
141         } else {
142             ret[PPD_NAME] = m_selectMM->selectedPPDName();
143         }
144     }
145     return ret;
146 }
147 
canProceed() const148 bool PageChoosePPD::canProceed() const
149 {
150     // It can proceed if a PPD file (local or not) is provided    bool changed = false;
151     bool allow = false;
152 
153     if (m_selectMM->isFileSelected()) {
154         allow = !m_selectMM->selectedPPDFileName().isNull();
155     } else if (!m_ppdFile.isNull()) {
156         allow = true;
157     } else {
158         allow = !m_selectMM->selectedPPDName().isNull();
159     }
160 
161     qDebug() << allow;
162     return allow;
163 }
164 
checkSelected()165 void PageChoosePPD::checkSelected()
166 {
167     emit allowProceed(canProceed());
168 }
169 
selectDefault()170 void PageChoosePPD::selectDefault()
171 {
172 }
173 
resultJob(KJob * job)174 void PageChoosePPD::resultJob(KJob *job)
175 {
176     if (!job->error() && job->property("URI").toString() == m_args[KCUPS_DEVICE_URI].toString()) {
177         auto fileCopyJob = qobject_cast<KIO::FileCopyJob*>(job);
178 
179         // Make sure this job is for the current device
180         m_ppdFile = fileCopyJob->destUrl().toLocalFile();
181         m_isValid = false;
182         emit proceed();
183     }
184 }
185 
removeTempPPD()186 void PageChoosePPD::removeTempPPD()
187 {
188     if (!m_ppdFile.isEmpty()) {
189         QFile::remove(m_ppdFile);
190         m_ppdFile.clear();
191     }
192 }
193 
194 #include "moc_PageChoosePPD.cpp"
195