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
filedialog.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 "filedialog.h"
19
20#include <QSettings>
21#include <QFileInfo>
22#include <QFileDialog>
23
24#include "fileformat.h"
25#include "pencildef.h"
26
27
28QString FileDialog::getOpenFileName(QWidget* parent, FileType fileType, const QString& caption)
29{
30 QString strInitialFilePath = getLastOpenPath(fileType);
31 QString strFilter = openFileFilters(fileType);
32 QString strSelectedFilter = getFilterForFile(strFilter, strInitialFilePath);
33
34 QString filePath = QFileDialog::getOpenFileName(parent,
35 caption.isEmpty() ? openDialogCaption(fileType) : caption,
36 strInitialFilePath,
37 strFilter,
38 strSelectedFilter.isNull() ? nullptr : &strSelectedFilter);
39 if (!filePath.isEmpty())
40 {
41 setLastOpenPath(fileType, filePath);
42
43 if (fileType == FileType::ANIMATION)
44 {
45 // When we open a project, change default export path for all filetypes
46 setLastSavePaths(filePath);
47 }
48 }
49
50 return filePath;
51}
52
53QStringList FileDialog::getOpenFileNames(QWidget* parent, FileType fileType, const QString& caption)
54{
55 QString strInitialFilePath = getLastOpenPath(fileType);
56 QString strFilter = openFileFilters(fileType);
57 QString strSelectedFilter = getFilterForFile(strFilter, strInitialFilePath);
58
59 QStringList filePaths = QFileDialog::getOpenFileNames(parent,
60 caption.isEmpty() ? openDialogCaption(fileType) : caption,
61 strInitialFilePath,
62 strFilter,
63 strSelectedFilter.isNull() ? nullptr : &strSelectedFilter);
64 if (!filePaths.isEmpty() && !filePaths.first().isEmpty())
65 {
66 setLastOpenPath(fileType, filePaths.first());
67 }
68
69 return filePaths;
70}
71
72void FileDialog::setLastSavePaths(const QString& filePath)
73{
74 QFileInfo filePathInfo(filePath);
75 QDir projectPath = filePathInfo.absoluteDir();
76 QString baseName = filePathInfo.baseName();
77 QList<FileType> fileTypes = { FileType::IMAGE, FileType::IMAGE_SEQUENCE, FileType::GIF, FileType::MOVIE, FileType::SOUND, FileType::PALETTE };
78 for (FileType& fileType : fileTypes)
79 {
80 setLastSavePath(fileType, projectPath.absoluteFilePath(defaultFileName(fileType, baseName)));
81 }
82}
83
84QString FileDialog::getSaveFileName(QWidget* parent, FileType fileType, const QString& caption)
85{
86 QString strInitialFilePath = getLastSavePath(fileType);
87 QString strFilter = saveFileFilters(fileType);
88 QString strSelectedFilter = getFilterForFile(strFilter, strInitialFilePath);
89
90 QString filePath = QFileDialog::getSaveFileName(parent,
91 caption.isEmpty() ? saveDialogCaption(fileType) : caption,
92 strInitialFilePath,
93 strFilter,
94 strSelectedFilter.isNull() ? nullptr : &strSelectedFilter);
95
96 if (filePath.isEmpty()) { return QString(); }
97
98 if (!hasValidSuffix(strFilter, filePath))
99 {
100 filePath += getDefaultExtensionByFileType(fileType);
101 }
102
103 if (fileType == FileType::ANIMATION)
104 {
105 // When we save a new project, change default path for all other filetypes
106 setLastSavePaths(filePath);
107 }
108
109 setLastSavePath(fileType, filePath);
110
111 return filePath;
112}
113
114QString FileDialog::getDefaultExtensionByFileType(const FileType fileType)
115{
116 switch (fileType)
117 {
118 case FileType::ANIMATION: return PFF_DEFAULT_PROJECT_EXT;
119 case FileType::IMAGE: return PFF_DEFAULT_IMAGE_EXT;
120 case FileType::IMAGE_SEQUENCE: return PFF_DEFAULT_IMAGE_SEQ_EXT;
121 case FileType::GIF: return PFF_DEFAULT_ANIMATED_EXT;
122 case FileType::ANIMATED_IMAGE: return PFF_DEFAULT_ANIMATED_EXT;
123 case FileType::PALETTE: return PFF_DEFAULT_PALETTE_EXT;
124 case FileType::MOVIE: return PFF_DEFAULT_MOVIE_EXT;
125 case FileType::SOUND: return PFF_DEFAULT_SOUND_EXT;
126 default:
127 Q_UNREACHABLE();
128 }
129}
130
131QString FileDialog::getLastOpenPath(FileType fileType)
132{
133 QSettings setting(PENCIL2D, PENCIL2D);
134 setting.beginGroup("LastOpenPath");
135 return setting.value(toSettingKey(fileType), QDir::homePath()).toString();
136}
137
138void FileDialog::setLastOpenPath(FileType fileType, const QString& openPath)
139{
140 QSettings setting(PENCIL2D, PENCIL2D);
141 setting.beginGroup("LastOpenPath");
142
143 setting.setValue(toSettingKey(fileType), QFileInfo(openPath).absolutePath());
144}
145
146QString FileDialog::getLastSavePath(FileType fileType)
147{
148 QSettings setting(PENCIL2D, PENCIL2D);
149 setting.beginGroup("LastSavePath");
150
151 return setting.value(toSettingKey(fileType),
152 QDir::homePath() + "/" + defaultFileName(fileType)).toString();
153}
154
155void FileDialog::setLastSavePath(FileType fileType, const QString& savePath)
156{
157 QSettings setting(PENCIL2D, PENCIL2D);
158 setting.beginGroup("LastSavePath");
159
160 setting.setValue(toSettingKey(fileType), savePath);
161}
162
163QString FileDialog::openDialogCaption(FileType fileType)
164{
165 switch (fileType)
166 {
167 case FileType::ANIMATION: return tr("Open animation");
168 case FileType::IMAGE: return tr("Import image");
169 case FileType::IMAGE_SEQUENCE: return tr("Import image sequence");
170 case FileType::GIF: return tr("Import Animated GIF");
171 case FileType::ANIMATED_IMAGE: return tr("Import animated image");
172 case FileType::MOVIE: return tr("Import movie");
173 case FileType::SOUND: return tr("Import sound");
174 case FileType::PALETTE: return tr("Open palette");
175 }
176 return "";
177}
178
179QString FileDialog::saveDialogCaption(FileType fileType)
180{
181 switch (fileType)
182 {
183 case FileType::ANIMATION: return tr("Save animation");
184 case FileType::IMAGE: return tr("Export image");
185 case FileType::IMAGE_SEQUENCE: return tr("Export image sequence");
186 case FileType::GIF: return tr("Export Animated GIF");
187 case FileType::ANIMATED_IMAGE: return tr("Export animated image");
188 case FileType::MOVIE: return tr("Export movie");
189 case FileType::SOUND: return "";
190 case FileType::PALETTE: return tr("Export palette");
191 }
192 return "";
193}
194
195QString FileDialog::openFileFilters(FileType fileType)
196{
197 switch (fileType)
198 {
199 case FileType::ANIMATION: return PFF_OPEN_PROJECT_EXT_FILTER;
200 case FileType::IMAGE: return PFF_IMAGE_FILTER;
201 case FileType::IMAGE_SEQUENCE: return PFF_IMAGE_SEQ_FILTER;
202 case FileType::GIF: return PFF_GIF_EXT_FILTER;
203 case FileType::ANIMATED_IMAGE: return PFF_ANIMATED_IMAGE_EXT_FILTER;
204 case FileType::MOVIE: return PFF_MOVIE_EXT;
205 case FileType::SOUND: return PFF_SOUND_EXT_FILTER;
206 case FileType::PALETTE: return PFF_PALETTE_EXT_FILTER;
207 }
208 return "";
209}
210
211QString FileDialog::saveFileFilters(FileType fileType)
212{
213 switch (fileType)
214 {
215 case FileType::ANIMATION: return PFF_SAVE_PROJECT_EXT_FILTER;
216 case FileType::IMAGE: return "";
217 case FileType::IMAGE_SEQUENCE: return "";
218 case FileType::GIF: return QString("%1 (*.gif)").arg(tr("Animated GIF"));
219 case FileType::ANIMATED_IMAGE: return "";
220 case FileType::MOVIE: return "MP4 (*.mp4);; AVI (*.avi);; WebM (*.webm);; APNG (*.apng)";
221 case FileType::SOUND: return "";
222 case FileType::PALETTE: return PFF_PALETTE_EXT_FILTER;
223 }
224 return "";
225}
226
227bool FileDialog::hasValidSuffix(const QString& filters, const QString& filePath)
228{
229 QString fileName = QFileInfo(filePath).fileName();
230 for (const QString& filter : filters.split(";;"))
231 {
232 int start = filter.indexOf("(") + 1;
233 int end = filter.indexOf(")");
234 Q_ASSERT(start >= 1 && end >= 0);
235
236 if (QDir::match(filter.mid(start, end - start), fileName)) {
237 return true;
238 }
239 }
240 return false;
241}
242
243QString FileDialog::getFilterForFile(const QString& filters, QString filePath)
244{
245 if (!filePath.contains("."))
246 {
247 return QString();
248 }
249 QString fileExt = filePath.remove(0, filePath.lastIndexOf(".")).prepend("*");
250
251 QStringList filtersSplit = filters.split(";;");
252 for (const QString& filter : filtersSplit)
253 {
254 int start = filter.indexOf("(");
255 int end = filter.indexOf(")");
256 if (start < 0 || end < 0)
257 {
258 continue;
259 }
260 start++;
261 QStringList filterExts = filter.mid(start, end - start).split(" ");
262 if (filterExts.contains(fileExt))
263 {
264 return filter.trimmed();
265 }
266 }
267
268 return QString();
269}
270
271QString FileDialog::defaultFileName(FileType fileType, QString baseName)
272{
273 QString defaultName = tr("untitled");
274 if (!baseName.isEmpty())
275 {
276 defaultName = baseName;
277 }
278 else if (fileType == FileType::ANIMATION)
279 {
280 defaultName = tr("MyAnimation");
281 }
282
283 return defaultName.append(getDefaultExtensionByFileType(fileType));
284}
285
286QString FileDialog::toSettingKey(FileType fileType)
287{
288 switch (fileType)
289 {
290 case FileType::ANIMATION: return "Animation";
291 case FileType::IMAGE: return "Image";
292 case FileType::IMAGE_SEQUENCE: return "ImageSequence";
293 case FileType::GIF: return "Animated GIF";
294 case FileType::ANIMATED_IMAGE: return "Animated Image";
295 case FileType::MOVIE: return "Movie";
296 case FileType::SOUND: return "Sound";
297 case FileType::PALETTE: return "Palette";
298 }
299 return "";
300}
FileDialog::getLastSavePath
static QString getLastSavePath(FileType fileType)
Retrieves the last used save path for a given file type.
Definition: filedialog.cpp:146
FileDialog::getOpenFileNames
static QStringList getOpenFileNames(QWidget *parent, FileType fileType, const QString &caption=QString())
Shows a file dialog which allows the user to select multiple files to open.
Definition: filedialog.cpp:53
FileDialog::setLastSavePath
static void setLastSavePath(FileType fileType, const QString &savePath)
Saves the last used save path for a given file type.
Definition: filedialog.cpp:155
FileDialog::getSaveFileName
static QString getSaveFileName(QWidget *parent, FileType fileType, const QString &caption=QString())
Shows a file dialog which allows the user to select a file save path.
Definition: filedialog.cpp:84
FileDialog::getOpenFileName
static QString getOpenFileName(QWidget *parent, FileType fileType, const QString &caption=QString())
Shows a file dialog which allows the user to select a file to open.
Definition: filedialog.cpp:28
FileDialog::setLastOpenPath
static void setLastOpenPath(FileType fileType, const QString &openPath)
Saves the last opened file of a given type.
Definition: filedialog.cpp:138
FileDialog::getLastOpenPath
static QString getLastOpenPath(FileType fileType)
Retrieves the last opened file of a given type.
Definition: filedialog.cpp:131
QDir
QDir::absoluteFilePath
QString absoluteFilePath(const QString &fileName) const const
QDir::homePath
QString homePath()
QDir::match
bool match(const QStringList &filters, const QString &fileName)
QFileDialog::getOpenFileName
QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options)
QFileDialog::getOpenFileNames
QStringList getOpenFileNames(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options)
QFileDialog::getSaveFileName
QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options)
QFileInfo
QFileInfo::fileName
QString fileName() const const
QList
QList::first
T & first()
QList::isEmpty
bool isEmpty() const const
QObject::parent
QObject * parent() const const
QObject::tr
QString tr(const char *sourceText, const char *disambiguation, int n)
QSettings
QSettings::beginGroup
void beginGroup(const QString &prefix)
QSettings::setValue
void setValue(const QString &key, const QVariant &value)
QSettings::value
QVariant value(const QString &key, const QVariant &defaultValue) const const
QString::split
QStringList split(const QString &sep, QString::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
QString
QString::append
QString & append(QChar ch)
QString::arg
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QString::contains
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
QString::isEmpty
bool isEmpty() const const
QString::isNull
bool isNull() const const
QString::lastIndexOf
int lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
QString::prepend
QString & prepend(QChar ch)
QString::remove
QString & remove(int position, int n)
QStringList
QStringList::contains
bool contains(const QString &str, Qt::CaseSensitivity cs) const const
QVariant::toString
QString toString() const const
QWidget
Generated on Thu May 8 2025 04:47:53 for Pencil2D by doxygen 1.9.6 based on revision 4513250b1d5b1a3676ec0e67b06b7a885ceaae39