All Classes Namespaces Functions Variables Enumerations Properties Pages
filespage.cpp
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 
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 
50 FilesPage::~FilesPage()
51 {
52  delete ui;
53 }
54 
55 void FilesPage::initPreset()
56 {
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 
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 
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 
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 
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 
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 
217 void FilesPage::askForPresetChange(int b)
218 {
219  mManager->set(SETTING::ASK_FOR_PRESET, b != Qt::Unchecked);
220 }
221 
222 void FilesPage::loadMostRecentChange(int b)
223 {
224  mManager->set(SETTING::LOAD_MOST_RECENT, b != Qt::Unchecked);
225 }
226 
227 void FilesPage::loadDefaultPreset(int b)
228 {
229  mManager->set(SETTING::LOAD_DEFAULT_PRESET, b != Qt::Unchecked);
230 }
231 
232 void FilesPage::autoSaveChange(int b)
233 {
234  mManager->set(SETTING::AUTO_SAVE, b != Qt::Unchecked);
235 }
236 
237 void FilesPage::autoSaveNumberChange(int number)
238 {
239  mManager->set(SETTING::AUTO_SAVE_NUMBER, number);
240 }
QString & append(QChar ch)
const QPalette & palette() const const
QString writableLocation(QStandardPaths::StandardLocation type)
QString filePath(const QString &fileName) const const
virtual int exec()
QString & remove(int position, int n)
Qt::ItemFlags flags() const const
QString tr(const char *sourceText, const char *disambiguation, int n)
void valueChanged(int i)
void setBold(bool enable)
void setValue(const QString &key, const QVariant &value)
QString number(int n, int base)
bool exists() const const
int toInt(bool *ok) const const
const QBrush & light() const const
QFont font() const const
void setFlags(Qt::ItemFlags flags)
UserRole
bool cd(const QString &dirName)
bool isEmpty() const const
void clicked(bool checked)
virtual QVariant data(int role) const const
void setBackground(const QBrush &brush)
void remove(const QString &key)
const QFont & font() const const
virtual void setData(int role, const QVariant &value)
QVariant value(const QString &key, const QVariant &defaultValue) const const
void stateChanged(int state)
void itemChanged(QListWidgetItem *item)
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QStringList allKeys() const const
void toggled(bool checked)
Unchecked
const QBrush & window() const const
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QString toString() const const
void setFont(const QFont &font)
QString text() const const
bool mkpath(const QString &dirPath) const const
void setText(const QString &text)
ItemIsEditable