18 #include "importimageseqdialog.h"
19 #include "ui_importimageseqoptions.h"
20 #include "ui_importimageseqpreview.h"
25 #include "predefinedsetmodel.h"
26 #include "viewmanager.h"
28 #include <QProgressDialog>
29 #include <QMessageBox>
32 #include <QDialogButtonBox>
33 #include <QPushButton>
35 ImportImageSeqDialog::ImportImageSeqDialog(
QWidget* parent, Mode mode, FileType fileType, ImportCriteria importCriteria) :
36 ImportExportDialog(parent, mode, fileType), mParent(parent), mImportCriteria(importCriteria), mFileType(fileType)
39 uiOptionsBox =
new Ui::ImportImageSeqOptions;
40 uiOptionsBox->
setupUi(getOptionsGroupBox());
42 uiGroupBoxPreview =
new Ui::ImportImageSeqPreviewGroupBox;
43 uiGroupBoxPreview->setupUi(getPreviewGroupBox());
45 if (importCriteria == ImportCriteria::PredefinedSet) {
46 setupPredefinedLayout();
51 getDialogButtonBox()->
button(QDialogButtonBox::StandardButton::Ok)->
setEnabled(
false);
54 void ImportImageSeqDialog::setupLayout()
57 hideInstructionsLabel(
true);
59 if (mFileType == FileType::GIF) {
66 connect(
this, &ImportImageSeqDialog::filePathsChanged,
this, &ImportImageSeqDialog::validateFiles);
69 void ImportImageSeqDialog::setupPredefinedLayout()
72 setInstructionsLabel(
tr(
"Select an image that matches the criteria: MyFile000.png, eg. Joe001.png \n"
73 "The importer will search and find images matching the same criteria. You can see the result in the preview box below."));
74 hideOptionsGroupBox(
true);
75 hidePreviewGroupBox(
false);
77 connect(
this, &ImportImageSeqDialog::filePathsChanged,
this, &ImportImageSeqDialog::updatePreviewList);
80 ImportImageSeqDialog::~ImportImageSeqDialog()
85 if (uiGroupBoxPreview) {
86 delete uiGroupBoxPreview;
90 int ImportImageSeqDialog::getSpace()
92 return uiOptionsBox->spaceSpinBox->value();
95 void ImportImageSeqDialog::updatePreviewList(
const QStringList& list)
98 if (mImportCriteria == ImportCriteria::PredefinedSet)
102 Status status = Status::OK;
103 status = validateKeySet(keySet, list);
105 QPushButton* okButton = getDialogButtonBox()->
button(QDialogButtonBox::StandardButton::Ok);
106 if (status == Status::FAIL)
110 status.description(),
117 setPreviewModel(keySet);
121 const PredefinedKeySet ImportImageSeqDialog::generatePredefinedKeySet()
const
126 const QStringList& filenames = setParams.filenames;
127 const int& digits = setParams.digits;
128 const QString& folderPath = setParams.folderPath;
130 for (
int i = 0; i < filenames.
size(); i++)
132 const int& frameIndex = filenames[i].
mid(setParams.dot - digits, digits).toInt();
133 const QString& absolutePath = folderPath + filenames[i];
135 keySet.insert(frameIndex, absolutePath);
137 keySet.setLayerName(setParams.prefix);
144 uiGroupBoxPreview->tableView->setModel(previewModel);
145 uiGroupBoxPreview->tableView->setColumnWidth(0, 500);
146 uiGroupBoxPreview->tableView->setColumnWidth(1, 100);
149 ImportExportDialog::Mode ImportImageSeqDialog::getMode()
151 return ImportExportDialog::Import;
154 FileType ImportImageSeqDialog::getFileType()
159 void ImportImageSeqDialog::setSpace(
int number)
162 uiOptionsBox->spaceSpinBox->setValue(number);
165 void ImportImageSeqDialog::importArbitrarySequence()
168 int number = getSpace();
172 hideQuestionMark(progress);
176 int totalImagesToImport = files.
count();
177 int imagesImportedSoFar = 0;
178 progress.setMaximum(totalImagesToImport);
181 bool failedImport =
false;
182 for (
const QString& strImgFile : files)
186 if (strImgFileLower.
endsWith(
".png") ||
188 strImgFileLower.
endsWith(
".jpeg") ||
193 mEditor->importImage(strImgFile);
195 imagesImportedSoFar++;
196 progress.setValue(imagesImportedSoFar);
199 if (progress.wasCanceled())
206 failedFiles += strImgFile +
"\n";
213 for (
int i = 1; i < number; i++)
215 mEditor->scrubForward();
223 tr(
"Unable to import") + failedFiles,
229 emit notifyAnimationLengthChanged();
235 QString strFilePath = getFilePath();
243 QString digit = strFilePath.
mid(slash + 1, dot - slash - 1);
247 for (
int i = digit.
length() - 1; i > 0; i--)
264 digit = strFilePath.
mid(dot - digits, digits);
265 QString prefix = strFilePath.
mid(slash + 1, dot - slash - digits - 1);
270 if (sList.
isEmpty()) {
return setParams; }
275 for (
int i = 0; i < sList.
size(); i++)
277 if (sList[i].startsWith(prefix) &&
278 sList[i].
length() == validLength &&
279 sList[i].
mid(sList[i].lastIndexOf(
".") - digits, digits).toInt() > 0 &&
282 finalList.
append(sList[i]);
285 if (finalList.
isEmpty()) {
return setParams; }
291 for (
QString fileName : finalList) {
292 absolutePaths << path + fileName;
296 setParams.digits = digits;
297 setParams.filenames = finalList;
298 setParams.folderPath = path;
299 setParams.absolutePaths = absolutePaths;
300 setParams.prefix = prefix;
304 void ImportImageSeqDialog::importPredefinedSet()
310 hideQuestionMark(progress);
314 int totalImagesToImport = keySet.size();
315 int imagesImportedSoFar = 0;
316 progress.setMaximum(totalImagesToImport);
318 mEditor->createNewBitmapLayer(keySet.layerName());
320 for (
int i = 0; i < keySet.size(); i++)
322 const int& frameIndex = keySet.keyFrameIndexAt(i);
323 const QString& filePath = keySet.filePathAt(i);
325 mEditor->scrubTo(frameIndex);
326 bool ok = mEditor->importImage(filePath);
327 imagesImportedSoFar++;
329 progress.setValue(imagesImportedSoFar);
332 if (progress.wasCanceled())
340 emit notifyAnimationLengthChanged();
345 return ImportExportDialog::getFilePaths();
353 Status status = Status::OK;
355 if (filepaths.
isEmpty()) { status = Status::FAIL; }
357 if (keySet.isEmpty())
359 status = Status::FAIL;
363 if (status == Status::FAIL)
365 status.setTitle(
tr(
"Invalid path"));
366 status.setDescription(
QString(
tr(
"The following file did not meet the criteria: \n%1 \n\nRead the instructions and try again")).arg(failedPathsString));
374 QString failedPathsString =
"";
376 Status status = Status::OK;
378 if (filepaths.
isEmpty()) { status = Status::FAIL; }
380 for (
int i = 0; i < filepaths.
count(); i++)
384 failedPathsString += filepaths.
at(i) +
"\n";
387 if (!failedPathsString.
isEmpty())
389 status = Status::FAIL;
390 status.setTitle(
tr(
"Invalid path"));
391 status.setDescription(
QString(
tr(
"The following file(-s) did not meet the criteria: \n%1")).arg(failedPathsString));
394 if (status == Status::OK)
396 getDialogButtonBox()->
button(QDialogButtonBox::StandardButton::Ok)->
setEnabled(
true);
bool isDigit() const const
const T & at(int i) const const
bool endsWith(const T &value) const const
int lastIndexOf(QStringView str, int from) const const
QString tr(const char *sourceText, const char *disambiguation, int n)
int lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
int count(const T &value) const const
void processEvents(QEventLoop::ProcessEventsFlags flags)
void append(const T &value)
bool isEmpty() const const
bool isEmpty() const const
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const const
QString createSeparatedList(const QStringList &list) const const
QString toLower() const const
bool exists() const const
QString mid(int position, int n) const const
QStringList entryList(QDir::Filters filters, QDir::SortFlags sort) const const
const QChar at(int position) const const
QList< T > mid(int pos, int length) const const
QString left(int n) const const
QMessageBox::StandardButton warning(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)