commit 7be8307768e34fd42b76c249a582c0a6b0e95e3e Author: Juergen Spitzmueller <sp...@lyx.org> Date: Thu Mar 21 09:13:09 2019 +0100
GuiLyXFiles: rework language selector Now only the languages available for the selected file are displayed. By default, LyX pre-selects the GUI language (and falls back to English if this is not available). Once another language has been selected by the user, this one is preferred before the GUI language (and the English fallback). --- src/frontends/qt4/GuiLyXFiles.cpp | 155 ++++++++++++++++++++++++------------ src/frontends/qt4/GuiLyXFiles.h | 17 ++++- src/frontends/qt4/ui/LyXFilesUi.ui | 4 +- 3 files changed, 122 insertions(+), 54 deletions(-) diff --git a/src/frontends/qt4/GuiLyXFiles.cpp b/src/frontends/qt4/GuiLyXFiles.cpp index c442b4e..adddf64 100644 --- a/src/frontends/qt4/GuiLyXFiles.cpp +++ b/src/frontends/qt4/GuiLyXFiles.cpp @@ -47,7 +47,7 @@ void GuiLyXFiles::getFiles(QMap<QString, QString> & in, QString const type) // 3) system_lyxdir // in this order. Files with a given sub-hierarchy will // only be listed once. - // We also consider i18n subdirectories and prefer them. + // We also consider i18n subdirectories and store them separately. QStringList dirs; QStringList relpaths; @@ -56,23 +56,9 @@ void GuiLyXFiles::getFiles(QMap<QString, QString> & in, QString const type) string const build = addPath(package().build_support().absFileName(), fromqstr(type)); string const system = addPath(package().system_support().absFileName(), fromqstr(type)); - // First, query the current language subdir (except for English) - QString const lang = languageCO->itemData(languageCO->currentIndex()).toString(); - if (!lang.startsWith("en")) { - // First try with the full code - dirs << toqstr(addPath(user, fromqstr(lang))); - dirs << toqstr(addPath(build, fromqstr(lang))); - dirs << toqstr(addPath(system, fromqstr(lang))); - // Then the name without country code - QString const shortl = lang.left(lang.indexOf('_')); - if (shortl != lang) { - dirs << toqstr(addPath(user, fromqstr(shortl))); - dirs << toqstr(addPath(build, fromqstr(shortl))); - dirs << toqstr(addPath(system, fromqstr(shortl))); - } - } + available_languages_.insert(toqstr("en"), qt_("English")); - // Next, search in the base path + // Search in the base path dirs << toqstr(user) << toqstr(build) << toqstr(system); @@ -84,30 +70,59 @@ void GuiLyXFiles::getFiles(QMap<QString, QString> & in, QString const type) QString fn(QFile(it.next()).fileName()); if (!fn.endsWith(getSuffix())) continue; - QString const relpath = toqstr(makeRelPath(qstring_to_ucs4(fn), - qstring_to_ucs4(dir))); + QString relpath = toqstr(makeRelPath(qstring_to_ucs4(fn), + qstring_to_ucs4(dir))); // <cat>/ int s = relpath.indexOf('/', 0); QString cat = qt_("General"); + QString localization = "en"; if (s != -1) { // <cat>/<subcat>/ cat = relpath.left(s); int sc = relpath.indexOf('/', s + 1); QString const subcat = (sc == -1) ? QString() : relpath.mid(s + 1, sc - s - 1); - if (langcodes_.contains(cat) - && !langcodes_.contains(dir.right(dir.lastIndexOf('/')))) - // Skip i18n dir - continue; + if (all_languages_.contains(cat) + && !all_languages_.contains(dir.right(dir.lastIndexOf('/')))) { + QMap<QString, QString>::const_iterator li = all_languages_.find(cat); + // Skip i18n dir, but add language to the combo + if (!available_languages_.contains(li.key())) + available_languages_.insert(li.key(), li.value()); + localization = cat; + } if (!subcat.isEmpty()) cat += '/' + subcat; } if (!relpaths.contains(relpath)) { relpaths.append(relpath); - in.insert(fn, cat); + if (localization == "en") + in.insert(relpath, cat); + else + // strip off lang/ + relpath = relpath.mid(relpath.indexOf('/') + 1); + QMap<QString, QString> lm; + if (localizations_.contains(relpath)) + lm = localizations_.find(relpath).value(); + lm.insert(localization, fn); + localizations_.insert(relpath, lm); } } } + // Find and store GUI language + for (auto const & l : guilangs_) { + // First try with the full name + // `en' files are not in a subdirectory + if (available_languages_.contains(toqstr(l))) { + guilang_ = toqstr(l); + break; + } + // Then the name without country code + string const shortl = token(l, '_', 0); + if (available_languages_.contains(toqstr(shortl))) { + guilang_ = toqstr(shortl); + break; + } + } } @@ -126,36 +141,20 @@ GuiLyXFiles::GuiLyXFiles(GuiView & lv) languages.getLanguage(fromqstr(index.data(Qt::UserRole).toString())); if (!lang) continue; - string const code = lang->code(); - languageCO->addItem(qt_(lang->display()), toqstr(code)); - langcodes_ << toqstr(code); + QString const code = toqstr(lang->code()); + if (!all_languages_.contains(code)) + all_languages_.insert(code, qt_(lang->display())); // Also store code without country code - string const shortcode = token(code, '_', 0); - if (shortcode != code) - langcodes_ << toqstr(shortcode); + QString const shortcode = code.left(code.indexOf('_')); + if (shortcode != code && !all_languages_.contains(shortcode)) + all_languages_.insert(shortcode, qt_(lang->display())); } - // Preset to GUI language + // Get GUI language string lang = getGuiMessages().language(); string const language = getEnv("LANGUAGE"); if (!language.empty()) lang += ":" + language; - - for (auto const & l : getVectorFromString(lang, ":")) { - // First try with the full name - // `en' files are not in a subdirectory - int i = languageCO->findData(toqstr(l)); - if (i != -1) { - languageCO->setCurrentIndex(i); - break; - } - // Then the name without country code - string const shortl = token(l, '_', 0); - i = languageCO->findData(toqstr(l)); - if (i != -1) { - languageCO->setCurrentIndex(i); - break; - } - } + guilangs_ = getVectorFromString(lang, ":"); // The filter bar filter_ = new FancyLineEdit(this); @@ -226,9 +225,11 @@ void GuiLyXFiles::on_fileTypeCO_activated(int) } -void GuiLyXFiles::on_languageCO_activated(int) +void GuiLyXFiles::on_languageCO_activated(int i) { - updateContents(); + savelang_ = languageCO->itemData(i).toString(); + filesLW->currentItem()->setData(0, Qt::ToolTipRole, getRealPath()); + changed(); } @@ -243,6 +244,46 @@ void GuiLyXFiles::on_filesLW_itemDoubleClicked(QTreeWidgetItem * item, int) close(); } +void GuiLyXFiles::on_filesLW_itemClicked(QTreeWidgetItem * item, int) +{ + QString const data = item->data(0, Qt::UserRole).toString(); + languageCO->clear(); + QMap<QString, QString>::const_iterator i =available_languages_.constBegin(); + while (i != available_languages_.constEnd()) { + if (localizations_.contains(data) + && localizations_.find(data).value().contains(i.key())) + languageCO->addItem(i.value(), i.key()); + ++i; + } + languageCO->setToolTip(qt_("All available languages of the selected file are displayed here.\n" + "The selected language version will be opened.")); + // Set language combo + // first try last setting + if (!savelang_.isEmpty()) { + int index = languageCO->findData(savelang_); + if (index != -1) { + languageCO->setCurrentIndex(index); + filesLW->currentItem()->setData(0, Qt::ToolTipRole, getRealPath()); + return; + } + } + // next, try GUI lang + if (!guilang_.isEmpty()) { + int index = languageCO->findData(guilang_); + if (index != -1) { + languageCO->setCurrentIndex(index); + filesLW->currentItem()->setData(0, Qt::ToolTipRole, getRealPath()); + return; + } + } + // Finally, fall back to English (which should be always there) + int index = languageCO->findData(toqstr("en")); + if (index != -1) { + languageCO->setCurrentIndex(index); + filesLW->currentItem()->setData(0, Qt::ToolTipRole, getRealPath()); + } +} + void GuiLyXFiles::on_browsePB_pressed() { @@ -270,7 +311,9 @@ void GuiLyXFiles::updateContents() { QString type = fileTypeCO->itemData(fileTypeCO->currentIndex()).toString(); QMap<QString, QString> files; + languageCO->clear(); getFiles(files, type); + languageCO->model()->sort(0); filesLW->clear(); QIcon user_icon(getPixmap("images/", "lyxfiles-user", "svgz,png")); @@ -378,10 +421,20 @@ void GuiLyXFiles::resetFilter() filterLabels(); } +QString const GuiLyXFiles::getRealPath() +{ + QString const relpath = filesLW->currentItem()->data(0, Qt::UserRole).toString(); + QString const language = languageCO->itemData(languageCO->currentIndex()).toString(); + if (localizations_.contains(relpath) + && localizations_.find(relpath).value().contains(language)) + return localizations_.find(relpath).value().find(language).value(); + return QString(); +} + void GuiLyXFiles::applyView() { - file_ = filesLW->currentItem()->data(0, Qt::UserRole).toString(); + file_ = getRealPath(); } diff --git a/src/frontends/qt4/GuiLyXFiles.h b/src/frontends/qt4/GuiLyXFiles.h index e0e4219..6a25697 100644 --- a/src/frontends/qt4/GuiLyXFiles.h +++ b/src/frontends/qt4/GuiLyXFiles.h @@ -36,6 +36,7 @@ private Q_SLOTS: void on_fileTypeCO_activated(int); void on_languageCO_activated(int); void on_filesLW_itemDoubleClicked(QTreeWidgetItem *, int); + void on_filesLW_itemClicked(QTreeWidgetItem *, int); void on_browsePB_pressed(); void slotButtonBox(QAbstractButton *); void filterLabels(); @@ -67,6 +68,8 @@ private: bool translateName() const; /// void getFiles(QMap<QString, QString> &, QString const); + /// Get the full file path in the selected localization + QString const getRealPath(); private: /// contains the search box @@ -75,8 +78,20 @@ private: QString type_; /// QString file_; + /// All languages (code, guiname) + QMap<QString, QString> all_languages_; + /// Languages available for files (code. guiname) + QMap<QString, QString> available_languages_; /// - QStringList langcodes_; + typedef QMap<QString, QMap<QString, QString>> localizationsMap; + /// + localizationsMap localizations_; + /// Possible GUI language representations + std::vector<std::string> guilangs_; + /// The real GUI lang as stored in available_languages_ + QString guilang_; + /// The last used language + QString savelang_; }; } // namespace frontend diff --git a/src/frontends/qt4/ui/LyXFilesUi.ui b/src/frontends/qt4/ui/LyXFilesUi.ui index 41dea0e..e90beb7 100644 --- a/src/frontends/qt4/ui/LyXFilesUi.ui +++ b/src/frontends/qt4/ui/LyXFilesUi.ui @@ -42,7 +42,7 @@ <item row="1" column="0" colspan="2"> <widget class="QLabel" name="languageLA"> <property name="toolTip"> - <string>Use this language if avaliable (if not, English is used as fallback)</string> + <string/> </property> <property name="text"> <string>&Language:</string> @@ -55,7 +55,7 @@ <item row="1" column="2"> <widget class="QComboBox" name="languageCO"> <property name="toolTip"> - <string>Use this language if avaliable (if not, English is used as fallback)</string> + <string>The available language(s) of the selected file will be displayed here</string> </property> </widget> </item>