1 /* ============================================================
2  *
3  * This file is a part of KDE project
4  *
5  *
6  * Date        : 2008-01-11
7  * Description : a kipi plugin to print images
8  *
9  * Copyright 2008-2012 by Angelo Naselli <anaselli at linux dot it>
10  *
11  * This program is free software; you can redistribute it
12  * and/or modify it under the terms of the GNU General
13  * Public License as published by the Free Software Foundation;
14  * either version 2, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * ============================================================ */
22 
23 #include "wizard.h"
24 
25 // C++ includes
26 
27 #include <memory>
28 
29 // Qt includes
30 
31 #include <QFileInfo>
32 #include <QFileDialog>
33 #include <QPainter>
34 #include <QPalette>
35 #include <QtGlobal>
36 #include <QPrinter>
37 #include <QPrintDialog>
38 #include <QPageSetupDialog>
39 #include <QPrinterInfo>
40 #include <QProgressDialog>
41 #include <QDomDocument>
42 #include <QContextMenuEvent>
43 #include <QXmlStreamWriter>
44 #include <QXmlStreamAttributes>
45 #include <QStringRef>
46 #include <QStandardPaths>
47 #include <QMenu>
48 #include <QIcon>
49 #include <QLocale>
50 #include <QMessageBox>
51 
52 // KDE includes
53 
54 #include <kconfigdialogmanager.h>
55 #include <kconfig.h>
56 #include <kconfiggroup.h>
57 #include <kdesktopfile.h>
58 #include <klocalizedstring.h>
59 
60 // Libkipi includes
61 
62 #include <KIPI/ImageCollectionSelector>
63 #include <KIPI/Interface>
64 
65 // Local includes
66 
67 #include "kpwizardpage.h"
68 #include "kpimageslist.h"
69 #include "kpimageinfo.h"
70 #include "kpaboutdata.h"
71 #include "tphoto.h"
72 #include "utils.h"
73 #include "templateicon.h"
74 #include "customdlg.h"
75 #include "ui_croppage.h"
76 #include "ui_photopage.h"
77 #include "kipiplugins_debug.h"
78 
79 namespace KIPIPrintImagesPlugin
80 {
81 
82 template <class Ui_Class>
83 
84 class WizardUI : public QWidget, public Ui_Class
85 {
86 public:
87 
WizardUI(QWidget * const parent)88     WizardUI(QWidget* const parent)
89         : QWidget(parent)
90     {
91         this->setupUi(this);
92         layout()->setContentsMargins(QMargins());
93     }
94 };
95 
96 typedef WizardUI<Ui_PhotoPage> PhotoUI;
97 typedef WizardUI<Ui_CropPage>  CropUI;
98 
99 class WizardPage : public KPWizardPage
100 {
101 public:
102 
WizardPage(KPWizardDialog * const dialog,const QString & title,QWidget * const ui)103     WizardPage(KPWizardDialog* const dialog, const QString& title, QWidget* const ui)
104         : KPWizardPage(dialog, title)
105     {
106         setPageWidget(ui);
107         setShowLeftView(false);
108     }
109 };
110 
111 typedef WizardPage PhotoPage;
112 typedef WizardPage CropPage;
113 
114 // ---------------------------------------------------------------------------
115 
116 // some title name definitions (managed by translators)
117 const char* photoPageName        = I18N_NOOP("Select page layout");
118 const char* cropPageName         = I18N_NOOP("Crop photos");
119 // custom page layout
120 const char* customPageLayoutName = I18N_NOOP("Custom");
121 
122 // Wizard implementation
123 struct Wizard::Private
124 {
125     PhotoPage*               m_photoPage;
126     CropPage*                m_cropPage;
127 
128     PhotoUI*                 m_photoUi;
129     CropUI*                  m_cropUi;
130 
131     ImageCollectionSelector* m_collectionSelector;
132 
133     // Page Size in mm
134     QSizeF                   m_pageSize;
135     QList<TPhoto*>           m_photos;
136     QList<TPhotoSize*>       m_photoSizes;
137     int                      m_infopageCurrentPhoto;
138     int                      m_currentPreviewPage;
139     int                      m_currentCropPhoto;
140     bool                     m_cancelPrinting;
141     QString                  m_tempPath;
142     QStringList              m_gimpFiles;
143     QString                  m_savedPhotoSize;
144 
145     //QPrintDialog*                  m_printDialog;
146     QPageSetupDialog*        m_pDlg;
147     QPrinter*                m_printer;
148     QList<QPrinterInfo>      m_printerList;
149     KPImagesList*            m_imagesFilesListBox;
150 };
151 
Wizard(QWidget * const parent)152 Wizard::Wizard(QWidget* const parent)
153     : KPWizardDialog(parent),
154       d(new Private)
155 {
156     //d->m_printDialog          = 0;
157     d->m_pDlg                 = nullptr;
158     d->m_printer              = nullptr;
159     d->m_infopageCurrentPhoto = 0;
160 
161     // Caption
162     setWindowTitle(i18n("Print assistant"));
163 
164     // About data
165     KPAboutData* const about = new KPAboutData(ki18n("Print assistant"),
166                                                ki18n("A tool to print images"),
167                                                ki18n("(c) 2003-2004, Todd Shoemaker\n"
168                                                "(c) 2007-2013, Angelo Naselli"));
169 
170     about->addAuthor(ki18n("Todd Shoemaker").toString(),
171                      ki18n("Author").toString(),
172                      QLatin1String("todd@theshoemakers.net"));
173 
174     about->addAuthor(ki18n("Angelo Naselli").toString(),
175                      ki18n("Developer").toString(),
176                      QLatin1String("anaselli@linux.it"));
177 
178     about->addAuthor(ki18n("Andreas Trink").toString(),
179                      ki18n("Contributor").toString(),
180                      QLatin1String("atrink@nociaro.org"));
181 
182     about->setHandbookEntry(QLatin1String("tool-printwizard"));
183     setAboutData(about);
184 
185     d->m_photoUi        = new PhotoUI(this);
186     d->m_photoPage      = new PhotoPage(this, i18n(photoPageName), d->m_photoUi);
187 
188     d->m_cropUi         = new CropUI(this);
189     d->m_cropPage       = new CropPage(this, i18n(cropPageName), d->m_cropUi) ;
190 
191     //TODO
192     d->m_pageSize       = QSizeF(-1, -1); // select a different page to force a refresh in initPhotoSizes.
193 
194     QList<QPrinterInfo>::iterator it;
195     d->m_printerList    = QPrinterInfo::availablePrinters();
196     qCDebug(KIPIPLUGINS_LOG) << " printers: " << d->m_printerList.count();
197     //d->m_photoPage->m_printer_choice->setInsertPolicy(QComboBox::InsertAtTop/*QComboBox::InsertAlphabetically*/);
198 
199     for (it = d->m_printerList.begin(); it != d->m_printerList.end(); ++it)
200     {
201         qCDebug(KIPIPLUGINS_LOG) << " printer: " << it->printerName();
202         d->m_photoUi->m_printer_choice->addItem(it->printerName());
203     }
204 
205     // selected page
206     connect(this, SIGNAL(currentIdChanged(int)),
207             this, SLOT(pageChanged(int)));
208 
209     // cancel button
210     connect(button(QWizard::CancelButton), SIGNAL(clicked()),
211             this, SLOT(reject()));
212 
213     // caption information
214     connect(d->m_photoUi->m_captions, SIGNAL(activated(QString)),
215             this, SLOT(captionChanged(QString)));
216 
217     connect(d->m_photoUi->m_FreeCaptionFormat , SIGNAL(editingFinished()),
218             this, SLOT(infopage_updateCaptions()));
219 
220     connect(d->m_photoUi->m_sameCaption , SIGNAL(stateChanged(int)),
221             this, SLOT(infopage_updateCaptions()));
222 
223     connect(d->m_photoUi->m_font_name , SIGNAL(currentFontChanged(QFont)),
224             this, SLOT(infopage_updateCaptions()));
225 
226     connect(d->m_photoUi->m_font_size , SIGNAL(valueChanged(int)),
227             this, SLOT(infopage_updateCaptions()));
228 
229     connect(d->m_photoUi->m_font_color , SIGNAL(signalColorSelected(QColor)),
230             this, SLOT(infopage_updateCaptions()));
231 
232     connect(d->m_photoUi->m_setDefault , SIGNAL(clicked()),
233             this, SLOT(saveCaptionSettings()));
234 
235     // printer
236     connect(d->m_photoUi->m_printer_choice, SIGNAL(activated(QString)),
237             this, SLOT(outputChanged(QString)));
238 
239     connect(d->m_photoUi->BtnPreviewPageUp, SIGNAL(clicked()),
240             this, SLOT(BtnPreviewPageUp_clicked()));
241 
242     connect(d->m_photoUi->BtnPreviewPageDown, SIGNAL(clicked()),
243             this, SLOT(BtnPreviewPageDown_clicked()));
244 
245     connect(d->m_photoUi->ListPhotoSizes, SIGNAL(currentRowChanged(int)),
246             this, SLOT(ListPhotoSizes_selected()));
247 
248     connect(d->m_cropUi->BtnCropPrev, SIGNAL(clicked()),
249             this, SLOT(BtnCropPrev_clicked()));
250 
251     connect(d->m_cropUi->BtnCropNext, SIGNAL(clicked()),
252             this, SLOT(BtnCropNext_clicked()));
253 
254     connect(d->m_cropUi->BtnCropRotateRight, SIGNAL(clicked()),
255             this, SLOT(BtnCropRotateRight_clicked()));
256 
257     connect(d->m_cropUi->BtnCropRotateLeft, SIGNAL(clicked()),
258             this, SLOT(BtnCropRotateLeft_clicked()));
259 
260     // don't crop
261     connect(d->m_cropUi->m_disableCrop, SIGNAL(stateChanged(int)),
262             this, SLOT(crop_selection(int)));
263 
264     // remove a page
265     connect(this, SIGNAL(pageRemoved(int)),
266             this, SLOT(slotPageRemoved(int)));
267 
268     connect(d->m_photoUi->m_pagesetup, SIGNAL(clicked()),
269             this, SLOT(pagesetupclicked()));
270 
271     // save JPG as
272     connect ( d->m_cropUi->BtnSaveAs, SIGNAL (clicked()),
273             this, SLOT (BtnSaveAs_clicked()) );
274 
275 
276     if (d->m_photoUi->mPrintList->layout())
277     {
278         delete d->m_photoUi->mPrintList->layout();
279     }
280 
281     QVBoxLayout* printListLayout = new QVBoxLayout;
282     printListLayout->setContentsMargins(QMargins());
283     printListLayout->setSpacing(0);
284 
285     d->m_imagesFilesListBox = new KPImagesList(d->m_photoUi->mPrintList, 32);
286     d->m_imagesFilesListBox->setAllowDuplicate(true);
287     d->m_imagesFilesListBox->setControlButtons(KPImagesList::Add      |
288                                                KPImagesList::Remove   |
289                                                KPImagesList::MoveUp   |
290                                                KPImagesList::MoveDown |
291                                                KPImagesList::Clear    |
292                                                KPImagesList::Save     |
293                                                KPImagesList::Load);
294     d->m_imagesFilesListBox->setControlButtonsPlacement(KPImagesList::ControlButtonsAbove);
295     d->m_imagesFilesListBox->enableDragAndDrop(false);
296 
297     d->m_cropUi->BtnCropRotateRight->setIcon(QIcon::fromTheme(QLatin1String("object-rotate-right")).pixmap(16, 16));
298     d->m_cropUi->BtnCropRotateLeft->setIcon(QIcon::fromTheme(QLatin1String("object-rotate-left")).pixmap(16, 16));
299 
300     printListLayout->addWidget(d->m_imagesFilesListBox);
301     d->m_photoUi->mPrintList->setLayout(printListLayout);
302 
303     d->m_photoUi->BmpFirstPagePreview->setAlignment(Qt::AlignHCenter);
304 
305     connect(d->m_imagesFilesListBox, SIGNAL(signalMoveDownItem()),
306             this, SLOT(BtnPrintOrderDown_clicked()));
307 
308     connect(d->m_imagesFilesListBox, SIGNAL(signalMoveUpItem()),
309             this, SLOT(BtnPrintOrderUp_clicked()));
310 
311     connect(d->m_imagesFilesListBox, SIGNAL(signalAddItems(QList<QUrl>)),
312             this, SLOT(slotAddItems(QList<QUrl>)));
313 
314     connect(d->m_imagesFilesListBox, SIGNAL(signalRemovingItem(KIPIPlugins::KPImagesListViewItem*)),
315             this, SLOT(slotRemovingItem(KIPIPlugins::KPImagesListViewItem*)));
316 
317     connect(d->m_imagesFilesListBox, SIGNAL(signalItemClicked(QTreeWidgetItem*)),
318             this, SLOT(imageSelected(QTreeWidgetItem*)));
319 
320     connect(d->m_imagesFilesListBox, SIGNAL(signalContextMenuRequested()),
321             this, SLOT(slotContextMenuRequested()));
322 
323     // Save item list => we catch the signal to add our PA attributes and elements Image children
324     connect(d->m_imagesFilesListBox, SIGNAL(signalXMLSaveItem(QXmlStreamWriter&,KIPIPlugins::KPImagesListViewItem*)),
325             this, SLOT(slotXMLSaveItem(QXmlStreamWriter&,KIPIPlugins::KPImagesListViewItem*)));
326 
327     // Save item list => we catch the signal to add our PA elements (not per image)
328     connect(d->m_imagesFilesListBox, SIGNAL(signalXMLCustomElements(QXmlStreamWriter&)),
329             this, SLOT(slotXMLCustomElement(QXmlStreamWriter&)));
330 
331     connect(d->m_imagesFilesListBox, SIGNAL(signalXMLLoadImageElement(QXmlStreamReader&)),
332             this, SLOT(slotXMLLoadElement(QXmlStreamReader&)));
333 
334     connect(d->m_imagesFilesListBox, SIGNAL(signalXMLCustomElements(QXmlStreamReader&)),
335             this, SLOT(slotXMLCustomElement(QXmlStreamReader&)));
336 
337     // To get rid of icons that sometime are not shown
338     d->m_photoUi->BtnPreviewPageUp->setIcon(QIcon::fromTheme(QLatin1String("go-next")).pixmap(16, 16));
339     d->m_photoUi->BtnPreviewPageDown->setIcon(QIcon::fromTheme(QLatin1String("go-previous")).pixmap(16, 16));
340 
341     //arrow-up-double
342     d->m_currentPreviewPage = 0;
343     d->m_currentCropPhoto   = 0;
344     d->m_cancelPrinting     = false;
345 }
346 
~Wizard()347 Wizard::~Wizard()
348 {
349     // TODO private object could be deleted inside private destructor
350     delete d->m_pDlg;
351     delete d->m_printer;
352 
353     for (int i = 0; i < d->m_photos.count(); ++i)
354         delete d->m_photos.at(i);
355 
356     d->m_photos.clear();
357     delete d;
358 }
359 
360 // create a MxN grid of photos, fitting on the page
createPhotoGrid(TPhotoSize * p,int pageWidth,int pageHeight,int rows,int columns,TemplateIcon * iconpreview)361 void createPhotoGrid(TPhotoSize* p, int pageWidth, int pageHeight, int rows, int columns, TemplateIcon* iconpreview)
362 {
363     int MARGIN      = (int)(((double)pageWidth + (double)pageHeight) / 2.0 * 0.04 + 0.5);
364     int GAP         = MARGIN / 4;
365     int photoWidth  = (pageWidth - (MARGIN * 2) - ((columns - 1) * GAP)) / columns;
366     int photoHeight = (pageHeight - (MARGIN * 2) - ((rows - 1) * GAP)) / rows;
367     int row         = 0;
368 
369     for (int y = MARGIN; row < rows && y < pageHeight - MARGIN; y += photoHeight + GAP)
370     {
371         int col = 0;
372 
373         for (int x = MARGIN; col < columns && x < pageWidth - MARGIN; x += photoWidth + GAP)
374         {
375             p->layouts.append(new QRect(x, y, photoWidth, photoHeight));
376             iconpreview->fillRect(x, y, photoWidth, photoHeight, Qt::color1);
377             col++;
378         }
379 
380         row++;
381     }
382 }
383 
print(const QList<QUrl> & fileList,const QString & tempPath)384 void Wizard::print(const QList<QUrl>& fileList, const QString& tempPath)
385 {
386     for (int i = 0; i < d->m_photos.count(); ++i)
387         delete d->m_photos.at(i);
388 
389     d->m_photos.clear();
390     //d->m_photoPage->m_PictureInfo->setRowCount(fileList.count());
391 
392     for (int i = 0; i < fileList.count(); ++i)
393     {
394         TPhoto* const photo = new TPhoto(150);
395         photo->filename     = fileList[i];
396         photo->first        = true;
397         d->m_photos.append(photo);
398     }
399 
400     d->m_tempPath = tempPath;
401     d->m_cropUi->BtnCropPrev->setEnabled(false);
402 
403     if (d->m_photos.count() == 1)
404         d->m_cropUi->BtnCropNext->setEnabled(false);
405 
406     emit currentIdChanged(d->m_photoPage->id());
407 }
408 
parseTemplateFile(const QString & fn,const QSizeF & pageSize)409 void Wizard::parseTemplateFile(const QString& fn, const QSizeF& pageSize)
410 {
411     QDomDocument doc(QLatin1String("mydocument"));
412     qCDebug(KIPIPLUGINS_LOG) << " XXX: " <<  fn;
413 
414     if (fn.isEmpty())
415     {
416         return;
417     }
418 
419     QFile file(fn);
420 
421     if (!file.open(QIODevice::ReadOnly))
422         return;
423 
424     if (!doc.setContent(&file))
425     {
426         file.close();
427         return;
428     }
429 
430     file.close();
431 
432     TPhotoSize* p = nullptr;
433 
434     // print out the element names of all elements that are direct children
435     // of the outermost element.
436     QDomElement docElem = doc.documentElement();
437     qCDebug(KIPIPLUGINS_LOG) << docElem.tagName(); // the node really is an element.
438 
439     QSizeF size;
440     QString unit;
441     int scaleValue;
442     QDomNode n = docElem.firstChild();
443 
444     while (!n.isNull())
445     {
446         size          = QSizeF(0, 0);
447         scaleValue    = 10; // 0.1 mm
448         QDomElement e = n.toElement(); // try to convert the node to an element.
449 
450         if (!e.isNull())
451         {
452             if (e.tagName() == QLatin1String("paper"))
453             {
454                 size = QSizeF(e.attribute(QLatin1String("width"),  QLatin1String("0")).toFloat(),
455                               e.attribute(QLatin1String("height"), QLatin1String("0")).toFloat());
456                 unit = e.attribute(QLatin1String("unit"), QLatin1String("mm"));
457 
458                 qCDebug(KIPIPLUGINS_LOG) <<  e.tagName() << QLatin1String(" name=") << e.attribute(QLatin1String("name"), QLatin1String("??"))
459                                          << " size= " << size
460                                          << " unit= " << unit;
461 
462                 if (size == QSizeF(0.0, 0.0) && size == pageSize)
463                 {
464                     // skipping templates without page size since pageSize is not set
465                     n = n.nextSibling();
466                     continue;
467                 }
468                 else if (unit != QLatin1String("mm") && size != QSizeF(0.0, 0.0)) // "cm", "inches" or "inch"
469                 {
470                     // convert to mm
471                     if (unit == QLatin1String("inches") ||  unit == QLatin1String("inch"))
472                     {
473                         size *= 25.4;
474                         scaleValue = 1000;
475                         qCDebug(KIPIPLUGINS_LOG) << "template size " << size << " page size " << pageSize;
476                     }
477                     else if (unit == QLatin1String("cm"))
478                     {
479                         size *= 10;
480                         scaleValue = 100;
481                         qCDebug(KIPIPLUGINS_LOG) << "template size " << size << " page size " << pageSize;
482                     }
483                     else
484                     {
485                         qCWarning(KIPIPLUGINS_LOG) << "Wrong unit " << unit << " skipping layout";
486                         n = n.nextSibling();
487                         continue;
488                     }
489                 }
490 
491                 static const float round_value = 0.01F;
492 
493                 if (size == QSizeF(0, 0))
494                 {
495                     size = pageSize;
496                     unit = QLatin1String("mm");
497                 }
498                 else if (pageSize     != QSizeF(0, 0) &&
499                          (size.height() > (pageSize.height() + round_value) ||
500                           size.width()  > (pageSize.width() + round_value)))
501                 {
502                     qCDebug(KIPIPLUGINS_LOG) << "skipping size " << size << " page size " << pageSize;
503                     // skipping layout it can't fit
504                     n = n.nextSibling();
505                     continue;
506                 }
507 
508                 // Next templates are good
509                 qCDebug(KIPIPLUGINS_LOG) << "layout size " << size << " page size " << pageSize;
510                 QDomNode np = e.firstChild();
511 
512                 while (!np.isNull())
513                 {
514                     QDomElement ep = np.toElement(); // try to convert the node to an element.
515 
516                     if (!ep.isNull())
517                     {
518                         if (ep.tagName() == QLatin1String("template"))
519                         {
520                             p = new TPhotoSize;
521                             QSizeF sizeManaged;
522 
523                             // set page size
524                             if (pageSize == QSizeF(0, 0))
525                             {
526                                 sizeManaged = size * scaleValue;
527                             }
528                             else if (unit == QLatin1String("inches") || unit == QLatin1String("inch"))
529                             {
530                                 sizeManaged = pageSize * scaleValue / 25.4;
531                             }
532                             else
533                             {
534                                 sizeManaged = pageSize * 10;
535                             }
536 
537                             p->layouts.append(new QRect(0, 0, (int)sizeManaged.width(), (int)sizeManaged.height()));
538                             // create a small preview of the template
539                             // TODO check if iconsize here is useless
540                             TemplateIcon iconpreview(80, sizeManaged.toSize());
541                             iconpreview.begin();
542 
543                             QString desktopFileName = ep.attribute(QLatin1String("name"), QLatin1String("XXX")) +
544                                                                    QLatin1String(".desktop");
545 
546                             QDir dir(QStandardPaths::locate(QStandardPaths::GenericDataLocation,
547                                                             QLatin1String("kipiplugin_printimages/templates"),
548                                                             QStandardPaths::LocateDirectory));
549                             const QStringList list = dir.entryList(QStringList() << desktopFileName);
550 
551                             qCDebug(KIPIPLUGINS_LOG) << "Template desktop files list: " << list;
552 
553                             QStringList::ConstIterator it  = list.constBegin();
554                             QStringList::ConstIterator end = list.constEnd();
555 
556                             if (it != end)
557                             {
558                                 p->label = KDesktopFile(dir.absolutePath() + QLatin1String("/") + *it).readName();
559                             }
560                             else
561                             {
562                                 p->label = ep.attribute(QLatin1String("name"), QLatin1String("XXX"));
563                                 qCWarning(KIPIPLUGINS_LOG) << "missed template translation " << desktopFileName;
564                             }
565 
566                             p->dpi        = ep.attribute(QLatin1String("dpi"), QLatin1String("0")).toInt();
567                             p->autoRotate = (ep.attribute(QLatin1String("autorotate"), QLatin1String("false")) == QLatin1String("true")) ? true : false;
568                             QDomNode nt   = ep.firstChild();
569 
570                             while (!nt.isNull())
571                             {
572                                 QDomElement et = nt.toElement(); // try to convert the node to an element.
573 
574                                 if (!et.isNull())
575                                 {
576                                     if (et.tagName() == QLatin1String("photo"))
577                                     {
578                                         float value = et.attribute(QLatin1String("width"), QLatin1String("0")).toFloat();
579                                         int width   = (int)((value == 0 ? size.width() : value) * scaleValue);
580                                         value       = et.attribute(QLatin1String("height"), QLatin1String("0")).toFloat();
581                                         int height  = (int)((value == 0 ? size.height() : value) * scaleValue);
582                                         int photoX  = (int)((et.attribute(QLatin1String("x"), QLatin1String("0")).toFloat() * scaleValue));
583                                         int photoY  = (int)((et.attribute(QLatin1String("y"), QLatin1String("0")).toFloat() * scaleValue));
584                                         p->layouts.append(new QRect(photoX, photoY, width, height));
585                                         iconpreview.fillRect(photoX, photoY, width, height, Qt::color1);
586                                     }
587                                     else if (et.tagName() == QLatin1String("photogrid"))
588                                     {
589                                         float value    = et.attribute(QLatin1String("pageWidth"), QLatin1String("0")).toFloat();
590                                         int pageWidth  = (int)((value == 0 ? size.width() : value) * scaleValue);
591                                         value          = et.attribute(QLatin1String("pageHeight"), QLatin1String("0")).toFloat();
592                                         int pageHeight = (int)((value == 0 ? size.height() : value) * scaleValue);
593                                         int rows       = et.attribute(QLatin1String("rows"), QLatin1String("0")).toInt();
594                                         int columns    = et.attribute(QLatin1String("columns"), QLatin1String("0")).toInt();
595 
596                                         if (rows > 0 && columns > 0)
597                                         {
598                                             createPhotoGrid(p, pageWidth, pageHeight, rows, columns, &iconpreview);
599                                         }
600                                         else
601                                         {
602                                             qCWarning(KIPIPLUGINS_LOG) << " Wrong grid configuration, rows " << rows << ", columns " << columns;
603                                         }
604                                     }
605                                     else
606                                     {
607                                         qCDebug(KIPIPLUGINS_LOG) << "    " <<  et.tagName();
608                                     }
609                                 }
610 
611                                 nt = nt.nextSibling();
612                             }
613 
614                             iconpreview.end();
615                             p->icon = iconpreview.getIcon();
616                             d->m_photoSizes.append(p);
617                         }
618                         else
619                         {
620                             qCDebug(KIPIPLUGINS_LOG) << "? " <<  ep.tagName() << " attr=" << ep.attribute(QLatin1String("name"), QLatin1String("??"));
621                         }
622                     }
623 
624                     np = np.nextSibling();
625                 }
626             }
627             else
628             {
629                 qCDebug(KIPIPLUGINS_LOG) << "??" << e.tagName() << " name=" << e.attribute(QLatin1String("name"), QLatin1String("??"));
630             }
631         }
632 
633         n = n.nextSibling();
634     }
635 }
636 
initPhotoSizes(const QSizeF & pageSize)637 void Wizard::initPhotoSizes(const QSizeF& pageSize)
638 {
639     qCDebug(KIPIPLUGINS_LOG) << "New page size " << pageSize
640                              << ", old page size " << d->m_pageSize;
641 
642     // don't refresh anything if we haven't changed page sizes.
643     if (pageSize == d->m_pageSize)
644         return;
645 
646     d->m_pageSize = pageSize;
647 
648     // cleaning m_pageSize memory before invoking clear()
649     for (int i = 0; i < d->m_photoSizes.count(); ++i)
650         delete d->m_photoSizes.at(i);
651 
652     d->m_photoSizes.clear();
653 
654     // get template-files and parse them
655 
656     QDir dir(QStandardPaths::locate(QStandardPaths::GenericDataLocation,
657                                     QLatin1String("kipiplugin_printimages/templates"),
658                                     QStandardPaths::LocateDirectory));
659     const QStringList list = dir.entryList(QStringList() << QLatin1String("*.xml"));
660 
661     qCDebug(KIPIPLUGINS_LOG) << "Template XML files list: " << list;
662 
663     foreach(const QString& fn, list)
664     {
665         parseTemplateFile(dir.absolutePath() + QLatin1String("/") + fn, pageSize);
666     }
667 
668     qCDebug(KIPIPLUGINS_LOG) << "d->m_photoSizes.count()="   << d->m_photoSizes.count();
669     qCDebug(KIPIPLUGINS_LOG) << "d->m_photoSizes.isEmpty()=" << d->m_photoSizes.isEmpty();
670 
671     if (d->m_photoSizes.isEmpty())
672     {
673         qCDebug(KIPIPLUGINS_LOG) << "Empty photoSize-list, create default size\n";
674         // There is no valid page size yet.  Create a default page (B10) to prevent crashes.
675         TPhotoSize* const p = new TPhotoSize;
676         p->dpi              = 0;
677         p->autoRotate       = false;
678         p->label            = i18n("Unsupported Paper Size");
679         // page size: B10 (32 x 45 mm)
680         p->layouts.append(new QRect(0, 0, 3200, 4500));
681         p->layouts.append(new QRect(0, 0, 3200, 4500));
682         // add to the list
683         d->m_photoSizes.append(p);
684     }
685 
686     // load the photo sizes into the listbox
687     d->m_photoUi->ListPhotoSizes->blockSignals(true);
688     d->m_photoUi->ListPhotoSizes->clear();
689     QList<TPhotoSize*>::iterator it;
690 
691     for (it = d->m_photoSizes.begin(); it != d->m_photoSizes.end(); ++it)
692     {
693         TPhotoSize* const s = static_cast<TPhotoSize*>(*it);
694 
695         if (s)
696         {
697             QListWidgetItem* const pWItem = new QListWidgetItem(s->label);
698             pWItem->setIcon(s->icon);
699             d->m_photoUi->ListPhotoSizes->addItem(pWItem);
700         }
701     }
702 
703     // Adding custom choice
704     QListWidgetItem* const pWItem = new QListWidgetItem(i18n(customPageLayoutName));
705 
706     //TODO FREE STYLE ICON
707     TemplateIcon ti(80, pageSize.toSize());
708     ti.begin();
709     QPainter& painter = ti.getPainter();
710     painter.setPen(Qt::color1);
711     painter.drawText(painter.viewport(), Qt::AlignCenter, i18n("Custom layout"));
712     ti.end();
713 
714     pWItem->setIcon(ti.getIcon());
715     d->m_photoUi->ListPhotoSizes->addItem(pWItem);
716     d->m_photoUi->ListPhotoSizes->blockSignals(false);
717     d->m_photoUi->ListPhotoSizes->setCurrentRow(0, QItemSelectionModel::Select);
718 }
719 
getMaxDPI(const QList<TPhoto * > & photos,const QList<QRect * > & layouts,int current)720 double getMaxDPI(const QList<TPhoto*>& photos, const QList<QRect*>& layouts, /*unsigned*/ int current)
721 {
722     Q_ASSERT(layouts.count() > 1);
723 
724     QList<QRect*>::const_iterator it = layouts.begin();
725     QRect* layout                    = static_cast<QRect*>(*it);
726     double maxDPI                    = 0.0;
727 
728     for (; current < photos.count(); ++current)
729     {
730         TPhoto* const photo = photos.at(current);
731         double dpi          = ((double) photo->cropRegion.width() + (double) photo->cropRegion.height()) /
732                               (((double) layout->width() / 1000.0) + ((double) layout->height() / 1000.0));
733 
734         if (dpi > maxDPI)
735             maxDPI = dpi;
736 
737         // iterate to the next position
738         ++it;
739         layout = (it == layouts.end()) ? nullptr : static_cast<QRect*>(*it);
740 
741         if (layout == nullptr)
742         {
743             break;
744         }
745     }
746 
747     return maxDPI;
748 }
749 
getLayout(int photoIndex) const750 QRect* Wizard::getLayout(int photoIndex) const
751 {
752     TPhotoSize* const s = d->m_photoSizes.at(d->m_photoUi->ListPhotoSizes->currentRow());
753 
754     // how many photos would actually be printed, including copies?
755     int photoCount      = (photoIndex + 1);
756 
757     // how many pages?  Recall that the first layout item is the paper size
758     int photosPerPage   = s->layouts.count() - 1;
759     int remainder       = photoCount % photosPerPage;
760     int retVal          = remainder;
761 
762     if (remainder == 0)
763         retVal = photosPerPage;
764 
765     return s->layouts.at(retVal);
766 }
767 
getPageCount() const768 int Wizard::getPageCount() const
769 {
770     int pageCount   = 0;
771     int photoCount  =  d->m_photos.count();
772 
773     if (photoCount > 0)
774     {
775         // get the selected layout
776         TPhotoSize* const s = d->m_photoSizes.at(d->m_photoUi->ListPhotoSizes->currentRow());
777 
778         // how many pages?  Recall that the first layout item is the paper size
779         int photosPerPage   = s->layouts.count() - 1;
780         int remainder       = photoCount % photosPerPage;
781         int emptySlots      = 0;
782 
783         if (remainder > 0)
784             emptySlots = photosPerPage - remainder;
785 
786         pageCount = photoCount / photosPerPage;
787 
788         if (emptySlots > 0)
789             pageCount++;
790     }
791 
792     return pageCount;
793 }
794 
795 const float FONT_HEIGHT_RATIO = 0.8F;
796 
printCaption(QPainter & p,TPhoto * const photo,int captionW,int captionH,const QString & caption)797 void Wizard::printCaption(QPainter& p, TPhoto* const photo, int captionW, int captionH, const QString& caption)
798 {
799     // PENDING anaselli TPhoto*photo will be needed to add a per photo caption management
800     QStringList captionByLines;
801 
802     int captionIndex = 0;
803 
804     while (captionIndex < caption.length())
805     {
806         QString newLine;
807         bool breakLine            = false; // End Of Line found
808         int currIndex;                     //  Caption QString current index
809 
810         // Check minimal lines dimension
811         //TODO fix length, maybe useless
812         int captionLineLocalLength = 40;
813 
814         for (currIndex = captionIndex; currIndex < caption.length() && !breakLine; ++currIndex)
815         {
816             if (caption[currIndex] == QLatin1Char('\n') || caption[currIndex].isSpace())
817                 breakLine = true;
818         }
819 
820         if (captionLineLocalLength <= (currIndex - captionIndex))
821             captionLineLocalLength = (currIndex - captionIndex);
822 
823         breakLine = false;
824 
825         for (currIndex = captionIndex;
826              (currIndex <= captionIndex + captionLineLocalLength) && (currIndex < caption.length()) && !breakLine;
827              ++currIndex)
828         {
829             breakLine = (caption[currIndex] == QLatin1Char('\n')) ? true : false;
830 
831             if (breakLine)
832                 newLine.append(QLatin1Char(' '));
833             else
834                 newLine.append(caption[currIndex]);
835         }
836 
837         captionIndex = currIndex; // The line is ended
838 
839         if (captionIndex != caption.length())
840         {
841             while (!newLine.endsWith(QLatin1Char(' ')))
842             {
843                 newLine.truncate(newLine.length() - 1);
844                 captionIndex--;
845             }
846         }
847 
848         captionByLines.prepend(newLine.trimmed());
849     }
850 
851     QFont font(photo->pCaptionInfo->m_caption_font);
852     font.setStyleHint(QFont::SansSerif);
853     font.setPixelSize((int)(captionH * FONT_HEIGHT_RATIO));
854     font.setWeight(QFont::Normal);
855 
856     QFontMetrics fm(font);
857     int pixelsHigh = fm.height();
858 
859     p.setFont(font);
860     p.setPen(photo->pCaptionInfo->m_caption_color);
861     qCDebug(KIPIPLUGINS_LOG) << "Number of lines " << (int) captionByLines.count() ;
862 
863     // Now draw the caption
864     // TODO allow printing captions  per photo and on top, bottom and vertically
865     for (int lineNumber = 0; lineNumber < (int) captionByLines.count(); ++lineNumber)
866     {
867         if (lineNumber > 0)
868             p.translate(0, - (int)(pixelsHigh));
869 
870         QRect r(0, 0, captionW, captionH);
871         //TODO anaselli check if ok
872         p.drawText(r, Qt::AlignLeft, captionByLines[lineNumber], &r);
873     }
874 }
875 
captionFormatter(TPhoto * const photo) const876 QString Wizard::captionFormatter(TPhoto* const photo) const
877 {
878     if (!photo->pCaptionInfo)
879         return QString();
880 
881     QString format;
882 
883     switch (photo->pCaptionInfo->m_caption_type)
884     {
885         case CaptionInfo::FileNames:
886             format = QLatin1String("%f");
887             break;
888         case CaptionInfo::ExifDateTime:
889             format = QLatin1String("%d");
890             break;
891         case CaptionInfo::Comment:
892             format = QLatin1String("%c");
893             break;
894         case CaptionInfo::Free:
895             format =  photo->pCaptionInfo->m_caption_text;
896             break;
897         default:
898             qCWarning(KIPIPLUGINS_LOG) << "UNKNOWN caption type " << photo->pCaptionInfo->m_caption_type;
899             break;
900     }
901 
902     QFileInfo fi(photo->filename.toLocalFile());
903     QString resolution;
904     QSize imageSize;
905 
906     if (photo->metaIface())
907     {
908         imageSize = photo->metaIface()->getImageDimensions();
909     }
910 
911     if (imageSize.isValid())
912     {
913         resolution = QString::fromUtf8("%1x%2").arg(imageSize.width()).arg(imageSize.height());
914     }
915 
916     format.replace(QLatin1String("\\n"), QLatin1String("\n"));
917 
918     // %f filename
919     // %c comment
920     // %d date-time
921     // %t exposure time
922     // %i iso
923     // %r resolution
924     // %a aperture
925     // %l focal length
926 
927     KPImageInfo info(photo->filename);
928     format.replace(QString::fromUtf8("%r"), resolution);
929     format.replace(QString::fromUtf8("%f"), fi.fileName());
930     format.replace(QString::fromUtf8("%c"), info.description());
931     format.replace(QString::fromUtf8("%d"), QLocale().toString(info.date(), QLocale::ShortFormat));
932 
933     if (photo->metaIface())
934     {
935         format.replace(QString::fromUtf8("%t"), photo->metaIface()->getExifTagString(QLatin1String("Exif.Photo.ExposureTime")));
936         format.replace(QString::fromUtf8("%i"), photo->metaIface()->getExifTagString(QLatin1String("Exif.Photo.ISOSpeedRatings")));
937         format.replace(QString::fromUtf8("%a"), photo->metaIface()->getExifTagString(QLatin1String("Exif.Photo.FNumber")));
938         format.replace(QString::fromUtf8("%l"), photo->metaIface()->getExifTagString(QLatin1String("Exif.Photo.FocalLength")));
939     }
940     else
941     {
942         format.replace(QString::fromUtf8("%t"), QLatin1String(""));
943         format.replace(QString::fromUtf8("%i"), QLatin1String(""));
944         format.replace(QString::fromUtf8("%a"), QLatin1String(""));
945         format.replace(QString::fromUtf8("%l"), QLatin1String(""));
946     }
947 
948     return format;
949 }
950 
paintOnePage(QPainter & p,const QList<TPhoto * > & photos,const QList<QRect * > & layouts,int & current,bool cropDisabled,bool useThumbnails)951 bool Wizard::paintOnePage(QPainter& p, const QList<TPhoto*>& photos, const QList<QRect*>& layouts,
952                           int& current, bool cropDisabled, bool useThumbnails)
953 {
954     Q_ASSERT(layouts.count() > 1);
955 
956     if (photos.count() == 0)
957         return true;   // no photos => last photo
958 
959     QList<QRect*>::const_iterator it = layouts.begin();
960     QRect* const srcPage             = static_cast<QRect*>(*it);
961     ++it;
962     QRect* layout                    = static_cast<QRect*>(*it);
963 
964     // scale the page size to best fit the painter
965     // size the rectangle based on the minimum image dimension
966     int destW = p.window().width();
967     int destH = p.window().height();
968     int srcW  = srcPage->width();
969     int srcH  = srcPage->height();
970 
971     if (destW < destH)
972     {
973         destH = NINT((double) destW * ((double) srcH / (double) srcW));
974 
975         if (destH > p.window().height())
976         {
977             destH = p.window().height();
978             destW = NINT((double) destH * ((double) srcW / (double) srcH));
979         }
980     }
981     else
982     {
983         destW = NINT((double) destH * ((double) srcW / (double) srcH));
984 
985         if (destW > p.window().width())
986         {
987             destW = p.window().width();
988             destH = NINT((double) destW * ((double) srcH / (double) srcW));
989         }
990     }
991 
992     double xRatio = (double) destW / (double) srcPage->width();
993     double yRatio = (double) destH / (double) srcPage->height();
994     int left      = (p.window().width()  - destW) / 2;
995     int top       = (p.window().height() - destH) / 2;
996 
997     // FIXME: may not want to erase the background page
998     p.eraseRect(left, top,
999                 NINT((double) srcPage->width()  * xRatio),
1000                 NINT((double) srcPage->height() * yRatio));
1001 
1002     for (; current < photos.count(); ++current)
1003     {
1004         TPhoto* const photo = photos.at(current);
1005         // crop
1006         QImage img;
1007 
1008         if (useThumbnails)
1009             img = photo->thumbnail().toImage();
1010         else
1011             img = photo->loadPhoto();
1012 
1013         // next, do we rotate?
1014         if (photo->rotation != 0)
1015         {
1016             // rotate
1017             QMatrix matrix;
1018             matrix.rotate(photo->rotation);
1019             img = img.transformed(matrix);
1020         }
1021 
1022         if (useThumbnails)
1023         {
1024             // scale the crop region to thumbnail coords
1025             double xRatio = 0.0;
1026             double yRatio = 0.0;
1027 
1028             if (photo->thumbnail().width() != 0)
1029                 xRatio = (double) photo->thumbnail().width() / (double) photo->width();
1030 
1031             if (photo->thumbnail().height() != 0)
1032                 yRatio = (double) photo->thumbnail().height() / (double) photo->height();
1033 
1034             int x1 = NINT((double) photo->cropRegion.left() * xRatio);
1035             int y1 = NINT((double) photo->cropRegion.top()  * yRatio);
1036             int w  = NINT((double) photo->cropRegion.width()  * xRatio);
1037             int h  = NINT((double) photo->cropRegion.height() * yRatio);
1038             img    = img.copy(QRect(x1, y1, w, h));
1039         }
1040         else if (!cropDisabled)       //d->m_cropUi->m_disableCrop->isChecked() )
1041         {
1042             img = img.copy(photo->cropRegion);
1043         }
1044 
1045         int x1 = NINT((double) layout->left() * xRatio);
1046         int y1 = NINT((double) layout->top()  * yRatio);
1047         int w  = NINT((double) layout->width() * xRatio);
1048         int h  = NINT((double) layout->height() * yRatio);
1049 
1050         QRect rectViewPort    = p.viewport();
1051         QRect newRectViewPort = QRect(x1 + left, y1 + top, w, h);
1052         QSize imageSize       = img.size();
1053 
1054         //     qCDebug(KIPIPLUGINS_LOG) << "Image         " << photo->filename << " size " << imageSize;
1055         //     qCDebug(KIPIPLUGINS_LOG) << "viewport size " << newRectViewPort.size();
1056 
1057         QPoint point;
1058 
1059         if (cropDisabled)  //->m_cropPage->m_disableCrop->isChecked() )
1060         {
1061             imageSize.scale(newRectViewPort.size(), Qt::KeepAspectRatio);
1062             int spaceLeft = (newRectViewPort.width() - imageSize.width()) / 2;
1063             int spaceTop  = (newRectViewPort.height() - imageSize.height()) / 2;
1064             p.setViewport(spaceLeft + newRectViewPort.x(), spaceTop + newRectViewPort.y(), imageSize.width(), imageSize.height());
1065             point         = QPoint(newRectViewPort.x() + spaceLeft + imageSize.width(), newRectViewPort.y() + spaceTop + imageSize.height());
1066         }
1067         else
1068         {
1069             p.setViewport(newRectViewPort);
1070             point = QPoint(x1 + left + w, y1 + top + w);
1071         }
1072 
1073         QRect rectWindow = p.window();
1074         p.setWindow(img.rect());
1075         p.drawImage(0, 0, img);
1076         p.setViewport(rectViewPort);
1077         p.setWindow(rectWindow);
1078         p.setBrushOrigin(point);
1079 
1080         if (photo->pCaptionInfo && photo->pCaptionInfo->m_caption_type != CaptionInfo::NoCaptions)
1081         {
1082             p.save();
1083             QString caption;
1084             caption = captionFormatter(photo);
1085             qCDebug(KIPIPLUGINS_LOG) << "Caption " << caption ;
1086 
1087             // draw the text at (0,0), but we will translate and rotate the world
1088             // before drawing so the text will be in the correct location
1089             // next, do we rotate?
1090             int captionW        = w - 2;
1091             double ratio        = photo->pCaptionInfo->m_caption_size * 0.01;
1092             int captionH        = (int)(qMin(w, h) * ratio);
1093             int exifOrientation = MetadataProcessor::NORMAL;
1094             int orientatation   = photo->rotation;
1095 
1096             if (photo->metaIface())
1097             {
1098                 exifOrientation = photo->metaIface()->getImageOrientation();
1099             }
1100 
1101             // ROT_90_HFLIP .. ROT_270
1102 
1103             if (exifOrientation == MetadataProcessor::ROT_90_HFLIP ||
1104                 exifOrientation == MetadataProcessor::ROT_90       ||
1105                 exifOrientation == MetadataProcessor::ROT_90_VFLIP ||
1106                 exifOrientation == MetadataProcessor::ROT_270)
1107             {
1108                 orientatation = (photo->rotation + 270) % 360;   // -90 degrees
1109             }
1110 
1111             if (orientatation == 90 || orientatation == 270)
1112             {
1113                 captionW = h;
1114             }
1115 
1116             p.rotate(orientatation);
1117             qCDebug(KIPIPLUGINS_LOG) << "rotation " << photo->rotation << " orientation " << orientatation ;
1118             int tx = left;
1119             int ty = top;
1120 
1121             switch (orientatation)
1122             {
1123                 case 0 :
1124                 {
1125                     tx += x1 + 1;
1126                     ty += y1 + (h - captionH - 1);
1127                     break;
1128                 }
1129                 case 90 :
1130                 {
1131                     tx = top + y1 + 1;
1132                     ty = -left - x1 - captionH - 1;
1133                     break;
1134                 }
1135                 case 180 :
1136                 {
1137                     tx = -left - x1 - w + 1;
1138                     ty = -top - y1 - (captionH + 1);
1139                     break;
1140                 }
1141                 case 270 :
1142                 {
1143                     tx = -top - y1 - h + 1;
1144                     ty = left + x1 + (w - captionH) - 1;
1145                     break;
1146                 }
1147             }
1148             p.translate(tx, ty);
1149             printCaption(p, photo, captionW, captionH, caption);
1150             p.restore();
1151         } // caption
1152 
1153         // iterate to the next position
1154         ++it;
1155         layout = it == layouts.end() ? nullptr : static_cast<QRect*>(*it);
1156 
1157         if (layout == nullptr)
1158         {
1159             current++;
1160             break;
1161         }
1162     }
1163 
1164     // did we print the last photo?
1165     return (current < photos.count());
1166 }
1167 
updateCropFrame(TPhoto * const photo,int photoIndex)1168 void Wizard::updateCropFrame(TPhoto* const photo, int photoIndex)
1169 {
1170     TPhotoSize* const s = d->m_photoSizes.at(d->m_photoUi->ListPhotoSizes->currentRow());
1171     d->m_cropUi->cropFrame->init(photo, getLayout(photoIndex)->width(), getLayout(photoIndex)->height(), s->autoRotate);
1172     d->m_cropUi->LblCropPhoto->setText(i18n("Photo %1 of %2", photoIndex + 1, QString::number(d->m_photos.count())));
1173 }
1174 
1175 // update the pages to be printed and preview first/last pages
previewPhotos()1176 void Wizard::previewPhotos()
1177 {
1178     //Change cursor to waitCursor during transition
1179     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1180 
1181     // get the selected layout
1182     int curr            = d->m_photoUi->ListPhotoSizes->currentRow();
1183     TPhotoSize* const s = d->m_photoSizes.at(curr);
1184     int photoCount      =  d->m_photos.count();
1185     int emptySlots      = 0;
1186     int pageCount       = 0;
1187     int photosPerPage   = 0;
1188 
1189     if (photoCount > 0)
1190     {
1191         // how many pages?  Recall that the first layout item is the paper size
1192         photosPerPage = s->layouts.count() - 1;
1193         int remainder = photoCount % photosPerPage;
1194 
1195         if (remainder > 0)
1196             emptySlots = photosPerPage - remainder;
1197 
1198         pageCount     = photoCount / photosPerPage;
1199 
1200         if (emptySlots > 0)
1201             pageCount++;
1202     }
1203 
1204     d->m_photoUi->LblPhotoCount->setText(QString::number(photoCount));
1205     d->m_photoUi->LblSheetsPrinted->setText(QString::number(pageCount));
1206     d->m_photoUi->LblEmptySlots->setText(QString::number(emptySlots));
1207 
1208     // photo previews
1209     // preview the first page.
1210     // find the first page of photos
1211     int count   = 0;
1212     int page    = 0;
1213     int current = 0;
1214     QList<TPhoto*>::iterator it;
1215 
1216     for (it = d->m_photos.begin(); it != d->m_photos.end(); ++it)
1217     {
1218         TPhoto* const photo = static_cast<TPhoto*>(*it);
1219 
1220         if (page == d->m_currentPreviewPage)
1221         {
1222             photo->cropRegion.setRect(-1, -1, -1, -1);
1223             photo->rotation = 0;
1224             int w = s->layouts.at(count + 1)->width();
1225             int h = s->layouts.at(count + 1)->height();
1226             d->m_cropUi->cropFrame->init(photo, w, h, s->autoRotate, false);
1227         }
1228 
1229         count++;
1230 
1231         if (count >= photosPerPage)
1232         {
1233             if (page == d->m_currentPreviewPage)
1234                 break;
1235 
1236             page++;
1237             current += photosPerPage;
1238             count    = 0;
1239         }
1240     }
1241 
1242     // send this photo list to the painter
1243     if (photoCount > 0)
1244     {
1245         QImage img(d->m_photoUi->BmpFirstPagePreview->size(), QImage::Format_ARGB32_Premultiplied);
1246         QPainter p(&img);
1247         p.setCompositionMode(QPainter::CompositionMode_Clear);
1248         //p.setCompositionMode(QPainter::CompositionMode_Destination );
1249         p.fillRect(img.rect(), Qt::color0); //Qt::transparent );
1250         p.setCompositionMode(QPainter::CompositionMode_SourceOver);
1251         paintOnePage(p, d->m_photos, s->layouts, current, d->m_cropUi->m_disableCrop->isChecked(), true);
1252         p.end();
1253 
1254         d->m_photoUi->BmpFirstPagePreview->clear();
1255         d->m_photoUi->BmpFirstPagePreview->setPixmap(QPixmap::fromImage(img));
1256         d->m_photoUi->LblPreview->setText(i18n("Page %1 of %2", d->m_currentPreviewPage + 1, getPageCount()));
1257     }
1258     else
1259     {
1260         d->m_photoUi->BmpFirstPagePreview->clear();
1261         d->m_photoUi->LblPreview->clear();
1262 //       d->m_photoUi->BmpFirstPagePreview->setPixmap ( QPixmap() );
1263         d->m_photoUi->LblPreview->setText(i18n("Page %1 of %2", 0, 0));
1264     }
1265 
1266     manageBtnPreviewPage();
1267     d->m_photoUi->update();
1268     QApplication::restoreOverrideCursor();
1269 }
1270 
manageBtnPreviewPage()1271 void Wizard::manageBtnPreviewPage()
1272 {
1273     if (d->m_photos.empty())
1274     {
1275         d->m_photoUi->BtnPreviewPageDown->setEnabled(false);
1276         d->m_photoUi->BtnPreviewPageUp->setEnabled(false);
1277     }
1278     else
1279     {
1280         d->m_photoUi->BtnPreviewPageDown->setEnabled(true);
1281         d->m_photoUi->BtnPreviewPageUp->setEnabled(true);
1282 
1283         if (d->m_currentPreviewPage == 0)
1284         {
1285             d->m_photoUi->BtnPreviewPageDown->setEnabled(false);
1286         }
1287 
1288         if ((d->m_currentPreviewPage + 1) == getPageCount())
1289         {
1290             d->m_photoUi->BtnPreviewPageUp->setEnabled(false);
1291         }
1292     }
1293 }
1294 
infopage_setCaptionButtons()1295 void Wizard::infopage_setCaptionButtons()
1296 {
1297     if (d->m_photos.size())
1298     {
1299         TPhoto* const pPhoto = d->m_photos.at(d->m_infopageCurrentPhoto);
1300 
1301         if (pPhoto && !d->m_photoUi->m_sameCaption->isChecked())
1302         {
1303             infopage_blockCaptionButtons();
1304 
1305             if (pPhoto->pCaptionInfo)
1306             {
1307                 d->m_photoUi->m_font_color->setColor(pPhoto->pCaptionInfo->m_caption_color);
1308                 d->m_photoUi->m_font_size->setValue(pPhoto->pCaptionInfo->m_caption_size);
1309                 d->m_photoUi->m_font_name->setCurrentFont(pPhoto->pCaptionInfo->m_caption_font);
1310                 d->m_photoUi->m_captions->setCurrentIndex(int(pPhoto->pCaptionInfo->m_caption_type));
1311                 d->m_photoUi->m_FreeCaptionFormat->setText(pPhoto->pCaptionInfo->m_caption_text);
1312                 enableCaptionGroup(d->m_photoUi->m_captions->currentText());
1313             }
1314             else
1315             {
1316                 infopage_readCaptionSettings();
1317                 captionChanged(d->m_photoUi->m_captions->currentText());
1318             }
1319 
1320             infopage_blockCaptionButtons(false);
1321         }
1322     }
1323 }
1324 
slotXMLCustomElement(QXmlStreamWriter & xmlWriter)1325 void Wizard::slotXMLCustomElement(QXmlStreamWriter& xmlWriter)
1326 {
1327     qCDebug(KIPIPLUGINS_LOG) << " invoked " ;
1328     xmlWriter.writeStartElement(QLatin1String("pa_layout"));
1329     xmlWriter.writeAttribute(QLatin1String("Printer"),   d->m_photoUi->m_printer_choice->currentText());
1330     xmlWriter.writeAttribute(QLatin1String("PageSize"),  QString::fromUtf8("%1").arg(d->m_printer->paperSize()));
1331     xmlWriter.writeAttribute(QLatin1String("PhotoSize"), d->m_photoUi->ListPhotoSizes->currentItem()->text());
1332     xmlWriter.writeEndElement(); // pa_layout
1333 }
1334 
slotXMLSaveItem(QXmlStreamWriter & xmlWriter,KIPIPlugins::KPImagesListViewItem * item)1335 void Wizard::slotXMLSaveItem(QXmlStreamWriter& xmlWriter, KIPIPlugins::KPImagesListViewItem* item)
1336 {
1337     if (d->m_photos.size())
1338     {
1339         int itemIndex        = d->m_imagesFilesListBox->listView()->indexFromItem(item).row();
1340         TPhoto* const pPhoto = d->m_photos[itemIndex];
1341         // TODO anaselli: first and copies could be removed since they are not useful any more
1342         xmlWriter.writeAttribute(QLatin1String("first"),  QString::fromUtf8("%1").arg(pPhoto->first));
1343         xmlWriter.writeAttribute(QLatin1String("copies"), QString::fromUtf8("%1").arg(pPhoto->first ? pPhoto->copies : 0));
1344 
1345         // additional info (caption... etc)
1346         if (pPhoto->pCaptionInfo)
1347         {
1348             xmlWriter.writeStartElement(QLatin1String("pa_caption"));
1349             xmlWriter.writeAttribute(QLatin1String("type"),  QString::fromUtf8("%1").arg(pPhoto->pCaptionInfo->m_caption_type));
1350             xmlWriter.writeAttribute(QLatin1String("font"),  pPhoto->pCaptionInfo->m_caption_font.toString());
1351             xmlWriter.writeAttribute(QLatin1String("size"),  QString::fromUtf8("%1").arg(pPhoto->pCaptionInfo->m_caption_size));
1352             xmlWriter.writeAttribute(QLatin1String("color"), pPhoto->pCaptionInfo->m_caption_color.name());
1353             xmlWriter.writeAttribute(QLatin1String("text"),  pPhoto->pCaptionInfo->m_caption_text);
1354             xmlWriter.writeEndElement(); // pa_caption
1355         }
1356     }
1357 }
1358 
slotXMLCustomElement(QXmlStreamReader & xmlReader)1359 void Wizard::slotXMLCustomElement(QXmlStreamReader& xmlReader)
1360 {
1361     qCDebug(KIPIPLUGINS_LOG) << " invoked " << xmlReader.name();
1362 
1363     while (!xmlReader.atEnd())
1364     {
1365         if (xmlReader.isStartElement() && xmlReader.name() == QLatin1String("pa_layout"))
1366         {
1367             bool ok;
1368             QXmlStreamAttributes attrs = xmlReader.attributes();
1369             // get value of each attribute from QXmlStreamAttributes
1370             QStringRef attr = attrs.value(QLatin1String("Printer"));
1371 
1372             if (!attr.isEmpty())
1373             {
1374                 qCDebug(KIPIPLUGINS_LOG) <<  " found " << attr.toString();
1375                 int index = d->m_photoUi->m_printer_choice->findText(attr.toString());
1376 
1377                 if (index != -1)
1378                 {
1379                     d->m_photoUi->m_printer_choice->setCurrentIndex(index);
1380                 }
1381 
1382                 outputChanged(d->m_photoUi->m_printer_choice->currentText());
1383             }
1384 
1385             attr = attrs.value(QLatin1String("PageSize"));
1386 
1387             if (!attr.isEmpty())
1388             {
1389                 qCDebug(KIPIPLUGINS_LOG) <<  " found " << attr.toString();
1390                 QPrinter::PaperSize paperSize = (QPrinter::PaperSize)attr.toString().toInt(&ok);
1391                 d->m_printer->setPaperSize(paperSize);
1392             }
1393 
1394             attr = attrs.value(QLatin1String("PhotoSize"));
1395 
1396             if (!attr.isEmpty())
1397             {
1398                 qCDebug(KIPIPLUGINS_LOG) <<  " found " << attr.toString();
1399                 d->m_savedPhotoSize = attr.toString();
1400             }
1401         }
1402 
1403         xmlReader.readNext();
1404     }
1405 
1406     // reset preview page number
1407     d->m_currentPreviewPage      = 0;
1408     initPhotoSizes(d->m_printer->paperSize(QPrinter::Millimeter));
1409     QList<QListWidgetItem*> list = d->m_photoUi->ListPhotoSizes->findItems(d->m_savedPhotoSize, Qt::MatchExactly);
1410 
1411     if (list.count())
1412     {
1413         qCDebug(KIPIPLUGINS_LOG) << " PhotoSize " << list[0]->text();
1414         d->m_photoUi->ListPhotoSizes->setCurrentItem(list[0]);
1415     }
1416     else
1417     {
1418         d->m_photoUi->ListPhotoSizes->setCurrentRow(0);
1419     }
1420 
1421     previewPhotos();
1422 }
1423 
slotXMLLoadElement(QXmlStreamReader & xmlReader)1424 void Wizard::slotXMLLoadElement(QXmlStreamReader& xmlReader)
1425 {
1426     if (d->m_photos.size())
1427     {
1428         // read image is the last.
1429         TPhoto* const pPhoto = d->m_photos[d->m_photos.size()-1];
1430         qCDebug(KIPIPLUGINS_LOG) << " invoked " << xmlReader.name();
1431 
1432         while (xmlReader.readNextStartElement())
1433         {
1434             qCDebug(KIPIPLUGINS_LOG) << pPhoto->filename << " " << xmlReader.name();
1435 
1436             if (xmlReader.name() == QLatin1String("pa_caption"))
1437             {
1438                 d->m_photoUi->m_sameCaption->blockSignals(true);
1439                 d->m_photoUi->m_sameCaption->setCheckState( Qt::Unchecked );
1440                 d->m_photoUi->m_sameCaption->blockSignals(false);
1441 
1442                 //useless this item has been added now
1443                 if (pPhoto->pCaptionInfo)
1444                     delete pPhoto->pCaptionInfo;
1445 
1446                 pPhoto->pCaptionInfo = new CaptionInfo();
1447                 // get all attributes and its value of a tag in attrs variable.
1448                 QXmlStreamAttributes attrs = xmlReader.attributes();
1449                 // get value of each attribute from QXmlStreamAttributes
1450                 QStringRef attr = attrs.value(QLatin1String("type"));
1451                 bool ok;
1452 
1453                 if (!attr.isEmpty())
1454                 {
1455                     qCDebug(KIPIPLUGINS_LOG) <<  " found " << attr.toString();
1456                     pPhoto->pCaptionInfo->m_caption_type = (CaptionInfo::AvailableCaptions)attr.toString().toInt(&ok);
1457                 }
1458 
1459                 attr = attrs.value(QLatin1String("font"));
1460 
1461                 if (!attr.isEmpty())
1462                 {
1463                     qCDebug(KIPIPLUGINS_LOG) <<  " found " << attr.toString();
1464                     pPhoto->pCaptionInfo->m_caption_font.fromString(attr.toString());
1465                 }
1466 
1467                 attr = attrs.value(QLatin1String("color"));
1468 
1469                 if (!attr.isEmpty())
1470                 {
1471                     qCDebug(KIPIPLUGINS_LOG) <<  " found " << attr.toString();
1472                     pPhoto->pCaptionInfo->m_caption_color.setNamedColor(attr.toString());
1473                 }
1474 
1475                 attr = attrs.value(QLatin1String("size"));
1476 
1477                 if (!attr.isEmpty())
1478                 {
1479                     qCDebug(KIPIPLUGINS_LOG) <<  " found " << attr.toString();
1480                     pPhoto->pCaptionInfo->m_caption_size = attr.toString().toInt(&ok);
1481                 }
1482 
1483                 attr = attrs.value(QLatin1String("text"));
1484 
1485                 if (!attr.isEmpty())
1486                 {
1487                     qCDebug(KIPIPLUGINS_LOG) <<  " found " << attr.toString();
1488                     pPhoto->pCaptionInfo->m_caption_text = attr.toString();
1489                 }
1490 
1491                 infopage_setCaptionButtons();
1492             }
1493         }
1494     }
1495 }
1496 
slotContextMenuRequested()1497 void Wizard::slotContextMenuRequested()
1498 {
1499     if (d->m_photos.size())
1500     {
1501         int itemIndex         = d->m_imagesFilesListBox->listView()->currentIndex().row();
1502         d->m_imagesFilesListBox->listView()->blockSignals(true);
1503         QMenu menu(d->m_imagesFilesListBox->listView());
1504         QAction* const action = menu.addAction(i18n("Add again"));
1505 
1506         connect(action, SIGNAL(triggered()),
1507                 this , SLOT(increaseCopies()));
1508 
1509         TPhoto* const pPhoto  = d->m_photos[itemIndex];
1510         qCDebug(KIPIPLUGINS_LOG) << " copies " << pPhoto->copies << " first " << pPhoto->first;
1511 
1512         if (pPhoto->copies > 1 || !pPhoto->first)
1513         {
1514             QAction* const actionr = menu.addAction(i18n("Remove"));
1515 
1516             connect(actionr, SIGNAL(triggered()),
1517                     this, SLOT(decreaseCopies()));
1518         }
1519 
1520         menu.exec(QCursor::pos());
1521         d->m_imagesFilesListBox->listView()->blockSignals(false);
1522     }
1523 }
1524 
imageSelected(QTreeWidgetItem * item)1525 void Wizard::imageSelected(QTreeWidgetItem* item)
1526 {
1527     KPImagesListViewItem* const l_item = dynamic_cast<KPImagesListViewItem*>(item);
1528 
1529     if (!l_item)
1530         return;
1531 
1532     int itemIndex                      = d->m_imagesFilesListBox->listView()->indexFromItem(l_item).row();
1533 
1534     qCDebug(KIPIPLUGINS_LOG) << " current row now is " << itemIndex;
1535     d->m_infopageCurrentPhoto = itemIndex;
1536 
1537     infopage_setCaptionButtons();
1538 }
1539 
decreaseCopies()1540 void Wizard::decreaseCopies()
1541 {
1542     if (d->m_photos.size())
1543     {
1544         KPImagesListViewItem* const item = dynamic_cast<KPImagesListViewItem* >(d->m_imagesFilesListBox->listView()->currentItem());
1545 
1546         if (!item)
1547             return;
1548 
1549         qCDebug(KIPIPLUGINS_LOG) << " Removing a copy of " << item->url();
1550         d->m_imagesFilesListBox->slotRemoveItems();
1551     }
1552 }
1553 
slotRemovingItem(KIPIPlugins::KPImagesListViewItem * item)1554 void Wizard::slotRemovingItem(KIPIPlugins::KPImagesListViewItem* item)
1555 {
1556     if (item)
1557     {
1558         int itemIndex = d->m_imagesFilesListBox->listView()->indexFromItem(item).row();
1559 
1560         if (d->m_photos.size() && itemIndex >= 0)
1561         {
1562             /// Debug data: found and copies
1563             bool found = false;
1564             int copies = 0;
1565 
1566             d->m_imagesFilesListBox->blockSignals(true);
1567             TPhoto* const pPhotoToRemove = d->m_photos.at(itemIndex);
1568 
1569             // photo to be removed could be:
1570             // 1) unique => just remove it
1571             // 2) first of n, =>
1572             //    search another with the same url
1573             //    and set it a first and with a count to n-1 then remove it
1574             // 3) one of n, search the first one and set count to n-1 then remove it
1575             if (pPhotoToRemove && pPhotoToRemove->first)
1576             {
1577                 if (pPhotoToRemove->copies > 0)
1578                 {
1579                     for (int i = 0; i < d->m_photos.count() && !found; ++i)
1580                     {
1581                         TPhoto* const pCurrentPhoto = d->m_photos.at(i);
1582 
1583                         if (pCurrentPhoto && pCurrentPhoto->filename == pPhotoToRemove->filename)
1584                         {
1585                             pCurrentPhoto->copies = pPhotoToRemove->copies - 1;
1586                             copies                = pCurrentPhoto->copies;
1587                             pCurrentPhoto->first  = true;
1588                             found                 = true;
1589                         }
1590                     }
1591                 }
1592                 // otherwise it's unique
1593             }
1594             else if (pPhotoToRemove)
1595             {
1596                 for (int i = 0; i < d->m_photos.count() && !found; ++i)
1597                 {
1598                     TPhoto* const pCurrentPhoto = d->m_photos.at(i);
1599 
1600                     if (pCurrentPhoto && pCurrentPhoto->filename == pPhotoToRemove->filename && pCurrentPhoto->first)
1601                     {
1602                         pCurrentPhoto->copies--;
1603                         copies = pCurrentPhoto->copies;
1604                         found  = true;
1605                     }
1606                 }
1607             }
1608             else
1609             {
1610                 qCDebug(KIPIPLUGINS_LOG) << " NULL TPhoto object ";
1611                 return;
1612             }
1613 
1614             if (pPhotoToRemove)
1615             {
1616                 qCDebug(KIPIPLUGINS_LOG) << "Removed fileName: " << pPhotoToRemove->filename.fileName() << " copy number " << copies;
1617             }
1618 
1619             d->m_photos.removeAt(itemIndex);
1620             delete pPhotoToRemove;
1621 
1622             d->m_imagesFilesListBox->blockSignals(false);
1623             previewPhotos();
1624         }
1625 
1626         if (d->m_photos.empty())
1627         {
1628             // No photos => disabling next button (e.g. crop page)
1629             d->m_photoPage->setComplete(false);
1630         }
1631     }
1632 }
1633 
slotAddItems(const QList<QUrl> & list)1634 void Wizard::slotAddItems(const QList<QUrl>& list)
1635 {
1636     if (list.count() == 0)
1637     {
1638         return;
1639     }
1640 
1641     QList<QUrl> urls;
1642     d->m_imagesFilesListBox->blockSignals(true);
1643 
1644     for (QList<QUrl>::ConstIterator it = list.constBegin(); it != list.constEnd(); ++it)
1645     {
1646         QUrl imageUrl = *it;
1647 
1648         // Check if the new item already exist in the list.
1649         bool found = false;
1650 
1651         for (int i = 0; i < d->m_photos.count() && !found; ++i)
1652         {
1653             TPhoto* const pCurrentPhoto = d->m_photos.at(i);
1654 
1655             if (pCurrentPhoto && pCurrentPhoto->filename == imageUrl && pCurrentPhoto->first)
1656             {
1657                 pCurrentPhoto->copies++;
1658                 found                = true;
1659                 TPhoto* const pPhoto = new TPhoto(*pCurrentPhoto);
1660                 pPhoto->first        = false;
1661                 d->m_photos.append(pPhoto);
1662                 qCDebug(KIPIPLUGINS_LOG) << "Added fileName: " << pPhoto->filename.fileName() << " copy number " << pCurrentPhoto->copies;
1663             }
1664         }
1665 
1666         if (!found)
1667         {
1668             TPhoto* const pPhoto = new TPhoto(150);
1669             pPhoto->filename     = *it;
1670             pPhoto->first        = true;
1671             d->m_photos.append(pPhoto);
1672             qCDebug(KIPIPLUGINS_LOG) << "Added new fileName: " << pPhoto->filename.fileName();
1673         }
1674     }
1675 
1676     d->m_imagesFilesListBox->blockSignals(false);
1677     infopage_updateCaptions();
1678     //previewPhotos();
1679 
1680     if (d->m_photos.size())
1681     {
1682         d->m_photoPage->setComplete(true);
1683     }
1684 }
1685 
increaseCopies()1686 void Wizard::increaseCopies()
1687 {
1688     if (d->m_photos.size())
1689     {
1690         QList<QUrl> list;
1691         KPImagesListViewItem* const item = dynamic_cast<KPImagesListViewItem* >(d->m_imagesFilesListBox->listView()->currentItem());
1692 
1693         if (!item)
1694             return;
1695 
1696         list.append(item->url());
1697         qCDebug(KIPIPLUGINS_LOG) << " Adding a copy of " << item->url();
1698         d->m_imagesFilesListBox->slotAddImages(list);
1699     }
1700 }
1701 
pageChanged(int curr)1702 void Wizard::pageChanged(int curr)
1703 {
1704     QWizardPage* const current = page(curr);
1705 
1706     if (!current) return;
1707 
1708     QWizardPage* const before  = visitedPages().isEmpty() ? nullptr : page(visitedPages().last());
1709 
1710     //Change cursor to waitCursor during transition
1711     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1712 
1713     if (before)
1714     {
1715         saveSettings(before->title());
1716         qCDebug(KIPIPLUGINS_LOG) << " before " << before->title();
1717     }
1718 
1719     qCDebug(KIPIPLUGINS_LOG) << " current " << current->title();
1720 
1721     if (current->title() == i18n(photoPageName))
1722     {
1723         // readSettings only the first time
1724         if (!before)
1725             readSettings(current->title());
1726 
1727         // set to first photo
1728         d->m_infopageCurrentPhoto = 0;
1729         d->m_imagesFilesListBox->listView()->clear();
1730         QList<QUrl> list;
1731 
1732         for (int i = 0; i < d->m_photos.count();++i)
1733         {
1734             TPhoto* const pCurrentPhoto = d->m_photos.at(i);
1735 
1736             if (pCurrentPhoto)
1737             {
1738                 list.push_back(pCurrentPhoto->filename);
1739             }
1740         }
1741 
1742         d->m_imagesFilesListBox->blockSignals(true);
1743         d->m_imagesFilesListBox->slotAddImages(list);
1744         d->m_imagesFilesListBox->listView()->setCurrentItem(d->m_imagesFilesListBox->listView()->itemAt(0, 0));
1745         d->m_imagesFilesListBox->blockSignals(false);
1746         d->m_photoUi->LblPhotoCount->setText(QString::number(d->m_photos.count()));
1747 
1748         // PhotoPage
1749         initPhotoSizes(d->m_printer->paperSize(QPrinter::Millimeter));
1750         // restore photoSize
1751 
1752         if (before && d->m_savedPhotoSize == i18n(customPageLayoutName))
1753         {
1754             d->m_photoUi->ListPhotoSizes->setCurrentRow(0);
1755         }
1756         else
1757         {
1758             QList<QListWidgetItem*> list = d->m_photoUi->ListPhotoSizes->findItems(d->m_savedPhotoSize, Qt::MatchExactly);
1759 
1760             if (list.count())
1761                 d->m_photoUi->ListPhotoSizes->setCurrentItem(list[0]);
1762             else
1763                 d->m_photoUi->ListPhotoSizes->setCurrentRow(0);
1764         }
1765 
1766         // update captions only the first time to avoid missing old changes when
1767         // back to this page
1768         if (!before)
1769             infopage_updateCaptions();
1770 
1771         // reset preview page number
1772         d->m_currentPreviewPage = 0;
1773         // create our photo sizes list
1774         previewPhotos();
1775     }
1776     else if (current->title() == i18n(cropPageName))
1777     {
1778         readSettings(current->title());
1779         d->m_currentCropPhoto = 0;
1780 
1781         if (d->m_photos.size())
1782         {
1783             TPhoto* const photo = d->m_photos[d->m_currentCropPhoto];
1784             setBtnCropEnabled();
1785             this->update();
1786             updateCropFrame(photo, d->m_currentCropPhoto);
1787         }
1788         else
1789         {
1790             // NOTE it should not pass here
1791             qCDebug(KIPIPLUGINS_LOG) << "Not any photos selected cropping is disabled";
1792         }
1793     }
1794 
1795     QApplication::restoreOverrideCursor();
1796 }
1797 
outputChanged(const QString & text)1798 void Wizard::outputChanged(const QString& text)
1799 {
1800     if (text == i18n("Print to PDF") ||
1801         text == i18n("Print to JPG") ||
1802         text == i18n("Print to gimp"))
1803     {
1804         delete d->m_printer;
1805 
1806         d->m_printer = new QPrinter();
1807         d->m_printer->setOutputFormat(QPrinter::PdfFormat);
1808     }
1809     else // real printer
1810     {
1811         QList<QPrinterInfo>::iterator it;
1812         //m_printerList = QPrinterInfo::availablePrinters ();
1813 
1814         for (it = d->m_printerList.begin(); it != d->m_printerList.end(); ++it)
1815         {
1816             if (it->printerName() == text)
1817             {
1818                 qCDebug(KIPIPLUGINS_LOG) << "Chosen printer: " << it->printerName();
1819                 delete d->m_printer;
1820                 d->m_printer = new QPrinter(*it);
1821             }
1822         }
1823 
1824         //d->m_printer->setPrinterName(text);
1825         d->m_printer->setOutputFormat(QPrinter::NativeFormat);
1826     }
1827 
1828     //default no margins
1829     d->m_printer->setFullPage(true);
1830     d->m_printer->setPageMargins(0, 0, 0, 0, QPrinter::Millimeter);
1831 }
1832 
updateCaption(TPhoto * pPhoto)1833 void Wizard::updateCaption(TPhoto* pPhoto)
1834 {
1835     if (pPhoto)
1836     {
1837         if (!pPhoto->pCaptionInfo && d->m_photoUi->m_captions->currentIndex() != CaptionInfo::NoCaptions)
1838         {
1839             pPhoto->pCaptionInfo = new CaptionInfo();
1840         }
1841         else if (pPhoto->pCaptionInfo && d->m_photoUi->m_captions->currentIndex() == CaptionInfo::NoCaptions)
1842         {
1843             delete pPhoto->pCaptionInfo;
1844             pPhoto->pCaptionInfo = nullptr;
1845         }
1846 
1847         if (pPhoto->pCaptionInfo)
1848         {
1849             pPhoto->pCaptionInfo->m_caption_color = d->m_photoUi->m_font_color->color();
1850             pPhoto->pCaptionInfo->m_caption_size  = d->m_photoUi->m_font_size->value();
1851             pPhoto->pCaptionInfo->m_caption_font  = d->m_photoUi->m_font_name->currentFont();
1852             pPhoto->pCaptionInfo->m_caption_type  = (CaptionInfo::AvailableCaptions)d->m_photoUi->m_captions->currentIndex();
1853             pPhoto->pCaptionInfo->m_caption_text  = d->m_photoUi->m_FreeCaptionFormat->text();
1854         }
1855     }
1856 }
1857 
infopage_updateCaptions()1858 void Wizard::infopage_updateCaptions()
1859 {
1860     if (d->m_photos.size())
1861     {
1862         if (d->m_photoUi->m_sameCaption->isChecked())
1863         {
1864             QList<TPhoto*>::iterator it;
1865 
1866             for (it = d->m_photos.begin(); it != d->m_photos.end(); ++it)
1867             {
1868                 TPhoto* const pPhoto = static_cast<TPhoto*>(*it);
1869                 updateCaption(pPhoto);
1870             }
1871         }
1872         else
1873         {
1874             QList <QTreeWidgetItem*> list =  d->m_imagesFilesListBox->listView()->selectedItems();
1875 
1876             foreach(QTreeWidgetItem* const item, list)
1877             {
1878                 KPImagesListViewItem* const lvItem = dynamic_cast<KPImagesListViewItem*>(item);
1879 
1880                 if (item)
1881                 {
1882                     int itemIndex        = d->m_imagesFilesListBox->listView()->indexFromItem(lvItem).row();
1883                     TPhoto* const pPhoto = d->m_photos.at(itemIndex);
1884                     updateCaption(pPhoto);
1885                 }
1886             }
1887         }
1888     }
1889 
1890     // create our photo sizes list
1891     previewPhotos();
1892 }
1893 
enableCaptionGroup(const QString & text)1894 void Wizard::enableCaptionGroup(const QString& text)
1895 {
1896     bool fontSettingsEnabled;
1897 
1898     if (text == i18n("No captions"))
1899     {
1900         fontSettingsEnabled = false;
1901         d->m_photoUi->m_FreeCaptionFormat->setEnabled(false);
1902         d->m_photoUi->m_free_label->setEnabled(false);
1903     }
1904     else if (text == i18n("Free"))
1905     {
1906         fontSettingsEnabled = true;
1907         d->m_photoUi->m_FreeCaptionFormat->setEnabled(true);
1908         d->m_photoUi->m_free_label->setEnabled(true);
1909     }
1910     else
1911     {
1912         fontSettingsEnabled = true;
1913         d->m_photoUi->m_FreeCaptionFormat->setEnabled(false);
1914         d->m_photoUi->m_free_label->setEnabled(false);
1915     }
1916 
1917     d->m_photoUi->m_font_name->setEnabled(fontSettingsEnabled);
1918     d->m_photoUi->m_font_size->setEnabled(fontSettingsEnabled);
1919     d->m_photoUi->m_font_color->setEnabled(fontSettingsEnabled);
1920 }
1921 
captionChanged(const QString & text)1922 void Wizard::captionChanged(const QString& text)
1923 {
1924     enableCaptionGroup(text);
1925     infopage_updateCaptions();
1926 }
1927 
BtnCropRotateLeft_clicked()1928 void Wizard::BtnCropRotateLeft_clicked()
1929 {
1930     // by definition, the cropRegion should be set by now,
1931     // which means that after our rotation it will become invalid,
1932     // so we will initialize it to -2 in an awful hack (this
1933     // tells the cropFrame to reset the crop region, but don't
1934     // automagically rotate the image to fit.
1935     TPhoto* const photo = d->m_photos[d->m_currentCropPhoto];
1936     photo->cropRegion   = QRect(-2, -2, -2, -2);
1937     photo->rotation     = (photo->rotation - 90) % 360;
1938 
1939     updateCropFrame(photo, d->m_currentCropPhoto);
1940 }
1941 
BtnCropRotateRight_clicked()1942 void Wizard::BtnCropRotateRight_clicked()
1943 {
1944     // by definition, the cropRegion should be set by now,
1945     // which means that after our rotation it will become invalid,
1946     // so we will initialize it to -2 in an awful hack (this
1947     // tells the cropFrame to reset the crop region, but don't
1948     // automagically rotate the image to fit.
1949     TPhoto* const photo = d->m_photos[d->m_currentCropPhoto];
1950     photo->cropRegion   = QRect(-2, -2, -2, -2);
1951     photo->rotation     = (photo->rotation + 90) % 360;
1952 
1953     updateCropFrame(photo, d->m_currentCropPhoto);
1954 }
1955 
setBtnCropEnabled()1956 void Wizard::setBtnCropEnabled()
1957 {
1958     if (d->m_currentCropPhoto == 0)
1959         d->m_cropUi->BtnCropPrev->setEnabled(false);
1960     else
1961         d->m_cropUi->BtnCropPrev->setEnabled(true);
1962 
1963     if (d->m_currentCropPhoto == (int) d->m_photos.count() - 1)
1964         d->m_cropUi->BtnCropNext->setEnabled(false);
1965     else
1966         d->m_cropUi->BtnCropNext->setEnabled(true);
1967 }
1968 
BtnCropNext_clicked()1969 void Wizard::BtnCropNext_clicked()
1970 {
1971     TPhoto* const photo = d->m_photos[++d->m_currentCropPhoto];
1972     setBtnCropEnabled();
1973 
1974     if (!photo)
1975     {
1976         d->m_currentCropPhoto = d->m_photos.count() - 1;
1977         return;
1978     }
1979 
1980     updateCropFrame(photo, d->m_currentCropPhoto);
1981 }
1982 
BtnCropPrev_clicked()1983 void Wizard::BtnCropPrev_clicked()
1984 {
1985     TPhoto* const photo = d->m_photos[--d->m_currentCropPhoto];
1986 
1987     setBtnCropEnabled();
1988 
1989     if (!photo)
1990     {
1991         d->m_currentCropPhoto = 0;
1992         return;
1993     }
1994 
1995     updateCropFrame(photo, d->m_currentCropPhoto);
1996 }
1997 
BtnPrintOrderUp_clicked()1998 void Wizard::BtnPrintOrderUp_clicked()
1999 {
2000     d->m_imagesFilesListBox->blockSignals(true);
2001     int currentIndex = d->m_imagesFilesListBox->listView()->currentIndex().row();
2002 
2003     qCDebug(KIPIPLUGINS_LOG) << "Moved photo " << currentIndex << " to  " << currentIndex + 1;
2004 
2005     d->m_photos.swap(currentIndex, currentIndex + 1);
2006     d->m_imagesFilesListBox->blockSignals(false);
2007     previewPhotos();
2008 }
2009 
ListPhotoSizes_selected()2010 void Wizard::ListPhotoSizes_selected()
2011 {
2012     TPhotoSize* s = nullptr;
2013     QSizeF size, sizeManaged;
2014 
2015     // TODO FREE STYLE
2016     // check if layout is managed by templates or free one
2017     // get the selected layout
2018     int curr              = d->m_photoUi->ListPhotoSizes->currentRow();
2019     QListWidgetItem* item = d->m_photoUi->ListPhotoSizes->item(curr);
2020 
2021     // if custom page layout we launch a dialog to choose what kind
2022     if (item->text() == i18n(customPageLayoutName))
2023     {
2024         // check if a custom layout has already been added
2025         if (curr >= 0 && curr < d->m_photoSizes.size())
2026         {
2027             s = d->m_photoSizes.at(curr);
2028             d->m_photoSizes.removeAt(curr);
2029             delete s;
2030             s = nullptr;
2031         }
2032 
2033         CustomLayoutDlg custDlg(this);
2034         custDlg.readSettings();
2035         custDlg.exec();
2036         custDlg.saveSettings();
2037 
2038         // get parameters from dialog
2039         size           = d->m_pageSize;
2040         int scaleValue = 10; // 0.1 mm
2041 
2042         // convert to mm
2043         if (custDlg.m_photoUnits->currentText() == i18n("inches"))
2044         {
2045             size       /= 25.4;
2046             scaleValue  = 1000;
2047         }
2048         else if (custDlg.m_photoUnits->currentText() == i18n("cm"))
2049         {
2050             size       /= 10;
2051             scaleValue  = 100;
2052         }
2053 
2054         sizeManaged = size * scaleValue;
2055 
2056         s = new TPhotoSize;
2057         TemplateIcon iconpreview(80, sizeManaged.toSize());
2058         iconpreview.begin();
2059 
2060         if (custDlg.m_photoGridCheck->isChecked())
2061         {
2062             // custom photo grid
2063             int rows       = custDlg.m_gridRows->value();
2064             int columns    = custDlg.m_gridColumns->value();
2065 
2066             s->layouts.append(new QRect(0, 0, (int)sizeManaged.width(), (int)sizeManaged.height()));
2067             s->autoRotate = custDlg.m_autorotate->isChecked();
2068             s->label      = item->text();
2069             s->dpi        = 0;
2070 
2071             int pageWidth  = (int)(size.width()) * scaleValue;
2072             int pageHeight = (int)(size.height()) * scaleValue;
2073             createPhotoGrid(s, pageWidth, pageHeight, rows, columns, &iconpreview);
2074         }
2075         else if (custDlg.m_fitAsManyCheck->isChecked())
2076         {
2077             int width                      = custDlg.m_photoWidth->value();
2078             int height                     = custDlg.m_photoHeight->value();
2079 
2080             //photo size must be less than page size
2081             static const float round_value = 0.01F;
2082 
2083             if ((height > (size.height() + round_value) || width  > (size.width() + round_value)))
2084             {
2085                 qCDebug(KIPIPLUGINS_LOG) << "photo size " << QSize(width, height) << "> page size " << size;
2086                 delete s;
2087                 s = nullptr;
2088             }
2089             else
2090             {
2091                 // fit as many photos of given size as possible
2092                 s->layouts.append(new QRect(0, 0, (int)sizeManaged.width(), (int)sizeManaged.height()));
2093                 s->autoRotate  = custDlg.m_autorotate->isChecked();
2094                 s->label       = item->text();
2095                 s->dpi         = 0;
2096                 int nColumns   = int(size.width()  / width);
2097                 int nRows      = int(size.height() / height);
2098                 int spareWidth = int(size.width())  % width;
2099 
2100                 // check if there's no room left to separate photos
2101                 if (nColumns > 1 &&  spareWidth == 0)
2102                 {
2103                     nColumns -= 1;
2104                     spareWidth = width;
2105                 }
2106 
2107                 int spareHeight = int(size.height()) % height;
2108 
2109                 // check if there's no room left to separate photos
2110                 if (nRows > 1 && spareHeight == 0)
2111                 {
2112                     nRows -= 1;
2113                     spareHeight = height;
2114                 }
2115 
2116                 if (nRows > 0 && nColumns > 0)
2117                 {
2118                     // n photos => dx1, photo1, dx2, photo2,... photoN, dxN+1
2119                     int dx      = spareWidth  * scaleValue / (nColumns + 1);
2120                     int dy      = spareHeight * scaleValue / (nRows + 1);
2121                     int photoX  = 0;
2122                     int photoY  = 0;
2123                     width      *= scaleValue;
2124                     height     *= scaleValue;
2125 
2126                     for (int row = 0; row < nRows; ++row)
2127                     {
2128                         photoY = dy * (row + 1) + (row * height);
2129 
2130                         for (int col = 0; col < nColumns; ++col)
2131                         {
2132                             photoX = dx * (col + 1) + (col * width);
2133                             qCDebug(KIPIPLUGINS_LOG) << "photo at P(" << photoX << ", " << photoY << ") size(" << width << ", " << height;
2134 
2135                             s->layouts.append(new QRect(photoX, photoY,
2136                                                         width, height));
2137                             iconpreview.fillRect(photoX, photoY, width, height, Qt::color1);
2138                         }
2139                     }
2140                 }
2141                 else
2142                 {
2143                     qCDebug(KIPIPLUGINS_LOG) << "I can't go on, rows " << nRows << "> columns " << nColumns;
2144                     delete s;
2145                     s = nullptr;
2146                 }
2147             }
2148         }
2149         else
2150         {
2151             // Atckin's layout
2152         }
2153 
2154         // TODO not for Atckin's layout
2155         iconpreview.end();
2156 
2157         if (s)
2158         {
2159             s->icon = iconpreview.getIcon();
2160             d->m_photoSizes.append(s);
2161         }
2162     }
2163     else
2164     {
2165         s = d->m_photoSizes.at(curr);
2166     }
2167 
2168     if (!s)
2169     {
2170         // change position to top
2171         d->m_photoUi->ListPhotoSizes->blockSignals(true);
2172         d->m_photoUi->ListPhotoSizes->setCurrentRow(0, QItemSelectionModel::Select);
2173         d->m_photoUi->ListPhotoSizes->blockSignals(false);
2174     }
2175 
2176     // reset preview page number
2177     d->m_currentPreviewPage = 0;
2178     previewPhotos();
2179 }
2180 
BtnPrintOrderDown_clicked()2181 void Wizard::BtnPrintOrderDown_clicked()
2182 {
2183     d->m_imagesFilesListBox->blockSignals(true);
2184     int currentIndex = d->m_imagesFilesListBox->listView()->currentIndex().row();
2185 
2186     qCDebug(KIPIPLUGINS_LOG) << "Moved photo " << currentIndex - 1 << " to  " << currentIndex;
2187 
2188     d->m_photos.swap(currentIndex, currentIndex - 1);
2189     d->m_imagesFilesListBox->blockSignals(false);
2190     previewPhotos();
2191 }
2192 
BtnPreviewPageDown_clicked()2193 void Wizard::BtnPreviewPageDown_clicked()
2194 {
2195     if (d->m_currentPreviewPage == 0)
2196         return;
2197 
2198     d->m_currentPreviewPage--;
2199     previewPhotos();
2200 }
2201 
BtnPreviewPageUp_clicked()2202 void Wizard::BtnPreviewPageUp_clicked()
2203 {
2204     if (d->m_currentPreviewPage == getPageCount() - 1)
2205         return;
2206 
2207     d->m_currentPreviewPage++;
2208     previewPhotos();
2209 }
2210 
BtnSaveAs_clicked()2211 void Wizard::BtnSaveAs_clicked()
2212 {
2213     qCDebug(KIPIPLUGINS_LOG) << "Save As Clicked";
2214     KConfig config ( QLatin1String("kipirc") );
2215     KConfigGroup group = config.group( QLatin1String( "PrintAssistant" ) );
2216     QUrl outputPath; // force to get current directory as default
2217     outputPath         = QUrl(group.readPathEntry( "OutputPath", outputPath.url() ));
2218     QString filename   = QFileDialog::getSaveFileName(qApp->activeWindow(), i18n("Output Path"), QLatin1String(".jpeg") );
2219     d->m_cropUi->m_fileName->setText(filename);
2220 }
2221 
saveSettings(const QString & pageName)2222 void Wizard::saveSettings(const QString& pageName)
2223 {
2224     qCDebug(KIPIPLUGINS_LOG) << pageName;
2225 
2226     // Save the current settings
2227     KConfig config(QLatin1String("kipirc"));
2228     KConfigGroup group = config.group(QLatin1String("PrintAssistant"));
2229 
2230     if (pageName == i18n(photoPageName))
2231     {
2232         group.writeEntry(QLatin1String("Printer"),   d->m_photoUi->m_printer_choice->currentText());
2233         // PhotoPage
2234         // photo size
2235         d->m_savedPhotoSize = d->m_photoUi->ListPhotoSizes->currentItem()->text();
2236         group.writeEntry(QLatin1String("PhotoSize"), d->m_savedPhotoSize);
2237         group.writeEntry(QLatin1String("IconSize"),  d->m_photoUi->ListPhotoSizes->iconSize());
2238     }
2239     else if (pageName == i18n(cropPageName))
2240     {
2241         // CropPage
2242         if (d->m_photoUi->m_printer_choice->currentText() == i18n("Print to JPG"))
2243         {
2244             // output path
2245             QString outputPath = d->m_cropUi->m_fileName->text();
2246             group.writePathEntry(QLatin1String("OutputPath"), outputPath);
2247         }
2248     }
2249 }
2250 
infopage_readCaptionSettings()2251 void Wizard::infopage_readCaptionSettings()
2252 {
2253     KConfig config(QLatin1String("kipirc"));
2254     KConfigGroup group = config.group(QLatin1String("PrintAssistant"));
2255 
2256     // image captions
2257     d->m_photoUi->m_captions->setCurrentIndex(group.readEntry(QLatin1String("Captions"), 0));
2258     // caption color
2259     QColor defColor(Qt::yellow);
2260     QColor color = group.readEntry(QLatin1String("CaptionColor"), defColor);
2261     d->m_photoUi->m_font_color->setColor(color);
2262     // caption font
2263     QFont defFont(QLatin1String("Sans Serif"));
2264     QFont font = group.readEntry(QLatin1String("CaptionFont"), defFont);
2265     d->m_photoUi->m_font_name->setCurrentFont(font.family());
2266     // caption size
2267     int fontSize = group.readEntry(QLatin1String("CaptionSize"), 4);
2268     d->m_photoUi->m_font_size->setValue(fontSize);
2269     // free caption
2270     QString captionTxt = group.readEntry(QLatin1String("FreeCaption"));
2271     d->m_photoUi->m_FreeCaptionFormat->setText(captionTxt);
2272 }
2273 
readSettings(const QString & pageName)2274 void Wizard::readSettings(const QString& pageName)
2275 {
2276     KConfig config(QLatin1String("kipirc"));
2277     KConfigGroup group = config.group(QLatin1String("PrintAssistant"));
2278 
2279     qCDebug(KIPIPLUGINS_LOG) << pageName;
2280 
2281     if (pageName == i18n(photoPageName))
2282     {
2283         // InfoPage
2284         QString printerName = group.readEntry("Printer", i18n("Print to PDF"));
2285         int index           = d->m_photoUi->m_printer_choice->findText(printerName);
2286 
2287         if (index != -1)
2288         {
2289             d->m_photoUi->m_printer_choice->setCurrentIndex(index);
2290         }
2291 
2292         // init QPrinter
2293         outputChanged(d->m_photoUi->m_printer_choice->currentText());
2294 
2295         QSize iconSize = group.readEntry("IconSize", QSize(24, 24));
2296         d->m_photoUi->ListPhotoSizes->setIconSize(iconSize);
2297 
2298         // photo size
2299         d->m_savedPhotoSize = group.readEntry("PhotoSize");
2300         //caption
2301         initPhotoSizes(d->m_printer->paperSize(QPrinter::Millimeter));
2302         infopage_readCaptionSettings();
2303 
2304         bool same_to_all = group.readEntry("SameCaptionToAll", 0) == 1;
2305         d->m_photoUi->m_sameCaption->setChecked(same_to_all);
2306         //enable right caption stuff
2307         captionChanged(d->m_photoUi->m_captions->currentText());
2308     }
2309     else if (pageName == i18n(cropPageName))
2310     {
2311         // CropPage
2312         if (d->m_photoUi->m_printer_choice->currentText() == i18n("Print to JPG"))
2313         {
2314             // set the last output path
2315             QUrl outputPath; // force to get current directory as default
2316             outputPath = QUrl(group.readPathEntry("OutputPath", outputPath.url()));
2317 
2318             d->m_cropUi->m_fileName->setVisible(true);
2319             d->m_cropUi->m_fileName->setEnabled(true);
2320             d->m_cropUi->m_fileName->setText(outputPath.path());
2321             d->m_cropUi->BtnSaveAs->setVisible(true);
2322 
2323         }
2324         else
2325         {
2326 
2327             d->m_cropUi->m_fileName->setVisible(false);
2328             d->m_cropUi->BtnSaveAs->setVisible(false);
2329 
2330         }
2331     }
2332 }
2333 
printPhotos(const QList<TPhoto * > & photos,const QList<QRect * > & layouts,QPrinter & printer)2334 void Wizard::printPhotos(const QList<TPhoto*>& photos, const QList<QRect*>& layouts, QPrinter& printer)
2335 {
2336     d->m_cancelPrinting = false;
2337     QProgressDialog pbar(this);
2338     pbar.setRange(0, photos.count());
2339     QApplication::processEvents();
2340 
2341     QPainter p;
2342     p.begin(&printer);
2343 
2344     int current   = 0;
2345     bool printing = true;
2346 
2347     while (printing)
2348     {
2349         printing = paintOnePage(p, photos, layouts, current, d->m_cropUi->m_disableCrop->isChecked());
2350 
2351         if (printing)
2352             printer.newPage();
2353 
2354         pbar.setValue(current);
2355         QApplication::processEvents();
2356 
2357         if (d->m_cancelPrinting)
2358         {
2359             printer.abort();
2360             return;
2361         }
2362     }
2363     p.end();
2364 }
2365 
printPhotosToFile(const QList<TPhoto * > & photos,const QString & baseFilename,TPhotoSize * const layouts)2366 QStringList Wizard::printPhotosToFile(const QList<TPhoto*>& photos, const QString& baseFilename, TPhotoSize* const layouts)
2367 {
2368     Q_ASSERT(layouts->layouts.count() > 1);
2369 
2370     d->m_cancelPrinting = false;
2371     QProgressDialog pbar(this);
2372     pbar.setRange(0, photos.count());
2373 
2374     QApplication::processEvents();
2375 
2376     int current   = 0;
2377     int pageCount = 1;
2378     bool printing = true;
2379     QStringList files;
2380 
2381     QRect* const srcPage = layouts->layouts.at(0);
2382 
2383     while (printing)
2384     {
2385         // make a pixmap to save to file.  Make it just big enough to show the
2386         // highest-dpi image on the page without losing data.
2387         double dpi = layouts->dpi;
2388 
2389         if (dpi == 0.0)
2390             dpi = getMaxDPI(photos, layouts->layouts, current) * 1.1;
2391 
2392         //int w = NINT(srcPage->width() / 1000.0 * dpi);
2393         //int h = NINT(srcPage->height()  / 1000.0 * dpi);
2394         int w = NINT(srcPage->width());
2395         int h = NINT(srcPage->height());
2396 
2397         QPixmap pixmap(w, h);
2398         QPainter painter;
2399         painter.begin(&pixmap);
2400 
2401         // save this page out to file
2402         QFileInfo fi(baseFilename);
2403         QString ext  = fi.completeSuffix();  // ext = ".jpeg"
2404         if (ext.isEmpty()) ext = QLatin1String(".jpeg");
2405         QString name = fi.baseName();
2406         QString path = fi.absolutePath();
2407 
2408         QString filename = path + QLatin1String("/") + name + QLatin1String("_") + QString::number(pageCount) + QLatin1String(".") + ext;
2409         bool saveFile    = true;
2410 
2411         if (QFile::exists(filename))
2412         {
2413             int result = QMessageBox::question(this, i18n("Overwrite File"),
2414                                                i18n("The following file will be overwritten. Are you sure you want to overwrite it?") +
2415                                                QLatin1String("\n\n") + filename,
2416                                                QMessageBox::StandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel),
2417                                                QMessageBox::No);
2418 
2419             if (result == QMessageBox::No)
2420             {
2421                 saveFile = false;
2422             }
2423             else if (result == QMessageBox::Cancel)
2424             {
2425                 break;
2426             }
2427         }
2428 
2429         printing = paintOnePage(painter, photos, layouts->layouts, current, d->m_cropUi->m_disableCrop->isChecked());
2430         painter.end();
2431 
2432         if (saveFile)
2433         {
2434             files.append(filename);
2435 
2436             if (!pixmap.save(filename,nullptr,100))
2437             {
2438                 QMessageBox::information(this, QString(), i18n("Could not save file, please check your output entry."));
2439                 break;
2440             }
2441         }
2442 
2443         pageCount++;
2444         pbar.setValue(current);
2445         QApplication::processEvents();
2446 
2447         if (d->m_cancelPrinting)
2448             break;
2449     }
2450 
2451     return files;
2452 }
2453 
removeGimpFiles()2454 void Wizard::removeGimpFiles()
2455 {
2456     for (QStringList::ConstIterator it = d->m_gimpFiles.constBegin(); it != d->m_gimpFiles.constEnd(); ++it)
2457     {
2458         if (QFile::exists(*it))
2459         {
2460             if (QFile::remove(*it) == false)
2461             {
2462                 QMessageBox::information(this, QString(), i18n("Could not remove the GIMP's temporary files."));
2463                 break;
2464             }
2465         }
2466     }
2467 }
2468 
2469 //TODO not needed at the moment maybe we can remove it
slotPageRemoved(int id)2470 void Wizard::slotPageRemoved(int id)
2471 {
2472     qCDebug(KIPIPLUGINS_LOG) << page(id)->title();
2473 }
2474 
crop_selection(int)2475 void Wizard::crop_selection(int)
2476 {
2477     d->m_cropUi->cropFrame->drawCropRectangle(!d->m_cropUi->m_disableCrop->isChecked());
2478     update();
2479 }
2480 
2481 // this is called when Cancel is clicked.
reject()2482 void Wizard::reject()
2483 {
2484     d->m_cancelPrinting = true;
2485 
2486     if (d->m_gimpFiles.count() > 0)
2487         removeGimpFiles();
2488 
2489     QDialog::reject();
2490 }
2491 
accept()2492 void Wizard::accept()
2493 {
2494     if (d->m_photos.empty())
2495     {
2496         KPWizardDialog::reject();
2497         return;
2498     }
2499 
2500     // set the default crop regions if not already set
2501     TPhotoSize* const s = d->m_photoSizes.at(d->m_photoUi->ListPhotoSizes->currentRow());
2502     QList<TPhoto*>::iterator it;
2503     int i               = 0;
2504 
2505     for (it = d->m_photos.begin(); it != d->m_photos.end(); ++it)
2506     {
2507         TPhoto* const photo = static_cast<TPhoto* >(*it);
2508 
2509         if (photo && photo->cropRegion == QRect(-1, -1, -1, -1))
2510             d->m_cropUi->cropFrame->init(photo, getLayout(i)->width(), getLayout(i)->height(), s->autoRotate);
2511 
2512         i++;
2513     }
2514 
2515     if (d->m_photoUi->m_printer_choice->currentText() != i18n("Print to JPG") &&
2516         d->m_photoUi->m_printer_choice->currentText() != i18n("Print to gimp"))
2517     {
2518         // tell him again!
2519         d->m_printer->setFullPage(true);
2520 
2521         qreal left, top, right, bottom;
2522         d->m_printer->getPageMargins(&left, &top, &right, &bottom, QPrinter::Millimeter);
2523 
2524         qCDebug(KIPIPLUGINS_LOG) << "Margins before print dialog: left " << left
2525                  << " right " << right << " top " << top << " bottom " << bottom;
2526         qCDebug(KIPIPLUGINS_LOG) << "(1) paper page " << d->m_printer->paperSize() << " size " << d->m_printer->paperSize(QPrinter::Millimeter);
2527 
2528         QPrinter::PaperSize paperSize =  d->m_printer->paperSize();
2529 
2530         QPrintDialog* const dialog          = new QPrintDialog(d->m_printer, this);
2531         dialog->setWindowTitle(i18n("Print assistant"));
2532 
2533         qCDebug(KIPIPLUGINS_LOG) << "(2) paper page " << dialog->printer()->paperSize() << " size " << dialog->printer()->paperSize(QPrinter::Millimeter);
2534 
2535         bool wantToPrint = (dialog->exec() == QDialog::Accepted);
2536 
2537         if (!wantToPrint)
2538         {
2539             KPWizardDialog::accept();
2540             return;
2541         }
2542 
2543         qCDebug(KIPIPLUGINS_LOG) << "(3) paper page " << dialog->printer()->paperSize() << " size " << dialog->printer()->paperSize(QPrinter::Millimeter);
2544 
2545         // Why paperSize changes if printer properties is not pressed?
2546         if (paperSize !=  d->m_printer->paperSize())
2547             d->m_printer->setPaperSize(paperSize);
2548 
2549         qCDebug(KIPIPLUGINS_LOG) << "(4) paper page " << dialog->printer()->paperSize() << " size " << dialog->printer()->paperSize(QPrinter::Millimeter);
2550 
2551         dialog->printer()->getPageMargins(&left, &top, &right, &bottom, QPrinter::Millimeter);
2552 
2553         qCDebug(KIPIPLUGINS_LOG) << "Dialog exit, new margins: left " << left
2554                  << " right " << right << " top " << top << " bottom " << bottom;
2555 
2556         QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
2557         printPhotos(d->m_photos, s->layouts, *d->m_printer);
2558         QApplication::restoreOverrideCursor();
2559     }
2560     else if (d->m_photoUi->m_printer_choice->currentText() == i18n("Print to gimp"))
2561     {
2562         // now output the items
2563         QString path = d->m_tempPath;
2564 
2565         if (!checkTempPath(this, path))
2566             return;
2567 
2568         path = path + QLatin1String("kipi_tmp_");
2569 
2570         if (d->m_gimpFiles.count() > 0)
2571             removeGimpFiles();
2572 
2573         d->m_gimpFiles = printPhotosToFile(d->m_photos, path, s);
2574         QStringList args;
2575         QString prog = QLatin1String("gimp-remote");
2576 
2577         for (QStringList::ConstIterator it = d->m_gimpFiles.constBegin(); it != d->m_gimpFiles.constEnd(); ++it)
2578             args << (*it);
2579 
2580         if (!launchExternalApp(prog, args))
2581         {
2582             QMessageBox::information(this, QString(),
2583                                      i18n("There was an error launching the GIMP. Please make sure it is properly installed."));
2584             return;
2585         }
2586     }
2587     else if (d->m_photoUi->m_printer_choice->currentText() == i18n("Print to JPG"))
2588     {
2589         // now output the items
2590         //TODO manage URL
2591         QString path = d->m_cropUi->m_fileName->text();
2592 
2593         if (path.isEmpty())
2594         {
2595             QMessageBox::information(this, QString(), i18n("Empty output path."));
2596             return;
2597         }
2598 
2599         qCDebug(KIPIPLUGINS_LOG) << path;
2600         QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
2601         printPhotosToFile(d->m_photos, path, s);
2602         QApplication::restoreOverrideCursor();
2603     }
2604 
2605     saveSettings(currentPage()->title());
2606     KPWizardDialog::accept();
2607 }
2608 
pagesetupdialogexit()2609 void Wizard::pagesetupdialogexit()
2610 {
2611     QPrinter* const printer = d->m_pDlg->printer();
2612 
2613     qCDebug(KIPIPLUGINS_LOG) << "Dialog exit, new size " << printer->paperSize(QPrinter::Millimeter)
2614              << " internal size " << d->m_printer->paperSize(QPrinter::Millimeter);
2615 
2616     qreal left, top, right, bottom;
2617     d->m_printer->getPageMargins(&left, &top, &right, &bottom, QPrinter::Millimeter);
2618 
2619     qCDebug(KIPIPLUGINS_LOG) << "Dialog exit, new margins: left " << left
2620              << " right " << right << " top " << top << " bottom " << bottom;
2621 
2622     // next should be useless invoke once changing wizard page
2623     //initPhotoSizes ( d->m_printer.paperSize(QPrinter::Millimeter));
2624 
2625     //     d->m_pageSize = d->m_printer.paperSize(QPrinter::Millimeter);
2626 #ifdef NOT_YET
2627     qCDebug(KIPIPLUGINS_LOG) << " dialog exited num of copies: " << printer->numCopies()
2628                              << " inside:   " << d->m_printer->numCopies();
2629 
2630     qCDebug(KIPIPLUGINS_LOG) << " dialog exited from : " << printer->fromPage()
2631                              << " to:   " << d->m_printer->toPage();
2632 #endif
2633 }
2634 
pagesetupclicked()2635 void Wizard::pagesetupclicked()
2636 {
2637     delete d->m_pDlg;
2638     d->m_pDlg = new QPageSetupDialog(d->m_printer, this);
2639     // TODO next line should work but it doesn't because of a QT bug
2640     //d->m_pDlg->open(this, SLOT(pagesetupdialogexit()));
2641     int ret   = d->m_pDlg->exec();
2642 
2643     if (ret == QDialog::Accepted)
2644     {
2645         pagesetupdialogexit();
2646     }
2647 
2648     // FIX page size dialog and preview PhotoPage
2649     initPhotoSizes(d->m_printer->paperSize(QPrinter::Millimeter));
2650 
2651     // restore photoSize
2652     if (d->m_savedPhotoSize == i18n(customPageLayoutName))
2653     {
2654         d->m_photoUi->ListPhotoSizes->setCurrentRow(0);
2655     }
2656     else
2657     {
2658         QList<QListWidgetItem*> list = d->m_photoUi->ListPhotoSizes->findItems(d->m_savedPhotoSize, Qt::MatchExactly);
2659 
2660         if (list.count())
2661             d->m_photoUi->ListPhotoSizes->setCurrentItem(list[0]);
2662         else
2663             d->m_photoUi->ListPhotoSizes->setCurrentRow(0);
2664     }
2665 
2666     // create our photo sizes list
2667     previewPhotos();
2668 }
2669 
infopage_blockCaptionButtons(bool block)2670 void Wizard::infopage_blockCaptionButtons(bool block)
2671 {
2672     d->m_photoUi->m_captions->blockSignals(block);
2673     d->m_photoUi->m_free_label->blockSignals(block);
2674     d->m_photoUi->m_sameCaption->blockSignals(block);
2675     d->m_photoUi->m_font_name->blockSignals(block);
2676     d->m_photoUi->m_font_size->blockSignals(block);
2677     d->m_photoUi->m_font_color->blockSignals(block);
2678 }
2679 
saveCaptionSettings()2680 void Wizard::saveCaptionSettings()
2681 {
2682     // Save the current settings
2683     KConfig config(QLatin1String("kipirc"));
2684     KConfigGroup group = config.group(QLatin1String("PrintAssistant"));
2685     // image captions
2686     group.writeEntry(QLatin1String("Captions"),         d->m_photoUi->m_captions->currentIndex());
2687     // caption color
2688     group.writeEntry(QLatin1String("CaptionColor"),     d->m_photoUi->m_font_color->color());
2689     // caption font
2690     group.writeEntry(QLatin1String("CaptionFont"),      QFont(d->m_photoUi->m_font_name->currentFont()));
2691     // caption size
2692     group.writeEntry(QLatin1String("CaptionSize"),      d->m_photoUi->m_font_size->value());
2693     // free caption
2694     group.writeEntry(QLatin1String("FreeCaption"),      d->m_photoUi->m_FreeCaptionFormat->text());
2695     // same to all
2696     group.writeEntry(QLatin1String("SameCaptionToAll"), (d->m_photoUi->m_sameCaption->isChecked() ? 1 : 0));
2697 }
2698 
2699 } // namespace KIPIPrintImagesPlugin
2700