d1f6c4e95b
* add final specifiers * apply clang-format * fix for macOS
919 lines
30 KiB
C++
919 lines
30 KiB
C++
|
|
|
|
#include "castviewer.h"
|
|
|
|
// Tnz6 includes
|
|
#include "castselection.h"
|
|
#include "tapp.h"
|
|
#include "menubarcommandids.h"
|
|
#include "floatingpanelcommand.h"
|
|
#include "iocommand.h"
|
|
#include "filmstripcommand.h"
|
|
#include "flipbook.h"
|
|
|
|
// TnzLib includes
|
|
#include "toonz/tscenehandle.h"
|
|
#include "toonz/txsheethandle.h"
|
|
#include "toonz/txshlevelhandle.h"
|
|
#include "toonz/levelset.h"
|
|
#include "toonz/toonzscene.h"
|
|
#include "toonz/levelset.h"
|
|
#include "toonz/txshsimplelevel.h"
|
|
#include "toonz/txshleveltypes.h"
|
|
|
|
// TnzQt includes
|
|
#include "toonzqt/dvdialog.h"
|
|
#include "toonzqt/gutil.h"
|
|
#include "toonzqt/trepetitionguard.h"
|
|
#include "toonzqt/icongenerator.h"
|
|
#include "toonzqt/infoviewer.h"
|
|
#include "historytypes.h"
|
|
|
|
// TnzCore includes
|
|
#include "tundo.h"
|
|
#include "tfiletype.h"
|
|
#include "tsystem.h"
|
|
|
|
// Qt includes
|
|
#include <QDrag>
|
|
#include <QDragEnterEvent>
|
|
#include <QDragMoveEvent>
|
|
#include <QDropEvent>
|
|
#include <QDragLeaveEvent>
|
|
#include <QHeaderView>
|
|
#include <QPainter>
|
|
#include <QBoxLayout>
|
|
#include <QLabel>
|
|
#include <QByteArray>
|
|
#include <QDesktopServices>
|
|
#include <QUrl>
|
|
#include <QMenu>
|
|
#include <QDir>
|
|
|
|
const char *AudioFolderName = "Audio";
|
|
|
|
using namespace DVGui;
|
|
|
|
namespace {
|
|
|
|
// Se il widget del cast viewer viene spostato in toonzqt (e quindi fatto
|
|
// dipendere dallo sceneHandle)
|
|
// questo undo puo' essere spostato in un nuovo file levelsetcommand in
|
|
// toonzlib.
|
|
class MoveLevelToFolderUndo final : public TUndo {
|
|
TLevelSet *m_levelSet;
|
|
std::wstring m_levelName;
|
|
TFilePath m_oldFolder;
|
|
TFilePath m_newFolder;
|
|
|
|
public:
|
|
MoveLevelToFolderUndo(TLevelSet *levelSet, std::wstring levelName,
|
|
TFilePath newFolder)
|
|
: m_levelSet(levelSet), m_levelName(levelName), m_newFolder(newFolder) {
|
|
TXshLevel *level = m_levelSet->getLevel(m_levelName);
|
|
m_oldFolder = m_levelSet->getFolder(level);
|
|
}
|
|
|
|
void undo() const override {
|
|
TXshLevel *level = m_levelSet->getLevel(m_levelName);
|
|
m_levelSet->moveLevelToFolder(m_oldFolder, level);
|
|
TApp::instance()->getCurrentScene()->notifyCastChange();
|
|
}
|
|
|
|
void redo() const override {
|
|
TXshLevel *level = m_levelSet->getLevel(m_levelName);
|
|
m_levelSet->moveLevelToFolder(m_newFolder, level);
|
|
TApp::instance()->getCurrentScene()->notifyCastChange();
|
|
}
|
|
|
|
int getSize() const override { return sizeof(*this); }
|
|
|
|
QString getHistoryString() override {
|
|
return QObject::tr("Move Level to Cast Folder");
|
|
}
|
|
};
|
|
}
|
|
|
|
//=============================================================================
|
|
//
|
|
// CastTreeViewer
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
CastTreeViewer::CastTreeViewer(QWidget *parent)
|
|
: QTreeWidget(parent), m_dropTargetItem(0) {
|
|
setObjectName("OnePixelMarginFrame");
|
|
// setObjectName("BrowserTreeView");
|
|
// setStyleSheet("#BrowserTreeView {border: 0px; margin: 1px;
|
|
// qproperty-autoFillBackground: true;}");
|
|
|
|
header()->close();
|
|
setIconSize(QSize(21, 17));
|
|
setUniformRowHeights(true);
|
|
// m_treeViewer->setColumnCount(1);
|
|
|
|
setAcceptDrops(true);
|
|
connect(this, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this,
|
|
SLOT(onItemChanged(QTreeWidgetItem *, int)));
|
|
connect(this,
|
|
SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
|
|
this, SLOT(onFolderChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
|
|
connect(TApp::instance()->getCurrentScene(), SIGNAL(sceneSwitched()), this,
|
|
SLOT(rebuildCastTree()));
|
|
connect(TApp::instance()->getCurrentScene(),
|
|
SIGNAL(castFolderAdded(const TFilePath &)), this,
|
|
SLOT(onCastFolderAdded(const TFilePath &)));
|
|
|
|
connect(TApp::instance()->getCurrentScene(), SIGNAL(nameSceneChanged()), this,
|
|
SLOT(onSceneNameChanged()));
|
|
|
|
// Connect all possible changes that can alter the
|
|
// bottom horizontal scrollbar to resize contents...
|
|
connect(this, SIGNAL(expanded(const QModelIndex &)), this,
|
|
SLOT(resizeToConts()));
|
|
|
|
connect(this, SIGNAL(collapsed(const QModelIndex &)), this,
|
|
SLOT(resizeToConts()));
|
|
|
|
connect(this->model(), SIGNAL(layoutChanged()), this, SLOT(resizeToConts()));
|
|
|
|
rebuildCastTree();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//! Resizes viewport to contents
|
|
void CastTreeViewer::resizeToConts(void) { resizeColumnToContents(0); }
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CastTreeViewer::resizeEvent(QResizeEvent *event) {
|
|
resizeColumnToContents(0);
|
|
QTreeView::resizeEvent(event);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
TLevelSet *CastTreeViewer::getLevelSet() {
|
|
return TApp::instance()->getCurrentScene()->getScene()->getLevelSet();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CastTreeViewer::enableCommands() {
|
|
enableCommand(this, MI_Clear, &CastTreeViewer::deleteFolder);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CastTreeViewer::onFolderChanged(QTreeWidgetItem *current,
|
|
QTreeWidgetItem *previous) {
|
|
// rende la selezione corrente; serve per intercettare il comando MI_Clear
|
|
makeCurrent();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CastTreeViewer::populateFolder(QTreeWidgetItem *folder) {
|
|
TFilePath folderPath(
|
|
folder->data(1, Qt::DisplayRole).toString().toStdWString());
|
|
std::vector<TFilePath> folders;
|
|
getLevelSet()->listFolders(folders, folderPath);
|
|
int i;
|
|
for (i = 0; i < (int)folders.size(); i++) {
|
|
TFilePath fp = folders[i];
|
|
QString fpQstr = QString::fromStdWString(fp.getWideString());
|
|
QString name =
|
|
QString::fromStdWString(fp.withoutParentDir().getWideString());
|
|
QTreeWidgetItem *child =
|
|
new QTreeWidgetItem((QTreeWidgetItem *)0, QStringList(name) << fpQstr);
|
|
if (name != AudioFolderName)
|
|
child->setFlags(child->flags() | Qt::ItemIsEditable);
|
|
folder->addChild(child);
|
|
populateFolder(child);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CastTreeViewer::onSceneNameChanged() {
|
|
QTreeWidgetItem *root = topLevelItem(0);
|
|
if (!root) return;
|
|
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
|
|
QString rootName = QString("Root");
|
|
if (scene) {
|
|
std::wstring name =
|
|
(scene->isUntitled()) ? L"Untitled" : scene->getSceneName();
|
|
rootName = rootName.fromStdWString(name);
|
|
}
|
|
root->setText(0, rootName);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CastTreeViewer::onCastFolderAdded(const TFilePath &path) {
|
|
QTreeWidgetItem *root = topLevelItem(0)->child(0);
|
|
assert(root->data(1, Qt::DisplayRole).toString() ==
|
|
toQString(getLevelSet()->getDefaultFolder()));
|
|
QString childName = QString::fromStdWString(path.getWideName());
|
|
QString childPathQstr = QString::fromStdWString(path.getWideString());
|
|
QTreeWidgetItem *childItem =
|
|
new QTreeWidgetItem(root, QStringList(childName) << childPathQstr);
|
|
childItem->setFlags(childItem->flags() | Qt::ItemIsEditable);
|
|
root->addChild(childItem);
|
|
setCurrentItem(childItem);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CastTreeViewer::rebuildCastTree() {
|
|
clear();
|
|
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
|
|
QString rootName = QString("Root");
|
|
if (scene) {
|
|
std::wstring name =
|
|
(scene->isUntitled()) ? L"Untitled" : scene->getSceneName();
|
|
rootName = rootName.fromStdWString(name);
|
|
}
|
|
|
|
QTreeWidgetItem *root =
|
|
new QTreeWidgetItem((QTreeWidgetItem *)0, QStringList(rootName));
|
|
static QPixmap clapboard(":Resources/clapboard.png");
|
|
root->setIcon(0, clapboard);
|
|
insertTopLevelItem(0, root);
|
|
populateFolder(root);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
QSize CastTreeViewer::sizeHint() const { return QSize(100, 100); }
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CastTreeViewer::paintEvent(QPaintEvent *event) {
|
|
QTreeWidget::paintEvent(event);
|
|
QPainter p(viewport());
|
|
if (m_dropTargetItem) {
|
|
p.setPen(QColor(50, 105, 200));
|
|
p.drawRect(visualItemRect(m_dropTargetItem).adjusted(0, 0, -1, 0));
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CastTreeViewer::dragEnterEvent(QDragEnterEvent *e) {
|
|
m_dropFilePath = TFilePath();
|
|
if (acceptResourceOrFolderDrop(e->mimeData()->urls())) {
|
|
if (e->mimeData()->urls().size() != 1) return;
|
|
TFilePath path(e->mimeData()->urls()[0].toLocalFile().toStdWString());
|
|
|
|
if (path.getType() == "tnz")
|
|
m_dropFilePath = path;
|
|
else
|
|
return;
|
|
}
|
|
if (!e->mimeData()->hasFormat("application/vnd.toonz.levels") &&
|
|
m_dropFilePath == TFilePath())
|
|
return;
|
|
m_dropTargetItem = itemAt(e->pos());
|
|
if (m_dropTargetItem &&
|
|
m_dropTargetItem->data(0, Qt::DisplayRole).toString() == AudioFolderName)
|
|
m_dropTargetItem = 0;
|
|
|
|
e->acceptProposedAction();
|
|
viewport()->update();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CastTreeViewer::dragMoveEvent(QDragMoveEvent *event) {
|
|
if (!event->mimeData()->hasFormat("application/vnd.toonz.levels") ||
|
|
m_dropFilePath != TFilePath())
|
|
return;
|
|
|
|
m_dropTargetItem = itemAt(event->pos());
|
|
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
|
|
QString rootName = QString("Root");
|
|
if (scene) {
|
|
std::wstring name =
|
|
(scene->isUntitled()) ? L"Untitled" : scene->getSceneName();
|
|
rootName = rootName.fromStdWString(name);
|
|
}
|
|
if (m_dropTargetItem &&
|
|
m_dropTargetItem->data(0, Qt::DisplayRole).toString() ==
|
|
AudioFolderName ||
|
|
m_dropFilePath != TFilePath() &&
|
|
m_dropTargetItem->data(0, Qt::DisplayRole).toString() == rootName)
|
|
m_dropTargetItem = 0;
|
|
|
|
if (!m_dropTargetItem)
|
|
event->ignore();
|
|
else
|
|
event->acceptProposedAction();
|
|
viewport()->update();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CastTreeViewer::dropEvent(QDropEvent *event) {
|
|
m_dropTargetItem = 0;
|
|
if (m_dropFilePath != TFilePath()) {
|
|
IoCmd::loadScene(m_dropFilePath);
|
|
m_dropFilePath = TFilePath();
|
|
m_dropTargetItem = 0;
|
|
update();
|
|
return;
|
|
}
|
|
|
|
if (!event->mimeData()->hasFormat("application/vnd.toonz.levels")) return;
|
|
m_dropTargetItem = itemAt(event->pos());
|
|
if (!m_dropTargetItem) return;
|
|
TFilePath folderPath(
|
|
m_dropTargetItem->data(1, Qt::DisplayRole).toString().toStdWString());
|
|
m_dropTargetItem = 0;
|
|
update();
|
|
|
|
if (folderPath.getName() == AudioFolderName) {
|
|
event->ignore();
|
|
return;
|
|
}
|
|
event->acceptProposedAction();
|
|
|
|
TLevelSet *levelSet = getLevelSet();
|
|
|
|
const CastItems *castItems =
|
|
dynamic_cast<const CastItems *>(event->mimeData());
|
|
assert(castItems);
|
|
if (!castItems) return;
|
|
int i;
|
|
TUndoManager::manager()->beginBlock();
|
|
for (i = 0; i < castItems->getItemCount(); i++) {
|
|
CastItem *item = castItems->getItem(i);
|
|
if (LevelCastItem *li = dynamic_cast<LevelCastItem *>(item)) {
|
|
TXshLevel *level = li->getLevel();
|
|
std::wstring levelName = level->getName();
|
|
MoveLevelToFolderUndo *undo =
|
|
new MoveLevelToFolderUndo(levelSet, levelName, folderPath);
|
|
levelSet->moveLevelToFolder(folderPath, level);
|
|
TUndoManager::manager()->add(undo);
|
|
} else if (SoundCastItem *si = dynamic_cast<SoundCastItem *>(item)) {
|
|
}
|
|
}
|
|
TUndoManager::manager()->endBlock();
|
|
emit itemMovedToFolder();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CastTreeViewer::dragLeaveEvent(QDragLeaveEvent *event) {
|
|
m_dropTargetItem = 0;
|
|
m_dropFilePath = TFilePath();
|
|
update();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CastTreeViewer::onItemChanged(QTreeWidgetItem *item, int column) {
|
|
if (column != 0) return;
|
|
if (item->isSelected()) {
|
|
TFilePath oldPath(item->data(1, Qt::DisplayRole).toString().toStdWString());
|
|
TFilePath newPath =
|
|
getLevelSet()->renameFolder(oldPath, item->text(0).toStdWString());
|
|
item->setText(1, QString::fromStdWString(newPath.getWideString()));
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
TFilePath CastTreeViewer::getCurrentFolder() const {
|
|
if (!currentItem()) return TFilePath();
|
|
QVariant data = currentItem()->data(1, Qt::DisplayRole);
|
|
if (data == QVariant()) return TFilePath();
|
|
return TFilePath(data.toString().toStdWString());
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CastTreeViewer::folderUp() {
|
|
QTreeWidgetItem *item = currentItem();
|
|
if (item && item->parent() != (QTreeWidgetItem *)0)
|
|
setCurrentItem(item->parent());
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CastTreeViewer::newFolder() {
|
|
QTreeWidgetItem *parentItem = currentItem();
|
|
if (parentItem == (QTreeWidgetItem *)0) return;
|
|
QString parentName = parentItem->data(0, Qt::DisplayRole).toString();
|
|
if (parentName == AudioFolderName) return;
|
|
|
|
TFilePath parentPath =
|
|
TFilePath(parentItem->data(1, Qt::DisplayRole).toString().toStdWString());
|
|
QString childName("New Folder");
|
|
TFilePath childPath = parentPath + childName.toStdWString();
|
|
QString childPathQstr = QString::fromStdWString(childPath.getWideString());
|
|
QTreeWidgetItem *childItem =
|
|
new QTreeWidgetItem(parentItem, QStringList(childName) << childPathQstr);
|
|
childItem->setFlags(childItem->flags() | Qt::ItemIsEditable);
|
|
parentItem->addChild(childItem);
|
|
setCurrentItem(childItem);
|
|
editItem(childItem);
|
|
TLevelSet *levelSet =
|
|
TApp::instance()->getCurrentScene()->getScene()->getLevelSet();
|
|
levelSet->createFolder(parentPath, childName.toStdWString());
|
|
TApp::instance()->getCurrentScene()->setDirtyFlag(true);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CastTreeViewer::deleteFolder() {
|
|
QTreeWidgetItem *item = currentItem();
|
|
if (!item || !item->parent()) return;
|
|
QString itemName = item->data(0, Qt::DisplayRole).toString();
|
|
if (itemName == AudioFolderName) return;
|
|
int ret = DVGui::MsgBox(tr("Delete folder ") + item->text(0) + "?", tr("Yes"),
|
|
tr("No"), 1);
|
|
if (ret == 2 || ret == 0) return;
|
|
QTreeWidgetItem *parentItem = item->parent();
|
|
|
|
TFilePath childPath(item->data(1, Qt::DisplayRole).toString().toStdWString());
|
|
TLevelSet *levelSet =
|
|
TApp::instance()->getCurrentScene()->getScene()->getLevelSet();
|
|
levelSet->removeFolder(childPath);
|
|
TApp::instance()->getCurrentScene()->setDirtyFlag(true);
|
|
|
|
parentItem->removeChild(item);
|
|
setCurrentItem(parentItem);
|
|
}
|
|
|
|
//=============================================================================
|
|
//
|
|
// CastBrowser
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#if QT_VERSION >= 0x050500
|
|
CastBrowser::CastBrowser(QWidget *parent, Qt::WindowFlags flags)
|
|
#else
|
|
CastBrowser::CastBrowser(QWidget *parent, Qt::WFlags flags)
|
|
#endif
|
|
: QSplitter(parent)
|
|
, m_treeViewer(0)
|
|
, m_folderName(0)
|
|
, m_itemViewer(0)
|
|
, m_castItems(new CastItems()) {
|
|
// style sheet
|
|
setObjectName("CastBrowser");
|
|
setFrameStyle(QFrame::StyledPanel);
|
|
setStyleSheet("QSplitter::handle {height:4px;}");
|
|
setStyleSheet("#CastBrowser { margin:1px;border:0px }");
|
|
|
|
m_treeViewer = new CastTreeViewer(this);
|
|
m_treeViewer->resize(300, m_treeViewer->size().height());
|
|
|
|
QFrame *box = new QFrame(this);
|
|
box->setFrameStyle(QFrame::StyledPanel);
|
|
QVBoxLayout *boxLayout = new QVBoxLayout(box);
|
|
boxLayout->setMargin(0);
|
|
boxLayout->setSpacing(0);
|
|
|
|
m_folderName = new QLabel("", box);
|
|
m_folderName->setFrameStyle(QFrame::StyledPanel);
|
|
m_folderName->setStyleSheet("border-bottom: 1px solid black");
|
|
m_itemViewer = new DvItemViewer(box, false, true, DvItemViewer::Cast);
|
|
DvItemViewerPanel *viewerPanel = m_itemViewer->getPanel();
|
|
viewerPanel->setMissingTextColor(QColor(200, 0, 0));
|
|
CastSelection *castSelection = new CastSelection();
|
|
castSelection->setBrowser(this);
|
|
viewerPanel->setSelection(castSelection);
|
|
viewerPanel->addColumn(DvItemListModel::FrameCount, 50);
|
|
m_itemViewer->setModel(this);
|
|
|
|
DvItemViewerTitleBar *titleBar = new DvItemViewerTitleBar(m_itemViewer, box);
|
|
// titleBar->hide();
|
|
DvItemViewerButtonBar *buttonBar =
|
|
new DvItemViewerButtonBar(m_itemViewer, box);
|
|
|
|
boxLayout->addWidget(m_folderName);
|
|
boxLayout->addWidget(titleBar);
|
|
boxLayout->addWidget(m_itemViewer);
|
|
boxLayout->addWidget(buttonBar);
|
|
|
|
boxLayout->setAlignment(buttonBar, Qt::AlignBottom);
|
|
box->setLayout(boxLayout);
|
|
|
|
addWidget(m_treeViewer);
|
|
addWidget(box);
|
|
|
|
setStretchFactor(1, 2);
|
|
|
|
TSceneHandle *sceneHandle = TApp::instance()->getCurrentScene();
|
|
|
|
connect(sceneHandle, SIGNAL(sceneSwitched()), this, SLOT(refresh()));
|
|
connect(sceneHandle, SIGNAL(castChanged()), this, SLOT(refresh()));
|
|
|
|
TXsheetHandle *xhseetHandle = TApp::instance()->getCurrentXsheet();
|
|
connect(xhseetHandle, SIGNAL(xsheetChanged()), m_itemViewer, SLOT(update()));
|
|
|
|
connect(buttonBar, SIGNAL(folderUp()), m_treeViewer, SLOT(folderUp()));
|
|
connect(buttonBar, SIGNAL(newFolder()), m_treeViewer, SLOT(newFolder()));
|
|
|
|
connect(m_treeViewer,
|
|
SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
|
|
this, SLOT(folderChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
|
|
|
|
connect(m_treeViewer, SIGNAL(itemMovedToFolder()), this, SLOT(refresh()));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
CastBrowser::~CastBrowser() {}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CastBrowser::sortByDataModel(DataType dataType, bool isDiscendent) {
|
|
if (dataType != getCurrentOrderType()) {
|
|
// Sort by another dataType
|
|
int i;
|
|
for (i = 1; i < m_castItems->getItemCount(); i++) {
|
|
int index = i;
|
|
while (index > 0 && compareData(dataType, index - 1, index) > 0) {
|
|
m_castItems->swapItem(index - 1, index);
|
|
index = index - 1;
|
|
}
|
|
}
|
|
setIsDiscendentOrder(true);
|
|
setOrderType(dataType);
|
|
}
|
|
// Sort by order (invert current)
|
|
if (isDiscendentOrder() != isDiscendent) {
|
|
setIsDiscendentOrder(isDiscendent);
|
|
std::vector<CastItem *> items;
|
|
for (int i = 0; i < m_castItems->getItemCount(); i++)
|
|
items.push_back(m_castItems->getItem(i)->clone());
|
|
m_castItems->clear();
|
|
for (int i = items.size() - 1; i >= 0; i--) m_castItems->addItem(items[i]);
|
|
}
|
|
|
|
m_itemViewer->getPanel()->update();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CastBrowser::folderChanged(QTreeWidgetItem *current,
|
|
QTreeWidgetItem *previous) {
|
|
refresh();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CastBrowser::refresh() {
|
|
if (isHidden()) return;
|
|
refreshData();
|
|
m_itemViewer->refresh();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
/*
|
|
void CastBrowser::getLevels(std::vector<TXshLevel*> &levels) const
|
|
{
|
|
TLevelSet *levelSet = CastTreeViewer::getLevelSet();
|
|
TFilePath folder = m_treeViewer->getCurrentFolder();
|
|
if(folder != TFilePath())
|
|
levelSet->listLevels(levels, folder);
|
|
else
|
|
levelSet->listLevels(levels);
|
|
}
|
|
*/
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CastBrowser::refreshData() {
|
|
m_castItems->clear();
|
|
TLevelSet *levelSet = CastTreeViewer::getLevelSet();
|
|
TFilePath folder = m_treeViewer->getCurrentFolder();
|
|
m_folderName->setText(toQString(folder));
|
|
std::vector<TXshLevel *> levels;
|
|
if (folder != TFilePath())
|
|
levelSet->listLevels(levels, folder);
|
|
else
|
|
levelSet->listLevels(levels);
|
|
|
|
int i;
|
|
for (i = 0; i < (int)levels.size(); i++) {
|
|
if (levels[i]->getSimpleLevel())
|
|
m_castItems->addItem(new LevelCastItem(
|
|
levels[i], m_itemViewer->getPanel()->getIconSize()));
|
|
else if (levels[i]->getPaletteLevel())
|
|
m_castItems->addItem(
|
|
new PaletteCastItem(levels[i]->getPaletteLevel(),
|
|
m_itemViewer->getPanel()->getIconSize()));
|
|
else if (levels[i]->getSoundLevel())
|
|
m_castItems->addItem(new SoundCastItem(
|
|
levels[i]->getSoundLevel(), m_itemViewer->getPanel()->getIconSize()));
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
int CastBrowser::getItemCount() const { return m_castItems->getItemCount(); }
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
QVariant CastBrowser::getItemData(int index, DataType dataType,
|
|
bool isSelected) {
|
|
if (index < 0 || index >= getItemCount()) return QVariant();
|
|
CastItem *item = m_castItems->getItem(index);
|
|
if (dataType == Name)
|
|
return item->getName();
|
|
else if (dataType == Thumbnail)
|
|
return item->getPixmap(isSelected);
|
|
else if (dataType == ToolTip)
|
|
return item->getToolTip();
|
|
else if (dataType == FrameCount)
|
|
return item->getFrameCount();
|
|
else if (dataType == VersionControlStatus) {
|
|
if (!item->exists())
|
|
return VC_Missing;
|
|
else
|
|
return 0; // No version control status displayed
|
|
} else
|
|
return QVariant();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
/*
|
|
TXshSimpleLevel *CastBrowser::getSelectedSimpleLevel() const
|
|
{
|
|
const std::set<int> &indices = m_itemViewer->getSelectedIndices();
|
|
if(indices.empty()) return 0;
|
|
|
|
int index = *indices.begin();
|
|
|
|
std::vector<TXshLevel*> levels;
|
|
getLevels(levels);
|
|
|
|
if(index<0 || index>=(int)levels.size()) return 0;
|
|
TXshLevel*level = levels[index];
|
|
if(!level) return 0;
|
|
else return level->getSimpleLevel();
|
|
}
|
|
*/
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CastBrowser::startDragDrop() {
|
|
TRepetitionGuard guard;
|
|
if (!guard.hasLock()) return;
|
|
|
|
const std::set<int> &indices = m_itemViewer->getSelectedIndices();
|
|
if (indices.empty()) return;
|
|
QDrag *drag = new QDrag(this);
|
|
|
|
QVariant v = getItemData(*indices.begin(), Thumbnail);
|
|
if (v != QVariant()) {
|
|
QPixmap dropThumbnail = v.value<QPixmap>();
|
|
if (!dropThumbnail.isNull()) drag->setPixmap(dropThumbnail);
|
|
}
|
|
drag->setMimeData(m_castItems->getSelectedItems(indices));
|
|
Qt::DropAction dropAction = drag->exec(Qt::CopyAction | Qt::MoveAction);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool CastBrowser::acceptDrop(const QMimeData *data) const {
|
|
return acceptResourceOrFolderDrop(data->urls());
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool CastBrowser::drop(const QMimeData *data) {
|
|
if (!acceptDrop(data)) return false;
|
|
|
|
if (data->hasUrls()) {
|
|
IoCmd::LoadResourceArguments args;
|
|
|
|
foreach (const QUrl &url, data->urls()) {
|
|
TFilePath fp(url.toLocalFile().toStdWString());
|
|
args.resourceDatas.push_back(fp);
|
|
}
|
|
|
|
args.castFolder = m_treeViewer->getCurrentFolder();
|
|
|
|
IoCmd::loadResources(args);
|
|
}
|
|
|
|
refresh();
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
QMenu *CastBrowser::getContextMenu(QWidget *parent, int index) {
|
|
const std::set<int> &indices = m_itemViewer->getSelectedIndices();
|
|
if (indices.empty()) {
|
|
QMenu *menu = new QMenu(parent);
|
|
menu->addAction(CommandManager::instance()->getAction(MI_RemoveUnused));
|
|
return menu;
|
|
}
|
|
// controllo cosa c'e' nella selezione.
|
|
// => audioSelected, vectorLevelSelected, paletteSelected
|
|
std::set<int>::const_iterator it;
|
|
bool audioSelected = false;
|
|
bool paletteSelected = false;
|
|
bool vectorLevelSelected = false;
|
|
bool otherFileSelected = false;
|
|
int levelSelectedCount = 0;
|
|
for (it = indices.begin(); it != indices.end(); ++it) {
|
|
int index = *it;
|
|
if (index < 0 || index >= m_castItems->getItemCount())
|
|
continue; // non dovrebbe mai succedere
|
|
TXshSimpleLevel *sl = m_castItems->getItem(index)->getSimpleLevel();
|
|
if (!sl) {
|
|
if (m_castItems->getItem(index)->getPaletteLevel())
|
|
paletteSelected = true;
|
|
else
|
|
audioSelected = true;
|
|
continue;
|
|
}
|
|
levelSelectedCount++;
|
|
if (sl->getType() == PLI_XSHLEVEL)
|
|
vectorLevelSelected = true;
|
|
else
|
|
otherFileSelected = true;
|
|
}
|
|
QMenu *menu = new QMenu(parent);
|
|
CommandManager *cm = CommandManager::instance();
|
|
|
|
menu->addAction(cm->getAction(MI_LevelSettings));
|
|
|
|
menu->addAction(cm->getAction(MI_ExposeResource));
|
|
menu->addAction(cm->getAction(MI_ShowFolderContents));
|
|
menu->addAction(cm->getAction(MI_ViewFile));
|
|
menu->addAction(cm->getAction(MI_FileInfo));
|
|
if (audioSelected && !paletteSelected && !vectorLevelSelected &&
|
|
!otherFileSelected)
|
|
return menu;
|
|
|
|
// MI_EditLevel solo se e' stato selezionato un singolo diverso da livelli
|
|
// palette a livelli audio
|
|
if (indices.size() == 1 && !audioSelected && !paletteSelected)
|
|
menu->addAction(cm->getAction(MI_EditLevel));
|
|
if (!paletteSelected) menu->addAction(cm->getAction(MI_SaveLevel));
|
|
menu->addSeparator();
|
|
// MI_ConvertToVectors se sono stati selezionati solo livelli non vettoriali
|
|
if (!audioSelected && !paletteSelected && !vectorLevelSelected)
|
|
menu->addAction(cm->getAction(MI_ConvertToVectors));
|
|
menu->addSeparator();
|
|
menu->addAction(cm->getAction(MI_RemoveLevel));
|
|
menu->addAction(cm->getAction(MI_RemoveUnused));
|
|
|
|
return menu;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CastBrowser::expose() {
|
|
std::set<int> selectedIndices =
|
|
m_itemViewer->getPanel()->getSelectedIndices();
|
|
TUndoManager::manager()->beginBlock();
|
|
for (int index : selectedIndices) {
|
|
CastItem *item = m_castItems->getItem(index);
|
|
TXshSimpleLevel *sl = item->getSimpleLevel();
|
|
TXshPaletteLevel *pl = item->getPaletteLevel();
|
|
TXshSoundLevel *soundl = item->getSoundLevel();
|
|
if (sl)
|
|
FilmstripCmd::moveToScene(sl);
|
|
else if (pl)
|
|
FilmstripCmd::moveToScene(pl);
|
|
else if (soundl)
|
|
FilmstripCmd::moveToScene(soundl);
|
|
}
|
|
TUndoManager::manager()->endBlock();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CastBrowser::edit() {
|
|
CastSelection *castSelection =
|
|
dynamic_cast<CastSelection *>(TSelection::getCurrent());
|
|
if (!castSelection) return;
|
|
std::vector<TXshLevel *> levels;
|
|
castSelection->getSelectedLevels(levels);
|
|
if ((int)levels.size() == 1) {
|
|
TXshLevel *l = levels[0];
|
|
if (l) {
|
|
TXshSimpleLevel *sl = l->getSimpleLevel();
|
|
if (sl) {
|
|
TApp::instance()->getCurrentLevel()->setLevel(sl);
|
|
return;
|
|
}
|
|
}
|
|
error(tr("It is not possible to edit the selected file."));
|
|
} else
|
|
error(tr("It is not possible to edit more than one file at once."));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CastBrowser::showFolderContents() {
|
|
int i = 0;
|
|
CastSelection *castSelection =
|
|
dynamic_cast<CastSelection *>(TSelection::getCurrent());
|
|
if (!castSelection) return;
|
|
std::vector<TXshLevel *> levels;
|
|
castSelection->getSelectedLevels(levels);
|
|
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
|
|
TFilePath folderPath, filePath;
|
|
for (i = 0; i < levels.size(); i++) {
|
|
folderPath = levels[i]->getPath().getParentDir();
|
|
filePath = levels[i]->getPath();
|
|
|
|
folderPath = scene->decodeFilePath(folderPath);
|
|
filePath = scene->decodeFilePath(filePath);
|
|
|
|
if (!TSystem::doesExistFileOrLevel(filePath)) {
|
|
error(
|
|
tr("It is not possible to show the folder containing the selected "
|
|
"file, as the file has not been saved yet."));
|
|
} else {
|
|
if (TSystem::isUNC(folderPath))
|
|
QDesktopServices::openUrl(
|
|
QUrl(QString::fromStdWString(folderPath.getWideString())));
|
|
else
|
|
QDesktopServices::openUrl(QUrl::fromLocalFile(
|
|
QString::fromStdWString(folderPath.getWideString())));
|
|
}
|
|
}
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CastBrowser::viewFile() {
|
|
CastSelection *castSelection =
|
|
dynamic_cast<CastSelection *>(TSelection::getCurrent());
|
|
if (!castSelection) return;
|
|
std::vector<TXshLevel *> levels;
|
|
castSelection->getSelectedLevels(levels);
|
|
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
|
|
TFilePath filePath;
|
|
if (levels.empty()) return;
|
|
int i = 0;
|
|
for (i = 0; i < levels.size(); i++) {
|
|
filePath = levels[i]->getPath();
|
|
|
|
filePath = scene->decodeFilePath(filePath);
|
|
if (!TSystem::doesExistFileOrLevel(filePath)) {
|
|
error(
|
|
tr("It is not possible to view the selected file, as the file has "
|
|
"not been saved yet."));
|
|
} else {
|
|
if (!TFileType::isViewable(TFileType::getInfo(filePath))) return;
|
|
|
|
if (Preferences::instance()->isDefaultViewerEnabled() &&
|
|
(filePath.getType() == "mov" || filePath.getType() == "avi" ||
|
|
filePath.getType() == "3gp"))
|
|
QDesktopServices::openUrl(QUrl("file:///" + toQString(filePath)));
|
|
else
|
|
::viewFile(filePath);
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CastBrowser::viewFileInfo() {
|
|
CastSelection *castSelection =
|
|
dynamic_cast<CastSelection *>(TSelection::getCurrent());
|
|
if (!castSelection) return;
|
|
std::vector<TXshLevel *> levels;
|
|
castSelection->getSelectedLevels(levels);
|
|
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
|
|
int i = 0;
|
|
|
|
if (levels.empty()) {
|
|
return;
|
|
} else {
|
|
for (i = 0; i < levels.size(); i++) {
|
|
TFilePath filePath;
|
|
filePath = levels[i]->getPath();
|
|
|
|
filePath = scene->decodeFilePath(filePath);
|
|
if (!TSystem::doesExistFileOrLevel(filePath)) {
|
|
error(
|
|
tr("It is not possible to show the info of the selected file, as "
|
|
"the file has not been saved yet."));
|
|
} else {
|
|
InfoViewer *infoViewer = 0;
|
|
infoViewer = new InfoViewer(this);
|
|
infoViewer->setItem(0, 0, filePath);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//=============================================================================
|
|
|
|
OpenFloatingPanel openCastPane(MI_OpenFileBrowser2, "SceneCast",
|
|
QObject::tr("Scene Cast"));
|