1 /*
2
3 Pencil2D - Traditional Animation Software
4 Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon
5 Copyright (C) 2012-2020 Matthew Chiawen Chang
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; version 2 of the License.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 */
17
18 #include "filespage.h"
19
20 #include <QSettings>
21 #include <QStandardPaths>
22
23 #include "errordialog.h"
24 #include "filemanager.h"
25 #include "pencilerror.h"
26 #include "presetdialog.h"
27
28 #include "ui_filespage.h"
29
FilesPage()30 FilesPage::FilesPage()
31 : ui(new Ui::FilesPage)
32 {
33 ui->setupUi(this);
34
35 initPreset();
36
37 connect(ui->addPreset, &QPushButton::clicked, this, &FilesPage::addPreset);
38 connect(ui->removePreset, &QPushButton::clicked, this, &FilesPage::removePreset);
39 connect(ui->setDefaultPreset, &QPushButton::clicked, this, &FilesPage::setDefaultPreset);
40 connect(ui->askPresetRbtn, &QRadioButton::toggled, this, &FilesPage::askForPresetChange);
41 connect(ui->loadLastActiveRbtn, &QRadioButton::toggled, this, &FilesPage::loadMostRecentChange);
42 connect(ui->loadDefaultPresetRbtn, &QRadioButton::toggled, this, &FilesPage::loadDefaultPreset);
43 connect(ui->presetListWidget, &QListWidget::itemChanged, this, &FilesPage::presetNameChanged);
44
45 auto spinBoxValueChange = static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged);
46 connect(ui->autosaveCheckBox, &QCheckBox::stateChanged, this, &FilesPage::autoSaveChange);
47 connect(ui->autosaveNumberBox, spinBoxValueChange, this, &FilesPage::autoSaveNumberChange);
48 }
49
~FilesPage()50 FilesPage::~FilesPage()
51 {
52 delete ui;
53 }
54
initPreset()55 void FilesPage::initPreset()
56 {
57 mPresetDir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
58 mPresetDir.mkpath("presets");
59 mPresetDir.cd("presets");
60
61 mPresetSettings = new QSettings(mPresetDir.filePath("presets.ini"), QSettings::IniFormat, this);
62
63 QListWidgetItem* defaultItem = new QListWidgetItem("Blank");
64 defaultItem->setData(Qt::UserRole, 0);
65 ui->presetListWidget->addItem(defaultItem);
66
67 bool ok = true;
68 for (const QString& key : mPresetSettings->allKeys())
69 {
70 int index = key.toInt(&ok);
71 if (!ok || index == 0 || !mPresetDir.exists(QString("%1.pclx").arg(index))) continue;
72
73 mMaxPresetIndex = qMax(index, mMaxPresetIndex);
74
75 QString name = mPresetSettings->value(key).toString();
76 if (name.isEmpty())
77 continue;
78
79 QListWidgetItem* item = new QListWidgetItem(name);
80 item->setFlags(item->flags() | Qt::ItemIsEditable);
81 item->setData(Qt::UserRole, index);
82 ui->presetListWidget->addItem(item);
83 }
84 }
85
addPreset()86 void FilesPage::addPreset()
87 {
88 int newPresetIndex = mMaxPresetIndex + 1;
89
90 // 1. save the current object to the preset folder
91 FileManager fm(this);
92 Status st = fm.save(mManager->object(), PresetDialog::getPresetPath(newPresetIndex));
93 if (!st.ok())
94 {
95 ErrorDialog errorDialog(st.title(),
96 st.description().append(tr("<br><br>Error: your preset may not have saved successfully. "
97 "If you believe that this error is an issue with Pencil2D, please create a new issue at:"
98 "<br><a href='https://github.com/pencil2d/pencil/issues'>https://github.com/pencil2d/pencil/issues</a><br>"
99 "Please include the following details in your issue:")), st.details().html());
100 errorDialog.exec();
101 return;
102 }
103
104 // 2. update the preset ini
105 QString presetName = QString("Preset %1").arg(newPresetIndex);
106 mPresetSettings->setValue(QString::number(newPresetIndex), presetName);
107 mMaxPresetIndex = newPresetIndex;
108
109 // 3. update the list widget
110 QListWidgetItem* newItem = new QListWidgetItem(presetName);
111 newItem->setFlags(newItem->flags() | Qt::ItemIsEditable);
112 newItem->setData(Qt::UserRole, newPresetIndex);
113 ui->presetListWidget->addItem(newItem);
114
115 ui->presetListWidget->scrollToBottom();
116 ui->presetListWidget->editItem(newItem);
117 }
118
removePreset()119 void FilesPage::removePreset()
120 {
121 if (ui->presetListWidget->count() <= 1) { return; }
122 if (ui->presetListWidget->selectedItems().empty()) { return; }
123
124 // 1. Remove the items from list widget
125 QList<QListWidgetItem*> itemsToRemove = ui->presetListWidget->selectedItems();
126 for (QListWidgetItem* item : itemsToRemove)
127 {
128 ui->presetListWidget->removeItemWidget(item);
129 }
130
131 // 2. Delete preset pclx files
132 for (QListWidgetItem* item : itemsToRemove)
133 {
134 int index = item->data(Qt::UserRole).toInt();
135 QFile presetFile(PresetDialog::getPresetPath(index));
136 presetFile.remove();
137 }
138
139 // 3. Delete items from the ini settings
140 for (QListWidgetItem* item : itemsToRemove)
141 {
142 int index = item->data(Qt::UserRole).toInt();
143 mPresetSettings->remove(QString::number(index));
144 }
145
146 // 4. check if the default preset has been deleted
147 int prevDefaultIndex = mManager->getInt(SETTING::DEFAULT_PRESET);
148 for (QListWidgetItem* item : itemsToRemove)
149 {
150 int index = item->data(Qt::UserRole).toInt();
151 if (index == prevDefaultIndex)
152 {
153 mManager->set(SETTING::DEFAULT_PRESET, 0);
154 }
155 }
156
157 // 5. delete items
158 for (QListWidgetItem* item : itemsToRemove)
159 {
160 delete item;
161 }
162 updateValues();
163 }
164
setDefaultPreset()165 void FilesPage::setDefaultPreset()
166 {
167 bool ok = true;
168
169 QListWidgetItem* newDefaultPresetItem = ui->presetListWidget->currentItem();
170 if (newDefaultPresetItem)
171 {
172 int newDefaultIndex = newDefaultPresetItem->data(Qt::UserRole).toInt(&ok);
173 Q_ASSERT(ok);
174
175 mManager->set(SETTING::DEFAULT_PRESET, newDefaultIndex);
176 updateValues();
177 }
178 }
179
presetNameChanged(QListWidgetItem * item)180 void FilesPage::presetNameChanged(QListWidgetItem* item)
181 {
182 // Remove characters that may be problematic for ini files
183 item->setText(item->text().remove(QChar('@')).remove(QChar('/')).remove(QChar('\\')));
184
185 bool ok = true;
186 int index = item->data(Qt::UserRole).toInt(&ok);
187 Q_ASSERT(ok);
188 mPresetSettings->setValue(QString::number(index), item->text());
189 }
190
updateValues()191 void FilesPage::updateValues()
192 {
193 bool ok = true;
194 int defaultPresetIndex = mManager->getInt(SETTING::DEFAULT_PRESET);
195
196 for (int i = 0; i < ui->presetListWidget->count(); i++)
197 {
198 QListWidgetItem* item = ui->presetListWidget->item(i);
199 int presetIndex = item->data(Qt::UserRole).toInt(&ok);
200
201 bool isDefault = presetIndex == defaultPresetIndex;
202
203 QFont font = item->font();
204 font.setBold(isDefault); // Bold text for the default item
205 item->setFont(font);
206
207 QBrush backgroundBrush = (isDefault) ? palette().light() : palette().window();
208 item->setBackground(backgroundBrush);
209 }
210 ui->autosaveCheckBox->setChecked(mManager->isOn(SETTING::AUTO_SAVE));
211 ui->autosaveNumberBox->setValue(mManager->getInt(SETTING::AUTO_SAVE_NUMBER));
212 ui->askPresetRbtn->setChecked(mManager->isOn(SETTING::ASK_FOR_PRESET));
213 ui->loadDefaultPresetRbtn->setChecked(mManager->isOn(SETTING::LOAD_DEFAULT_PRESET));
214 ui->loadLastActiveRbtn->setChecked(mManager->isOn(SETTING::LOAD_MOST_RECENT));
215 }
216
askForPresetChange(int b)217 void FilesPage::askForPresetChange(int b)
218 {
219 mManager->set(SETTING::ASK_FOR_PRESET, b != Qt::Unchecked);
220 }
221
loadMostRecentChange(int b)222 void FilesPage::loadMostRecentChange(int b)
223 {
224 mManager->set(SETTING::LOAD_MOST_RECENT, b != Qt::Unchecked);
225 }
226
loadDefaultPreset(int b)227 void FilesPage::loadDefaultPreset(int b)
228 {
229 mManager->set(SETTING::LOAD_DEFAULT_PRESET, b != Qt::Unchecked);
230 }
231
autoSaveChange(int b)232 void FilesPage::autoSaveChange(int b)
233 {
234 mManager->set(SETTING::AUTO_SAVE, b != Qt::Unchecked);
235 }
236
autoSaveNumberChange(int number)237 void FilesPage::autoSaveNumberChange(int number)
238 {
239 mManager->set(SETTING::AUTO_SAVE_NUMBER, number);
240 }
241