File indexing completed on 2025-01-05 03:53:14
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2017-05-25 0007 * Description : a tool to print images 0008 * 0009 * SPDX-FileCopyrightText: 2017-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0010 * 0011 * SPDX-License-Identifier: GPL-2.0-or-later 0012 * 0013 * ============================================================ */ 0014 0015 #include "advprintphotopage.h" 0016 0017 // Qt includes 0018 0019 #include <QFile> 0020 #include <QDir> 0021 #include <QIcon> 0022 #include <QPointer> 0023 #include <QPrinterInfo> 0024 #include <QWidget> 0025 #include <QMessageBox> 0026 #include <QApplication> 0027 #include <QStyle> 0028 #include <QMenu> 0029 #include <QAction> 0030 #include <QPageSetupDialog> 0031 #include <QXmlStreamAttributes> 0032 #include <QDomDocument> 0033 #include <QDomNode> 0034 0035 // KDE includes 0036 0037 #include <kdesktopfile.h> 0038 0039 // Local includes 0040 0041 #include "digikam_debug.h" 0042 #include "advprintwizard.h" 0043 #include "advprintcustomdlg.h" 0044 #include "templateicon.h" 0045 #include "digikam_globals_p.h" // For KF6::Ki18n deprecated 0046 0047 namespace DigikamGenericPrintCreatorPlugin 0048 { 0049 0050 static const struct CustomPageLayoutName 0051 { 0052 0053 #if KI18N_VERSION >= QT_VERSION_CHECK(5, 89, 0) 0054 0055 const KLazyLocalizedString title; 0056 0057 #else 0058 0059 const char* context; 0060 const char* title; 0061 0062 #endif 0063 0064 } 0065 CUSTOM_PAGE_LAYOUT_NAME = 0066 { 0067 I18NC_NOOP("@info layout page", "Custom") 0068 }; 0069 0070 class Q_DECL_HIDDEN AdvPrintPhotoPage::Private 0071 { 0072 public: 0073 0074 template <class Ui_Class> 0075 0076 class Q_DECL_HIDDEN WizardUI : public QWidget, 0077 public Ui_Class 0078 { 0079 public: 0080 0081 explicit WizardUI(QWidget* const parent) 0082 : QWidget(parent) 0083 { 0084 this->setupUi(this); 0085 } 0086 }; 0087 0088 typedef WizardUI<Ui_AdvPrintPhotoPage> PhotoUI; 0089 0090 public: 0091 0092 explicit Private(QWizard* const dialog) 0093 : pageSetupDlg(nullptr), 0094 printer (nullptr), 0095 wizard (nullptr), 0096 settings (nullptr), 0097 iface (nullptr) 0098 { 0099 photoUi = new PhotoUI(dialog); 0100 wizard = dynamic_cast<AdvPrintWizard*>(dialog); 0101 0102 if (wizard) 0103 { 0104 settings = wizard->settings(); 0105 iface = wizard->iface(); 0106 } 0107 } 0108 0109 PhotoUI* photoUi; 0110 QPageSetupDialog* pageSetupDlg; 0111 QPrinter* printer; 0112 QList<QPrinterInfo> printerList; 0113 0114 AdvPrintWizard* wizard; 0115 AdvPrintSettings* settings; 0116 DInfoInterface* iface; 0117 }; 0118 0119 AdvPrintPhotoPage::AdvPrintPhotoPage(QWizard* const wizard, const QString& title) 0120 : DWizardPage(wizard, title), 0121 d (new Private(wizard)) 0122 { 0123 d->photoUi->BtnPreviewPageUp->setIcon(QIcon::fromTheme(QLatin1String("go-next")) 0124 .pixmap(16, 16)); 0125 d->photoUi->BtnPreviewPageDown->setIcon(QIcon::fromTheme(QLatin1String("go-previous")) 0126 .pixmap(16, 16)); 0127 0128 // ---------------------- 0129 0130 d->photoUi->m_printer_choice->setEditable(false); 0131 d->photoUi->m_printer_choice->setWhatsThis(i18nc("@info", "Select your preferred print output.")); 0132 0133 // Populate hardcoded printers 0134 0135 QMap<AdvPrintSettings::Output, QString> map2 = AdvPrintSettings::outputNames(); 0136 QMap<AdvPrintSettings::Output, QString>::const_iterator it2 = map2.constBegin(); 0137 0138 while (it2 != map2.constEnd()) 0139 { 0140 d->photoUi->m_printer_choice->addSqueezedItem(it2.value(), (int)it2.key()); 0141 ++it2; 0142 } 0143 0144 // Populate real printers 0145 0146 d->printerList = QPrinterInfo::availablePrinters(); 0147 0148 for (QList<QPrinterInfo>::iterator it = d->printerList.begin() ; 0149 it != d->printerList.end() ; ++it) 0150 { 0151 d->photoUi->m_printer_choice->addSqueezedItem(it->printerName()); 0152 } 0153 0154 connect(d->photoUi->m_printer_choice, SIGNAL(signalItemActivated(QString)), 0155 this, SLOT(slotOutputChanged(QString))); 0156 0157 connect(d->photoUi->BtnPreviewPageUp, SIGNAL(clicked()), 0158 this, SLOT(slotBtnPreviewPageUpClicked())); 0159 0160 connect(d->photoUi->BtnPreviewPageDown, SIGNAL(clicked()), 0161 this, SLOT(slotBtnPreviewPageDownClicked())); 0162 0163 connect(d->photoUi->ListPhotoSizes, SIGNAL(currentRowChanged(int)), 0164 this, SLOT(slotListPhotoSizesSelected())); 0165 0166 connect(d->photoUi->m_pagesetup, SIGNAL(clicked()), 0167 this, SLOT(slotPageSetup())); 0168 0169 if (d->photoUi->mPrintList->layout()) 0170 { 0171 delete d->photoUi->mPrintList->layout(); 0172 } 0173 0174 // ----------------------------------- 0175 0176 d->photoUi->mPrintList->setIface(d->iface); 0177 d->photoUi->mPrintList->setAllowDuplicate(true); 0178 d->photoUi->mPrintList->setControlButtons(DItemsList::Add | 0179 DItemsList::Remove | 0180 DItemsList::MoveUp | 0181 DItemsList::MoveDown | 0182 DItemsList::Clear | 0183 DItemsList::Save | 0184 DItemsList::Load); 0185 d->photoUi->mPrintList->setControlButtonsPlacement(DItemsList::ControlButtonsAbove); 0186 d->photoUi->mPrintList->enableDragAndDrop(false); 0187 0188 d->photoUi->BmpFirstPagePreview->setAlignment(Qt::AlignHCenter); 0189 0190 connect(d->photoUi->mPrintList, SIGNAL(signalMoveDownItem()), 0191 this, SLOT(slotBtnPrintOrderDownClicked())); 0192 0193 connect(d->photoUi->mPrintList, SIGNAL(signalMoveUpItem()), 0194 this, SLOT(slotBtnPrintOrderUpClicked())); 0195 0196 connect(d->photoUi->mPrintList, SIGNAL(signalAddItems(QList<QUrl>)), 0197 this, SLOT(slotAddItems(QList<QUrl>))); 0198 0199 connect(d->photoUi->mPrintList, SIGNAL(signalRemovedItems(QList<int>)), 0200 this, SLOT(slotRemovingItems(QList<int>))); 0201 0202 connect(d->photoUi->mPrintList, SIGNAL(signalContextMenuRequested()), 0203 this, SLOT(slotContextMenuRequested())); 0204 0205 connect(d->photoUi->mPrintList, SIGNAL(signalXMLSaveItem(QXmlStreamWriter&,int)), 0206 this, SLOT(slotXMLSaveItem(QXmlStreamWriter&,int))); 0207 0208 connect(d->photoUi->mPrintList, SIGNAL(signalXMLCustomElements(QXmlStreamWriter&)), 0209 this, SLOT(slotXMLCustomElement(QXmlStreamWriter&))); 0210 0211 connect(d->photoUi->mPrintList, SIGNAL(signalXMLLoadImageElement(QXmlStreamReader&)), 0212 this, SLOT(slotXMLLoadElement(QXmlStreamReader&))); 0213 0214 connect(d->photoUi->mPrintList, SIGNAL(signalXMLCustomElements(QXmlStreamReader&)), 0215 this, SLOT(slotXMLCustomElement(QXmlStreamReader&))); 0216 0217 // ----------------------------------- 0218 0219 setPageWidget(d->photoUi); 0220 setLeftBottomPix(QIcon::fromTheme(QLatin1String("image-stack"))); 0221 0222 slotOutputChanged(d->photoUi->m_printer_choice->itemHighlighted()); 0223 } 0224 0225 AdvPrintPhotoPage::~AdvPrintPhotoPage() 0226 { 0227 delete d->printer; 0228 delete d->pageSetupDlg; 0229 delete d; 0230 } 0231 0232 void AdvPrintPhotoPage::initializePage() 0233 { 0234 d->photoUi->mPrintList->listView()->selectAll(); 0235 d->photoUi->mPrintList->slotRemoveItems(); 0236 0237 if (d->settings->selMode == AdvPrintSettings::IMAGES) 0238 { 0239 d->photoUi->mPrintList->loadImagesFromCurrentSelection(); 0240 } 0241 else 0242 { 0243 d->wizard->setItemsList(d->settings->inputImages); 0244 } 0245 0246 initPhotoSizes(d->printer->pageLayout().pageSize().size(QPageSize::Millimeter)); 0247 0248 // restore photoSize 0249 0250 #if KI18N_VERSION >= QT_VERSION_CHECK(5, 89, 0) 0251 0252 if (d->settings->savedPhotoSize == CUSTOM_PAGE_LAYOUT_NAME.title.toString()) 0253 0254 #else 0255 0256 if (d->settings->savedPhotoSize == i18nc(CUSTOM_PAGE_LAYOUT_NAME.context, CUSTOM_PAGE_LAYOUT_NAME.title)) 0257 0258 #endif 0259 0260 { 0261 d->photoUi->ListPhotoSizes->setCurrentRow(0); 0262 } 0263 else 0264 { 0265 QList<QListWidgetItem*> list = d->photoUi->ListPhotoSizes->findItems(d->settings->savedPhotoSize, Qt::MatchExactly); 0266 0267 if (list.count()) 0268 { 0269 d->photoUi->ListPhotoSizes->setCurrentItem(list[0]); 0270 } 0271 else 0272 { 0273 d->photoUi->ListPhotoSizes->setCurrentRow(0); 0274 } 0275 } 0276 0277 // reset preview page number 0278 0279 d->settings->currentPreviewPage = 0; 0280 0281 // create our photo sizes list 0282 0283 int gid = d->photoUi->m_printer_choice->findText(d->settings->outputName(AdvPrintSettings::GIMP)); 0284 0285 if (d->settings->gimpPath.isEmpty()) 0286 { 0287 // Gimp is not available : we disable the option. 0288 0289 d->photoUi->m_printer_choice->setItemData(gid, false, Qt::UserRole-1); 0290 } 0291 0292 int index = d->photoUi->m_printer_choice->findText(d->settings->printerName); 0293 0294 if (index != -1) 0295 { 0296 d->photoUi->m_printer_choice->setCurrentIndex(index); 0297 } 0298 0299 slotOutputChanged(d->photoUi->m_printer_choice->itemHighlighted()); 0300 0301 d->photoUi->ListPhotoSizes->setIconSize(QSize(32, 32)); 0302 initPhotoSizes(d->printer->pageLayout().pageSize().size(QPageSize::Millimeter)); 0303 0304 d->wizard->previewPhotos(); 0305 } 0306 0307 bool AdvPrintPhotoPage::validatePage() 0308 { 0309 d->settings->inputImages = d->photoUi->mPrintList->imageUrls(); 0310 d->settings->printerName = d->photoUi->m_printer_choice->itemHighlighted(); 0311 0312 if (d->photoUi->ListPhotoSizes->currentItem()) 0313 { 0314 d->settings->savedPhotoSize = d->photoUi->ListPhotoSizes->currentItem()->text(); 0315 } 0316 0317 return true; 0318 } 0319 0320 bool AdvPrintPhotoPage::isComplete() const 0321 { 0322 return (!d->photoUi->mPrintList->imageUrls().isEmpty() || 0323 !d->wizard->itemsList().isEmpty()); 0324 } 0325 0326 QPrinter* AdvPrintPhotoPage::printer() const 0327 { 0328 return d->printer; 0329 } 0330 0331 DItemsList* AdvPrintPhotoPage::imagesList() const 0332 { 0333 return d->photoUi->mPrintList; 0334 } 0335 0336 Ui_AdvPrintPhotoPage* AdvPrintPhotoPage::ui() const 0337 { 0338 return d->photoUi; 0339 } 0340 0341 void AdvPrintPhotoPage::slotOutputChanged(const QString& text) 0342 { 0343 if (AdvPrintSettings::outputNames().values().contains(text)) 0344 { 0345 delete d->printer; 0346 0347 d->printer = new QPrinter(); 0348 d->printer->setOutputFormat(QPrinter::PdfFormat); 0349 } 0350 else // real printer 0351 { 0352 for (QList<QPrinterInfo>::iterator it = d->printerList.begin() ; 0353 it != d->printerList.end() ; ++it) 0354 { 0355 if (it->printerName() == text) 0356 { 0357 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Chosen printer: " << it->printerName(); 0358 delete d->printer; 0359 d->printer = new QPrinter(*it); 0360 } 0361 } 0362 0363 d->printer->setOutputFormat(QPrinter::NativeFormat); 0364 } 0365 0366 // default no margins 0367 0368 d->printer->setFullPage(true); 0369 QMarginsF margins(0, 0, 0, 0); 0370 d->printer->setPageMargins(margins, QPageLayout::Millimeter); 0371 } 0372 0373 void AdvPrintPhotoPage::slotXMLLoadElement(QXmlStreamReader& xmlReader) 0374 { 0375 if (d->settings->photos.size()) 0376 { 0377 // read image is the last. 0378 0379 AdvPrintPhoto* const pPhoto = d->settings->photos[d->settings->photos.size()-1]; 0380 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << " invoked " << xmlReader.name(); 0381 0382 while (xmlReader.readNextStartElement()) 0383 { 0384 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << pPhoto->m_url << " " << xmlReader.name(); 0385 0386 if (xmlReader.name() == QLatin1String("pa_caption")) 0387 { 0388 //useless this item has been added now 0389 0390 if (pPhoto->m_pAdvPrintCaptionInfo) 0391 { 0392 delete pPhoto->m_pAdvPrintCaptionInfo; 0393 } 0394 0395 pPhoto->m_pAdvPrintCaptionInfo = new AdvPrintCaptionInfo(); 0396 0397 // get all attributes and its value of a tag in attrs variable. 0398 0399 QXmlStreamAttributes attrs = xmlReader.attributes(); 0400 0401 // get value of each attribute from QXmlStreamAttributes 0402 0403 QStringView attr = attrs.value(QLatin1String("type")); 0404 bool ok; 0405 0406 if (!attr.isEmpty()) 0407 { 0408 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << " found " << attr.toString(); 0409 pPhoto->m_pAdvPrintCaptionInfo->m_captionType = 0410 (AdvPrintSettings::CaptionType)attr.toString().toInt(&ok); 0411 } 0412 0413 attr = attrs.value(QLatin1String("font")); 0414 0415 if (!attr.isEmpty()) 0416 { 0417 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << " found " << attr.toString(); 0418 pPhoto->m_pAdvPrintCaptionInfo->m_captionFont.fromString(attr.toString()); 0419 } 0420 0421 attr = attrs.value(QLatin1String("color")); 0422 0423 if (!attr.isEmpty()) 0424 { 0425 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << " found " << attr.toString(); 0426 pPhoto->m_pAdvPrintCaptionInfo->m_captionColor.setNamedColor(attr.toString()); 0427 } 0428 0429 attr = attrs.value(QLatin1String("size")); 0430 0431 if (!attr.isEmpty()) 0432 { 0433 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << " found " << attr.toString(); 0434 pPhoto->m_pAdvPrintCaptionInfo->m_captionSize = attr.toString().toInt(&ok); 0435 } 0436 0437 attr = attrs.value(QLatin1String("text")); 0438 0439 if (!attr.isEmpty()) 0440 { 0441 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << " found " << attr.toString(); 0442 pPhoto->m_pAdvPrintCaptionInfo->m_captionText = attr.toString(); 0443 } 0444 } 0445 } 0446 } 0447 } 0448 0449 void AdvPrintPhotoPage::slotXMLSaveItem(QXmlStreamWriter& xmlWriter, int itemIndex) 0450 { 0451 if (d->settings->photos.size()) 0452 { 0453 AdvPrintPhoto* const pPhoto = d->settings->photos[itemIndex]; 0454 0455 // TODO: first and copies could be removed since they are not useful any more 0456 0457 xmlWriter.writeAttribute(QLatin1String("first"), 0458 QString::fromUtf8("%1") 0459 .arg(pPhoto->m_first)); 0460 0461 xmlWriter.writeAttribute(QLatin1String("copies"), 0462 QString::fromUtf8("%1") 0463 .arg(pPhoto->m_first ? pPhoto->m_copies : 0)); 0464 0465 // additional info (caption... etc) 0466 0467 if (pPhoto->m_pAdvPrintCaptionInfo) 0468 { 0469 xmlWriter.writeStartElement(QLatin1String("pa_caption")); 0470 xmlWriter.writeAttribute(QLatin1String("type"), 0471 QString::fromUtf8("%1").arg(pPhoto->m_pAdvPrintCaptionInfo->m_captionType)); 0472 xmlWriter.writeAttribute(QLatin1String("font"), 0473 pPhoto->m_pAdvPrintCaptionInfo->m_captionFont.toString()); 0474 xmlWriter.writeAttribute(QLatin1String("size"), 0475 QString::fromUtf8("%1").arg(pPhoto->m_pAdvPrintCaptionInfo->m_captionSize)); 0476 xmlWriter.writeAttribute(QLatin1String("color"), 0477 pPhoto->m_pAdvPrintCaptionInfo->m_captionColor.name()); 0478 xmlWriter.writeAttribute(QLatin1String("text"), 0479 pPhoto->m_pAdvPrintCaptionInfo->m_captionText); 0480 xmlWriter.writeEndElement(); // pa_caption 0481 } 0482 } 0483 } 0484 0485 void AdvPrintPhotoPage::slotXMLCustomElement(QXmlStreamWriter& xmlWriter) 0486 { 0487 xmlWriter.writeStartElement(QLatin1String("pa_layout")); 0488 xmlWriter.writeAttribute(QLatin1String("Printer"), d->photoUi->m_printer_choice->itemHighlighted()); 0489 xmlWriter.writeAttribute(QLatin1String("PageSize"), QString::fromUtf8("%1").arg(d->printer->pageLayout().pageSize().id())); 0490 xmlWriter.writeAttribute(QLatin1String("PhotoSize"), d->photoUi->ListPhotoSizes->currentItem()->text()); 0491 xmlWriter.writeEndElement(); // pa_layout 0492 } 0493 0494 void AdvPrintPhotoPage::slotContextMenuRequested() 0495 { 0496 if (d->settings->photos.size()) 0497 { 0498 int itemIndex = d->photoUi->mPrintList->listView()->currentIndex().row(); 0499 d->photoUi->mPrintList->listView()->blockSignals(true); 0500 QMenu menu(d->photoUi->mPrintList->listView()); 0501 QAction* const action = menu.addAction(i18n("Add again")); 0502 0503 connect(action, SIGNAL(triggered()), 0504 this , SLOT(slotIncreaseCopies())); 0505 0506 AdvPrintPhoto* const pPhoto = d->settings->photos[itemIndex]; 0507 0508 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << " copies " 0509 << pPhoto->m_copies 0510 << " first " 0511 << pPhoto->m_first; 0512 0513 if ((pPhoto->m_copies > 1) || !pPhoto->m_first) 0514 { 0515 QAction* const actionr = menu.addAction(i18n("Remove")); 0516 0517 connect(actionr, SIGNAL(triggered()), 0518 this, SLOT(slotDecreaseCopies())); 0519 } 0520 0521 menu.exec(QCursor::pos()); 0522 d->photoUi->mPrintList->listView()->blockSignals(false); 0523 } 0524 } 0525 0526 void AdvPrintPhotoPage::slotIncreaseCopies() 0527 { 0528 if (d->settings->photos.size()) 0529 { 0530 QList<QUrl> list; 0531 DItemsListViewItem* const item = dynamic_cast<DItemsListViewItem*>(d->photoUi->mPrintList->listView()->currentItem()); 0532 0533 if (!item) 0534 { 0535 return; 0536 } 0537 0538 list.append(item->url()); 0539 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << " Adding a copy of " << item->url(); 0540 d->photoUi->mPrintList->slotAddImages(list); 0541 } 0542 } 0543 0544 void AdvPrintPhotoPage::slotDecreaseCopies() 0545 { 0546 if (d->settings->photos.size()) 0547 { 0548 DItemsListViewItem* const item = dynamic_cast<DItemsListViewItem*> 0549 (d->photoUi->mPrintList->listView()->currentItem()); 0550 0551 if (!item) 0552 { 0553 return; 0554 } 0555 0556 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << " Removing a copy of " << item->url(); 0557 d->photoUi->mPrintList->slotRemoveItems(); 0558 } 0559 } 0560 0561 void AdvPrintPhotoPage::slotAddItems(const QList<QUrl>& list) 0562 { 0563 if (list.count() == 0) 0564 { 0565 return; 0566 } 0567 0568 QList<QUrl> urls; 0569 d->photoUi->mPrintList->blockSignals(true); 0570 0571 for (QList<QUrl>::ConstIterator it = list.constBegin() ; 0572 it != list.constEnd() ; ++it) 0573 { 0574 QUrl imageUrl = *it; 0575 0576 // Check if the new item already exist in the list. 0577 0578 bool found = false; 0579 0580 for (int i = 0 ; i < d->settings->photos.count() && !found ; ++i) 0581 { 0582 AdvPrintPhoto* const pCurrentPhoto = d->settings->photos.at(i); 0583 0584 if (pCurrentPhoto && 0585 (pCurrentPhoto->m_url == imageUrl) && 0586 pCurrentPhoto->m_first) 0587 { 0588 pCurrentPhoto->m_copies++; 0589 found = true; 0590 AdvPrintPhoto* const pPhoto = new AdvPrintPhoto(*pCurrentPhoto); 0591 pPhoto->m_first = false; 0592 d->settings->photos.append(pPhoto); 0593 0594 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Added fileName: " 0595 << pPhoto->m_url.fileName() 0596 << " copy number " 0597 << pCurrentPhoto->m_copies; 0598 } 0599 } 0600 0601 if (!found) 0602 { 0603 AdvPrintPhoto* const pPhoto = new AdvPrintPhoto(150, d->iface); 0604 pPhoto->m_url = *it; 0605 pPhoto->m_first = true; 0606 d->settings->photos.append(pPhoto); 0607 0608 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Added new fileName: " 0609 << pPhoto->m_url.fileName(); 0610 } 0611 } 0612 0613 d->photoUi->mPrintList->blockSignals(false); 0614 d->photoUi->LblPhotoCount->setText(QString::number(d->settings->photos.count())); 0615 0616 if (d->settings->photos.size()) 0617 { 0618 setComplete(true); 0619 } 0620 } 0621 0622 void AdvPrintPhotoPage::slotRemovingItems(const QList<int>& list) 0623 { 0624 if (list.count() == 0) 0625 { 0626 return; 0627 } 0628 0629 d->photoUi->mPrintList->blockSignals(true); 0630 0631 Q_FOREACH (int itemIndex, list) 0632 { 0633 if (d->settings->photos.size() && itemIndex >= 0) 0634 { 0635 /// Debug data: found and copies 0636 0637 bool found = false; 0638 int copies = 0; 0639 0640 AdvPrintPhoto* const pPhotoToRemove = d->settings->photos.at(itemIndex); 0641 0642 // photo to be removed could be: 0643 // 1) unique => just remove it 0644 // 2) first of n, => 0645 // search another with the same url 0646 // and set it a first and with a count to n-1 then remove it 0647 // 3) one of n, search the first one and set count to n-1 then remove it 0648 0649 if (pPhotoToRemove && pPhotoToRemove->m_first) 0650 { 0651 if (pPhotoToRemove->m_copies > 0) 0652 { 0653 for (int i = 0 ; i < d->settings->photos.count() && !found ; ++i) 0654 { 0655 AdvPrintPhoto* const pCurrentPhoto = d->settings->photos.at(i); 0656 0657 if (pCurrentPhoto && pCurrentPhoto->m_url == pPhotoToRemove->m_url) 0658 { 0659 pCurrentPhoto->m_copies = pPhotoToRemove->m_copies - 1; 0660 copies = pCurrentPhoto->m_copies; 0661 pCurrentPhoto->m_first = true; 0662 found = true; 0663 } 0664 } 0665 } 0666 0667 // otherwise it's unique 0668 } 0669 else if (pPhotoToRemove) 0670 { 0671 for (int i = 0 ; i < d->settings->photos.count() && !found ; ++i) 0672 { 0673 AdvPrintPhoto* const pCurrentPhoto = d->settings->photos.at(i); 0674 0675 if (pCurrentPhoto && 0676 pCurrentPhoto->m_url == pPhotoToRemove->m_url && 0677 pCurrentPhoto->m_first) 0678 { 0679 pCurrentPhoto->m_copies--; 0680 copies = pCurrentPhoto->m_copies; 0681 found = true; 0682 } 0683 } 0684 } 0685 else 0686 { 0687 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << " NULL AdvPrintPhoto object "; 0688 return; 0689 } 0690 0691 if (pPhotoToRemove) 0692 { 0693 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Removed fileName: " 0694 << pPhotoToRemove->m_url.fileName() 0695 << " copy number " 0696 << copies; 0697 } 0698 0699 d->settings->photos.removeAt(itemIndex); 0700 delete pPhotoToRemove; 0701 } 0702 } 0703 0704 d->wizard->previewPhotos(); 0705 d->photoUi->mPrintList->blockSignals(false); 0706 d->photoUi->LblPhotoCount->setText(QString::number(d->settings->photos.count())); 0707 0708 if (d->settings->photos.isEmpty()) 0709 { 0710 // No photos => disabling next button (e.g. crop page) 0711 0712 setComplete(false); 0713 } 0714 } 0715 0716 void AdvPrintPhotoPage::slotBtnPrintOrderDownClicked() 0717 { 0718 d->photoUi->mPrintList->blockSignals(true); 0719 int currentIndex = d->photoUi->mPrintList->listView()->currentIndex().row(); 0720 0721 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Moved photo " 0722 << currentIndex - 1 0723 << " to " 0724 << currentIndex; 0725 0726 d->settings->photos.swapItemsAt(currentIndex, currentIndex - 1); 0727 d->photoUi->mPrintList->blockSignals(false); 0728 d->wizard->previewPhotos(); 0729 } 0730 0731 void AdvPrintPhotoPage::slotBtnPrintOrderUpClicked() 0732 { 0733 d->photoUi->mPrintList->blockSignals(true); 0734 int currentIndex = d->photoUi->mPrintList->listView()->currentIndex().row(); 0735 0736 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Moved photo " 0737 << currentIndex 0738 << " to " 0739 << currentIndex + 1; 0740 0741 d->settings->photos.swapItemsAt(currentIndex, currentIndex + 1); 0742 d->photoUi->mPrintList->blockSignals(false); 0743 d->wizard->previewPhotos(); 0744 } 0745 0746 void AdvPrintPhotoPage::slotXMLCustomElement(QXmlStreamReader& xmlReader) 0747 { 0748 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << " invoked " << xmlReader.name(); 0749 0750 while (!xmlReader.atEnd()) 0751 { 0752 if (xmlReader.isStartElement() && xmlReader.name() == QLatin1String("pa_layout")) 0753 { 0754 bool ok; 0755 QXmlStreamAttributes attrs = xmlReader.attributes(); 0756 0757 // get value of each attribute from QXmlStreamAttributes 0758 0759 QStringView attr = attrs.value(QLatin1String("Printer")); 0760 0761 if (!attr.isEmpty()) 0762 { 0763 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << " found " << attr.toString(); 0764 int index = d->photoUi->m_printer_choice->findText(attr.toString()); 0765 0766 if (index != -1) 0767 { 0768 d->photoUi->m_printer_choice->setCurrentIndex(index); 0769 } 0770 0771 slotOutputChanged(d->photoUi->m_printer_choice->itemHighlighted()); 0772 } 0773 0774 attr = attrs.value(QLatin1String("PageSize")); 0775 0776 if (!attr.isEmpty()) 0777 { 0778 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << " found " << attr.toString(); 0779 QPageSize pageSize((QPageSize::PageSizeId)attr.toString().toInt(&ok)); 0780 d->printer->setPageSize(pageSize); 0781 } 0782 0783 attr = attrs.value(QLatin1String("PhotoSize")); 0784 0785 if (!attr.isEmpty()) 0786 { 0787 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << " found " << attr.toString(); 0788 d->settings->savedPhotoSize = attr.toString(); 0789 } 0790 } 0791 0792 xmlReader.readNext(); 0793 } 0794 0795 // reset preview page number 0796 0797 d->settings->currentPreviewPage = 0; 0798 0799 initPhotoSizes(d->printer->pageLayout().pageSize().size(QPageSize::Millimeter)); 0800 0801 QList<QListWidgetItem*> list = d->photoUi->ListPhotoSizes->findItems(d->settings->savedPhotoSize, 0802 Qt::MatchExactly); 0803 0804 if (list.count()) 0805 { 0806 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << " PhotoSize " << list[0]->text(); 0807 d->photoUi->ListPhotoSizes->setCurrentItem(list[0]); 0808 } 0809 else 0810 { 0811 d->photoUi->ListPhotoSizes->setCurrentRow(0); 0812 } 0813 0814 d->wizard->previewPhotos(); 0815 } 0816 0817 void AdvPrintPhotoPage::slotBtnPreviewPageDownClicked() 0818 { 0819 if (d->settings->currentPreviewPage == 0) 0820 { 0821 return; 0822 } 0823 0824 d->settings->currentPreviewPage--; 0825 d->wizard->previewPhotos(); 0826 } 0827 0828 void AdvPrintPhotoPage::slotBtnPreviewPageUpClicked() 0829 { 0830 if (d->settings->currentPreviewPage == getPageCount() - 1) 0831 { 0832 return; 0833 } 0834 0835 d->settings->currentPreviewPage++; 0836 d->wizard->previewPhotos(); 0837 } 0838 0839 int AdvPrintPhotoPage::getPageCount() const 0840 { 0841 int pageCount = 0; 0842 int photoCount = d->settings->photos.count(); 0843 0844 if (photoCount > 0) 0845 { 0846 // get the selected layout 0847 0848 AdvPrintPhotoSize* const s = d->settings->photosizes.at(d->photoUi->ListPhotoSizes->currentRow()); 0849 0850 // how many pages? Recall that the first layout item is the paper size 0851 0852 int photosPerPage = s->m_layouts.count() - 1; 0853 int remainder = photoCount % photosPerPage; 0854 int emptySlots = 0; 0855 0856 if (remainder > 0) 0857 { 0858 emptySlots = photosPerPage - remainder; 0859 } 0860 0861 pageCount = photoCount / photosPerPage; 0862 0863 if (emptySlots > 0) 0864 { 0865 pageCount++; 0866 } 0867 } 0868 0869 return pageCount; 0870 } 0871 0872 void AdvPrintPhotoPage::createPhotoGrid(AdvPrintPhotoSize* const p, 0873 int pageWidth, 0874 int pageHeight, 0875 int rows, 0876 int columns, 0877 TemplateIcon* const iconpreview) 0878 { 0879 // To prevent divide by 0. 0880 0881 if (!columns) columns = 1; 0882 if (!rows) rows = 1; 0883 0884 int MARGIN = (int)(((double)pageWidth + (double)pageHeight) / 2.0 * 0.04 + 0.5); 0885 int GAP = MARGIN / 4; 0886 int photoWidth = (pageWidth - (MARGIN * 2) - ((columns - 1) * GAP)) / columns; 0887 int photoHeight = (pageHeight - (MARGIN * 2) - ((rows - 1) * GAP)) / rows; 0888 int row = 0; 0889 0890 for (int y = MARGIN ; 0891 (row < rows) && (y < (pageHeight - MARGIN)) ; 0892 y += (photoHeight + GAP)) 0893 { 0894 int col = 0; 0895 0896 for (int x = MARGIN ; 0897 (col < columns) && (x < (pageWidth - MARGIN)) ; 0898 x += (photoWidth + GAP)) 0899 { 0900 p->m_layouts.append(new QRect(x, y, photoWidth, photoHeight)); 0901 iconpreview->fillRect(x, y, photoWidth, photoHeight, Qt::color1); 0902 ++col; 0903 } 0904 0905 ++row; 0906 } 0907 } 0908 0909 void AdvPrintPhotoPage::slotListPhotoSizesSelected() 0910 { 0911 AdvPrintPhotoSize* s = nullptr; 0912 QSizeF size, sizeManaged; 0913 0914 // TODO FREE STYLE 0915 // check if layout is managed by templates or free one 0916 // get the selected layout 0917 0918 int curr = d->photoUi->ListPhotoSizes->currentRow(); 0919 QListWidgetItem* item = d->photoUi->ListPhotoSizes->item(curr); 0920 0921 // if custom page layout we launch a dialog to choose what kind 0922 0923 #if KI18N_VERSION >= QT_VERSION_CHECK(5, 89, 0) 0924 0925 if (item->text() == CUSTOM_PAGE_LAYOUT_NAME.title.toString()) 0926 0927 #else 0928 0929 if (item->text() == i18nc(CUSTOM_PAGE_LAYOUT_NAME.context, CUSTOM_PAGE_LAYOUT_NAME.title)) 0930 0931 #endif 0932 0933 { 0934 // check if a custom layout has already been added 0935 0936 if ((curr >= 0) && (curr < d->settings->photosizes.size())) 0937 { 0938 s = d->settings->photosizes.at(curr); 0939 d->settings->photosizes.removeAt(curr); 0940 delete s; 0941 s = nullptr; 0942 } 0943 0944 QPointer<AdvPrintCustomLayoutDlg> custDlg = new AdvPrintCustomLayoutDlg(this); 0945 custDlg->readSettings(); 0946 custDlg->exec(); 0947 custDlg->saveSettings(); 0948 0949 // get parameters from dialog 0950 0951 size = d->settings->pageSize; 0952 int scaleValue = 10; // 0.1 mm 0953 0954 // convert to mm 0955 0956 if (custDlg->m_photoUnits->currentText() == i18n("inches")) 0957 { 0958 size /= 25.4; 0959 scaleValue = 1000; 0960 } 0961 else if (custDlg->m_photoUnits->currentText() == i18n("cm")) 0962 { 0963 size /= 10; 0964 scaleValue = 100; 0965 } 0966 0967 sizeManaged = size * scaleValue; 0968 s = new AdvPrintPhotoSize; 0969 TemplateIcon iconpreview(80, sizeManaged.toSize()); 0970 iconpreview.begin(); 0971 0972 if (custDlg->m_photoGridCheck->isChecked()) 0973 { 0974 // custom photo grid 0975 0976 int rows = custDlg->m_gridRows->value(); 0977 int columns = custDlg->m_gridColumns->value(); 0978 0979 s->m_layouts.append(new QRect(0, 0, 0980 (int)sizeManaged.width(), 0981 (int)sizeManaged.height())); 0982 s->m_autoRotate = custDlg->m_autorotate->isChecked(); 0983 s->m_label = item->text(); 0984 s->m_dpi = 0; 0985 0986 int pageWidth = (int)(size.width()) * scaleValue; 0987 int pageHeight = (int)(size.height()) * scaleValue; 0988 createPhotoGrid(s, pageWidth, pageHeight, 0989 rows, columns, &iconpreview); 0990 } 0991 else if (custDlg->m_fitAsManyCheck->isChecked()) 0992 { 0993 double width = custDlg->m_photoWidth->value(); 0994 double height = custDlg->m_photoHeight->value(); 0995 0996 //photo size must be less than page size 0997 0998 static const float round_value = 0.01F; 0999 1000 if (((height > (size.height() + round_value)) || 1001 (width > (size.width() + round_value)))) 1002 { 1003 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "photo size " 1004 << QSizeF(width, height) 1005 << "> page size " 1006 << size; 1007 delete s; 1008 s = nullptr; 1009 } 1010 else 1011 { 1012 // fit as many photos of given size as possible 1013 1014 s->m_layouts.append(new QRect(0, 0, (int)sizeManaged.width(), 1015 (int)sizeManaged.height())); 1016 s->m_autoRotate = custDlg->m_autorotate->isChecked(); 1017 s->m_label = item->text(); 1018 s->m_dpi = 0; 1019 int nColumns = int(size.width() / width); 1020 int nRows = int(size.height() / height); 1021 double spareWidth = int(size.width() * scaleValue) % int(width * scaleValue); 1022 spareWidth /= scaleValue; 1023 1024 // check if there's no room left to separate photos 1025 1026 if ((nColumns > 1) && (spareWidth == 0.0)) 1027 { 1028 nColumns -= 1; 1029 spareWidth = width; 1030 } 1031 1032 double spareHeight = int(size.height() * scaleValue) % int(height * scaleValue); 1033 spareHeight /= scaleValue; 1034 1035 // check if there's no room left to separate photos 1036 1037 if ((nRows > 1) && (spareHeight == 0.0)) 1038 { 1039 nRows -= 1; 1040 spareHeight = height; 1041 } 1042 1043 if ((nRows > 0) && (nColumns > 0)) 1044 { 1045 // n photos => dx1, photo1, dx2, photo2,... photoN, dxN+1 1046 1047 int dx = spareWidth * scaleValue / (nColumns + 1); 1048 int dy = spareHeight * scaleValue / (nRows + 1); 1049 int photoX = 0; 1050 int photoY = 0; 1051 width *= scaleValue; 1052 height *= scaleValue; 1053 1054 for (int row = 0 ; row < nRows ; ++row) 1055 { 1056 photoY = dy * (row + 1) + (row * height); 1057 1058 for (int col = 0 ; col < nColumns ; ++col) 1059 { 1060 photoX = dx * (col + 1) + (col * width); 1061 1062 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "photo at P(" 1063 << photoX 1064 << ", " 1065 << photoY 1066 << ") size(" 1067 << width 1068 << ", " 1069 << height; 1070 1071 s->m_layouts.append(new QRect(photoX, photoY, 1072 width, height)); 1073 iconpreview.fillRect(photoX, photoY, 1074 width, height, Qt::color1); 1075 } 1076 } 1077 } 1078 else 1079 { 1080 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "I cannot go on, rows " 1081 << nRows 1082 << "> columns " 1083 << nColumns; 1084 delete s; 1085 s = nullptr; 1086 } 1087 } 1088 } 1089 else 1090 { 1091 // Atckin's layout 1092 } 1093 1094 // TODO not for Atckin's layout 1095 1096 iconpreview.end(); 1097 1098 if (s) 1099 { 1100 s->m_icon = iconpreview.getIcon(); 1101 d->settings->photosizes.append(s); 1102 } 1103 1104 delete custDlg; 1105 } 1106 else 1107 { 1108 s = d->settings->photosizes.at(curr); 1109 } 1110 1111 // reset preview page number 1112 1113 d->settings->currentPreviewPage = 0; 1114 1115 if (!s) 1116 { 1117 QMessageBox::warning(this, i18nc("@title:window", "Custom Layout"), 1118 i18n("The selected custom photo size can " 1119 "not be applied to the paper size.")); 1120 1121 // change position to top 1122 1123 d->photoUi->ListPhotoSizes->setCurrentRow(0); 1124 } 1125 1126 d->wizard->previewPhotos(); 1127 } 1128 1129 void AdvPrintPhotoPage::slotPageSetup() 1130 { 1131 delete d->pageSetupDlg; 1132 QString lastSize = d->photoUi->ListPhotoSizes->currentItem()->text(); 1133 d->pageSetupDlg = new QPageSetupDialog(d->printer, this); 1134 int ret = d->pageSetupDlg->exec(); 1135 1136 if (ret == QDialog::Accepted) 1137 { 1138 QPrinter* const printer = d->pageSetupDlg->printer(); 1139 1140 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Dialog exit, new size " 1141 << printer->pageLayout().pageSize().size(QPageSize::Millimeter) 1142 << " internal size " 1143 << d->printer->pageLayout().pageSize().size(QPageSize::Millimeter); 1144 1145 qreal left, top, right, bottom; 1146 auto margins = d->printer->pageLayout().margins(QPageLayout::Millimeter); 1147 left = margins.left(); 1148 top = margins.top(); 1149 right = margins.right(); 1150 bottom = margins.bottom(); 1151 1152 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Dialog exit, new margins: left " 1153 << left 1154 << " right " 1155 << right 1156 << " top " 1157 << top 1158 << " bottom " 1159 << bottom; 1160 1161 // next should be useless invoke once changing wizard page 1162 /* 1163 d->wizard->initPhotoSizes(d->printer.paperSize(QPrinter::Millimeter)); 1164 1165 d->settings->pageSize = d->printer.paperSize(QPrinter::Millimeter); 1166 */ 1167 1168 #ifdef DEBUG 1169 1170 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << " dialog exited num of copies: " 1171 << printer->numCopies() 1172 << " inside: " 1173 << d->printer->numCopies(); 1174 1175 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << " dialog exited from : " 1176 << printer->fromPage() 1177 << " to: " 1178 << d->printer->toPage(); 1179 #endif 1180 } 1181 1182 // Fix the page size dialog and preview PhotoPage 1183 1184 initPhotoSizes(d->printer->pageLayout().pageSize().size(QPageSize::Millimeter)); 1185 1186 // restore photoSize 1187 1188 #if KI18N_VERSION >= QT_VERSION_CHECK(5, 89, 0) 1189 1190 if (lastSize == CUSTOM_PAGE_LAYOUT_NAME.title.toString()) 1191 1192 #else 1193 1194 if (lastSize == i18nc(CUSTOM_PAGE_LAYOUT_NAME.context, CUSTOM_PAGE_LAYOUT_NAME.title)) 1195 1196 #endif 1197 1198 { 1199 d->photoUi->ListPhotoSizes->setCurrentRow(0); 1200 } 1201 else 1202 { 1203 QList<QListWidgetItem*> list = 1204 d->photoUi->ListPhotoSizes->findItems(lastSize, Qt::MatchExactly); 1205 1206 if (list.count()) 1207 { 1208 d->photoUi->ListPhotoSizes->setCurrentItem(list[0]); 1209 } 1210 else 1211 { 1212 d->photoUi->ListPhotoSizes->setCurrentRow(0); 1213 } 1214 } 1215 1216 // create our photo sizes list 1217 1218 d->wizard->previewPhotos(); 1219 } 1220 1221 void AdvPrintPhotoPage::manageBtnPreviewPage() 1222 { 1223 if (d->settings->photos.isEmpty()) 1224 { 1225 d->photoUi->BtnPreviewPageDown->setEnabled(false); 1226 d->photoUi->BtnPreviewPageUp->setEnabled(false); 1227 } 1228 else 1229 { 1230 d->photoUi->BtnPreviewPageDown->setEnabled(true); 1231 d->photoUi->BtnPreviewPageUp->setEnabled(true); 1232 1233 if (d->settings->currentPreviewPage == 0) 1234 { 1235 d->photoUi->BtnPreviewPageDown->setEnabled(false); 1236 } 1237 1238 if ((d->settings->currentPreviewPage + 1) == getPageCount()) 1239 { 1240 d->photoUi->BtnPreviewPageUp->setEnabled(false); 1241 } 1242 } 1243 } 1244 1245 void AdvPrintPhotoPage::initPhotoSizes(const QSizeF& pageSize) 1246 { 1247 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "New page size " 1248 << pageSize 1249 << ", old page size " 1250 << d->settings->pageSize; 1251 1252 // don't refresh anything if we haven't changed page sizes. 1253 1254 if (pageSize == d->settings->pageSize) 1255 { 1256 return; 1257 } 1258 1259 d->settings->pageSize = pageSize; 1260 1261 // cleaning pageSize memory before invoking clear() 1262 1263 for (int i = 0 ; i < d->settings->photosizes.count() ; ++i) 1264 { 1265 delete d->settings->photosizes.at(i); 1266 } 1267 1268 d->settings->photosizes.clear(); 1269 1270 // get template-files and parse them 1271 1272 QDir dir(QStandardPaths::locate(QStandardPaths::GenericDataLocation, 1273 QLatin1String("digikam/templates"), 1274 QStandardPaths::LocateDirectory)); 1275 const QStringList list = dir.entryList(QStringList() << QLatin1String("*.xml")); 1276 1277 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Template XML files list: " 1278 << list; 1279 1280 Q_FOREACH (const QString& fn, list) 1281 { 1282 parseTemplateFile(dir.absolutePath() + QLatin1Char('/') + fn, pageSize); 1283 } 1284 1285 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "photosizes count() =" 1286 << d->settings->photosizes.count(); 1287 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "photosizes isEmpty() =" 1288 << d->settings->photosizes.isEmpty(); 1289 1290 if (d->settings->photosizes.isEmpty()) 1291 { 1292 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Empty photoSize-list, create default size"; 1293 1294 // There is no valid page size yet. Create a default page (B10) to prevent crashes. 1295 1296 AdvPrintPhotoSize* const p = new AdvPrintPhotoSize; 1297 1298 // page size: B10 (32 x 45 mm) 1299 1300 p->m_layouts.append(new QRect(0, 0, 3200, 4500)); 1301 p->m_layouts.append(new QRect(0, 0, 3200, 4500)); 1302 1303 // add to the list 1304 1305 d->settings->photosizes.append(p); 1306 } 1307 1308 // load the photo sizes into the listbox 1309 1310 d->photoUi->ListPhotoSizes->blockSignals(true); 1311 d->photoUi->ListPhotoSizes->clear(); 1312 QList<AdvPrintPhotoSize*>::iterator it; 1313 1314 for (it = d->settings->photosizes.begin() ; 1315 it != d->settings->photosizes.end() ; ++it) 1316 { 1317 AdvPrintPhotoSize* const s = static_cast<AdvPrintPhotoSize*>(*it); 1318 1319 if (s) 1320 { 1321 QListWidgetItem* const pWItem = new QListWidgetItem(s->m_label); 1322 pWItem->setIcon(s->m_icon); 1323 d->photoUi->ListPhotoSizes->addItem(pWItem); 1324 } 1325 } 1326 1327 // Adding custom choice 1328 1329 #if KI18N_VERSION >= QT_VERSION_CHECK(5, 89, 0) 1330 1331 QListWidgetItem* const pWItem = new QListWidgetItem(CUSTOM_PAGE_LAYOUT_NAME.title.toString()); 1332 1333 #else 1334 1335 QListWidgetItem* const pWItem = new QListWidgetItem(i18nc(CUSTOM_PAGE_LAYOUT_NAME.context, CUSTOM_PAGE_LAYOUT_NAME.title)); 1336 1337 #endif 1338 1339 TemplateIcon ti(80, pageSize.toSize()); 1340 ti.begin(); 1341 QPainter& painter = ti.getPainter(); 1342 painter.setPen(Qt::color1); 1343 painter.drawText(painter.viewport(), Qt::AlignCenter, i18n("Custom\nlayout")); 1344 ti.end(); 1345 1346 pWItem->setIcon(ti.getIcon()); 1347 d->photoUi->ListPhotoSizes->addItem(pWItem); 1348 d->photoUi->ListPhotoSizes->blockSignals(false); 1349 d->photoUi->ListPhotoSizes->setCurrentRow(0, QItemSelectionModel::Select); 1350 } 1351 1352 void AdvPrintPhotoPage::parseTemplateFile(const QString& fn, const QSizeF& pageSize) 1353 { 1354 QDomDocument doc(QLatin1String("mydocument")); 1355 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << " XXX: " << fn; 1356 1357 if (fn.isEmpty()) 1358 { 1359 return; 1360 } 1361 1362 QFile file(fn); 1363 1364 if (!file.open(QIODevice::ReadOnly)) 1365 { 1366 return; 1367 } 1368 1369 if (!doc.setContent(&file)) 1370 { 1371 file.close(); 1372 return; 1373 } 1374 1375 file.close(); 1376 1377 AdvPrintPhotoSize* p = nullptr; 1378 1379 // print out the element names of all elements that are direct children 1380 // of the outermost element. 1381 1382 QDomElement docElem = doc.documentElement(); 1383 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << docElem.tagName(); // the node really is an element. 1384 1385 QSizeF size; 1386 QString unit; 1387 int scaleValue; 1388 QDomNode n = docElem.firstChild(); 1389 1390 while (!n.isNull()) 1391 { 1392 size = QSizeF(0, 0); 1393 scaleValue = 10; // 0.1 mm 1394 QDomElement e = n.toElement(); // try to convert the node to an element. 1395 1396 if (!e.isNull()) 1397 { 1398 if (e.tagName() == QLatin1String("paper")) 1399 { 1400 size = QSizeF(e.attribute(QLatin1String("width"), 1401 QLatin1String("0")).toFloat(), 1402 e.attribute(QLatin1String("height"), 1403 QLatin1String("0")).toFloat()); 1404 unit = e.attribute(QLatin1String("unit"), 1405 QLatin1String("mm")); 1406 1407 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << e.tagName() 1408 << QLatin1String(" name=") 1409 << e.attribute(QLatin1String("name"), 1410 QLatin1String("??")) 1411 << " size= " << size 1412 << " unit= " << unit; 1413 1414 if ((size == QSizeF(0.0, 0.0)) && (size == pageSize)) 1415 { 1416 // skipping templates without page size since pageSize is not set 1417 1418 n = n.nextSibling(); 1419 continue; 1420 } 1421 else if (unit != QLatin1String("mm") && 1422 size != QSizeF(0.0, 0.0)) // "cm", "inches" or "inch" 1423 { 1424 // convert to mm 1425 1426 if ((unit == QLatin1String("inches")) || 1427 (unit == QLatin1String("inch"))) 1428 { 1429 size *= 25.4; 1430 scaleValue = 1000; 1431 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "template size " 1432 << size 1433 << " page size " 1434 << pageSize; 1435 } 1436 else if (unit == QLatin1String("cm")) 1437 { 1438 size *= 10; 1439 scaleValue = 100; 1440 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "template size " 1441 << size 1442 << " page size " 1443 << pageSize; 1444 } 1445 else 1446 { 1447 qCWarning(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Wrong unit " 1448 << unit 1449 << " skipping layout"; 1450 n = n.nextSibling(); 1451 continue; 1452 } 1453 } 1454 1455 static const float round_value = 0.01F; 1456 1457 if (size == QSizeF(0, 0)) 1458 { 1459 size = pageSize; 1460 unit = QLatin1String("mm"); 1461 } 1462 else if ((pageSize != QSizeF(0, 0)) && 1463 ((size.height() > (pageSize.height() + round_value)) || 1464 (size.width() > (pageSize.width() + round_value)))) 1465 { 1466 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "skipping size " 1467 << size 1468 << " page size " 1469 << pageSize; 1470 // skipping layout it can't fit 1471 1472 n = n.nextSibling(); 1473 continue; 1474 } 1475 1476 // Next templates are good 1477 1478 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "layout size " 1479 << size 1480 << " page size " 1481 << pageSize; 1482 QDomNode np = e.firstChild(); 1483 1484 while (!np.isNull()) 1485 { 1486 QDomElement ep = np.toElement(); // try to convert the node to an element. 1487 1488 if (!ep.isNull()) 1489 { 1490 if (ep.tagName() == QLatin1String("template")) 1491 { 1492 p = new AdvPrintPhotoSize; 1493 QSizeF sizeManaged; 1494 1495 // set page size 1496 1497 if (pageSize == QSizeF(0, 0)) 1498 { 1499 sizeManaged = size * scaleValue; 1500 } 1501 else if ((unit == QLatin1String("inches")) || 1502 (unit == QLatin1String("inch"))) 1503 { 1504 sizeManaged = pageSize * scaleValue / 25.4; 1505 } 1506 else 1507 { 1508 sizeManaged = pageSize * 10; 1509 } 1510 1511 p->m_layouts.append(new QRect(0, 1512 0, 1513 (int)sizeManaged.width(), 1514 (int)sizeManaged.height())); 1515 1516 // create a small preview of the template 1517 1518 TemplateIcon iconpreview(80, sizeManaged.toSize()); 1519 iconpreview.begin(); 1520 1521 QString desktopFileName = ep.attribute(QLatin1String("name"), 1522 QLatin1String("XXX")) + 1523 QLatin1String(".desktop"); 1524 1525 QDir dir(QStandardPaths::locate(QStandardPaths::GenericDataLocation, 1526 QLatin1String("digikam/templates"), 1527 QStandardPaths::LocateDirectory)); 1528 const QStringList list = dir.entryList(QStringList() 1529 << desktopFileName); 1530 1531 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Template desktop files list: " 1532 << list; 1533 1534 QStringList::ConstIterator it = list.constBegin(); 1535 QStringList::ConstIterator end = list.constEnd(); 1536 1537 if (it != end) 1538 { 1539 p->m_label = KDesktopFile(dir.absolutePath() + 1540 QLatin1Char('/') + *it).readName(); 1541 } 1542 else 1543 { 1544 p->m_label = ep.attribute(QLatin1String("name"), QLatin1String("XXX")); 1545 qCWarning(DIGIKAM_DPLUGIN_GENERIC_LOG) << "missed template translation " 1546 << desktopFileName; 1547 } 1548 1549 p->m_dpi = ep.attribute(QLatin1String("dpi"), 1550 QLatin1String("0")).toInt(); 1551 p->m_autoRotate = (ep.attribute(QLatin1String("autorotate"), 1552 QLatin1String("false")) == QLatin1String("true")) ? 1553 true : false; 1554 QDomNode nt = ep.firstChild(); 1555 1556 while (!nt.isNull()) 1557 { 1558 QDomElement et = nt.toElement(); // try to convert the node to an element. 1559 1560 if (!et.isNull()) 1561 { 1562 if (et.tagName() == QLatin1String("photo")) 1563 { 1564 float value = et.attribute(QLatin1String("width"), 1565 QLatin1String("0")).toFloat(); 1566 int width = (int)((value == 0 ? size.width() : value) * 1567 scaleValue); 1568 value = et.attribute(QLatin1String("height"), 1569 QLatin1String("0")).toFloat(); 1570 int height = (int)((value == 0 ? size.height() : value) * 1571 scaleValue); 1572 int photoX = (int)((et.attribute(QLatin1String("x"), 1573 QLatin1String("0")).toFloat() * scaleValue)); 1574 int photoY = (int)((et.attribute(QLatin1String("y"), 1575 QLatin1String("0")).toFloat() * scaleValue)); 1576 1577 p->m_layouts.append(new QRect(photoX, 1578 photoY, 1579 width, 1580 height)); 1581 iconpreview.fillRect(photoX, 1582 photoY, 1583 width, 1584 height, 1585 Qt::color1); 1586 } 1587 else if (et.tagName() == QLatin1String("photogrid")) 1588 { 1589 float value = et.attribute(QLatin1String("pageWidth"), 1590 QLatin1String("0")).toFloat(); 1591 int pageWidth = (int)((value == 0 ? size.width() : value) * 1592 scaleValue); 1593 value = et.attribute(QLatin1String("pageHeight"), 1594 QLatin1String("0")).toFloat(); 1595 int pageHeight = (int)((value == 0 ? size.height() : value) * 1596 scaleValue); 1597 int rows = et.attribute(QLatin1String("rows"), 1598 QLatin1String("0")).toInt(); 1599 int columns = et.attribute(QLatin1String("columns"), 1600 QLatin1String("0")).toInt(); 1601 1602 if (rows > 0 && columns > 0) 1603 { 1604 createPhotoGrid(p, 1605 pageWidth, 1606 pageHeight, 1607 rows, 1608 columns, 1609 &iconpreview); 1610 } 1611 else 1612 { 1613 qCWarning(DIGIKAM_DPLUGIN_GENERIC_LOG) 1614 << " Wrong grid configuration, rows " 1615 << rows 1616 << ", columns " 1617 << columns; 1618 } 1619 } 1620 else 1621 { 1622 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << " " 1623 << et.tagName(); 1624 } 1625 } 1626 1627 nt = nt.nextSibling(); 1628 } 1629 1630 iconpreview.end(); 1631 p->m_icon = iconpreview.getIcon(); 1632 d->settings->photosizes.append(p); 1633 } 1634 else 1635 { 1636 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "? " 1637 << ep.tagName() 1638 << " attr=" 1639 << ep.attribute(QLatin1String("name"), 1640 QLatin1String("??")); 1641 } 1642 } 1643 1644 np = np.nextSibling(); 1645 } 1646 } 1647 else 1648 { 1649 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "??" 1650 << e.tagName() 1651 << " name=" 1652 << e.attribute(QLatin1String("name"), QLatin1String("??")); 1653 } 1654 } 1655 1656 n = n.nextSibling(); 1657 } 1658 } 1659 1660 } // namespace DigikamGenericPrintCreatorPlugin 1661 1662 #include "moc_advprintphotopage.cpp"