diff --git a/toonz/sources/common/tsystem/tsystem.cpp b/toonz/sources/common/tsystem/tsystem.cpp index bf5e3d3..8792f33 100644 --- a/toonz/sources/common/tsystem/tsystem.cpp +++ b/toonz/sources/common/tsystem/tsystem.cpp @@ -228,7 +228,7 @@ void setPathsPermissions(const TFilePathSet &pathSet, f.setPermissions(permissions); } } -} +} // namespace // gestire exception void TSystem::mkDir(const TFilePath &path) { @@ -438,7 +438,7 @@ public: //------------------------------------------------------------ /*! return the folder path list which is readable and executable -*/ + */ void TSystem::readDirectory_Dir_ReadExe(TFilePathSet &dst, const TFilePath &path) { QStringList dirItems; @@ -496,7 +496,7 @@ void TSystem::readDirectory_DirItems(QStringList &dst, const TFilePath &path) { //------------------------------------------------------------ /*! to retrieve the both lists with groupFrames option = on and off. -*/ + */ void TSystem::readDirectory(TFilePathSet &groupFpSet, TFilePathSet &allFpSet, const TFilePath &path) { if (!TFileStatus(path).isDirectory()) @@ -620,7 +620,7 @@ void TSystem::readDirectory(TFilePathSet &dst, const QDir &dir, while (FindNextFile(hFind, &find_dir_data)) addEntry(); } #else - entries = (dir.entryList(dir.filter() | QDir::NoDotAndDotDot)); + entries = (dir.entryList(dir.filter() | QDir::NoDotAndDotDot)); #endif TFilePath dirPath(dir.path().toStdWString()); @@ -690,6 +690,8 @@ void TSystem::readDirectoryTree(TFilePathSet &dst, const TFilePath &path, if (!TFileStatus(path).isDirectory()) throw TSystemException(path, " is not a directory"); + std::set fpSet; + QFileInfoList fil = QDir(toQString(path)).entryInfoList(); int i; for (i = 0; i < fil.size(); i++) { @@ -700,9 +702,15 @@ void TSystem::readDirectoryTree(TFilePathSet &dst, const TFilePath &path, if (TFileStatus(son).isDirectory()) { if (!onlyFiles) dst.push_back(son); readDirectoryTree(dst, son, groupFrames, onlyFiles); - } else - dst.push_back(son); + } else { + if (groupFrames && son.getDots() == "..") { + son = son.withFrame(); + } + fpSet.insert(son); + } } + + dst.insert(dst.end(), fpSet.begin(), fpSet.end()); } //------------------------------------------------------------ @@ -801,10 +809,10 @@ bool TSystem::doesExistFileOrLevel(const TFilePath &fp) { QString name(QString::fromStdWString(fp.getWideName())); name.append(QString::fromStdString(fp.getDottedType())); - int sepPos = name.indexOf("#"); - int dotPos = name.indexOf(".", sepPos); - int removeChars = dotPos - sepPos; - int doubleUnderscorePos = name.indexOf("__", sepPos); + int sepPos = name.indexOf("#"); + int dotPos = name.indexOf(".", sepPos); + int removeChars = dotPos - sepPos; + int doubleUnderscorePos = name.indexOf("__", sepPos); if (doubleUnderscorePos > 0) removeChars = doubleUnderscorePos - sepPos; name.remove(sepPos, removeChars); @@ -1011,7 +1019,7 @@ bool TSystem::showDocument(const TFilePath &path) { char newPath[2048]; while (pos < thePath.size()) { - char c = thePath[pos]; + char c = thePath[pos]; if (c == ' ') newPath[count++] = '\\'; newPath[count++] = c; diff --git a/toonz/sources/image/tzp/tiio_plt.cpp b/toonz/sources/image/tzp/tiio_plt.cpp index a92c16c..55a3166 100644 --- a/toonz/sources/image/tzp/tiio_plt.cpp +++ b/toonz/sources/image/tzp/tiio_plt.cpp @@ -1,7 +1,7 @@ #include "tiio_plt.h" -//#include "tiio.h" +// #include "tiio.h" #include "trastercm.h" #include "toonztags.h" @@ -93,8 +93,8 @@ static int decode_group_name(char group_name[], char **name, int *key, *sister_index = atoi(s + 1); else if (s[0] >= '0' && s[0] <= '9') *key = atoi(s); - *t = '!'; - s = t + 1; + *t = '!'; + s = t + 1; } *name = s; return 1; @@ -213,6 +213,11 @@ void PltReader::open(FILE *file) { m_nColor = palette[10]; m_nPencil = palette[11]; + bool isOldCmap13Plt = false; + if (m_nColor == 128 && m_nPencil == 32) { + isOldCmap13Plt = true; + } + std::string colorNames; if (TIFFGetField(m_tiff, TIFFTAG_TOONZCOLORNAMES, &count, &data)) colorNames = data; @@ -234,7 +239,7 @@ void PltReader::open(FILE *file) { if (strcmp(pageName, "_UNUSED_PAGE") == 0) continue; if (sisterIndex == -1 || i < m_nColor) m_infoRow[i].r = 255; - if (i < m_nColor) m_infoRow[i].g = 255; + if (i < m_nColor) m_infoRow[i].g = 255; while (isdigit(item->name[0])) // in toonz colors cannot begin with digits item->name++; @@ -245,8 +250,17 @@ void PltReader::open(FILE *file) { m_pltNames[i] = std::pair(pageName, item->name); if (sisterIndex != -1) { - int comboindex = (i < 256) ? (sisterIndex >> 16) + 256 : sisterIndex >> 8; - if (i >= 256) ComboInkIndex[i - 256] = comboindex; + int comboindex; + if (isOldCmap13Plt) { + comboindex = (i < 128) ? (sisterIndex >> 11) + 128 : sisterIndex >> 4; + if (i == 128) + ComboInkIndex[0] = 0; + else if (i > 128) + ComboInkIndex[i - 128] = comboindex; + } else { + comboindex = (i < 256) ? (sisterIndex >> 16) + 256 : sisterIndex >> 8; + if (i >= 256) ComboInkIndex[i - 256] = comboindex; + } std::map>::iterator it; if ((it = m_pltNames.find(comboindex)) == m_pltNames.end() || isDefaultName(it->second.second)) { @@ -285,7 +299,7 @@ void PltReader::readLine(char *buffer, int x0, int x1, int shrink) { int i; for (i = 0; i < m_info.m_lx; i++) pix[i] = TPixelRGBM32(); - int y = m_row++; + int y = m_row++; if (y == 1) { for (i = 0; i < m_info.m_lx; i++) pix[i] = m_infoRow[i]; diff --git a/toonz/sources/image/tzp/tiio_tzp.cpp b/toonz/sources/image/tzp/tiio_tzp.cpp index 6bbd524..080f9bd 100644 --- a/toonz/sources/image/tzp/tiio_tzp.cpp +++ b/toonz/sources/image/tzp/tiio_tzp.cpp @@ -1,14 +1,14 @@ #include "tiio_tzp.h" -//#include "tiio.h" +// #include "tiio.h" #include "trastercm.h" #include "toonztags.h" #include "texception.h" #include "tiffio.h" #include "tiffiop.h" -//#include "tspecialstyleid.h" +// #include "tspecialstyleid.h" #include #ifdef _MSC_VER @@ -37,6 +37,8 @@ class TzpReader final : public Tiio::Reader { bool m_isBigEndian; bool m_isFirstLineRead; + bool m_isOldCmap13; + public: TzpReader(); ~TzpReader(); @@ -63,6 +65,7 @@ TzpReader::TzpReader() , m_lx(0) , m_ly(0) , m_isCmap24(false) + , m_isOldCmap13(false) , m_nColor(0) , m_nPencil(0) , m_isBigEndian(false) @@ -145,8 +148,9 @@ void TzpReader::open(FILE *file) { m_nColor = palette[10]; m_nPencil = palette[11]; + // Old 4.1 palette : 4bit paint, 4bit tone, 5bit ink if (m_nColor == 128 && m_nPencil == 32) { - throw TException("Old 4.1 Palette"); + m_isOldCmap13 = true; } if (bps == 32) @@ -180,7 +184,7 @@ extern int ComboInkIndex[]; // a bad patch.... void TzpReader::readLine(char *buffer, int x0, int x1, int shrink) { TPixelCM32 *pix = (TPixelCM32 *)buffer; for (int i = 0; i < m_info.m_lx; i++) pix[i] = TPixelCM32(); - int y = m_row++; + int y = m_row++; const int paintOffset = 0; // paint#1 --> 1 const int inkOffset = 1 + m_nColor - 1; // ink#0 --> nColor-1 @@ -213,7 +217,7 @@ void TzpReader::readLine(char *buffer, int x0, int x1, int shrink) { pix[i] = TPixelCM32(ink, paint, tone); } } - } else { + } else if (!m_isOldCmap13) { if (m_y <= y && y < m_y + m_ly) { std::vector line(m_lx); TIFFReadScanline(m_tiff, (char *)&line[0], y - m_y, 0); @@ -243,6 +247,39 @@ void TzpReader::readLine(char *buffer, int x0, int x1, int shrink) { } } } + } else { + if (m_y <= y && y < m_y + m_ly) { + std::vector line(m_lx); + TIFFReadScanline(m_tiff, (char *)&line[0], y - m_y, 0); + pix += m_x; + static std::set table; + + /// per le tzp che vengono da Irix + bool bigEndian = + (m_tiff->tif_header.classic.tiff_magic == TIFF_BIGENDIAN); + + for (int i = 0; i < m_lx; i++) { + unsigned short inPix = line[i]; + if (bigEndian) inPix = swapUshort(inPix); + + int ink = ((inPix >> 3) & 0x1F); + int tone = ((inPix >> 8) & 0xF); + int paint = ((inPix >> 12) & 0xF); + tone |= tone << 4; + if (paint > 0) paint += paintOffset; + if (ComboInkIndex[ink] != -1) + ink = ComboInkIndex[ink]; + else + ink += inkOffset; + pix[i] = TPixelCM32(ink, paint, tone); + if (tone < 255) { + // int w = ink; + } + if (table.find(ink) == table.end()) { + table.insert(ink); + } + } + } } } diff --git a/toonz/sources/toonz/CMakeLists.txt b/toonz/sources/toonz/CMakeLists.txt index ec21113..c73aa8a 100644 --- a/toonz/sources/toonz/CMakeLists.txt +++ b/toonz/sources/toonz/CMakeLists.txt @@ -127,6 +127,7 @@ set(MOC_HEADERS exportxsheetpdf.h custompanelmanager.h custompaneleditorpopup.h + convertfolderpopup.h ) if(PLATFORM EQUAL 64) @@ -375,6 +376,7 @@ set(SOURCES exportxsheetpdf.cpp custompanelmanager.cpp custompaneleditorpopup.cpp + convertfolderpopup.cpp # Tracker file dummyprocessor.cpp metnum.cpp diff --git a/toonz/sources/toonz/convertfolderpopup.cpp b/toonz/sources/toonz/convertfolderpopup.cpp new file mode 100644 index 0000000..35c3f94 --- /dev/null +++ b/toonz/sources/toonz/convertfolderpopup.cpp @@ -0,0 +1,511 @@ + +#include "convertfolderpopup.h" + +// Tnz6 includes +#include "menubarcommandids.h" +#include "tapp.h" +#include "filebrowser.h" +#include "filebrowserpopup.h" + +// TnzQt includes +#include "toonzqt/gutil.h" +#include "toonzqt/imageutils.h" +#include "toonzqt/menubarcommand.h" +#include "toonzqt/filefield.h" +#include "toonzqt/checkbox.h" +#include "toonzqt/icongenerator.h" + +// TnzLib includes +#include "toonz/tscenehandle.h" +#include "toonz/toonzscene.h" +#include "toonz/sceneproperties.h" +#include "toonz/tproject.h" + +// TnzCore includes +#include "tsystem.h" +#include "tfiletype.h" +#include "tlevel_io.h" +#include "tiio.h" +#include "tenv.h" + +// Qt includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class ConvertFolderPopup::Converter final : public QThread { + int m_skippedCount; + int m_doneCount; + ConvertFolderPopup* m_parent; + QString m_logTxt; + +public: + Converter(ConvertFolderPopup* parent, QString logTxt) + : m_parent(parent), m_skippedCount(0), m_doneCount(0), m_logTxt(logTxt) {} + void run() override; + void convertLevel(const TFilePath& fp); + int getSkippedCount() const { return m_skippedCount; } + int getDoneCount() const { return m_doneCount; } + QString logTxt() const { return m_logTxt; } +}; + +void ConvertFolderPopup::Converter::run() { + ToonzScene* sc = TApp::instance()->getCurrentScene()->getScene(); + DVGui::ProgressDialog* progressDialog = m_parent->m_progressDialog; + int levelCount = m_parent->m_srcFilePaths.size(); + + for (int i = 0; !m_parent->m_notifier->abortTask() && i < levelCount; i++) { + TFilePath sourceLevelPath = sc->decodeFilePath(m_parent->m_srcFilePaths[i]); + QString levelName = QString::fromStdString(sourceLevelPath.getLevelName()); + + TFilePath dstFolder = sourceLevelPath.getParentDir(); + // check already existent levels + TFilePath dstFilePath = + m_parent->getDestinationFilePath(m_parent->m_srcFilePaths[i]); + + if (TSystem::doesExistFileOrLevel(dstFilePath)) { + if (m_parent->m_skip->isChecked()) { + m_logTxt.append(tr("Level %1 already exists; skipped.\n") + .arg(dstFilePath.getQString())); + m_skippedCount++; + continue; + } else { + bool ok = TSystem::removeFileOrLevel(dstFilePath); + if (!ok) { + m_logTxt.append(tr("Failed to remove existing level %1; skipped.\n") + .arg(dstFilePath.getQString())); + m_skippedCount++; + continue; + } + } + } + + progressDialog->setLabelText(QString(tr("Converting level %1 of %2: %3") + .arg(i + 1) + .arg(levelCount) + .arg(levelName))); + + convertLevel(sourceLevelPath); + } + if (m_parent->m_notifier->abortTask()) + m_logTxt.append(tr("Convert aborted.\n")); +} + +void ConvertFolderPopup::Converter::convertLevel( + const TFilePath& sourceFileFullPath) { + ToonzScene* sc = TApp::instance()->getCurrentScene()->getScene(); + ConvertFolderPopup* popup = m_parent; + + QString levelName = QString::fromStdString(sourceFileFullPath.getLevelName()); + TFilePath dstFileFullPath = popup->getDestinationFilePath(sourceFileFullPath); + + TFrameId from, to; + + if (TFileType::isLevelFilePath(sourceFileFullPath)) { + popup->getFrameRange(sourceFileFullPath, from, to); + + if (from == TFrameId() || to == TFrameId()) { + m_logTxt.append(tr("Level %1 has no frame; skipped.") + .arg(sourceFileFullPath.getQString())); + popup->m_notifier->notifyError(); + return; + } + } + // convert old levels (tzp/tzu) to tlv + ImageUtils::convertOldLevel2Tlv(sourceFileFullPath, dstFileFullPath, from, to, + m_parent->m_notifier); + m_doneCount++; + popup->m_notifier->notifyLevelCompleted(dstFileFullPath); +} + +//================================================================== +// SaveLogTxtPopup +//================================================================== + +class SaveLogTxtPopup final : public FileBrowserPopup { + QString m_logTxt; + +public: + SaveLogTxtPopup(QString txt) + : FileBrowserPopup(QObject::tr("Save log text")), m_logTxt(txt) { + setModal(true); + addFilterType("txt"); + setOkText(QObject::tr("Save")); + } + + bool execute() override { + if (m_selectedPaths.empty()) return false; + + TFilePath savePath(*m_selectedPaths.begin()); + if (savePath.isEmpty()) return false; + + savePath = savePath.withNoFrame().withType("txt"); // Just to be sure + if (TFileStatus(savePath).doesExist()) { + int ret = DVGui::MsgBox( + QObject::tr( + "The log file already exists.\n Do you want to overwrite it?") + .arg(toQString(savePath.withoutParentDir())), + QObject::tr("Overwrite"), QObject::tr("Don't Overwrite"), 0); + + if (ret == 2) return false; + } + + ToonzScene* sc = TApp::instance()->getCurrentScene()->getScene(); + savePath = sc->decodeFilePath(savePath); + + QFile file(savePath.getQString()); + if (!file.open(QIODevice::WriteOnly)) { + DVGui::error(tr("Failed to open the file %1").arg(savePath.getQString())); + return false; + } + QTextStream out(&file); + out << m_logTxt; + file.close(); + + return true; + } +}; +//============================================================================= + +ConvertResultPopup::ConvertResultPopup(QString log, TFilePath path) + : QDialog(), m_logTxt(log), m_targetPath(path) { + setModal(true); + + QTextEdit* edit = new QTextEdit(this); + QPushButton* saveLogButton = new QPushButton(tr("Save log file.."), this); + QPushButton* closeButton = new QPushButton(tr("Close"), this); + + edit->setPlainText(m_logTxt); + edit->setReadOnly(true); + + QVBoxLayout* mainLay = new QVBoxLayout(); + mainLay->setMargin(5); + mainLay->setSpacing(10); + { + mainLay->addWidget(edit, 1); + mainLay->addWidget(new QLabel(tr("Do you want to save the log?")), 0); + + QHBoxLayout* buttonsLay = new QHBoxLayout(); + buttonsLay->setMargin(0); + buttonsLay->setSpacing(10); + buttonsLay->setAlignment(Qt::AlignCenter); + { + buttonsLay->addWidget(saveLogButton, 0); + buttonsLay->addWidget(closeButton, 0); + } + mainLay->addLayout(buttonsLay, 0); + } + setLayout(mainLay); + + connect(closeButton, SIGNAL(clicked()), this, SLOT(close())); + connect(saveLogButton, SIGNAL(clicked()), this, SLOT(onSaveLog())); +} + +void ConvertResultPopup::onSaveLog() { + SaveLogTxtPopup popup(m_logTxt); + + popup.setFolder(m_targetPath); + popup.setFilename(TFilePath("tzp_convert_log.txt")); + if (popup.exec() == QDialog::Accepted) close(); +} + +//============================================================================= + +ConvertFolderPopup::ConvertFolderPopup() + : Dialog(TApp::instance()->getMainWindow(), true, false, + "ConvertTZPInFolder") + , m_converter(0) + , m_isConverting(false) { + setModal(false); + setWindowTitle(tr("Convert TZP In Folder")); + + m_okBtn = new QPushButton(tr("Convert"), this); + m_cancelBtn = new QPushButton(tr("Cancel"), this); + + m_notifier = new ImageUtils::FrameTaskNotifier(); + + m_progressDialog = new DVGui::ProgressDialog("", tr("Cancel"), 0, 0); + m_skip = new DVGui::CheckBox(tr("Skip Existing Files"), this); + m_subfolder = new DVGui::CheckBox(tr("Apply to Subfolder"), this); + + m_convertFolderFld = new DVGui::FileField(0, QString(""), true); + + m_srcFileList = new QListWidget(this); + + m_convertFolderFld->setFileMode(QFileDialog::DirectoryOnly); + //----------------------- + + m_progressDialog->setWindowTitle(tr("Convert TZP in Folder")); + m_progressDialog->setWindowFlags( + Qt::Dialog | Qt::WindowTitleHint); // Don't show ? and X buttons + m_progressDialog->setWindowModality(Qt::WindowModal); + + //----layout + m_topLayout->setMargin(5); + m_topLayout->setSpacing(5); + { + QHBoxLayout* folderLay = new QHBoxLayout(); + folderLay->setMargin(0); + folderLay->setSpacing(5); + { + folderLay->addWidget(new QLabel(tr("Folder to convert:"), this), 0); + folderLay->addWidget(m_convertFolderFld, 1); + } + m_topLayout->addLayout(folderLay, 0); + + QHBoxLayout* mainLay = new QHBoxLayout(); + mainLay->setMargin(0); + mainLay->setSpacing(5); + { + QVBoxLayout* leftLay = new QVBoxLayout(); + leftLay->setMargin(0); + leftLay->setSpacing(5); + { + leftLay->addWidget(m_skip, 0); + leftLay->addWidget(m_subfolder, 0); + leftLay->addStretch(1); + } + mainLay->addLayout(leftLay, 0); + + mainLay->addWidget(m_srcFileList, 1); + } + m_topLayout->addLayout(mainLay, 1); + } + m_buttonLayout->setMargin(0); + m_buttonLayout->setSpacing(20); + { + m_buttonLayout->addWidget(m_okBtn); + m_buttonLayout->addWidget(m_cancelBtn); + } + + //--- signal-slot connections + qRegisterMetaType("TFilePath"); + + bool ret = true; + ret = ret && connect(m_okBtn, SIGNAL(clicked()), this, SLOT(apply())); + ret = ret && connect(m_cancelBtn, SIGNAL(clicked()), this, SLOT(reject())); + ret = ret && connect(m_notifier, SIGNAL(frameCompleted(int)), + m_progressDialog, SLOT(setValue(int))); + ret = ret && connect(m_notifier, SIGNAL(levelCompleted(const TFilePath&)), + this, SLOT(onLevelConverted(const TFilePath&))); + ret = ret && connect(m_progressDialog, SIGNAL(canceled()), m_notifier, + SLOT(onCancelTask())); + + ret = ret && connect(m_convertFolderFld, SIGNAL(pathChanged()), this, + SLOT(onFileInFolderChanged())); + ret = ret && connect(m_skip, SIGNAL(clicked()), this, SLOT(onSkipChanged())); + ret = ret && connect(m_subfolder, SIGNAL(clicked()), this, + SLOT(onSubfolderChanged())); + + assert(ret); +} + +//------------------------------------------------------------------ + +ConvertFolderPopup::~ConvertFolderPopup() { + delete m_notifier; + delete m_progressDialog; + delete m_converter; +} + +//------------------------------------------------------------------ + +void ConvertFolderPopup::setFiles() { + if (m_convertFolderFld->getPath().isEmpty()) { + m_srcFilePaths.clear(); + m_srcFileList->clear(); + return; + } + ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene(); + TFilePath srcFolderPath = scene->decodeFilePath( + TFilePath(m_convertFolderFld->getPath().toStdString())); + + bool skip = m_skip->isChecked(); + bool subFolder = m_subfolder->isChecked(); + + QGuiApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + + TFilePathSet fps; + if (subFolder) + TSystem::readDirectoryTree(fps, srcFolderPath, true, true); + else + TSystem::readDirectory(fps, srcFolderPath, true, true); + + m_srcFilePaths.clear(); + QStringList tgtItems; + QStringList skipItems; + for (const auto fp : fps) { + // applies to only tzp + if (fp.getType() != "tzp") continue; + + // check the destination file existence + TFilePath dstFp = getDestinationFilePath(fp); + TFilePath relPath = fp - srcFolderPath; + if (!TSystem::doesExistFileOrLevel(dstFp)) { + m_srcFilePaths.push_back(fp); + tgtItems.append(relPath.getQString()); + } else if (skip) + skipItems.append(tr("[SKIP] ") + relPath.getQString()); + else { + tgtItems.append(tr("[OVERWRITE] ") + relPath.getQString()); + m_srcFilePaths.push_back(fp); + } + } + + m_srcFileList->clear(); + m_srcFileList->addItems(tgtItems); + m_srcFileList->addItems(skipItems); + + QGuiApplication::restoreOverrideCursor(); +} + +//------------------------------------------------------------------ + +void ConvertFolderPopup::apply() { + if (m_convertFolderFld->getPath().isEmpty()) { + DVGui::error(tr("Target folder is not specified.")); + return; + } + if (m_srcFilePaths.empty()) { + DVGui::error(tr("No files will be converted.")); + return; + } + + QMessageBox::StandardButton btn = QMessageBox::question( + this, tr("Cofirmation"), + tr("Converting %1 files. Are you sure?").arg(m_srcFilePaths.size()), + QMessageBox::Yes | QMessageBox::No); + if (btn != QMessageBox::Yes) return; + + // parameters are ok: close the dialog first + close(); + + m_isConverting = true; + m_progressDialog->reset(); + m_progressDialog->setMinimum(0); + m_progressDialog->setMaximum(100); + m_progressDialog->show(); + m_notifier->reset(); + QApplication::setOverrideCursor(Qt::WaitCursor); + + QString logTxt = + tr("Convert TZP in folder\n") + + tr("Target Folder: %1\n").arg(m_convertFolderFld->getPath()) + + tr("Skip Existing Files: %1\n") + .arg((m_skip->isChecked()) ? "True" : "False") + + tr("Apply to Subfolder: %1\n") + .arg((m_subfolder->isChecked()) ? "True" : "False") + + tr("Approx. levels to be converted: %1\n\n").arg(m_srcFilePaths.size()) + + tr("Started: ") + QDateTime::currentDateTime().toString() + "\n"; + m_converter = new Converter(this, logTxt); + bool ret = + connect(m_converter, SIGNAL(finished()), this, SLOT(onConvertFinished())); + Q_ASSERT(ret); + + // start converting. Conversion end is handled by onConvertFinished() slot + m_converter->start(); +} + +//------------------------------------------------------------------ + +void ConvertFolderPopup::onConvertFinished() { + m_isConverting = false; + TFilePath dstFolderPath(m_convertFolderFld->getPath().toStdWString()); + FileBrowser::refreshFolder(dstFolderPath); + + m_progressDialog->close(); + QApplication::restoreOverrideCursor(); + + QString logTxt = m_converter->logTxt(); + // opens result + + int errorCount = m_notifier->getErrorCount(); + int skippedCount = m_converter->getSkippedCount(); + int doneCount = m_converter->getDoneCount(); + + if (m_notifier->abortTask()) + logTxt.append(tr("Convert aborted:")); + else + logTxt.append(tr("Convert completed:")); + + logTxt.append( + tr(" %1 level(s) done, %2 level(s) skipped with %3 error(s).\n") + .arg(doneCount) + .arg(skippedCount) + .arg(errorCount)); + logTxt.append(tr("Ended: ") + QDateTime::currentDateTime().toString()); + + delete m_converter; + m_converter = 0; + + ConvertResultPopup resultPopup(logTxt, dstFolderPath); + resultPopup.exec(); +} + +//------------------------------------------------------------------ + +void ConvertFolderPopup::onLevelConverted(const TFilePath& fullPath) { + IconGenerator::instance()->invalidate(fullPath); +} + +//------------------------------------------------------------------ + +void ConvertFolderPopup::onFileInFolderChanged() { setFiles(); } + +//------------------------------------------------------------------ + +void ConvertFolderPopup::onSkipChanged() { setFiles(); } + +//------------------------------------------------------------------ + +void ConvertFolderPopup::onSubfolderChanged() { setFiles(); } + +//------------------------------------------------------------------ + +TFilePath ConvertFolderPopup::getDestinationFilePath( + const TFilePath& sourceFilePath) { + TFilePath destFolder = sourceFilePath.getParentDir(); + ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene(); + + // Build the output level name + const std::string& ext = "tlv"; + const std::wstring& name = sourceFilePath.getWideName(); + + TFilePath destName = TFilePath(name).withType(ext); + + // Merge the two + return destFolder + destName; +} + +//------------------------------------------------------------------ + +void ConvertFolderPopup::getFrameRange(const TFilePath& sourceFilePath, + TFrameId& from, TFrameId& to) { + from = to = TFrameId(); + + if (!TFileType::isLevelFilePath(sourceFilePath)) return; + + TLevelReaderP lr(sourceFilePath); + if (!lr) return; + + TLevelP level = lr->loadInfo(); + if (level->begin() == level->end()) return; + + from = level->begin()->first; + to = (--level->end())->first; +} + +//============================================================================= +// ConvertFolderPopup +//----------------------------------------------------------------------------- + +OpenPopupCommandHandler openConvertTZPInFolderPopup( + MI_ConvertTZPInFolder); diff --git a/toonz/sources/toonz/convertfolderpopup.h b/toonz/sources/toonz/convertfolderpopup.h new file mode 100644 index 0000000..a465870 --- /dev/null +++ b/toonz/sources/toonz/convertfolderpopup.h @@ -0,0 +1,107 @@ +#pragma once + +#ifndef CONVERTFOLDERPOPUP_H +#define CONVERTFOLDERPOPUP_H + +// TnzQt includes +#include "toonzqt/dvdialog.h" + +// TnzCore includes +#include "tfilepath.h" + +// Qt includes +#include +#include +#include + +//============================================================== + +// Forward declarations + +class TPalette; +class TPropertyGroup; +class ToonzScene; + +class QCheckBox; +class QLabel; +class QListWidget; + +namespace DVGui { +class FileField; +class ProgressDialog; +class CheckBox; +} // namespace DVGui + +namespace ImageUtils { +class FrameTaskNotifier; +} + +//============================================================== + +//***************************************************************************** +// ConvertPopup declaration +//***************************************************************************** + +/*! + \brief Window class used in the conversion of levels between different + file formats. +*/ + +class ConvertFolderPopup : public DVGui::Dialog { + Q_OBJECT + +public: + ConvertFolderPopup(); + ~ConvertFolderPopup(); + + void setFiles(); + bool isConverting() const { return m_isConverting; } + +public slots: + + void apply(); //!< Starts the conversion. + void onConvertFinished(); + void onLevelConverted(const TFilePath& fullPath); + void onFileInFolderChanged(); + void onSkipChanged(); + void onSubfolderChanged(); + +protected: + TFilePath getDestinationFilePath(const TFilePath& sourceFilePath); + void getFrameRange(const TFilePath& sourceFilePath, TFrameId& from, + TFrameId& to); + + void showEvent(QShowEvent* e) override { setFiles(); } + +private: + DVGui::FileField* m_convertFolderFld; + DVGui::CheckBox *m_skip, *m_subfolder; + + QPushButton *m_okBtn, *m_cancelBtn; + + QListWidget* m_srcFileList; + + class Converter; + Converter* m_converter; + + ImageUtils::FrameTaskNotifier* m_notifier; + DVGui::ProgressDialog* m_progressDialog; + + std::vector m_srcFilePaths; + + bool m_isConverting; +}; + +class ConvertResultPopup : public QDialog { + Q_OBJECT + + QString m_logTxt; + TFilePath m_targetPath; + +public: + ConvertResultPopup(QString log, TFilePath path); +protected slots: + void onSaveLog(); +}; + +#endif // CONVERTPOPUP_H diff --git a/toonz/sources/toonz/mainwindow.cpp b/toonz/sources/toonz/mainwindow.cpp index db6a2eb..2857413 100644 --- a/toonz/sources/toonz/mainwindow.cpp +++ b/toonz/sources/toonz/mainwindow.cpp @@ -1662,6 +1662,8 @@ void MainWindow::defineActions() { QT_TR_NOOP("&Clear Recent level File List"), ""); createMenuFileAction(MI_ConvertFileWithInput, QT_TR_NOOP("&Convert File..."), "", "convert"); + createMenuFileAction(MI_ConvertTZPInFolder, + QT_TR_NOOP("&Convert TZP Files In Folder..."), ""); createMenuFileAction(MI_LoadColorModel, QT_TR_NOOP("&Load Color Model..."), "", "load_colormodel"); createMenuFileAction(MI_ImportMagpieFile, diff --git a/toonz/sources/toonz/menubarcommandids.h b/toonz/sources/toonz/menubarcommandids.h index e263a33..ccc43ac 100644 --- a/toonz/sources/toonz/menubarcommandids.h +++ b/toonz/sources/toonz/menubarcommandids.h @@ -54,7 +54,7 @@ #define MI_ClonePreview "MI_ClonePreview" #define MI_FreezePreview "MI_FrezzePreview" #define MI_SavePreviewedFrames "MI_SavePreviewedFrames" -//#define MI_SavePreview "MI_SavePreview" +// #define MI_SavePreview "MI_SavePreview" #define MI_Print "MI_Print" #define MI_Preferences "MI_Preferences" #define MI_SavePreset "MI_SavePreset" @@ -83,7 +83,7 @@ #define MI_CanvasSize "MI_CanvasSize" #define MI_RemoveUnused "MI_RemoveUnused" -//#define MI_OpenCurrentScene "MI_OpenCurrentScene" +// #define MI_OpenCurrentScene "MI_OpenCurrentScene" #define MI_OpenFileBrowser "MI_OpenFileBrowser" #define MI_OpenFileViewer "MI_OpenFileViewer" #define MI_OpenFilmStrip "MI_OpenFilmStrip" @@ -96,7 +96,7 @@ #define MI_OpenToolOptionBar "MI_OpenToolOptionBar" #define MI_OpenLevelView "MI_OpenLevelView" #define MI_OpenStopMotionPanel "MI_OpenStopMotionPanel" -//#define MI_OpenExport "MI_OpenExport" +// #define MI_OpenExport "MI_OpenExport" #define MI_BrightnessAndContrast "MI_BrightnessAndContrast" #define MI_Antialias "MI_Antialias" #define MI_AdjustLevels "MI_AdjustLevels" @@ -238,7 +238,7 @@ #define MI_ZeroThick "MI_ZeroThick" #define MI_CursorOutline "MI_CursorOutline" -//#define MI_LoadResourceFile "MI_LoadResourceFile" +// #define MI_LoadResourceFile "MI_LoadResourceFile" #define MI_DuplicateFile "MI_DuplicateFile" #define MI_ViewFile "MI_ViewFile" #define MI_ConvertFiles "MI_ConvertFiles" @@ -470,4 +470,5 @@ #define MI_OpenCustomPanels "MI_OpenCustomPanels" #define MI_CustomPanelEditor "MI_CustomPanelEditor" +#define MI_ConvertTZPInFolder "MI_ConvertTZPInFolder" #endif diff --git a/toonz/sources/toonzlib/toonzimageutils.cpp b/toonz/sources/toonzlib/toonzimageutils.cpp index 3f88cbf..423fbc2 100644 --- a/toonz/sources/toonzlib/toonzimageutils.cpp +++ b/toonz/sources/toonzlib/toonzimageutils.cpp @@ -101,7 +101,7 @@ TRect rasterizeStroke(TOfflineGL *&gl, TRect rasBounds, TStroke *stroke, TRect rasterizeRegion(TOfflineGL *&gl, TRect rasBounds, TRegion *region, TRectD clip) { - TRectD regionBBox = region->getBBox(); + TRectD regionBBox = region->getBBox(); if (!clip.isEmpty()) regionBBox = regionBBox * clip; TRect rect = convert(regionBBox) * rasBounds; @@ -169,7 +169,7 @@ void fastAddPaintRegion(const TToonzImageP &ti, TRegion *region, int newPaintId, std::min(maxStyleId, subregion->getStyle()), maxStyleId); } } -} +} // namespace //------------------------------------------------------------------- @@ -455,7 +455,7 @@ TToonzImageP ToonzImageUtils::vectorToToonzImage( else { visible = false; for (int j = 0; j < style->getColorParamCount() && !visible; j++) { - TPixel32 color = style->getColorParamValue(j); + TPixel32 color = style->getColorParamValue(j); if (color.m != 0) visible = true; } } @@ -577,7 +577,7 @@ void ToonzImageUtils::scrambleStyles(const TToonzImageP &ti, assert(j >= 0); assert(j < 1000000); if (j >= (int)lut.size()) lut.resize(j + 1, -1); - lut[j] = k; + lut[j] = k; if (j != k) isIdentity = false; } if (isIdentity) return; @@ -590,9 +590,9 @@ void ToonzImageUtils::scrambleStyles(const TToonzImageP &ti, TPixelCM32 *pix = ras->pixels(y); TPixelCM32 *endPix = pix + lx; while (pix < endPix) { - int ink = pix->getInk(); - if (0 <= ink && ink < m && lut[ink] >= 0) ink = lut[ink]; - int paint = pix->getPaint(); + int ink = pix->getInk(); + if (0 <= ink && ink < m && lut[ink] >= 0) ink = lut[ink]; + int paint = pix->getPaint(); if (0 <= paint && paint < m && lut[paint] >= 0) paint = lut[paint]; if (ink != pix->getInk() || paint != pix->getPaint()) { *pix = TPixelCM32(ink, paint, pix->getTone()); @@ -735,16 +735,16 @@ void ToonzImageUtils::eraseImage(const TToonzImageP &ti, paint = inPix->m > 0 && erasePaint && canErasePaint ? 0 : outPix->getPaint(); - tone = inPix->m > 0 && eraseInk && canEraseInk - ? std::max(outPix->getTone(), (int)inPix->m) - : outPix->getTone(); + tone = inPix->m > 0 && eraseInk && canEraseInk + ? std::max(outPix->getTone(), (int)inPix->m) + : outPix->getTone(); } else { paint = inPix->m < 255 && erasePaint && canErasePaint ? 0 : outPix->getPaint(); - tone = inPix->m < 255 && eraseInk && canEraseInk - ? std::max(outPix->getTone(), 255 - (int)inPix->m) - : outPix->getTone(); + tone = inPix->m < 255 && eraseInk && canEraseInk + ? std::max(outPix->getTone(), 255 - (int)inPix->m) + : outPix->getTone(); } *outPix = TPixelCM32(outPix->getInk(), paint, tone); }