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"