File indexing completed on 2025-01-19 03:52:56

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2019-03-27
0007  * Description : a tool to export items to a local storage
0008  *
0009  * SPDX-FileCopyrightText: 2006-2009 by Johannes Wienke <languitar at semipol dot de>
0010  * SPDX-FileCopyrightText: 2011-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0011  * SPDX-FileCopyrightText: 2019-2020 by Maik Qualmann <metzpinguin at gmail dot com>
0012  *
0013  * SPDX-License-Identifier: GPL-2.0-or-later
0014  *
0015  * ============================================================ */
0016 
0017 #include "fcexportwidget.h"
0018 
0019 // Qt includes
0020 
0021 #include <QApplication>
0022 #include <QRadioButton>
0023 #include <QButtonGroup>
0024 #include <QVBoxLayout>
0025 #include <QCheckBox>
0026 #include <QGroupBox>
0027 #include <QComboBox>
0028 #include <QSpinBox>
0029 #include <QLabel>
0030 
0031 // KDE includes
0032 
0033 #include <klocalizedstring.h>
0034 
0035 // Local includes
0036 
0037 #include "digikam_debug.h"
0038 #include "dfileselector.h"
0039 #include "wstoolutils.h"
0040 #include "dlayoutbox.h"
0041 #include "fctask.h"
0042 #include "metaenginesettings.h"
0043 
0044 namespace DigikamGenericFileCopyPlugin
0045 {
0046 
0047 class Q_DECL_HIDDEN FCExportWidget::Private
0048 {
0049 public:
0050 
0051     explicit Private()
0052       : iface               (nullptr),
0053         selector            (nullptr),
0054         imageList           (nullptr),
0055         sidecars            (nullptr),
0056         writeMetadataToFile (nullptr),
0057         overwrite           (nullptr),
0058         albumPath           (nullptr),
0059         targetButtonGroup   (nullptr),
0060         fileCopyButton      (nullptr),
0061         symLinkButton       (nullptr),
0062         relativeButton      (nullptr),
0063         imageChangeGroupBox (nullptr),
0064         changeImagesProp    (nullptr),
0065         removeMetadataProp  (nullptr),
0066         imageCompression    (nullptr),
0067         imageResize         (nullptr),
0068         imageFormat         (nullptr)
0069     {
0070     }
0071 
0072     DInfoInterface* iface;
0073     DFileSelector*  selector;
0074     DItemsList*     imageList;
0075 
0076     QCheckBox*      sidecars;
0077     QCheckBox*      writeMetadataToFile;
0078     QCheckBox*      overwrite;
0079     QCheckBox*      albumPath;
0080 
0081     QButtonGroup*   targetButtonGroup;
0082     QRadioButton*   fileCopyButton;
0083     QRadioButton*   symLinkButton;
0084     QRadioButton*   relativeButton;
0085 
0086     QUrl            targetUrl;
0087 
0088     QGroupBox*      imageChangeGroupBox;
0089     QCheckBox*      changeImagesProp;
0090     QCheckBox*      removeMetadataProp;
0091 
0092     QSpinBox*       imageCompression;
0093     QSpinBox*       imageResize;
0094     QComboBox*      imageFormat;
0095 };
0096 
0097 FCExportWidget::FCExportWidget(DInfoInterface* const iface, QWidget* const parent)
0098     : QWidget(parent),
0099       d      (new Private)
0100 {
0101     d->iface = iface;
0102 
0103     // setup local target selection
0104 
0105     const int spacing           = qMin(QApplication::style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing),
0106                              QApplication::style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing));
0107 
0108     DHBox* const hbox           = new DHBox(this);
0109     QLabel* const locationLabel = new QLabel(hbox);
0110     locationLabel->setText(i18n("Target location: "));
0111     d->selector                 = new DFileSelector(hbox);
0112     d->selector->setFileDlgMode(QFileDialog::Directory);
0113     d->selector->setFileDlgOptions(QFileDialog::ShowDirsOnly);
0114     d->selector->setFileDlgTitle(i18nc("@title:window", "Target Folder"));
0115     d->selector->setWhatsThis(i18n("Sets the target address to copy the items to."));
0116 
0117     QLabel* const targetLabel   = new QLabel(i18n("Target file behavior:"), this);
0118     d->targetButtonGroup        = new QButtonGroup(this);
0119     d->fileCopyButton           = new QRadioButton(i18n("Copy files"), this);
0120     d->symLinkButton            = new QRadioButton(i18n("Create symlinks"), this);
0121     d->relativeButton           = new QRadioButton(i18n("Create relative symlinks"), this);
0122 
0123     d->sidecars                 = new QCheckBox(i18n("Include the sidecar of the items"), this);
0124     d->writeMetadataToFile      = new QCheckBox(i18n("Write sidecar metadata to the items"), this);
0125     d->overwrite                = new QCheckBox(i18n("Overwrite existing items in the target"), this);
0126     d->albumPath                = new QCheckBox(i18n("Use the album path of the items in the target"), this);
0127 
0128     if (!d->iface->supportAlbums())
0129     {
0130         d->albumPath->hide();
0131     }
0132 
0133     if (MetaEngineSettings::instance()->settings().metadataWritingMode != MetaEngine::WRITE_TO_SIDECAR_ONLY)
0134     {
0135         d->writeMetadataToFile->hide();
0136     }
0137 
0138     d->targetButtonGroup->addButton(d->fileCopyButton, FCContainer::CopyFile);
0139     d->targetButtonGroup->addButton(d->symLinkButton,  FCContainer::FullSymLink);
0140     d->targetButtonGroup->addButton(d->relativeButton, FCContainer::RelativeSymLink);
0141     d->targetButtonGroup->setExclusive(true);
0142     d->fileCopyButton->setChecked(true);
0143 
0144     //---------------------------------------------
0145 
0146     d->changeImagesProp = new QCheckBox(i18n("Adjust image properties"), this);
0147     d->changeImagesProp->setChecked(false);
0148     d->changeImagesProp->setWhatsThis(i18n("If you enable this option, "
0149                                            "all images to be sent can be "
0150                                            "resized and recompressed."));
0151 
0152     //---------------------------------------------
0153 
0154     d->imageChangeGroupBox          = new QGroupBox(i18n("Image Properties"), this);
0155 
0156     d->imageResize                  = new QSpinBox(d->imageChangeGroupBox);
0157     d->imageResize->setRange(300, 6000);
0158     d->imageResize->setSingleStep(1);
0159     d->imageResize->setValue(1024);
0160     d->imageResize->setSuffix(i18n(" px"));
0161     d->imageResize->setWhatsThis(i18n("Select the length of the images that are to be sent. "
0162                                        "The aspect ratio is preserved."));
0163     d->imageChangeGroupBox->setEnabled(false);
0164 
0165     QLabel* const  labelImageResize = new QLabel(i18n("Image Length:"), d->imageChangeGroupBox);
0166     labelImageResize->setBuddy(d->imageResize);
0167 
0168     //---------------------------------------------
0169 
0170     QLabel* const labelImageFormat = new QLabel(d->imageChangeGroupBox);
0171     labelImageFormat->setWordWrap(false);
0172     labelImageFormat->setText(i18n("Image Format:"));
0173 
0174     d->imageFormat                 = new QComboBox(d->imageChangeGroupBox);
0175     d->imageFormat->setEditable(false);
0176     d->imageFormat->setWhatsThis(i18n("Select your preferred format to convert image."));
0177     d->imageFormat->addItem(i18nc("Image format: JPEG", "Jpeg"), FCContainer::JPEG);
0178     d->imageFormat->addItem(i18nc("Image format: PNG",  "Png"),  FCContainer::PNG);
0179     labelImageFormat->setBuddy(d->imageFormat);
0180 
0181     //---------------------------------------------
0182 
0183     d->imageCompression                 = new QSpinBox(d->imageChangeGroupBox);
0184     d->imageCompression->setRange(1, 100);
0185     d->imageCompression->setSingleStep(1);
0186     d->imageCompression->setValue(75);
0187     d->imageCompression->setWhatsThis(i18n("<p>The new compression value of JPEG images to be sent:</p>"
0188                                            "<p><b>1</b>: very high compression<br/>"
0189                                            "<b>25</b>: high compression<br/>"
0190                                            "<b>50</b>: medium compression<br/>"
0191                                            "<b>75</b>: low compression (default value)<br/>"
0192                                            "<b>100</b>: no compression</p>"));
0193 
0194     QLabel* const labelImageCompression = new QLabel(i18n("Image quality:"), d->imageChangeGroupBox);
0195     labelImageCompression->setBuddy(d->imageCompression);
0196 
0197     //---------------------------------------------
0198 
0199     d->removeMetadataProp = new QCheckBox(i18n("Remove all metadata"), d->imageChangeGroupBox);
0200     d->removeMetadataProp->setWhatsThis(i18n("If you enable this option, all metadata "
0201                                              "as Exif, Iptc, and Xmp will be removed."));
0202 
0203     //---------------------------------------------
0204 
0205     QGridLayout* const grid2 = new QGridLayout(d->imageChangeGroupBox);
0206     grid2->addWidget(labelImageResize,      0, 0, 1, 1);
0207     grid2->addWidget(d->imageResize,        0, 1, 1, 2);
0208     grid2->addWidget(labelImageFormat,      1, 0, 1, 1);
0209     grid2->addWidget(d->imageFormat,        1, 1, 1, 2);
0210     grid2->addWidget(labelImageCompression, 2, 0, 1, 1);
0211     grid2->addWidget(d->imageCompression,   2, 1, 1, 2);
0212     grid2->addWidget(d->removeMetadataProp, 3, 0, 1, 2);
0213     grid2->setColumnStretch(2, 10);
0214     grid2->setSpacing(spacing);
0215     grid2->setAlignment(Qt::AlignTop);
0216 
0217     //---------------------------------------------
0218 
0219     // setup image list
0220     d->imageList = new DItemsList(this);
0221     d->imageList->setObjectName(QLatin1String("FCExport ImagesList"));
0222     d->imageList->setIface(d->iface);
0223     d->imageList->loadImagesFromCurrentSelection();
0224     d->imageList->setAllowRAW(true);
0225     d->imageList->listView()->setWhatsThis(i18n("This is the list of items to copy "
0226                                                 "to the specified target."));
0227 
0228     // layout dialog
0229     QVBoxLayout* const layout = new QVBoxLayout(this);
0230 
0231     layout->addWidget(hbox);
0232     layout->addWidget(targetLabel);
0233     layout->addWidget(d->fileCopyButton);
0234     layout->addWidget(d->symLinkButton);
0235     layout->addWidget(d->relativeButton);
0236     layout->addWidget(d->sidecars);
0237     layout->addWidget(d->writeMetadataToFile);
0238     layout->addWidget(d->overwrite);
0239     layout->addWidget(d->albumPath);
0240     layout->addWidget(d->imageList);
0241     layout->addWidget(d->changeImagesProp);
0242     layout->addWidget(d->imageChangeGroupBox);
0243     layout->setSpacing(spacing);
0244     layout->setContentsMargins(QMargins());
0245 
0246     // ------------------------------------------------------------------------
0247 
0248     connect(d->selector->lineEdit(), SIGNAL(textEdited(QString)),
0249             this, SLOT(slotLabelUrlChanged()));
0250 
0251     connect(d->selector, SIGNAL(signalUrlSelected(QUrl)),
0252             this, SLOT(slotLabelUrlChanged()));
0253 
0254     connect(d->fileCopyButton, SIGNAL(toggled(bool)),
0255             this, SLOT(slotFileCopyButtonChanged(bool)));
0256 
0257     connect(d->changeImagesProp, SIGNAL(toggled(bool)),
0258             d->imageChangeGroupBox, SLOT(setEnabled(bool)));
0259 
0260 }
0261 
0262 FCExportWidget::~FCExportWidget()
0263 {
0264     delete d;
0265 }
0266 
0267 DItemsList* FCExportWidget::imagesList() const
0268 {
0269     return d->imageList;
0270 }
0271 
0272 QUrl FCExportWidget::targetUrl() const
0273 {
0274     return d->targetUrl;
0275 }
0276 
0277 FCContainer FCExportWidget::getSettings() const
0278 {
0279     FCContainer settings;
0280 
0281     settings.iface                 = d->iface;
0282     settings.destUrl               = d->targetUrl;
0283     settings.behavior              = d->targetButtonGroup->checkedId();
0284     settings.imageFormat           = d->imageFormat->currentIndex();
0285     settings.imageResize           = d->imageResize->value();
0286     settings.imageCompression      = d->imageCompression->value();
0287     settings.sidecars              = d->sidecars->isChecked();
0288     settings.writeMetadataToFile   = d->writeMetadataToFile->isChecked();
0289     settings.overwrite             = d->overwrite->isChecked();
0290     settings.albumPath             = d->albumPath->isChecked();
0291     settings.removeMetadata        = d->removeMetadataProp->isChecked();
0292     settings.changeImageProperties = d->changeImagesProp->isChecked();
0293 
0294     return settings;
0295 }
0296 
0297 void FCExportWidget::setSettings(const FCContainer& settings)
0298 {
0299     d->targetUrl                  = settings.destUrl;
0300     d->selector->setFileDlgPath(d->targetUrl.toLocalFile());
0301     QAbstractButton* const button = d->targetButtonGroup->button(settings.behavior);
0302 
0303     if (button)
0304     {
0305         button->setChecked(true);
0306     }
0307 
0308     d->imageFormat->setCurrentIndex(settings.imageFormat);
0309     d->imageResize->setValue(settings.imageResize);
0310     d->imageCompression->setValue(settings.imageCompression);
0311     d->sidecars->setChecked(settings.sidecars);
0312     d->writeMetadataToFile->setChecked(settings.writeMetadataToFile);
0313     d->overwrite->setChecked(settings.overwrite);
0314     d->albumPath->setChecked(settings.albumPath);
0315     d->removeMetadataProp->setChecked(settings.removeMetadata);
0316     d->changeImagesProp->setChecked(settings.changeImageProperties);
0317 }
0318 
0319 void FCExportWidget::slotLabelUrlChanged()
0320 {
0321     d->targetUrl = QUrl::fromLocalFile(d->selector->fileDlgPath());
0322 
0323     Q_EMIT signalTargetUrlChanged(d->targetUrl);
0324 }
0325 
0326 void FCExportWidget::slotFileCopyButtonChanged(bool enabled)
0327 {
0328     if (!enabled)
0329     {
0330         d->changeImagesProp->setChecked(false);
0331     }
0332 
0333     d->changeImagesProp->setEnabled(enabled);
0334 
0335      // The changeImagesProp is by default and on each change unchecked
0336 
0337     d->imageChangeGroupBox->setEnabled(false);
0338 }
0339 
0340 } // namespace DigikamGenericFileCopyPlugin
0341 
0342 #include "moc_fcexportwidget.cpp"