File indexing completed on 2025-01-19 03:53:04

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2021-03-20
0007  * Description : a tool to export images to iNaturalist web service
0008  *
0009  * SPDX-FileCopyrightText: 2021      by Joerg Lohse <joergmlpts at gmail dot com>
0010  * SPDX-FileCopyrightText: 2005-2008 by Vardhman Jain <vardhman at gmail dot com>
0011  * SPDX-FileCopyrightText: 2008-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0012  * SPDX-FileCopyrightText: 2009      by Luka Renko <lure at kubuntu dot org>
0013  *
0014  * SPDX-License-Identifier: GPL-2.0-or-later
0015  *
0016  * ============================================================ */
0017 
0018 #include "inatwidget_p.h"
0019 
0020 namespace DigikamGenericINatPlugin
0021 {
0022 
0023 const DItemsListView::ColumnType ItemDate     = DItemsListView::ColumnType::User1;
0024 const DItemsListView::ColumnType ItemLocation = DItemsListView::ColumnType::User2;
0025 
0026 INatWidget::INatWidget(QWidget* const parent,
0027                        DInfoInterface* const iface,
0028                        const QString& serviceName)
0029     : WSSettingsWidget(parent, iface, serviceName),
0030       d               (new Private)
0031 {
0032     d->serviceName = serviceName;
0033 
0034     // -- The account group. ----------------------------------------------
0035 
0036     // make room and insert a QLabel for an account icon
0037 
0038     QWidget* const userNameLbl                = getAccountBoxLayout()->itemAt(0)->widget();
0039     getAccountBoxLayout()->removeWidget(userNameLbl);
0040     getAccountBoxLayout()->addWidget(userNameLbl, 0, 0, 1, 1);
0041     d->accountIcon                            = new QLabel(getAccountBox());
0042     getAccountBoxLayout()->addWidget(d->accountIcon, 0, 1, 1, 1);
0043 
0044     // change user and remove account buttons go the in the row
0045 
0046     getAccountBoxLayout()->removeWidget(getChangeUserBtn());
0047     QHBoxLayout* const changeRemoveUserLayout = new QHBoxLayout();
0048     d->removeAccount                          = new QPushButton(getAccountBox());
0049     d->removeAccount->setText(i18n("Remove Account"));
0050     changeRemoveUserLayout->addWidget(getChangeUserBtn());
0051     changeRemoveUserLayout->addWidget(d->removeAccount);
0052     getAccountBoxLayout()->addLayout(changeRemoveUserLayout, 2, 0, 1, -1);
0053 
0054     // -- The image list --------------------------------------------------
0055 
0056     d->imglst = new DItemsList(this);
0057 
0058 
0059     d->imglst->setAllowRAW(true);
0060     d->imglst->setIface(iface);
0061     d->imglst->loadImagesFromCurrentSelection();
0062 
0063     d->imglst->listView()->setWhatsThis(i18n("This is the list of images to "
0064                                         "upload to an iNaturalist observation."));
0065 
0066     d->imglst->listView()->setColumn(ItemDate, i18n("Date"), true);
0067     d->imglst->listView()->setColumn(ItemLocation, i18n("Location"), true);
0068 
0069     // -- The observation group. ------------------------------------------
0070 
0071     QGroupBox* const idBox                  = new QGroupBox(i18n("Observation"), getSettingsBox());
0072     QVBoxLayout* const idBoxLayout          = new QVBoxLayout(idBox);
0073 
0074     d->identificationImage                  = new QLabel(idBox);
0075     d->identificationLabel                  = new QLabel(i18n("<i>no identification</i>"), idBox);
0076     d->identificationLabel->setWordWrap(true);
0077     QHBoxLayout* const identificationLayout = new QHBoxLayout();
0078     identificationLayout->addWidget(d->identificationImage);
0079     identificationLayout->addWidget(d->identificationLabel, 1);
0080     idBoxLayout->addLayout(identificationLayout);
0081 
0082     d->closestKnownObservation              = new QLabel(idBox);
0083     d->closestKnownObservation->setWordWrap(true);
0084     d->closestKnownObservation->setOpenExternalLinks(true);
0085     idBoxLayout->addWidget(d->closestKnownObservation);
0086 
0087     d->observationDescription               = new DPlainTextEdit(0, idBox);
0088     d->observationDescription->setPlaceholderText(i18n("Optionally describe "
0089                                                   "your observation or explain your identification here."));
0090     QTextDocument* const pdoc               = d->observationDescription->document();
0091     QFontMetrics fm(pdoc->defaultFont());
0092     QMargins margins                        = d->observationDescription->contentsMargins();
0093     const int nRows                         = 3;
0094     d->observationDescription->setFixedHeight(nRows * fm.lineSpacing() +
0095                                               2 * (pdoc->documentMargin() +
0096                                               d->observationDescription->frameWidth()) +
0097                                               margins.top() + margins.bottom());
0098     idBoxLayout->addWidget(d->observationDescription);
0099     d->observationDescription->hide();
0100 
0101     d->identificationEdit                   = new TaxonEdit(idBox);
0102     d->identificationEdit->setToolTip(i18n("Enter your identification here, "
0103                                            "popups will guide to a supported "
0104                                            "name."));
0105     d->identificationEdit->setPlaceholderText(i18n("Enter your identification "
0106                                                    "here; it is required."));
0107     d->taxonPopup                           = new SuggestTaxonCompletion(d->identificationEdit);
0108     idBoxLayout->addWidget(d->identificationEdit);
0109 
0110     QLabel* const placeLabel                = new QLabel(i18n("Place:"), idBox);
0111     d->placesComboBox                       = new QComboBox(idBox);
0112     d->placesComboBox->setInsertPolicy(QComboBox::NoInsert);
0113     d->placesComboBox->setEditable(true);
0114     d->moreOptionsButton                    = new QPushButton(i18n("More options"), idBox);
0115     d->moreOptionsButton->setCheckable(true);
0116     d->moreOptionsButton->setChecked(false);
0117     idBoxLayout->addWidget(d->moreOptionsButton);
0118     QHBoxLayout* const placesLayout         = new QHBoxLayout();
0119     placesLayout->addWidget(placeLabel);
0120     placesLayout->addWidget(d->placesComboBox, 1);
0121     placesLayout->addWidget(d->moreOptionsButton);
0122     idBoxLayout->addLayout(placesLayout);
0123 
0124     d->moreOptionsWidget                    = new QWidget(idBox);
0125     QVBoxLayout* const moreOptionsLayout    = new QVBoxLayout(d->moreOptionsWidget);
0126 
0127     QLabel* const warnTimeText1             = new QLabel(i18n("Photos should be taken within"), idBox);
0128     d->photoMaxTimeDiffSpB                  = new QSpinBox(idBox);
0129     d->photoMaxTimeDiffSpB->setMinimum(1);
0130     d->photoMaxTimeDiffSpB->setMaximum(9999);
0131     d->photoMaxTimeDiffSpB->setSingleStep(1);
0132     d->photoMaxTimeDiffSpB->setValue(5);
0133     d->photoMaxTimeDiffSpB->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
0134     d->photoMaxTimeDiffSpB->setEnabled(true);
0135     QLabel* const warnTimeText2             = new QLabel(i18n("minute(s) of observation."), idBox);
0136     QHBoxLayout* const warnTimeLayout       = new QHBoxLayout();
0137     warnTimeLayout->addWidget(warnTimeText1);
0138     warnTimeLayout->addWidget(d->photoMaxTimeDiffSpB);
0139     warnTimeLayout->addWidget(warnTimeText2, 1);
0140     moreOptionsLayout->addLayout(warnTimeLayout);
0141 
0142     QLabel* const warnLocationText1         = new QLabel(i18n("Photos should be taken within"), idBox);
0143     d->photoMaxDistanceSpB                  = new QSpinBox(idBox);
0144     d->photoMaxDistanceSpB->setMinimum(1);
0145     d->photoMaxDistanceSpB->setMaximum(9999);
0146     d->photoMaxDistanceSpB->setSingleStep(1);
0147     d->photoMaxDistanceSpB->setValue(15);
0148     d->photoMaxDistanceSpB->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
0149     d->photoMaxDistanceSpB->setEnabled(true);
0150     QLabel* const warnLocationText2         = new QLabel(i18n("meter(s) of observation."), idBox);
0151     QHBoxLayout* warnLocationLayout         = new QHBoxLayout();
0152     warnLocationLayout->addWidget(warnLocationText1);
0153     warnLocationLayout->addWidget(d->photoMaxDistanceSpB);
0154     warnLocationLayout->addWidget(warnLocationText2, 1);
0155     moreOptionsLayout->addLayout(warnLocationLayout);
0156 
0157     QLabel* const warnCloseObsText1         = new QLabel(i18n("Known observations should be within"), idBox);
0158     d->closestObservationMaxSpB             = new QSpinBox(idBox);
0159     d->closestObservationMaxSpB->setMinimum(10);
0160     d->closestObservationMaxSpB->setMaximum(99999);
0161     d->closestObservationMaxSpB->setSingleStep(10);
0162     d->closestObservationMaxSpB->setValue(500);
0163     d->closestObservationMaxSpB->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
0164     d->closestObservationMaxSpB->setEnabled(true);
0165     QLabel* const warnCloseObsText2         = new QLabel(i18n("meter(s) of observation."), idBox);
0166     QHBoxLayout* const warnCloseObsLayout   = new QHBoxLayout();
0167     warnCloseObsLayout->addWidget(warnCloseObsText1);
0168     warnCloseObsLayout->addWidget(d->closestObservationMaxSpB);
0169     warnCloseObsLayout->addWidget(warnCloseObsText2, 1);
0170     moreOptionsLayout->addLayout(warnCloseObsLayout);
0171     idBoxLayout->addWidget(d->moreOptionsWidget);
0172     d->moreOptionsWidget->hide();
0173 
0174     idBox->show();
0175     getSettingsBoxLayout()->insertWidget(2, idBox);
0176     getSettingsBoxLayout()->setStretch(2, 5);
0177 
0178     // -- The options group. ------------------------------------------------
0179 
0180     getPhotoIdCheckBox()->show();
0181 
0182     // hiding widgets not needed here.
0183 
0184     getUploadBox()->hide();
0185     getSizeBox()->hide();
0186     getAlbumBox()->hide();
0187 
0188     replaceImageList(d->imglst);
0189 
0190     this->updateLabels(QString());
0191 }
0192 
0193 INatWidget::~INatWidget()
0194 {
0195     delete d->taxonPopup;
0196     delete d;
0197 }
0198 
0199 void INatWidget::updateLabels(const QString& name, const QString& /*url*/)
0200 {
0201     QString url = QLatin1String("https://www.inaturalist.org/");
0202 
0203     if (!name.isEmpty())
0204     {
0205         url += QLatin1String("observations?place_id=any&user_id=") + name +
0206                QLatin1String("&verifiable=any");
0207     }
0208 
0209     getHeaderLbl()->setText(i18n("<b><h2><a href=\"%1\"><font color=\"#74ac00\""
0210                                  ">iNaturalist</font></a> Export</h2></b>",
0211                                  url));
0212 }
0213 
0214 } // namespace DigikamGenericINatPlugin
0215 
0216 #include "moc_inatwidget.cpp"