Просмотр исходного кода

Fix language inconsistencies in ctkLanguageComboBox

Closes #280
Julien Finet лет назад: 12
Родитель
Сommit
69a2a31b49
2 измененных файлов с 169 добавлено и 56 удалено
  1. 122 40
      Libs/Widgets/ctkLanguageComboBox.cpp
  2. 47 16
      Libs/Widgets/ctkLanguageComboBox.h

+ 122 - 40
Libs/Widgets/ctkLanguageComboBox.cpp

@@ -34,11 +34,14 @@ protected:
 public:
   ctkLanguageComboBoxPrivate(ctkLanguageComboBox& object);
   void init();
-  void addLanguages(const QStringList& languages);
-  void addLanguage(const QString& language);
-
-  QString   DefaultLanguage;
-  QString   Dir;
+  void addLanguageFiles(const QStringList& fileNames);
+  bool addLanguage(const QString& language);
+  bool insertLanguage(int index, const QString& language);
+  bool languageItem(const QString& language,
+                    QIcon& icon, QString& text,QVariant& data);
+
+  QString DefaultLanguage;
+  QString LanguageDirectory;
 };
 
 // ----------------------------------------------------------------------------
@@ -51,68 +54,103 @@ ctkLanguageComboBoxPrivate::ctkLanguageComboBoxPrivate(ctkLanguageComboBox &obje
 void ctkLanguageComboBoxPrivate::init()
 {
   Q_Q(ctkLanguageComboBox);
-  /// Recover all the translation file from the directory Translations
-  QDir translationDir = QDir(this->Dir);
 
-  QStringList languages = translationDir.entryList(QStringList("*.qm"));
+  QObject::connect(q, SIGNAL(currentIndexChanged(int)),
+                   q, SLOT(onLanguageChanged(int)));
 
-  /// Add default language.
-  if (!this->DefaultLanguage.isEmpty())
+  /// Add default language if any
+  if (this->DefaultLanguage.isEmpty())
     {
     this->addLanguage(this->DefaultLanguage);
     }
-  /// Add all the languages availables
-  this->addLanguages(languages);
-
-  QObject::connect(q, SIGNAL(currentIndexChanged(int)),
-                   q, SLOT(onLanguageChanged(int)));
 }
 
 // ----------------------------------------------------------------------------
-void ctkLanguageComboBoxPrivate::addLanguages(const QStringList& languages)
+void ctkLanguageComboBoxPrivate::addLanguageFiles(const QStringList& fileNames)
 {
-  foreach(QString language, languages)
+  foreach(QString fileName, fileNames)
     {
+    QFileInfo file(fileName);
+    if (!file.exists())
+      {
+      qWarning() << "File " << file.absoluteFilePath() << " doesn't exist.";
+      }
+    // language is "de_ch" for a file named "/abc/def_de_ch.qm"
+    QString language = file.completeBaseName();
     language.remove(0,language.indexOf('_') + 1);
-    language.chop(3);
     this->addLanguage(language);
     }
 }
 
 // ----------------------------------------------------------------------------
-void ctkLanguageComboBoxPrivate::addLanguage(const QString& language)
+bool ctkLanguageComboBoxPrivate::addLanguage(const QString& language)
 {
   Q_Q(ctkLanguageComboBox);
-  QLocale lang(language);
-  QString icon = ":Icons/Languages/";
-  icon += language;
-  icon += ".png";
-  q->addItem(QIcon(icon), QLocale::languageToString(lang.language()), language);
+  return this->insertLanguage(q->count(), language);
 }
 
 // ----------------------------------------------------------------------------
-ctkLanguageComboBox::ctkLanguageComboBox(QWidget* _parent)
-  : QComboBox(_parent)
-  , d_ptr(new ctkLanguageComboBoxPrivate(*this))
+bool ctkLanguageComboBoxPrivate::insertLanguage(int index, const QString& language)
 {
+  Q_Q(ctkLanguageComboBox);
+  QIcon icon;
+  QString text;
+  QVariant data;
+  bool res =this->languageItem(language, icon, text, data);
+  if (res)
+    {
+    q->insertItem(index, icon, text, data);
+    }
+  return res;
 }
 
 // ----------------------------------------------------------------------------
-ctkLanguageComboBox::~ctkLanguageComboBox()
+bool ctkLanguageComboBoxPrivate::languageItem(const QString& language,
+                                              QIcon& icon,
+                                              QString& text,
+                                              QVariant& data)
 {
+  QLocale locale(language);
+  if (language.isEmpty() ||
+      locale.name() == "C")
+    {
+    icon = QIcon();
+    text = QString();
+    data = QVariant();
+    return false;
+    }
+  QString countryFlag = locale.name();
+  countryFlag.remove(0, countryFlag.lastIndexOf('_') + 1);
+  countryFlag = countryFlag.toLower();
+  icon = QIcon(QString(":Icons/Languages/%1.png").arg(countryFlag));
+  text = QLocale::languageToString(locale.language());
+  data = locale.name();
+  return true;
 }
 
 // ----------------------------------------------------------------------------
-QString ctkLanguageComboBox::currentLanguage() const
+ctkLanguageComboBox::ctkLanguageComboBox(QWidget* _parent)
+  : QComboBox(_parent)
+  , d_ptr(new ctkLanguageComboBoxPrivate(*this))
 {
-  return this->itemData(this->currentIndex()).toString();
+  Q_D(ctkLanguageComboBox);
+  d->init();
 }
 
 // ----------------------------------------------------------------------------
-void ctkLanguageComboBox::setCurrentLanguage(const QString &language)
+ctkLanguageComboBox::ctkLanguageComboBox(const QString& defaultLanguage,
+                                         QWidget* _parent)
+  : QComboBox(_parent)
+  , d_ptr(new ctkLanguageComboBoxPrivate(*this))
+{
+  Q_D(ctkLanguageComboBox);
+  d->DefaultLanguage = defaultLanguage;
+  d->init();
+}
+
+// ----------------------------------------------------------------------------
+ctkLanguageComboBox::~ctkLanguageComboBox()
 {
-  int index = this->findData(QVariant(language));
-  this->setCurrentIndex(index);
 }
 
 // ----------------------------------------------------------------------------
@@ -126,29 +164,73 @@ QString ctkLanguageComboBox::defaultLanguage() const
 void ctkLanguageComboBox::setDefaultLanguage(const QString& language)
 {
   Q_D(ctkLanguageComboBox);
-  d->DefaultLanguage = language;
+  bool isValid = false;
+  if (!d->DefaultLanguage.isEmpty())
+    {
+    QIcon icon;
+    QString text;
+    QVariant data;
+    isValid = d->languageItem(language, icon, text, data);
+    if (isValid)
+      {
+      // Replace the default language
+      this->setItemIcon(0, icon);
+      this->setItemText(0, text);
+      this->setItemData(0, data);
+      }
+    else
+      {
+      this->removeItem(0);
+      }
+    }
+  else
+    {
+    isValid = d->insertLanguage(0, language);
+    }
+  d->DefaultLanguage = isValid ? this->itemData(0).toString() : QString();
+}
+
+// ----------------------------------------------------------------------------
+QString ctkLanguageComboBox::currentLanguage() const
+{
+  return this->itemData(this->currentIndex()).toString();
+}
+
+// ----------------------------------------------------------------------------
+void ctkLanguageComboBox::setCurrentLanguage(const QString &language)
+{
+  int index = this->findData(QVariant(language));
+  this->setCurrentIndex(index);
 }
 
 // ----------------------------------------------------------------------------
 QString ctkLanguageComboBox::directory() const
 {
   Q_D(const ctkLanguageComboBox);
-  return d->Dir;
+  return d->LanguageDirectory;
 }
 
 // ----------------------------------------------------------------------------
 void ctkLanguageComboBox::setDirectory(const QString& dir)
 {
   Q_D(ctkLanguageComboBox);
-  d->Dir = dir;
-  d->init();
+
+  d->LanguageDirectory = dir;
+
+  /// Recover all the translation file from the directory Translations
+  QDir translationDir = QDir(d->LanguageDirectory);
+  QStringList languages = translationDir.entryList(QStringList("*.qm"));
+
+  /// Add all the languages availables
+  d->addLanguageFiles(languages);
+
   this->update();
 }
 
 // ----------------------------------------------------------------------------
 void ctkLanguageComboBox::onLanguageChanged(int index)
 {
-  QVariant lang = this->itemData(index);
-  //QLocale locale(lang.toString());
-  emit currentLanguageNameChanged(lang.toString());
+  Q_UNUSED(index);
+  QString currentLanguage = this->currentLanguage();
+  emit currentLanguageNameChanged(currentLanguage);
 }

+ 47 - 16
Libs/Widgets/ctkLanguageComboBox.h

@@ -26,56 +26,87 @@
 
 // CTK includes
 #include "ctkWidgetsExport.h"
+class ctkLanguageComboBoxPrivate;
 
 /// ctkLanguageComboBox is a simple QComboBox to select the language
 /// of your application.
-
 /// You have to set the default language of your application and then
 /// set the directory to allow the comboBox to find the translation files.
-/// ctkLanguageComboBox automaically recognizes the language of the
-/// translation file by the suffix _en or _fr and add the associated
+/// ctkLanguageComboBox automatically recognizes the language of the
+/// translation file by the suffix "_en" or "_fr" and add the associated
 /// language to the comboBox.
-
 /// \note:
 /// Translation files names need to finish with the suffix of the
 /// country.
 /// Example: for a french traduction, xxxx_fr.ts
-
-class ctkLanguageComboBoxPrivate;
-
+/// \warning Please don't use QComboBox methods when using this class.
 class CTK_WIDGETS_EXPORT ctkLanguageComboBox : public QComboBox
 {
   Q_OBJECT
-  Q_PROPERTY(QString currentLanguage READ currentLanguage WRITE setCurrentLanguage)
+  /// \brief This property controls the default language of the application.
+  ///
+  /// The default language is the language in which all the texts in GUI
+  /// elements are written.
+  /// As the application doesn't have translation file for the default
+  /// language, this property adds an item to the combobox.
+  /// The language format is a lowercase, two-letter, ISO 639 language code.
+  /// For example: "fr", "en" or "de_ch".
+  /// If empty, there is no default language, and there is no entry added.
+  /// By default, there is no default language.
+  /// \sa defaultLanguage(), setDefaultLanguage(), QLocale::setDefault()
+  Q_PROPERTY(QString defaultLanguage READ defaultLanguage WRITE setDefaultLanguage)
+
+  /// This property controls the directory where the translation files are
+  /// located.
+  /// \sa directory(), setDirectory()
   Q_PROPERTY(QString directory READ directory WRITE setDirectory)
 
+  /// This property controls the current language of the combobox.
+  /// The \a defaultLanguage by default.
+  /// \sa currentLanguage(), setCurrentLanguage()
+  Q_PROPERTY(QString currentLanguage READ currentLanguage WRITE setCurrentLanguage NOTIFY currentLanguageNameChanged USER true)
+
 public:
   typedef QComboBox Superclass;
+  /// Constructor of ctkLanguageComboBox
   ctkLanguageComboBox(QWidget *parent = 0);
+  /// Constructor that specifies a default language.
+  /// \sa defaultLanguage
+  ctkLanguageComboBox(const QString& defaultLanguage, QWidget *parent = 0);
   virtual ~ctkLanguageComboBox();
 
-  /// Return the currentLanguage of the combobox.
-  QString currentLanguage()const;
-  void setCurrentLanguage(const QString& language);
-
-  /// Set the default language of your application.
-  /// As the application doesn't have translation file for the default
-  /// language, it's very important to set this variable. Otherwise,
-  /// the default language is not added to the ComboBox.
+  /// Return the default language.
+  /// \sa defaultLanguage, setDefaultLanguage()
   QString defaultLanguage()const;
+
+  /// Set the default language. The previous default language is removed and
+  /// replaced with the new default language.
+  /// \sa defaultLanguage, defaultLanguage()
   void setDefaultLanguage(const QString& language);
 
   /// Set the \a directory with all the translation files.
   /// The list of available languages will be populated based on
   /// the discovered translation files.
+  /// The default language will still be the first item in the menu.
+  /// Empty by default.
   QString directory()const;
   void setDirectory(const QString& dir);
 
+  /// Return the currently selected language of the combobox.
+  /// \sa currentLanguage, setCurrentLanguage()
+  QString currentLanguage()const;
+
+public Q_SLOTS:
+  /// Set the current language
+  /// \sa currentLanguage, currentLanguage()
+  void setCurrentLanguage(const QString& language);
+
 protected slots:
   void onLanguageChanged(int index);
 
 signals:
   /// Signals emitted when the current language changed.
+  /// \sa QLocale::name()
   void currentLanguageNameChanged(const QString&);
 
 protected: