1 /*****************************************************************************
2 * LibreMines *
3 * Copyright (C) 2020-2021 Bruno Bollos Correa *
4 * *
5 * This program is free software: you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation, either version 3 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
17 *****************************************************************************
18 */
19
20
21 #include "libreminespreferencesdialog.h"
22 #include "ui_libreminespreferencesdialog.h"
23
24 #include <QStyleFactory>
25 #include <QMessageBox>
26
27 #include "minefieldextratheme.h"
28
LibreMinesPreferencesDialog(QWidget * parent)29 LibreMinesPreferencesDialog::LibreMinesPreferencesDialog(QWidget *parent) :
30 QDialog(parent),
31 ui(new Ui::LibreMinesPreferencesDialog),
32 updateLanguageDialog(true)
33 {
34 ui->setupUi(this);
35
36 // Default system theme
37 ui->comboBoxApplicationStyle->addItem("default");
38
39 // Dark and light fusion
40 ui->comboBoxApplicationStyle->addItems({"Fusion Dark", "Fusion Light"});
41
42 // QSS
43 ui->comboBoxApplicationStyle->addItems({"ConsoleStyle", "NeonButtons"});
44
45 // QDarkStyle
46 ui->comboBoxApplicationStyle->addItems({"QDarkStyle", "QDarkStyle Light"});
47
48 // Breeze
49 ui->comboBoxApplicationStyle->addItems({"Breeze Dark", "Breeze Light"});
50
51 // Styles from system
52 ui->comboBoxApplicationStyle->addItems(QStyleFactory::keys());
53
54 // Default Minefield themes
55 ui->comboBoxMinefieldTheme->addItems({"Classic Dark", "Classic Light", "TwEmoji"});
56
57 // Load extra minefield theme (if found).
58 for(const QString& path :
59 QStandardPaths::standardLocations(QStandardPaths::AppLocalDataLocation))
60 {
61 QDir dir(path);
62
63 // Continue if the directory does not exist
64 if(!dir.exists() || !dir.cd("minefield_extra_themes"))
65 continue;
66
67 for(const QString& themeName :
68 dir.entryList(QDir::AllDirs | QDir::NoDot | QDir::NoDotDot))
69 {
70 // Add the new theme to the check box if it has a valid format
71 if(MinefieldExtraTheme::isValidTheme(dir.path(), themeName))
72 {
73 if(ui->comboBoxMinefieldTheme->findText(themeName) != -1)
74 {
75 qWarning() << "The minefield theme \'" << themeName
76 << "\' seems to be duplicate.";
77 }
78 else
79 {
80 ui->comboBoxMinefieldTheme->addItem(themeName);
81 }
82 }
83 }
84
85 }
86
87 ui->comboBoxFacesReaction->addItems({"Open Emoji Colored", "Open Emoji Black", "Open Emoji White",
88 "TwEmoji Colored", "Disable"});
89 ui->comboBoxWhenCtrlIsPressed->addItems({tr("Go to the Edge"), tr("Jump 3 Cells"), tr("Jump 5 Cells"), tr("Jump 10 Cells")});
90
91 ui->comboBoxLanguage->addItems({"English", "Português do Brasil"});
92
93 ui->comboBoxMinefieldGenerationAnimation->addItems({tr("On"), tr("Limited"), tr("Off")});
94
95
96 // Space character is not allowed. This will remove every space character of the line edit
97 // ui->lineEditUsername->setValidator(new QRegExpValidator(QRegExp("^(?i)[a-z][a-z0-9]*$")));
98 connect(ui->lineEditUsername, &QLineEdit::textChanged,
99 this, [this](QString text)
100 { ui->lineEditUsername->setText(text.remove(" ", Qt::CaseInsensitive)); });
101
102 connect(ui->comboBoxApplicationStyle, &QComboBox::currentTextChanged,
103 this, [this](QString text)
104 {
105 text.remove(" ", Qt::CaseInsensitive);
106 Q_EMIT SIGNAL_optionChanged("ApplicationTheme", text);
107 });
108
109 connect(ui->comboBoxMinefieldTheme, &QComboBox::currentTextChanged,
110 this, [this](QString text)
111 {
112 text.remove(" ", Qt::CaseInsensitive);
113 Q_EMIT SIGNAL_optionChanged("MinefieldTheme", text);
114 });
115
116 connect(ui->sbMinimumCellLength, QOverload<int>::of(&QSpinBox::valueChanged),
117 this, &LibreMinesPreferencesDialog::SLOT_updateCellLengthParameters);
118 connect(ui->sbMaximumCellLength, QOverload<int>::of(&QSpinBox::valueChanged),
119 this, &LibreMinesPreferencesDialog::SLOT_updateCellLengthParameters);
120
121 connect(ui->comboBoxLanguage, &QComboBox::currentTextChanged,
122 this, &LibreMinesPreferencesDialog::SLOT_updateLanguage);
123
124 ui->keyInputMoveLeft->setKey(Qt::Key_A);
125 ui->keyInputMoveUp->setKey(Qt::Key_W);
126 ui->keyInputMoveRight->setKey(Qt::Key_D);
127 ui->keyInputMoveDown->setKey(Qt::Key_S);
128 ui->keyInputReleaseCell->setKey(Qt::Key_O);
129 ui->keyInputFlagCell->setKey(Qt::Key_P);
130 ui->keyInputCenterCell->setKey(Qt::Key_Space);
131 }
132
~LibreMinesPreferencesDialog()133 LibreMinesPreferencesDialog::~LibreMinesPreferencesDialog()
134 {
135 delete ui;
136 }
137
optionFirstCellClean() const138 bool LibreMinesPreferencesDialog::optionFirstCellClean() const
139 {
140 return ui->cbFirstCellClean->isChecked();
141 }
142
optionCleanNeighborCellsWhenClickedOnShowedCell() const143 bool LibreMinesPreferencesDialog::optionCleanNeighborCellsWhenClickedOnShowedCell() const
144 {
145 return ui->cbCleanNeighborCellsWhenClickedOnShowedCell->isChecked();
146 }
147
optionProgressBar() const148 bool LibreMinesPreferencesDialog::optionProgressBar() const
149 {
150 return ui->cbProgressBarInGame->isChecked();
151 }
152
optionApplicationStyle() const153 QString LibreMinesPreferencesDialog::optionApplicationStyle() const
154 {
155 QString s = ui->comboBoxApplicationStyle->currentText();
156 s.remove(" ", Qt::CaseInsensitive);
157 return s;
158 }
159
optionMinefieldTheme() const160 QString LibreMinesPreferencesDialog::optionMinefieldTheme() const
161 {
162 QString s = ui->comboBoxMinefieldTheme->currentText();
163 s.remove(" ", Qt::CaseInsensitive);
164 return s;
165 }
166
optionFacesReaction() const167 QString LibreMinesPreferencesDialog::optionFacesReaction() const
168 {
169 QString s = ui->comboBoxFacesReaction->currentText();
170 s.remove(" ", Qt::CaseInsensitive);
171 return s;
172 }
173
optionUsername() const174 QString LibreMinesPreferencesDialog::optionUsername() const
175 {
176 return ui->lineEditUsername->text();
177 }
178
optionWhenCtrlIsPressed() const179 uchar LibreMinesPreferencesDialog::optionWhenCtrlIsPressed() const
180 {
181 return ui->comboBoxWhenCtrlIsPressed->currentIndex();
182 }
183
optionMinimumCellLength() const184 int LibreMinesPreferencesDialog::optionMinimumCellLength() const
185 {
186 return ui->sbMinimumCellLength->value();
187 }
188
optionMaximumCellLength() const189 int LibreMinesPreferencesDialog::optionMaximumCellLength() const
190 {
191 return ui->sbMaximumCellLength->value();
192 }
193
optionsLanguage() const194 QString LibreMinesPreferencesDialog::optionsLanguage() const
195 {
196 if(ui->comboBoxLanguage->currentText().compare("English", Qt::CaseInsensitive) == 0)
197 return "en";
198 if(ui->comboBoxLanguage->currentText().compare("Português do Brasil", Qt::CaseInsensitive) == 0)
199 return "pt_BR";
200 return "";
201 }
202
optionMinefieldGenerationAnimation() const203 uchar LibreMinesPreferencesDialog::optionMinefieldGenerationAnimation() const
204 {
205 return ui->comboBoxMinefieldGenerationAnimation->currentIndex();
206 }
207
optionMinefieldGenerationAnimationString() const208 QString LibreMinesPreferencesDialog::optionMinefieldGenerationAnimationString() const
209 {
210 return ui->comboBoxMinefieldGenerationAnimation->currentText();
211 }
212
optionAskToSaveMatchScoreBehaviour() const213 AskToSaveMatchScore LibreMinesPreferencesDialog::optionAskToSaveMatchScoreBehaviour() const
214 {
215 if(ui->rbSaveScoreNever->isChecked())
216 return LibreMines::SaveNever;
217 if(ui->rbSaveScoreAlways->isChecked())
218 return LibreMines::SaveAlways;
219 if(ui->rbSaveScoreWhenHighScore->isChecked())
220 return LibreMines::SaveWhenNewHighScore;
221 if(ui->rbSaveScoreWhenGameCompleted->isChecked())
222 return LibreMines::SaveWhenGameCompleted;
223 if(ui->rbSaveScoreWhenHighScoreAndGameCompleted->isChecked())
224 return LibreMines::SaveWhenGameCompleted | LibreMines::SaveWhenNewHighScore;
225 return LibreMines::SaveNever;
226 }
227
setOptionFirstCellClean(const QString & option)228 void LibreMinesPreferencesDialog::setOptionFirstCellClean(const QString &option)
229 {
230 ui->cbFirstCellClean->setChecked(option.compare("On", Qt::CaseInsensitive) == 0);
231 }
232
setOptionCleanNeighborCellsWhenClickedOnShowedCell(const QString & option)233 void LibreMinesPreferencesDialog::setOptionCleanNeighborCellsWhenClickedOnShowedCell(const QString &option)
234 {
235 ui->cbCleanNeighborCellsWhenClickedOnShowedCell->setChecked(option.compare("On", Qt::CaseInsensitive) == 0);
236 }
237
setOptionProgressBar(const QString & option)238 void LibreMinesPreferencesDialog::setOptionProgressBar(const QString &option)
239 {
240 ui->cbProgressBarInGame->setChecked(option.compare("On", Qt::CaseInsensitive) == 0);
241 }
242
setOptionApplicationStyle(const QString & option)243 void LibreMinesPreferencesDialog::setOptionApplicationStyle(const QString &option)
244 {
245 QString s = option;
246 if(option.compare("FusionDark", Qt::CaseInsensitive) == 0){ s = "Fusion Dark"; }
247 else if(option.compare("FusionLight", Qt::CaseInsensitive) == 0){ s = "Fusion Light"; }
248 else if(option.compare("QDarkStyleLight", Qt::CaseInsensitive) == 0){ s = "QDarkStyle Light"; }
249 else if(option.compare("BreezeDark", Qt::CaseInsensitive) == 0){ s = "Breeze Dark"; }
250 else if(option.compare("BreezeLight", Qt::CaseInsensitive) == 0){ s = "Breeze Light"; }
251
252 ui->comboBoxApplicationStyle->setCurrentText(s);
253 }
254
setOptionMinefieldTheme(const QString & option)255 void LibreMinesPreferencesDialog::setOptionMinefieldTheme(const QString &option)
256 {
257 QString s = option;
258 if(option.compare("ClassicLight", Qt::CaseInsensitive) == 0){ s = "Classic Light"; }
259 else if(option.compare("ClassicDark", Qt::CaseInsensitive) == 0){ s = "Classic Dark"; }
260 else if(option.compare("TwEmoji", Qt::CaseInsensitive) == 0){ s = "TwEmoji"; }
261
262 ui->comboBoxMinefieldTheme->setCurrentText(s);
263 }
264
setOptionFacesReaction(const QString & option)265 void LibreMinesPreferencesDialog::setOptionFacesReaction(const QString &option)
266 {
267 QString s = "Disable";
268 if(option.compare("OpenEmojiColored", Qt::CaseInsensitive) == 0){ s = "Open Emoji Colored"; }
269 else if(option.compare("OpenEmojiBlack", Qt::CaseInsensitive) == 0){ s = "Open Emoji Black"; }
270 else if(option.compare("OpenEmojiWhite", Qt::CaseInsensitive) == 0){ s = "Open Emoji White"; }
271 else if(option.compare("TwEmojiColored", Qt::CaseInsensitive) == 0){ s = "TwEmoji Colored"; }
272
273 ui->comboBoxFacesReaction->setCurrentText(s);
274 }
275
setOptionUsername(const QString & username)276 void LibreMinesPreferencesDialog::setOptionUsername(const QString &username)
277 {
278 ui->lineEditUsername->setText(username);
279 }
280
setOptionWhenCtrlIsPressed(const uchar option)281 void LibreMinesPreferencesDialog::setOptionWhenCtrlIsPressed(const uchar option)
282 {
283 if(ui->comboBoxWhenCtrlIsPressed->count() > option)
284 ui->comboBoxWhenCtrlIsPressed->setCurrentIndex(option);
285 }
286
setOptionMinimumCellLength(const int option)287 void LibreMinesPreferencesDialog::setOptionMinimumCellLength(const int option)
288 {
289 ui->sbMinimumCellLength->setValue(option);
290 }
291
setOptionMaximumCellLength(const int option)292 void LibreMinesPreferencesDialog::setOptionMaximumCellLength(const int option)
293 {
294 ui->sbMaximumCellLength->setValue(option);
295 }
296
setOptionLanguage(const QString & option)297 void LibreMinesPreferencesDialog::setOptionLanguage(const QString &option)
298 {
299 QString s = "English";
300 if(option.compare("pt_BR", Qt::CaseInsensitive) == 0)
301 s = "Português do Brasil";
302
303 // Ugly way to avoid the creation of the dialog when this function is called
304 updateLanguageDialog = false;
305 ui->comboBoxLanguage->setCurrentText(s);
306 QTimer::singleShot(10, this, [this](){ updateLanguageDialog = true; });
307 }
308
setOptionMinefieldGenerationAnimation(const uchar option)309 void LibreMinesPreferencesDialog::setOptionMinefieldGenerationAnimation(const uchar option)
310 {
311 if(ui->comboBoxMinefieldGenerationAnimation->count() > option)
312 ui->comboBoxMinefieldGenerationAnimation->setCurrentIndex(option);
313 }
314
setOptionMinefieldGenerationAnimation(const QString & option)315 void LibreMinesPreferencesDialog::setOptionMinefieldGenerationAnimation(const QString &option)
316 {
317 ui->comboBoxMinefieldGenerationAnimation->setCurrentText(option);
318 }
319
setOptionAskToSaveMatchScoreBehaviour(const uchar option)320 void LibreMinesPreferencesDialog::setOptionAskToSaveMatchScoreBehaviour(const uchar option)
321 {
322 switch(option)
323 {
324 case LibreMines::SaveNever:
325 return ui->rbSaveScoreNever->setChecked(true);
326 case LibreMines::SaveWhenNewHighScore:
327 return ui->rbSaveScoreWhenHighScore->setChecked(true);
328 case LibreMines::SaveWhenGameCompleted:
329 return ui->rbSaveScoreWhenGameCompleted->setChecked(true);
330 case LibreMines::SaveWhenGameCompleted | LibreMines::SaveWhenNewHighScore:
331 return ui->rbSaveScoreWhenHighScoreAndGameCompleted->setChecked(true);
332 case LibreMines::SaveAlways:
333 return ui->rbSaveScoreAlways->setChecked(true);
334 }
335
336 return ui->rbSaveScoreNever->setChecked(true);
337 }
338
optionKeyboardControllerKeys() const339 QList<int> LibreMinesPreferencesDialog::optionKeyboardControllerKeys() const
340 {
341 return
342 {
343 ui->keyInputMoveLeft->currentKey(),
344 ui->keyInputMoveUp->currentKey(),
345 ui->keyInputMoveRight->currentKey(),
346 ui->keyInputMoveDown->currentKey(),
347 ui->keyInputReleaseCell->currentKey(),
348 ui->keyInputFlagCell->currentKey(),
349 ui->keyInputCenterCell->currentKey()
350 };
351 }
352
optionKeyboardControllerKeysString() const353 QString LibreMinesPreferencesDialog::optionKeyboardControllerKeysString() const
354 {
355 QString s;
356
357 s += QString::number(ui->keyInputMoveLeft->currentKey(), 16);
358 s += ' ';
359 s += QString::number(ui->keyInputMoveUp->currentKey(), 16);
360 s += ' ';
361 s += QString::number(ui->keyInputMoveRight->currentKey(), 16);
362 s += ' ';
363 s += QString::number(ui->keyInputMoveDown->currentKey(), 16);
364 s += ' ';
365 s += QString::number(ui->keyInputReleaseCell->currentKey(), 16);
366 s += ' ';
367 s += QString::number(ui->keyInputFlagCell->currentKey(), 16);
368 s += ' ';
369 s += QString::number(ui->keyInputCenterCell->currentKey(), 16);
370
371 return s;
372 }
373
setOptionKeyboardControllerKeys(const QList<int> & keys)374 void LibreMinesPreferencesDialog::setOptionKeyboardControllerKeys(const QList<int> &keys)
375 {
376 ui->keyInputMoveLeft->setKey(keys.at(0));
377 ui->keyInputMoveUp->setKey(keys.at(1));
378 ui->keyInputMoveRight->setKey(keys.at(2));
379 ui->keyInputMoveDown->setKey(keys.at(3));
380 ui->keyInputReleaseCell->setKey(keys.at(4));
381 ui->keyInputFlagCell->setKey(keys.at(5));
382 if(keys.size() == 7)
383 {
384 ui->keyInputCenterCell->setKey(keys.at(6));
385 }
386 }
387
closeEvent(QCloseEvent * e)388 void LibreMinesPreferencesDialog::closeEvent(QCloseEvent *e)
389 {
390 Q_UNUSED(e);
391 this->hide();
392 }
393
hideEvent(QHideEvent * e)394 void LibreMinesPreferencesDialog::hideEvent(QHideEvent *e)
395 {
396 Q_UNUSED(e);
397 Q_EMIT SIGNAL_visibilityChanged(false);
398 }
399
showEvent(QShowEvent * e)400 void LibreMinesPreferencesDialog::showEvent(QShowEvent *e)
401 {
402 Q_UNUSED(e);
403 Q_EMIT SIGNAL_visibilityChanged(true);
404 }
405
SLOT_updateCellLengthParameters()406 void LibreMinesPreferencesDialog::SLOT_updateCellLengthParameters()
407 {
408 ui->sbMinimumCellLength->setMaximum(ui->sbMaximumCellLength->value());
409 ui->sbMaximumCellLength->setMinimum(ui->sbMinimumCellLength->value());
410 }
411
SLOT_updateLanguage()412 void LibreMinesPreferencesDialog::SLOT_updateLanguage()
413 {
414 if(updateLanguageDialog)
415 {
416 QMessageBox::information(this, tr("Restart LibreMines to apply this preference!"),
417 tr("Please restart the application to redefine your language"));
418 }
419 }
420
421