File indexing completed on 2025-01-05 03:53:15
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2008-01-11 0007 * Description : a tool to print images 0008 * 0009 * SPDX-FileCopyrightText: 2008-2012 by Angelo Naselli <anaselli at linux dot it> 0010 * SPDX-FileCopyrightText: 2006-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0011 * 0012 * SPDX-License-Identifier: GPL-2.0-or-later 0013 * 0014 * ============================================================ */ 0015 0016 #include "advprintwizard.h" 0017 0018 // C++ includes 0019 0020 #include <memory> 0021 0022 // Qt includes 0023 0024 #include <QFileInfo> 0025 #include <QPalette> 0026 #include <QtGlobal> 0027 #include <QDomDocument> 0028 #include <QContextMenuEvent> 0029 #include <QStringView> 0030 #include <QStandardPaths> 0031 #include <QMenu> 0032 #include <QIcon> 0033 #include <QLocale> 0034 #include <QTemporaryDir> 0035 #include <QKeyEvent> 0036 0037 // KDE includes 0038 0039 #include <klocalizedstring.h> 0040 #include <ksharedconfig.h> 0041 #include <kconfiggroup.h> 0042 0043 // Local includes 0044 0045 #include "digikam_globals.h" 0046 #include "digikam_debug.h" 0047 #include "advprintthread.h" 0048 #include "advprintintropage.h" 0049 #include "advprintalbumspage.h" 0050 #include "advprintphotopage.h" 0051 #include "advprintcaptionpage.h" 0052 #include "advprintcroppage.h" 0053 #include "advprintoutputpage.h" 0054 #include "advprintfinalpage.h" 0055 #include "templateicon.h" 0056 #include "dwizardpage.h" 0057 #include "dfiledialog.h" 0058 #include "dmetadata.h" 0059 0060 namespace DigikamGenericPrintCreatorPlugin 0061 { 0062 0063 class Q_DECL_HIDDEN AdvPrintWizard::Private 0064 { 0065 public: 0066 0067 explicit Private() 0068 : introPage (nullptr), 0069 albumsPage (nullptr), 0070 photoPage (nullptr), 0071 captionPage (nullptr), 0072 cropPage (nullptr), 0073 outputPage (nullptr), 0074 finalPage (nullptr), 0075 settings (nullptr), 0076 previewThread(nullptr), 0077 iface (nullptr), 0078 tempPath (nullptr) 0079 { 0080 } 0081 0082 AdvPrintIntroPage* introPage; 0083 AdvPrintAlbumsPage* albumsPage; 0084 AdvPrintPhotoPage* photoPage; 0085 AdvPrintCaptionPage* captionPage; 0086 AdvPrintCropPage* cropPage; 0087 AdvPrintOutputPage* outputPage; 0088 AdvPrintFinalPage* finalPage; 0089 AdvPrintSettings* settings; 0090 AdvPrintThread* previewThread; 0091 DInfoInterface* iface; 0092 0093 QTemporaryDir* tempPath; 0094 }; 0095 0096 AdvPrintWizard::AdvPrintWizard(QWidget* const parent, DInfoInterface* const iface) 0097 : DWizardDlg(parent, QLatin1String("PrintCreatorDialog")), 0098 d (new Private) 0099 { 0100 setWindowTitle(i18nc("@title:window", "Print Creator")); 0101 0102 d->iface = iface; 0103 d->settings = new AdvPrintSettings; 0104 d->previewThread = new AdvPrintThread(this); 0105 0106 KSharedConfigPtr config = KSharedConfig::openConfig(); 0107 KConfigGroup group = config->group(QLatin1String("PrintCreator")); 0108 d->settings->readSettings(group); 0109 0110 d->introPage = new AdvPrintIntroPage(this, i18n("Welcome to Print Creator")); 0111 d->albumsPage = new AdvPrintAlbumsPage(this, i18n("Albums Selection")); 0112 d->photoPage = new AdvPrintPhotoPage(this, i18n("Select Page Layout")); 0113 d->captionPage = new AdvPrintCaptionPage(this, i18n("Caption Settings")); 0114 d->cropPage = new AdvPrintCropPage(this, i18n("Crop and Rotate Photos")); 0115 d->outputPage = new AdvPrintOutputPage(this, i18n("Images Output Settings")); 0116 d->finalPage = new AdvPrintFinalPage(this, i18n("Render Printing")); 0117 d->finalPage->setPhotoPage(d->photoPage); 0118 0119 // ----------------------------------- 0120 0121 connect(button(QWizard::CancelButton), SIGNAL(clicked()), 0122 this, SLOT(reject())); 0123 0124 connect(d->photoPage->imagesList(), SIGNAL(signalImageListChanged()), 0125 d->captionPage, SLOT(slotUpdateImagesList())); 0126 0127 connect(d->previewThread, SIGNAL(signalPreview(QImage)), 0128 this, SLOT(slotPreview(QImage))); 0129 0130 d->tempPath = new QTemporaryDir(); 0131 d->settings->tempPath = d->tempPath->path(); 0132 0133 installEventFilter(this); 0134 } 0135 0136 AdvPrintWizard::~AdvPrintWizard() 0137 { 0138 d->previewThread->cancel(); 0139 0140 KSharedConfigPtr config = KSharedConfig::openConfig(); 0141 KConfigGroup group = config->group(QLatin1String("PrintCreator")); 0142 d->settings->writeSettings(group); 0143 0144 delete d->settings; 0145 delete d->tempPath; 0146 delete d; 0147 } 0148 0149 DInfoInterface* AdvPrintWizard::iface() const 0150 { 0151 return d->iface; 0152 } 0153 0154 AdvPrintSettings* AdvPrintWizard::settings() const 0155 { 0156 return d->settings; 0157 } 0158 0159 int AdvPrintWizard::nextId() const 0160 { 0161 if (d->settings->selMode == AdvPrintSettings::ALBUMS) 0162 { 0163 if (currentPage() == d->introPage) 0164 { 0165 return d->albumsPage->id(); 0166 } 0167 } 0168 else 0169 { 0170 if (currentPage() == d->introPage) 0171 { 0172 return d->photoPage->id(); 0173 } 0174 } 0175 0176 if (d->settings->printerName == d->settings->outputName(AdvPrintSettings::FILES)) 0177 { 0178 if (currentPage() == d->cropPage) 0179 { 0180 return d->outputPage->id(); 0181 } 0182 } 0183 else 0184 { 0185 if (currentPage() == d->cropPage) 0186 { 0187 return d->finalPage->id(); 0188 } 0189 } 0190 0191 return DWizardDlg::nextId(); 0192 } 0193 0194 QList<QUrl> AdvPrintWizard::itemsList() const 0195 { 0196 QList<QUrl> urls; 0197 0198 for (QList<AdvPrintPhoto*>::iterator it = d->settings->photos.begin() ; 0199 it != d->settings->photos.end() ; ++it) 0200 { 0201 AdvPrintPhoto* const photo = static_cast<AdvPrintPhoto*>(*it); 0202 urls << photo->m_url; 0203 } 0204 0205 return urls; 0206 } 0207 0208 void AdvPrintWizard::setItemsList(const QList<QUrl>& fileList) 0209 { 0210 QList<QUrl> list = fileList; 0211 0212 for (int i = 0 ; i < d->settings->photos.count() ; ++i) 0213 { 0214 delete d->settings->photos.at(i); 0215 } 0216 0217 d->settings->photos.clear(); 0218 0219 if (list.isEmpty() && d->iface) 0220 { 0221 list = d->iface->currentSelectedItems(); 0222 } 0223 0224 for (int i = 0 ; i < list.count() ; ++i) 0225 { 0226 AdvPrintPhoto* const photo = new AdvPrintPhoto(150, d->iface); 0227 photo->m_url = list[i]; 0228 photo->m_first = true; 0229 d->settings->photos.append(photo); 0230 } 0231 0232 d->cropPage->ui()->BtnCropPrev->setEnabled(false); 0233 0234 if (d->settings->photos.count() == 1) 0235 { 0236 d->cropPage->ui()->BtnCropNext->setEnabled(false); 0237 } 0238 0239 Q_EMIT currentIdChanged(d->photoPage->id()); 0240 } 0241 0242 void AdvPrintWizard::updateCropFrame(AdvPrintPhoto* const photo, int photoIndex) 0243 { 0244 int sizeIndex = d->photoPage->ui()->ListPhotoSizes->currentRow(); 0245 AdvPrintPhotoSize* const s = d->settings->photosizes.at(sizeIndex); 0246 0247 d->cropPage->ui()->cropFrame->init(photo, 0248 d->settings->getLayout(photoIndex, sizeIndex)->width(), 0249 d->settings->getLayout(photoIndex, sizeIndex)->height(), 0250 s->m_autoRotate, 0251 true); 0252 0253 d->cropPage->ui()->LblCropPhoto->setText(i18n("Photo %1 of %2", 0254 photoIndex + 1, 0255 d->settings->photos.count())); 0256 } 0257 0258 void AdvPrintWizard::previewPhotos() 0259 { 0260 if (d->settings->photosizes.isEmpty()) 0261 { 0262 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Photo sizes is null"; 0263 return; 0264 } 0265 0266 // get the selected layout 0267 0268 int photoCount = d->settings->photos.count(); 0269 int curr1 = d->photoPage->ui()->ListPhotoSizes->currentRow(); 0270 AdvPrintPhotoSize* const s = d->settings->photosizes.at(curr1); 0271 int emptySlots = 0; 0272 int pageCount = 0; 0273 int photosPerPage = 0; 0274 0275 if (photoCount > 0) 0276 { 0277 // how many pages? Recall that the first layout item is the paper size 0278 0279 photosPerPage = s->m_layouts.count() - 1; 0280 int remainder = photoCount % photosPerPage; 0281 0282 if (remainder > 0) 0283 { 0284 emptySlots = photosPerPage - remainder; 0285 } 0286 0287 pageCount = photoCount / photosPerPage; 0288 0289 if (emptySlots > 0) 0290 { 0291 pageCount++; 0292 } 0293 } 0294 0295 d->photoPage->ui()->LblPhotoCount->setText(QString::number(photoCount)); 0296 d->photoPage->ui()->LblSheetsPrinted->setText(QString::number(pageCount)); 0297 d->photoPage->ui()->LblEmptySlots->setText(QString::number(emptySlots)); 0298 0299 if (photoCount > 0) 0300 { 0301 // photo previews 0302 // preview the first page. 0303 // find the first page of photos 0304 0305 int page = 0; 0306 int count = 0; 0307 int current = 0; 0308 int currentPage = 0; 0309 0310 for (QList<AdvPrintPhoto*>::iterator it = d->settings->photos.begin() ; 0311 it != d->settings->photos.end() ; ++it) 0312 { 0313 AdvPrintPhoto* const photo = static_cast<AdvPrintPhoto*>(*it); 0314 0315 photo->m_cropRegion.setRect(-1, -1, -1, -1); 0316 photo->m_rotation = 0; 0317 QRect* const curr2 = s->m_layouts.at(count + 1); 0318 photo->updateCropRegion(curr2->width(), 0319 curr2->height(), 0320 s->m_autoRotate); 0321 0322 count++; 0323 0324 if (count >= photosPerPage) 0325 { 0326 if (page == d->settings->currentPreviewPage) 0327 { 0328 currentPage = current; 0329 } 0330 0331 page++; 0332 current += photosPerPage; 0333 count = 0; 0334 } 0335 } 0336 0337 // send this photo list to the painter 0338 0339 AdvPrintSettings* const pwSettings = new AdvPrintSettings; 0340 pwSettings->photos = d->settings->photos; 0341 pwSettings->outputLayouts = s; 0342 pwSettings->currentPreviewPage = currentPage; 0343 pwSettings->disableCrop = d->cropPage->ui()->m_disableCrop->isChecked(); 0344 0345 d->previewThread->preview(pwSettings, d->photoPage->ui()->BmpFirstPagePreview->size()); 0346 d->previewThread->start(); 0347 } 0348 else 0349 { 0350 d->photoPage->ui()->BmpFirstPagePreview->clear(); 0351 d->photoPage->ui()->LblPreview->clear(); 0352 d->photoPage->ui()->LblPreview->setText(i18n("Page %1 of %2", 0, 0)); 0353 d->photoPage->manageBtnPreviewPage(); 0354 d->photoPage->update(); 0355 } 0356 } 0357 0358 void AdvPrintWizard::slotPreview(const QImage& img) 0359 { 0360 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Receive Preview" << img.size(); 0361 0362 d->photoPage->ui()->BmpFirstPagePreview->clear(); 0363 d->photoPage->ui()->BmpFirstPagePreview->setPixmap(QPixmap::fromImage(img)); 0364 d->photoPage->ui()->LblPreview->setText(i18n("Page %1 of %2", 0365 d->settings->currentPreviewPage + 1, 0366 d->photoPage->getPageCount())); 0367 d->photoPage->manageBtnPreviewPage(); 0368 d->photoPage->update(); 0369 } 0370 0371 int AdvPrintWizard::normalizedInt(double n) 0372 { 0373 return (int)(n + 0.5); 0374 } 0375 0376 bool AdvPrintWizard::eventFilter(QObject* o, QEvent* e) 0377 { 0378 if (e && (e->type() == QEvent::KeyRelease)) 0379 { 0380 QKeyEvent* const k = (QKeyEvent*)e; 0381 0382 if ((k->key() == Qt::Key_PageUp) || 0383 (k->key() == Qt::Key_PageDown) || 0384 (k->key() == Qt::Key_Up) || 0385 (k->key() == Qt::Key_Down)) 0386 { 0387 if (currentPage() == d->cropPage) 0388 { 0389 // Pass the key event to move crop frame region. 0390 0391 d->cropPage->ui()->cropFrame->setFocus(); 0392 QApplication::sendEvent(d->cropPage->ui()->cropFrame, e); 0393 0394 return true; // eat event 0395 } 0396 } 0397 } 0398 0399 return QWizard::eventFilter(o, e); 0400 } 0401 0402 } // namespace DigikamGenericPrintCreatorPlugin 0403 0404 #include "moc_advprintwizard.cpp"