diff --git a/toonz/sources/include/toonz/namebuilder.h b/toonz/sources/include/toonz/namebuilder.h index 8e47749..4fa00a5 100644 --- a/toonz/sources/include/toonz/namebuilder.h +++ b/toonz/sources/include/toonz/namebuilder.h @@ -33,7 +33,9 @@ public: //------------------------------------------------------------------- // NameCreator genera la sequenza 'A', 'B', ... -class DVAPI NameCreator final : public NameBuilder { +// inherited by FlexibleNameCreator +class DVAPI NameCreator : public NameBuilder { +protected: std::vector m_s; public: diff --git a/toonz/sources/toonz/penciltestpopup.cpp b/toonz/sources/toonz/penciltestpopup.cpp index e3e8b2d..c2afb16 100644 --- a/toonz/sources/toonz/penciltestpopup.cpp +++ b/toonz/sources/toonz/penciltestpopup.cpp @@ -20,7 +20,6 @@ #include "toonz/toonzscene.h" #include "toutputproperties.h" #include "toonz/sceneproperties.h" -#include "toonz/namebuilder.h" #include "toonz/levelset.h" #include "toonz/txshleveltypes.h" #include "toonz/toonzfolders.h" @@ -36,6 +35,7 @@ #include "tsystem.h" #include "tpixelutils.h" #include "tenv.h" +#include "tlevel_io.h" #include @@ -379,6 +379,90 @@ void openCaptureFilterSettings(const QWidget* parent, } #endif +QString convertToFrameWithLetter(int value, int length = -1) { + QString str; + str.setNum((int)(value / 10)); + while (str.length() < length) str.push_front("0"); + QChar letter = numToLetter(value % 10); + if (!letter.isNull()) str.append(letter); + return str; +} + +QString fidsToString(const std::vector& fids, + bool letterOptionEnabled) { + if (fids.empty()) return PencilTestPopup::tr("No", "frame id"); + QString retStr(""); + if (letterOptionEnabled) { + bool beginBlock = true; + for (int f = 0; f < fids.size() - 1; f++) { + int num = fids[f].getNumber(); + int next_num = fids[f + 1].getNumber(); + + if (num % 10 == 0 && num + 10 == next_num) { + if (beginBlock) { + retStr += convertToFrameWithLetter(num) + " - "; + beginBlock = false; + } + } else { + retStr += convertToFrameWithLetter(num) + ", "; + beginBlock = true; + } + } + retStr += convertToFrameWithLetter(fids.back().getNumber()); + } else { + bool beginBlock = true; + for (int f = 0; f < fids.size() - 1; f++) { + int num = fids[f].getNumber(); + int next_num = fids[f + 1].getNumber(); + if (num + 1 == next_num) { + if (beginBlock) { + retStr += QString::number(num) + " - "; + beginBlock = false; + } + } else { + retStr += QString::number(num) + ", "; + beginBlock = true; + } + } + retStr += QString::number(fids.back().getNumber()); + } + return retStr; +} + +bool findCell(TXsheet* xsh, int col, const TXshCell& targetCell, + int& bottomRowWithTheSameLevel) { + bottomRowWithTheSameLevel = -1; + TXshColumnP column = const_cast(xsh)->getColumn(col); + if (!column) return false; + + TXshCellColumn* cellColumn = column->getCellColumn(); + if (!cellColumn) return false; + + int r0, r1; + if (!cellColumn->getRange(r0, r1)) return false; + + for (int r = r0; r <= r1; r++) { + TXshCell cell = cellColumn->getCell(r); + if (cell == targetCell) return true; + if (cell.m_level == targetCell.m_level) bottomRowWithTheSameLevel = r; + } + + return false; +} + +bool getRasterLevelSize(TXshLevel* level, TDimension& dim) { + std::vector fids; + level->getFids(fids); + if (fids.empty()) return false; + TXshSimpleLevel* simpleLevel = level->getSimpleLevel(); + if (!simpleLevel) return false; + TRasterImageP rimg = (TRasterImageP)simpleLevel->getFrame(fids[0], false); + if (!rimg || rimg->isEmpty()) return false; + + dim = rimg->getRaster()->getSize(); + return true; +} + } // namespace //============================================================================= @@ -495,10 +579,7 @@ void FrameNumberLineEdit::setValue(int value) { QString str; if (Preferences::instance()->isShowFrameNumberWithLettersEnabled()) { - str.setNum((int)(value / 10)); - while (str.length() < 3) str.push_front("0"); - QChar letter = numToLetter(value % 10); - if (!letter.isNull()) str.append(letter); + str = convertToFrameWithLetter(value, 3); } else { str.setNum(value); while (str.length() < 4) str.push_front("0"); @@ -525,7 +606,9 @@ int FrameNumberLineEdit::getValue() { //----------------------------------------------------------------------------- -void FrameNumberLineEdit::focusOutEvent(QFocusEvent*) {} +void FrameNumberLineEdit::focusOutEvent(QFocusEvent* e) { + LineEdit::focusOutEvent(e); +} //============================================================================= @@ -553,6 +636,46 @@ void LevelNameLineEdit::onEditingFinished() { //============================================================================= +std::wstring FlexibleNameCreator::getPrevious() { + if (m_s.empty() || (m_s[0] == 0 && m_s.size() == 1)) { + m_s.push_back('Z' - 'A'); + m_s.push_back('Z' - 'A'); + return L"ZZ"; + } + int i = 0; + int n = m_s.size(); + while (i < n) { + m_s[i]--; + if (m_s[i] >= 0) break; + m_s[i] = 'Z' - 'A'; + i++; + } + if (i >= n) { + n--; + m_s.pop_back(); + } + std::wstring s; + for (i = n - 1; i >= 0; i--) s.append(1, (wchar_t)(L'A' + m_s[i])); + return s; +} + +//------------------------------------------------------------------- + +bool FlexibleNameCreator::setCurrent(std::wstring name) { + if (name.empty() || name.size() > 2) return false; + std::vector newNameBuf; + for (std::wstring::iterator it = name.begin(); it != name.end(); ++it) { + int s = (int)((*it) - L'A'); + if (s < 0 || s > 'Z' - 'A') return false; + newNameBuf.push_back(s); + } + m_s.clear(); + for (int i = newNameBuf.size() - 1; i >= 0; i--) m_s.push_back(newNameBuf[i]); + return true; +} + +//============================================================================= + PencilTestSaveInFolderPopup::PencilTestSaveInFolderPopup(QWidget* parent) : Dialog(parent, true, false, "PencilTestSaveInFolder") { setWindowTitle("Create the Destination Subfolder to Save"); @@ -907,12 +1030,15 @@ PencilTestPopup::PencilTestPopup() int startFrame = Preferences::instance()->isShowFrameNumberWithLettersEnabled() ? 10 : 1; m_frameNumberEdit = new FrameNumberLineEdit(this, startFrame); + m_frameInfoLabel = new QLabel("", this); m_fileTypeCombo = new QComboBox(this); m_fileFormatOptionButton = new QPushButton(tr("Options"), this); m_saveInFileFld = new FileField(this, m_saveInFolderPopup->getParentPath()); QToolButton* nextLevelButton = new QToolButton(this); + m_previousLevelButton = new QToolButton(this); + m_saveOnCaptureCB = new QCheckBox(tr("Save images as they are captured"), this); @@ -959,9 +1085,13 @@ PencilTestPopup::PencilTestPopup() fileFrame->setObjectName("CleanupSettingsFrame"); m_frameNumberEdit->setObjectName("LargeSizedText"); + m_frameInfoLabel->setAlignment(Qt::AlignRight); nextLevelButton->setFixedSize(24, 24); nextLevelButton->setArrowType(Qt::RightArrow); nextLevelButton->setToolTip(tr("Next Level")); + m_previousLevelButton->setFixedSize(24, 24); + m_previousLevelButton->setArrowType(Qt::LeftArrow); + m_previousLevelButton->setToolTip(tr("Previous Level")); m_saveOnCaptureCB->setChecked(true); imageFrame->setObjectName("CleanupSettingsFrame"); @@ -1060,16 +1190,30 @@ PencilTestPopup::PencilTestPopup() { levelLay->addWidget(new QLabel(tr("Name:"), this), 0, 0, Qt::AlignRight); - levelLay->addWidget(m_levelNameEdit, 0, 1); - levelLay->addWidget(nextLevelButton, 0, 2); + QHBoxLayout* nameLay = new QHBoxLayout(); + nameLay->setMargin(0); + nameLay->setSpacing(2); + { + nameLay->addWidget(m_previousLevelButton, 0); + nameLay->addWidget(m_levelNameEdit, 1); + nameLay->addWidget(nextLevelButton, 0); + } + levelLay->addLayout(nameLay, 0, 1); levelLay->addWidget(new QLabel(tr("Frame:"), this), 1, 0, Qt::AlignRight); - levelLay->addWidget(m_frameNumberEdit, 1, 1); + + QHBoxLayout* frameLay = new QHBoxLayout(); + frameLay->setMargin(0); + frameLay->setSpacing(2); + { + frameLay->addWidget(m_frameNumberEdit, 1); + frameLay->addWidget(m_frameInfoLabel, 1, Qt::AlignVCenter); + } + levelLay->addLayout(frameLay, 1, 1); } levelLay->setColumnStretch(0, 0); levelLay->setColumnStretch(1, 1); - levelLay->setColumnStretch(2, 0); fileLay->addLayout(levelLay, 0); QHBoxLayout* fileTypeLay = new QHBoxLayout(); @@ -1173,6 +1317,8 @@ PencilTestPopup::PencilTestPopup() SLOT(onLevelNameEdited())); ret = ret && connect(nextLevelButton, SIGNAL(pressed()), this, SLOT(onNextName())); + ret = ret && connect(m_previousLevelButton, SIGNAL(pressed()), this, + SLOT(onPreviousName())); ret = ret && connect(m_colorTypeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(onColorTypeComboChanged(int))); ret = ret && connect(m_captureWhiteBGButton, SIGNAL(pressed()), this, @@ -1200,6 +1346,12 @@ PencilTestPopup::PencilTestPopup() SLOT(onCaptureFilterSettingsBtnPressed())); ret = ret && connect(subfolderButton, SIGNAL(clicked(bool)), this, SLOT(openSaveInFolderPopup())); + ret = ret && connect(m_saveInFileFld, SIGNAL(pathChanged()), this, + SLOT(refreshFrameInfo())); + ret = ret && connect(m_fileTypeCombo, SIGNAL(activated(int)), this, + SLOT(refreshFrameInfo())); + ret = ret && connect(m_frameNumberEdit, SIGNAL(editingFinished()), this, + SLOT(refreshFrameInfo())); assert(ret); refreshCameraList(); @@ -1220,7 +1372,7 @@ PencilTestPopup::PencilTestPopup() } } - onNextName(); + setToNextNewLevel(); } //----------------------------------------------------------------------------- @@ -1394,6 +1546,8 @@ void PencilTestPopup::onResolutionComboActivated(const QString& itemText) { // update env CamCapCameraResolution = itemText.toStdString(); + + refreshFrameInfo(); } //----------------------------------------------------------------------------- @@ -1411,17 +1565,52 @@ void PencilTestPopup::onFileFormatOptionButtonPressed() { //----------------------------------------------------------------------------- void PencilTestPopup::onLevelNameEdited() { - // set the start frame 10 if the option in preferences - // "Show ABC Appendix to the Frame Number in Xsheet Cell" is active. - // (frame 10 is displayed as "1" with this option) - int startFrame = - Preferences::instance()->isShowFrameNumberWithLettersEnabled() ? 10 : 1; - m_frameNumberEdit->setValue(startFrame); + updateLevelNameAndFrame(m_levelNameEdit->text().toStdWString()); } //----------------------------------------------------------------------------- - void PencilTestPopup::onNextName() { + std::unique_ptr nameCreator(new FlexibleNameCreator()); + if (!nameCreator->setCurrent(m_levelNameEdit->text().toStdWString())) { + setToNextNewLevel(); + return; + } + + std::wstring levelName = nameCreator->getNext(); + + updateLevelNameAndFrame(levelName); +} + +//----------------------------------------------------------------------------- + +void PencilTestPopup::onPreviousName() { + std::unique_ptr nameCreator(new FlexibleNameCreator()); + + std::wstring levelName; + + // if the current level name is non-sequencial, then try to switch the last + // sequencial level in the scene. + if (!nameCreator->setCurrent(m_levelNameEdit->text().toStdWString())) { + TLevelSet* levelSet = + TApp::instance()->getCurrentScene()->getScene()->getLevelSet(); + nameCreator->setCurrent(L"ZZ"); + for (;;) { + levelName = nameCreator->getPrevious(); + if (levelSet->getLevel(levelName) != 0) break; + if (levelName == L"A") { + setToNextNewLevel(); + return; + } + } + } else + levelName = nameCreator->getPrevious(); + + updateLevelNameAndFrame(levelName); +} + +//----------------------------------------------------------------------------- + +void PencilTestPopup::setToNextNewLevel() { const std::auto_ptr nameBuilder(NameBuilder::getBuilder(L"")); TLevelSet* levelSet = @@ -1450,13 +1639,41 @@ void PencilTestPopup::onNextName() { break; } - m_levelNameEdit->setText(QString::fromStdWString(levelName)); + updateLevelNameAndFrame(levelName); +} + +//----------------------------------------------------------------------------- + +void PencilTestPopup::updateLevelNameAndFrame(std::wstring levelName) { + if (levelName != m_levelNameEdit->text().toStdWString()) + m_levelNameEdit->setText(QString::fromStdWString(levelName)); + m_previousLevelButton->setDisabled(levelName == L"A"); + // set the start frame 10 if the option in preferences // "Show ABC Appendix to the Frame Number in Xsheet Cell" is active. // (frame 10 is displayed as "1" with this option) - int startFrame = - Preferences::instance()->isShowFrameNumberWithLettersEnabled() ? 10 : 1; + bool withLetter = + Preferences::instance()->isShowFrameNumberWithLettersEnabled(); + + TLevelSet* levelSet = + TApp::instance()->getCurrentScene()->getScene()->getLevelSet(); + TXshLevel* level_p = levelSet->getLevel(levelName); + int startFrame; + if (!level_p) { + startFrame = withLetter ? 10 : 1; + } else { + std::vector fids; + level_p->getFids(fids); + if (fids.empty()) { + startFrame = withLetter ? 10 : 1; + } else { + int lastNum = fids.back().getNumber(); + startFrame = withLetter ? ((int)(lastNum / 10) + 1) * 10 : lastNum + 1; + } + } m_frameNumberEdit->setValue(startFrame); + + refreshFrameInfo(); } //----------------------------------------------------------------------------- @@ -1490,6 +1707,11 @@ void PencilTestPopup::onImageCaptured(int id, const QImage& image) { } else m_frameNumberEdit->setValue(m_frameNumberEdit->getValue() + 1); + /* notify */ + TApp::instance()->getCurrentScene()->notifySceneChanged(); + TApp::instance()->getCurrentScene()->notifyCastChange(); + TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); + // restart interval timer for capturing next frame (it is single shot) if (m_timerCB->isChecked() && m_captureButton->isChecked()) { m_captureTimer->start(m_timerIntervalFld->getValue() * 1000); @@ -1539,6 +1761,11 @@ void PencilTestPopup::showEvent(QShowEvent* event) { if (m_currentCamera->state() == QCamera::LoadedState) m_currentCamera->start(); } + + TSceneHandle* sceneHandle = TApp::instance()->getCurrentScene(); + connect(sceneHandle, SIGNAL(sceneSwitched()), this, SLOT(refreshFrameInfo())); + connect(sceneHandle, SIGNAL(castChanged()), this, SLOT(refreshFrameInfo())); + refreshFrameInfo(); } //----------------------------------------------------------------------------- @@ -1564,6 +1791,12 @@ void PencilTestPopup::hideEvent(QHideEvent* event) { m_currentCamera->unload(); } Dialog::hideEvent(event); + + TSceneHandle* sceneHandle = TApp::instance()->getCurrentScene(); + disconnect(sceneHandle, SIGNAL(sceneSwitched()), this, + SLOT(refreshFrameInfo())); + disconnect(sceneHandle, SIGNAL(castChanged()), this, + SLOT(refreshFrameInfo())); } //----------------------------------------------------------------------------- @@ -1783,6 +2016,8 @@ bool PencilTestPopup::importImage(QImage& image) { TXshSimpleLevel* sl = 0; TXshLevel* level = scene->getLevelSet()->getLevel(levelName); + enum State { NEWLEVEL = 0, ADDFRAME, OVERWRITE } state; + /* if the level already exists in the scene cast */ if (level) { /* if the existing level is not a raster level, then return */ @@ -1815,7 +2050,9 @@ bool PencilTestPopup::importImage(QImage& image) { int ret = DVGui::MsgBox(question, QObject::tr("Overwrite"), QObject::tr("Cancel")); if (ret == 0 || ret == 2) return false; - } + state = OVERWRITE; + } else + state = ADDFRAME; } /* if the level does not exist in the scene cast */ else { @@ -1838,13 +2075,15 @@ bool PencilTestPopup::importImage(QImage& image) { } /* confirm overwrite */ - QString question = - tr("File %1 does exist.\nDo you want to overwrite it?") - .arg(toQString(actualLevelFp.withFrame(frameNumber))); - int ret = DVGui::MsgBox(question, QObject::tr("Overwrite"), - QObject::tr("Cancel")); - if (ret == 0 || ret == 2) return false; - + TFilePath frameFp(actualLevelFp.withFrame(frameNumber)); + if (TFileStatus(frameFp).doesExist()) { + QString question = + tr("File %1 does exist.\nDo you want to overwrite it?") + .arg(toQString(frameFp)); + int ret = DVGui::MsgBox(question, QObject::tr("Overwrite"), + QObject::tr("Cancel")); + if (ret == 0 || ret == 2) return false; + } } /* if the file does not exist, then create a new level */ else { @@ -1859,6 +2098,8 @@ bool PencilTestPopup::importImage(QImage& image) { sl->getProperties()->setImageRes( TDimension(image.width(), image.height())); } + + state = NEWLEVEL; } TFrameId fid(frameNumber); @@ -1879,36 +2120,65 @@ bool PencilTestPopup::importImage(QImage& image) { if (m_saveOnCaptureCB->isChecked()) sl->save(); /* placement in xsheet */ + int row = app->getCurrentFrame()->getFrame(); int col = app->getCurrentColumn()->getColumnIndex(); - /* try to find the vacant cell */ - int tmpRow = row; - while (1) { - /* if the same cell is already in the column, then just replace the content - * and do not set a new cell */ - if (xsh->getCell(tmpRow, col) == TXshCell(sl, fid)) break; - /* in case setting the same level as the the current column */ - else if (xsh->getCell(tmpRow, col).isEmpty()) { - xsh->setCell(tmpRow, col, TXshCell(sl, fid)); - break; - } - /* in case the level is different from the current column, then insert a new - column */ - else if (xsh->getCell(tmpRow, col).m_level->getSimpleLevel() != sl) { + // if the level is newly created or imported, then insert a new column + if (state == NEWLEVEL) { + if (!xsh->isColumnEmpty(col)) { col += 1; xsh->insertColumn(col); - xsh->setCell(row, col, TXshCell(sl, fid)); - app->getCurrentColumn()->setColumnIndex(col); - break; } - tmpRow++; + xsh->setCell(row, col, TXshCell(sl, fid)); + app->getCurrentColumn()->setColumnIndex(col); + return true; } - /* notify */ - app->getCurrentScene()->notifySceneChanged(); - app->getCurrentScene()->notifyCastChange(); - app->getCurrentXsheet()->notifyXsheetChanged(); + // state == OVERWRITE, ADDFRAME + + // if the same cell is already in the column, then just replace the content + // and do not set a new cell + int foundCol, foundRow = -1; + // most possibly, it's in the current column + int rowCheck; + if (findCell(xsh, col, TXshCell(sl, fid), rowCheck)) return true; + if (rowCheck >= 0) { + foundRow = rowCheck; + foundCol = col; + } + // search entire xsheet + for (int c = 0; c < xsh->getColumnCount(); c++) { + if (c == col) continue; + if (findCell(xsh, c, TXshCell(sl, fid), rowCheck)) return true; + if (rowCheck >= 0) { + foundRow = rowCheck; + foundCol = c; + } + } + // if there is a column containing the same level + if (foundRow >= 0) { + // put the cell at the bottom + int tmpRow = foundRow + 1; + while (1) { + if (xsh->getCell(tmpRow, foundCol).isEmpty()) { + xsh->setCell(tmpRow, foundCol, TXshCell(sl, fid)); + app->getCurrentColumn()->setColumnIndex(foundCol); + break; + } + tmpRow++; + } + } + // if the level is registered in the scene, but is not placed in the xsheet, + // then insert a new column + else { + if (!xsh->isColumnEmpty(col)) { + col += 1; + xsh->insertColumn(col); + } + xsh->setCell(row, col, TXshCell(sl, fid)); + app->getCurrentColumn()->setColumnIndex(col); + } return true; } @@ -1935,8 +2205,260 @@ void PencilTestPopup::openSaveInFolderPopup() { if (m_saveInFolderPopup->exec()) { QString oldPath = m_saveInFileFld->getPath(); m_saveInFileFld->setPath(m_saveInFolderPopup->getPath()); - if (oldPath == m_saveInFileFld->getPath()) onNextName(); + if (oldPath == m_saveInFileFld->getPath()) + setToNextNewLevel(); + else + refreshFrameInfo(); + } +} + +//----------------------------------------------------------------------------- + +// Refresh information that how many & which frames are saved for the current +// level +void PencilTestPopup::refreshFrameInfo() { + if (!m_currentCamera || m_deviceName.isNull()) { + m_frameInfoLabel->setText(""); + return; + } + + QString tooltipStr, labelStr; + enum InfoType { NEW = 0, ADD, OVERWRITE, WARNING } infoType(WARNING); + + static QColor infoColors[4] = {Qt::cyan, Qt::green, Qt::yellow, Qt::red}; + + ToonzScene* currentScene = TApp::instance()->getCurrentScene()->getScene(); + TLevelSet* levelSet = currentScene->getLevelSet(); + + std::wstring levelName = m_levelNameEdit->text().toStdWString(); + int frameNumber = m_frameNumberEdit->getValue(); + + QStringList texts = m_resolutionCombo->currentText().split(' '); + if (texts.size() != 3) return; + TDimension camRes(texts[0].toInt(), texts[2].toInt()); + + bool letterOptionEnabled = + Preferences::instance()->isShowFrameNumberWithLettersEnabled(); + + // level with the same name + TXshLevel* level_sameName = levelSet->getLevel(levelName); + + TFilePath levelFp = TFilePath(m_saveInFileFld->getPath()) + + TFilePath(levelName + L".." + + m_fileTypeCombo->currentText().toStdWString()); + + // level with the same path + TXshLevel* level_samePath = levelSet->getLevel(*(currentScene), levelFp); + + TFilePath actualLevelFp = currentScene->decodeFilePath(levelFp); + + // level existence + bool levelExist = TSystem::doesExistFileOrLevel(actualLevelFp); + + // frame existence + TFilePath frameFp(actualLevelFp.withFrame(frameNumber)); + bool frameExist = false; + if (levelExist) frameExist = TFileStatus(frameFp).doesExist(); + + // ### CASE 1 ### + // If there is no same level registered in the scene cast + if (!level_sameName && !level_samePath) { + // If there is a level in the file system + if (levelExist) { + TLevelReaderP lr; + TLevelP level_p; + try { + lr = TLevelReaderP(actualLevelFp); + } catch (...) { + // TODO: output something + m_frameInfoLabel->setText(tr("UNDEFINED WARNING")); + return; + } + if (!lr) { + // TODO: output something + m_frameInfoLabel->setText(tr("UNDEFINED WARNING")); + return; + } + try { + level_p = lr->loadInfo(); + } catch (...) { + // TODO: output something + m_frameInfoLabel->setText(tr("UNDEFINED WARNING")); + return; + } + if (!level_p) { + // TODO: output something + m_frameInfoLabel->setText(tr("UNDEFINED WARNING")); + return; + } + int frameCount = level_p->getFrameCount(); + TLevel::Iterator it = level_p->begin(); + std::vector fids; + for (int i = 0; it != level_p->end(); ++it, ++i) + fids.push_back(it->first); + + tooltipStr += + tr("The level is not registered in the scene, but exists in the file " + "system."); + + // check resolution + const TImageInfo* ii; + try { + ii = lr->getImageInfo(fids[0]); + } catch (...) { + // TODO: output something + m_frameInfoLabel->setText(tr("UNDEFINED WARNING")); + return; + } + TDimension dim(ii->m_lx, ii->m_ly); + // if the saved images has not the same resolution as the current camera + // resolution + if (camRes != dim) { + tooltipStr += tr("WARNING : Image size mismatch. The saved image " + "size is %1 x %2.") + .arg(dim.lx) + .arg(dim.ly); + labelStr += tr("WARNING"); + infoType = WARNING; + } + // if the resolutions are matched + else { + if (frameCount == 1) + tooltipStr += tr("\nFrame %1 exists.") + .arg(fidsToString(fids, letterOptionEnabled)); + else + tooltipStr += tr("\nFrames %1 exist.") + .arg(fidsToString(fids, letterOptionEnabled)); + // if the frame exists, then it will be overwritten + if (frameExist) { + labelStr += tr("OVERWRITE 1 of"); + infoType = OVERWRITE; + } else { + labelStr += tr("ADD to"); + infoType = ADD; + } + if (frameCount == 1) + labelStr += tr(" %1 frame").arg(frameCount); + else + labelStr += tr(" %1 frames").arg(frameCount); + } + } + // If no level exists in the file system, then it will be a new level + else { + tooltipStr += tr("The level will be newly created."); + labelStr += tr("NEW"); + infoType = NEW; + } + } + // ### CASE 2 ### + // If there is already the level registered in the scene cast + else if (level_sameName && level_samePath && + level_sameName == level_samePath) { + tooltipStr += tr("The level is already registered in the scene."); + if (!levelExist) tooltipStr += tr("\nNOTE : The level is not saved."); + + std::vector fids; + level_sameName->getFids(fids); + + // check resolution + TDimension dim; + bool ret = getRasterLevelSize(level_sameName, dim); + if (!ret) { + tooltipStr += + tr("\nWARNING : Failed to get image size of the existing level %1.") + .arg(QString::fromStdWString(levelName)); + labelStr += tr("WARNING"); + infoType = WARNING; + } + // if the saved images has not the same resolution as the current camera + // resolution + else if (camRes != dim) { + tooltipStr += tr("\nWARNING : Image size mismatch. The existing level " + "size is %1 x %2.") + .arg(dim.lx) + .arg(dim.ly); + labelStr += tr("WARNING"); + infoType = WARNING; + } + // if the resolutions are matched + else { + int frameCount = fids.size(); + if (fids.size() == 1) + tooltipStr += tr("\nFrame %1 exists.") + .arg(fidsToString(fids, letterOptionEnabled)); + else + tooltipStr += tr("\nFrames %1 exist.") + .arg(fidsToString(fids, letterOptionEnabled)); + // Check if the target frame already exist in the level + bool hasFrame = false; + for (int f = 0; f < frameCount; f++) { + if (fids.at(f).getNumber() == frameNumber) { + hasFrame = true; + break; + } + } + // If there is already the frame then it will be overwritten + if (hasFrame) { + labelStr += tr("OVERWRITE 1 of"); + infoType = OVERWRITE; + } + // Or, the frame will be added to the level + else { + labelStr += tr("ADD to"); + infoType = ADD; + } + if (frameCount == 1) + labelStr += tr(" %1 frame").arg(frameCount); + else + labelStr += tr(" %1 frames").arg(frameCount); + } } + // ### CASE 3 ### + // If there are some conflicts with the existing level. + else { + if (level_sameName) { + TFilePath anotherPath = level_sameName->getPath(); + tooltipStr += + tr("WARNING : Level name conflicts. There already is a level %1 in the scene with the path\ + \n %2.") + .arg(QString::fromStdWString(levelName)) + .arg(toQString(anotherPath)); + // check resolution + TDimension dim; + bool ret = getRasterLevelSize(level_sameName, dim); + if (ret && camRes != dim) + tooltipStr += tr("\nWARNING : Image size mismatch. The size of level " + "with the same name is is %1 x %2.") + .arg(dim.lx) + .arg(dim.ly); + } + if (level_samePath) { + std::wstring anotherName = level_samePath->getName(); + if (!tooltipStr.isEmpty()) tooltipStr += QString("\n"); + tooltipStr += + tr("WARNING : Level path conflicts. There already is a level with the path %1\ + \n in the scene with the name %2.") + .arg(toQString(levelFp)) + .arg(QString::fromStdWString(anotherName)); + // check resolution + TDimension dim; + bool ret = getRasterLevelSize(level_samePath, dim); + if (ret && camRes != dim) + tooltipStr += tr("\nWARNING : Image size mismatch. The size of level " + "with the same path is %1 x %2.") + .arg(dim.lx) + .arg(dim.ly); + } + labelStr += tr("WARNING"); + infoType = WARNING; + } + + QColor infoColor = infoColors[(int)infoType]; + m_frameInfoLabel->setStyleSheet(QString("QLabel{color: %1;}\ + QLabel QWidget{ color: black;}") + .arg(infoColor.name())); + m_frameInfoLabel->setText(labelStr); + m_frameInfoLabel->setToolTip(tooltipStr); } //----------------------------------------------------------------------------- diff --git a/toonz/sources/toonz/penciltestpopup.h b/toonz/sources/toonz/penciltestpopup.h index 6009317..8cfa88f 100644 --- a/toonz/sources/toonz/penciltestpopup.h +++ b/toonz/sources/toonz/penciltestpopup.h @@ -5,6 +5,7 @@ #include "toonzqt/dvdialog.h" #include "toonzqt/lineedit.h" +#include "toonz/namebuilder.h" #include @@ -127,6 +128,18 @@ signals: }; //============================================================================= +// FlexibleNameCreator +// Inherits NameCreator, added function for obtaining the previous name and +// setting the current name. + +class FlexibleNameCreator final : public NameCreator { +public: + FlexibleNameCreator() {} + std::wstring getPrevious(); + bool setCurrent(std::wstring name); +}; + +//============================================================================= // PencilTestSaveInFolderPopup //----------------------------------------------------------------------------- @@ -186,6 +199,10 @@ class PencilTestPopup : public DVGui::Dialog { CameraCaptureLevelControl* m_camCapLevelControl; + QLabel* m_frameInfoLabel; + + QToolButton* m_previousLevelButton; + #ifdef MACOSX QCameraViewfinder* m_dummyViewFinder; #endif @@ -198,6 +215,9 @@ class PencilTestPopup : public DVGui::Dialog { void processImage(QImage& procImage); bool importImage(QImage& image); + void setToNextNewLevel(); + void updateLevelNameAndFrame(std::wstring levelName); + public: PencilTestPopup(); ~PencilTestPopup(); @@ -216,6 +236,7 @@ protected slots: void onFileFormatOptionButtonPressed(); void onLevelNameEdited(); void onNextName(); + void onPreviousName(); void onColorTypeComboChanged(int index); void onImageCaptured(int, const QImage&); void onCaptureWhiteBGButtonPressed(); @@ -229,6 +250,8 @@ protected slots: void onCaptureButtonClicked(bool); void onCaptureFilterSettingsBtnPressed(); + void refreshFrameInfo(); + public slots: void openSaveInFolderPopup(); };