1 /*
2 SPDX-FileCopyrightText: 2009-2021 Graeme Gott <graeme@gottcode.org>
3
4 SPDX-License-Identifier: GPL-3.0-or-later
5 */
6
7 #include "language_dialog.h"
8
9 #include "language_settings.h"
10
11 #include <QDialogButtonBox>
12 #include <QCheckBox>
13 #include <QComboBox>
14 #include <QDir>
15 #include <QGridLayout>
16 #include <QFileDialog>
17 #include <QFileInfo>
18 #include <QFormLayout>
19 #include <QHBoxLayout>
20 #include <QLabel>
21 #include <QLineEdit>
22 #include <QPushButton>
23 #include <QSettings>
24 #include <QTextStream>
25 #include <QVBoxLayout>
26
27 //-----------------------------------------------------------------------------
28
LanguageDialog(QWidget * parent)29 LanguageDialog::LanguageDialog(QWidget* parent)
30 : QDialog(parent)
31 {
32 setWindowTitle(tr("Board Language"));
33
34 m_language = new QComboBox(this);
35 const QStringList languages = QDir("tanglet:").entryList(QDir::Dirs | QDir::NoDotAndDotDot);
36 for (const QString& language : languages) {
37 QSettings settings(QString("tanglet:%1/language.ini").arg(language), QSettings::IniFormat);
38 #if (QT_VERSION < QT_VERSION_CHECK(6,0,0))
39 settings.setIniCodec("UTF-8");
40 #endif
41 QString name = settings.value("Language/Name").toString();
42 if (name.isEmpty()) {
43 name = QLocale(language).nativeLanguageName();
44 }
45 int i;
46 for (i = 0; i < m_language->count(); ++i) {
47 if (m_language->itemText(i).localeAwareCompare(name) >= 0) {
48 break;
49 }
50 }
51 m_language->insertItem(i, name, language);
52 }
53 m_language->addItem(tr("Custom"), 0);
54 m_language->setCurrentIndex(m_language->count() - 1);
55 connect(m_language, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &LanguageDialog::chooseLanguage);
56
57 QSettings settings;
58 settings.beginGroup("Board");
59
60 m_dice = new QLineEdit(this);
61 m_dice_path = settings.value("Dice").toString();
62 m_dice->setText(QDir::toNativeSeparators(QFileInfo(m_dice_path).canonicalFilePath()));
63 connect(m_dice, &QLineEdit::textEdited, this, &LanguageDialog::chooseDice);
64 QPushButton* choose_dice = new QPushButton(tr("Choose..."), this);
65 connect(choose_dice, &QPushButton::clicked, this, &LanguageDialog::browseDice);
66
67 m_words = new QLineEdit(this);
68 m_words_path = settings.value("Words").toString();
69 m_words->setText(QDir::toNativeSeparators(QFileInfo(m_words_path).canonicalFilePath()));
70 connect(m_words, &QLineEdit::textEdited, this, &LanguageDialog::chooseWords);
71 QPushButton* choose_words = new QPushButton(tr("Choose..."), this);
72 connect(choose_words, &QPushButton::clicked, this, &LanguageDialog::browseWords);
73
74 m_dictionary = new QLineEdit(this);
75 m_dictionary->setText(settings.value("Dictionary").toString());
76
77 setLanguage(LanguageSettings(settings).language());
78
79 // Creat warning message
80 QLabel* warning = new QLabel(tr("<b>Note:</b> These settings will take effect when you start a new game."), this);
81
82 // Create buttons
83 m_buttons = new QDialogButtonBox(QDialogButtonBox::RestoreDefaults | QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this);
84 connect(m_buttons, &QDialogButtonBox::accepted, this, &LanguageDialog::accept);
85 connect(m_buttons, &QDialogButtonBox::rejected, this, &LanguageDialog::reject);
86 connect(m_buttons, &QDialogButtonBox::clicked, this, &LanguageDialog::clicked);
87
88 // Lay out window
89 QGridLayout* layout = new QGridLayout(this);
90 layout->setColumnStretch(1, 1);
91
92 layout->addWidget(new QLabel(tr("Language:"), this), 0, 0, Qt::AlignRight | Qt::AlignVCenter);
93 layout->addWidget(m_language, 0, 1, 1, 2, Qt::AlignLeft | Qt::AlignVCenter);
94
95 layout->addWidget(new QLabel(tr("Dice:"), this), 1, 0, Qt::AlignRight | Qt::AlignVCenter);
96 layout->addWidget(m_dice, 1, 1);
97 layout->addWidget(choose_dice, 1, 2);
98
99 layout->addWidget(new QLabel(tr("Word list:"), this), 2, 0, Qt::AlignRight | Qt::AlignVCenter);
100 layout->addWidget(m_words, 2, 1);
101 layout->addWidget(choose_words, 2, 2);
102
103 layout->addWidget(new QLabel(tr("Dictionary:"), this), 3, 0, Qt::AlignRight | Qt::AlignVCenter);
104 layout->addWidget(m_dictionary, 3, 1, 1, 2);
105
106 layout->addWidget(warning, 4, 1, 1, 2);
107
108 layout->setRowStretch(5, 1);
109 layout->setRowMinimumHeight(5, 24);
110
111 layout->addWidget(m_buttons, 6, 0, 1, 3);
112 }
113
114 //-----------------------------------------------------------------------------
115
restoreDefaults()116 void LanguageDialog::restoreDefaults()
117 {
118 QSettings settings;
119 const LanguageSettings language;
120
121 if (settings.contains("Language")) {
122 const int lang = settings.value("Language").toInt();
123 if (lang) {
124 const QString name = QLocale(QLocale::Language(lang)).name().section('_', 0, 0);
125 if (name != language.language()) {
126 settings.setValue("Board/Locale", name);
127 }
128 }
129 settings.remove("Language");
130 }
131
132 if (settings.contains("CustomDice")) {
133 settings.setValue("Board/Dice", settings.value("CustomDice"));
134 settings.remove("CustomDice");
135 settings.remove("Dice");
136 } else if (settings.contains("Dice")) {
137 const QString dice = settings.value("Dice").toString();
138 if (dice != language.dice()) {
139 settings.setValue("Board/Dice", dice);
140 }
141 settings.remove("Dice");
142 }
143
144 if (settings.contains("CustomWords")) {
145 settings.setValue("Board/Words", settings.value("CustomWords"));
146 settings.remove("CustomWords");
147 settings.remove("Words");
148 } else if (settings.contains("Words")) {
149 const QString words = settings.value("Words").toString();
150 if (words != language.words()) {
151 settings.setValue("Board/Words", words);
152 }
153 settings.remove("Words");
154 }
155
156 if (settings.contains("CustomDictionary")) {
157 settings.setValue("Board/Dictionary", settings.value("CustomDictionary"));
158 settings.remove("CustomDictionary");
159 settings.remove("Dictionary");
160 } else if (settings.contains("Dictionary")) {
161 const QString dictionary = settings.value("Dictionary").toString();
162 if (dictionary != language.dictionary()) {
163 settings.setValue("Board/Dictionary", dictionary);
164 }
165 settings.remove("Dictionary");
166 }
167 }
168
169 //-----------------------------------------------------------------------------
170
accept()171 void LanguageDialog::accept()
172 {
173 bool changed = false;
174
175 QSettings settings;
176 settings.beginGroup("Board");
177
178 const QString language = m_language->itemData(m_language->currentIndex()).toString();
179 const QString default_language = LanguageSettings().language();
180 if (settings.value("Locale", default_language).toString() != language) {
181 if (language != default_language) {
182 settings.setValue("Locale", language);
183 } else {
184 settings.remove("Locale");
185 }
186 changed = true;
187 }
188
189 if (settings.value("Dice").toString() != m_dice_path) {
190 if (!m_dice_path.isEmpty()) {
191 settings.setValue("Dice", m_dice_path);
192 } else {
193 settings.remove("Dice");
194 }
195 changed = true;
196 }
197
198 if (settings.value("Words").toString() != m_words_path) {
199 if (!m_words_path.isEmpty()) {
200 settings.setValue("Words", m_words_path);
201 } else {
202 settings.remove("Words");
203 }
204 changed = true;
205 }
206
207 const QString dictionary = m_dictionary->text();
208 if (settings.value("Dictionary").toString() != dictionary) {
209 if (!dictionary.isEmpty()) {
210 settings.setValue("Dictionary", dictionary);
211 } else {
212 settings.remove("Dictionary");
213 }
214 changed = true;
215 }
216
217 if (changed) {
218 QDialog::accept();
219 } else {
220 QDialog::reject();
221 }
222 }
223
224 //-----------------------------------------------------------------------------
225
clicked(QAbstractButton * button)226 void LanguageDialog::clicked(QAbstractButton* button)
227 {
228 if (m_buttons->buttonRole(button) == QDialogButtonBox::ResetRole) {
229 m_dice->clear();
230 m_words->clear();
231 m_dictionary->clear();
232 setLanguage(QLocale::system().name());
233 }
234 }
235
236 //-----------------------------------------------------------------------------
237
chooseLanguage(int index)238 void LanguageDialog::chooseLanguage(int index)
239 {
240 LanguageSettings settings(m_language->itemData(index).toString());
241 m_dice->setPlaceholderText(QDir::toNativeSeparators(QFileInfo(settings.dice()).canonicalFilePath()));
242 m_words->setPlaceholderText(QDir::toNativeSeparators(QFileInfo(settings.words()).canonicalFilePath()));
243 m_dictionary->setPlaceholderText(settings.dictionary());
244 }
245
246 //-----------------------------------------------------------------------------
247
browseDice()248 void LanguageDialog::browseDice()
249 {
250 QString path = m_dice->text();
251 if (path.isEmpty()) {
252 path = m_dice->placeholderText();
253 }
254 path = QFileDialog::getOpenFileName(this, tr("Choose Dice File"), path);
255 chooseDice(path);
256 }
257
258 //-----------------------------------------------------------------------------
259
chooseDice(const QString & path)260 void LanguageDialog::chooseDice(const QString& path)
261 {
262 if (!path.isEmpty()) {
263 m_dice_path = QFileInfo(path).canonicalFilePath();
264 m_dice->setText(QDir::toNativeSeparators(m_dice_path));
265 } else {
266 m_dice_path.clear();
267 }
268 }
269
270 //-----------------------------------------------------------------------------
271
browseWords()272 void LanguageDialog::browseWords()
273 {
274 QString path = m_words->text();
275 if (path.isEmpty()) {
276 path = m_words->placeholderText();
277 }
278 path = QFileDialog::getOpenFileName(this, tr("Choose Word List File"), path);
279 chooseWords(path);
280 }
281
282 //-----------------------------------------------------------------------------
283
chooseWords(const QString & path)284 void LanguageDialog::chooseWords(const QString& path)
285 {
286 if (!path.isEmpty()) {
287 m_words_path = QFileInfo(path).canonicalFilePath();
288 m_words->setText(QDir::toNativeSeparators(m_words_path));
289 } else {
290 m_words_path.clear();
291 }
292 }
293
294 //-----------------------------------------------------------------------------
295
setLanguage(const QString & language)296 void LanguageDialog::setLanguage(const QString& language)
297 {
298 int index = m_language->findData(language);
299 if (index == -1) {
300 index = m_language->findData("en");
301 }
302 m_language->setCurrentIndex(index);
303 }
304
305 //-----------------------------------------------------------------------------
306