tahoma2d/toonz/sources/toonz/filebrowserpopup.cpp
2023-10-12 01:28:00 -04:00

2365 lines
78 KiB
C++

#include "filebrowserpopup.h"
// Tnz6 includes
#include "menubarcommandids.h"
#include "iocommand.h"
#include "exportlevelcommand.h"
#include "filebrowser.h"
#include "tapp.h"
#include "filebrowsermodel.h"
#include "formatsettingspopups.h"
#include "magpiefileimportpopup.h"
#include "columnselection.h"
#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"
#include "toonzqt/icongenerator.h"
#include "toonzqt/colorfield.h"
#include "toonzqt/tselectionhandle.h"
// TnzLib includes
#include "toonz/tscenehandle.h"
#include "toonz/tpalettehandle.h"
#include "toonz/txshlevelhandle.h"
#include "toonz/txsheethandle.h"
#include "toonz/palettecontroller.h"
#include "toonz/studiopalette.h"
#include "toonz/toonzscene.h"
#include "toonz/tproject.h"
#include "toonz/txshcell.h"
#include "toonz/txshsimplelevel.h"
#include "toonz/tcamera.h"
#include "toonz/sceneproperties.h"
#include "toonz/tstageobjecttree.h"
#include "toonz/txshleveltypes.h"
// specify in the preference whether to replace the level after saveLevelAs
// command
#include "toonz/preferences.h"
#include "toonz/tcolumnhandle.h"
#include "toonz/tframehandle.h"
#include "toonz/levelset.h"
#include "toonz/palettecmd.h"
#include "toonz/stage.h"
// TnzCore includes
#include "tsystem.h"
#include "tiio.h"
#include "tlevel_io.h"
#include "tundo.h"
// Qt includes
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGridLayout>
#include <QFrame>
#include <QPushButton>
#include <QLabel>
#include <QComboBox>
#include <QGroupBox>
#include <QCoreApplication>
#include <QMainWindow>
#include <QApplication>
//***********************************************************************************
// FileBrowserPopup implementation
//***********************************************************************************
FileBrowserPopup::FileBrowserPopup(const QString &title, Options options,
QString applyButtonTxt,
QWidget *customWidget)
: QDialog(TApp::instance()->getMainWindow())
, m_isDirectoryOnly(false)
, m_multiSelectionEnabled(options & MULTISELECTION)
, m_forSaving(options & FOR_SAVING)
, m_dialogSize(800, 600)
, m_customWidget(customWidget) {
setWindowTitle(title);
setModal(false);
m_browser = new FileBrowser(this, Qt::WindowFlags(), false, m_multiSelectionEnabled);
m_nameFieldLabel = new QLabel(tr("File name:"));
m_nameField = new DVGui::LineEdit(this);
m_okButton = new QPushButton(tr("OK"), this);
m_cancelButton = new QPushButton(tr("Cancel"), this);
QPushButton *applyButton = 0;
if (options & WITH_APPLY_BUTTON)
applyButton = new QPushButton(
(applyButtonTxt.isEmpty()) ? tr("Apply") : applyButtonTxt, this);
std::list<std::vector<TFrameId>> tmp_list;
m_currentFIdsSet = tmp_list;
//-------------
m_okButton->setMaximumWidth(100);
m_okButton->setAutoDefault(false);
m_cancelButton->setMaximumWidth(100);
m_cancelButton->setAutoDefault(false);
if (applyButton) {
applyButton->setMaximumWidth(100);
applyButton->setAutoDefault(false);
}
// layout
if (!(options & CUSTOM_LAYOUT)) {
QVBoxLayout *mainLayout = new QVBoxLayout();
mainLayout->setMargin(0);
mainLayout->setSpacing(3);
{
mainLayout->addWidget(m_browser, 1);
QHBoxLayout *bottomLay = new QHBoxLayout();
bottomLay->setMargin(5);
bottomLay->setSpacing(3);
{
bottomLay->addWidget(m_nameFieldLabel, 0);
bottomLay->addWidget(m_nameField, 1);
}
mainLayout->addLayout(bottomLay);
if (m_customWidget) mainLayout->addWidget(m_customWidget);
QHBoxLayout *buttonsLay = new QHBoxLayout();
buttonsLay->setMargin(5);
buttonsLay->setSpacing(15);
{
buttonsLay->addStretch();
buttonsLay->addWidget(m_okButton);
if (applyButton) buttonsLay->addWidget(applyButton);
buttonsLay->addWidget(m_cancelButton);
}
mainLayout->addLayout(buttonsLay);
}
setLayout(mainLayout);
}
// Establish connections
bool ret = true;
ret =
ret && connect(m_okButton, SIGNAL(clicked()), this, SLOT(onOkPressed()));
ret = ret && connect(m_cancelButton, SIGNAL(clicked()), this, SLOT(close()));
ret =
ret &&
connect(
m_browser,
SIGNAL(filePathsSelected(const std::set<TFilePath> &,
const std::list<std::vector<TFrameId>> &)),
this,
SLOT(onFilePathsSelected(const std::set<TFilePath> &,
const std::list<std::vector<TFrameId>> &)));
ret = ret && connect(m_browser, SIGNAL(filePathClicked(const TFilePath &)),
this, SIGNAL(filePathClicked(const TFilePath &)));
if (applyButton) {
ret = ret &&
connect(applyButton, SIGNAL(clicked()), this, SLOT(onApplyPressed()));
}
assert(ret);
resize(m_dialogSize);
/*- Qt5 でQDialogがParentWidgetの中心位置に来ない不具合を回避する -*/
QPoint dialogCenter = mapToGlobal(rect().center());
QPoint parentWindowCenter = TApp::instance()->getMainWindow()->mapToGlobal(
TApp::instance()->getMainWindow()->rect().center());
move(parentWindowCenter - dialogCenter);
}
//-----------------------------------------------------------------------------
void FileBrowserPopup::setFilterTypes(const QStringList &typesList) {
m_browser->setFilterTypes(typesList);
}
//-----------------------------------------------------------------------------
void FileBrowserPopup::removeFilterType(const QString &type) {
m_browser->removeFilterType(type);
}
//-----------------------------------------------------------------------------
void FileBrowserPopup::addFilterType(const QString &type) {
m_browser->addFilterType(type);
}
//-----------------------------------------------------------------------------
void FileBrowserPopup::setFileMode(bool isDirectoryOnly) {
m_isDirectoryOnly = isDirectoryOnly;
if (isDirectoryOnly) {
m_nameFieldLabel->setText(tr("Folder name:"));
connect(m_browser, SIGNAL(treeFolderChanged(const TFilePath &)), this,
SLOT(onFilePathClicked(const TFilePath &)));
} else {
m_nameFieldLabel->setText(tr("File name:"));
disconnect(m_browser, SIGNAL(treeFolderChanged(const TFilePath &)), this,
SLOT(onFilePathClicked(const TFilePath &)));
}
}
//-----------------------------------------------------------------------------
void FileBrowserPopup::setFolder(const TFilePath &folderPath) {
m_browser->setFolder(folderPath, true, true, true);
}
//-----------------------------------------------------------------------------
void FileBrowserPopup::setFilename(const TFilePath &filename) {
m_nameField->setText(QString::fromStdWString(filename.getWideString()));
}
//-----------------------------------------------------------------------------
void FileBrowserPopup::onOkPressed() {
const TFilePath &folder = m_browser->getFolder();
// Rebuild paths selection in case the text field has an explicit entry
if (!m_nameField->text().isEmpty()) {
const QString &str = m_nameField->text();
if (!isValidFileName(QFileInfo(str).baseName()) && !m_isDirectoryOnly) {
DVGui::error(
QObject::tr("A filename cannot be empty or contain any of the "
"following characters:\n \\ / : * ? \" < > |"));
return;
}
if (isReservedFileName_message(QFileInfo(str).baseName())) return;
m_selectedPaths.clear();
if (!m_isDirectoryOnly)
m_selectedPaths.insert(folder +
TFilePath(m_nameField->text().toStdWString()));
else
m_selectedPaths.insert(TFilePath(m_nameField->text().toStdWString()));
}
// Analyze and correct the paths selection
std::set<TFilePath> pathSet;
std::set<TFilePath>::const_iterator pt, pEnd(m_selectedPaths.end());
for (pt = m_selectedPaths.begin(); pt != pEnd; ++pt) {
if (folder == TFilePath()) {
// history // That means, TFilePath()
// represents
if (*pt == TFilePath() ||
!pt->isAbsolute()) // the History folder? Really? That's lame...
{
DVGui::error(tr("Invalid file"));
return;
}
} else {
if (m_forSaving && m_browser->getFilterTypes().contains("tnz")) {
TProjectManager *pm = TProjectManager::instance();
TFilePath currentPrjDir =
pm->getCurrentProject()->getProjectPath().getParentDir();
if (!currentPrjDir.isAncestorOf(*pt)) {
DVGui::warning(QObject::tr(
"You cannot save a scene outside of the current project's folder."));
return;
}
}
if (!m_isDirectoryOnly)
pathSet.insert(*pt);
else {
if (TFileStatus(*pt).isDirectory())
pathSet.insert(*pt);
else
pathSet.insert(folder);
}
}
if (!m_multiSelectionEnabled) break;
}
m_browser->selectNone();
m_selectedPaths.swap(pathSet);
if (execute()) {
QCoreApplication::processEvents(); // <Solves a bug on XP... Bugzilla
// #6041>
accept(); // Tempted to remove the above - it should
} // NOT be here, maybe in the executes()...
}
//-----------------------------------------------------------------------------
/*! process without closing the browser
*/
void FileBrowserPopup::onApplyPressed() {
TFilePath folder = m_browser->getFolder();
std::set<TFilePath> pathSet;
if (!m_nameField->text().isEmpty()) // if the user has written in the text
// field that wins on the item
// sselection!
{
m_selectedPaths.clear();
if (!m_isDirectoryOnly)
m_selectedPaths.insert(folder +
TFilePath(m_nameField->text().toStdString()));
else
m_selectedPaths.insert(TFilePath(m_nameField->text().toStdWString()));
}
std::set<TFilePath>::const_iterator it = m_selectedPaths.begin();
while (it != m_selectedPaths.end()) {
if (folder == TFilePath()) {
// history
if (*it == TFilePath() || !it->isAbsolute()) {
DVGui::error(tr("Invalid file"));
return;
}
} else {
if (!m_isDirectoryOnly)
pathSet.insert(*it);
else {
// if (TFileStatus(*it).isDirectory())
// pathSet.insert(*it);
// else
pathSet.insert(folder);
}
}
if (!m_multiSelectionEnabled) break;
++it;
}
m_browser->selectNone();
m_selectedPaths.swap(pathSet);
if (executeApply()) {
QCoreApplication::processEvents();
}
}
//-----------------------------------------------------------------------------
void FileBrowserPopup::onFilePathClicked(const TFilePath &fp) {
std::set<TFilePath> app;
app.insert(fp);
std::list<std::vector<TFrameId>> tmp;
onFilePathsSelected(app, tmp);
}
//-----------------------------------------------------------------------------
void FileBrowserPopup::onFilePathsSelected(
const std::set<TFilePath> &paths,
const std::list<std::vector<TFrameId>> &fIds) {
if (paths.size() == 0 && m_forSaving) return;
m_selectedPaths = paths;
m_currentFIdsSet = fIds;
if (paths.size() == 1) {
const TFilePath &fp = *paths.begin();
QString text;
if (!m_isDirectoryOnly)
text = QString::fromStdWString(fp.getLevelNameW());
else {
if (TFileStatus(fp).isDirectory())
text = fp.getQString();
else
text = QString::fromStdWString(m_browser->getFolder().getWideString());
}
std::string textStr = text.toStdString();
m_nameField->setText(text);
} else
m_nameField->setText("");
}
//-----------------------------------------------------------------------------
void FileBrowserPopup::onFilePathDoubleClicked(const TFilePath &) {
// do nothing by default
}
//-----------------------------------------------------------------------------
void FileBrowserPopup::setOkText(const QString &text) {
m_okButton->setText(text);
// if the button label is "Save" then the browser is assumed as for saving
if (text == QObject::tr("Save")) m_forSaving = true;
}
//-----------------------------------------------------------------------------
void FileBrowserPopup::hideEvent(QHideEvent *e) {
TSelectionHandle::getCurrent()->popSelection();
m_dialogSize = size();
move(pos());
resize(size());
}
//-----------------------------------------------------------------------------
void FileBrowserPopup::showEvent(QShowEvent *) {
TSelectionHandle::getCurrent()->pushSelection();
m_selectedPaths.clear();
m_currentFIdsSet.clear();
TFilePath projectPath = TProjectManager::instance()->getCurrentProjectPath();
if (m_currentProjectPath != projectPath) {
m_currentProjectPath = projectPath;
initFolder();
// set initial folder of all browsers to $scenefolder when the scene folder
// mode is set in user preferences
if (Preferences::instance()->getPathAliasPriority() ==
Preferences::SceneFolderAlias) {
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
if (scene && !scene->isUntitled())
setFolder(scene->getScenePath().getParentDir());
}
m_nameField->update();
m_nameField->setFocus();
}
resize(m_dialogSize);
}
//-----------------------------------------------------------------------------
// utility function. Make the widget to be a child of modal file browser in
// order to allow control.
void FileBrowserPopup::setModalBrowserToParent(QWidget *widget) {
if (!widget) return;
for (QWidget *pwidget : QApplication::topLevelWidgets()) {
if ((pwidget->isWindow()) && (pwidget->isModal()) &&
(pwidget->isVisible())) {
FileBrowserPopup *popup = qobject_cast<FileBrowserPopup *>(pwidget);
if (popup) {
// According to the description of QDialog;
// "setParent() function will clear the window flags specifying the
// window-system properties for the widget (in particular it will reset
// the Qt::Dialog flag)."
// So keep the window flags and set back after calling setParent().
Qt::WindowFlags flags = widget->windowFlags();
widget->setParent(pwidget);
widget->setWindowFlags(flags);
return;
}
}
}
}
//***********************************************************************************
// GenericLoadFilePopup implementation
//***********************************************************************************
GenericLoadFilePopup::GenericLoadFilePopup(const QString &title)
: FileBrowserPopup(title) {}
//-----------------------------------------------------------------------------
bool GenericLoadFilePopup::execute() {
if (m_selectedPaths.empty()) return false;
const TFilePath &path = *m_selectedPaths.begin();
assert(!path.isEmpty()); // Should always be, see
// FileBrowserPopup::onOk..()
return TFileStatus(path).doesExist();
}
//-----------------------------------------------------------------------------
TFilePath GenericLoadFilePopup::getPath() {
return (exec() == QDialog::Rejected) ? TFilePath() : *m_selectedPaths.begin();
}
//***********************************************************************************
// GenericSaveFilePopup implementation
//***********************************************************************************
GenericSaveFilePopup::GenericSaveFilePopup(const QString &title,
QWidget *customWidget)
: FileBrowserPopup(title, Options(FOR_SAVING), "", customWidget) {
connect(m_nameField, SIGNAL(returnPressedNow()), m_okButton,
SLOT(animateClick()));
}
//-----------------------------------------------------------------------------
bool GenericSaveFilePopup::execute() {
if (m_selectedPaths.empty()) return false;
TFilePath path(*m_selectedPaths.begin());
assert(!path.isEmpty());
// In case the path is not coherent with the specified type filter,
// it means that the user specified it by typing and forgot the right type
// (yep, even if a DIFFERENT type was specified - next time do it right :P)
const QStringList &extList = m_browser->getFilterTypes();
if (!m_isDirectoryOnly &&
!extList.contains(QString::fromStdString(path.getType()))) {
path =
TFilePath(path.getWideString() + L"." + extList.first().toStdWString());
}
// Ask for user permission to overwrite if necessary
if (!m_isDirectoryOnly && TFileStatus(path).doesExist()) {
const QString &question =
QObject::tr("File %1 already exists.\nDo you want to overwrite it?")
.arg(toQString(path));
int ret = DVGui::MsgBox(question, QObject::tr("Overwrite"),
QObject::tr("Cancel"));
if (ret == 0 || ret == 2) return false;
}
m_selectedPaths.clear();
m_selectedPaths.insert(path);
return true;
}
//-----------------------------------------------------------------------------
TFilePath GenericSaveFilePopup::getPath() {
return (exec() == QDialog::Rejected) ? TFilePath() : *m_selectedPaths.begin();
}
//=============================================================================
// LoadScenePopup
LoadScenePopup::LoadScenePopup() : FileBrowserPopup(tr("Load Scene")) {
setOkText(tr("Load"));
addFilterType("tnz");
addFilterType("xdts");
// set the initial current path according to the current module
setInitialFolderByCurrentRoom();
connect(m_browser, SIGNAL(filePathDoubleClicked(const TFilePath &)), this,
SLOT(onFilePathDoubleClicked(const TFilePath &)));
}
bool LoadScenePopup::execute() {
if (m_selectedPaths.empty()) return false;
const TFilePath &fp = *m_selectedPaths.begin();
if (fp.getType() != "tnz" && fp.getType() != "xdts") {
DVGui::error(toQString(fp) + tr(" is not a scene file."));
return false;
}
if (!TFileStatus(fp).doesExist()) {
DVGui::error(toQString(fp) + tr(" does not exist."));
return false;
}
return IoCmd::loadScene(fp);
}
void LoadScenePopup::initFolder() { setInitialFolderByCurrentRoom(); }
void LoadScenePopup::setInitialFolderByCurrentRoom() {
QString roomName = TApp::instance()->getCurrentRoomName();
TProjectP project = TProjectManager::instance()->getCurrentProject();
TFilePath scenePath;
if (roomName == "Cleanup" || roomName == "InknPaint")
scenePath = project->getFolder(TProject::Drawings, true);
else if (roomName == "PltEdit")
scenePath = project->getFolder(TProject::Palettes, true);
else
scenePath = project->getFolder(TProject::Scenes, true);
setFolder(scenePath);
}
void LoadScenePopup::showEvent(QShowEvent *e) {
m_nameField->clear();
FileBrowserPopup::showEvent(e);
}
void LoadScenePopup::onFilePathDoubleClicked(const TFilePath &path) {
Q_UNUSED(path);
onOkPressed();
}
//=============================================================================
// LoadSubScenePopup
LoadSubScenePopup::LoadSubScenePopup()
: FileBrowserPopup(tr("Load Sub-Scene")) {
setOkText(tr("Load"));
addFilterType("tnz");
TFilePath scenePath =
TProjectManager::instance()->getCurrentProject()->getScenesPath();
setFolder(scenePath);
}
bool LoadSubScenePopup::execute() {
if (m_selectedPaths.empty()) return false;
const TFilePath &fp = *m_selectedPaths.begin();
if (fp.getType() != "tnz") {
DVGui::error(toQString(fp) + tr(" is not a scene file."));
return false;
}
if (!TFileStatus(fp).doesExist()) {
DVGui::error(toQString(fp) + tr(" does not exist."));
return false;
}
return IoCmd::loadSubScene(fp);
}
void LoadSubScenePopup::initFolder() {
setFolder(TProjectManager::instance()->getCurrentProject()->getScenesPath());
}
void LoadSubScenePopup::showEvent(QShowEvent *e) {
m_nameField->clear();
FileBrowserPopup::showEvent(e);
}
//=============================================================================
// SaveSceneAsPopup
SaveSceneAsPopup::SaveSceneAsPopup()
: FileBrowserPopup(tr("Save Scene"), Options(FOR_SAVING)) {
setOkText(tr("Save"));
addFilterType("tnz");
connect(m_nameField, SIGNAL(returnPressedNow()), m_okButton,
SLOT(animateClick()));
}
bool SaveSceneAsPopup::execute() {
if (m_selectedPaths.empty()) return false;
const TFilePath &fp = *m_selectedPaths.begin();
if (isSpaceString(QString::fromStdString(
fp.getName()))) // Lol. Cmon! Really necessary?
return false;
return IoCmd::saveScene(fp, 0);
}
void SaveSceneAsPopup::initFolder() {
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
if (!scene->isUntitled())
setFolder(scene->getScenePath().getParentDir());
else
setFolder(
TProjectManager::instance()->getCurrentProject()->getScenesPath());
}
//=============================================================================
// SaveSubSceneAsPopup
SaveSubSceneAsPopup::SaveSubSceneAsPopup()
: FileBrowserPopup(tr("Sub-Scene"), Options(FOR_SAVING)) {
setOkText(tr("Save"));
connect(m_nameField, SIGNAL(returnPressedNow()), m_okButton,
SLOT(animateClick()));
}
bool SaveSubSceneAsPopup::execute() {
if (m_selectedPaths.empty()) return false;
return IoCmd::saveScene(*m_selectedPaths.begin(), IoCmd::SAVE_SUBXSHEET);
}
void SaveSubSceneAsPopup::initFolder() {
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
if (!scene->isUntitled())
setFolder(scene->getScenePath().getParentDir());
else
setFolder(
TProjectManager::instance()->getCurrentProject()->getScenesPath());
}
//=============================================================================
// LoadLevelPopup
namespace {
QPushButton *createShowButton(QWidget *parent) {
QPushButton *button = new QPushButton(parent);
button->setObjectName("menuToggleButton");
button->setFixedSize(15, 15);
button->setIcon(createQIcon("menu_toggle"));
button->setCheckable(true);
button->setChecked(false);
button->setAutoDefault(false);
return button;
}
} // namespace
LoadLevelPopup::LoadLevelPopup()
: FileBrowserPopup(tr("Load Level"),
Options(MULTISELECTION | WITH_APPLY_BUTTON), "",
new QWidget(0)) {
setModal(false);
setOkText(tr("Load"));
QWidget *optionWidget = (QWidget *)m_customWidget;
// choose tlv caching behavior
QLabel *cacheBehaviorLabel =
new QLabel(tr("Raster Level Caching Behavior"), this);
m_rasterCacheBehaviorComboBox = new QComboBox(this);
//----Load Subsequence Level
QPushButton *showSubsequenceButton = createShowButton(this);
QLabel *subsequenceLabel = new QLabel(tr("Load Subsequence Level"), this);
m_subsequenceFrame = new QFrame(this);
m_fromFrame = new FrameNumberLineEdit(this, TFrameId(1));
m_toFrame = new FrameNumberLineEdit(this, TFrameId(1));
//----Arrangement in Xsheet
m_arrLvlPropWidget = new QWidget(this);
QPushButton *showArrangementButton = createShowButton(this);
QLabel *arrangementLabel =
new QLabel(tr("Level Settings & Arrangement in Scene"), this);
m_arrangementFrame = new QFrame(this);
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);
m_posTo = new DVGui::IntLineEdit(this, 1, 1);
//----Level Properties
m_levelPropertiesFrame = new QFrame(this);
m_levelName = new DVGui::LineEdit(this);
m_dpiWidget = new QWidget(this);
m_dpiPolicy = new QComboBox(this);
m_dpi = new DVGui::DoubleLineEdit(this);
m_subsampling = new DVGui::IntLineEdit(this, 1, 1);
m_antialias = new DVGui::IntLineEdit(this, 10, 0, 100);
m_premultiply = new DVGui::CheckBox(tr("Premultiply"), this);
m_whiteTransp = new DVGui::CheckBox(tr("White As Transparent"), this);
m_notExistLabel = new QLabel(tr("(FILE DOES NOT EXIST)"));
//----
m_rasterCacheBehaviorComboBox->addItem(
tr("On Demand"), IoCmd::LoadResourceArguments::ON_DEMAND);
m_rasterCacheBehaviorComboBox->addItem(
tr("All Icons"), IoCmd::LoadResourceArguments::ALL_ICONS);
m_rasterCacheBehaviorComboBox->addItem(
tr("All Icons & Images"),
IoCmd::LoadResourceArguments::ALL_ICONS_AND_IMAGES);
// use the default value set in the preference
m_rasterCacheBehaviorComboBox->setCurrentIndex(
m_rasterCacheBehaviorComboBox->findData(
Preferences::instance()->getRasterLevelCachingBehavior()));
cacheBehaviorLabel->setObjectName("TitleTxtLabel");
//----Load Subsequence Level
m_subsequenceFrame->setObjectName("LoadLevelFrame");
subsequenceLabel->setObjectName("TitleTxtLabel");
m_subsequenceFrame->hide();
m_fromFrame->setMaximumWidth(50);
m_toFrame->setMaximumWidth(50);
//----Arrangement in Xsheet
m_arrangementFrame->setObjectName("LoadLevelFrame");
m_levelPropertiesFrame->setObjectName("LoadLevelFrame");
arrangementLabel->setObjectName("TitleTxtLabel");
m_arrLvlPropWidget->hide();
QStringList sList;
sList << QString("Auto") << QString("1") << QString("2") << QString("3")
<< QString("4") << QString("5") << QString("6") << QString("7")
<< QString("8");
m_stepCombo->addItems(sList);
m_incCombo->addItems(sList);
//----Level Properties
m_dpiPolicy->addItem(QObject::tr("Image DPI"), LevelOptions::DP_ImageDpi);
m_dpiPolicy->addItem(QObject::tr("Custom DPI"), LevelOptions::DP_CustomDpi);
m_dpi->setRange(1, (std::numeric_limits<double>::max)());
m_dpi->setFixedWidth(54);
// initialize with the default value
LevelOptions options;
setLevelProperties(options);
//"FILE DOES NOT EXIST" label
m_notExistLabel->setObjectName("FileDoesNotExistLabel");
m_notExistLabel->hide();
//----layout
auto createVBoxLayout = [](int margin, int spacing) {
QVBoxLayout *layout = new QVBoxLayout();
layout->setMargin(margin);
layout->setSpacing(spacing);
return layout;
};
auto createHBoxLayout = [](int margin, int spacing) {
QHBoxLayout *layout = new QHBoxLayout();
layout->setMargin(margin);
layout->setSpacing(spacing);
return layout;
};
QVBoxLayout *mainLayout = createVBoxLayout(5, 3);
{
QHBoxLayout *cacheLay = createHBoxLayout(0, 5);
{
cacheLay->addStretch(1);
cacheLay->addWidget(cacheBehaviorLabel, 0);
cacheLay->addWidget(m_rasterCacheBehaviorComboBox, 0);
}
mainLayout->addLayout(cacheLay, 0);
//----Load Subsequence Level
QHBoxLayout *subsequenceHeadLay = createHBoxLayout(0, 5);
{
QFontMetrics metrics(font());
subsequenceHeadLay->addSpacing(metrics.width("File name:") + 3);
subsequenceHeadLay->addWidget(m_notExistLabel, 0);
subsequenceHeadLay->addStretch(1);
subsequenceHeadLay->addWidget(subsequenceLabel, 0);
subsequenceHeadLay->addWidget(showSubsequenceButton, 0);
}
mainLayout->addLayout(subsequenceHeadLay, 0);
QHBoxLayout *subsequenceLay = createHBoxLayout(5, 5);
{
subsequenceLay->addWidget(new QLabel(tr("From:"), this), 0);
subsequenceLay->addWidget(m_fromFrame, 0);
subsequenceLay->addWidget(new QLabel(tr(" To:"), this), 0);
subsequenceLay->addWidget(m_toFrame, 0);
}
m_subsequenceFrame->setLayout(subsequenceLay);
mainLayout->addWidget(m_subsequenceFrame, 0,
Qt::AlignRight | Qt::AlignVCenter);
//----Arrangement in Xsheet
QHBoxLayout *arrangementHeadLay = createHBoxLayout(0, 3);
{
arrangementHeadLay->addWidget(arrangementLabel, 1,
Qt::AlignRight | Qt::AlignVCenter);
arrangementHeadLay->addWidget(showArrangementButton, 0);
}
mainLayout->addLayout(arrangementHeadLay);
QHBoxLayout *bottomLay = createHBoxLayout(0, 10);
{
QGridLayout *levelLay = new QGridLayout();
levelLay->setMargin(5);
levelLay->setSpacing(5);
{
levelLay->addWidget(new QLabel(tr("Level Name:"), this), 0, 0,
Qt::AlignRight | Qt::AlignVCenter);
levelLay->addWidget(m_levelName, 0, 1);
QHBoxLayout *dpiLay = createHBoxLayout(0, 5);
{
dpiLay->addSpacing(10);
dpiLay->addWidget(new QLabel(tr("DPI:"), this), 0,
Qt::AlignRight | Qt::AlignVCenter);
dpiLay->addWidget(m_dpiPolicy, 0);
dpiLay->addWidget(m_dpi, 1);
}
m_dpiWidget->setLayout(dpiLay);
levelLay->addWidget(m_dpiWidget, 0, 2, 1, 3);
levelLay->addWidget(m_premultiply, 1, 0, 1, 2);
levelLay->addWidget(m_whiteTransp, 2, 0, 1, 2);
// levelLay->addWidget(m_doAntialias, 1, 3, 1, 2);
levelLay->addWidget(new QLabel(tr("Antialias Softness:"), this), 1, 2,
1, 2, Qt::AlignRight | Qt::AlignVCenter);
levelLay->addWidget(m_antialias, 1, 4);
levelLay->addWidget(new QLabel(tr("Subsampling:"), this), 2, 2, 1, 2,
Qt::AlignRight | Qt::AlignVCenter);
levelLay->addWidget(m_subsampling, 2, 4);
}
levelLay->setColumnStretch(1, 1);
levelLay->setColumnStretch(4, 1);
m_levelPropertiesFrame->setLayout(levelLay);
bottomLay->addWidget(m_levelPropertiesFrame, 0);
QGridLayout *arrLay = new QGridLayout();
arrLay->setMargin(5);
arrLay->setSpacing(5);
{
arrLay->addWidget(new QLabel(tr("From:"), this), 0, 0,
Qt::AlignRight | Qt::AlignVCenter);
arrLay->addWidget(m_xFrom, 0, 1);
arrLay->addWidget(new QLabel(tr(" To:"), this), 0, 2,
Qt::AlignRight | Qt::AlignVCenter);
arrLay->addWidget(m_xTo, 0, 3);
arrLay->addWidget(new QLabel(tr(" Step:"), this), 1, 0,
Qt::AlignRight | Qt::AlignVCenter);
arrLay->addWidget(m_stepCombo, 1, 1);
arrLay->addWidget(new QLabel(tr(" Inc:"), this), 1, 2,
Qt::AlignRight | Qt::AlignVCenter);
arrLay->addWidget(m_incCombo, 1, 3);
arrLay->addWidget(new QLabel(tr(" Frames:"), this), 2, 0,
Qt::AlignRight | Qt::AlignVCenter);
arrLay->addWidget(m_posFrom, 2, 1);
arrLay->addWidget(new QLabel(tr("::"), this), 2, 2, Qt::AlignCenter);
arrLay->addWidget(m_posTo, 2, 3);
}
arrLay->setColumnStretch(1, 1);
arrLay->setColumnStretch(3, 1);
m_arrangementFrame->setLayout(arrLay);
bottomLay->addWidget(m_arrangementFrame, 0);
}
m_arrLvlPropWidget->setLayout(bottomLay);
mainLayout->addWidget(m_arrLvlPropWidget, 0,
Qt::AlignRight | Qt::AlignVCenter);
}
optionWidget->setLayout(mainLayout);
//----signal-slot connections
//----Load Subsequence Level
connect(showSubsequenceButton, SIGNAL(toggled(bool)), m_subsequenceFrame,
SLOT(setVisible(bool)));
connect(m_fromFrame, SIGNAL(editingFinished()),
SLOT(onSubsequentFrameChanged()));
connect(m_toFrame, SIGNAL(editingFinished()),
SLOT(onSubsequentFrameChanged()));
//----Arrangement in Xsheet
connect(showArrangementButton, SIGNAL(toggled(bool)), m_arrLvlPropWidget,
SLOT(setVisible(bool)));
connect(m_xFrom, SIGNAL(editingFinished()), SLOT(updatePosTo()));
connect(m_xTo, SIGNAL(editingFinished()), SLOT(updatePosTo()));
connect(m_posFrom, SIGNAL(editingFinished()), SLOT(updatePosTo()));
connect(m_stepCombo, SIGNAL(currentIndexChanged(int)), SLOT(updatePosTo()));
connect(m_incCombo, SIGNAL(currentIndexChanged(int)), SLOT(updatePosTo()));
connect(m_nameField, SIGNAL(editingFinished()), this,
SLOT(onNameSetEditted()));
connect(m_browser, SIGNAL(treeFolderChanged(const TFilePath &)), this,
SLOT(onNameSetEditted()));
connect(m_browser, SIGNAL(filePathDoubleClicked(const TFilePath &)), this,
SLOT(onFilePathDoubleClicked(const TFilePath &)));
//----Level Properties
connect(m_dpiPolicy, SIGNAL(activated(int)), this,
SLOT(onDpiPolicyActivated()));
connect(m_premultiply, SIGNAL(clicked(bool)), this,
SLOT(onDoPremultiplyClicked()));
connect(m_whiteTransp, SIGNAL(clicked(bool)), this,
SLOT(onWhiteTranspClicked()));
}
//-----------------------------------------------------------------------
void LoadLevelPopup::onNameSetEditted() {
getCurrentPathSet().clear();
getCurrentFIdsSet().clear();
// if nothing input
if (m_nameField->text() == "") {
m_notExistLabel->hide();
updateBottomGUI();
}
// if the path exists
else {
TFilePath path =
m_browser->getFolder() + TFilePath(m_nameField->text().toStdString());
getCurrentPathSet().insert(path);
if (TSystem::doesExistFileOrLevel(path)) {
m_notExistLabel->hide();
updateBottomGUI();
} else {
m_notExistLabel->show();
m_fromFrame->setValue(TFrameId(1));
m_toFrame->setValue(TFrameId(1));
m_subsequenceFrame->setEnabled(true);
m_xFrom->setValue(TFrameId(1));
m_xTo->setValue(TFrameId(1));
m_levelName->setText(QString::fromStdString(path.getName()));
m_arrangementFrame->setEnabled(true);
m_levelName->setEnabled(true);
m_levelPropertiesFrame->setEnabled(true);
updatePosTo();
}
}
update();
}
//-----------------------------------------------------------------------
void LoadLevelPopup::updatePosTo() {
// calculate how many frames to be occupied in the xsheet
TFilePath fp = getCurrentPath();
if (QString::fromStdString(fp.getType()) == "tpl") {
m_posTo->setText(m_posFrom->text());
return;
}
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 =
frameLengthBetweenFIds() * ((m_stepCombo->currentIndex() == 0)
? 1
: m_stepCombo->currentIndex());
} else // Inc =! Auto
{
int loopAmount;
loopAmount = tceil((double)(frameLengthBetweenFIds()) / (double)inc);
frameLength = loopAmount * ((m_stepCombo->currentIndex() == 0)
? inc
: m_stepCombo->currentIndex());
}
}
//-- if loading the existing level
else if (m_incCombo->currentIndex() == 0) // Inc = Auto
{
if (isScene) {
frameLength = frameLengthBetweenFIds();
} else {
std::vector<TFrameId> fIds = getCurrentFIds();
//--- If loading the level with sequential files, reuse the list of
// TFrameId
if (fIds.size() != 0) {
if (m_stepCombo->currentIndex() == 0) // Step = Auto
{
frameLength = 0;
std::vector<TFrameId>::iterator it;
for (it = fIds.begin(); it != fIds.end(); it++) {
if (xFrom <= *it && *it <= xTo)
frameLength++;
else if (xTo < *it)
break;
}
} else // Step != Auto
{
std::vector<TFrameId>::iterator it;
int loopAmount = 0;
for (it = fIds.begin(); it != fIds.end(); it++) {
if (xFrom <= *it && *it <= xTo) loopAmount++;
}
frameLength = loopAmount * m_stepCombo->currentIndex();
}
}
// loading another type of level such as tlv
else {
if (fp.isEmpty()) return;
try {
TLevelReaderP lr(fp);
TLevelP level;
if (lr) level = lr->loadInfo();
if (!level.getPointer()) return;
if (m_stepCombo->currentIndex() == 0) // Step = Auto
{
frameLength = 0;
TLevel::Iterator it;
for (it = level->begin(); it != level->end(); it++) {
if (xFrom <= it->first && it->first <= xTo)
frameLength++;
else if (xTo < it->first)
break;
}
} else // Step != Auto
{
TLevel::Iterator it;
int loopAmount = 0;
for (it = level->begin(); it != level->end(); it++) {
if (xFrom <= it->first && it->first <= xTo) loopAmount++;
}
frameLength = loopAmount * m_stepCombo->currentIndex();
}
} catch (...) {
return;
}
}
}
}
// Inc != Auto
else {
int inc = m_incCombo->currentIndex();
int loopAmount;
loopAmount = tceil((double)(frameLengthBetweenFIds()) / (double)inc);
frameLength = loopAmount * ((m_stepCombo->currentIndex() == 0)
? inc
: m_stepCombo->currentIndex());
}
m_posTo->setText(
QString::number(m_posFrom->text().toInt() + frameLength - 1));
}
//-----------------------------------------------------------------------
/*! if the from / to values in the subsequent box, update m_xFrom and m_xTo
*/
void LoadLevelPopup::onSubsequentFrameChanged() {
m_xFrom->setValue(m_fromFrame->getValue());
m_xTo->setValue(m_toFrame->getValue());
updatePosTo();
}
//-----------------------------------------------------------------------
void LoadLevelPopup::showEvent(QShowEvent *e) {
m_nameField->clear();
FileBrowserPopup::showEvent(e);
bool ret = true;
TFrameHandle *fh = TApp::instance()->getCurrentFrame();
ret = ret &&
connect(fh, SIGNAL(frameSwitched()), this, SLOT(onFrameSwitched()));
ret = ret &&
connect(fh, SIGNAL(frameTypeChanged()), this, SLOT(onFrameSwitched()));
TSelectionHandle *sh = TApp::instance()->getCurrentSelection();
ret = ret && connect(sh, SIGNAL(selectionChanged(TSelection *)), this,
SLOT(onSelectionChanged(TSelection *)));
ret = ret && connect(TApp::instance()->getCurrentScene(),
SIGNAL(preferenceChanged(const QString &)), this,
SLOT(onPreferenceChanged(const QString &)));
assert(ret);
onFrameSwitched();
onSelectionChanged(sh->getSelection());
onPreferenceChanged("");
onNameSetEditted(); // clear currentPathSet
}
//-----------------------------------------------------------------------
void LoadLevelPopup::hideEvent(QHideEvent *e) {
FileBrowserPopup::hideEvent(e);
TFrameHandle *fh = TApp::instance()->getCurrentFrame();
disconnect(fh, SIGNAL(frameSwitched()), this, SLOT(onFrameSwitched()));
disconnect(fh, SIGNAL(frameTypeChanged()), this, SLOT(onFrameSwitched()));
TSelectionHandle *sh = TApp::instance()->getCurrentSelection();
disconnect(sh, SIGNAL(selectionChanged(TSelection *)), this,
SLOT(onSelectionChanged(TSelection *)));
disconnect(TApp::instance()->getCurrentScene(),
SIGNAL(preferenceChanged(const QString &)), this,
SLOT(onPreferenceChanged(const QString &)));
}
//-----------------------------------------------------------------------
void LoadLevelPopup::onFrameSwitched() {
TFrameHandle *fh = TApp::instance()->getCurrentFrame();
if (fh->isEditingLevel())
m_posFrom->setText("1");
else
m_posFrom->setText(QString::number(fh->getFrame() + 1));
updatePosTo();
}
//-----------------------------------------------------------------------
bool LoadLevelPopup::execute() {
if (m_selectedPaths.size() == 1) {
const TFilePath &fp = *m_selectedPaths.begin();
//---- SubSequent load
// if loading the "missing" level
if (m_notExistLabel->isVisible()) {
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();
TFrameId firstFrame;
TFrameId lastFrame;
// if the level is sequential and there is a reusable list of TFrameId
if (fIds.size() != 0) {
firstFrame = fIds[0];
lastFrame = fIds[fIds.size() - 1];
}
// another case such as loading tlv
else {
try {
TLevelReaderP lr(fp);
TLevelP level;
if (lr) level = lr->loadInfo();
if (!level.getPointer()) return false;
firstFrame = level->begin()->first;
lastFrame = (--level->end())->first;
lr = TLevelReaderP();
} catch (...) {
return false;
}
}
TFrameId firstLoadingFId = m_fromFrame->getValue();
TFrameId lastLoadingFId = m_toFrame->getValue();
if (firstFrame != firstLoadingFId || lastFrame != lastLoadingFId)
setLoadingLevelRange(firstLoadingFId, lastLoadingFId);
}
IoCmd::LoadResourceArguments args(fp);
args.row0 = m_posFrom->text().toInt() - 1;
args.frameCount = m_posTo->text().toInt() - m_posFrom->text().toInt() + 1;
if ((int)getCurrentFIdsSet().size() != 0)
args.frameIdsSet.push_back(*getCurrentFIdsSet().begin());
else if (m_notExistLabel->isVisible()) {
TFrameId firstLoadingFId = m_fromFrame->getValue();
TFrameId lastLoadingFId = m_toFrame->getValue();
// putting the Fids in order to avoid LoadInfo later
std::vector<TFrameId> tmp_fids;
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);
}
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();
args.inc = m_incCombo->currentIndex();
args.doesFileActuallyExist = !m_notExistLabel->isVisible();
args.cachingBehavior = IoCmd::LoadResourceArguments::CacheRasterBehavior(
m_rasterCacheBehaviorComboBox->currentData().toInt());
if (m_arrLvlPropWidget->isVisible() &&
m_levelPropertiesFrame->isEnabled()) {
for (IoCmd::LoadResourceArguments::ResourceData &rd :
args.resourceDatas) {
rd.m_options = LevelOptions();
getLevelProperties(*rd.m_options);
}
}
return 0 < IoCmd::loadResources(args, true, 0);
} else {
std::set<TFilePath>::const_iterator it;
IoCmd::LoadResourceArguments args;
args.row0 = m_posFrom->text().toInt() - 1;
for (it = m_selectedPaths.begin(); it != m_selectedPaths.end(); ++it)
args.resourceDatas.push_back(*it);
std::list<std::vector<TFrameId>> fIdsSet = getCurrentFIdsSet();
if (fIdsSet.size() > 0) {
std::list<std::vector<TFrameId>>::const_iterator fIdIt;
for (fIdIt = fIdsSet.begin(); fIdIt != fIdsSet.end(); ++fIdIt)
args.frameIdsSet.insert(args.frameIdsSet.begin(), *fIdIt);
}
args.cachingBehavior = IoCmd::LoadResourceArguments::CacheRasterBehavior(
m_rasterCacheBehaviorComboBox->currentData().toInt());
if (m_arrLvlPropWidget->isVisible() &&
m_levelPropertiesFrame->isEnabled()) {
for (IoCmd::LoadResourceArguments::ResourceData &rd :
args.resourceDatas) {
rd.m_options = LevelOptions();
getLevelProperties(*rd.m_options);
}
}
return 0 < IoCmd::loadResources(args, true, 0);
}
}
//-----------------------------------------------------------------------
void LoadLevelPopup::initFolder() {
TFilePath fp;
TProject *project =
TProjectManager::instance()->getCurrentProject().getPointer();
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
if (scene) fp = scene->decodeFilePath(project->getProjectFolder());
setFolder(fp);
onFilePathsSelected(getCurrentPathSet(), getCurrentFIdsSet());
}
//----------------------------------------------------------------------------
void LoadLevelPopup::onFilePathDoubleClicked(const TFilePath &path) {
Q_UNUSED(path);
onOkPressed();
}
//----------------------------------------------------------------------------
void LoadLevelPopup::onFilePathsSelected(
const std::set<TFilePath> &paths,
const std::list<std::vector<TFrameId>> &fIds) {
m_notExistLabel->hide();
FileBrowserPopup::onFilePathsSelected(paths, fIds);
updateBottomGUI();
}
//----------------------------------------------------------------------------
void LoadLevelPopup::updateBottomGUI() {
auto disableAll = [&]() {
m_fromFrame->setText("");
m_toFrame->setText("");
m_subsequenceFrame->setEnabled(false);
m_xFrom->setText("");
m_xTo->setText("");
m_levelName->setText("");
m_posTo->setText("");
m_arrangementFrame->setEnabled(false);
m_levelPropertiesFrame->setEnabled(false);
};
std::set<TFilePath> paths = getCurrentPathSet();
std::list<std::vector<TFrameId>> fIdsSet = getCurrentFIdsSet();
if (paths.empty() || paths.size() > 1) {
disableAll();
if (paths.size() > 1) {
m_levelName->setEnabled(false);
m_levelPropertiesFrame->setEnabled(true);
}
return;
}
TFilePath fp = getCurrentPath();
std::vector<TFrameId> fIds = getCurrentFIds();
QString ext = QString::fromStdString(fp.getType());
// initialize
if (fp.isEmpty() || ext == "") {
disableAll();
return;
} else if (ext == "tpl") {
m_fromFrame->setText("1");
m_toFrame->setText("1");
m_subsequenceFrame->setEnabled(false);
m_xFrom->setText("1");
m_xTo->setText("1");
m_levelName->setText(QString::fromStdString(fp.getName()));
m_posTo->setText(m_posFrom->text());
m_arrangementFrame->setEnabled(false);
m_levelPropertiesFrame->setEnabled(false);
} else if (ext == "tnz") {
ToonzScene scene;
scene.setScenePath(fp);
int sceneLength = scene.getFrameCount();
QString str;
m_fromFrame->setText(str.number(std::min(1, sceneLength)));
m_toFrame->setText(str.number(sceneLength));
m_subsequenceFrame->setEnabled(false);
m_xFrom->setText(m_fromFrame->text());
m_xTo->setText(m_toFrame->text());
m_levelName->setText(QString::fromStdString(fp.getName()));
m_stepCombo->setCurrentIndex(0);
m_incCombo->setCurrentIndex(0);
m_arrangementFrame->setEnabled(false);
m_levelPropertiesFrame->setEnabled(false);
} else {
TFrameId firstFrame;
TFrameId lastFrame;
// for level with sequential frames
if (fIds.size() != 0) {
firstFrame = fIds[0];
lastFrame = fIds[fIds.size() - 1];
} else {
try {
TLevelReaderP lr(fp);
TLevelP level;
if (lr) level = lr->loadInfo();
if (!level.getPointer() || level->getTable()->size() == 0) return;
firstFrame = level->begin()->first;
lastFrame = (--level->end())->first;
} catch (...) {
disableAll();
return;
}
}
m_fromFrame->setValue(firstFrame);
m_toFrame->setValue(lastFrame);
m_subsequenceFrame->setEnabled(true);
m_xFrom->setValue(firstFrame);
m_xTo->setValue(lastFrame);
// if some option in the preferences is selected, load the level with
// removing
// six letters of the scene name from the level name
m_levelName->setText(getLevelNameWithoutSceneNumber(fp.getName()));
// If the option "Show "ABC" Appendix to the Frame Number in Xsheet Cell" is
// ON, frame numbers normally increment at interval of 10.
// Placing such level with "Auto" step option will cause unwanted
// spacing between frames in Xsheet. Setting the step to "1" can prevent
// such problem.
if (Preferences::instance()->isShowFrameNumberWithLettersEnabled() &&
m_stepCombo->currentIndex() == 0)
m_stepCombo->setCurrentIndex(1);
m_arrangementFrame->setEnabled(true);
m_levelName->setEnabled(true);
m_levelPropertiesFrame->setEnabled(true);
}
updatePosTo();
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
/*! if some option in the preferences is selected, load the level with removing
six letters of the scene name from the level name
*/
QString LoadLevelPopup::getLevelNameWithoutSceneNumber(std::string orgName) {
QString levelOrgName = QString::fromStdString(orgName);
// check out the preference
if (!Preferences::instance()->isRemoveSceneNumberFromLoadedLevelNameEnabled())
return levelOrgName;
// do nothing if the level name has less than 7 letters
if (levelOrgName.size() <= 6) return levelOrgName;
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
if (!scene) return levelOrgName;
QString sceneName = QString::fromStdWString(scene->getSceneName()).left(5);
// if the first 5 letters are same a the scene name, then remove the letters
// to the under score
// this code is intended to cover both the case "c0001_hogehoge.tif" and
// "c0001A_tif"
if (!levelOrgName.startsWith(sceneName)) return levelOrgName;
if (!levelOrgName.contains("_")) return levelOrgName;
return levelOrgName.right(levelOrgName.size() - levelOrgName.indexOf("_") -
1);
}
//----------------------------------------------------------------------------
/*! if the x-sheet cells are selected, load levels at the upper-left corner of
* the selection
*/
void LoadLevelPopup::onSelectionChanged(TSelection *selection) {
TCellSelection *cellSelection = dynamic_cast<TCellSelection *>(selection);
if (!cellSelection) return;
int r0, r1, c0, c1;
cellSelection->getSelectedCells(r0, c0, r1, c1);
m_posFrom->setText(QString::number(r0 + 1));
updatePosTo();
}
//----------------------------------------------------------------------------
void LoadLevelPopup::onPreferenceChanged(const QString &propertyName) {
if (!propertyName.isEmpty() && propertyName != "pixelsOnly") return;
bool pixelsMode = Preferences::instance()->getBoolValue(pixelsOnly);
m_dpiWidget->setHidden(pixelsMode);
if (pixelsMode) {
m_dpiPolicy->setCurrentIndex(
m_dpiPolicy->findData(LevelOptions::DP_ImageDpi));
m_dpi->setValue(Stage::standardDpi);
m_dpi->setEnabled(false);
}
}
//----------------------------------------------------------------------------
void LoadLevelPopup::setLevelProperties(LevelOptions &options) {
m_dpiPolicy->setCurrentIndex(m_dpiPolicy->findData(options.m_dpiPolicy));
m_dpi->setValue(options.m_dpi);
m_subsampling->setValue(options.m_subsampling);
m_antialias->setValue(options.m_antialias);
m_whiteTransp->setChecked(options.m_whiteTransp);
m_premultiply->setChecked(options.m_premultiply);
onDpiPolicyActivated();
}
//----------------------------------------------------------------------------
void LoadLevelPopup::getLevelProperties(LevelOptions &options) {
options.m_dpiPolicy =
LevelOptions::DpiPolicy(m_dpiPolicy->currentData().toInt());
options.m_dpi = m_dpi->getValue();
options.m_subsampling = m_subsampling->getValue();
options.m_antialias = m_antialias->getValue();
options.m_whiteTransp = m_whiteTransp->isChecked();
options.m_premultiply = m_premultiply->isChecked();
}
//----------------------------------------------------------------------------
void LoadLevelPopup::onDpiPolicyActivated() {
m_dpi->setEnabled(m_dpiPolicy->currentData().toInt() ==
LevelOptions::DP_CustomDpi);
}
//----------------------------------------------------------------------------
// exclusive with the whiteTransp option
void LoadLevelPopup::onDoPremultiplyClicked() {
if (m_whiteTransp->isChecked()) m_whiteTransp->setChecked(false);
}
//----------------------------------------------------------------------------
// exclusive with the doPremultiply option
void LoadLevelPopup::onWhiteTranspClicked() {
if (m_premultiply->isChecked()) m_premultiply->setChecked(false);
}
//=============================================================================
// SaveLevelAsPopup
SaveLevelAsPopup::SaveLevelAsPopup()
: FileBrowserPopup(tr("Save Level"), Options(FOR_SAVING)) {
setOkText(tr("Save"));
connect(m_nameField, SIGNAL(returnPressedNow()), m_okButton,
SLOT(animateClick()));
}
bool SaveLevelAsPopup::execute() {
if (m_selectedPaths.empty()) return false;
TFilePath &fp = (TFilePath &)*m_selectedPaths.begin();
if (isSpaceString(QString::fromStdString(fp.getName()))) return false;
// pointer to be replaced
TXshLevel *levelToBeReplaced =
TApp::instance()->getCurrentLevel()->getLevel();
TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
int curColumnIndex = TApp::instance()->getCurrentColumn()->getColumnIndex();
bool ret = IoCmd::saveLevel(fp);
// ask whether to expose the saved level in xsheet
bool doExpose = true;
if (levelToBeReplaced->getType() & FULLCOLOR_TYPE)
doExpose = false;
else if (ret &&
!Preferences::instance()->isReplaceAfterSaveLevelAsEnabled()) {
QString question(QObject::tr("Do you want to expose the renamed level ?"));
int val = DVGui::MsgBox(question,
QObject::tr("Expose"), // val = 1
QObject::tr("Don't expose"), 0); // val = 2
if (val == 0) return false; // close button
if (val == 2) doExpose = false;
}
// exposing the level
if (ret && doExpose) {
// if the extensions are missing, add them here
TXshSimpleLevel *sl = dynamic_cast<TXshSimpleLevel *>(
TApp::instance()->getCurrentLevel()->getLevel());
if (!sl) return false;
std::string ext = sl->getPath().getType();
if (fp.getType() == "") fp = fp.withType(ext);
IoCmd::LoadResourceArguments args(fp);
args.expose = false;
int count = IoCmd::loadResources(args);
if (count == 0) return false;
TXshLevelP xl = args.loadedLevels[0];
// in case of replacing with a saved file
if (Preferences::instance()->isReplaceAfterSaveLevelAsEnabled()) {
for (int c = 0; c < xsh->getColumnCount(); c++) {
if (xsh->isColumnEmpty(c)) continue;
int r0, r1;
xsh->getCellRange(c, r0, r1);
for (int r = r0; r <= r1; r++) {
TXshCell cell = xsh->getCell(r, c);
if (cell.m_level.getPointer() != levelToBeReplaced) continue;
cell.m_level = xl;
xsh->setCell(r, c, cell);
}
}
TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
//--- update the scene cast
TLevelSet *levelSet =
TApp::instance()->getCurrentScene()->getScene()->getLevelSet();
for (int i = 0; i < levelSet->getLevelCount(); i++) {
TXshLevel *tmpLevel = levelSet->getLevel(i);
if (tmpLevel != levelToBeReplaced) continue;
if (!TApp::instance()
->getCurrentScene()
->getScene()
->getTopXsheet()
->isLevelUsed(tmpLevel))
levelSet->removeLevel(tmpLevel);
}
}
// In case of loading the saved file into a vacant column
else {
// find the leftmost empty column
int emptyColumnIndex = xsh->getFirstFreeColumnIndex();
// if the scene frame is selected and the old level is found in the
// current column,
// then place the new level at the same frame with the old one
if (TApp::instance()->getCurrentFrame()->isEditingScene()) {
// check out the current column
int r0, r1;
xsh->getCellRange(curColumnIndex, r0, r1);
for (int r = r0; r <= r1; r++) {
TXshCell cell = xsh->getCell(r, curColumnIndex);
if (!cell.isEmpty() &&
cell.m_level.getPointer() == levelToBeReplaced) {
// set the new level at the same frame with the old one
cell.m_level = xl;
xsh->setCell(r, emptyColumnIndex, cell);
}
}
}
// if the level editing mode, then just place the new level
else {
std::vector<TFrameId> dummy_fIds;
xsh->exposeLevel(0, emptyColumnIndex, xl.getPointer(), dummy_fIds);
}
}
TApp::instance()->getCurrentLevel()->setLevel(xl.getPointer());
TApp::instance()->getCurrentScene()->notifyCastChange();
TApp::instance()->getCurrentLevel()->notifyLevelChange();
DvDirModel::instance()->refreshFolder(fp.getParentDir());
// reset undo memory!!
if (Preferences::instance()->getBoolValue(resetUndoOnSavingLevel))
TUndoManager::manager()->reset();
}
if (ret)
std::cout << "SaveLevelAs complete." << std::endl;
else
std::cout << "SaveLevelAs failed for some reason." << std::endl;
return ret;
}
void SaveLevelAsPopup::initFolder() {
TProject *project =
TProjectManager::instance()->getCurrentProject().getPointer();
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
TFilePath fp;
if (scene) fp = scene->decodeFilePath(project->getFolder(TProject::Drawings));
setFolder(fp);
}
//---------------------------------------------------------------------------
/*
For Save Level As command, it is needed to check if the current level is
selected (just like Save Level command) BEFORE opening the popup. So I decided
to use an original MenuItemHandler rather than OpenPopupCommandHandler.
06/07/2016 Shun
*/
class SaveLevelAsCommandHandler final : public MenuItemHandler {
SaveLevelAsPopup *m_popup;
public:
SaveLevelAsCommandHandler() : MenuItemHandler(MI_SaveLevelAs), m_popup(0) {}
void execute() override {
TXshSimpleLevel *sl = TApp::instance()->getCurrentLevel()->getSimpleLevel();
if (!sl) {
DVGui::warning(QObject::tr("No Current Level"));
return;
}
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
if (!scene) {
DVGui::warning(QObject::tr("No Current Scene"));
return;
}
if (!m_popup) m_popup = new SaveLevelAsPopup();
m_popup->show();
m_popup->raise();
m_popup->activateWindow();
}
} saveLevelAsCommandHandler;
//=============================================================================
// Used both for ReplaceLevelPopup and ReplaceParentDirectoryPopup
// which are needed to maintain the current selection on open.
template <class T>
class OpenReplaceFilePopupHandler final : public MenuItemHandler {
T *m_popup;
public:
OpenReplaceFilePopupHandler(CommandId cmdId)
: MenuItemHandler(cmdId), m_popup(0) {}
// The current selection is cleared on the construction of FileBrowser
// ( by calling makeCurrent() in DvDirTreeView::currentChanged() ).
// Thus checking the selection must be done BEFORE making the browser
// or it fails to get the selection on the first call of this command.
bool initialize(TCellSelection::Range &range, std::set<int> &columnRange,
bool &replaceCells) {
TSelection *sel = TApp::instance()->getCurrentSelection()->getSelection();
if (!sel) return false;
TCellSelection *cellSel = dynamic_cast<TCellSelection *>(sel);
TColumnSelection *columnSel = dynamic_cast<TColumnSelection *>(sel);
if ((!cellSel && !columnSel) || sel->isEmpty()) {
DVGui::error(
QObject::tr("Nothing to replace: no cells or columns selected."));
return false;
}
if (cellSel) {
range = cellSel->getSelectedCells();
replaceCells = true;
} else if (columnSel) {
columnRange = columnSel->getIndices();
replaceCells = false;
}
return true;
}
void execute() override {
TCellSelection::Range range;
std::set<int> columnRange;
bool replaceCells;
if (!initialize(range, columnRange, replaceCells)) return;
if (!m_popup) m_popup = new T();
m_popup->setRange(range, columnRange, replaceCells);
m_popup->show();
m_popup->raise();
m_popup->activateWindow();
}
};
//=============================================================================
// ReplaceLevelPopup
ReplaceLevelPopup::ReplaceLevelPopup()
: FileBrowserPopup(tr("Replace Level"), Options(WITH_APPLY_BUTTON)) {
setOkText(tr("Replace"));
connect(TApp::instance()->getCurrentSelection(),
SIGNAL(selectionChanged(TSelection *)), this,
SLOT(onSelectionChanged(TSelection *)));
}
void ReplaceLevelPopup::setRange(TCellSelection::Range &range,
std::set<int> &columnRange,
bool &replaceCells) {
m_range = range;
m_columnRange = columnRange;
m_replaceCells = replaceCells;
}
bool ReplaceLevelPopup::execute() {
if (m_selectedPaths.empty()) return false;
const TFilePath &fp = *m_selectedPaths.begin();
if (!TSystem::doesExistFileOrLevel(fp)) {
DVGui::error(tr("File not found\n") + toQString(fp));
return false;
}
IoCmd::LoadResourceArguments args(fp);
args.expose = false;
args.col0 = m_range.m_c0;
args.col1 = m_range.m_c1;
args.row0 = m_range.m_r0;
args.row1 = m_range.m_r1;
int count = IoCmd::loadResources(args);
if (count == 0) return false;
TXshLevelP xl = args.loadedLevels[0];
TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
// cell selection
if (m_replaceCells) {
int r, c;
for (c = m_range.m_c0; c <= m_range.m_c1; c++)
for (r = m_range.m_r0; r <= m_range.m_r1; r++) {
TXshCell cell = xsh->getCell(r, c, false);
if (!cell.m_level.getPointer()) continue;
cell.m_level = xl;
xsh->setCell(r, c, cell);
}
}
// column selection
else {
int frameLength = xsh->getFrameCount();
std::set<int>::iterator i = m_columnRange.begin();
while (i != m_columnRange.end()) {
for (int r = 0; r < frameLength; r++) {
TXshCell cell = xsh->getCell(r, *i, false);
if (!cell.m_level.getPointer()) continue;
cell.m_level = xl;
xsh->setCell(r, *i, cell);
}
i++;
}
}
TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
TApp::instance()->getCurrentScene()->notifyCastChange();
DvDirModel::instance()->refreshFolder(fp.getParentDir());
return true;
}
//-----------------------------------------------------------------------------
void ReplaceLevelPopup::initFolder() {
setFolder(
TProjectManager::instance()->getCurrentProject()->getProjectFolder());
}
//-----------------------------------------------------------------------------
void ReplaceLevelPopup::onSelectionChanged(TSelection *sel) {
if (!sel) return;
TCellSelection *cellSel = dynamic_cast<TCellSelection *>(sel);
TColumnSelection *columnSel = dynamic_cast<TColumnSelection *>(sel);
if ((!cellSel && !columnSel) || sel->isEmpty()) return;
if (cellSel) {
m_range = cellSel->getSelectedCells();
m_replaceCells = true;
} else if (columnSel) {
m_columnRange = columnSel->getIndices();
m_replaceCells = false;
}
}
//=============================================================================
// SavePaletteAsPopup
SavePaletteAsPopup::SavePaletteAsPopup()
: FileBrowserPopup(tr("Save Palette"), Options(FOR_SAVING)) {
setOkText(tr("Save"));
addFilterType("tpl");
connect(m_nameField, SIGNAL(returnPressedNow()), m_okButton,
SLOT(animateClick()));
}
bool SavePaletteAsPopup::execute() {
if (m_selectedPaths.empty()) return false;
TFilePath fp(*m_selectedPaths.begin());
TPaletteHandle *paletteHandle =
TApp::instance()->getPaletteController()->getCurrentLevelPalette();
TPalette *palette = paletteHandle->getPalette();
if (!palette) {
DVGui::warning("No current palette exists");
return true;
}
const std::string &type = fp.getType();
if (!type.empty() && type != "tpl")
return false;
else if (type.empty())
fp = fp.getParentDir() + TFilePath(fp.getName() + ".tpl");
if (TFileStatus(fp).doesExist()) {
const QString &question =
QObject::tr(
"The palette %1 already exists.\nDo you want to overwrite it?")
.arg(toQString(fp));
int ret = DVGui::MsgBox(question, QObject::tr("Overwrite"),
QObject::tr("Cancel"), 0);
if (ret == 2 || ret == 0) return false;
}
const TFilePath &refImagePath = palette->getRefImgPath();
if (!refImagePath.isEmpty()) palette->setRefImgPath(TFilePath());
// In questo caso non voglio salvare la reference image.
StudioPalette::instance()->save(fp, palette);
if (!refImagePath.isEmpty()) palette->setRefImgPath(refImagePath);
palette->setDirtyFlag(false);
paletteHandle->notifyPaletteChanged();
return true;
}
void SavePaletteAsPopup::initFolder() {
setFolder(
TProjectManager::instance()->getCurrentProjectPath().getParentDir());
}
//=============================================================================
// LoadColorModelPopup
LoadColorModelPopup::LoadColorModelPopup()
: FileBrowserPopup(tr("Load Color Model"), Options(), "", new QFrame(0)) {
QFrame *optionFrame = (QFrame *)m_customWidget;
m_paletteFrame = new DVGui::LineEdit("", this);
// layout
QHBoxLayout *mainLayout = new QHBoxLayout();
mainLayout->setMargin(5);
mainLayout->setSpacing(5);
{
mainLayout->addStretch(1);
mainLayout->addWidget(new QLabel(tr("Frames :"), this), 0);
mainLayout->addWidget(m_paletteFrame, 0);
}
optionFrame->setLayout(mainLayout);
setOkText(tr("Load"));
addFilterType("bmp");
addFilterType("jpg");
addFilterType("png");
addFilterType("rgb");
addFilterType("sgi");
addFilterType("tga");
addFilterType("tif");
addFilterType("tiff");
addFilterType("tlv");
addFilterType("pli");
addFilterType("psd");
}
//--------------------------------------------------------------
void LoadColorModelPopup::onFilePathsSelected(
const std::set<TFilePath> &paths) {
std::list<std::vector<TFrameId>> tmp;
FileBrowserPopup::onFilePathsSelected(paths, tmp);
m_paletteFrame->setText("");
if (paths.size() == 1) {
// Initialize the line with the level's starting frame
const TFilePath &fp = *paths.begin();
try {
TLevelReaderP lr(fp);
TLevelP level;
if (lr) level = lr->loadInfo();
if (level.getPointer() && level->begin() != level->end()) {
int firstFrame = level->begin()->first.getNumber();
if (firstFrame > 0)
m_paletteFrame->setText(QString::number(firstFrame));
}
} catch (...) {
}
}
}
//--------------------------------------------------------------
bool LoadColorModelPopup::execute() {
if (m_selectedPaths.empty()) return false;
const TFilePath &fp = *m_selectedPaths.begin();
TPaletteHandle *paletteHandle =
TApp::instance()->getPaletteController()->getCurrentLevelPalette();
TPalette *palette = paletteHandle->getPalette();
if (!palette || palette->isCleanupPalette()) {
DVGui::error(QObject::tr("Cannot load Color Model in current palette."));
return false;
}
PaletteCmd::ColorModelLoadingConfiguration config;
// if the palette is locked, replace the color model's palette with the
// destination
if (palette->isLocked()) {
// do nothing as config will use behavior = ReplaceColorModelPlt by default
// config.behavior = PaletteCmd::ReplaceColorModelPlt;
} else {
ColorModelBehaviorPopup popup(m_selectedPaths, 0);
int ret = popup.exec();
if (ret == QDialog::Rejected) return false;
popup.getLoadingConfiguration(config);
}
std::vector<int> framesInput = string2Indexes(m_paletteFrame->text());
if (!framesInput.empty()) {
for (int i = 0; i < framesInput.size(); i++)
std::cout << framesInput[i] << std::endl;
}
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
int isLoaded = PaletteCmd::loadReferenceImage(paletteHandle, config, fp,
scene, framesInput);
// return value - isLoaded
// 2: failed to get palette
// 1: failed to get image
// 0: OK
if (isLoaded == 2) {
std::cout << "GetCurrentPalette Failed!" << std::endl;
return false;
} else if (isLoaded == 1) {
std::cout << "GetReferenceImage Failed!" << std::endl;
return false;
} else if (0 != isLoaded) {
std::cout << "loadReferenceImage Failed for some reason." << std::endl;
return false;
}
// no changes in the icon with replace (Keep the destination palette) option
if (config.behavior != PaletteCmd::ReplaceColorModelPlt) {
TXshLevel *level = TApp::instance()->getCurrentLevel()->getLevel();
if (!level) return true;
std::vector<TFrameId> fids;
level->getFids(fids);
invalidateIcons(level, fids);
}
return true;
}
//--------------------------------------------------------------
void LoadColorModelPopup::showEvent(QShowEvent *e) {
m_nameField->clear();
FileBrowserPopup::showEvent(e);
}
//=============================================================================
/*! replace the parent folder path of the levels in the selected cells
*/
ReplaceParentDirectoryPopup::ReplaceParentDirectoryPopup()
: FileBrowserPopup(tr("Replace Parent Directory")) {
setOkText(tr("Replace"));
setFileMode(true); // isDirectoryOnly
}
void ReplaceParentDirectoryPopup::setRange(TCellSelection::Range &range,
std::set<int> &columnRange,
bool &replaceCells) {
m_range = range;
m_columnRange = columnRange;
m_replaceCells = replaceCells;
}
bool ReplaceParentDirectoryPopup::execute() {
if (m_selectedPaths.empty()) return false;
const TFilePath &fp = *m_selectedPaths.begin();
// make the level list in the selected cells
TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
std::vector<TXshLevel *> levelsToBeReplaced;
if (m_replaceCells) {
int r, c;
for (c = m_range.m_c0; c <= m_range.m_c1; c++) {
for (r = m_range.m_r0; r <= m_range.m_r1; r++) {
TXshCell cell = xsh->getCell(r, c);
if (cell.isEmpty() ||
!cell.m_level->getSimpleLevel()) // TLV and PLI only
continue;
levelsToBeReplaced.push_back(cell.m_level.getPointer());
}
}
} else {
// calculate scene length
int frameLength = xsh->getFrameCount();
std::set<int>::iterator i = m_columnRange.begin();
while (i != m_columnRange.end()) {
for (int r = 0; r < frameLength; r++) {
TXshCell cell = xsh->getCell(r, *i);
if (!cell.m_level.getPointer()) continue;
levelsToBeReplaced.push_back(cell.m_level.getPointer());
}
i++;
}
}
// avoid level duplication
std::sort(levelsToBeReplaced.begin(), levelsToBeReplaced.end());
levelsToBeReplaced.erase(
std::unique(levelsToBeReplaced.begin(), levelsToBeReplaced.end()),
levelsToBeReplaced.end());
if (levelsToBeReplaced.empty()) return false;
// check if the file exists. If exists, load it and store them in the map
// rewrite the path in the level settings
bool somethingChanged = false;
std::vector<TXshLevel *>::iterator it = levelsToBeReplaced.begin();
for (; it != levelsToBeReplaced.end(); it++) {
TFilePath orgPath = (*it)->getPath();
if (orgPath.isEmpty()) continue;
TFilePath newPath = orgPath.withParentDir(fp);
if (orgPath == newPath) continue;
// If the file exists
if (TSystem::doesExistFileOrLevel(newPath)) {
TXshSimpleLevel *sl = (*it)->getSimpleLevel();
if (!sl) continue;
// replace the file with aliases, if possible
newPath = TApp::instance()->getCurrentScene()->getScene()->codeFilePath(
newPath);
sl->setPath(newPath);
sl->invalidateFrames();
std::vector<TFrameId> frames;
sl->getFids(frames);
std::vector<TFrameId>::iterator f_it = frames.begin();
for (; f_it != frames.end(); f_it++)
IconGenerator::instance()->invalidate(sl, *f_it);
somethingChanged = true;
}
}
if (!somethingChanged) return false;
TApp::instance()->getCurrentLevel()->notifyLevelChange();
TApp::instance()->getCurrentScene()->notifySceneChanged();
TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
return true;
}
void ReplaceParentDirectoryPopup::initFolder() {
setFolder(
TProjectManager::instance()->getCurrentProjectPath().getParentDir());
}
//=============================================================================
// ImportMagpieFilePopup
ImportMagpieFilePopup::ImportMagpieFilePopup()
: FileBrowserPopup(tr("Import Toonz Lip Sync File")) {
setOkText(tr("Load"));
addFilterType("tls");
}
bool ImportMagpieFilePopup::execute() {
if (m_selectedPaths.empty()) return false;
const TFilePath &fp = *m_selectedPaths.begin();
if (!TSystem::doesExistFileOrLevel(fp)) {
DVGui::error(tr("%1 does not exist.").arg(toQString(fp)));
return false;
}
static MagpieFileImportPopup *magpieFileImportPopup =
new MagpieFileImportPopup();
magpieFileImportPopup->setFilePath(fp);
magpieFileImportPopup->show();
return true;
}
void ImportMagpieFilePopup::initFolder() {
TProject *project =
TProjectManager::instance()->getCurrentProject().getPointer();
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
TFilePath fp;
if (scene) fp = scene->decodeFilePath(project->getFolder(TProject::Drawings));
setFolder(fp);
}
void ImportMagpieFilePopup::showEvent(QShowEvent *e) {
m_nameField->clear();
FileBrowserPopup::showEvent(e);
}
//=============================================================================
// BrowserPopup
BrowserPopup::BrowserPopup() : FileBrowserPopup("") {
setOkText(tr("Choose"));
m_browser->enableGlobalSelection(false);
}
bool BrowserPopup::execute() {
if (m_selectedPaths.empty()) return false;
const TFilePath &fp = *m_selectedPaths.begin();
if (!TSystem::doesExistFileOrLevel(fp)) {
const QString &msg = tr("Path %1 doesn't exists.").arg(toQString(fp));
DVGui::info(msg);
return false;
}
m_path = fp;
return true;
}
void BrowserPopup::initFolder(TFilePath path) {
// if the path is empty
if (path.isEmpty()) {
TProject *project =
TProjectManager::instance()->getCurrentProject().getPointer();
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
if (scene)
setFolder(scene->decodeFilePath(project->getFolder(TProject::Drawings)));
return;
}
if (!TFileStatus(path).doesExist()) {
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
if (scene) path = scene->decodeFilePath(path);
}
if (!path.getType().empty()) path = path.getParentDir();
setFolder(path);
setFilename(TFilePath());
}
//=============================================================================
// BrowserPopupController
/* N.B. Eliminare nel momento in cui la classe FileBrowserPopup, con tutte le
classi annesse
(FileBrowser, DvDirTreeView, ...), sara'
spostata nella libreria toonzQt. */
BrowserPopupController::BrowserPopupController() : m_browserPopup() {
m_isExecute = false;
DVGui::FileField::setBrowserPopupController(this);
}
void BrowserPopupController::openPopup(QStringList filters,
bool isDirectoryOnly,
QString lastSelectedPath,
const QWidget *parentWidget) {
if (!m_browserPopup) m_browserPopup = new BrowserPopup();
m_browserPopup->setWindowTitle(QString(""));
m_browserPopup->setFilterTypes(filters);
m_browserPopup->setWindowTitle((isDirectoryOnly)
? QString(QObject::tr("Choose Folder"))
: QString(QObject::tr("File Browser")));
m_browserPopup->initFolder(TFilePath(lastSelectedPath.toStdWString()));
m_browserPopup->setFileMode(isDirectoryOnly);
Qt::WindowFlags flags = m_browserPopup->windowFlags();
bool parentSet = false;
if (parentWidget) {
for (QWidget *pwidget : QApplication::topLevelWidgets()) {
if (pwidget->isWindow() && pwidget->isVisible() &&
pwidget->isAncestorOf(parentWidget)) {
m_browserPopup->setParent(pwidget);
m_browserPopup->setWindowFlags(flags);
parentSet = true;
break;
}
}
}
if (isDirectoryOnly)
m_browserPopup->setFilename(TFilePath(lastSelectedPath.toStdWString()));
if (m_browserPopup->exec() == QDialog::Accepted)
m_isExecute = true;
else
m_isExecute = false;
// set back the parent to the main window in order to prevent to be
// deleted along with the parent widget
if (parentSet) {
m_browserPopup->setParent(TApp::instance()->getMainWindow());
m_browserPopup->setWindowFlags(flags);
}
}
// codePath is set to true by default
QString BrowserPopupController::getPath(bool codePath) {
m_isExecute = false;
if (!m_browserPopup) return QString();
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
TFilePath fp = m_browserPopup->getPath();
if (scene && codePath) fp = scene->codeFilePath(fp);
std::cout << ::to_string(fp) << std::endl;
return toQString(fp);
}
//=============================================================================
BrowserPopupController browserPopupController;
//-----------------------------------------------------------------------------
OpenPopupCommandHandler<SaveSceneAsPopup> saveSceneAsPopupCommand(
MI_SaveSceneAs);
OpenPopupCommandHandler<SaveSubSceneAsPopup> saveSubSceneAsPopupCommand(
MI_SaveSubxsheetAs);
OpenPopupCommandHandler<LoadLevelPopup> loadLevelPopupCommand(MI_LoadLevel);
OpenPopupCommandHandler<ConvertPopupWithInput> convertWithInputPopupCommand(
MI_ConvertFileWithInput);
OpenPopupCommandHandler<SavePaletteAsPopup> savePalettePopupCommand(
MI_SavePaletteAs);
OpenPopupCommandHandler<LoadColorModelPopup> loadColorModelPopupCommand(
MI_LoadColorModel);
OpenPopupCommandHandler<ImportMagpieFilePopup> importMagpieFilePopupCommand(
MI_ImportMagpieFile);
// Note: MI_ReplaceLevel and MI_ReplaceParentDirectory uses the original
// handler in order to obtain the selection information before making the
// browser.
OpenReplaceFilePopupHandler<ReplaceLevelPopup> replaceLevelPopupCommand(
MI_ReplaceLevel);
OpenReplaceFilePopupHandler<ReplaceParentDirectoryPopup>
replaceParentFolderPopupCommand(MI_ReplaceParentDirectory);