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 : 2009-06-15 0007 * Description : localize selector widget 0008 * 0009 * SPDX-FileCopyrightText: 2009-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 "localizeselector.h" 0016 0017 // Qt includes 0018 0019 #include <QLabel> 0020 #include <QIcon> 0021 #include <QMenu> 0022 #include <QAction> 0023 #include <QListWidget> 0024 #include <QWidgetAction> 0025 #include <QStyle> 0026 #include <QToolButton> 0027 #include <QApplication> 0028 #include <QScrollBar> 0029 #include <QListWidgetItem> 0030 #include <QGridLayout> 0031 #include <QScopedPointer> 0032 #include <QEventLoop> 0033 0034 // KDE includes 0035 0036 #include <klocalizedstring.h> 0037 0038 // Local includes 0039 0040 #include "digikam_debug.h" 0041 #include "localizeconfig.h" 0042 #include "localizesettings.h" 0043 #include "donlinetranslator.h" 0044 #include "altlangstredit.h" 0045 0046 namespace Digikam 0047 { 0048 0049 class Q_DECL_HIDDEN TranslateAction : public QWidgetAction 0050 { 0051 Q_OBJECT 0052 0053 public: 0054 0055 explicit TranslateAction(QObject* const parent) 0056 : QWidgetAction(parent) 0057 { 0058 } 0059 0060 QWidget* createWidget(QWidget* parent) override 0061 { 0062 m_list = new QListWidget(parent); 0063 QFontMetrics fontMt(m_list->font()); 0064 QRect fontRect = fontMt.boundingRect(0, 0, m_list->width(), m_list->height(), 0, QLatin1String("XX-XX")); 0065 int width = m_list->contentsMargins().left() + m_list->contentsMargins().right(); 0066 width += fontRect.width() + m_list->verticalScrollBar()->height(); 0067 m_list->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 0068 m_list->setFixedWidth(width); 0069 0070 return m_list; 0071 } 0072 0073 public: 0074 0075 QListWidget* m_list = nullptr; 0076 }; 0077 0078 class Q_DECL_HIDDEN LocalizeSelector::Private 0079 { 0080 public: 0081 0082 explicit Private() 0083 : translateButton (nullptr), 0084 settingsButton (nullptr), 0085 translateAction (nullptr) 0086 { 0087 } 0088 0089 public: 0090 0091 QToolButton* translateButton; 0092 QToolButton* settingsButton; 0093 0094 TranslateAction* translateAction; 0095 }; 0096 0097 LocalizeSelector::LocalizeSelector(QWidget* const parent) 0098 : DHBox(parent), 0099 d (new Private) 0100 { 0101 d->translateButton = new QToolButton(this); 0102 d->translateButton->setIcon(QIcon::fromTheme(QLatin1String("language-chooser"))); 0103 d->translateButton->setPopupMode(QToolButton::MenuButtonPopup); 0104 QMenu* const menu = new QMenu(d->translateButton); 0105 d->translateAction = new TranslateAction(d->translateButton); 0106 menu->addAction(d->translateAction); 0107 d->translateButton->setMenu(menu); 0108 0109 d->settingsButton = new QToolButton(this); 0110 d->settingsButton->setIcon(QIcon::fromTheme(QLatin1String("configure"))); 0111 d->settingsButton->setToolTip(i18nc("@info", "Open localize setup")); 0112 0113 setContentsMargins(QMargins()); 0114 setSpacing(qMin(QApplication::style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing), 0115 QApplication::style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing))); 0116 0117 slotLocalizeChanged(); 0118 0119 // -------------------------------------------------------- 0120 0121 connect(d->settingsButton, &QToolButton::clicked, 0122 this, &LocalizeSelector::slotOpenLocalizeSetup); 0123 0124 connect(d->translateAction->m_list, &QListWidget::itemClicked, 0125 this, &LocalizeSelector::slotTranslate); 0126 0127 connect(d->translateButton, &QToolButton::pressed, 0128 d->translateButton, &QToolButton::showMenu); 0129 0130 connect(LocalizeSettings::instance(), &LocalizeSettings::signalSettingsChanged, 0131 this, &LocalizeSelector::slotLocalizeChanged); 0132 } 0133 0134 LocalizeSelector::~LocalizeSelector() 0135 { 0136 delete d; 0137 } 0138 0139 void LocalizeSelector::populateTranslationEntries() 0140 { 0141 d->translateAction->m_list->clear(); 0142 0143 QStringList allRFC3066 = DOnlineTranslator::supportedRFC3066(LocalizeSettings::instance()->settings().translatorEngine); 0144 LocalizeContainer set = LocalizeSettings::instance()->settings(); 0145 0146 Q_FOREACH (const QString& lg, set.translatorLang) 0147 { 0148 QListWidgetItem* const item = new QListWidgetItem(d->translateAction->m_list); 0149 item->setText(lg); 0150 item->setToolTip(i18nc("@info", "Translate to %1", AltLangStrEdit::languageNameRFC3066(lg))); 0151 d->translateAction->m_list->addItem(item); 0152 } 0153 } 0154 0155 void LocalizeSelector::slotOpenLocalizeSetup() 0156 { 0157 LocalizeSettings::instance()->openLocalizeSetup(); 0158 } 0159 0160 void LocalizeSelector::slotLocalizeChanged() 0161 { 0162 populateTranslationEntries(); 0163 d->translateButton->setToolTip(i18nc("@info: language edit widget", "Select language to translate with %1", 0164 DOnlineTranslator::engineName(LocalizeSettings::instance()->settings().translatorEngine))); 0165 } 0166 0167 void LocalizeSelector::slotTranslate(QListWidgetItem* item) 0168 { 0169 d->translateButton->menu()->close(); 0170 0171 if (item) 0172 { 0173 Q_EMIT signalTranslate(item->text()); 0174 } 0175 } 0176 0177 // ------------------------------------------------------------------------ 0178 0179 class Q_DECL_HIDDEN LocalizeSelectorList::Private 0180 { 0181 public: 0182 0183 explicit Private() 0184 : trLabel (nullptr), 0185 trSelector(nullptr), 0186 trList (nullptr) 0187 { 0188 } 0189 0190 public: 0191 0192 QLabel* trLabel; 0193 LocalizeSelector* trSelector; 0194 LanguagesList* trList; 0195 }; 0196 0197 LocalizeSelectorList::LocalizeSelectorList(QWidget* const parent) 0198 : QWidget(parent), 0199 d (new Private) 0200 { 0201 QGridLayout* const grid = new QGridLayout(this); 0202 0203 d->trLabel = new QLabel(this); 0204 d->trSelector = new LocalizeSelector(this); 0205 d->trList = new LanguagesList(this); 0206 d->trList->setContextMenuPolicy(Qt::CustomContextMenu); 0207 0208 grid->addWidget(d->trLabel, 0, 0, 1, 1); 0209 grid->addWidget(d->trSelector, 0, 1, 1, 1); 0210 grid->addWidget(d->trList, 1, 0, 1, 2); 0211 grid->setColumnStretch(0, 10); 0212 grid->setRowStretch(2, 10); 0213 grid->setContentsMargins(0, 0, 0, 0); 0214 0215 connect(d->trSelector, SIGNAL(signalTranslate(QString)), 0216 this, SLOT(slotAppendTranslation(QString))); 0217 0218 connect(d->trList, SIGNAL(customContextMenuRequested(QPoint)), 0219 this, SLOT(slotShowContextMenu(QPoint))); 0220 } 0221 0222 LocalizeSelectorList::~LocalizeSelectorList() 0223 { 0224 delete d; 0225 } 0226 0227 void LocalizeSelectorList::setTitle(const QString& title) 0228 { 0229 d->trLabel->setText(title); 0230 } 0231 0232 void LocalizeSelectorList::clearLanguages() 0233 { 0234 d->trList->clear(); 0235 } 0236 0237 void LocalizeSelectorList::addLanguage(const QString& code) 0238 { 0239 d->trList->addTopLevelItem(new QTreeWidgetItem(d->trList, QStringList() << code << AltLangStrEdit::languageNameRFC3066(code))); 0240 } 0241 0242 QStringList LocalizeSelectorList::languagesList() const 0243 { 0244 QStringList codes; 0245 0246 QTreeWidgetItemIterator it(d->trList); 0247 0248 while (*it) 0249 { 0250 codes << (*it)->text(0); 0251 ++it; 0252 } 0253 0254 return codes; 0255 } 0256 0257 void LocalizeSelectorList::slotShowContextMenu(const QPoint& pos) 0258 { 0259 QPoint globalPos = d->trList->mapToGlobal(pos); 0260 0261 QMenu menu; 0262 QAction* const rm = menu.addAction(i18nc("@action", "Remove this entry")); 0263 QAction* const cl = menu.addAction(i18nc("@action", "Clear List")); 0264 QAction* const ac = menu.exec(globalPos); 0265 0266 if (ac == rm) 0267 { 0268 delete d->trList->currentItem(); 0269 } 0270 else if (ac == cl) 0271 { 0272 d->trList->clear(); 0273 } 0274 0275 Q_EMIT signalSettingsChanged(); 0276 } 0277 0278 void LocalizeSelectorList::slotAppendTranslation(const QString& lang) 0279 { 0280 QTreeWidgetItemIterator it(d->trList); 0281 0282 while (*it) 0283 { 0284 if ((*it)->text(0).startsWith(lang)) 0285 { 0286 return; 0287 } 0288 0289 ++it; 0290 } 0291 0292 addLanguage(lang); 0293 0294 Q_EMIT signalSettingsChanged(); 0295 } 0296 0297 // ------------------------------------------------------------------------ 0298 0299 bool s_inlineTranslateString(const QString& text, const QString& trCode, QString& tr, QString& error) 0300 { 0301 QScopedPointer<DOnlineTranslator> trengine(new DOnlineTranslator); 0302 QScopedPointer<QEventLoop> waitingLoop(new QEventLoop); 0303 0304 DOnlineTranslator::Language srcLang = DOnlineTranslator::Auto; 0305 DOnlineTranslator::Language trLang = DOnlineTranslator::language(DOnlineTranslator::fromRFC3066(LocalizeSettings::instance()->settings().translatorEngine, trCode)); 0306 0307 qCDebug(DIGIKAM_WIDGETS_LOG) << "Request to translate with Web-service:"; 0308 qCDebug(DIGIKAM_WIDGETS_LOG) << "Text to translate :" << text; 0309 qCDebug(DIGIKAM_WIDGETS_LOG) << "To target language :" << trLang; 0310 qCDebug(DIGIKAM_WIDGETS_LOG) << "With source language :" << srcLang; 0311 0312 QObject::connect(trengine.data(), &DOnlineTranslator::signalFinished, 0313 waitingLoop.data(), &QEventLoop::quit); 0314 0315 trengine->translate(text, // String to translate 0316 LocalizeSettings::instance()->settings().translatorEngine, // Web service 0317 trLang, // Target language 0318 srcLang, // Source langage 0319 DOnlineTranslator::Auto); 0320 0321 waitingLoop->exec(QEventLoop::ExcludeUserInputEvents); 0322 0323 if (trengine->error() == DOnlineTranslator::NoError) 0324 { 0325 tr = trengine->translation(); 0326 qCDebug(DIGIKAM_WIDGETS_LOG) << "Text translated :" << tr; 0327 0328 return true; 0329 } 0330 else 0331 { 0332 error = QChar(trengine->error()); 0333 } 0334 0335 return false; 0336 } 0337 0338 } // namespace Digikam 0339 0340 #include "localizeselector.moc" 0341 0342 #include "moc_localizeselector.cpp"