File indexing completed on 2025-02-02 04:18:27
0001 /* 0002 * SPDX-FileCopyrightText: 2016 Jouni Pentikäinen <joupent@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kis_dlg_import_image_sequence.h" 0008 0009 #include "KisDocument.h" 0010 #include "KisMainWindow.h" 0011 #include "kis_image.h" 0012 #include "kis_image_animation_interface.h" 0013 #include "KisImportExportManager.h" 0014 #include "KoFileDialog.h" 0015 #include <QStandardPaths> 0016 #include <QRegExp> 0017 0018 0019 class KisDlgImportImageSequence::ListItem : QListWidgetItem { 0020 0021 public: 0022 ListItem(const QString &text, QListWidget *view, QCollator *collator) 0023 : QListWidgetItem(text, view) 0024 , collator(collator) 0025 {} 0026 0027 bool operator <(const QListWidgetItem &other) const override 0028 { 0029 if (collator->numericMode()) { 0030 const QRegExp rx(QLatin1String("[^0-9]+")); 0031 0032 #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) 0033 QStringList ours = text().split(rx, Qt::SkipEmptyParts); 0034 QStringList theirs = other.text().split(rx, Qt::SkipEmptyParts); 0035 #else 0036 QStringList ours = text().split(rx, QString::SkipEmptyParts); 0037 QStringList theirs = other.text().split(rx, QString::SkipEmptyParts); 0038 #endif 0039 0040 // Let's compare the last numbers -- they are most likely to be the serial numbers 0041 if (ours.size() > 0 && theirs.size() > 0) { 0042 return (ours.last().toInt() < theirs.last().toInt()); 0043 } 0044 0045 } 0046 return collator->compare(this->text(), other.text()) < 0; 0047 } 0048 0049 private: 0050 QCollator *collator; 0051 }; 0052 0053 KisDlgImportImageSequence::KisDlgImportImageSequence(KisMainWindow *mainWindow, KisDocument *document) : 0054 KoDialog(mainWindow), 0055 m_mainWindow(mainWindow), 0056 m_document(document) 0057 { 0058 setButtons(Ok | Cancel); 0059 setDefaultButton(Ok); 0060 0061 QWidget * page = new QWidget(this); 0062 m_ui.setupUi(page); 0063 setMainWidget(page); 0064 0065 enableButtonOk(false); 0066 0067 m_ui.cmbOrder->addItem(i18n("Ascending"), Ascending); 0068 m_ui.cmbOrder->addItem(i18n("Descending"), Descending); 0069 m_ui.cmbOrder->setCurrentIndex(0); 0070 0071 m_ui.cmbSortMode->addItem(i18n("Alphabetical"), Natural); 0072 m_ui.cmbSortMode->addItem(i18n("Numerical"), Numerical); 0073 m_ui.cmbSortMode->setCurrentIndex(1); 0074 0075 m_ui.lstFiles->setSelectionMode(QAbstractItemView::ExtendedSelection); 0076 0077 connect(m_ui.btnAddImages, &QAbstractButton::clicked, this, &KisDlgImportImageSequence::slotAddFiles); 0078 connect(m_ui.btnRemove, &QAbstractButton::clicked, this, &KisDlgImportImageSequence::slotRemoveFiles); 0079 connect(m_ui.spinStep, SIGNAL(valueChanged(int)), this, SLOT(slotSkipChanged(int))); 0080 connect(m_ui.cmbOrder, SIGNAL(currentIndexChanged(int)), this, SLOT(slotOrderOptionsChanged(int))); 0081 connect(m_ui.cmbSortMode, SIGNAL(currentIndexChanged(int)), this, SLOT(slotOrderOptionsChanged(int))); 0082 connect(m_ui.autoAddHoldframesBox, &QCheckBox::stateChanged, this, &KisDlgImportImageSequence::autoAddHoldframes); 0083 // cold initialization of the controls 0084 slotSkipChanged(m_ui.spinStep->value()); 0085 slotOrderOptionsChanged(m_ui.cmbOrder->currentIndex()); 0086 slotOrderOptionsChanged(m_ui.cmbSortMode->currentIndex()); 0087 m_ui.beginFromZeroIndexBox->hide(); 0088 } 0089 0090 QStringList KisDlgImportImageSequence::files() 0091 { 0092 QStringList list; 0093 0094 for (int i=0; i < m_ui.lstFiles->count(); i++) { 0095 list.append(m_ui.lstFiles->item(i)->text()); 0096 } 0097 0098 return list; 0099 } 0100 0101 int KisDlgImportImageSequence::firstFrame() 0102 { 0103 return m_ui.spinFirstFrame->value(); 0104 } 0105 0106 int KisDlgImportImageSequence::step() 0107 { 0108 return m_ui.spinStep->value(); 0109 } 0110 0111 bool KisDlgImportImageSequence::autoAddHoldframes(){ 0112 0113 bool isChecked = m_ui.autoAddHoldframesBox->isChecked(); 0114 if(isChecked && m_ui.cmbOrder->currentIndex() == 0){ 0115 m_ui.beginFromZeroIndexBox->show(); 0116 } 0117 else { 0118 m_ui.beginFromZeroIndexBox->hide(); 0119 } 0120 return isChecked; 0121 } 0122 0123 void KisDlgImportImageSequence::slotAddFiles() 0124 { 0125 QStringList urls = showOpenFileDialog(); 0126 0127 if (!urls.isEmpty()) { 0128 Q_FOREACH(QString url, urls) { 0129 new ListItem(url, m_ui.lstFiles, &m_collator); 0130 } 0131 0132 sortFileList(); 0133 } 0134 0135 enableButtonOk(m_ui.lstFiles->count() > 0); 0136 } 0137 0138 QStringList KisDlgImportImageSequence::showOpenFileDialog() 0139 { 0140 KoFileDialog dialog(this, KoFileDialog::ImportFiles, "OpenDocument"); 0141 dialog.setDefaultDir(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)); 0142 dialog.setMimeTypeFilters(KisImportExportManager::supportedMimeTypes(KisImportExportManager::Import)); 0143 dialog.setCaption(i18n("Import Images")); 0144 0145 return dialog.filenames(); 0146 } 0147 0148 0149 0150 void KisDlgImportImageSequence::slotRemoveFiles() 0151 { 0152 QList<QListWidgetItem*> selected = m_ui.lstFiles->selectedItems(); 0153 0154 Q_FOREACH(QListWidgetItem *item, selected) { 0155 delete item; 0156 } 0157 0158 enableButtonOk(m_ui.lstFiles->count() > 0); 0159 } 0160 0161 void KisDlgImportImageSequence::slotSkipChanged(int) 0162 { 0163 int documentFps = m_document->image()->animationInterface()->framerate(); 0164 float sourceFps = 1.0f * documentFps / m_ui.spinStep->value(); 0165 0166 m_ui.lblFramerate->setText(i18n("Source fps: %1", sourceFps)); 0167 } 0168 0169 void KisDlgImportImageSequence::slotOrderOptionsChanged(int) 0170 { 0171 0172 if(m_ui.cmbSortMode->currentIndex() == 0){ // we shouldn't add hold frames automatically if they are sorted alphabetically 0173 m_ui.autoAddHoldframesBox->setChecked(false); 0174 m_ui.autoAddHoldframesBox->setEnabled(false); 0175 } 0176 else { 0177 m_ui.autoAddHoldframesBox->setEnabled(true); 0178 } 0179 0180 if(m_ui.cmbOrder->currentIndex() == 1){ 0181 m_ui.beginFromZeroIndexBox->setChecked(false); //redundant 0182 m_ui.beginFromZeroIndexBox->hide(); 0183 } 0184 this->sortOrder = m_ui.cmbOrder->currentIndex(); 0185 sortFileList(); 0186 } 0187 0188 bool KisDlgImportImageSequence::startFrom1(){ 0189 return m_ui.beginFromZeroIndexBox->isChecked(); 0190 } 0191 0192 int KisDlgImportImageSequence::isAscending(){ 0193 return this->sortOrder; 0194 } 0195 0196 void KisDlgImportImageSequence::sortFileList() 0197 { 0198 int order = m_ui.cmbOrder->currentData().toInt(); 0199 bool numeric = m_ui.cmbSortMode->currentData().toInt() == Numerical; 0200 0201 m_collator.setNumericMode(numeric); 0202 m_ui.lstFiles->sortItems((order == Ascending) ? Qt::AscendingOrder : Qt::DescendingOrder); 0203 }