Pencil2D Animation
Download Community News Docs Contribute
  • Overview
  • Articles
  • Code
  •  
  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members
  • File List
Loading...
Searching...
No Matches
  • app
  • src
generalpage.cpp
1/*
2
3Pencil2D - Traditional Animation Software
4Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon
5Copyright (C) 2012-2020 Matthew Chiawen Chang
6
7This program is free software; you can redistribute it and/or
8modify it under the terms of the GNU General Public License
9as published by the Free Software Foundation; version 2 of the License.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16*/
17
18#include "generalpage.h"
19
20#include <memory>
21#include <QMessageBox>
22#include <QSettings>
23#include <QTranslator>
24
25#include "pencildef.h"
26#include "preferencemanager.h"
27
28#include "ui_generalpage.h"
29
30GeneralPage::GeneralPage() : ui(new Ui::GeneralPage)
31{
32 ui->setupUi(this);
33
34 QSettings settings(PENCIL2D, PENCIL2D);
35
36 QString languages [][3]
37 {
38 // translatable string, endonym, locale code
39 { tr("Arabic"), QStringLiteral("العربية"), "ar" },
40 { tr("Bulgarian"), QStringLiteral("Български"), "bg" },
41 { tr("Catalan"), QStringLiteral("Català"), "ca" },
42 { tr("Czech"), QStringLiteral("Čeština"), "cs" },
43 { tr("Danish"), QStringLiteral("Dansk"), "da" },
44 { tr("German"), QStringLiteral("Deutsch"), "de" },
45 { tr("Greek"), QStringLiteral("Ελληνικά"), "el" },
46 { tr("English"), QStringLiteral("English"), "en" },
47 { tr("Spanish"), QStringLiteral("Español"), "es" },
48 { tr("Estonian"), QStringLiteral("Eesti"), "et" },
49 { tr("Persian"), QStringLiteral("فارسی"), "fa" },
50 { tr("French"), QStringLiteral("Français"), "fr" },
51 { tr("Hebrew"), QStringLiteral("עברית"), "he" },
52 { tr("Hungarian"), QStringLiteral("Magyar"), "hu_HU" },
53 { tr("Indonesian"), QStringLiteral("Bahasa Indonesia"), "id" },
54 { tr("Italian"), QStringLiteral("Italiano"), "it" },
55 { tr("Japanese"), QStringLiteral("日本語"), "ja" },
56 { tr("Kabyle"), QStringLiteral("Taqbaylit"), "kab" },
57 { tr("Korean"), QStringLiteral("한국어"), "ko" },
58 { tr("Norwegian Bokmål"), QStringLiteral("Norsk bokmål"), "nb" },
59 { tr("Dutch \u2013 Netherlands"), QStringLiteral("Nederlands \u2013 Nederland"), "nl_NL" },
60 { tr("Polish"), QStringLiteral("Polski"), "pl" },
61 { tr("Portuguese \u2013 Portugal"), QStringLiteral("Português \u2013 Portugal"), "pt_PT" },
62 { tr("Portuguese \u2013 Brazil"), QStringLiteral("Português \u2013 Brasil"), "pt_BR" },
63 { tr("Russian"), QStringLiteral("Русский"), "ru" },
64 { tr("Slovene"), QStringLiteral("Slovenščina"), "sl" },
65 { tr("Swedish"), QStringLiteral("Svenska"), "sv" },
66 { tr("Turkish"), QStringLiteral("Türkçe"), "tr" },
67 { tr("Vietnamese"), QStringLiteral("Tiếng Việt"), "vi" },
68 { tr("Cantonese"), QStringLiteral("粵语"), "yue" },
69 { tr("Chinese \u2013 China"), QStringLiteral("简体中文"), "zh_CN" },
70 { tr("Chinese \u2013 Taiwan"), QStringLiteral("繁體中文"), "zh_TW" },
71 };
72
73 for (auto& lang : languages)
74 {
75 const QString itemText = QStringLiteral("%1 (%2)").arg(lang[0]).arg(lang[1]);
76 const QString localeCode = lang[2];
77 ui->languageCombo->addItem(itemText, localeCode);
78 }
79
80 int value = settings.value("windowOpacity").toInt();
81 ui->windowOpacityLevel->setValue(100 - value);
82
83 QPixmap previewCheckerboard(":background/checkerboard.png");
84 QPixmap previewWhite(32, 32);
85 QPixmap previewGrey(32, 32);
86 QPixmap previewDots(":background/dots.png");
87 QPixmap previewWeave(":background/weave.jpg");
88
89 previewWhite.fill(Qt::white);
90 previewGrey.fill(Qt::lightGray);
91
92 ui->checkerBackgroundButton->setIcon(previewCheckerboard.scaled(32, 32));
93 ui->whiteBackgroundButton->setIcon(previewWhite);
94 ui->greyBackgroundButton->setIcon(previewGrey);
95 ui->dotsBackgroundButton->setIcon(previewDots.scaled(32, 32));
96 ui->weaveBackgroundButton->setIcon(previewWeave.scaled(32, 32));
97 ui->backgroundButtons->setId(ui->checkerBackgroundButton, 1);
98 ui->backgroundButtons->setId(ui->whiteBackgroundButton, 2);
99 ui->backgroundButtons->setId(ui->greyBackgroundButton, 3);
100 ui->backgroundButtons->setId(ui->dotsBackgroundButton, 4);
101 ui->backgroundButtons->setId(ui->weaveBackgroundButton, 5);
102
103 ui->undoRedoGroupApplyButton->setDisabled(true);
104 ui->undoRedoGroupCancelButton->setDisabled(true);
105
106 auto buttonClicked = static_cast<void (QButtonGroup::*)(QAbstractButton*)>(&QButtonGroup::buttonClicked);
107 auto curIndexChanged = static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged);
108 auto spinValueChanged = static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged);
109 connect(ui->languageCombo, curIndexChanged, this, &GeneralPage::languageChanged);
110 connect(ui->windowOpacityLevel, &QSlider::valueChanged, this, &GeneralPage::windowOpacityChange);
111 connect(ui->backgroundButtons, buttonClicked, this, &GeneralPage::backgroundChanged);
112 connect(ui->shadowsBox, &QCheckBox::stateChanged, this, &GeneralPage::shadowsCheckboxStateChanged);
113 connect(ui->toolCursorsBox, &QCheckBox::stateChanged, this, &GeneralPage::toolCursorsCheckboxStateChanged);
114 connect(ui->antialiasingBox, &QCheckBox::stateChanged, this, &GeneralPage::antiAliasCheckboxStateChanged);
115 connect(ui->curveSmoothingLevel, &QSlider::valueChanged, this, &GeneralPage::curveSmoothingChanged);
116 connect(ui->highResBox, &QCheckBox::stateChanged, this, &GeneralPage::highResCheckboxStateChanged);
117 connect(ui->canvasCursorBox, &QCheckBox::stateChanged, this, &GeneralPage::canvasCursorCheckboxStateChanged);
118 connect(ui->gridSizeInputW, spinValueChanged, this, &GeneralPage::gridWidthChanged);
119 connect(ui->gridSizeInputH, spinValueChanged, this, &GeneralPage::gridHeightChanged);
120 connect(ui->actionSafeCheckBox, &QCheckBox::stateChanged, this, &GeneralPage::actionSafeCheckBoxStateChanged);
121 connect(ui->actionSafeInput, spinValueChanged, this, &GeneralPage::actionSafeAreaChanged);
122 connect(ui->titleSafeCheckBox, &QCheckBox::stateChanged, this, &GeneralPage::titleSafeCheckBoxStateChanged);
123 connect(ui->titleSafeInput, spinValueChanged, this, &GeneralPage::titleSafeAreaChanged);
124 connect(ui->safeHelperTextCheckbox, &QCheckBox::stateChanged, this, &GeneralPage::SafeAreaHelperTextCheckBoxStateChanged);
125 connect(ui->gridCheckBox, &QCheckBox::stateChanged, this, &GeneralPage::gridCheckBoxStateChanged);
126 connect(ui->framePoolSizeSpin, spinValueChanged, this, &GeneralPage::frameCacheNumberChanged);
127 connect(ui->invertScrollDirectionBox, &QCheckBox::stateChanged, this, &GeneralPage::invertScrollDirectionBoxStateChanged);
128 connect(ui->newUndoRedoCheckBox, &QCheckBox::stateChanged, this, &GeneralPage::newUndoRedoCheckBoxStateChanged);
129 connect(ui->undoStepsBox, spinValueChanged, this, &GeneralPage::undoRedoMaxStepsChanged);
130 connect(ui->undoRedoGroupApplyButton, &QPushButton::clicked, this, &GeneralPage::undoRedoApplyButtonPressed);
131 connect(ui->undoRedoGroupCancelButton, &QPushButton::clicked, this, &GeneralPage::undoRedoCancelButtonPressed);
132}
133
134GeneralPage::~GeneralPage()
135{
136 delete ui;
137}
138
139void GeneralPage::updateValues()
140{
141 int index = ui->languageCombo->findData(mManager->getString(SETTING::LANGUAGE));
142
143 if (index >= 0)
144 {
145 QSignalBlocker b(ui->languageCombo);
146 ui->languageCombo->setCurrentIndex(index);
147 }
148
149 QSignalBlocker b1(ui->curveSmoothingLevel);
150 ui->curveSmoothingLevel->setValue(mManager->getInt(SETTING::CURVE_SMOOTHING));
151 QSignalBlocker b2(ui->windowOpacityLevel);
152 ui->windowOpacityLevel->setValue(100 - mManager->getInt(SETTING::WINDOW_OPACITY));
153 QSignalBlocker b3(ui->shadowsBox);
154 ui->shadowsBox->setChecked(mManager->isOn(SETTING::SHADOW));
155 QSignalBlocker b4(ui->toolCursorsBox);
156 ui->toolCursorsBox->setChecked(mManager->isOn(SETTING::TOOL_CURSOR));
157 QSignalBlocker b5(ui->antialiasingBox);
158 ui->antialiasingBox->setChecked(mManager->isOn(SETTING::ANTIALIAS));
159 QSignalBlocker b6(ui->canvasCursorBox);
160 ui->canvasCursorBox->setChecked(mManager->isOn(SETTING::CANVAS_CURSOR));
161 QSignalBlocker b7(ui->gridSizeInputW);
162 ui->gridSizeInputW->setValue(mManager->getInt(SETTING::GRID_SIZE_W));
163 QSignalBlocker b11(ui->gridSizeInputH);
164 ui->gridSizeInputH->setValue(mManager->getInt(SETTING::GRID_SIZE_H));
165 QSignalBlocker b8(ui->gridCheckBox);
166 ui->gridCheckBox->setChecked(mManager->isOn(SETTING::GRID));
167 QSignalBlocker b16(ui->actionSafeCheckBox);
168
169 bool actionSafeOn = mManager->isOn(SETTING::ACTION_SAFE_ON);
170 ui->actionSafeCheckBox->setChecked(actionSafeOn);
171 QSignalBlocker b14(ui->actionSafeInput);
172 ui->actionSafeInput->setValue(mManager->getInt(SETTING::ACTION_SAFE));
173 QSignalBlocker b17(ui->titleSafeCheckBox);
174 bool titleSafeOn = mManager->isOn(SETTING::TITLE_SAFE_ON);
175 ui->titleSafeCheckBox->setChecked(titleSafeOn);
176 QSignalBlocker b15(ui->titleSafeInput);
177 ui->titleSafeInput->setValue(mManager->getInt(SETTING::TITLE_SAFE));
178
179 QSignalBlocker b18(ui->safeHelperTextCheckbox);
180 ui->safeHelperTextCheckbox->setChecked(mManager->isOn(SETTING::OVERLAY_SAFE_HELPER_TEXT_ON));
181
182 QSignalBlocker b9(ui->highResBox);
183 ui->highResBox->setChecked(mManager->isOn(SETTING::HIGH_RESOLUTION));
184
185 QSignalBlocker b10(ui->backgroundButtons);
186 QString bgName = mManager->getString(SETTING::BACKGROUND_STYLE);
187
188 QSignalBlocker b12(ui->framePoolSizeSpin);
189 ui->framePoolSizeSpin->setValue(mManager->getInt(SETTING::FRAME_POOL_SIZE));
190
191 QSignalBlocker bNewUndoRedoCheckBox(ui->newUndoRedoCheckBox);
192 ui->newUndoRedoCheckBox->setChecked(mManager->isOn(SETTING::NEW_UNDO_REDO_SYSTEM_ON));
193
194 QSignalBlocker bUndoRedoLimitSpinBox(ui->undoStepsBox);
195 ui->undoStepsBox->setValue(mManager->getInt(SETTING::UNDO_REDO_MAX_STEPS));
196
197 int buttonIdx = 1;
198 if (bgName == "checkerboard") buttonIdx = 1;
199 else if (bgName == "white") buttonIdx = 2;
200 else if (bgName == "grey") buttonIdx = 3;
201 else if (bgName == "dots") buttonIdx = 4;
202 else if (bgName == "weave") buttonIdx = 5;
203 else Q_ASSERT(false);
204
205 ui->backgroundButtons->button(buttonIdx)->setChecked(true);
206
207 ui->invertScrollDirectionBox->setChecked(mManager->isOn(SETTING::INVERT_SCROLL_ZOOM_DIRECTION));
208}
209
210void GeneralPage::languageChanged(int i)
211{
212 QString strLocale = ui->languageCombo->itemData(i).toString();
213 mManager->set(SETTING::LANGUAGE, strLocale);
214
215 QLocale locale = strLocale.isEmpty() ? QLocale::system() : QLocale(strLocale);
216 std::unique_ptr<QTranslator> newlangTr(new QTranslator(this));
217 if (newlangTr->load(locale, "pencil", "_", ":/i18n/"))
218 {
219 const QString title = newlangTr->translate(staticMetaObject.className(), "Restart Required");
220 const QString text = newlangTr->translate(staticMetaObject.className(), "The language change will take effect after a restart of Pencil2D");
221 if (!title.isNull() && !text.isNull())
222 {
223 QMessageBox::warning(this, title, text);
224 return;
225 }
226 }
227
228 // Failed to retrieve translation in new language, fall back to current language
229 QMessageBox::warning(this,
230 tr("Restart Required"),
231 tr("The language change will take effect after a restart of Pencil2D"));
232}
233
234void GeneralPage::backgroundChanged(QAbstractButton* button)
235{
236 QString brushName = "white";
237 if (button == ui->checkerBackgroundButton) brushName = "checkerboard";
238 else if (button == ui->whiteBackgroundButton) brushName = "white";
239 else if (button == ui->greyBackgroundButton) brushName = "grey";
240 else if (button == ui->dotsBackgroundButton) brushName = "dots";
241 else if (button == ui->weaveBackgroundButton) brushName = "weave";
242 else Q_UNREACHABLE();
243 mManager->set(SETTING::BACKGROUND_STYLE, brushName);
244}
245
246void GeneralPage::curveSmoothingChanged(int value)
247{
248 mManager->set(SETTING::CURVE_SMOOTHING, value);
249}
250
251void GeneralPage::highResCheckboxStateChanged(int b)
252{
253 mManager->set(SETTING::HIGH_RESOLUTION, b != Qt::Unchecked);
254}
255
256void GeneralPage::shadowsCheckboxStateChanged(int b)
257{
258 mManager->set(SETTING::SHADOW, b != Qt::Unchecked);
259}
260
261void GeneralPage::antiAliasCheckboxStateChanged(int b)
262{
263 mManager->set(SETTING::ANTIALIAS, b != Qt::Unchecked);
264}
265
266void GeneralPage::toolCursorsCheckboxStateChanged(int b)
267{
268 mManager->set(SETTING::TOOL_CURSOR, b != Qt::Unchecked);
269}
270
271void GeneralPage::canvasCursorCheckboxStateChanged(int b)
272{
273 mManager->set(SETTING::CANVAS_CURSOR, b != Qt::Unchecked);
274}
275
276void GeneralPage::gridWidthChanged(int value)
277{
278 mManager->set(SETTING::GRID_SIZE_W, value);
279}
280
281void GeneralPage::gridHeightChanged(int value)
282{
283 mManager->set(SETTING::GRID_SIZE_H, value);
284}
285
286void GeneralPage::actionSafeCheckBoxStateChanged(int b)
287{
288 mManager->set(SETTING::ACTION_SAFE_ON, b != Qt::Unchecked);
289 updateSafeHelperTextEnabledState();
290}
291
292void GeneralPage::actionSafeAreaChanged(int value)
293{
294 mManager->set(SETTING::ACTION_SAFE, value);
295}
296
297void GeneralPage::titleSafeCheckBoxStateChanged(int b)
298{
299 mManager->set(SETTING::TITLE_SAFE_ON, b != Qt::Unchecked);
300 updateSafeHelperTextEnabledState();
301}
302
303void GeneralPage::updateSafeHelperTextEnabledState()
304{
305 if (!ui->actionSafeCheckBox->isChecked() && !ui->titleSafeCheckBox->isChecked()) {
306 ui->safeHelperTextCheckbox->setEnabled(false);
307 ui->labSafeHelperText->setEnabled(false);
308 } else {
309 ui->safeHelperTextCheckbox->setEnabled(true);
310 ui->labSafeHelperText->setEnabled(true);
311 }
312}
313
314void GeneralPage::SafeAreaHelperTextCheckBoxStateChanged(int b)
315{
316 mManager->set(SETTING::OVERLAY_SAFE_HELPER_TEXT_ON, b != Qt::Unchecked);
317}
318
319void GeneralPage::titleSafeAreaChanged(int value)
320{
321 mManager->set(SETTING::TITLE_SAFE, value);
322}
323
324void GeneralPage::gridCheckBoxStateChanged(int b)
325{
326 mManager->set(SETTING::GRID, b != Qt::Unchecked);
327}
328
329void GeneralPage::frameCacheNumberChanged(int value)
330{
331 mManager->set(SETTING::FRAME_POOL_SIZE, value);
332}
333
334void GeneralPage::invertScrollDirectionBoxStateChanged(int b)
335{
336 mManager->set(SETTING::INVERT_SCROLL_ZOOM_DIRECTION, b != Qt::Unchecked);
337}
338
339void GeneralPage::newUndoRedoCheckBoxStateChanged()
340{
341 ui->undoRedoGroupApplyButton->setEnabled(canApplyOrCancelUndoRedoChanges());
342 ui->undoRedoGroupCancelButton->setEnabled(canApplyOrCancelUndoRedoChanges());
343}
344
345void GeneralPage::undoRedoMaxStepsChanged()
346{
347 ui->undoRedoGroupApplyButton->setEnabled(canApplyOrCancelUndoRedoChanges());
348 ui->undoRedoGroupCancelButton->setEnabled(canApplyOrCancelUndoRedoChanges());
349}
350
351bool GeneralPage::canApplyOrCancelUndoRedoChanges() const
352{
353 const bool newSystemIsOnCurrent = mManager->isOn(SETTING::NEW_UNDO_REDO_SYSTEM_ON);
354 const int maxUndoRedoStepNumCurrent = mManager->getInt(SETTING::UNDO_REDO_MAX_STEPS);
355
356 if (newSystemIsOnCurrent != ui->newUndoRedoCheckBox->isChecked()
357 || maxUndoRedoStepNumCurrent != ui->undoStepsBox->value()) {
358 return true;
359 } else {
360 return false;
361 }
362}
363
364void GeneralPage::undoRedoApplyButtonPressed()
365{
366 if (ui->undoStepsBox->value() != mManager->getInt(SETTING::UNDO_REDO_MAX_STEPS)) {
367 QMessageBox messageBox(this);
368 messageBox.setIcon(QMessageBox::Warning);
369 messageBox.setText(tr("Resets your current undo history"));
370 messageBox.setInformativeText(tr("Changing the maximum number of undo/redo steps resets your current undo/redo history. \n\nAre you sure you want to proceed?"));
371 messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
372
373 if (messageBox.exec() == QMessageBox::Yes) {
374 mManager->set(SETTING::UNDO_REDO_MAX_STEPS, ui->undoStepsBox->value());
375 } else {
376 ui->undoStepsBox->setValue(mManager->getInt(SETTING::UNDO_REDO_MAX_STEPS));
377 }
378 }
379
380 const bool systemIsOn = mManager->isOn(SETTING::NEW_UNDO_REDO_SYSTEM_ON);
381 if (ui->newUndoRedoCheckBox->isChecked() != systemIsOn) {
382 if (ui->newUndoRedoCheckBox->isChecked()) {
383 QMessageBox messageBox(this);
384 messageBox.setIcon(QMessageBox::Warning);
385 messageBox.setText(tr("Experimental feature!"));
386 messageBox.setInformativeText(tr("This feature is work in progress and may not currently allow for the same features as the current undo/redo system. Once enabled, you'll need to restart the application to start using it. \n\nDo you still want to try?"));
387 messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
388
389 if (messageBox.exec() == QMessageBox::Yes) {
390 mManager->set(SETTING::NEW_UNDO_REDO_SYSTEM_ON, true);
391 } else {
392 ui->newUndoRedoCheckBox->setCheckState(Qt::Unchecked);
393 mManager->set(SETTING::NEW_UNDO_REDO_SYSTEM_ON, false);
394 }
395 } else {
396 QMessageBox messageBox(this);
397 messageBox.setIcon(QMessageBox::Information);
398 messageBox.setText(tr("The undo/redo system will be changed on the next launch of the application"));
399 messageBox.exec();
400 mManager->set(SETTING::NEW_UNDO_REDO_SYSTEM_ON, false);
401 }
402 }
403
404 ui->undoRedoGroupCancelButton->setDisabled(true);
405 ui->undoRedoGroupApplyButton->setDisabled(true);
406}
407
408void GeneralPage::undoRedoCancelButtonPressed()
409{
410 ui->undoStepsBox->setValue(mManager->getInt(SETTING::UNDO_REDO_MAX_STEPS));
411 ui->newUndoRedoCheckBox->setCheckState(mManager->isOn(SETTING::NEW_UNDO_REDO_SYSTEM_ON) ? Qt::Checked : Qt::Unchecked);
412 ui->undoRedoGroupCancelButton->setDisabled(true);
413 ui->undoRedoGroupApplyButton->setDisabled(true);
414}
GeneralPage
Definition: generalpage.h:29
QAbstractButton
QAbstractButton::clicked
void clicked(bool checked)
QAbstractSlider::valueChanged
void valueChanged(int value)
QButtonGroup
QButtonGroup::buttonClicked
void buttonClicked(QAbstractButton *button)
QCheckBox::stateChanged
void stateChanged(int state)
QComboBox
QComboBox::currentIndexChanged
void currentIndexChanged(int index)
QLocale
QLocale::system
QLocale system()
QMessageBox
QMessageBox::Warning
Warning
QMessageBox::Yes
Yes
QMessageBox::warning
QMessageBox::StandardButton warning(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
QObject::tr
QString tr(const char *sourceText, const char *disambiguation, int n)
QPixmap
QSettings
QSignalBlocker
QSpinBox
QSpinBox::valueChanged
void valueChanged(int i)
QString
QString::arg
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QString::isEmpty
bool isEmpty() const const
QString::isNull
bool isNull() const const
QString::toInt
int toInt(bool *ok, int base) const const
Qt::Unchecked
Unchecked
Qt::white
white
QTranslator
QWidget::locale
locale
Generated on Mon Oct 26 2026 11:04:58 for Pencil2D by doxygen 1.9.6 based on revision 408563a37068daf7f1b4c6a9291daef039be8cb5