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