File indexing completed on 2025-04-27 03:58:40

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2023-08-20
0007  * Description : Localization of Strings Config widget.
0008  *
0009  * SPDX-FileCopyrightText: 2021-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 "localizeconfig.h"
0016 
0017 // Qt includes
0018 
0019 #include <QComboBox>
0020 #include <QGridLayout>
0021 #include <QGroupBox>
0022 #include <QLabel>
0023 #include <QApplication>
0024 #include <QStyle>
0025 #include <QHeaderView>
0026 #include <QPushButton>
0027 #include <QCheckBox>
0028 #include <QIcon>
0029 #include <QTreeWidgetItemIterator>
0030 
0031 // KDE includes
0032 
0033 #include <klocalizedstring.h>
0034 
0035 // Local includes
0036 
0037 #include "localizesettings.h"
0038 #include "altlangstredit.h"
0039 #include "digikam_debug.h"
0040 #include "dlayoutbox.h"
0041 #include "dexpanderbox.h"
0042 
0043 namespace Digikam
0044 {
0045 
0046 LanguagesList::LanguagesList(QWidget* const parent)
0047     : QTreeWidget(parent)
0048 {
0049     setRootIsDecorated(false);
0050     setItemsExpandable(false);
0051     setExpandsOnDoubleClick(false);
0052     setAlternatingRowColors(true);
0053     setSelectionMode(QAbstractItemView::NoSelection);
0054     setAllColumnsShowFocus(true);
0055     setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
0056     setColumnCount(2);
0057     setHeaderLabels(QStringList() << i18nc("@title: translator language code", "Code (Language-Country)")
0058                                   << i18nc("@title: translator language name", "Name"));
0059     header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
0060     header()->setSectionResizeMode(1, QHeaderView::Stretch);
0061 }
0062 
0063 void LanguagesList::slotSearchTextChanged(const SearchTextSettings& settings)
0064 {
0065     int found = 0;
0066 
0067     QTreeWidgetItemIterator it(this);
0068 
0069     while (*it)
0070     {
0071         if (
0072             (*it)->text(0).contains(settings.text, settings.caseSensitive) ||
0073             (*it)->text(1).contains(settings.text, settings.caseSensitive)
0074            )
0075         {
0076             found++;
0077             (*it)->setHidden(false);
0078         }
0079         else
0080         {
0081             (*it)->setHidden(true);
0082         }
0083 
0084         ++it;
0085     }
0086 
0087     Q_EMIT signalSearchResult(found);
0088 }
0089 
0090 // --------------------------------------------------------------------------------------------------
0091 
0092 class Q_DECL_HIDDEN LanguagesView : public QGroupBox
0093 {
0094     Q_OBJECT
0095 
0096 public:
0097 
0098     explicit LanguagesView(QWidget* const parent)
0099         : QGroupBox     (parent),
0100           m_langList    (nullptr),
0101           m_showSelected(nullptr),
0102           m_langFilter  (nullptr)
0103     {
0104         QVBoxLayout* const vlay = new QVBoxLayout();
0105         setLayout(vlay);
0106 
0107         m_langList              = new LanguagesList(this);
0108         DHBox* const hbox       = new DHBox(this);
0109         m_showSelected          = new QCheckBox(hbox);
0110         m_langFilter            = new SearchTextBar(hbox, QLatin1String("TranslatorLangSearchBar"),
0111                                                     i18nc("@info", "Enter here a string to search in languages list..."));
0112 
0113         vlay->addWidget(m_langList);
0114         vlay->addWidget(hbox);
0115 
0116         connect(m_showSelected, SIGNAL(toggled(bool)),
0117                 this, SLOT(slotShowSelected(bool)));
0118 
0119         connect(m_langFilter, SIGNAL(signalSearchTextSettings(SearchTextSettings)),
0120                 m_langList, SLOT(slotSearchTextChanged(SearchTextSettings)));
0121 
0122         connect(m_langList, SIGNAL(signalSearchResult(int)),
0123                 this, SLOT(slotSearchResult(int)));
0124 
0125         connect(m_langList, SIGNAL(itemClicked(QTreeWidgetItem*,int)),
0126                 this, SLOT(slotItemClicked(QTreeWidgetItem*,int)));
0127 
0128         slotItemClicked(nullptr, 0);
0129     }
0130 
0131     void updateStats()
0132     {
0133         int count = 0;
0134         QTreeWidgetItemIterator it(m_langList);
0135 
0136         while (*it)
0137         {
0138             if ((*it)->checkState(0) == Qt::Checked)
0139             {
0140                 count++;
0141             }
0142 
0143             ++it;
0144         }
0145 
0146         m_showSelected->setText(i18nc("@info", "Show only selected items (%1/%2)",
0147                                 count, m_langList->topLevelItemCount()));
0148     }
0149 
0150 private Q_SLOTS:
0151 
0152     void slotItemClicked(QTreeWidgetItem*, int column)
0153     {
0154         if (column == 0)
0155         {
0156             updateStats();
0157         }
0158     }
0159 
0160     void slotShowSelected(bool b)
0161     {
0162         QTreeWidgetItemIterator it(m_langList);
0163 
0164         while (*it)
0165         {
0166             if (b)
0167             {
0168                 (*it)->setHidden((*it)->checkState(0) != Qt::Checked);
0169             }
0170             else
0171             {
0172                 (*it)->setHidden(false);
0173             }
0174 
0175             ++it;
0176         }
0177     }
0178 
0179     void slotSearchResult(int found)
0180     {
0181         m_langFilter->slotSearchResult(found ? true : false);
0182     }
0183 
0184 public:
0185 
0186     LanguagesList* m_langList;
0187     QCheckBox*     m_showSelected;
0188     SearchTextBar* m_langFilter;
0189 };
0190 
0191 class Q_DECL_HIDDEN LocalizeConfig::Private
0192 {
0193 public:
0194 
0195     explicit Private()
0196       : altLangList     (nullptr),
0197         altLangGroup    (nullptr),
0198         translatorCB    (nullptr),
0199         translatorLabel (nullptr),
0200         trLangList      (nullptr),
0201         trLangGroup     (nullptr)
0202     {
0203     }
0204 
0205     LanguagesList*  altLangList;
0206     LanguagesView*  altLangGroup;
0207 
0208     QStringList     trLangEnabled;
0209     QComboBox*      translatorCB;
0210     QLabel*         translatorLabel;
0211     LanguagesList*  trLangList;
0212     LanguagesView*  trLangGroup;
0213 };
0214 
0215 LocalizeConfig::LocalizeConfig(QWidget* const parent)
0216     : QWidget(parent),
0217       d      (new Private)
0218 {
0219     const int spacing = qMin(QApplication::style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing),
0220                              QApplication::style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing));
0221 
0222     QGridLayout* const grid = new QGridLayout(this);
0223 
0224     // --------------------------------------------------------
0225 
0226     d->altLangGroup         = new LanguagesView(this);
0227     d->altLangGroup->setTitle(i18nc("@title", "Select Alternative Languages To Edit Text"));
0228     d->altLangList          = d->altLangGroup->m_langList;
0229 
0230     // --------------------------------------------------------
0231 
0232     QLabel* const trLabel   = new QLabel(i18nc("@label", "Online Translator:"), this);
0233     d->translatorCB         = new QComboBox(this);
0234     d->translatorCB->setToolTip(i18nc("@option", "Select here the online engine to translate text"));
0235     d->translatorCB->insertItem(DOnlineTranslator::Google,         QLatin1String("Google"));
0236     d->translatorCB->insertItem(DOnlineTranslator::Yandex,         QLatin1String("Yandex"));
0237     d->translatorCB->insertItem(DOnlineTranslator::Bing,           QLatin1String("Bing"));
0238     d->translatorCB->insertItem(DOnlineTranslator::LibreTranslate, QLatin1String("Libre Translate"));
0239     d->translatorCB->insertItem(DOnlineTranslator::Lingva,         QLatin1String("Lingva"));
0240 
0241     d->translatorLabel      = new QLabel(xi18nc("@info", "<para>The translator engine is an online Web-service used to translate "
0242                                                          "text from one language to another one. This feature is available on "
0243                                                          "metadata option where alternative language is supported, as Title, "
0244                                                          "Caption, etc. The translation process is fully automatized but it requires "
0245                                                          "an Internet connection to work.</para>"
0246                                                          "<para>User can select the more appropriate translator engine depending of "
0247                                                          "desired target language, as not all world-wide languages are supported "
0248                                                          "by online Web-services.</para>"), this);
0249     d->translatorLabel->setWordWrap(true);
0250 
0251     d->trLangGroup             = new LanguagesView(this);
0252     d->trLangList              = d->trLangGroup->m_langList;
0253 
0254     // --------------------------------------------------------
0255 
0256     grid->setAlignment(Qt::AlignTop);
0257     grid->addWidget(d->altLangGroup,                       0, 0, 1, 3);
0258     grid->addWidget(new DLineWidget(Qt::Horizontal, this), 1, 0, 1, 3);
0259     grid->addWidget(trLabel,                               2, 0, 1, 1);
0260     grid->addWidget(d->translatorCB,                       2, 1, 1, 1);
0261     grid->addWidget(d->translatorLabel,                    3, 0, 1, 3);
0262     grid->addWidget(d->trLangGroup,                        4, 0, 1, 3);
0263     grid->setRowStretch(4, 10);
0264     grid->setColumnStretch(2, 10);
0265     grid->setContentsMargins(spacing, spacing, spacing, spacing);
0266     grid->setSpacing(spacing);
0267 
0268     // --------------------------------------------------------
0269 
0270     populateAltLanguages();
0271     populateTranslatorLanguages();
0272     readSettings();
0273     slotTranslatorChanged();
0274 
0275     connect(d->translatorCB, SIGNAL(currentIndexChanged(int)),
0276             this, SLOT(slotTranslatorChanged()));
0277 }
0278 
0279 LocalizeConfig::~LocalizeConfig()
0280 {
0281     delete d;
0282 }
0283 
0284 void LocalizeConfig::populateAltLanguages()
0285 {
0286     d->altLangList->clear();
0287 
0288     Q_FOREACH (const QString& code, AltLangStrEdit::allLanguagesRFC3066())
0289     {
0290         new QTreeWidgetItem(d->altLangList,
0291                             QStringList() << code
0292                                           << AltLangStrEdit::languageNameRFC3066(code));
0293     }
0294 }
0295 
0296 void LocalizeConfig::populateTranslatorLanguages()
0297 {
0298     d->trLangList->clear();
0299 
0300     Q_FOREACH (const QString& code, DOnlineTranslator::supportedRFC3066((DOnlineTranslator::Engine)d->translatorCB->currentIndex()))
0301     {
0302         new QTreeWidgetItem(d->trLangList,
0303                             QStringList() << code
0304                                           << AltLangStrEdit::languageNameRFC3066(code));
0305     }
0306 }
0307 
0308 void LocalizeConfig::slotTranslatorChanged()
0309 {
0310     int count       = 0;
0311 
0312     QTreeWidgetItemIterator it(d->trLangList);
0313 
0314     while (*it)
0315     {
0316         (*it)->setDisabled(!DOnlineTranslator::isSupportTranslation(
0317             (DOnlineTranslator::Engine)d->translatorCB->currentIndex(),
0318             DOnlineTranslator::language(DOnlineTranslator::fromRFC3066((DOnlineTranslator::Engine)d->translatorCB->currentIndex(), (*it)->text(0))))
0319         );
0320 
0321         if (!(*it)->isDisabled())
0322         {
0323             count++;
0324         }
0325 
0326         ++it;
0327     }
0328 
0329     d->trLangGroup->setTitle(i18nc("@title", "Available Translator Languages (%1/%2)",
0330                              count, d->trLangList->topLevelItemCount()));
0331 }
0332 
0333 void LocalizeConfig::applySettings()
0334 {
0335     LocalizeSettings* const config = LocalizeSettings::instance();
0336 
0337     if (!config)
0338     {
0339         return;
0340     }
0341 
0342     LocalizeContainer set;
0343 
0344     set.alternativeLang << QLatin1String("x-default");  // This first entry must always be present on the list.
0345 
0346     QTreeWidgetItemIterator it(d->altLangList);
0347 
0348     while (*it)
0349     {
0350         if (((*it)->checkState(0) == Qt::Checked))
0351         {
0352             set.alternativeLang << (*it)->text(0);
0353         }
0354 
0355         ++it;
0356     }
0357 
0358     set.translatorEngine = (DOnlineTranslator::Engine)d->translatorCB->currentIndex();
0359 
0360     QTreeWidgetItemIterator it2(d->trLangList);
0361 
0362     while (*it2)
0363     {
0364         if (((*it2)->checkState(0) == Qt::Checked) && !(*it2)->isDisabled())
0365         {
0366             set.translatorLang << (*it2)->text(0);
0367         }
0368 
0369         ++it2;
0370     }
0371 
0372     config->setSettings(set, LocalizeSettings::LocalizeConfig);
0373 }
0374 
0375 void LocalizeConfig::readSettings()
0376 {
0377     LocalizeSettings* const config = LocalizeSettings::instance();
0378 
0379     if (!config)
0380     {
0381         return;
0382     }
0383 
0384     LocalizeContainer set          = config->settings();
0385 
0386     QTreeWidgetItemIterator it(d->altLangList);
0387 
0388     while (*it)
0389     {
0390         if (set.translatorLang.contains((*it)->text(0)))
0391         {
0392             (*it)->setCheckState(0, Qt::Checked);
0393         }
0394         else
0395         {
0396             (*it)->setCheckState(0, Qt::Unchecked);
0397         }
0398 
0399         ++it;
0400     }
0401 
0402     d->translatorCB->setCurrentIndex(set.translatorEngine);
0403 
0404     QTreeWidgetItemIterator it2(d->trLangList);
0405 
0406     while (*it2)
0407     {
0408         if (set.translatorLang.contains((*it2)->text(0)))
0409         {
0410             (*it2)->setCheckState(0, Qt::Checked);
0411         }
0412         else
0413         {
0414             (*it2)->setCheckState(0, Qt::Unchecked);
0415         }
0416 
0417         ++it2;
0418     }
0419 
0420     d->altLangGroup->updateStats();
0421     d->trLangGroup->updateStats();
0422 }
0423 
0424 } // namespace Digikam
0425 
0426 #include "localizeconfig.moc"
0427 
0428 #include "moc_localizeconfig.cpp"