1 /*
2   SPDX-FileCopyrightText: 1998 Preston Brown <pbrown@kde.org>
3   SPDX-FileCopyrightText: 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
4 
5   SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
6 */
7 
8 #include "calprinter.h"
9 #include "calprintdefaultplugins.h"
10 #include "journalprint.h"
11 #include "yearprint.h"
12 
13 #include <KMessageBox>
14 #include <KStandardGuiItem>
15 #include <QVBoxLayout>
16 
17 #include <KConfigGroup>
18 #include <QButtonGroup>
19 #include <QDialogButtonBox>
20 #include <QGridLayout>
21 #include <QGroupBox>
22 #include <QPrintDialog>
23 #include <QPrintPreviewDialog>
24 #include <QSplitter>
25 #include <QStackedWidget>
26 
27 #include <PimCommon/KPimPrintPreviewDialog>
28 
29 using namespace CalendarSupport;
30 
CalPrinter(QWidget * parent,const Akonadi::ETMCalendar::Ptr & calendar,bool uniqItem)31 CalPrinter::CalPrinter(QWidget *parent, const Akonadi::ETMCalendar::Ptr &calendar, bool uniqItem)
32     : QObject(parent)
33     , mParent(parent)
34     , mConfig(new KConfig(QStringLiteral("calendar_printing.rc"), KConfig::SimpleConfig))
35     , mUniqItem(uniqItem)
36 {
37 
38     init(calendar);
39 }
40 
~CalPrinter()41 CalPrinter::~CalPrinter()
42 {
43     qDeleteAll(mPrintPlugins);
44     delete mConfig;
45 }
46 
init(const Akonadi::ETMCalendar::Ptr & calendar)47 void CalPrinter::init(const Akonadi::ETMCalendar::Ptr &calendar)
48 {
49     mCalendar = calendar;
50 
51     qDeleteAll(mPrintPlugins);
52     mPrintPlugins.clear();
53 
54     if (!mUniqItem) {
55         mPrintPlugins.prepend(new CalPrintYear());
56         mPrintPlugins.prepend(new CalPrintJournal());
57         mPrintPlugins.prepend(new CalPrintTodos());
58         mPrintPlugins.prepend(new CalPrintMonth());
59         mPrintPlugins.prepend(new CalPrintWeek());
60         mPrintPlugins.prepend(new CalPrintDay());
61     }
62     mPrintPlugins.prepend(new CalPrintIncidence());
63 
64     PrintPlugin::List::Iterator it = mPrintPlugins.begin();
65     PrintPlugin::List::Iterator end = mPrintPlugins.end();
66     for (; it != end; ++it) {
67         if (*it) {
68             (*it)->setConfig(mConfig);
69             (*it)->setCalendar(mCalendar);
70             (*it)->doLoadConfig();
71         }
72     }
73 }
74 
setDateRange(QDate fd,QDate td)75 void CalPrinter::setDateRange(QDate fd, QDate td)
76 {
77     for (const auto plugin : std::as_const(mPrintPlugins)) {
78         plugin->setDateRange(fd, td);
79     }
80 }
81 
print(int type,QDate fd,QDate td,const KCalendarCore::Incidence::List & selectedIncidences,bool preview)82 void CalPrinter::print(int type, QDate fd, QDate td, const KCalendarCore::Incidence::List &selectedIncidences, bool preview)
83 {
84     PrintPlugin::List::Iterator it;
85     const PrintPlugin::List::Iterator end = mPrintPlugins.end();
86     for (it = mPrintPlugins.begin(); it != end; ++it) {
87         (*it)->setSelectedIncidences(selectedIncidences);
88     }
89     QPointer<CalPrintDialog> printDialog = new CalPrintDialog(type, mPrintPlugins, mParent, mUniqItem);
90 
91     KConfigGroup grp(mConfig, ""); // orientation setting isn't in a group
92     printDialog->setOrientation(CalPrinter::ePrintOrientation(grp.readEntry("Orientation", 1)));
93     printDialog->setPreview(preview);
94     setDateRange(fd, td);
95 
96     if (printDialog->exec() == QDialog::Accepted) {
97         grp.writeEntry("Orientation", static_cast<int>(printDialog->orientation()));
98 
99         // Save all changes in the dialog
100         for (it = mPrintPlugins.begin(); it != mPrintPlugins.end(); ++it) {
101             (*it)->doSaveConfig();
102         }
103         doPrint(printDialog->selectedPlugin(), printDialog->orientation(), preview);
104     }
105     delete printDialog;
106 
107     for (it = mPrintPlugins.begin(); it != mPrintPlugins.end(); ++it) {
108         (*it)->setSelectedIncidences(KCalendarCore::Incidence::List());
109     }
110 }
111 
doPrint(PrintPlugin * selectedStyle,CalPrinter::ePrintOrientation dlgorientation,bool preview)112 void CalPrinter::doPrint(PrintPlugin *selectedStyle, CalPrinter::ePrintOrientation dlgorientation, bool preview)
113 {
114     if (!selectedStyle) {
115         KMessageBox::error(mParent, i18nc("@info", "Unable to print, an invalid print style was specified."), i18nc("@title:window", "Printing error"));
116         return;
117     }
118 
119     QPrinter printer;
120     switch (dlgorientation) {
121     case eOrientPlugin:
122         printer.setPageOrientation(selectedStyle->defaultOrientation());
123         break;
124     case eOrientPortrait:
125         printer.setPageOrientation(QPageLayout::Portrait);
126         break;
127     case eOrientLandscape:
128         printer.setPageOrientation(QPageLayout::Landscape);
129         break;
130     case eOrientPrinter:
131         break;
132     }
133 
134     if (preview) {
135         QPointer<PimCommon::KPimPrintPreviewDialog> printPreview = new PimCommon::KPimPrintPreviewDialog(&printer);
136         connect(printPreview.data(), &QPrintPreviewDialog::paintRequested, this, [selectedStyle, &printer]() {
137             selectedStyle->doPrint(&printer);
138         });
139         printPreview->exec();
140         delete printPreview;
141     } else {
142         QPointer<QPrintDialog> printDialog = new QPrintDialog(&printer, mParent);
143         if (printDialog->exec() == QDialog::Accepted) {
144             selectedStyle->doPrint(&printer);
145         }
146         delete printDialog;
147     }
148 }
149 
updateConfig()150 void CalPrinter::updateConfig()
151 {
152 }
153 
CalPrintDialog(int initialPrintType,const PrintPlugin::List & plugins,QWidget * parent,bool uniqItem)154 CalPrintDialog::CalPrintDialog(int initialPrintType, const PrintPlugin::List &plugins, QWidget *parent, bool uniqItem)
155     : QDialog(parent)
156 {
157     setWindowTitle(i18nc("@title:window", "Print"));
158     auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
159     auto mainLayout = new QVBoxLayout(this);
160     mOkButton = buttonBox->button(QDialogButtonBox::Ok);
161     mOkButton->setDefault(true);
162     mOkButton->setShortcut(Qt::CTRL | Qt::Key_Return);
163     connect(buttonBox, &QDialogButtonBox::accepted, this, &CalPrintDialog::slotOk);
164     connect(buttonBox, &QDialogButtonBox::rejected, this, &CalPrintDialog::reject);
165     setModal(true);
166     auto page = new QWidget(this);
167     auto pageVBoxLayout = new QVBoxLayout(page);
168     pageVBoxLayout->setContentsMargins(0, 0, 0, 0);
169     mainLayout->addWidget(page);
170     mainLayout->addWidget(buttonBox);
171 
172     auto splitter = new QSplitter(page);
173     pageVBoxLayout->addWidget(splitter);
174     splitter->setOrientation(Qt::Horizontal);
175     splitter->setChildrenCollapsible(false);
176     auto typeBox = new QGroupBox(i18nc("@title:group", "Print Style"), splitter);
177     QBoxLayout *typeLayout = new QVBoxLayout(typeBox);
178     mTypeGroup = new QButtonGroup(typeBox);
179 
180     auto splitterRight = new QWidget(splitter);
181     auto splitterRightLayout = new QGridLayout(splitterRight);
182     splitterRightLayout->setContentsMargins(0, 0, 0, 0);
183     // splitterRightLayout->setMargin( marginHint() );
184     // splitterRightLayout->setSpacing( spacingHint() );
185 
186     mConfigArea = new QStackedWidget(splitterRight);
187     splitterRightLayout->addWidget(mConfigArea, 0, 0, 1, 2);
188     auto orientationLabel = new QLabel(i18nc("@label", "Page &orientation:"), splitterRight);
189     orientationLabel->setAlignment(Qt::AlignRight);
190     splitterRightLayout->addWidget(orientationLabel, 1, 0);
191 
192     mOrientationSelection = new QComboBox(splitterRight);
193     mOrientationSelection->setToolTip(i18nc("@info:tooltip", "Set the print orientation"));
194     mOrientationSelection->setWhatsThis(i18nc("@info:whatsthis",
195                                               "Choose if you want your output to be printed in \"portrait\" or "
196                                               "\"landscape\". You can also default to the orientation best suited to "
197                                               "the selected style or to your printer's default setting."));
198     mOrientationSelection->addItem(i18nc("@item:inlistbox", "Use Default Orientation of Selected Style"));
199     mOrientationSelection->addItem(i18nc("@item:inlistbox", "Use Printer Default"));
200     mOrientationSelection->addItem(i18nc("@item:inlistbox", "Portrait"));
201     mOrientationSelection->addItem(i18nc("@item:inlistbox", "Landscape"));
202     splitterRightLayout->addWidget(mOrientationSelection, 1, 1);
203 
204     // signals and slots connections
205     connect(mTypeGroup, &QButtonGroup::buttonClicked, this, &CalPrintDialog::setPrintType);
206     orientationLabel->setBuddy(mOrientationSelection);
207 
208     // First insert the config widgets into the widget stack. This possibly assigns
209     // proper ids (when two plugins have the same sortID), so store them in a map
210     // and use these new IDs to later sort the plugins for the type selection.
211     for (PrintPlugin::List::ConstIterator it = plugins.constBegin(), total = plugins.constEnd(); it != total; ++it) {
212         int newid = mConfigArea->insertWidget((*it)->sortID(), (*it)->configWidget(mConfigArea));
213         mPluginIDs[newid] = (*it);
214     }
215     // Insert all plugins in sorted order; plugins with clashing IDs will be first
216     QMap<int, PrintPlugin *>::ConstIterator mapit;
217     bool firstButton = true;
218     int id = 0;
219     for (mapit = mPluginIDs.constBegin(); mapit != mPluginIDs.constEnd(); ++mapit) {
220         PrintPlugin *p = mapit.value();
221         auto radioButton = new QRadioButton(p->description());
222         radioButton->setEnabled(p->enabled());
223         radioButton->setToolTip(i18nc("@info:tooltip", "Select the type of print"));
224         radioButton->setWhatsThis(i18nc("@info:whatsthis",
225                                         "Select one of the following types of prints you want to make. "
226                                         "You may want to print an individual item, or all the items for a "
227                                         "specific time range (like a day, week or month), or you may want "
228                                         "to print your to-do list."));
229         // Check the first available button (to ensure one is selected initially) and then
230         // the button matching the desired print type -- if such is available!
231         if ((firstButton || p->sortID() == initialPrintType) && p->enabled()) {
232             firstButton = false;
233             radioButton->setChecked(true);
234             changePrintType(id);
235         }
236         mTypeGroup->addButton(radioButton, mapit.key());
237         typeLayout->addWidget(radioButton);
238         id++;
239     }
240     if (uniqItem) {
241         typeBox->hide();
242     }
243     typeLayout->insertStretch(-1, 100);
244     setMinimumSize(minimumSizeHint());
245     resize(minimumSizeHint());
246 }
247 
~CalPrintDialog()248 CalPrintDialog::~CalPrintDialog()
249 {
250 }
251 
setPreview(bool preview)252 void CalPrintDialog::setPreview(bool preview)
253 {
254     if (preview) {
255         mOkButton->setText(i18nc("@action:button", "&Preview"));
256     } else {
257         mOkButton->setText(KStandardGuiItem::print().text());
258     }
259 }
260 
changePrintType(int i)261 void CalPrintDialog::changePrintType(int i)
262 {
263     mConfigArea->setCurrentIndex(i);
264     mConfigArea->currentWidget()->raise();
265     QAbstractButton *btn = mTypeGroup->button(i);
266     if (btn) {
267         btn->setChecked(true);
268     }
269 }
270 
setPrintType(QAbstractButton * button)271 void CalPrintDialog::setPrintType(QAbstractButton *button)
272 {
273     if (button) {
274         const int i = mTypeGroup->id(button);
275         mConfigArea->setCurrentIndex(i);
276         mConfigArea->currentWidget()->raise();
277         button->setChecked(true);
278     }
279 }
280 
setOrientation(CalPrinter::ePrintOrientation orientation)281 void CalPrintDialog::setOrientation(CalPrinter::ePrintOrientation orientation)
282 {
283     mOrientation = orientation;
284     mOrientationSelection->setCurrentIndex(mOrientation);
285 }
286 
orientation() const287 CalPrinter::ePrintOrientation CalPrintDialog::orientation() const
288 {
289     return mOrientation;
290 }
291 
selectedPlugin()292 PrintPlugin *CalPrintDialog::selectedPlugin()
293 {
294     int id = mConfigArea->currentIndex();
295     if (mPluginIDs.contains(id)) {
296         return mPluginIDs[id];
297     } else {
298         return nullptr;
299     }
300 }
301 
slotOk()302 void CalPrintDialog::slotOk()
303 {
304     mOrientation = static_cast<CalPrinter::ePrintOrientation>(mOrientationSelection->currentIndex());
305 
306     QMap<int, PrintPlugin *>::ConstIterator it = mPluginIDs.constBegin();
307     for (; it != mPluginIDs.constEnd(); ++it) {
308         if (it.value()) {
309             it.value()->readSettingsWidget();
310         }
311     }
312     accept();
313 }
314