file path processing using regexp

This commit is contained in:
shun-iwasawa 2021-09-27 11:17:07 +09:00 committed by manongjohn
parent 832c2a62d5
commit d0e08fac5c
41 changed files with 1042 additions and 475 deletions

View file

@ -73,7 +73,7 @@ inline QString blanks(const QString &str, int count = 15) {
//--------------------------------------------------------------------
inline QString getStr(const TFrameId &id) {
if (id.getLetter() != 0)
if (!id.getLetter().isEmpty())
return QString::number(id.getNumber()) + id.getLetter();
else
return QString::number(id.getNumber());

View file

@ -132,6 +132,9 @@ TLevelP TLevelReader::loadInfo() {
if (!data.empty()) {
std::vector<TFilePath>::iterator it =
std::min_element(data.begin(), data.end(), myLess);
m_frameFormat = (*it).getFrame().getCurrentFormat();
/*
TFilePath fr = (*it).withoutParentDir().withName("").withType("");
wstring ws = fr.getWideString();
if (ws.length() == 5) {
@ -150,7 +153,7 @@ TLevelP TLevelReader::loadInfo() {
else
m_frameFormat = TFrameId::UNDERSCORE_NO_PAD;
}
*/
} else
m_frameFormat = TFrameId::FOUR_ZEROS;

View file

@ -27,9 +27,16 @@ const char wauxslash = '\\';
// QT
#include <QObject>
#include <QRegExp>
bool TFilePath::m_underscoreFormatAllowed = true;
// specifies file path condition for sequential image for each project.
// See filepathproperties.h
bool TFilePath::m_useStandard = true;
bool TFilePath::m_acceptNonAlphabetSuffix = false;
int TFilePath::m_letterCountForSuffix = 1;
namespace {
/*-- fromSeg位置 と
@ -102,23 +109,27 @@ std::string TFrameId::expand(FrameFormat format) const {
} else {
o_buff << m_frame;
}
if (m_letter != '\0') o_buff << m_letter;
if (m_letter.isEmpty())
return o_buff.str();
else
return o_buff.str() + m_letter.toStdString();
}
//-------------------------------------------------------------------
const TFrameId &TFrameId::operator++() {
++m_frame;
m_letter = 0;
m_letter = "";
// m_letter = 0;
return *this;
}
//-------------------------------------------------------------------
const TFrameId &TFrameId::operator--() {
if (m_letter > 0)
m_letter = 0;
if (!m_letter.isEmpty()) m_letter = "";
// if (m_letter > 0)
// m_letter = 0;
else
--m_frame;
return *this;
@ -287,8 +298,7 @@ void TFilePath::setPath(std::wstring path) {
(m_path.length() > 1 && m_path[m_path.length() - 1] == wslash))
m_path.erase(m_path.length() - 1, 1);
if (isUncName &&
!(m_path.find_last_of(L'\\') > 1 ||
if (isUncName && !(m_path.find_last_of(L'\\') > 1 ||
m_path.find_last_of(L'/') >
1)) // e' indicato solo il nome della macchina...
m_path.append(1, wslash);
@ -531,6 +541,15 @@ bool TFilePath::isRoot() const {
// ritorna ""(niente tipo, niente punto), "." (file con tipo) o ".." (file con
// tipo e frame)
std::string TFilePath::getDots() const {
if (!TFilePath::m_useStandard) {
TFilePathInfo info = analyzePath();
if (info.extension.isEmpty()) return "";
if (info.sepChar.isNull()) return ".";
// return ".." regardless of sepChar type (either "_" or ".")
return "..";
}
//-----
QString type = QString::fromStdString(getType()).toLower();
if (isFfmpegType()) return ".";
int i = getLastSlash(m_path);
@ -555,6 +574,12 @@ std::string TFilePath::getDots() const {
std::string TFilePath::getDottedType()
const // ritorna l'estensione con PUNTO (se c'e')
{
if (!TFilePath::m_useStandard) {
QString ext = analyzePath().extension;
if (ext.isEmpty()) return "";
return "." + ext.toLower().toStdString();
}
int i = getLastSlash(m_path);
std::wstring str = m_path.substr(i + 1);
i = str.rfind(L".");
@ -568,6 +593,15 @@ std::string TFilePath::getDottedType()
std::string TFilePath::getUndottedType()
const // ritorna l'estensione senza PUNTO
{
if (!TFilePath::m_useStandard) {
QString ext = analyzePath().extension;
if (ext.isEmpty())
return "";
else
return ext.toLower().toStdString();
}
//-----
size_t i = getLastSlash(m_path);
std::wstring str = m_path.substr(i + 1);
i = str.rfind(L".");
@ -579,6 +613,11 @@ std::string TFilePath::getUndottedType()
std::wstring TFilePath::getWideName() const // noDot! noSlash!
{
if (!TFilePath::m_useStandard) {
return analyzePath().levelName.toStdWString();
}
//-----
QString type = QString::fromStdString(getType()).toLower();
int i = getLastSlash(m_path); // cerco l'ultimo slash
std::wstring str = m_path.substr(i + 1);
@ -613,6 +652,16 @@ std::string TFilePath::getLevelName() const {
// es. TFilePath("/pippo/pluto.0001.gif").getLevelName() == "pluto..gif"
std::wstring TFilePath::getLevelNameW() const {
if (!TFilePath::m_useStandard) {
TFilePathInfo info = analyzePath();
if (info.extension.isEmpty()) return info.levelName.toStdWString();
QString name = info.levelName;
if (!info.sepChar.isNull()) name += info.sepChar;
name += "." + info.extension;
return name.toStdWString();
}
//-----
int i = getLastSlash(m_path); // cerco l'ultimo slash
std::wstring str = m_path.substr(i + 1); // str e' m_path senza directory
QString type = QString::fromStdString(getType()).toLower();
@ -627,7 +676,8 @@ std::wstring TFilePath::getLevelNameW() const {
return str;
if (!checkForSeqNum(type) || !isNumbers(str, i, j) ||
i == (int)std::wstring::npos) return str;
i == (int)std::wstring::npos)
return str;
// prova.0001.tif
return str.erase(i + 1, j - i - 1);
}
@ -638,7 +688,8 @@ TFilePath TFilePath::getParentDir() const // noSlash!
{
int i = getLastSlash(m_path); // cerco l'ultimo slash
if (i < 0) {
if (m_path.length() >= 2 && (('a' <= m_path[0] && m_path[0] <= 'z') ||
if (m_path.length() >= 2 &&
(('a' <= m_path[0] && m_path[0] <= 'z') ||
('A' <= m_path[0] && m_path[0] <= 'Z')) &&
m_path[1] == ':')
return TFilePath(m_path.substr(0, 2));
@ -651,8 +702,13 @@ TFilePath TFilePath::getParentDir() const // noSlash!
}
//-----------------------------------------------------------------------------
// return true if the fID is EMPTY_FRAME
bool TFilePath::isLevelName() const {
if (!TFilePath::m_useStandard) {
return analyzePath().fId.getNumber() == TFrameId::EMPTY_FRAME;
}
//-----
QString type = QString::fromStdString(getType()).toLower();
if (isFfmpegType() || !checkForSeqNum(type)) return false;
try {
@ -665,6 +721,11 @@ bool TFilePath::isLevelName() const {
}
TFrameId TFilePath::getFrame() const {
if (!TFilePath::m_useStandard) {
return analyzePath().fId;
}
//-----
int i = getLastSlash(m_path); // cerco l'ultimo slash
std::wstring str = m_path.substr(i + 1); // str e' il path senza parentdir
QString type = QString::fromStdString(getType()).toLower();
@ -680,8 +741,7 @@ TFrameId TFilePath::getFrame() const {
if (j == (int)std::wstring::npos) return TFrameId(TFrameId::NO_FRAME);
if (i == j + 1) return TFrameId(TFrameId::EMPTY_FRAME);
/*-- 間が数字でない場合(ファイル名にまぎれた"_" や "."がある場合)を除外する
* --*/
// 間が数字でない場合(ファイル名にまぎれた"_" や "."がある場合)を除外する
if (!checkForSeqNum(type) || !isNumbers(str, j, i))
return TFrameId(TFrameId::NO_FRAME);
@ -692,12 +752,11 @@ TFrameId TFilePath::getFrame() const {
}
char letter = '\0';
if (iswalpha(str[k])) letter = str[k++] + ('a' - L'a');
/*
if (number == 0 || k < i) // || letter!='\0')
throw TMalformedFrameException(
*this,
str + L": " + QObject::tr("Malformed frame name").toStdWString());
*/
// if (number == 0 || k < i) // || letter!='\0')
// throw TMalformedFrameException(
// *this,
// str + L": " + QObject::tr("Malformed frame name").toStdWString());
int padding = 0;
if (str[j + 1] == '0') padding = digits;
@ -751,6 +810,20 @@ TFilePath TFilePath::withName(const std::string &name) const {
//-----------------------------------------------------------------------------
TFilePath TFilePath::withName(const std::wstring &name) const {
if (!TFilePath::m_useStandard) {
TFilePathInfo info = analyzePath();
QString ret = info.parentDir + QString::fromStdWString(name);
if (info.fId.getNumber() != TFrameId::NO_FRAME) {
QString sepChar = (info.sepChar.isNull()) ? "." : QString(info.sepChar);
ret += sepChar + QString::fromStdString(
info.fId.expand(info.fId.getCurrentFormat()));
}
if (!info.extension.isEmpty()) ret += "." + info.extension;
return TFilePath(ret);
}
int i = getLastSlash(m_path); // cerco l'ultimo slash
std::wstring str = m_path.substr(i + 1); // str e' il path senza parentdir
QString type = QString::fromStdString(getType()).toLower();
@ -790,6 +863,31 @@ TFilePath TFilePath::withParentDir(const TFilePath &dir) const {
TFilePath TFilePath::withFrame(const TFrameId &frame,
TFrameId::FrameFormat format) const {
if (!TFilePath::m_useStandard) {
TFilePathInfo info = analyzePath();
// Override format input because it may be wrong.
if (checkForSeqNum(info.extension)) format = frame.getCurrentFormat();
// override format if the original fid is available
else if (info.fId.getNumber() != TFrameId::NO_FRAME)
format = info.fId.getCurrentFormat();
if (info.extension.isEmpty()) {
if (frame.isEmptyFrame() || frame.isNoFrame()) return *this;
return TFilePath(m_path + L"." + ::to_wstring(frame.expand(format)));
}
if (frame.isNoFrame()) {
return TFilePath(info.parentDir + info.levelName + "." + info.extension);
}
QString sepChar = (info.sepChar.isNull()) ? "." : QString(info.sepChar);
return TFilePath(info.parentDir + info.levelName + sepChar +
QString::fromStdString(frame.expand(format)) + "." +
info.extension);
}
//-----------------
const std::wstring dot = L".", dotDot = L"..";
int i = getLastSlash(m_path); // cerco l'ultimo slash
std::wstring str = m_path.substr(i + 1); // str e' il path senza parentdir
@ -804,6 +902,8 @@ TFilePath TFilePath::withFrame(const TFrameId &frame,
format == TFrameId::UNDERSCORE_NO_PAD ||
format == TFrameId::UNDERSCORE_CUSTOM_PAD))
ch = "_";
// no extension case
if (j == (int)std::wstring::npos) {
if (frame.isEmptyFrame() || frame.isNoFrame())
return *this;
@ -842,7 +942,7 @@ TFilePath TFilePath::withFrame(const TFrameId &frame,
(k == j - 1 ||
(checkForSeqNum(type) &&
isNumbers(str, k,
j)))) /*-- "_." の並びか、"_[数字]."の並びのとき --*/
j)))) //-- "_." の並びか、"_[数字]."の並びのとき --
return TFilePath(m_path.substr(0, k + i + 1) +
((frame.isNoFrame())
? L""
@ -893,6 +993,16 @@ TFilePath TFilePath::operator-(const TFilePath &fp) const {
//-----------------------------------------------------------------------------
bool TFilePath::match(const TFilePath &fp) const {
if (!TFilePath::m_useStandard) {
if (getParentDir() != fp.getParentDir()) return false;
TFilePathInfo info = analyzePath();
TFilePathInfo info_ext = fp.analyzePath();
return (info.levelName == info_ext.levelName && info.fId == info_ext.fId &&
info.extension == info_ext.extension);
}
return getParentDir() == fp.getParentDir() && getName() == fp.getName() &&
getFrame() == fp.getFrame() && getType() == fp.getType();
}
@ -915,3 +1025,118 @@ void TFilePath::split(std::wstring &head, TFilePath &tail) const {
head = ancestor.getWideString();
tail = *this - ancestor;
}
//-----------------------------------------------------------------------------
QString TFilePath::fidRegExpStr() {
if (m_useStandard) return QString("(\\d+)([a-zA-Z]?)");
QString suffixLetter = (m_acceptNonAlphabetSuffix)
? "[^\\._ \\\\/:,;*?\"<>|0123456789]"
: "[a-zA-Z]";
QString countLetter = (m_letterCountForSuffix == 0)
? "{0,}"
: (QString("{0,%1}").arg(m_letterCountForSuffix));
return QString("(\\d+)(%1%2)").arg(suffixLetter).arg(countLetter);
// const QString fIdRegExp("(\\d+)([a-zA-Z]?)");
}
//-----------------------------------------------------------------------------
TFilePath::TFilePathInfo TFilePath::analyzePath() const {
assert(!TFilePath::m_useStandard);
TFilePath::TFilePathInfo info;
int i = getLastSlash(m_path);
std::wstring str = m_path.substr(i + 1);
if (i >= 0) info.parentDir = QString::fromStdWString(m_path.substr(0, i + 1));
QString fileName = QString::fromStdWString(str);
// Level Name : letters other than \/:,;*?"<>|
const QString levelNameRegExp("([^\\\\/:,;*?\"<>|]+)");
// Sep Char : period or underscore
const QString sepCharRegExp("([\\._])");
// Frame Number and Suffix
QString fIdRegExp = TFilePath::fidRegExpStr();
// Extensionletters other than "._" or \/:,;*?"<>| or " "(space)
const QString extensionRegExp("([^\\._ \\\\/:,;*?\"<>|]+)");
// ignore frame numbers on non-sequential (i.e. movie) extension case :
// hoge_0001.mp4
// QRegExp rx_mf("^" + levelNameRegExp + "\\." + extensionRegExp + "$");
// if (rx_mf.indexIn(levelName) != -1) {
// QString ext = rx_mf.cap(2);
// if (!checkForSeqNum(ext)) {
// info.levelName = rx_mf.cap(1);
// info.sepChar = QChar();
// info.fId = TFrameId(TFrameId::NO_FRAME, 0, 0); //NO_PADで初期化する
// info.extension = ext;
// return info;
// }
//}
// hogehoge.0001a.jpg
// empty frame case : hogehoge..jpg
QRegExp rx("^" + levelNameRegExp + sepCharRegExp + "(?:" + fIdRegExp + ")?" +
"\\." + extensionRegExp + "$");
if (rx.indexIn(fileName) != -1) {
assert(rx.captureCount() == 5);
info.levelName = rx.cap(1);
info.sepChar = rx.cap(2)[0];
info.extension = rx.cap(5);
// ignore frame numbers on non-sequential (i.e. movie) extension case :
// hoge_0001.mp4
if (!checkForSeqNum(info.extension)) {
info.levelName = rx.cap(1) + rx.cap(2);
if (!rx.cap(3).isEmpty()) info.levelName += rx.cap(3);
if (!rx.cap(4).isEmpty()) info.levelName += rx.cap(4);
info.sepChar = QChar();
info.fId = TFrameId(TFrameId::NO_FRAME, 0, 0); // initialize with NO_PAD
} else {
QString numberStr = rx.cap(3);
if (numberStr.isEmpty()) // empty frame case : hogehoge..jpg
info.fId =
TFrameId(TFrameId::EMPTY_FRAME, 0, 4, info.sepChar.toLatin1());
else {
int number = numberStr.toInt();
int padding = 0;
if (numberStr[0] == "0") // with padding
padding = numberStr.count();
QString suffix;
if (!rx.cap(4).isEmpty()) suffix = rx.cap(4);
info.fId = TFrameId(number, suffix, padding, info.sepChar.toLatin1());
}
}
return info;
}
// QRegExp rx_ef("^" + levelNameRegExp + sepCharRegExp + "\\." +
// extensionRegExp + "$"); if (rx_ef.indexIn(levelName) != -1) {
// info.levelName = rx_ef.cap(1);
// info.sepChar = rx_ef.cap(2)[0];
// info.fId = TFrameId(TFrameId::EMPTY_FRAME, 0, 4, info.sepChar.toLatin1());
// info.extension = rx_ef.cap(3);
// return info;
//}
// no frame case : hogehoge.jpg
// no level name case : .jpg
QRegExp rx_nf("^(?:" + levelNameRegExp + ")?\\." + extensionRegExp + "$");
if (rx_nf.indexIn(fileName) != -1) {
if (!rx_nf.cap(1).isEmpty()) info.levelName = rx_nf.cap(1);
info.sepChar = QChar();
info.fId = TFrameId(TFrameId::NO_FRAME, 0, 0); // initialize with NO_PAD
info.extension = rx_nf.cap(2);
return info;
}
// no periods
info.levelName = fileName;
info.sepChar = QChar();
info.fId = TFrameId(TFrameId::NO_FRAME, 0, 0); // initialize with NO_PAD
info.extension = QString();
return info;
}

View file

@ -332,7 +332,7 @@ void TLevelWriterAvi::createBitmap(int lx, int ly) {
TImageWriterP TLevelWriterAvi::getFrameWriter(TFrameId fid) {
if (IOError != 0)
throw TImageException(m_path, buildAVIExceptionString(IOError));
if (fid.getLetter() != 0) return TImageWriterP(0);
if (!fid.getLetter().isEmpty()) return TImageWriterP(0);
int index = fid.getNumber() - 1;
TImageWriterAvi *iwa = new TImageWriterAvi(m_path, index, this);
return TImageWriterP(iwa);
@ -879,7 +879,7 @@ TLevelP TLevelReaderAvi::loadInfo() {
TImageReaderP TLevelReaderAvi::getFrameReader(TFrameId fid) {
if (IOError != 0)
throw TImageException(m_path, buildAVIExceptionString(IOError));
if (fid.getLetter() != 0) return TImageReaderP(0);
if (!fid.getLetter().isEmpty()) return TImageReaderP(0);
int index = fid.getNumber() - 1;
TImageReaderAvi *ira = new TImageReaderAvi(m_path, index, this);

View file

@ -119,7 +119,7 @@ TLevelWriterGif::~TLevelWriterGif() {
TImageWriterP TLevelWriterGif::getFrameWriter(TFrameId fid) {
// if (IOError != 0)
// throw TImageException(m_path, buildGifExceptionString(IOError));
if (fid.getLetter() != 0) return TImageWriterP(0);
if (!fid.getLetter().isEmpty()) return TImageWriterP(0);
int index = fid.getNumber();
TImageWriterGif *iwg = new TImageWriterGif(m_path, index, this);
return TImageWriterP(iwg);
@ -224,7 +224,7 @@ TLevelP TLevelReaderGif::loadInfo() {
TImageReaderP TLevelReaderGif::getFrameReader(TFrameId fid) {
// if (IOError != 0)
// throw TImageException(m_path, buildAVIExceptionString(IOError));
if (fid.getLetter() != 0) return TImageReaderP(0);
if (!fid.getLetter().isEmpty()) return TImageReaderP(0);
int index = fid.getNumber();
TImageReaderGif *irm = new TImageReaderGif(m_path, index, this, m_info);
return TImageReaderP(irm);

View file

@ -104,7 +104,7 @@ TLevelWriterMov::~TLevelWriterMov() {
TImageWriterP TLevelWriterMov::getFrameWriter(TFrameId fid) {
// if (IOError != 0)
// throw TImageException(m_path, buildMovExceptionString(IOError));
if (fid.getLetter() != 0) return TImageWriterP(0);
if (!fid.getLetter().isEmpty()) return TImageWriterP(0);
int index = fid.getNumber();
TImageWriterMov *iwg = new TImageWriterMov(m_path, index, this);
return TImageWriterP(iwg);
@ -207,7 +207,7 @@ TLevelP TLevelReaderMov::loadInfo() {
TImageReaderP TLevelReaderMov::getFrameReader(TFrameId fid) {
// if (IOError != 0)
// throw TImageException(m_path, buildAVIExceptionString(IOError));
if (fid.getLetter() != 0) return TImageReaderP(0);
if (!fid.getLetter().isEmpty()) return TImageReaderP(0);
int index = fid.getNumber();
TImageReaderMov *irm = new TImageReaderMov(m_path, index, this, m_info);

View file

@ -100,7 +100,7 @@ TLevelWriterMp4::~TLevelWriterMp4() {
TImageWriterP TLevelWriterMp4::getFrameWriter(TFrameId fid) {
// if (IOError != 0)
// throw TImageException(m_path, buildMp4ExceptionString(IOError));
if (fid.getLetter() != 0) return TImageWriterP(0);
if (!fid.getLetter().isEmpty()) return TImageWriterP(0);
int index = fid.getNumber();
TImageWriterMp4 *iwg = new TImageWriterMp4(m_path, index, this);
return TImageWriterP(iwg);
@ -203,7 +203,7 @@ TLevelP TLevelReaderMp4::loadInfo() {
TImageReaderP TLevelReaderMp4::getFrameReader(TFrameId fid) {
// if (IOError != 0)
// throw TImageException(m_path, buildAVIExceptionString(IOError));
if (fid.getLetter() != 0) return TImageReaderP(0);
if (!fid.getLetter().isEmpty()) return TImageReaderP(0);
int index = fid.getNumber();
TImageReaderMp4 *irm = new TImageReaderMp4(m_path, index, this, m_info);

View file

@ -101,7 +101,7 @@ TLevelWriterWebm::~TLevelWriterWebm() {
TImageWriterP TLevelWriterWebm::getFrameWriter(TFrameId fid) {
// if (IOError != 0)
// throw TImageException(m_path, buildGifExceptionString(IOError));
if (fid.getLetter() != 0) return TImageWriterP(0);
if (!fid.getLetter().isEmpty()) return TImageWriterP(0);
int index = fid.getNumber();
TImageWriterWebm *iwg = new TImageWriterWebm(m_path, index, this);
return TImageWriterP(iwg);
@ -204,7 +204,7 @@ TLevelP TLevelReaderWebm::loadInfo() {
TImageReaderP TLevelReaderWebm::getFrameReader(TFrameId fid) {
// if (IOError != 0)
// throw TImageException(m_path, buildAVIExceptionString(IOError));
if (fid.getLetter() != 0) return TImageReaderP(0);
if (!fid.getLetter().isEmpty()) return TImageReaderP(0);
int index = fid.getNumber();
TImageReaderWebm *irm = new TImageReaderWebm(m_path, index, this, m_info);

View file

@ -29,7 +29,7 @@ typedef TVectorImage::IntersectionBranch IntersectionBranch;
TNZ_LITTLE_ENDIAN undefined !!
#endif
static const int c_majorVersionNumber = 120;
static const int c_majorVersionNumber = 150;
static const int c_minorVersionNumber = 0;
/*=====================================================================*/
@ -669,15 +669,27 @@ void ParsedPliImp::loadInfo(bool readPlt, TPalette *&palette,
USHORT frame;
m_iChan >> frame;
QByteArray suffix;
if (m_majorVersionNumber >= 150) {
TUINT32 suffixLength;
m_iChan >> suffixLength;
if ((int)suffixLength > 0) {
suffix.resize(suffixLength);
m_iChan.read(suffix.data(), suffixLength);
}
} else {
char letter = 0;
if (m_majorVersionNumber > 6 ||
(m_majorVersionNumber == 6 && m_minorVersionNumber >= 6))
m_iChan >> letter;
if (letter > 0) suffix = QByteArray(&letter, 1);
}
m_frameOffsInFile[TFrameId(frame, letter)] = m_iChan.tellg();
m_frameOffsInFile[TFrameId(frame, QString::fromUtf8(suffix))] =
m_iChan.tellg();
// m_iChan.seekg(m_tagLength, ios::cur);
m_iChan.seekg(m_tagLength - 2, ios::cur);
if (m_majorVersionNumber < 150) m_iChan.seekg(m_tagLength - 2, ios::cur);
} else if (type == PliTag::STYLE_NGOBJ) {
m_iChan.seekg(pos, ios::beg);
TagElem *tagElem = readTag();
@ -798,7 +810,7 @@ ImageTag *ParsedPliImp::loadFrame(const TFrameId &frameNumber) {
// PliTag *tag;
USHORT type = PliTag::IMAGE_BEGIN_GOBJ;
USHORT frame;
char letter;
QByteArray suffix;
TFrameId frameId;
// cerco il frame
@ -813,13 +825,21 @@ ImageTag *ParsedPliImp::loadFrame(const TFrameId &frameNumber) {
while ((type = readTagHeader()) != PliTag::END_CNTRL) {
if (type == PliTag::IMAGE_BEGIN_GOBJ) {
m_iChan >> frame;
if (m_majorVersionNumber >= 150) {
TUINT32 suffixLength;
m_iChan >> suffixLength;
suffix.resize(suffixLength);
m_iChan.read(suffix.data(), suffixLength);
} else {
char letter = 0;
if (m_majorVersionNumber > 6 ||
(m_majorVersionNumber == 6 && m_minorVersionNumber >= 6))
(m_majorVersionNumber == 6 && m_minorVersionNumber >= 6)) {
m_iChan >> letter;
else
letter = 0;
if (letter > 0) suffix = QByteArray(&letter, 1);
}
}
frameId = TFrameId(frame, letter);
frameId = TFrameId(frame, QString::fromUtf8(suffix));
m_frameOffsInFile[frameId] = m_iChan.tellg();
if (frameId == frameNumber) break;
} else
@ -1056,15 +1076,16 @@ inline bool ParsedPliImp::readDynamicData(TINT32 &val, TUINT32 &bufOffs) {
case 4:
if (m_isIrixEndian) {
val = (m_buf[bufOffs + 3] | (m_buf[bufOffs + 2] << 8) |
(m_buf[bufOffs + 1] << 16) | (m_buf[bufOffs] << 24)) & 0x7fffffff;
(m_buf[bufOffs + 1] << 16) | (m_buf[bufOffs] << 24)) &
0x7fffffff;
if (m_buf[bufOffs] & 0x80) {
val = -val;
isNegative = true;
}
} else {
val = (m_buf[bufOffs] | (m_buf[bufOffs + 1] << 8) |
(m_buf[bufOffs + 2] << 16) |
(m_buf[bufOffs + 3] << 24)) & 0x7fffffff;
(m_buf[bufOffs + 2] << 16) | (m_buf[bufOffs + 3] << 24)) &
0x7fffffff;
if (m_buf[bufOffs + 3] & 0x80) {
val = -val;
isNegative = true;
@ -1614,11 +1635,25 @@ PliTag *ParsedPliImp::readImageTag() {
bufOffs += 2;
int headerLength = 2;
QByteArray suffix;
if (m_majorVersionNumber >= 150) {
TUINT32 suffixLength;
readTUINT32Data(suffixLength, bufOffs);
headerLength += 4;
if (suffixLength > 0) {
suffix = QByteArray((char *)m_buf.get() + bufOffs, suffixLength);
bufOffs += suffixLength;
headerLength += suffixLength;
}
} else {
char letter = 0;
if (m_majorVersionNumber > 6 ||
(m_majorVersionNumber == 6 && m_minorVersionNumber >= 6)) {
letter = (char)m_buf[bufOffs++];
++headerLength;
if (letter > 0) suffix = QByteArray(&letter, 1);
}
}
TUINT32 numObjects = (m_tagLength - headerLength) / m_currDynamicTypeBytesNum;
@ -1638,7 +1673,8 @@ PliTag *ParsedPliImp::readImageTag() {
assert(false);
std::unique_ptr<ImageTag[]> tag(
new ImageTag(TFrameId(frame, letter), numObjects, std::move(object)));
new ImageTag(TFrameId(frame, QString::fromUtf8(suffix)), numObjects,
std::move(object)));
return tag.release();
}
@ -2128,10 +2164,24 @@ TUINT32 ParsedPliImp::writeImageTag(ImageTag *tag) {
TUINT32 *objectOffset, offset, tagLength;
int maxval = 0, minval = 100000;
writeTagHeader((UCHAR)PliTag::IMAGE_BEGIN_GOBJ, 3);
QByteArray suffix = tag->m_numFrame.getLetter().toUtf8();
TUINT32 suffixLength = suffix.size();
UINT fIdTagLength;
if (m_majorVersionNumber >= 150) { // write the suffix length before data
fIdTagLength = 2 + 4 + suffixLength;
writeTagHeader((UCHAR)PliTag::IMAGE_BEGIN_GOBJ, fIdTagLength);
*m_oChan << (USHORT)tag->m_numFrame.getNumber();
*m_oChan << tag->m_numFrame.getLetter();
*m_oChan << suffixLength;
if (suffixLength > 0) m_oChan->writeBuf(suffix.data(), suffixLength);
} else { // write only the first byte
fIdTagLength = 3;
writeTagHeader((UCHAR)PliTag::IMAGE_BEGIN_GOBJ, fIdTagLength);
*m_oChan << (USHORT)tag->m_numFrame.getNumber();
if (suffixLength > 0)
m_oChan->writeBuf(suffix.data(), 1);
else
*m_oChan << (UCHAR)0;
}
m_currDynamicTypeBytesNum = 3;
objectOffset = new TUINT32[tag->m_numObjects];
@ -2155,12 +2205,23 @@ TUINT32 ParsedPliImp::writeImageTag(ImageTag *tag) {
setDynamicTypeBytesNum(minval, maxval);
tagLength = tag->m_numObjects * m_currDynamicTypeBytesNum + 3;
tagLength = tag->m_numObjects * m_currDynamicTypeBytesNum + fIdTagLength;
// tagLength = tag->m_numObjects * m_currDynamicTypeBytesNum + 3;
offset = writeTagHeader((UCHAR)PliTag::IMAGE_GOBJ, tagLength);
suffix = tag->m_numFrame.getLetter().toUtf8();
*m_oChan << (USHORT)tag->m_numFrame.getNumber();
*m_oChan << tag->m_numFrame.getLetter();
if (m_majorVersionNumber >= 150) { // write the suffix length before data
*m_oChan << suffixLength;
if (suffixLength > 0) m_oChan->writeBuf(suffix.data(), suffixLength);
} else { // write only the first byte
if (suffixLength > 0)
m_oChan->writeBuf(suffix.data(), 1);
else
*m_oChan << (UCHAR)0;
}
for (i = 0; i < tag->m_numObjects; i++) writeDynamicData(objectOffset[i]);
@ -2635,7 +2696,13 @@ void ParsedPli::getVersion(UINT &majorVersionNumber,
/*=====================================================================*/
void ParsedPli::setVersion(UINT majorVersionNumber, UINT minorVersionNumber) {
if (imp->m_versionLocked) return;
if (imp->m_versionLocked) {
// accept only when settings higher versions
if ((imp->m_majorVersionNumber > majorVersionNumber) ||
(imp->m_majorVersionNumber == majorVersionNumber &&
imp->m_minorVersionNumber >= minorVersionNumber))
return;
}
if (majorVersionNumber >= 120) imp->m_versionLocked = true;
imp->m_majorVersionNumber = majorVersionNumber;
imp->m_minorVersionNumber = minorVersionNumber;

View file

@ -422,8 +422,8 @@ TImageP TImageReaderPli::doLoad() {
// throw;
// }
// if (regionsComputed) //WARNING !!! la seedFill mette il flag a ValidRegion a
// TRUE
// if (regionsComputed) //WARNING !!! la seedFill mette il flag a ValidRegion
// a TRUE
// outVectImage->seedFill(); //le vecchie immagini hanno il seed
// (version<3.1)
@ -564,6 +564,9 @@ solo nel costruttore)
PliTag *tag = new PrecisionScaleTag(precisionScale);
tags.push_back((PliObjectTag *)tag);
}
// update the format version if multiple suffixes is supported0
if (!TFilePath::useStandard()) pli->setVersion(150, 0);
// Store the auto close tolerance
double pliTolerance = m_lwp->m_pli->getAutocloseTolerance();
// write the tag if the frame's tolerance has been changed or

View file

@ -190,7 +190,7 @@ TLevelWriterSprite::~TLevelWriterSprite() {
//-----------------------------------------------------------
TImageWriterP TLevelWriterSprite::getFrameWriter(TFrameId fid) {
if (fid.getLetter() != 0) return TImageWriterP(0);
if (!fid.getLetter().isEmpty()) return TImageWriterP(0);
int index = fid.getNumber();
TImageWriterSprite *iwg = new TImageWriterSprite(m_path, index, this);
return TImageWriterP(iwg);

View file

@ -25,7 +25,6 @@
TNZ_LITTLE_ENDIAN undefined !!
#endif
const int CURRENT_VERSION = 14;
const int CREATOR_LENGTH = 40;
namespace {
@ -40,6 +39,13 @@ char *reverse(char *buffer, int size) {
}
return buffer;
}
// switch the saving version according to the file path property
int currentVersion() {
if (TFilePath::useStandard()) return 14;
return 15;
}
} // namespace
static int tfwrite(const char *data, const unsigned int count, FILE *f) {
@ -138,6 +144,8 @@ bool readVersion(FILE *chan, int &version) {
version = 13;
} else if (memcmp(magic, "TLV14", 5) == 0) {
version = 14;
} else if (memcmp(magic, "TLV15", 5) == 0) {
version = 15;
} else {
return false;
}
@ -162,7 +170,7 @@ bool readHeaderAndOffsets(FILE *chan, TzlOffsetMap &frameOffsTable,
if (!readVersion(chan, version)) return false;
// read creator
if (version == 14) {
if (version >= 14) {
char buffer[CREATOR_LENGTH + 1];
memset(buffer, 0, sizeof buffer);
fread(&buffer, sizeof(char), CREATOR_LENGTH, chan);
@ -201,9 +209,18 @@ bool readHeaderAndOffsets(FILE *chan, TzlOffsetMap &frameOffsTable,
TFrameId oldFid(TFrameId::EMPTY_FRAME);
for (int i = 0; i < (int)frameCount; i++) {
TINT32 number, offs, length;
char letter;
QByteArray suffix;
fread(&number, sizeof(TINT32), 1, chan);
if (version >= 15) {
TINT32 suffixLength;
fread(&suffixLength, sizeof(TINT32), 1, chan);
suffix.resize(suffixLength);
fread(suffix.data(), sizeof(char), suffixLength, chan);
} else {
char letter;
fread(&letter, sizeof(char), 1, chan);
suffix = QByteArray(&letter, 1);
}
fread(&offs, sizeof(TINT32), 1, chan);
if (version >= 12) fread(&length, sizeof(TINT32), 1, chan);
@ -215,7 +232,7 @@ bool readHeaderAndOffsets(FILE *chan, TzlOffsetMap &frameOffsTable,
// std::cout << "#" << i << std::hex << " n 0x" << number
//<< " l 0x" << letter << " o 0x" << offs << std::dec << std::endl;
TFrameId fid(number, letter);
TFrameId fid(number, QString::fromUtf8(suffix));
// assert(i==0 || oldFid<fid);
if (version >= 12) {
@ -241,9 +258,18 @@ bool readHeaderAndOffsets(FILE *chan, TzlOffsetMap &frameOffsTable,
for (int i = 0; i < (int)frameCount; i++) {
TINT32 number, thumbnailOffs, thumbnailLength;
char letter;
QByteArray suffix;
fread(&number, sizeof(TINT32), 1, chan);
if (version >= 15) {
TINT32 suffixLength;
fread(&suffixLength, sizeof(TINT32), 1, chan);
suffix.resize(suffixLength);
fread(suffix.data(), sizeof(char), suffixLength, chan);
} else {
char letter;
fread(&letter, sizeof(char), 1, chan);
suffix = QByteArray(&letter, 1);
}
fread(&thumbnailOffs, sizeof(TINT32), 1, chan);
fread(&thumbnailLength, sizeof(TINT32), 1, chan);
@ -252,7 +278,7 @@ bool readHeaderAndOffsets(FILE *chan, TzlOffsetMap &frameOffsTable,
thumbnailOffs = swapTINT32(thumbnailOffs);
thumbnailLength = swapTINT32(thumbnailLength);
#endif
TFrameId fid(number, letter);
TFrameId fid(number, QString::fromUtf8(suffix));
iconOffsTable[fid] = TzlChunk(thumbnailOffs, thumbnailLength);
}
}
@ -460,7 +486,7 @@ void TLevelWriterTzl::buildFreeChunksTable() {
// dati relativi alle immagini
if (m_version == 13)
curPos = 6 * sizeof(TINT32) + 4 * sizeof(char) + 8 * sizeof(char);
else if (m_version == 14)
else if (m_version >= 14)
curPos = 6 * sizeof(TINT32) + 4 * sizeof(char) + 8 * sizeof(char) +
CREATOR_LENGTH * sizeof(char);
else
@ -495,7 +521,7 @@ TLevelWriterTzl::TLevelWriterTzl(const TFilePath &path, TPropertyGroup *info)
, m_palette(0)
, m_res(0, 0)
, m_exists(false)
, m_version(CURRENT_VERSION)
, m_version(currentVersion())
, m_updatedIconsSize(false)
, m_currentIconSize(0, 0)
, m_iconSize(TDimension(80, 60))
@ -506,13 +532,14 @@ TLevelWriterTzl::TLevelWriterTzl(const TFilePath &path, TPropertyGroup *info)
m_path = path;
m_palettePath = path.withNoFrame().withType("tpl");
TFileStatus fs(path);
m_magic = "TLV14B1a"; // actual version
m_magic = (m_version == 14) ? "TLV14B1a" : "TLV15B1a"; // actual version
erasedFrame = false;
// version TLV10B1a: first version
// version TLV11B1a: added frameIds
// version TLV12B1a: incremental writings
// version TLV13B1a: added thumbnails
// version TLV15B1a: add creator string (fixed size = CREATOR_LENGTH char)
// version TLV14B1a: add creator string (fixed size = CREATOR_LENGTH char)
// version TLV15B1a: support multiple suffixes
if (fs.doesExist()) {
// if (!fs.isWritable())
@ -530,7 +557,7 @@ TLevelWriterTzl::TLevelWriterTzl(const TFilePath &path, TPropertyGroup *info)
if (m_version >= 12) buildFreeChunksTable();
m_headerWritten = true;
m_exists = true;
if (m_version == 14)
if (m_version >= 14)
m_frameCountPos = 8 + CREATOR_LENGTH + 3 * sizeof(TINT32);
else
m_frameCountPos = 8 + 3 * sizeof(TINT32);
@ -555,9 +582,9 @@ TLevelWriterTzl::TLevelWriterTzl(const TFilePath &path, TPropertyGroup *info)
//-------------------------------------------------------------------
TLevelWriterTzl::~TLevelWriterTzl() {
if (m_version < CURRENT_VERSION) {
if (m_version < currentVersion()) {
if (!convertToLatestVersion()) return;
assert(m_version == CURRENT_VERSION);
assert(m_version == currentVersion());
}
delete m_codec;
@ -575,11 +602,16 @@ TLevelWriterTzl::~TLevelWriterTzl() {
for (; it != m_frameOffsTable.end(); ++it) {
TFrameId fid = it->first;
TINT32 num = fid.getNumber();
char letter = fid.getLetter();
QByteArray suffix = fid.getLetter().toUtf8();
TINT32 offs = it->second.m_offs;
TINT32 length = it->second.m_length;
tfwrite(&num, 1, m_chan);
tfwrite(&letter, 1, m_chan);
if (m_version >= 15) { // write the suffix length before data
TINT32 suffixLength = suffix.size();
tfwrite(&suffixLength, 1, m_chan);
tfwrite(suffix.constData(), suffixLength, m_chan);
} else // write only the first byte
tfwrite(suffix.constData(), 1, m_chan);
tfwrite(&offs, 1, m_chan);
tfwrite(&length, 1, m_chan);
}
@ -593,11 +625,16 @@ TLevelWriterTzl::~TLevelWriterTzl() {
for (; iconIt != m_iconOffsTable.end(); ++iconIt) {
TFrameId fid = iconIt->first;
TINT32 num = fid.getNumber();
char letter = fid.getLetter();
QByteArray suffix = fid.getLetter().toUtf8();
TINT32 thumbnailOffs = iconIt->second.m_offs;
TINT32 thumbnailLength = iconIt->second.m_length;
tfwrite(&num, 1, m_chan);
tfwrite(&letter, 1, m_chan);
if (m_version >= 15) { // write the suffix length before data
TINT32 suffixLength = suffix.size();
tfwrite(&suffixLength, 1, m_chan);
tfwrite(suffix.constData(), suffixLength, m_chan);
} else // write only the first byte
tfwrite(suffix.constData(), 1, m_chan);
tfwrite(&thumbnailOffs, 1, m_chan);
tfwrite(&thumbnailLength, 1, m_chan);
}
@ -774,7 +811,7 @@ bool TLevelWriterTzl::convertToLatestVersion() {
if (!m_chan) return false;
if (!writeVersionAndCreator(m_chan, m_magic, m_creator)) return false;
m_creatorWritten = true;
m_version = CURRENT_VERSION;
m_version = currentVersion();
TLevelReaderP lr(tempPath);
if (!lr) return false;
TLevelP level = lr->loadInfo();
@ -800,11 +837,16 @@ bool TLevelWriterTzl::convertToLatestVersion() {
for (; it2 != m_frameOffsTable.end(); ++it2) {
TFrameId fid = it2->first;
TINT32 num = fid.getNumber();
char letter = fid.getLetter();
QByteArray suffix = fid.getLetter().toUtf8();
TINT32 offs = it2->second.m_offs;
TINT32 length = it2->second.m_length;
tfwrite(&num, 1, m_chan);
tfwrite(&letter, 1, m_chan);
if (m_version >= 15) { // write the suffix length before data
TINT32 suffixLength = suffix.size();
tfwrite(&suffixLength, 1, m_chan);
tfwrite(suffix.constData(), suffixLength, m_chan);
} else // write only the first byte
tfwrite(suffix.constData(), 1, m_chan);
tfwrite(&offs, 1, m_chan);
tfwrite(&length, 1, m_chan);
}
@ -816,11 +858,16 @@ bool TLevelWriterTzl::convertToLatestVersion() {
for (; iconIt != m_iconOffsTable.end(); ++iconIt) {
TFrameId fid = iconIt->first;
TINT32 num = fid.getNumber();
char letter = fid.getLetter();
QByteArray suffix = fid.getLetter().toUtf8();
TINT32 thumbnailOffs = iconIt->second.m_offs;
TINT32 thumbnailLength = iconIt->second.m_length;
tfwrite(&num, 1, m_chan);
tfwrite(&letter, 1, m_chan);
if (m_version >= 15) { // write the suffix length before data
TINT32 suffixLength = suffix.size();
tfwrite(&suffixLength, 1, m_chan);
tfwrite(suffix.constData(), suffixLength, m_chan);
} else // write only the first byte
tfwrite(suffix.constData(), 1, m_chan);
tfwrite(&thumbnailOffs, 1, m_chan);
tfwrite(&thumbnailLength, 1, m_chan);
}
@ -856,7 +903,7 @@ bool TLevelWriterTzl::convertToLatestVersion() {
m_headerWritten = true;
m_exists = true;
m_frameCountPos = 8 + CREATOR_LENGTH + 3 * sizeof(TINT32);
assert(m_version == CURRENT_VERSION);
assert(m_version == currentVersion());
if (!m_renumberTable.empty()) renumberFids(m_renumberTable);
return true;
}
@ -867,9 +914,9 @@ void TLevelWriterTzl::saveImage(const TImageP &img, const TFrameId &_fid,
if (!m_chan) return;
// se il file è di una versione precedente allora lo converto prima
if (m_version < CURRENT_VERSION) {
if (m_version < currentVersion()) {
if (!convertToLatestVersion()) return;
assert(m_version == CURRENT_VERSION);
assert(m_version == currentVersion());
}
if (!m_updatedIconsSize && m_exists)
@ -1348,7 +1395,7 @@ float TLevelWriterTzl::getFreeSpace() {
if (m_version == 13)
totalSpace = m_offsetTablePos - 6 * sizeof(TINT32) - 4 * sizeof(char) -
8 * sizeof(char);
else if (m_version == 14)
else if (m_version >= 14)
totalSpace = m_offsetTablePos - 6 * sizeof(TINT32) - 4 * sizeof(char) -
8 * sizeof(char) - CREATOR_LENGTH * sizeof(char);
assert(totalSpace > 0);
@ -2285,6 +2332,10 @@ TImageP TImageReaderTzl::load() {
if (!m_lrp->m_frameOffsTable.empty() && !m_lrp->m_iconOffsTable.empty())
image = load14();
break;
case 15: // same as v14
if (!m_lrp->m_frameOffsTable.empty() && !m_lrp->m_iconOffsTable.empty())
image = load14();
break;
default:
image = load10();
}

View file

@ -16,7 +16,7 @@
#define DVVAR DV_IMPORT_VAR
#endif
class QString;
#include <QString>
//-----------------------------------------------------------------------------
/*
@ -28,7 +28,7 @@ class QString;
//! figures and, in case, by a character (necessary for added frames)
class DVAPI TFrameId {
int m_frame;
char m_letter; // serve per i frame "aggiunti" del tipo pippo.0001a.tzp =>
QString m_letter; // serve per i frame "aggiunti" del tipo pippo.0001a.tzp =>
// f=1 c='a'
int m_zeroPadding;
char m_startSeqInd;
@ -50,13 +50,13 @@ public:
}; // pippo_1.tif
TFrameId(int f = EMPTY_FRAME)
: m_frame(f), m_letter(0), m_zeroPadding(4), m_startSeqInd('.') {}
TFrameId(int f, char c)
: m_frame(f), m_letter(c), m_zeroPadding(4), m_startSeqInd('.') {}
TFrameId(int f, char c, int p)
: m_frame(f), m_letter(c), m_zeroPadding(p), m_startSeqInd('.') {}
TFrameId(int f, char c, int p, char s)
: m_frame(f), m_letter(c), m_zeroPadding(p), m_startSeqInd(s) {}
: m_frame(f), m_letter(""), m_zeroPadding(4), m_startSeqInd('.') {}
TFrameId(int f, char c, int p = 4, char s = '.')
: m_frame(f), m_zeroPadding(p), m_startSeqInd(s) {
m_letter = (c == '\0') ? "" : QString(c);
}
TFrameId(int f, QString str, int p = 4, char s = '.')
: m_frame(f), m_letter(str), m_zeroPadding(p), m_startSeqInd(s) {}
inline bool operator==(const TFrameId &f) const {
return f.m_frame == m_frame && f.m_letter == m_letter;
@ -66,7 +66,8 @@ public:
}
inline bool operator<(const TFrameId &f) const {
return (m_frame < f.m_frame ||
(m_frame == f.m_frame && m_letter < f.m_letter));
(m_frame == f.m_frame &&
QString::localeAwareCompare(m_letter, f.m_letter) < 0));
}
inline bool operator>(const TFrameId &f) const { return f < *this; }
inline bool operator>=(const TFrameId &f) const { return !operator<(f); }
@ -89,7 +90,7 @@ public:
// operator string() const;
std::string expand(FrameFormat format = FOUR_ZEROS) const;
int getNumber() const { return m_frame; }
char getLetter() const { return m_letter; }
QString getLetter() const { return m_letter; }
void setZeroPadding(int p) { m_zeroPadding = p; }
int getZeroPadding() const { return m_zeroPadding; }
@ -132,7 +133,23 @@ inline std::ostream &operator<<(std::ostream &out, const TFrameId &f) {
constructor.*/
class DVAPI TFilePath {
static bool m_underscoreFormatAllowed;
// specifies file path condition for sequential image for each project.
// See filepathproperties.h
static bool m_useStandard;
static bool m_acceptNonAlphabetSuffix;
static int m_letterCountForSuffix;
std::wstring m_path;
struct TFilePathInfo {
QString parentDir; // with slash
QString levelName;
QChar sepChar; // either "." or "_"
TFrameId fId;
QString extension;
};
void setPath(std::wstring path);
public:
@ -142,6 +159,23 @@ public:
m_underscoreFormatAllowed = state;
}
// called from TProjectManager::getCurrentProject() and
// ProjectPopup::updateProjectFromFields
// returns true if something changed
static bool setFilePathProperties(bool useStandard, bool acceptNonAlphaSuffix,
int letterCountForSuffix) {
if (m_useStandard == useStandard &&
m_acceptNonAlphabetSuffix == acceptNonAlphaSuffix &&
m_letterCountForSuffix == letterCountForSuffix)
return false;
m_useStandard = useStandard;
m_acceptNonAlphabetSuffix = acceptNonAlphaSuffix;
m_letterCountForSuffix = letterCountForSuffix;
return true;
}
static bool useStandard() { return m_useStandard; }
static QString fidRegExpStr();
/*!This constructor creates a string removing redundances ('//', './',etc.)
and final slashes,
correcting (redressing) the "twisted" slashes.
@ -191,6 +225,7 @@ If the path is "<alpha>:" a slash will be added*/
std::string getType() const {
return getUndottedType();
} // ritorna l'estensione SENZA PUNTO
/*!Returns the base filename (no extension, no dots, no slash)*/
std::string getName() const; // noDot! noSlash!
std::wstring getWideName() const; // noDot! noSlash!
@ -274,6 +309,8 @@ type is a string that indicate the filename extension(ex:. bmp or .bmp)*/
// '/a/b/c.txt' => head='a' tail='b/c.txt'
void split(std::wstring &head, TFilePath &tail) const;
TFilePathInfo analyzePath() const;
};
//-----------------------------------------------------------------------------

View file

@ -9,6 +9,7 @@
class ToonzScene;
class TSceneProperties;
class FilePathProperties;
#undef DVAPI
#undef DVVAR
@ -28,6 +29,8 @@ class DVAPI TProject final : public TSmartObject {
bool m_useSubScenePath;
TSceneProperties *m_sprop;
FilePathProperties *m_fpProp;
public:
// default folders names
static const std::string Inputs;
@ -70,6 +73,8 @@ public:
void setSceneProperties(const TSceneProperties &sprop);
const TSceneProperties &getSceneProperties() const { return *m_sprop; }
FilePathProperties *getFilePathProperties() const { return m_fpProp; }
//?????????????????????????????????????????????
void setUseScenePath(std::string folderName, bool on);
//?????????????????????????????????????????????

View file

@ -442,8 +442,9 @@ frame duplication.
// cutomized exposseLevel used from LoadLevel command
int exposeLevel(int row, int col, TXshLevel *xl, std::vector<TFrameId> &fIds_,
int xFrom = -1, int xTo = -1, int step = -1, int inc = -1,
int frameCount = -1, bool doesFileActuallyExist = true);
TFrameId xFrom = TFrameId(), TFrameId xTo = TFrameId(),
int step = -1, int inc = -1, int frameCount = -1,
bool doesFileActuallyExist = true);
/*! Exposes level \b \e xl \b \e fids in xsheet starting from cell identified
* by \b \e row and \b \e col.

View file

@ -161,24 +161,23 @@ QString fidsToString(const std::vector<TFrameId> &fids,
bool beginBlock = true;
for (int f = 0; f < fids.size() - 1; f++) {
int num = fids[f].getNumber();
char letter = fids[f].getLetter();
QString letter = fids[f].getLetter();
int next_num = fids[f + 1].getNumber();
char next_letter = fids[f + 1].getLetter();
QString next_letter = fids[f + 1].getLetter();
if (num + 1 == next_num && letter == '\0' && next_letter == '\0') {
if (num + 1 == next_num && letter.isEmpty() && next_letter.isEmpty()) {
if (beginBlock) {
retStr += QString::number(num) + " - ";
beginBlock = false;
}
} else {
retStr += QString::number(num);
if (letter != '\0') retStr += QString(letter);
if (!letter.isEmpty()) retStr += letter;
retStr += ", ";
beginBlock = true;
}
}
if (fids.back().getLetter() != '\0')
retStr += QString(fids.back().getLetter());
if (!fids.back().getLetter().isEmpty()) retStr += fids.back().getLetter();
}
return retStr;
}

View file

@ -670,10 +670,12 @@ FrameNumberLineEdit::FrameNumberLineEdit(QWidget* parent, TFrameId fId,
bool acceptLetter)
: LineEdit(parent) {
setFixedWidth(60);
if (acceptLetter)
m_regexpValidator =
new QRegExpValidator(QRegExp("^\\d{1,4}[A-Za-z]?$"), this);
else
if (acceptLetter) {
QString regExpStr = QString("^%1$").arg(TFilePath::fidRegExpStr());
m_regexpValidator = new QRegExpValidator(QRegExp(regExpStr), this);
TProjectManager* pm = TProjectManager::instance();
pm->addListener(this);
} else
m_regexpValidator = new QRegExpValidator(QRegExp("^\\d{1,4}$"), this);
m_regexpValidator_alt =
@ -698,7 +700,7 @@ void FrameNumberLineEdit::updateValidator() {
void FrameNumberLineEdit::setValue(TFrameId fId) {
QString str;
if (Preferences::instance()->isShowFrameNumberWithLettersEnabled()) {
if (fId.getLetter() != '\0') {
if (!fId.getLetter().isEmpty()) {
// need some warning?
}
str = convertToFrameWithLetter(fId.getNumber(), 3);
@ -724,18 +726,31 @@ TFrameId FrameNumberLineEdit::getValue() {
}
return TFrameId(f);
} else {
QRegExp rx("^(\\d{1,4})([A-Za-z]?)$");
QString regExpStr = QString("^%1$").arg(TFilePath::fidRegExpStr());
QRegExp rx(regExpStr);
int pos = rx.indexIn(text());
if (pos < 0) return TFrameId();
if (rx.cap(2).isEmpty())
return TFrameId(rx.cap(1).toInt());
else
return TFrameId(rx.cap(1).toInt(), rx.cap(2).at(0).toLatin1());
return TFrameId(rx.cap(1).toInt(), rx.cap(2));
}
}
//-----------------------------------------------------------------------------
void FrameNumberLineEdit::onProjectSwitched() {
QRegExpValidator* oldValidator = m_regexpValidator;
QString regExpStr = QString("^%1$").arg(TFilePath::fidRegExpStr());
m_regexpValidator = new QRegExpValidator(QRegExp(regExpStr), this);
updateValidator();
if (oldValidator) delete oldValidator;
}
void FrameNumberLineEdit::onProjectChanged() { onProjectSwitched(); }
//-----------------------------------------------------------------------------
void FrameNumberLineEdit::focusInEvent(QFocusEvent *e) {
m_textOnFocusIn = text();
}

View file

@ -9,6 +9,7 @@
#include "toonzqt/lineedit.h"
#include "tfilepath.h"
#include "toonz/tproject.h"
// TnzQt includes
#include "toonzqt/tabbar.h"
@ -71,7 +72,8 @@ class IntLineEdit;
// "Show ABC Appendix to the Frame Number in Xsheet Cell" is active.
//-----------------------------------------------------------------------------
class FrameNumberLineEdit : public DVGui::LineEdit {
class FrameNumberLineEdit : public DVGui::LineEdit,
public TProjectManager::Listener {
Q_OBJECT
/* having two validators and switch them according to the preferences*/
QRegExpValidator *m_regexpValidator, *m_regexpValidator_alt;
@ -89,6 +91,10 @@ public:
/*! Return an integer with text field value. */
TFrameId getValue();
// TProjectManager::Listener
void onProjectSwitched() override;
void onProjectChanged() override;
protected:
/*! If focus is lost and current text value is out of range emit signal
\b editingFinished.*/

View file

@ -102,8 +102,8 @@ TFrameId getNewFrameId(TXshSimpleLevel *sl, int row) {
TFrameId fid(row + 1);
if (sl->isFid(fid)) {
fid = TFrameId(fid.getNumber(), 'a');
while (fid.getLetter() < 'z' && sl->isFid(fid))
fid = TFrameId(fid.getNumber(), fid.getLetter() + 1);
while (fid.getLetter().toUtf8().at(0) < 'z' && sl->isFid(fid))
fid = TFrameId(fid.getNumber(), fid.getLetter().toUtf8().at(0) + 1);
}
return fid;
}
@ -123,9 +123,15 @@ TFrameId getDesiredFId(TXshCellColumn *column, int r0, TXshSimpleLevel *sl,
if (neighborFId.isEmptyFrame()) neighborFId = tmpFId;
if (maxFId < tmpFId) maxFId = tmpFId;
}
if (maxFId.getLetter() && maxFId.getLetter() < 'z' && maxFId == neighborFId)
return TFrameId(maxFId.getNumber(), maxFId.getLetter() + 1);
else
QByteArray suffix = maxFId.getLetter().toUtf8();
// increment letter
if (suffix.size() == 1 &&
((suffix.at(0) >= 'A' && suffix.at(0) < 'Z') ||
(suffix.at(0) >= 'a' && suffix.at(0) < 'z')) &&
maxFId == neighborFId) {
return TFrameId(maxFId.getNumber(), suffix.at(0) + 1);
} else
return TFrameId(maxFId.getNumber() + 1);
}

View file

@ -1827,6 +1827,15 @@ bool ToolUtils::doUpdateXSheet(TXshSimpleLevel *sl,
bool ToolUtils::renumberForInsertFId(TXshSimpleLevel *sl, const TFrameId &fid,
const TFrameId &maxFid, TXsheet *xsh) {
auto getNextLetter = [](const QString &letter) {
if (letter.isEmpty()) return QString('a');
if (letter == 'z' || letter == 'Z') return QString();
QByteArray byteArray = letter.toUtf8();
// return incrementing the last letter
byteArray.data()[byteArray.size() - 1]++;
return QString::fromUtf8(byteArray);
};
std::vector<TFrameId> fids;
std::vector<TFrameId> oldFrames;
sl->getFids(oldFrames);
@ -1840,10 +1849,10 @@ bool ToolUtils::renumberForInsertFId(TXshSimpleLevel *sl, const TFrameId &fid,
for (auto itr = fidsSet.upper_bound(maxFid); itr != fidsSet.end(); ++itr) {
if (*itr > tmpFid) break;
fIdsToBeShifted.push_back(*itr);
if (fid.getLetter()) {
if ((*itr).getLetter() < 'z')
tmpFid = TFrameId((*itr).getNumber(),
((*itr).getLetter()) ? (*itr).getLetter() + 1 : 'a');
if (!fid.getLetter().isEmpty()) {
QString nextLetter = getNextLetter((*itr).getLetter());
if (!nextLetter.isEmpty())
tmpFid = TFrameId((*itr).getNumber(), nextLetter);
else
tmpFid = TFrameId((*itr).getNumber() + 1);
} else
@ -1854,11 +1863,10 @@ bool ToolUtils::renumberForInsertFId(TXshSimpleLevel *sl, const TFrameId &fid,
for (TFrameId &tmpFid : fids) {
if (fIdsToBeShifted.contains(tmpFid)) {
if (fid.getLetter()) {
if (tmpFid.getLetter() < 'z')
tmpFid =
TFrameId(tmpFid.getNumber(),
(tmpFid.getLetter()) ? tmpFid.getLetter() + 1 : 'a');
if (!fid.getLetter().isEmpty()) {
QString nextLetter = getNextLetter(tmpFid.getLetter());
if (!nextLetter.isEmpty())
tmpFid = TFrameId(tmpFid.getNumber(), nextLetter);
else
tmpFid = TFrameId(tmpFid.getNumber() + 1);
} else

View file

@ -3013,6 +3013,13 @@ static void dRenumberCells(int col, int r0, int r1) {
levelsTable[sl].push_back(std::make_pair(oldFid, newFid));
}
}
auto getNextLetter = [](const QString &letter) {
if (letter.isEmpty()) return QString('a');
QByteArray byteArray = letter.toUtf8();
// return incrementing the last letter
byteArray.data()[byteArray.size() - 1]++;
return QString::fromUtf8(byteArray);
};
// Ensure renumber consistency in case some destination fid would overwrite
// some unrenumbered fid in the level
@ -3022,8 +3029,7 @@ static void dRenumberCells(int col, int r0, int r1) {
if (cellsMap.find(it->second) == cellsMap.end() &&
it->first.getSimpleLevel()->isFid(it->second.getFrameId())) {
TFrameId &fid = it->second.m_frameId;
fid = TFrameId(fid.getNumber(),
fid.getLetter() ? fid.getLetter() + 1 : 'a',
fid = TFrameId(fid.getNumber(), getNextLetter(fid.getLetter()),
fid.getZeroPadding(), fid.getStartSeqInd());
}
}
@ -3218,8 +3224,8 @@ static void createNewDrawing(TXsheet *xsh, int row, int col,
TFrameId fid(row + 1);
if (sl->isFid(fid)) {
fid = TFrameId(fid.getNumber(), 'a');
while (fid.getLetter() < 'z' && sl->isFid(fid))
fid = TFrameId(fid.getNumber(), fid.getLetter() + 1);
while (fid.getLetter().toUtf8().at(0) < 'z' && sl->isFid(fid))
fid = TFrameId(fid.getNumber(), fid.getLetter().toUtf8().at(0) + 1);
}
// add the new frame
sl->setFrame(fid, sl->createEmptyFrame());

View file

@ -874,7 +874,8 @@ void XSheetPDFTemplate::drawCellNumber(QPainter& painter, QRect rect,
str = getFrameNumberWithLetters(cell.m_frameId.getNumber());
} else {
str = QString::number(cell.m_frameId.getNumber());
if (cell.m_frameId.getLetter() != '\0') str += cell.m_frameId.getLetter();
if (!cell.m_frameId.getLetter().isEmpty())
str += cell.m_frameId.getLetter();
}
painter.drawText(rect, Qt::AlignCenter, str);
}

View file

@ -15,6 +15,12 @@
#include "convertpopup.h"
#include "matchline.h"
#include "colormodelbehaviorpopup.h"
//#if defined(x64)
//#include "penciltestpopup.h" // FrameNumberLineEdit
//#else
//#include "penciltestpopup_qt.h"
//#endif
#include "../stopmotion/stopmotioncontroller.h" // FrameNumberLineEdit
// TnzQt includes
#include "toonzqt/gutil.h"
@ -707,8 +713,8 @@ LoadLevelPopup::LoadLevelPopup()
QPushButton *showSubsequenceButton = createShowButton(this);
QLabel *subsequenceLabel = new QLabel(tr("Load Subsequence Level"), this);
m_subsequenceFrame = new QFrame(this);
m_fromFrame = new DVGui::IntLineEdit(this, 1, 1);
m_toFrame = new DVGui::IntLineEdit(this, 1, 1);
m_fromFrame = new FrameNumberLineEdit(this, TFrameId(1));
m_toFrame = new FrameNumberLineEdit(this, TFrameId(1));
//----Arrangement in Xsheet
m_arrLvlPropWidget = new QWidget(this);
@ -716,8 +722,8 @@ LoadLevelPopup::LoadLevelPopup()
QLabel *arrangementLabel =
new QLabel(tr("Level Settings & Arrangement in Scene"), this);
m_arrangementFrame = new QFrame(this);
m_xFrom = new DVGui::IntLineEdit(this, 1, 1);
m_xTo = new DVGui::IntLineEdit(this, 1, 1);
m_xFrom = new FrameNumberLineEdit(this, TFrameId(1));
m_xTo = new FrameNumberLineEdit(this, TFrameId(1));
m_stepCombo = new QComboBox(this);
m_incCombo = new QComboBox(this);
m_posFrom = new DVGui::IntLineEdit(this, 1, 1);
@ -968,12 +974,12 @@ void LoadLevelPopup::onNameSetEditted() {
} else {
m_notExistLabel->show();
m_fromFrame->setText("1");
m_toFrame->setText("1");
m_fromFrame->setValue(TFrameId(1));
m_toFrame->setValue(TFrameId(1));
m_subsequenceFrame->setEnabled(true);
m_xFrom->setText("1");
m_xTo->setText("1");
m_xFrom->setValue(TFrameId(1));
m_xTo->setValue(TFrameId(1));
m_levelName->setText(QString::fromStdString(path.getName()));
@ -998,26 +1004,39 @@ void LoadLevelPopup::updatePosTo() {
return;
}
int xFrom = m_xFrom->text().toInt();
int xTo = m_xTo->text().toInt();
TFrameId xFrom = m_xFrom->getValue();
TFrameId xTo = m_xTo->getValue();
int frameLength;
bool isScene = (QString::fromStdString(fp.getType()) == "tnz");
if (isScene) { // scene does not consider frame suffixes
xFrom = TFrameId(xFrom.getNumber());
xTo = TFrameId(xTo.getNumber());
}
auto frameLengthBetweenFIds = [&]() {
if (xFrom > xTo) return 0;
int ret = xTo.getNumber() - xFrom.getNumber() + 1;
if (!xTo.getLetter().isEmpty()) ret++;
return ret;
};
//--- if loading the "missing" level
if (m_notExistLabel->isVisible()) {
int inc = m_incCombo->currentIndex();
if (inc == 0) // Inc = Auto
{
frameLength = (xTo - xFrom + 1) * ((m_stepCombo->currentIndex() == 0)
frameLength =
frameLengthBetweenFIds() * ((m_stepCombo->currentIndex() == 0)
? 1
: m_stepCombo->currentIndex());
} else // Inc =! Auto
{
int loopAmount;
loopAmount = tceil((double)(xTo - xFrom + 1) / (double)inc);
loopAmount = tceil((double)(frameLengthBetweenFIds()) / (double)inc);
frameLength = loopAmount * ((m_stepCombo->currentIndex() == 0)
? inc
: m_stepCombo->currentIndex());
@ -1028,7 +1047,7 @@ void LoadLevelPopup::updatePosTo() {
else if (m_incCombo->currentIndex() == 0) // Inc = Auto
{
if (isScene) {
frameLength = xTo - xFrom + 1;
frameLength = frameLengthBetweenFIds();
} else {
std::vector<TFrameId> fIds = getCurrentFIds();
//--- If loading the level with sequential files, reuse the list of
@ -1036,32 +1055,23 @@ void LoadLevelPopup::updatePosTo() {
if (fIds.size() != 0) {
if (m_stepCombo->currentIndex() == 0) // Step = Auto
{
frameLength = 0;
std::vector<TFrameId>::iterator it;
int firstFrame = 0;
int lastFrame = 0;
for (it = fIds.begin(); it != fIds.end(); it++) {
if (xFrom <= it->getNumber()) {
firstFrame = it->getNumber();
if (xFrom <= *it && *it <= xTo)
frameLength++;
else if (xTo < *it)
break;
}
}
for (it = fIds.begin(); it != fIds.end(); it++) {
if (it->getNumber() <= xTo) {
lastFrame = it->getNumber();
}
}
frameLength = lastFrame - firstFrame + 1;
} else // Step != Auto
{
std::vector<TFrameId>::iterator it;
int loopAmount = 0;
for (it = fIds.begin(); it != fIds.end(); it++) {
if (xFrom <= it->getNumber() && it->getNumber() <= xTo)
loopAmount++;
if (xFrom <= *it && *it <= xTo) loopAmount++;
}
frameLength = loopAmount * m_stepCombo->currentIndex();
}
}
// loading another type of level such as tlv
else {
@ -1074,29 +1084,20 @@ void LoadLevelPopup::updatePosTo() {
if (m_stepCombo->currentIndex() == 0) // Step = Auto
{
frameLength = 0;
TLevel::Iterator it;
int firstFrame = 0;
int lastFrame = 0;
for (it = level->begin(); it != level->end(); it++) {
if (xFrom <= it->first.getNumber()) {
firstFrame = it->first.getNumber();
if (xFrom <= it->first && it->first <= xTo)
frameLength++;
else if (xTo < it->first)
break;
}
}
for (it = level->begin(); it != level->end(); it++) {
if (it->first.getNumber() <= xTo) {
lastFrame = it->first.getNumber();
}
}
frameLength = lastFrame - firstFrame + 1;
} else // Step != Auto
{
TLevel::Iterator it;
int loopAmount = 0;
for (it = level->begin(); it != level->end(); it++) {
if (xFrom <= it->first.getNumber() &&
it->first.getNumber() <= xTo)
loopAmount++;
if (xFrom <= it->first && it->first <= xTo) loopAmount++;
}
frameLength = loopAmount * m_stepCombo->currentIndex();
}
@ -1110,7 +1111,7 @@ void LoadLevelPopup::updatePosTo() {
else {
int inc = m_incCombo->currentIndex();
int loopAmount;
loopAmount = tceil((double)(xTo - xFrom + 1) / (double)inc);
loopAmount = tceil((double)(frameLengthBetweenFIds()) / (double)inc);
frameLength = loopAmount * ((m_stepCombo->currentIndex() == 0)
? inc
: m_stepCombo->currentIndex());
@ -1123,8 +1124,8 @@ void LoadLevelPopup::updatePosTo() {
/*! if the from / to values in the subsequent box, update m_xFrom and m_xTo
*/
void LoadLevelPopup::onSubsequentFrameChanged() {
m_xFrom->setText(m_fromFrame->text());
m_xTo->setText(m_toFrame->text());
m_xFrom->setValue(m_fromFrame->getValue());
m_xTo->setValue(m_toFrame->getValue());
updatePosTo();
}
@ -1192,9 +1193,9 @@ bool LoadLevelPopup::execute() {
//---- SubSequent load
// if loading the "missing" level
if (m_notExistLabel->isVisible()) {
int firstFrameNumber = m_fromFrame->text().toInt();
int lastFrameNumber = m_toFrame->text().toInt();
setLoadingLevelRange(firstFrameNumber, lastFrameNumber);
TFrameId firstLoadingFId = m_fromFrame->getValue();
TFrameId lastLoadingFId = m_toFrame->getValue();
setLoadingLevelRange(firstLoadingFId, lastLoadingFId);
} else if (m_subsequenceFrame->isEnabled() &&
m_subsequenceFrame->isVisible()) {
std::vector<TFrameId> fIds = getCurrentFIds();
@ -1220,11 +1221,10 @@ bool LoadLevelPopup::execute() {
return false;
}
}
int firstFrameNumber = m_fromFrame->text().toInt();
int lastFrameNumber = m_toFrame->text().toInt();
if (firstFrame.getNumber() != firstFrameNumber ||
lastFrame.getNumber() != lastFrameNumber)
setLoadingLevelRange(firstFrameNumber, lastFrameNumber);
TFrameId firstLoadingFId = m_fromFrame->getValue();
TFrameId lastLoadingFId = m_toFrame->getValue();
if (firstFrame != firstLoadingFId || lastFrame != lastLoadingFId)
setLoadingLevelRange(firstLoadingFId, lastLoadingFId);
}
IoCmd::LoadResourceArguments args(fp);
@ -1237,20 +1237,27 @@ bool LoadLevelPopup::execute() {
args.frameIdsSet.push_back(*getCurrentFIdsSet().begin());
else if (m_notExistLabel->isVisible()) {
int firstFrameNumber = m_fromFrame->text().toInt();
int lastFrameNumber = m_toFrame->text().toInt();
TFrameId firstLoadingFId = m_fromFrame->getValue();
TFrameId lastLoadingFId = m_toFrame->getValue();
// putting the Fids in order to avoid LoadInfo later
std::vector<TFrameId> tmp_fids;
for (int i = firstFrameNumber; i <= lastFrameNumber; i++) {
int i = firstLoadingFId.getNumber();
if (!firstLoadingFId.getLetter().isEmpty()) {
tmp_fids.push_back(firstLoadingFId);
i++;
}
for (; i <= lastLoadingFId.getNumber(); i++) {
tmp_fids.push_back(TFrameId(i));
}
if (!lastLoadingFId.getLetter().isEmpty())
tmp_fids.push_back(lastLoadingFId);
args.frameIdsSet.push_back(tmp_fids);
}
int xFrom = m_xFrom->text().toInt();
if (xFrom) args.xFrom = xFrom;
int xTo = m_xTo->text().toInt();
if (xTo) args.xTo = xTo;
TFrameId xFrom = m_xFrom->getValue();
if (!xFrom.isEmptyFrame()) args.xFrom = xFrom;
TFrameId xTo = m_xTo->getValue();
if (!xTo.isEmptyFrame()) args.xTo = xTo;
args.levelName = m_levelName->text().toStdWString();
args.step = m_stepCombo->currentIndex();
@ -1372,9 +1379,8 @@ void LoadLevelPopup::updateBottomGUI() {
disableAll();
return;
} else if (ext == "tpl") {
QString str;
m_fromFrame->setText(str.number(1));
m_toFrame->setText(str.number(1));
m_fromFrame->setText("1");
m_toFrame->setText("1");
m_subsequenceFrame->setEnabled(false);
m_xFrom->setText("1");
@ -1420,13 +1426,12 @@ void LoadLevelPopup::updateBottomGUI() {
return;
}
}
m_fromFrame->setText(QString().number(firstFrame.getNumber()));
m_toFrame->setText(QString().number(lastFrame.getNumber()));
m_fromFrame->setValue(firstFrame);
m_toFrame->setValue(lastFrame);
m_subsequenceFrame->setEnabled(true);
m_xFrom->setText(m_fromFrame->text());
m_xTo->setText(m_toFrame->text());
m_xFrom->setValue(firstFrame);
m_xTo->setValue(lastFrame);
// if some option in the preferences is selected, load the level with
// removing

View file

@ -32,6 +32,7 @@ class QPushButton;
class QComboBox;
class QGroupBox;
class QCheckBox;
class FrameNumberLineEdit;
namespace DVGui {
class ColorField;
@ -266,11 +267,11 @@ class LoadLevelPopup final : public FileBrowserPopup {
Q_OBJECT
QFrame *m_subsequenceFrame;
DVGui::IntLineEdit *m_fromFrame, *m_toFrame;
FrameNumberLineEdit *m_fromFrame, *m_toFrame;
QWidget *m_arrLvlPropWidget;
QFrame *m_arrangementFrame;
DVGui::IntLineEdit *m_xFrom, *m_xTo;
FrameNumberLineEdit *m_xFrom, *m_xTo;
QComboBox *m_stepCombo, *m_incCombo;
DVGui::IntLineEdit *m_posFrom, *m_posTo;

View file

@ -711,9 +711,9 @@ void FilmstripFrames::paintEvent(QPaintEvent *evt) {
}
// for sequential frame
else {
char letter = fid.getLetter();
QString letter = fid.getLetter();
text = QString::number(fid.getNumber()).rightJustified(4, '0') +
(letter != '\0' ? QString(letter) : "");
(!letter.isEmpty() ? letter : "");
}
p.drawText(tmp_frameRect.adjusted(0, 0, -3, 2), text,
QTextOption(Qt::AlignRight | Qt::AlignBottom));

View file

@ -1341,6 +1341,17 @@ public:
int getHistoryType() override { return HistoryType::FilmStrip; }
};
QString getNextLetter(const QString &letter) {
// 空なら a を返す
if (letter.isEmpty()) return QString('a');
// 1文字かつ z または Z ならEmptyを返す
if (letter == 'z' || letter == 'Z') return QString();
QByteArray byteArray = letter.toUtf8();
// それ以外の場合、最後の文字をとにかく1進めて返す
byteArray.data()[byteArray.size() - 1]++;
return QString::fromUtf8(byteArray);
};
} // namespace
//=============================================================================
@ -1487,10 +1498,10 @@ void FilmstripCmd::renumber(
// make sure that srcFid has not been used. add a letter if this is needed
if (tmp.count(tarFid) > 0) {
do {
char letter = tarFid.getLetter();
tarFid = TFrameId(tarFid.getNumber(), letter == 0 ? 'a' : letter + 1);
} while (tarFid.getLetter() <= 'z' && tmp.count(tarFid) > 0);
if (tarFid.getLetter() > 'z') {
tarFid =
TFrameId(tarFid.getNumber(), getNextLetter(tarFid.getLetter()));
} while (!tarFid.getLetter().isEmpty() && tmp.count(tarFid) > 0);
if (tarFid.getLetter().isEmpty()) {
// todo: error message
return;
}
@ -2763,13 +2774,9 @@ void FilmstripCmd::renumberDrawing(TXshSimpleLevel *sl, const TFrameId &oldFid,
if (it == fids.end()) return;
TFrameId newFid = desiredNewFid;
while (std::find(fids.begin(), fids.end(), newFid) != fids.end()) {
char letter = newFid.getLetter();
if (letter == 'z') return;
if (letter == 0)
letter = 'a';
else
letter++;
newFid = TFrameId(newFid.getNumber(), letter);
QString nextLetter = getNextLetter(newFid.getLetter());
if (nextLetter.isEmpty()) return;
newFid = TFrameId(newFid.getNumber(), nextLetter);
}
*it = newFid;
if (Preferences::instance()->isSyncLevelRenumberWithXsheetEnabled()) {

View file

@ -891,9 +891,9 @@ TXshLevel *loadLevel(ToonzScene *scene,
const IoCmd::LoadResourceArguments::ResourceData &rd,
const TFilePath &castFolder, int row0, int &col0, int row1,
int &col1, bool expose, std::vector<TFrameId> &fIds,
int xFrom = -1, int xTo = -1, std::wstring levelName = L"",
int step = -1, int inc = -1, int frameCount = -1,
bool doesFileActuallyExist = true) {
TFrameId xFrom = TFrameId(), TFrameId xTo = TFrameId(),
std::wstring levelName = L"", int step = -1, int inc = -1,
int frameCount = -1, bool doesFileActuallyExist = true) {
TFilePath actualPath = scene->decodeFilePath(rd.m_path);
LoadLevelUndo *undo = 0;
@ -1022,12 +1022,15 @@ TXshLevel *loadLevel(ToonzScene *scene,
// loadResource(scene, path, castFolder, row, col, expose)
//---------------------------------------------------------------------------
TXshLevel *loadResource(
ToonzScene *scene, const IoCmd::LoadResourceArguments::ResourceData &rd,
const TFilePath &castFolder, int row0, int &col0, int row1, int &col1,
bool expose, std::vector<TFrameId> fIds = std::vector<TFrameId>(),
int xFrom = -1, int xTo = -1, std::wstring levelName = L"", int step = -1,
int inc = -1, int frameCount = -1, bool doesFileActuallyExist = true) {
TXshLevel *loadResource(ToonzScene *scene,
const IoCmd::LoadResourceArguments::ResourceData &rd,
const TFilePath &castFolder, int row0, int &col0,
int row1, int &col1, bool expose,
std::vector<TFrameId> fIds = std::vector<TFrameId>(),
TFrameId xFrom = TFrameId(), TFrameId xTo = TFrameId(),
std::wstring levelName = L"", int step = -1,
int inc = -1, int frameCount = -1,
bool doesFileActuallyExist = true) {
IoCmd::LoadResourceArguments::ResourceData actualRd(rd);
actualRd.m_path = scene->decodeFilePath(rd.m_path);

View file

@ -127,7 +127,7 @@ public:
std::vector<TXshLevel *> loadedLevels; //!< [\p Out] Levels loaded by
//! resource loading procedures.
int xFrom, xTo;
TFrameId xFrom, xTo;
std::wstring levelName;
int step, inc, frameCount;
bool doesFileActuallyExist;

View file

@ -19,10 +19,15 @@
#include "toonzqt/checkbox.h"
#include "toonzqt/gutil.h"
// TnzLib
#include "toonz/filepathproperties.h"
// TnzCore includes
#include "tsystem.h"
#include "tenv.h"
#include "tapp.h"
#include "tfilepath.h"
#include "toonz/tscenehandle.h"
#include "toonz/toonzscene.h"
#include "toonz/preferences.h"
@ -35,9 +40,19 @@
#include <QComboBox>
#include <QStandardPaths>
#include <QGroupBox>
#include <QTabWidget>
#include <QStackedWidget>
#include <QButtonGroup>
#include <QRadioButton>
using namespace DVGui;
namespace {
enum { Rule_Standard = 0, Rule_Custom };
}
//===================================================================
TFilePath getDocumentsPath() {
@ -85,6 +100,33 @@ ProjectPopup::ProjectPopup(bool isModal)
new CheckBox("*Separate assets into scene sub-folders");
m_useSubSceneCbs->setMaximumHeight(WidgetHeight);
m_rulePreferenceBG = new QButtonGroup(this);
QRadioButton *standardRB = new QRadioButton(tr("Standard"), this);
QRadioButton *customRB =
new QRadioButton(QString("[Experimental] ") + tr("Custom"), this);
m_acceptNonAlphabetSuffixCB =
new CheckBox(tr("Accept Non-alphabet Suffix"), this);
m_letterCountCombo = new QComboBox(this);
//-----
m_rulePreferenceBG->addButton(standardRB, Rule_Standard);
m_rulePreferenceBG->addButton(customRB, Rule_Custom);
m_rulePreferenceBG->setExclusive(true);
standardRB->setToolTip(tr(
"In the standard mode files with the following file name are handled as sequencial images:\n\
[LEVEL_NAME][\".\"or\"_\"][FRAME_NUMBER][SUFFIX].[EXTENSION]\n\
For [SUFFIX] zero or one occurrences of alphabet (a-z, A-Z) can be used in the standard mode."));
customRB->setToolTip(
tr("In the custom mode you can customize the file path rules.\n\
Note that this mode uses regular expression for file name validation and may slow the operation."));
m_letterCountCombo->addItem(tr("1"), 1);
m_letterCountCombo->addItem(tr("2"), 2);
m_letterCountCombo->addItem(tr("3"), 3);
m_letterCountCombo->addItem(tr("5"), 5);
m_letterCountCombo->addItem(tr("Unlimited"), 0);
m_settingsLabel = new QLabel(tr("Settings"), this);
m_settingsBox = createSettingsBox();
@ -127,7 +169,12 @@ ProjectPopup::ProjectPopup(bool isModal)
SLOT(setVisible(bool)));
pm->addListener(this);
//---------
connect(m_rulePreferenceBG, SIGNAL(buttonClicked(int)), this,
SLOT(onRulePreferenceToggled(int)));
}
//-----------------------------------------------------------------------------
QFrame *ProjectPopup::createSettingsBox() {
@ -136,10 +183,20 @@ QFrame *ProjectPopup::createSettingsBox() {
TProjectManager *pm = TProjectManager::instance();
QGridLayout *lay = new QGridLayout();
lay->setMargin(5);
lay->setHorizontalSpacing(5);
lay->setVerticalSpacing(10);
QTabWidget *tabWidget = new QTabWidget(this);
QVBoxLayout *settingsLayout = new QVBoxLayout();
settingsLayout->setMargin(5);
settingsLayout->setSpacing(10);
{
settingsLayout->addWidget(tabWidget, 1);
// project folder settings
QWidget *projectFolderPanel = new QWidget(this);
QGridLayout *folderLayout = new QGridLayout();
folderLayout->setMargin(5);
folderLayout->setHorizontalSpacing(5);
folderLayout->setVerticalSpacing(10);
{
std::vector<std::string> folderNames;
pm->getFolderNames(folderNames);
@ -153,32 +210,45 @@ QFrame *ProjectPopup::createSettingsBox() {
if (qName == "drawings" || qName == "extras" || qName == "inputs")
assetFolder = true;
QLabel *label = new QLabel("+" + qName + (assetFolder ? "*" : ""), this);
lay->addWidget(label, i + 4, 0, Qt::AlignRight | Qt::AlignVCenter);
lay->addWidget(ff, i + 4, 1);
folderLayout->addWidget(label, i + 4, 0, Qt::AlignRight | Qt::AlignVCenter);
folderLayout->addWidget(ff, i + 4, 1);
}
/*
std::vector<std::tuple<QString, std::string>> cbs = {
std::make_tuple(tr("Append $scenepath to +drawings"),
TProject::Drawings),
std::make_tuple(tr("Append $scenepath to +inputs"), TProject::Inputs),
std::make_tuple(tr("Append $scenepath to +extras"), TProject::Extras) };
int currentRow = lay->rowCount();
int currentRow = folderLayout->rowCount();
folderLayout->addWidget(m_useSubSceneCbs, currentRow, 1);
}
projectFolderPanel->setLayout(folderLayout);
tabWidget->addTab(projectFolderPanel, tr("Project Folder"));
for (int i = 0; i < cbs.size(); ++i) {
auto const &name = std::get<0>(cbs[i]);
auto const &folderName = std::get<1>(cbs[i]);
CheckBox *cb = new CheckBox(name);
cb->setMaximumHeight(WidgetHeight);
lay->addWidget(cb, currentRow + i, 1);
m_useScenePathCbs.append(qMakePair(folderName, cb));
cb->hide();
// file path settings
QWidget *filePathPanel = new QWidget(this);
QVBoxLayout *fpLayout = new QVBoxLayout();
fpLayout->setMargin(5);
fpLayout->setSpacing(10);
{
fpLayout->addWidget(m_rulePreferenceBG->buttons()[0], 0); // standardRB
fpLayout->addWidget(m_rulePreferenceBG->buttons()[1], 0); // customRB
// add some indent
QGridLayout *customLay = new QGridLayout();
customLay->setMargin(10);
customLay->setHorizontalSpacing(10);
customLay->setVerticalSpacing(10);
{
customLay->addWidget(m_acceptNonAlphabetSuffixCB, 0, 0, 1, 2);
customLay->addWidget(
new QLabel(tr("Maximum Letter Count For Suffix"), this), 1, 0);
customLay->addWidget(m_letterCountCombo, 1, 1);
}
*/
int currentRow = lay->rowCount();
lay->addWidget(m_useSubSceneCbs, currentRow, 1);
customLay->setColumnStretch(2, 1);
fpLayout->addLayout(customLay, 0);
fpLayout->addStretch(1);
}
filePathPanel->setLayout(fpLayout);
tabWidget->addTab(filePathPanel, tr("File Path Rules"));
}
projectSettingsBox->setLayout(lay);
projectSettingsBox->setLayout(settingsLayout);
return projectSettingsBox;
}
@ -208,6 +278,18 @@ void ProjectPopup::updateFieldsFromProject(TProject *project) {
m_useSubSceneCbs->blockSignals(true);
m_useSubSceneCbs->setChecked(project->getUseSubScenePath());
m_useSubSceneCbs->blockSignals(false);
// file path
FilePathProperties *fpProp = project->getFilePathProperties();
bool useStandard = fpProp->useStandard();
bool acceptNonAlphabet = fpProp->acceptNonAlphabetSuffix();
int letterCount = fpProp->letterCountForSuffix();
m_rulePreferenceBG->button((useStandard) ? Rule_Standard : Rule_Custom)
->setChecked(true);
onRulePreferenceToggled((useStandard) ? Rule_Standard : Rule_Custom);
m_acceptNonAlphabetSuffixCB->setChecked(acceptNonAlphabet);
m_letterCountCombo->setCurrentIndex(
m_letterCountCombo->findData(letterCount));
}
//-----------------------------------------------------------------------------
@ -229,6 +311,20 @@ void ProjectPopup::updateProjectFromFields(TProject *project) {
*/
bool useScenePath = m_useSubSceneCbs->isChecked();
project->setUseSubScenePath(useScenePath);
// file path
FilePathProperties *fpProp = project->getFilePathProperties();
bool useStandard = m_rulePreferenceBG->checkedId() == Rule_Standard;
bool acceptNonAlphabet = m_acceptNonAlphabetSuffixCB->isChecked();
int letterCount = m_letterCountCombo->currentData().toInt();
fpProp->setUseStandard(useStandard);
fpProp->setAcceptNonAlphabetSuffix(acceptNonAlphabet);
fpProp->setLetterCountForSuffix(letterCount);
if (TFilePath::setFilePathProperties(useStandard, acceptNonAlphabet,
letterCount))
DvDirModel::instance()->refreshFolderChild(QModelIndex()); // refresh all
TProjectManager::instance()->notifyProjectChanged();
}
@ -246,6 +342,13 @@ void ProjectPopup::showEvent(QShowEvent *) {
updateFieldsFromProject(currentProject.getPointer());
}
//-----------------------------------------------------------------------------
void ProjectPopup::onRulePreferenceToggled(int id) {
m_acceptNonAlphabetSuffixCB->setEnabled((id == Rule_Custom));
m_letterCountCombo->setEnabled((id == Rule_Custom));
}
//=============================================================================
/*! \class ProjectSettingsPopup
\brief The ProjectSettingsPopup class provides a dialog to
@ -269,7 +372,7 @@ ProjectSettingsPopup::ProjectSettingsPopup() : ProjectPopup(false) {
int i;
for (i = 0; i < m_folderFlds.size(); i++) {
FileField *ff = m_folderFlds[i].second;
connect(ff, SIGNAL(pathChanged()), this, SLOT(onFolderChanged()));
connect(ff, SIGNAL(pathChanged()), this, SLOT(onSomethingChanged()));
}
/*
for (i = 0; i < m_useScenePathCbs.size(); i++) {
@ -278,8 +381,16 @@ ProjectSettingsPopup::ProjectSettingsPopup() : ProjectPopup(false) {
SLOT(onUseSceneChekboxChanged(int)));
}
*/
connect(m_useSubSceneCbs, SIGNAL(stateChanged(int)), this,
SLOT(onUseSceneChekboxChanged(int)));
connect(m_useSubSceneCbs, SIGNAL(stateChanged(int)), this, SLOT(onSomethingChanged()));
// file path settings
connect(m_rulePreferenceBG, SIGNAL(buttonClicked(int)), this,
SLOT(onSomethingChanged()));
connect(m_acceptNonAlphabetSuffixCB, SIGNAL(clicked(bool)), this,
SLOT(onSomethingChanged()));
connect(m_letterCountCombo, SIGNAL(activated(int)), this,
SLOT(onSomethingChanged()));
}
//-----------------------------------------------------------------------------
@ -374,21 +485,7 @@ void ProjectSettingsPopup::onProjectChanged() {
//-----------------------------------------------------------------------------
void ProjectSettingsPopup::onFolderChanged() {
TProjectP project = TProjectManager::instance()->getCurrentProject();
updateProjectFromFields(project.getPointer());
try {
project->save();
} catch (TSystemException se) {
DVGui::warning(QString::fromStdWString(se.getMessage()));
return;
}
DvDirModel::instance()->refreshFolder(project->getProjectFolder());
}
//-----------------------------------------------------------------------------
void ProjectSettingsPopup::onUseSceneChekboxChanged(int) {
void ProjectSettingsPopup::onSomethingChanged() {
TProjectP project = TProjectManager::instance()->getCurrentProject();
updateProjectFromFields(project.getPointer());
try {
@ -556,6 +653,12 @@ void ProjectCreatePopup::showEvent(QShowEvent *) {
setSizePolicy(sizePolicy);
setFixedSize(width(), height());
setSizeGripEnabled(false);
// default file path settings
m_rulePreferenceBG->button(Rule_Standard)->setChecked(true);
onRulePreferenceToggled(Rule_Standard);
m_acceptNonAlphabetSuffixCB->setChecked(false);
m_letterCountCombo->setCurrentIndex(m_letterCountCombo->findData(1));
}
void ProjectCreatePopup::setPath(QString path) {

View file

@ -16,11 +16,12 @@ namespace DVGui {
class FileField;
class LineEdit;
class CheckBox;
}
} // namespace DVGui
class QComboBox;
class QGridLayout;
class QGroupBox;
class QButtonGroup;
//=============================================================================
// ProjectPopup
@ -46,6 +47,11 @@ protected:
QFrame *m_settingsBox;
QPushButton *m_showSettingsButton;
// file path settings
QButtonGroup *m_rulePreferenceBG;
DVGui::CheckBox *m_acceptNonAlphabetSuffixCB;
QComboBox *m_letterCountCombo;
public:
ProjectPopup(bool isModal);
// da TProjectManager::Listener
@ -60,6 +66,9 @@ public:
protected:
void showEvent(QShowEvent *) override;
protected slots:
void onRulePreferenceToggled(int);
};
//=============================================================================
@ -75,8 +84,7 @@ public:
ProjectSettingsPopup();
public slots:
void onFolderChanged();
void onUseSceneChekboxChanged(int);
void onSomethingChanged();
void projectChanged();
void onProjectChanged() override;

View file

@ -250,12 +250,13 @@ void TvpJsonLayer::build(int index, ToonzScene* scene, TXshCellColumn* column) {
if (Preferences::instance()->isShowFrameNumberWithLettersEnabled())
instance_name = getFrameNumberWithLetters(fid.getNumber());
else {
std::string frameNumber("");
QString frameNumber("");
// set number
if (fid.getNumber() >= 0) frameNumber = std::to_string(fid.getNumber());
if (fid.getNumber() >= 0)
frameNumber = QString::number(fid.getNumber());
// add letter
if (fid.getLetter() != 0) frameNumber.append(1, fid.getLetter());
instance_name = QString::fromStdString(frameNumber);
if (!fid.getLetter().isEmpty()) frameNumber += fid.getLetter();
instance_name = frameNumber;
}
fid.setZeroPadding(frameFormats[cell.m_level.getPointer()].first);

View file

@ -60,21 +60,23 @@ void XdtsHeader::write(QJsonObject &json) const {
//-----------------------------------------------------------------------------
TFrameId XdtsFrameDataItem::str2Fid(const QString &str) const {
if (str.isEmpty()) return TFrameId::EMPTY_FRAME;
bool ok;
int frame = str.toInt(&ok);
if (ok) return TFrameId(frame);
// separate the last word as suffix
frame = str.left(str.size() - 1).toInt(&ok);
if (!ok) return TFrameId(-1); // EMPTY
if (!str[str.size() - 1].isLetter()) return TFrameId(-1); // EMPTY
char c = str[str.size() - 1].toLatin1();
return TFrameId(frame, c);
QString regExpStr = QString("^%1$").arg(TFilePath::fidRegExpStr());
QRegExp rx(regExpStr);
int pos = rx.indexIn(str);
if (pos < 0) return TFrameId();
if (rx.cap(2).isEmpty())
return TFrameId(rx.cap(1).toInt());
else
return TFrameId(rx.cap(1).toInt(), rx.cap(2));
}
QString XdtsFrameDataItem::fid2Str(const TFrameId &fid) const {
if (fid.getLetter() == 0) return QString::number(fid.getNumber());
return QString::number(fid.getNumber()) + QString(fid.getLetter());
if (fid.getLetter().isEmpty()) return QString::number(fid.getNumber());
return QString::number(fid.getNumber()) + fid.getLetter();
}
void XdtsFrameDataItem::read(const QJsonObject &json) {

View file

@ -301,7 +301,8 @@ void parse(const QString &text, std::wstring &levelName, TFrameId &fid) {
QRegExp spaces("\\t|\\s");
QRegExp numbers("\\d+");
QRegExp characters("[^\\d+]");
QRegExp fidWithSuffix("([0-9]+)([a-z]?)");
QRegExp fidWithSuffix(TFilePath::fidRegExpStr());
// QRegExp fidWithSuffix("([0-9]+)([a-z]?)");
QString str = text;
// remove final spaces
@ -320,9 +321,8 @@ void parse(const QString &text, std::wstring &levelName, TFrameId &fid) {
fid = TFrameId(str.toInt());
} else if (fidWithSuffix.exactMatch(str)) {
levelName = L"";
fid = TFrameId(
fidWithSuffix.cap(1).toInt(),
fidWithSuffix.cap(2) == "" ? 0 : fidWithSuffix.cap(2).toLatin1()[0]);
fid = TFrameId(fidWithSuffix.cap(1).toInt(), fidWithSuffix.cap(2));
// fidWithSuffix.cap(2) == "" ? 0 : fidWithSuffix.cap(2).toLatin1()[0]);
} else if (str.contains(characters)) {
levelName = text.toStdWString();
fid = TFrameId::NO_FRAME;
@ -336,9 +336,8 @@ void parse(const QString &text, std::wstring &levelName, TFrameId &fid) {
} else if (fidWithSuffix.exactMatch(lastString)) {
QString firstString = str.left(lastSpaceIndex);
levelName = firstString.toStdWString();
fid = TFrameId(
fidWithSuffix.cap(1).toInt(),
fidWithSuffix.cap(2) == "" ? 0 : fidWithSuffix.cap(2).toLatin1()[0]);
fid = TFrameId(fidWithSuffix.cap(1).toInt(), fidWithSuffix.cap(2));
// fidWithSuffix.cap(2) == "" ? 0 : fidWithSuffix.cap(2).toLatin1()[0]);
} else if (lastString.contains(characters)) {
levelName = text.toStdWString();
fid = TFrameId::NO_FRAME;
@ -654,9 +653,9 @@ void RenameCellField::showInRowCol(int row, int col, bool multiColumnSelected) {
: QString::fromStdWString(levelName) + QString(" ") +
m_viewer->getFrameNumberWithLetters(fid.getNumber()));
else {
std::string frameNumber("");
if (fid.getNumber() > 0) frameNumber = std::to_string(fid.getNumber());
if (fid.getLetter() != 0) frameNumber.append(1, fid.getLetter());
QString frameNumber("");
if (fid.getNumber() > 0) frameNumber = QString::number(fid.getNumber());
if (!fid.getLetter().isEmpty()) frameNumber += fid.getLetter();
// get text from sound text level
if (cell.m_level->getType() == TXshLevelType::SND_TXT_XSHLEVEL) {
@ -669,12 +668,12 @@ void RenameCellField::showInRowCol(int row, int col, bool multiColumnSelected) {
}
// other level types
else {
setText((frameNumber.empty())
setText((frameNumber.isEmpty())
? QString::fromStdWString(levelName)
: (multiColumnSelected)
? QString::fromStdString(frameNumber)
? frameNumber
: QString::fromStdWString(levelName) + QString(" ") +
QString::fromStdString(frameNumber));
frameNumber);
}
}
selectAll();
@ -762,8 +761,8 @@ void RenameCellField::renameSoundTextColumn(TXshSoundTextColumn *sndTextCol,
//-----------------------------------------------------------------------------
void RenameCellField::renameCell() {
QString s = text();
std::wstring newName = s.toStdWString();
QString newName = text();
// std::wstring newName = s.toStdWString();
setText("");
@ -777,16 +776,16 @@ void RenameCellField::renameCell() {
xsheet->getColumn(m_col)->getSoundTextColumn()) {
TXshSoundTextColumn *sndTextCol =
xsheet->getColumn(m_col)->getSoundTextColumn();
renameSoundTextColumn(sndTextCol, s);
renameSoundTextColumn(sndTextCol, newName);
return;
}
// convert the last one digit of the frame number to alphabet
// Ex. 12 -> 1B 21 -> 2A 30 -> 3
if (Preferences::instance()->isShowFrameNumberWithLettersEnabled())
parse_with_letter(QString::fromStdWString(newName), levelName, fid);
parse_with_letter(newName, levelName, fid);
else {
parse(QString::fromStdWString(newName), levelName, fid);
parse(newName, levelName, fid);
}
bool animationSheetEnabled =
Preferences::instance()->isAnimationSheetEnabled();
@ -2012,12 +2011,12 @@ void CellArea::drawLevelCell(QPainter &p, int row, int col, bool isReference,
if (Preferences::instance()->isShowFrameNumberWithLettersEnabled())
fnum = m_viewer->getFrameNumberWithLetters(fid.getNumber());
else {
std::string frameNumber("");
QString frameNumber("");
// set number
if (fid.getNumber() >= 0) frameNumber = std::to_string(fid.getNumber());
if (fid.getNumber() >= 0) frameNumber = QString::number(fid.getNumber());
// add letter
if (fid.getLetter() != 0) frameNumber.append(1, fid.getLetter());
fnum = QString::fromStdString(frameNumber);
if (!fid.getLetter().isEmpty()) frameNumber += fid.getLetter();
fnum = frameNumber;
}
int alignFlag =
@ -2351,9 +2350,9 @@ void CellArea::drawPaletteCell(QPainter &p, int row, int col,
TFrameId fid = cell.m_frameId;
std::wstring levelName = cell.m_level->getName();
std::string frameNumber("");
if (fid.getNumber() > 0) frameNumber = std::to_string(fid.getNumber());
if (fid.getLetter() != 0) frameNumber.append(1, fid.getLetter());
// QString frameNumber("");
// if (fid.getNumber() > 0) frameNumber = QString::number(fid.getNumber());
// if (fid.getLetter() != 0) frameNumber += fid.getLetter();
QRect nameRect =
o->rect(PredefinedRect::CELL_NAME).translated(QPoint(x, y));
@ -2395,13 +2394,12 @@ void CellArea::drawPaletteCell(QPainter &p, int row, int col,
numberStr = m_viewer->getFrameNumberWithLetters(fid.getNumber());
p.drawText(nameRect, Qt::AlignRight | Qt::AlignBottom, numberStr);
} else {
std::string frameNumber("");
QString frameNumber("");
// set number
if (fid.getNumber() > 0) frameNumber = std::to_string(fid.getNumber());
if (fid.getNumber() > 0) frameNumber = QString::number(fid.getNumber());
// add letter
if (fid.getLetter() != 0) frameNumber.append(1, fid.getLetter());
numberStr = QString::fromStdString(frameNumber);
p.drawText(nameRect, Qt::AlignRight | Qt::AlignBottom, numberStr);
if (!fid.getLetter().isEmpty()) frameNumber += fid.getLetter();
p.drawText(nameRect, Qt::AlignRight | Qt::AlignBottom, frameNumber);
}
}
@ -3085,14 +3083,13 @@ void CellArea::mouseMoveEvent(QMouseEvent *event) {
: QString::fromStdWString(levelName) + QString(" ") +
m_viewer->getFrameNumberWithLetters(fid.getNumber());
} else {
std::string frameNumber("");
if (fid.getNumber() >= 0) frameNumber = std::to_string(fid.getNumber());
if (fid.getLetter() != 0) frameNumber.append(1, fid.getLetter());
QString frameNumber("");
if (fid.getNumber() >= 0) frameNumber = QString::number(fid.getNumber());
if (!fid.getLetter().isEmpty()) frameNumber += fid.getLetter();
m_tooltip =
QString((frameNumber.empty())
? QString::fromStdWString(levelName)
: QString::fromStdWString(levelName) + QString(" ") +
QString::fromStdString(frameNumber));
QString((frameNumber.isEmpty()) ? QString::fromStdWString(levelName)
: QString::fromStdWString(levelName) +
QString(" ") + frameNumber);
}
} else if (isSoundColumn &&
o->rect(PredefinedRect::PREVIEW_TRACK)

View file

@ -551,7 +551,7 @@ public:
int i;
for (i = 1; i < count; i++)
if (m_sourceCells[i].m_level != cell.m_level ||
m_sourceCells[i].m_frameId.getLetter() != 0)
!m_sourceCells[i].m_frameId.getLetter().isEmpty())
return;
// check if all the selected cells have the same frame number

View file

@ -162,6 +162,7 @@ set(HEADERS
../include/toonz/preferencesitemids.h
../include/toonz/txsheetcolumnchange.h
../include/toonz/expressionreferencemonitor.h
../include/toonz/filepathproperties.h
)
set(SOURCES
@ -320,6 +321,7 @@ set(SOURCES
txshmeshcolumn.cpp
textureutils.cpp
boardsettings.cpp
filepathproperties.cpp
)
if(BUILD_TARGET_WIN)

View file

@ -206,7 +206,7 @@ QScriptValue Scene::getCell(int row, int col) {
if (sl) {
QScriptValue level = create(engine(), new Level(sl));
QScriptValue fid;
if (cell.m_frameId.getLetter() == 0)
if (cell.m_frameId.getLetter().isEmpty())
fid = cell.m_frameId.getNumber();
else
fid = QString::fromStdString(cell.m_frameId.expand());

View file

@ -10,6 +10,7 @@
#include "toonz/toonzfolders.h"
#include "toonz/cleanupparameters.h"
#include "toonz/preferences.h"
#include "toonz/filepathproperties.h"
// TnzBase includes
#include "tenv.h"
@ -17,6 +18,7 @@
// TnzCore includes
#include "tsystem.h"
#include "tstream.h"
#include "tfilepath.h"
#include "tfilepath_io.h"
#include "tconvert.h"
@ -321,11 +323,18 @@ TFilePath getDesktopPath() {
\see TProjectManager and TOStream.
*/
TProject::TProject() : m_name(), m_path(), m_sprop(new TSceneProperties()) {}
TProject::TProject()
: m_name()
, m_path()
, m_sprop(new TSceneProperties())
, m_fpProp(new FilePathProperties()) {}
//-------------------------------------------------------------------
TProject::~TProject() { delete m_sprop; }
TProject::~TProject() {
delete m_sprop;
delete m_fpProp;
}
//-------------------------------------------------------------------
/*! Associates the \b name to the specified \b path.
@ -615,6 +624,13 @@ bool TProject::save(const TFilePath &projectPath) {
os.openChild("sceneProperties");
getSceneProperties().saveData(os);
os.closeChild();
if (!getFilePathProperties()->isDefault()) {
os.openChild("filePathProperties");
getFilePathProperties()->saveData(os);
os.closeChild();
}
os.closeChild();
// crea (se necessario) le directory relative ai vari folder
@ -725,6 +741,9 @@ void TProject::load(const TFilePath &projectPath) {
}
setSceneProperties(sprop);
is.matchEndTag();
} else if (tagName == "filePathProperties") {
m_fpProp->loadData(is);
is.matchEndTag();
}
}
@ -1038,6 +1057,12 @@ TProjectP TProjectManager::getCurrentProject() {
assert(TProject::isAProjectPath(fp));
currentProject = new TProject();
currentProject->load(fp);
// update TFilePath condition on loading the current project
FilePathProperties *fpProp = currentProject->getFilePathProperties();
TFilePath::setFilePathProperties(fpProp->useStandard(),
fpProp->acceptNonAlphabetSuffix(),
fpProp->letterCountForSuffix());
}
return currentProject;
}

View file

@ -1061,8 +1061,8 @@ int TXsheet::exposeLevel(int row, int col, TXshLevel *xl, bool overwrite) {
//-----------------------------------------------------------------------------
// customized version for load level popup
int TXsheet::exposeLevel(int row, int col, TXshLevel *xl,
std::vector<TFrameId> &fIds_, int xFrom, int xTo,
int step, int inc, int frameCount,
std::vector<TFrameId> &fIds_, TFrameId xFrom,
TFrameId xTo, int step, int inc, int frameCount,
bool doesFileActuallyExist) {
if (!xl) return 0;
std::vector<TFrameId> fids;
@ -1104,7 +1104,7 @@ int TXsheet::exposeLevel(int row, int col, TXshLevel *xl,
{
std::vector<TFrameId>::iterator it;
it = fids.begin();
while (it->getNumber() < xFrom) it++;
while (*it < xFrom) it++;
if (step == 0) // Step = Auto
{
@ -1112,14 +1112,12 @@ int TXsheet::exposeLevel(int row, int col, TXshLevel *xl,
next_it = it;
next_it++;
int startFrame = it->getNumber();
for (int f = startFrame; f < startFrame + frameCount; f++) {
if (next_it != fids.end() && f >= next_it->getNumber()) {
for (int f = 0; f < frameCount; f++) {
setCell(row++, col, TXshCell(xl, *it));
if (next_it != fids.end()) {
it++;
next_it++;
}
setCell(row++, col, TXshCell(xl, *it));
}
}
@ -1143,7 +1141,7 @@ int TXsheet::exposeLevel(int row, int col, TXshLevel *xl,
loopCount = frameCount / step;
for (int loop = 0; loop < loopCount; loop++) {
TFrameId id(xFrom + loop * inc, fids.begin()->getLetter());
TFrameId id(xFrom.getNumber() + loop * inc, xFrom.getLetter());
for (int s = 0; s < step; s++) {
setCell(row++, col, TXshCell(xl, id));
}

View file

@ -17,24 +17,17 @@ TFrameId qstringToFrameId(QString str) {
return TFrameId::EMPTY_FRAME;
else if (str == "-" || str == "-2")
return TFrameId::NO_FRAME;
TFrameId fid;
int s = 0;
QString number;
char letter(0);
for (s = 0; s < str.size(); s++) {
QChar c = str.at(s);
if (c.isNumber()) number.append(c);
#if QT_VERSION >= 0x050500
QString regExpStr = QString("^%1$").arg(TFilePath::fidRegExpStr());
QRegExp rx(regExpStr);
int pos = rx.indexIn(str);
if (pos < 0) return TFrameId();
if (rx.cap(2).isEmpty())
return TFrameId(rx.cap(1).toInt());
else
letter = c.toLatin1();
#else
else
letter = c.toAscii();
#endif
}
return TFrameId(number.toInt(), letter);
}
return TFrameId(rx.cap(1).toInt(), rx.cap(2));
}
} // namespace
//-----------------------------------------------------------------------------
@ -123,13 +116,13 @@ void TXshLevelColumn::loadData(TIStream &is) {
while (is.openChild(tagName)) {
if (tagName == "cell") {
TPersist *p = 0;
QString str;
std::string str;
int row = 1, rowCount = 1, increment = 0;
TFilePath path;
is >> row >> rowCount >> p >> str >> increment;
TFrameId fid = qstringToFrameId(str);
assert((fid.getLetter() == 0 && rowCount >= 0) ||
(fid.getLetter() != 0 && rowCount == 1));
TFrameId fid = qstringToFrameId(QString::fromStdString(str));
assert((fid.getLetter().isEmpty() && rowCount >= 0) ||
(!fid.getLetter().isEmpty() && rowCount == 1));
TXshLevel *xshLevel = dynamic_cast<TXshLevel *>(p);
if (xshLevel) {
int fidNumber = fid.getNumber();
@ -182,11 +175,11 @@ void TXshLevelColumn::saveData(TOStream &os) {
int n = 1, inc = 0, dr = fid.getNumber();
// If fid has not letter save more than one cell and its incrementation;
// otherwise save one cell.
if (r < r1 && fid.getLetter() == 0) {
if (r < r1 && fid.getLetter().isEmpty()) {
TXshCell cell2 = getCell(r + 1);
TFrameId fid2 = cell2.m_frameId;
if (cell2.m_level.getPointer() == cell.m_level.getPointer() &&
fid2.getLetter() == 0) {
fid2.getLetter().isEmpty()) {
inc = cell2.m_frameId.getNumber() - dr;
n++;
for (;;) {
@ -194,7 +187,7 @@ void TXshLevelColumn::saveData(TOStream &os) {
cell2 = getCell(r + n);
TFrameId fid2 = cell2.m_frameId;
if (cell2.m_level.getPointer() != cell.m_level.getPointer() ||
fid2.getLetter() != 0)
!fid2.getLetter().isEmpty())
break;
if (fid2.getNumber() != dr + n * inc) break;
n++;

View file

@ -24,28 +24,16 @@ TFrameId qstringToFrameId(QString str) {
else if (str == "-" || str == "-2")
return TFrameId::NO_FRAME;
TFrameId fid;
QString number;
char letter(0);
int s, strSize = str.size();
for (s = 0; s < strSize; ++s) {
QChar c = str.at(s);
if (c.isNumber())
number.append(c);
QString regExpStr = QString("^%1$").arg(TFilePath::fidRegExpStr());
QRegExp rx(regExpStr);
int pos = rx.indexIn(str);
if (pos < 0) return TFrameId();
if (rx.cap(2).isEmpty())
return TFrameId(rx.cap(1).toInt());
else
#if QT_VERSION >= 0x050500
letter = c.toLatin1();
#else
letter = c.toAscii();
#endif
}
return TFrameId(number.toInt(), letter);
}
return TFrameId(rx.cap(1).toInt(), rx.cap(2));
}
} // namespace
//*******************************************************************************
// TXshMeshColumn implementation
@ -94,12 +82,12 @@ void TXshMeshColumn::saveData(TOStream &os) {
// If fid has no letter save more than one cell and its increment -
// otherwise save just one cell
if (r < r1 && fid.getLetter() == 0) {
if (r < r1 && fid.getLetter().isEmpty()) {
TXshCell cell2 = getCell(r + 1);
TFrameId fid2 = cell2.m_frameId;
if (cell2.m_level.getPointer() == cell.m_level.getPointer() &&
fid2.getLetter() == 0) {
fid2.getLetter().isEmpty()) {
inc = cell2.m_frameId.getNumber() - dr;
for (++n;; ++n) {
if (r + n > r1) break;
@ -108,7 +96,7 @@ void TXshMeshColumn::saveData(TOStream &os) {
TFrameId fid2 = cell2.m_frameId;
if (cell2.m_level.getPointer() != cell.m_level.getPointer() ||
fid2.getLetter() != 0)
!fid2.getLetter().isEmpty())
break;
if (fid2.getNumber() != dr + n * inc) break;
@ -150,16 +138,16 @@ void TXshMeshColumn::loadData(TIStream &is) {
while (is.openChild(tagName)) {
if (tagName == "cell") {
TPersist *p = 0;
QString str;
std::string str;
int row = 1, rowCount = 1, increment = 0;
TFilePath path;
is >> row >> rowCount >> p >> str >> increment;
TFrameId fid = qstringToFrameId(str);
assert((fid.getLetter() == 0 && rowCount >= 0) ||
(fid.getLetter() != 0 && rowCount == 1));
TFrameId fid = qstringToFrameId(QString::fromStdString(str));
assert((fid.getLetter().isEmpty() && rowCount >= 0) ||
(!fid.getLetter().isEmpty() && rowCount == 1));
TXshLevel *xshLevel = dynamic_cast<TXshLevel *>(p);
if (xshLevel) {

View file

@ -485,7 +485,8 @@ int TXshSimpleLevel::guessStep() const {
TFrameId firstFid = *ft++, secondFid = *ft++;
if (firstFid.getLetter() != 0 || secondFid.getLetter() != 0) return 1;
if (!firstFid.getLetter().isEmpty() || !secondFid.getLetter().isEmpty())
return 1;
int step = secondFid.getNumber() - firstFid.getNumber();
if (step == 1) return 1;
@ -494,7 +495,7 @@ int TXshSimpleLevel::guessStep() const {
// (cerco di limitare il numero di volte in cui devo controllare tutta la
// lista)
TFrameId lastFid = *m_frames.rbegin();
if (lastFid.getLetter() != 0) return 1;
if (!lastFid.getLetter().isEmpty()) return 1;
if (lastFid.getNumber() != firstFid.getNumber() + step * (frameCount - 1))
return 1;
@ -502,7 +503,7 @@ int TXshSimpleLevel::guessStep() const {
for (int i = 2; ft != m_frames.end(); ++ft, ++i) {
const TFrameId &fid = *ft;
if (fid.getLetter() != 0) return 1;
if (!fid.getLetter().isEmpty()) return 1;
if (fid.getNumber() != firstFid.getNumber() + step * i) return 1;
}