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 "AddPrinterAssistant.h"
8 
9 #include "PageDestinations.h"
10 #include "PageChoosePrinters.h"
11 #include "PageChoosePPD.h"
12 #include "PageAddPrinter.h"
13 
14 #include <KCupsRequest.h>
15 
16 #include <QHostInfo>
17 #include <QPushButton>
18 
19 #include <KLocalizedString>
20 #include <KPixmapSequence>
21 #include <KIconLoader>
22 #include <KSharedConfig>
23 #include <KWindowConfig>
24 
AddPrinterAssistant()25 AddPrinterAssistant::AddPrinterAssistant()
26 {
27     setWindowTitle(i18nc("@title:window", "Add a New Printer"));
28     setWindowIcon(QIcon::fromTheme(QLatin1String("printer")));
29     buttonBox()->removeButton(buttonBox()->button(QDialogButtonBox::Cancel));
30     // Needed so we have our dialog size saved
31     setAttribute(Qt::WA_DeleteOnClose);
32 
33     QPushButton *helpButton = buttonBox()->addButton(QDialogButtonBox::Help);
34     // Configure the help button to be flat, disabled and empty
35     helpButton->setFlat(true);
36     helpButton->setEnabled(false);
37     helpButton->setIcon(QIcon());
38     helpButton->setText(QString());
39 
40     // Setup the busy cursor
41     m_busySeq = new KPixmapSequenceOverlayPainter(this);
42     m_busySeq->setSequence(KIconLoader::global()->loadPixmapSequence(QLatin1String("process-working"), KIconLoader::SizeSmallMedium));
43     m_busySeq->setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
44     m_busySeq->setWidget(helpButton);
45 
46     connect(finishButton(), &QPushButton::clicked, this, &AddPrinterAssistant::slotFinishButtonClicked);
47 
48     // Restore the dialog size
49     KConfigGroup configGroup(KSharedConfig::openConfig(QLatin1String("print-manager")), "AddPrinterAssistant");
50     KWindowConfig::restoreWindowSize(windowHandle(), configGroup);
51 }
52 
~AddPrinterAssistant()53 AddPrinterAssistant::~AddPrinterAssistant()
54 {
55     KConfigGroup configGroup(KSharedConfig::openConfig(QLatin1String("print-manager")), "AddPrinterAssistant");
56     KWindowConfig::saveWindowSize(windowHandle(), configGroup);
57 }
58 
initAddPrinter(const QString & printer,const QString & deviceId)59 void AddPrinterAssistant::initAddPrinter(const QString &printer, const QString &deviceId)
60 {
61     // setup our hash args with the information if we are
62     // adding a new printer or a class
63     QVariantHash args({
64                           {ADDING_PRINTER, true}
65                       });
66 
67     KPageWidgetItem *currentPage;
68     if (deviceId.isEmpty()) {
69         m_devicesPage = new KPageWidgetItem(new PageDestinations(args), i18nc("@title:window", "Select a Printer to Add"));
70         addPage(m_devicesPage);
71         currentPage = m_devicesPage;
72 
73         m_choosePPDPage = new KPageWidgetItem(new PageChoosePPD, i18nc("@title:window", "Pick a Driver"));
74         addPage(m_choosePPDPage);
75     } else {
76         args[KCUPS_DEVICE_URI] = printer;
77         args[KCUPS_DEVICE_ID] = deviceId;
78         args[KCUPS_DEVICE_LOCATION] = QHostInfo::localHostName();
79 
80         m_choosePPDPage = new KPageWidgetItem(new PageChoosePPD(args), i18nc("@title:window", "Pick a Driver"));
81         addPage(m_choosePPDPage);
82         currentPage = m_choosePPDPage;
83     }
84 
85     m_addPrinterPage = new KPageWidgetItem(new PageAddPrinter, i18nc("@title:window", "Please describe your printer"));
86     addPage(m_addPrinterPage);
87 
88     // Set this later so that all m_*Pages are created
89     setCurrentPage(currentPage);
90 }
91 
initAddClass()92 void AddPrinterAssistant::initAddClass()
93 {
94     // setup our hash args with the information if we are
95     // adding a new printer or a class
96     const QVariantHash args({
97                                 {ADDING_PRINTER, false},
98                                 {KCUPS_DEVICE_LOCATION, QHostInfo::localHostName()}
99                             });
100 
101     KPageWidgetItem *currentPage;
102     m_chooseClassPage = new KPageWidgetItem(new PageChoosePrinters(args), i18nc("@title:window", "Configure your connection"));
103     addPage(m_chooseClassPage);
104     currentPage = m_chooseClassPage;
105 
106     m_addPrinterPage = new KPageWidgetItem(new PageAddPrinter, i18nc("@title:window", "Please describe your printer"));
107     addPage(m_addPrinterPage);
108 
109     // Set this later so that all m_*Pages are created
110     setCurrentPage(currentPage);
111 }
112 
initChangePPD(const QString & printer,const QString & deviceUri,const QString & makeAndModel)113 void AddPrinterAssistant::initChangePPD(const QString &printer, const QString &deviceUri, const QString &makeAndModel)
114 {
115     // setup our hash args with the information if we are
116     // adding a new printer or a class
117     const QVariantHash args({
118                                 {ADDING_PRINTER, true},
119                                 {KCUPS_DEVICE_URI, deviceUri},
120                                 {KCUPS_PRINTER_NAME, printer},
121                                 {KCUPS_PRINTER_MAKE_AND_MODEL, makeAndModel}
122                             });
123 
124     m_choosePPDPage = new KPageWidgetItem(new PageChoosePPD(args), i18nc("@title:window", "Pick a Driver"));
125     addPage(m_choosePPDPage);
126     setCurrentPage(m_choosePPDPage);
127 }
128 
back()129 void AddPrinterAssistant::back()
130 {
131     KAssistantDialog::back();
132     auto currPage = qobject_cast<GenericPage*>(currentPage()->widget());
133     enableNextButton(currPage->canProceed());
134     if (!qobject_cast<GenericPage*>(currentPage()->widget())->isValid()) {
135         back();
136     }
137 }
138 
next()139 void AddPrinterAssistant::next()
140 {
141     next(currentPage());
142 }
143 
next(KPageWidgetItem * currentPage)144 void AddPrinterAssistant::next(KPageWidgetItem *currentPage)
145 {
146     // Each page has all it's settings and previous pages
147     // settings stored, so when going backwards
148     // we don't set (or even unset values),
149     // and we only call setValues on the next page if
150     // the currentPage() has changes.
151     const QVariantHash args = qobject_cast<GenericPage*>(currentPage->widget())->values();
152     if (currentPage == m_devicesPage) {
153         qobject_cast<GenericPage*>(m_choosePPDPage->widget())->setValues(args);
154         setCurrentPage(m_choosePPDPage);
155     } else if (currentPage == m_chooseClassPage ||currentPage == m_choosePPDPage) {
156         qobject_cast<GenericPage*>(m_addPrinterPage->widget())->setValues(args);
157         setCurrentPage(m_addPrinterPage);
158     }
159 }
160 
setCurrentPage(KPageWidgetItem * page)161 void AddPrinterAssistant::setCurrentPage(KPageWidgetItem *page)
162 {
163     // if after setting the values the page is still valid show
164     // it up, if not call next with it so we can find the next page
165     if (qobject_cast<GenericPage*>(page->widget())->isValid()) {
166         KAssistantDialog::setCurrentPage(page);
167         auto currPage = qobject_cast<GenericPage*>(currentPage()->widget());
168         auto nextPage = qobject_cast<GenericPage*>(page->widget());
169         // Disconnect the current page slots
170         disconnect(currPage, &GenericPage::allowProceed, this, &AddPrinterAssistant::enableNextButton);
171         disconnect(currPage, &GenericPage::allowProceed, this, &AddPrinterAssistant::enableFinishButton);
172         disconnect(currPage, &GenericPage::proceed, this, static_cast<void(AddPrinterAssistant::*)()>(&AddPrinterAssistant::next));
173         disconnect(currPage, &GenericPage::startWorking, m_busySeq, &KPixmapSequenceOverlayPainter::start);
174         disconnect(currPage, &GenericPage::stopWorking, m_busySeq, &KPixmapSequenceOverlayPainter::stop);
175 
176         // Connect next page signals
177         connect(nextPage, &GenericPage::startWorking, m_busySeq, &KPixmapSequenceOverlayPainter::start);
178         connect(nextPage, &GenericPage::stopWorking, m_busySeq, &KPixmapSequenceOverlayPainter::stop);
179         connect(nextPage, &GenericPage::proceed, this, static_cast<void(AddPrinterAssistant::*)()>(&AddPrinterAssistant::next));
180 
181         // check the working property
182         if (nextPage->isWorking()) {
183             m_busySeq->start();
184         } else {
185             m_busySeq->stop();
186         }
187 
188         // When ChangePPD() is called addPrinterPage is zero
189         if (page == m_addPrinterPage || m_addPrinterPage == nullptr) {
190             connect(nextPage, &GenericPage::allowProceed, this, &AddPrinterAssistant::enableFinishButton);
191             enableNextButton(false);
192             enableFinishButton(nextPage->canProceed());
193         } else {
194             connect(nextPage, &GenericPage::allowProceed, this, &AddPrinterAssistant::enableNextButton);
195             enableNextButton(nextPage->canProceed());
196         }
197     } else {
198         // In case page is not valid try the next one
199         next(page);
200     }
201 }
202 
showEvent(QShowEvent * event)203 void AddPrinterAssistant::showEvent(QShowEvent *event)
204 {
205     KAssistantDialog::showEvent(event);
206     enableNextButton(false);
207     enableFinishButton(false);
208 }
209 
slotFinishButtonClicked()210 void AddPrinterAssistant::slotFinishButtonClicked()
211 {
212     auto page = qobject_cast<GenericPage*>(currentPage()->widget());
213     enableFinishButton(false);
214     if (page->finishClicked()) {
215         //KAssistantDialog::slotButtonClicked(button); // FIXME next() really?
216         next();
217     } else {
218         enableFinishButton(true);
219     }
220 }
221 
enableNextButton(bool enable)222 void AddPrinterAssistant::enableNextButton(bool enable)
223 {
224     nextButton()->setEnabled(enable);
225 }
226 
enableFinishButton(bool enable)227 void AddPrinterAssistant::enableFinishButton(bool enable)
228 {
229     finishButton()->setEnabled(enable);
230 }
231 
232 #include "moc_AddPrinterAssistant.cpp"
233