From 85d29433d58af14bc4ad3fbbf0fc995da460e3a9 Mon Sep 17 00:00:00 2001 From: Alex Zolotarev Date: Mon, 9 May 2011 21:08:25 +0300 Subject: [PATCH] Added save/load preffered languages order to the framework [qt] Added language preferences dialog logic --- map/languages.cpp | 94 +++++++++++++++++++++++++ map/languages.hpp | 17 +++++ map/map.pro | 6 +- qt/preferences_dialog.cpp | 144 +++++++++++++++++++++++++++++++++++--- qt/preferences_dialog.hpp | 10 ++- 5 files changed, 260 insertions(+), 11 deletions(-) create mode 100644 map/languages.cpp create mode 100644 map/languages.hpp diff --git a/map/languages.cpp b/map/languages.cpp new file mode 100644 index 0000000000..bb7fe9a600 --- /dev/null +++ b/map/languages.cpp @@ -0,0 +1,94 @@ +#include "languages.hpp" +#include "settings.hpp" + +#include "../base/logging.hpp" +#include "../base/string_utils.hpp" + +#include "../coding/file_reader.hpp" +#include "../coding/strutil.hpp" + +#include "../platform/platform.hpp" + +#include "../std/algorithm.hpp" +#include "../std/sstream.hpp" + +#define DEFAULT_LANGUAGES "default" +#define MAX_SUPPORTED_LANGUAGES 64 +#define LANGUAGES_FILE "languages.txt" +#define LANG_DELIMETER "|" +#define SETTING_LANG_KEY "languages_priority" + +namespace languages +{ + /// sorts outLanguages according to langCodes order + static void Sort(vector const & langCodes, CodesAndNamesT & outLanguages) + { + CodesAndNamesT result; + for (size_t i = 0; i < langCodes.size(); ++i) + { + for (CodesAndNamesT::iterator it = outLanguages.begin(); it != outLanguages.end(); ++it) + { + if (langCodes[i] == it->first) + { + result.push_back(*it); + outLanguages.erase(it); + break; + } + } + } + // copy all languages left + for (CodesAndNamesT::iterator it = outLanguages.begin(); it != outLanguages.end(); ++it) + result.push_back(*it); + + result.swap(outLanguages); + CHECK_EQUAL(outLanguages.size(), MAX_SUPPORTED_LANGUAGES, ()); + } + + struct Collector + { + CodesT & m_out; + Collector(CodesT & out) : m_out(out) {} + void operator()(string const & str) + { + m_out.push_back(str); + } + }; + + void GetCurrentSettings(CodesAndNamesT & outLanguages) + { + string settingsString; + if (!Settings::Get(SETTING_LANG_KEY, settingsString)) + settingsString = DEFAULT_LANGUAGES; // @TODO get preffered languages from the system + + CodesT currentCodes; + Collector c(currentCodes); + utils::TokenizeString(settingsString, LANG_DELIMETER, c); + + GetSupportedLanguages(outLanguages); + Sort(currentCodes, outLanguages); + } + + void SaveSettings(CodesT const & langs) + { + CHECK_EQUAL(langs.size(), MAX_SUPPORTED_LANGUAGES, ()); + string const saveString = JoinStrings(langs.begin(), langs.end(), LANG_DELIMETER); + Settings::Set(SETTING_LANG_KEY, saveString); + } + + bool GetSupportedLanguages(CodesAndNamesT & outLanguages) + { + outLanguages.clear(); + FileReader file(GetPlatform().ReadPathForFile(LANGUAGES_FILE)); + string const langs = file.ReadAsText(); + istringstream stream(langs); + for (size_t i = 0; i < MAX_SUPPORTED_LANGUAGES; ++i) + { + string line; + getline(stream, line); + size_t delimIndex = string::npos; + if ((delimIndex = line.find(LANG_DELIMETER)) != string::npos) + outLanguages.push_back(make_pair(line.substr(0, delimIndex), line.substr(delimIndex + 1))); + } + return !outLanguages.empty(); + } +} diff --git a/map/languages.hpp b/map/languages.hpp new file mode 100644 index 0000000000..dfea3a814d --- /dev/null +++ b/map/languages.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include "../std/vector.hpp" +#include "../std/string.hpp" +#include "../std/utility.hpp" + +namespace languages +{ + typedef vector > CodesAndNamesT; +typedef vector CodesT; + + void GetCurrentSettings(CodesAndNamesT & outLanguages); + void SaveSettings(CodesT const & langs); + /// @return true if loaded default lang list which was used + /// for name: in features during world data generation + bool GetSupportedLanguages(CodesAndNamesT & outLanguages); +} diff --git a/map/map.pro b/map/map.pro index 54881f20c7..2fc51c278a 100644 --- a/map/map.pro +++ b/map/map.pro @@ -23,7 +23,8 @@ HEADERS += \ information_display.hpp \ settings.hpp \ location_state.hpp \ - benchmark_provider.hpp + benchmark_provider.hpp \ + languages.hpp \ SOURCES += \ feature_vec_model.cpp \ @@ -36,7 +37,8 @@ SOURCES += \ information_display.cpp \ settings.cpp \ location_state.cpp \ - benchmark_provider.cpp + benchmark_provider.cpp \ + languages.cpp \ !iphone*:!bada* { HEADERS += qgl_render_context.hpp diff --git a/qt/preferences_dialog.cpp b/qt/preferences_dialog.cpp index 89d4e8f2e5..4f2f7bde12 100644 --- a/qt/preferences_dialog.cpp +++ b/qt/preferences_dialog.cpp @@ -1,29 +1,157 @@ #include "preferences_dialog.hpp" +#include "../map/languages.hpp" + #include #include #include +#include +#include +#include +#include namespace qt { PreferencesDialog::PreferencesDialog(QWidget * parent, bool & autoUpdatesEnabled) - : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint), m_autoUpdatesEnabled(autoUpdatesEnabled) + : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint), + m_autoUpdatesEnabled(autoUpdatesEnabled) { QIcon icon(":logo.png"); setWindowIcon(icon); setWindowTitle(tr("Preferences")); - QCheckBox * updateCheckbox = new QCheckBox("Automatically check for updates on startup", this); - updateCheckbox->setCheckState(autoUpdatesEnabled ? Qt::Checked : Qt::Unchecked); - connect(updateCheckbox, SIGNAL(stateChanged(int)), this, SLOT(OnCheckboxStateChanged(int))); + m_pTable = new QTableWidget(0, 2, this); + m_pTable->setAlternatingRowColors(true); + m_pTable->setShowGrid(false); + m_pTable->setSelectionBehavior(QAbstractItemView::SelectRows); + m_pTable->verticalHeader()->setVisible(false); + m_pTable->horizontalHeader()->setVisible(false); + m_pTable->horizontalHeader()->setStretchLastSection(true); + + languages::CodesAndNamesT langList; + languages::GetCurrentSettings(langList); + for (size_t i = 0; i < langList.size(); ++i) + { + m_pTable->insertRow(i); + QTableWidgetItem * c1 = new QTableWidgetItem(langList[i].first.c_str()); + c1->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + m_pTable->setItem(i, 0, c1); + QTableWidgetItem * c2 = new QTableWidgetItem(QString::fromUtf8(langList[i].second.c_str())); + c2->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + m_pTable->setItem(i, 1, c2); + } + + QPushButton * upButton = new QPushButton(); + upButton->setIcon(QIcon(":/navig64/up.png")); + upButton->setToolTip(tr("Move up")); + upButton->setDefault(false); + connect(upButton, SIGNAL(clicked()), this, SLOT(OnUpClick())); + + QPushButton * downButton = new QPushButton(); + downButton->setIcon(QIcon(":/navig64/down.png")); + downButton->setToolTip(tr("Move down")); + downButton->setDefault(false); + connect(downButton, SIGNAL(clicked()), this, SLOT(OnDownClick())); + + QPushButton * closeButton = new QPushButton(tr("Close")); + closeButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + closeButton->setDefault(true); + connect(closeButton, SIGNAL(clicked()), this, SLOT(OnCloseClick())); + + QVBoxLayout * vBox = new QVBoxLayout(); + vBox->addWidget(upButton); + vBox->addWidget(downButton); QHBoxLayout * hBox = new QHBoxLayout(); - hBox->addWidget(updateCheckbox); - setLayout(hBox); + hBox->addLayout(vBox); + hBox->addWidget(m_pTable); + + QHBoxLayout * bottomLayout = new QHBoxLayout(); + bottomLayout->addStretch(1); + bottomLayout->setSpacing(0); + bottomLayout->addWidget(closeButton); + + QVBoxLayout * finalBox = new QVBoxLayout(); + finalBox->addLayout(hBox); + finalBox->addLayout(bottomLayout); + setLayout(finalBox); + + if (m_pTable->rowCount() > 0) + m_pTable->selectRow(0); } - void PreferencesDialog::OnCheckboxStateChanged(int state) + void PreferencesDialog::OnCloseClick() { - m_autoUpdatesEnabled = (state == Qt::Checked) ? true : false; + done(0); + } + + static void SwapRows(QTableWidget & widget, int row1, int row2) + { + QTableWidgetItem * c0 = widget.takeItem(row1, 0); + QTableWidgetItem * c1 = widget.takeItem(row1, 1); + widget.setItem(row1, 0, widget.takeItem(row2, 0)); + widget.setItem(row1, 1, widget.takeItem(row2, 1)); + widget.setItem(row2, 0, c0); + widget.setItem(row2, 1, c1); + } + + static void ShiftSelectionRange(QList & range, int offset) + { + QList newRange; + for (int i = 0; i < range.size(); ++i) + newRange.append(QTableWidgetSelectionRange(range[i].topRow() + offset, + range[i].leftColumn(), + range[i].bottomRow() + offset, + range[i].rightColumn())); + range = newRange; + } + + void PreferencesDialog::OnUpClick() + { + QList selection = m_pTable->selectedRanges(); + int const selSize = selection.size(); + if (selSize && selection[0].topRow() > 0) + { + for (int i = 0; i < selSize; ++i) + { + m_pTable->setRangeSelected(selection[i], false); + for (int j = selection[i].topRow(); j < selection[i].topRow() + selection[i].rowCount(); ++j) + SwapRows(*m_pTable, j, j - 1); + } + + ShiftSelectionRange(selection, -1); + for (int i = 0; i < selSize; ++i) + m_pTable->setRangeSelected(selection[i], true); + m_pTable->scrollToItem(m_pTable->item(selection[0].topRow(), 0)); + } + } + + void PreferencesDialog::OnDownClick() + { + QList selection = m_pTable->selectedRanges(); + int const selSize = selection.size(); + if (selSize && selection[selSize - 1].bottomRow() < m_pTable->rowCount() - 1) + { + for (int i = selSize - 1; i >= 0; --i) + { + m_pTable->setRangeSelected(selection[i], false); + for (int j = selection[i].bottomRow(); j > selection[i].bottomRow() - selection[i].rowCount(); --j) + SwapRows(*m_pTable, j, j + 1); + } + ShiftSelectionRange(selection, +1); + for (int i = 0; i < selSize; ++i) + m_pTable->setRangeSelected(selection[i], true); + m_pTable->scrollToItem(m_pTable->item(selection[selSize - 1].bottomRow(), 0)); + } + } + + void PreferencesDialog::done(int code) + { + languages::CodesT langCodes; + for (int i = 0; i < m_pTable->rowCount(); ++i) + langCodes.push_back(m_pTable->item(i, 0)->text().toUtf8().constData()); + languages::SaveSettings(langCodes); + + QDialog::done(code); } } diff --git a/qt/preferences_dialog.hpp b/qt/preferences_dialog.hpp index 250acd7ecd..8e0e560a02 100644 --- a/qt/preferences_dialog.hpp +++ b/qt/preferences_dialog.hpp @@ -2,19 +2,27 @@ #include +class QTableWidget; + namespace qt { class PreferencesDialog : public QDialog { Q_OBJECT + virtual QSize sizeHint () const { return QSize(400, 400); } + virtual void done(int); + public: explicit PreferencesDialog(QWidget * parent, bool & autoUpdatesEnabled); private slots: - void OnCheckboxStateChanged(int state); + void OnCloseClick(); + void OnUpClick(); + void OnDownClick(); private: bool & m_autoUpdatesEnabled; + QTableWidget * m_pTable; }; } // namespace qt