b30b6c
b30b6c
b96f40
#include "scenebrowser.h"
b30b6c
b30b6c
// Tnz6 includes
b30b6c
#include "dvdirtreeview.h"
b96f40
#include "filebrowser.h"
b30b6c
#include "filebrowsermodel.h"
b30b6c
#include "fileselection.h"
b30b6c
#include "filmstripselection.h"
b30b6c
#include "castselection.h"
b30b6c
#include "menubarcommandids.h"
b30b6c
#include "floatingpanelcommand.h"
b30b6c
#include "iocommand.h"
b30b6c
#include "history.h"
b30b6c
#include "tapp.h"
b30b6c
b30b6c
// TnzQt includes
b30b6c
#include "toonzqt/dvdialog.h"
b30b6c
#include "toonzqt/icongenerator.h"
b30b6c
#include "toonzqt/menubarcommand.h"
b30b6c
#include "toonzqt/gutil.h"
b30b6c
#include "toonzqt/trepetitionguard.h"
b30b6c
b30b6c
// TnzLib includes
b30b6c
#include "toonz/tscenehandle.h"
b30b6c
#include "toonz/toonzscene.h"
b30b6c
#include "toonz/txshsimplelevel.h"
b30b6c
#include "toonz/txshsoundlevel.h"
b30b6c
#include "toonz/tproject.h"
b30b6c
#include "toonz/txshlevelhandle.h"
b30b6c
#include "toonz/namebuilder.h"
b30b6c
#include "toonz/toonzimageutils.h"
b30b6c
#include "toonz/preferences.h"
b30b6c
b30b6c
// TnzBase includes
b30b6c
#include "tenv.h"
b30b6c
b30b6c
// TnzCore includes
b30b6c
#include "tsystem.h"
b30b6c
#include "tconvert.h"
b30b6c
#include "tfiletype.h"
b30b6c
#include "tlevel_io.h"
b30b6c
b30b6c
// Qt includes
b30b6c
#include <qdrag></qdrag>
b30b6c
#include <qdragenterevent></qdragenterevent>
b30b6c
#include <qdragmoveevent></qdragmoveevent>
b30b6c
#include <qdropevent></qdropevent>
b30b6c
#include <qdragleaveevent></qdragleaveevent>
b30b6c
#include <qboxlayout></qboxlayout>
b30b6c
#include <qlabel></qlabel>
b30b6c
#include <qbytearray></qbytearray>
b30b6c
#include <qmenu></qmenu>
b30b6c
#include <qdatetime></qdatetime>
b30b6c
#include <qinputdialog></qinputdialog>
b30b6c
#include <qdesktopservices></qdesktopservices>
b30b6c
#include <qdirmodel></qdirmodel>
b30b6c
#include <qdir></qdir>
b30b6c
#include <qpixmap></qpixmap>
b30b6c
#include <qurl></qurl>
b30b6c
#include <qregexp></qregexp>
b30b6c
#include <qscrollbar></qscrollbar>
b30b6c
#include <qmap></qmap>
b30b6c
#include <qpushbutton></qpushbutton>
b30b6c
#include <qpalette></qpalette>
b30b6c
#include <qcheckbox></qcheckbox>
b30b6c
#include <qmutex></qmutex>
b30b6c
#include <qmutexlocker></qmutexlocker>
b30b6c
#include <qmessagebox></qmessagebox>
b30b6c
#include <qapplication></qapplication>
b30b6c
#include <qformlayout></qformlayout>
b30b6c
#include <qmainwindow></qmainwindow>
b30b6c
#include <qlineedit></qlineedit>
b30b6c
#include <qtreewidgetitem></qtreewidgetitem>
b30b6c
#include <qsplitter></qsplitter>
b30b6c
#include <qfilesystemwatcher></qfilesystemwatcher>
b30b6c
b30b6c
// tcg includes
b30b6c
#include "tcg/boost/range_utility.h"
b30b6c
#include "tcg/boost/permuted_range.h"
b30b6c
b30b6c
// boost includes
b30b6c
#include <boost bind.hpp=""></boost>
b30b6c
#include <boost counting_iterator.hpp="" iterator=""></boost>
b30b6c
#include <boost adaptor="" filtered.hpp="" range=""></boost>
b30b6c
#include <boost adaptor="" range="" transformed.hpp=""></boost>
b30b6c
b30b6c
namespace ba = boost::adaptors;
b30b6c
b30b6c
using namespace DVGui;
b30b6c
b30b6c
b30b6c
//=============================================================================
b30b6c
//      Local namespace
b30b6c
//=============================================================================
b30b6c
b30b6c
namespace {
b96f40
std::set<scenebrowser *=""> activePreproductionBoards;</scenebrowser>
b96f40
//std::map<tfilepath, fcdata=""> frameCountMap;</tfilepath,>
b96f40
//QMutex frameCountMapMutex;
b30b6c
QMutex levelFileMutex;
b30b6c
b30b6c
}  // namespace
b30b6c
b30b6c
inline bool isMultipleFrameType(std::string type) {
b30b6c
  return (type == "tlv" || type == "tzl" || type == "pli" || type == "mov" ||
b30b6c
          type == "avi" || type == "3gp" || type == "gif" || type == "mp4" ||
b30b6c
          type == "webm");
b30b6c
}
b30b6c
b30b6c
//=============================================================================
0e2be0
//
0e2be0
// SceneBrowserButtonBar
0e2be0
//
0e2be0
//-----------------------------------------------------------------------------
0e2be0
0e2be0
SceneBrowserButtonBar::SceneBrowserButtonBar(DvItemViewer *itemViewer,
0e2be0
                                             QWidget *parent)
0e2be0
    : QToolBar(parent) {
0e2be0
  setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
0e2be0
  setIconSize(QSize(17, 17));
0e2be0
  setObjectName("buttonBar");
0e2be0
  // buttonBar->setIconSize(QSize(10,10));
0e2be0
0e2be0
  QIcon newFolderIcon = createQIcon("newfolder");
b399ae
  QAction *newScene  = new QAction(newFolderIcon, tr("Add new scene"), this);
b399ae
  newScene->setIconText(tr("Add scene"));
b399ae
  addAction(newScene);
e6161a
  //addSeparator();
0e2be0
b399ae
  connect(newScene, SIGNAL(triggered()), SIGNAL(newScene()));
0e2be0
}
0e2be0
0e2be0
//=============================================================================
b96f40
// SceneBrowser
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b30b6c
#if QT_VERSION >= 0x050500
b96f40
SceneBrowser::SceneBrowser(QWidget *parent, Qt::WindowFlags flags,
b30b6c
                         bool noContextMenu, bool multiSelectionEnabled)
b30b6c
#else
b96f40
SceneBrowser::SceneBrowser(QWidget *parent, Qt::WFlags flags, bool noContextMenu,
b30b6c
                         bool multiSelectionEnabled)
b30b6c
#endif
b30b6c
    : QFrame(parent), m_folderName(0), m_itemViewer(0) {
b30b6c
  // style sheet
b96f40
  setObjectName("SceneBrowser");
b30b6c
  setFrameStyle(QFrame::StyledPanel);
b30b6c
3b274a
  //m_mainSplitter      = new QSplitter(this);
b30b6c
  m_folderTreeView    = new DvDirTreeView(this);
b30b6c
  QFrame *box         = new QFrame(this);
b30b6c
  QLabel *folderLabel = new QLabel(tr("Folder: "), this);
b30b6c
  m_folderName        = new QLineEdit();
b30b6c
  m_itemViewer = new DvItemViewer(box, noContextMenu, multiSelectionEnabled,
b30b6c
                                  DvItemViewer::Browser);
b30b6c
  DvItemViewerTitleBar *titleBar = new DvItemViewerTitleBar(m_itemViewer, box);
0e2be0
  SceneBrowserButtonBar *buttonBar =
0e2be0
      new SceneBrowserButtonBar(m_itemViewer, box);
b30b6c
  DvItemViewerPanel *viewerPanel = m_itemViewer->getPanel();
ec5207
  viewerPanel->setThumbnailsView();
b30b6c
  viewerPanel->addColumn(DvItemListModel::FileType, 50);
b30b6c
  viewerPanel->addColumn(DvItemListModel::FrameCount, 50);
b30b6c
  viewerPanel->addColumn(DvItemListModel::FileSize, 50);
b30b6c
  viewerPanel->addColumn(DvItemListModel::CreationDate, 130);
b30b6c
  viewerPanel->addColumn(DvItemListModel::ModifiedDate, 130);
b30b6c
  if (Preferences::instance()->isSVNEnabled())
b30b6c
    viewerPanel->addColumn(DvItemListModel::VersionControlStatus, 120);
b30b6c
b30b6c
  viewerPanel->setSelection(new FileSelection());
b30b6c
  DVItemViewPlayDelegate *itemViewPlayDelegate =
b30b6c
      new DVItemViewPlayDelegate(viewerPanel);
b30b6c
  viewerPanel->setItemViewPlayDelegate(itemViewPlayDelegate);
b30b6c
3b274a
  //m_mainSplitter->setObjectName("SceneBrowserSplitter");
b30b6c
  m_folderTreeView->setObjectName("DirTreeView");
b30b6c
  box->setObjectName("castFrame");
b30b6c
  box->setFrameStyle(QFrame::StyledPanel);
b30b6c
b30b6c
  m_itemViewer->setModel(this);
b30b6c
b30b6c
  // layout
b30b6c
  QVBoxLayout *mainLayout = new QVBoxLayout();
b30b6c
  mainLayout->setMargin(3);
b30b6c
  mainLayout->setSpacing(2);
b30b6c
  {
b30b6c
    mainLayout->addWidget(buttonBar);
b30b6c
b30b6c
    QHBoxLayout *folderLay = new QHBoxLayout();
b30b6c
    folderLay->setMargin(0);
b30b6c
    folderLay->setSpacing(0);
b30b6c
    {
b30b6c
      folderLay->addWidget(folderLabel, 0);
b30b6c
      folderLay->addWidget(m_folderName, 1);
b30b6c
    }
b30b6c
    mainLayout->addLayout(folderLay, 0);
b30b6c
3b274a
    //m_mainSplitter->addWidget(m_folderTreeView);
b30b6c
    QVBoxLayout *boxLayout = new QVBoxLayout(box);
b30b6c
    boxLayout->setMargin(0);
b30b6c
    boxLayout->setSpacing(0);
b30b6c
    {
b30b6c
      boxLayout->addWidget(titleBar, 0);
b30b6c
      boxLayout->addWidget(m_itemViewer, 1);
b30b6c
    }
3b274a
    //m_mainSplitter->addWidget(box);
3b274a
    mainLayout->addWidget(box, 1);
b30b6c
  }
b30b6c
  setLayout(mainLayout);
b30b6c
3b274a
  //m_mainSplitter->setSizes(QList<int>() << 270 << 500);</int>
b30b6c
b30b6c
  // signal-slot connections
b30b6c
  bool ret = connect(m_folderTreeView, SIGNAL(currentNodeChanged()),
b30b6c
                     itemViewPlayDelegate, SLOT(resetPlayWidget()));
b30b6c
  // if the current forder is changed in the folder tree, then update in the
b30b6c
  // item view
b30b6c
  ret = ret && connect(m_folderTreeView, SIGNAL(currentNodeChanged()), this,
b30b6c
                       SLOT(onTreeFolderChanged()));
b30b6c
b30b6c
  ret = ret && connect(m_itemViewer, SIGNAL(clickedItem(int)), this,
b30b6c
                       SLOT(onClickedItem(int)));
b30b6c
  ret = ret && connect(m_itemViewer, SIGNAL(doubleClickedItem(int)), this,
b30b6c
                       SLOT(onDoubleClickedItem(int)));
b30b6c
  ret =
b30b6c
      ret && connect(m_itemViewer, SIGNAL(selectedItems(const std::set<int> &)),</int>
b30b6c
                     this, SLOT(onSelectedItems(const std::set<int> &)));</int>
b399ae
  ret = ret && connect(buttonBar, SIGNAL(newScene()), this, SLOT(newScene()));
b30b6c
b30b6c
  ret = ret && connect(&m_frameCountReader, SIGNAL(calculatedFrameCount()),
b30b6c
                       m_itemViewer->getPanel(), SLOT(update()));
b30b6c
b30b6c
  QAction *refresh = CommandManager::instance()->getAction(MI_RefreshTree);
b30b6c
  ret = ret && connect(refresh, SIGNAL(triggered()), this, SLOT(refresh()));
b30b6c
  addAction(refresh);
b30b6c
b30b6c
  // Version Control instance connection
b30b6c
  if (Preferences::instance()->isSVNEnabled())
b30b6c
    ret =
b30b6c
        ret && connect(VersionControl::instance(),
b30b6c
                       SIGNAL(commandDone(const QStringList &)), this,
b30b6c
                       SLOT(onVersionControlCommandDone(const QStringList &)));
b30b6c
b30b6c
  // if the folderName is edited, move the current folder accordingly
b30b6c
  ret = ret && connect(m_folderName, SIGNAL(editingFinished()), this,
b30b6c
                       SLOT(onFolderEdited()));
b30b6c
b30b6c
  // folder history
b30b6c
  ret = ret && connect(m_folderTreeView, SIGNAL(currentNodeChanged()), this,
b30b6c
                       SLOT(storeFolderHistory()));
b30b6c
b30b6c
  // check out the update of the current folder.
b30b6c
  // Use MyFileSystemWatcher which is shared by all browsers.
b30b6c
  // Adding and removing paths to the watcher is done in DvDirTreeView.
b30b6c
  ret = ret && connect(MyFileSystemWatcher::instance(),
b30b6c
                       SIGNAL(directoryChanged(const QString &)), this,
b30b6c
                       SLOT(onFileSystemChanged(const QString &)));
225725
  
225725
  // when the scene switched, update the path of the scene location node
225725
  TSceneHandle *sceneHandle = TApp::instance()->getCurrentScene();
225725
  //ret = ret && connect(sceneHandle, SIGNAL(sceneSwitched()), this,
225725
  //                     SLOT(onSceneSwitched()));
225725
  ret = ret && connect(sceneHandle, SIGNAL(nameSceneChanged()), this,
225725
                       SLOT(onSceneSwitched()));
225725
225725
  //onSceneSwitched();
b30b6c
b30b6c
  // store the first item("Root") in the history
b30b6c
  m_indexHistoryList.append(m_folderTreeView->currentIndex());
b30b6c
  m_currentPosition = 0;
b30b6c
b30b6c
  refreshHistoryButtons();
b30b6c
b30b6c
  assert(ret);
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
SceneBrowser::~SceneBrowser() {}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
/*! when the m_folderName is edited, move the current folder accordingly
b30b6c
 */
b96f40
void SceneBrowser::onFolderEdited() {
b30b6c
  TFilePath inputPath(m_folderName->text().toStdWString());
b30b6c
  QModelIndex index = DvDirModel::instance()->getIndexByPath(inputPath);
b30b6c
b30b6c
  // If there is no node matched
b30b6c
  if (!index.isValid()) {
b30b6c
    QMessageBox::warning(this, tr("Open folder failed"),
b30b6c
                         tr("The input folder path was invalid."));
b30b6c
    return;
b30b6c
  }
b30b6c
  m_folderTreeView->collapseAll();
b30b6c
b30b6c
  m_folderTreeView->setCurrentIndex(index);
b30b6c
b30b6c
  // expand the folder tree
b30b6c
  QModelIndex tmpIndex = index;
b30b6c
  while (tmpIndex.isValid()) {
b30b6c
    m_folderTreeView->expand(tmpIndex);
b30b6c
    tmpIndex = tmpIndex.parent();
b30b6c
  }
b30b6c
b30b6c
  m_folderTreeView->scrollTo(index);
b30b6c
  m_folderTreeView->update();
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::storeFolderHistory() {
b30b6c
  QModelIndex currentModelIndex = m_folderTreeView->currentIndex();
b30b6c
b30b6c
  if (!currentModelIndex.isValid()) return;
b30b6c
b30b6c
  if (m_indexHistoryList[m_currentPosition] == currentModelIndex) return;
b30b6c
b30b6c
  // If there is no next history item, then create it
b30b6c
  if (m_currentPosition == m_indexHistoryList.size() - 1) {
b30b6c
    m_indexHistoryList << currentModelIndex;
b30b6c
    m_currentPosition++;
b30b6c
  }
b30b6c
  // If the next hitory item is the same as the current one, just move to it
b30b6c
  else if (m_indexHistoryList[m_currentPosition + 1] == currentModelIndex) {
b30b6c
    m_currentPosition++;
b30b6c
  }
b30b6c
  // If the next history item is different from the current one, then replace
b30b6c
  // with the new one
b30b6c
  else {
b30b6c
    int size = m_indexHistoryList.size();
b30b6c
    // remove the old history items
b30b6c
    for (int i = m_currentPosition + 1; i < size; i++)
b30b6c
      m_indexHistoryList.removeLast();
b30b6c
    m_indexHistoryList << currentModelIndex;
b30b6c
    m_currentPosition++;
b30b6c
  }
b30b6c
  refreshHistoryButtons();
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::refreshHistoryButtons() {
b30b6c
  emit historyChanged((m_currentPosition != 0),
b30b6c
                      (m_currentPosition != m_indexHistoryList.size() - 1));
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::onBackButtonPushed() {
b30b6c
  if (m_currentPosition == 0) return;
b30b6c
  m_currentPosition--;
b30b6c
  QModelIndex currentIndex = m_indexHistoryList[m_currentPosition];
b30b6c
  m_folderTreeView->setCurrentIndex(currentIndex);
b30b6c
  m_folderTreeView->collapseAll();
b30b6c
  while (currentIndex.isValid()) {
b30b6c
    currentIndex = currentIndex.parent();
b30b6c
    m_folderTreeView->expand(currentIndex);
b30b6c
  }
b30b6c
  m_folderTreeView->update();
b30b6c
b30b6c
  refreshHistoryButtons();
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::onFwdButtonPushed() {
b30b6c
  if (m_currentPosition >= m_indexHistoryList.size() - 1) return;
b30b6c
  m_currentPosition++;
b30b6c
  QModelIndex currentIndex = m_indexHistoryList[m_currentPosition];
b30b6c
  m_folderTreeView->setCurrentIndex(currentIndex);
b30b6c
  m_folderTreeView->collapseAll();
b30b6c
  while (currentIndex.isValid()) {
b30b6c
    currentIndex = currentIndex.parent();
b30b6c
    m_folderTreeView->expand(currentIndex);
b30b6c
  }
b30b6c
  m_folderTreeView->update();
b30b6c
b30b6c
  refreshHistoryButtons();
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
/*! clear the history when the tree date is replaced
b30b6c
 */
b96f40
void SceneBrowser::clearHistory() {
b30b6c
  int size = m_indexHistoryList.size();
b30b6c
  // leave the last item
b30b6c
  for (int i = 1; i < size; i++) m_indexHistoryList.removeLast();
b30b6c
  m_currentPosition = 0;
b30b6c
  refreshHistoryButtons();
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
/*! update the current folder when changes detected from QFileSystemWatcher
b30b6c
 */
b96f40
void SceneBrowser::onFileSystemChanged(const QString &folderPath) {
b30b6c
  if (folderPath != m_folder.getQString()) return;
b30b6c
  // changes may create/delete of folder, so update the DvDirModel
b30b6c
  QModelIndex parentFolderIndex = m_folderTreeView->currentIndex();
b30b6c
  DvDirModel::instance()->refresh(parentFolderIndex);
b30b6c
b30b6c
  refreshCurrentFolderItems();
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::sortByDataModel(DataType dataType, bool isDiscendent) {
b30b6c
  struct locals {
b96f40
    static inline bool itemLess(int aIdx, int bIdx, SceneBrowser &fb,
b30b6c
                                DataType dataType) {
b30b6c
      return (fb.compareData(dataType, aIdx, bIdx) > 0);
b30b6c
    }
b30b6c
b30b6c
    static inline bool indexLess(int aIdx, int bIdx,
b30b6c
                                 const std::vector<int> &vec) {</int>
b30b6c
      return (vec[aIdx] < vec[bIdx]);
b30b6c
    }
b30b6c
b30b6c
    static inline int complement(int val, int max) {
b30b6c
      return (assert(0 <= val && val <= max), max - val);
b30b6c
    }
b30b6c
  };  // locals
b30b6c
b30b6c
  if (dataType != getCurrentOrderType()) {
b30b6c
    // Build the permutation table
b30b6c
    std::vector<int> new2OldIdx(</int>
b30b6c
        boost::make_counting_iterator(0),
b30b6c
        boost::make_counting_iterator(int(m_items.size())));
b30b6c
b30b6c
    std::stable_sort(
b30b6c
        new2OldIdx.begin(), new2OldIdx.end(),
b30b6c
        boost::bind(locals::itemLess, _1, _2, boost::ref(*this), dataType));
b30b6c
b30b6c
    // Use the renumbering table to permutate elements
b30b6c
    std::vector<item>(</item>
b30b6c
        boost::make_permutation_iterator(m_items.begin(), new2OldIdx.begin()),
b30b6c
        boost::make_permutation_iterator(m_items.begin(), new2OldIdx.end()))
b30b6c
        .swap(m_items);
b30b6c
b30b6c
    // Use the permutation table to update current file selection, if any
b30b6c
    FileSelection *fs =
b30b6c
        static_cast<fileselection *="">(m_itemViewer->getPanel()->getSelection());</fileselection>
b30b6c
b30b6c
    if (!fs->isEmpty()) {
b30b6c
      std::vector<int> old2NewIdx(</int>
b30b6c
          boost::make_counting_iterator(0),
b30b6c
          boost::make_counting_iterator(int(m_items.size())));
b30b6c
b30b6c
      std::sort(old2NewIdx.begin(), old2NewIdx.end(),
b30b6c
                boost::bind(locals::indexLess, _1, _2, boost::ref(new2OldIdx)));
b30b6c
b30b6c
      std::vector<int> newSelectedIndices;</int>
b30b6c
      tcg::substitute(
b30b6c
          newSelectedIndices,
b30b6c
          tcg::permuted_range(old2NewIdx, fs->getSelectedIndices() |
b30b6c
                                              ba::filtered(boost::bind(
b30b6c
                                                  std::less<int>(), _1,</int>
b30b6c
                                                  int(old2NewIdx.size())))));
b30b6c
b30b6c
      fs->select(!newSelectedIndices.empty() ? &newSelectedIndices.front() : 0,
b30b6c
                 int(newSelectedIndices.size()));
b30b6c
    }
b30b6c
b30b6c
    setIsDiscendentOrder(true);
b30b6c
    setOrderType(dataType);
b30b6c
  }
b30b6c
b30b6c
  // Reverse lists if necessary
b30b6c
  if (isDiscendentOrder() != isDiscendent) {
b30b6c
    std::reverse(m_items.begin(), m_items.end());
b30b6c
b30b6c
    // Reverse file selection, if any
b30b6c
    FileSelection *fs =
b30b6c
        dynamic_cast<fileselection *="">(m_itemViewer->getPanel()->getSelection());</fileselection>
b30b6c
b30b6c
    if (!fs->isEmpty()) {
b30b6c
      int iCount = int(m_items.size()), lastIdx = iCount - 1;
b30b6c
b30b6c
      std::vector<int> newSelectedIndices;</int>
b30b6c
      tcg::substitute(
b30b6c
          newSelectedIndices,
b30b6c
          fs->getSelectedIndices() |
b30b6c
              ba::filtered(boost::bind(std::less<int>(), _1, iCount)) |</int>
b30b6c
              ba::transformed(boost::bind(locals::complement, _1, lastIdx)));
b30b6c
b30b6c
      fs->select(!newSelectedIndices.empty() ? &newSelectedIndices.front() : 0,
b30b6c
                 int(newSelectedIndices.size()));
b30b6c
    }
b30b6c
b30b6c
    setIsDiscendentOrder(isDiscendent);
b30b6c
  }
b30b6c
b30b6c
  m_itemViewer->getPanel()->update();
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::setFilterTypes(const QStringList &types) { m_filter = types; }
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::addFilterType(const QString &type) {
b30b6c
  if (!m_filter.contains(type)) m_filter.push_back(type);
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::removeFilterType(const QString &type) {
b30b6c
  m_filter.removeAll(type);
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::refreshCurrentFolderItems() {
b30b6c
  m_items.clear();
b30b6c
b30b6c
  // put the parent directory item
bc4a05
  //TFilePath parentFp = m_folder.getParentDir();
bc4a05
  //if (parentFp != TFilePath("") && parentFp != m_folder)
bc4a05
  //  m_items.push_back(Item(parentFp, true, false));
b30b6c
b30b6c
  // register the file items
b30b6c
  if (m_folder != TFilePath()) {
b30b6c
    TFilePathSet files;
b30b6c
    TFilePathSet all_files;  // for updating m_multiFileItemMap
b30b6c
b30b6c
    TFileStatus fpStatus(m_folder);
b30b6c
    // if the item is link, then set the link target of it
b30b6c
    if (fpStatus.isLink()) {
b30b6c
      QFileInfo info(toQString(m_folder));
b30b6c
      setFolder(TFilePath(info.symLinkTarget().toStdWString()));
b30b6c
      return;
b30b6c
    }
b30b6c
    if (fpStatus.doesExist() && fpStatus.isDirectory() &&
b30b6c
        fpStatus.isReadable()) {
b30b6c
      try {
b30b6c
        TSystem::readDirectory(files, all_files, m_folder);
b30b6c
      } catch (...) {
b30b6c
      }
b30b6c
    }
b30b6c
    TFilePathSet::iterator it;
b30b6c
    for (it = files.begin(); it != files.end(); ++it) {
b30b6c
      // skip the plt file (Palette file for TOONZ 4.6 and earlier)
b30b6c
      if (it->getType() == "plt") continue;
b30b6c
b30b6c
      // filter the file
b30b6c
      else if (m_filter.isEmpty()) {
b30b6c
        if (it->getType() != "tnz" && it->getType() != "scr" &&
b30b6c
            it->getType() != "tnzbat" && it->getType() != "mpath" &&
b30b6c
            it->getType() != "curve" && it->getType() != "tpl" &&
b30b6c
            TFileType::getInfo(*it) == TFileType::UNKNOW_FILE)
b30b6c
          continue;
bc4a05
      } else if (m_filter.contains(QString::fromStdString(it->getType())))
b30b6c
        continue;
b30b6c
      // store the filtered file paths
b30b6c
      m_items.push_back(Item(*it));
b30b6c
    }
b30b6c
b30b6c
    // update the m_multiFileItemMap
b30b6c
    m_multiFileItemMap.clear();
b30b6c
b30b6c
    for (it = all_files.begin(); it != all_files.end(); it++) {
b30b6c
      TFrameId tFrameId;
b96f40
      tFrameId = it->getFrame();
b30b6c
      TFilePath levelName(it->getLevelName());
b30b6c
b30b6c
      if (levelName.isLevelName()) {
b30b6c
        Item &levelItem = m_multiFileItemMap[levelName];
b30b6c
b30b6c
        // TODO:
b30b6c
        // とりあえず残すが、FileInfoの取得に時間がかかるようならオプション化も検討
b30b6c
        // 2015/12/28 shun_iwasawa
b30b6c
        QFileInfo fileInfo(QString::fromStdWString(it->getWideString()));
b30b6c
        // Update level infos
b30b6c
        if (levelItem.m_creationDate.isNull() ||
b30b6c
            (fileInfo.created() < levelItem.m_creationDate))
b30b6c
          levelItem.m_creationDate = fileInfo.created();
b30b6c
        if (levelItem.m_modifiedDate.isNull() ||
b30b6c
            (fileInfo.lastModified() > levelItem.m_modifiedDate))
b30b6c
          levelItem.m_modifiedDate = fileInfo.lastModified();
b30b6c
        levelItem.m_fileSize += fileInfo.size();
b30b6c
b30b6c
        // store frameId
b30b6c
        levelItem.m_frameIds.push_back(tFrameId);
b30b6c
b30b6c
        levelItem.m_frameCount++;
b30b6c
      }
b30b6c
    }
b30b6c
  }
b30b6c
b30b6c
  // Set Missing Version Control Items
b30b6c
  int missingItemCount          = 0;
b30b6c
  DvDirVersionControlNode *node = dynamic_cast<dvdirversioncontrolnode *="">(</dvdirversioncontrolnode>
b30b6c
      m_folderTreeView->getCurrentNode());
b30b6c
  if (node) {
b30b6c
    QList<tfilepath> list = node->getMissingFiles();</tfilepath>
b30b6c
    missingItemCount      = list.size();
b30b6c
    for (int i = 0; i < missingItemCount; i++)
b30b6c
      m_items.push_back(Item(list.at(i)));
b30b6c
  }
b30b6c
b30b6c
  // Refresh Data (fill Item field)
b30b6c
  refreshData();
b30b6c
b30b6c
  // If I added some missing items I need to sort items.
b30b6c
  if (missingItemCount > 0) {
b30b6c
    DataType currentDataType = getCurrentOrderType();
b30b6c
    int i;
b30b6c
    for (i = 1; i < m_items.size(); i++) {
b30b6c
      int index = i;
b30b6c
      while (index > 0 && compareData(currentDataType, index - 1, index) > 0) {
b30b6c
        std::swap(m_items[index - 1], m_items[index]);
b30b6c
        index = index - 1;
b30b6c
      }
b30b6c
    }
b30b6c
  }
b30b6c
  // update the ordering rules
b30b6c
  bool discendentOrder     = isDiscendentOrder();
b30b6c
  DataType currentDataType = getCurrentOrderType();
b30b6c
  setOrderType(Name);
b30b6c
  setIsDiscendentOrder(true);
b30b6c
  sortByDataModel(currentDataType, discendentOrder);
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::setFolder(const TFilePath &fp, bool expandNode,
b30b6c
                            bool forceUpdate) {
b30b6c
  if (fp == m_folder && !forceUpdate) return;
b30b6c
b30b6c
  // set the current folder path
b30b6c
  m_folder        = fp;
b30b6c
  m_dayDateString = "";
b30b6c
  // set the folder name
b30b6c
  if (fp == TFilePath())
b30b6c
    m_folderName->setText("");
b30b6c
  else
b30b6c
    m_folderName->setText(toQString(fp));
b30b6c
b30b6c
  refreshCurrentFolderItems();
b30b6c
b30b6c
  if (!TFileStatus(fp).isLink())
b30b6c
    m_folderTreeView->setCurrentNode(fp, expandNode);
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
/*! process when inputting the folder which is not regitered in the folder tree
b30b6c
   (e.g. UNC path in Windows)
b30b6c
 */
b96f40
void SceneBrowser::setUnregisteredFolder(const TFilePath &fp) {
b30b6c
  if (fp != TFilePath()) {
b30b6c
    TFileStatus fpStatus(fp);
b30b6c
    // if the item is link, then set the link target of it
b30b6c
    if (fpStatus.isLink()) {
b30b6c
      QFileInfo info(toQString(fp));
b30b6c
      setFolder(TFilePath(info.symLinkTarget().toStdWString()));
b30b6c
      return;
b30b6c
    }
b30b6c
b30b6c
    // get both the folder & file list by readDirectory and
b30b6c
    // readDirectory_Dir_ReadExe
b30b6c
    TFilePathSet folders;
b30b6c
    TFilePathSet files;
b30b6c
    // for updating m_multiFileItemMap
b30b6c
    TFilePathSet all_files;
b30b6c
b30b6c
    if (fpStatus.doesExist() && fpStatus.isDirectory() &&
b30b6c
        fpStatus.isReadable()) {
b30b6c
      try {
b30b6c
        TSystem::readDirectory(files, all_files, fp);
b30b6c
        TSystem::readDirectory_Dir_ReadExe(folders, fp);
b30b6c
      } catch (...) {
b30b6c
      }
b30b6c
    }
b30b6c
b30b6c
    TFilePathSet::iterator it;
b30b6c
b30b6c
    // register all folder items
b30b6c
    for (it = folders.begin(); it != folders.end(); ++it) {
b30b6c
      if (TFileStatus(*it).isLink())
b30b6c
        m_items.push_back(Item(*it, true, true));
b30b6c
      else
b30b6c
        m_items.push_back(Item(*it, true, false));
b30b6c
    }
b30b6c
b30b6c
    for (it = files.begin(); it != files.end(); ++it) {
b30b6c
      // skip the plt file (Palette file for TOONZ 4.6 and earlier)
b30b6c
      if (it->getType() == "plt") continue;
b30b6c
b30b6c
      // filtering
b30b6c
      else if (m_filter.isEmpty()) {
b30b6c
        if (it->getType() != "tnz" && it->getType() != "scr" &&
b30b6c
            it->getType() != "tnzbat" && it->getType() != "mpath" &&
b30b6c
            it->getType() != "curve" && it->getType() != "tpl" &&
b30b6c
            TFileType::getInfo(*it) == TFileType::UNKNOW_FILE)
b30b6c
          continue;
bc4a05
      } else if (m_filter.contains(QString::fromStdString(it->getType())))
b30b6c
        continue;
b30b6c
b30b6c
      m_items.push_back(Item(*it));
b30b6c
    }
b30b6c
b30b6c
    // update the m_multiFileItemMap
b30b6c
    m_multiFileItemMap.clear();
b30b6c
    for (it = all_files.begin(); it != all_files.end(); it++) {
b30b6c
      TFilePath levelName(it->getLevelName());
b30b6c
      if (levelName.isLevelName()) {
b30b6c
        Item &levelItem = m_multiFileItemMap[levelName];
b30b6c
        levelItem.m_frameIds.push_back(it->getFrame());
b30b6c
        levelItem.m_frameCount++;
b30b6c
      }
b30b6c
    }
b30b6c
  }
b30b6c
  // for all items in the folder, retrieve the file names(m_name) from the
b30b6c
  // paths(m_path)
b30b6c
  refreshData();
b30b6c
b30b6c
  // update the ordering rules
b30b6c
  bool discendentOrder     = isDiscendentOrder();
b30b6c
  DataType currentDataType = getCurrentOrderType();
b30b6c
  setOrderType(Name);
b30b6c
  setIsDiscendentOrder(true);
b30b6c
  sortByDataModel(currentDataType, discendentOrder);
b30b6c
b30b6c
  m_itemViewer->repaint();
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::setHistoryDay(std::string dayDateString) {
b30b6c
  m_folder                = TFilePath();
b30b6c
  m_dayDateString         = dayDateString;
b30b6c
  const History::Day *day = History::instance()->getDay(dayDateString);
b30b6c
  m_items.clear();
b30b6c
  if (day == 0) {
b30b6c
    m_folderName->setText("");
b30b6c
  } else {
b30b6c
    m_folderName->setText(QString::fromStdString(dayDateString));
b30b6c
    std::vector<tfilepath> files;</tfilepath>
b30b6c
    day->getFiles(files);
b30b6c
    std::vector<tfilepath>::iterator it;</tfilepath>
b30b6c
    for (it = files.begin(); it != files.end(); ++it)
b30b6c
      m_items.push_back(Item(*it));
b30b6c
  }
b30b6c
  refreshData();
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
/*! for all items in the folder, retrieve the file names(m_name) from the
b30b6c
 * paths(m_path)
b30b6c
 */
b96f40
void SceneBrowser::refreshData() {
b30b6c
  std::vector<item>::iterator it;</item>
b30b6c
  for (it = m_items.begin(); it != m_items.end(); ++it) {
b30b6c
    if (it->m_name == QString(""))
b30b6c
      it->m_name = toQString(it->m_path.withoutParentDir());
b30b6c
  }
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
int SceneBrowser::getItemCount() const { return m_items.size(); }
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::readInfo(Item &item) {
b30b6c
  TFilePath fp = item.m_path;
b30b6c
  QFileInfo info(toQString(fp));
b30b6c
  if (info.exists()) {
b30b6c
    item.m_creationDate = info.created();
b30b6c
    item.m_modifiedDate = info.lastModified();
b30b6c
    item.m_fileType     = info.suffix();
b30b6c
    item.m_fileSize     = info.size();
b30b6c
    if (fp.getType() == "tnz") {
b30b6c
      ToonzScene scene;
b30b6c
      try {
b30b6c
        item.m_frameCount = scene.loadFrameCount(fp);
b30b6c
      } catch (...) {
b30b6c
      }
b30b6c
    } else
b30b6c
      readFrameCount(item);
b30b6c
b30b6c
    item.m_validInfo = true;
b30b6c
  } else if (fp.isLevelName())  // for levels johndoe..tif etc.
b30b6c
  {
b30b6c
    try {
b30b6c
      // Find this level's item
b30b6c
      std::map<tfilepath, item="">::iterator it =</tfilepath,>
b30b6c
          m_multiFileItemMap.find(TFilePath(item.m_path.getLevelName()));
b30b6c
      if (it == m_multiFileItemMap.end()) throw "";
b30b6c
b30b6c
      item.m_creationDate = it->second.m_creationDate;
b30b6c
      item.m_modifiedDate = it->second.m_modifiedDate;
b30b6c
      item.m_fileType     = it->second.m_fileType;
b30b6c
      item.m_fileSize     = it->second.m_fileSize;
b30b6c
      item.m_frameCount   = it->second.m_frameCount;
b30b6c
      item.m_validInfo    = true;
b30b6c
b30b6c
      // keep the list of frameIds at the first time and try to reuse it.
b30b6c
      item.m_frameIds = it->second.m_frameIds;
b30b6c
b30b6c
      // The old way
b30b6c
      /*TLevelReaderP lr(fp);
b30b6c
item.m_frameCount = lr->loadInfo()->getFrameCount();
b30b6c
item.m_creationDate = QDateTime();
b30b6c
item.m_modifiedDate = QDateTime();
b30b6c
item.m_fileSize = -1;
b30b6c
item.m_validInfo = true;*/
b30b6c
    } catch (...) {
b30b6c
      item.m_frameCount = 0;
b30b6c
    }
b30b6c
  }
b30b6c
b30b6c
  item.m_validInfo = true;
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b30b6c
//! Frame count needs a special access function for viewable types - for they
b30b6c
//! are
b30b6c
//! calculated by using a dedicated thread and therefore cannot be simply
b30b6c
//! classified as *valid* or *invalid* infos...
b96f40
void SceneBrowser::readFrameCount(Item &item) {
b30b6c
  if (TFileType::isViewable(TFileType::getInfo(item.m_path))) {
b30b6c
    if (isMultipleFrameType(item.m_path.getType()))
b30b6c
      item.m_frameCount = m_frameCountReader.getFrameCount(item.m_path);
b30b6c
    else
b30b6c
      item.m_frameCount = 1;
b30b6c
  } else
b30b6c
    item.m_frameCount = 0;
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
QVariant SceneBrowser::getItemData(int index, DataType dataType,
b30b6c
                                  bool isSelected) {
b30b6c
  if (index < 0 || index >= (int)m_items.size()) return QVariant();
b30b6c
  Item &item = m_items[index];
b30b6c
  if (dataType == Name) {
b30b6c
    // show two dots( ".." ) for the paret directory item
b30b6c
    if (item.m_path == m_folder.getParentDir())
b30b6c
      return QString("..");
b30b6c
    else
b30b6c
      return item.m_name;
b30b6c
  } else if (dataType == Thumbnail) {
b30b6c
    QSize iconSize = m_itemViewer->getPanel()->getIconSize();
b30b6c
    // parent folder icons
b30b6c
    if (item.m_path == m_folder.getParentDir()) {
b30b6c
      static QPixmap folderUpPixmap(svgToPixmap(":Resources/folderup_icon.svg",
b30b6c
                                                iconSize, Qt::KeepAspectRatio));
b30b6c
      return folderUpPixmap;
b30b6c
    }
b30b6c
    // folder icons
b30b6c
    else if (item.m_isFolder) {
b30b6c
      if (item.m_isLink) {
b30b6c
        static QPixmap linkIcon(svgToPixmap(":Resources/link_icon.svg",
b30b6c
                                            iconSize, Qt::KeepAspectRatio));
b30b6c
        return linkIcon;
b30b6c
      } else {
b30b6c
        static QPixmap folderIcon(svgToPixmap(":Resources/folder_icon.svg",
b30b6c
                                              iconSize, Qt::KeepAspectRatio));
b30b6c
        return folderIcon;
b30b6c
      }
b30b6c
    }
b30b6c
b30b6c
    QPixmap pixmap = IconGenerator::instance()->getIcon(item.m_path);
b30b6c
    if (pixmap.isNull()) {
b30b6c
      pixmap = QPixmap(iconSize);
b30b6c
      pixmap.fill(Qt::white);
b30b6c
    }
b30b6c
    return scalePixmapKeepingAspectRatio(pixmap, iconSize, Qt::transparent);
b30b6c
  } else if (dataType == Icon)
b30b6c
    return QVariant();
b30b6c
  else if (dataType == ToolTip || dataType == FullPath)
b30b6c
    return QString::fromStdWString(item.m_path.getWideString());
b30b6c
b30b6c
  else if (dataType == IsFolder) {
b30b6c
    return item.m_isFolder;
b30b6c
  }
b30b6c
b30b6c
  if (!item.m_validInfo) {
b30b6c
    readInfo(item);
b30b6c
    if (!item.m_validInfo) return QVariant();
b30b6c
  }
b30b6c
b30b6c
  if (dataType == CreationDate) return item.m_creationDate;
b30b6c
  if (dataType == ModifiedDate) return item.m_modifiedDate;
b30b6c
  if (dataType == FileType) {
b30b6c
    if (item.m_isLink)
b30b6c
      return QString("<link>");
b30b6c
    else if (item.m_isFolder)
b30b6c
      return QString("<dir>");</dir>
b30b6c
    else
b30b6c
      return QString::fromStdString(item.m_path.getType()).toUpper();
b30b6c
  } else if (dataType == FileSize)
b30b6c
    return (item.m_fileSize == -1) ? QVariant() : item.m_fileSize;
b30b6c
  else if (dataType == FrameCount) {
b30b6c
    if (item.m_frameCount == -1) readFrameCount(item);
b30b6c
    return item.m_frameCount;
b30b6c
  } else if (dataType == PlayAvailable) {
b30b6c
    std::string type = item.m_path.getType();
b30b6c
    if (item.m_frameCount > 1 && type != "tzp" && type != "tzu") return true;
b30b6c
    return false;
b30b6c
  } else if (dataType == VersionControlStatus) {
b30b6c
    return getItemVersionControlStatus(item);
b30b6c
  } else
b30b6c
    return QVariant();
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
bool SceneBrowser::isSceneItem(int index) const {
b30b6c
  return 0 <= index && index < (int)m_items.size() &&
b30b6c
         m_items[index].m_path.getType() == "tnz";
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
bool SceneBrowser::canRenameItem(int index) const {
b30b6c
  // se sto guardando la history non posso rinominare nulla
b30b6c
  if (getFolder() == TFilePath()) return false;
b30b6c
  if (index < 0 || index >= (int)m_items.size()) return false;
b30b6c
  // for now, disable rename for folders
b30b6c
  if (m_items[index].m_isFolder) return false;
b30b6c
  TFilePath fp = m_items[index].m_path;
b30b6c
  return TFileStatus(fp).doesExist();
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
int SceneBrowser::findIndexWithPath(TFilePath path) {
b30b6c
  int i;
b30b6c
  for (i = 0; i < m_items.size(); i++)
b30b6c
    if (m_items[i].m_path == path) return i;
b30b6c
  return -1;
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::renameItem(int index, const QString &newName) {
b30b6c
  if (getFolder() == TFilePath()) return;
b30b6c
  if (index < 0 || index >= (int)m_items.size()) return;
b30b6c
b30b6c
  TFilePath fp    = m_items[index].m_path;
b30b6c
  TFilePath newFp = fp;
b30b6c
  if (renameFile(newFp, newName)) {
b30b6c
    m_items[index].m_name = QString::fromStdWString(newFp.getLevelNameW());
b30b6c
    m_items[index].m_path = newFp;
b30b6c
b30b6c
    // ho rinominato anche la palette devo aggiornarla.
b30b6c
    if (newFp.getType() == "tlv" || newFp.getType() == "tzp" ||
b30b6c
        newFp.getType() == "tzu") {
b30b6c
      const char *type = (newFp.getType() == "tlv") ? "tpl" : "plt";
b30b6c
      int paletteIndex = findIndexWithPath(fp.withNoFrame().withType(type));
b30b6c
      if (paletteIndex >= 0) {
b30b6c
        TFilePath palettePath = newFp.withNoFrame().withType(type);
b30b6c
        m_items[paletteIndex].m_name =
b30b6c
            QString::fromStdWString(palettePath.getLevelNameW());
b30b6c
        m_items[paletteIndex].m_path = palettePath;
b30b6c
      }
b30b6c
    }
b30b6c
    m_itemViewer->update();
b30b6c
b30b6c
    if (fp.getType() == "tnz") {
b30b6c
      // ho cambiato il folder _files. Devo aggiornare il folder che lo contiene
b30b6c
      // nel tree view
b30b6c
      QModelIndex index = m_folderTreeView->currentIndex();
b30b6c
      if (index.isValid()) {
b30b6c
        DvDirModel::instance()->refresh(index);
b30b6c
        // m_folderTreeView->getDvDirModel()->refresh(index);
b30b6c
        m_folderTreeView->update();
b30b6c
      }
b30b6c
    }
b30b6c
  }
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
bool SceneBrowser::renameFile(TFilePath &fp, QString newName) {
b30b6c
  if (isSpaceString(newName)) return true;
b30b6c
b30b6c
  TFilePath newFp(newName.toStdWString());
b30b6c
  if (newFp.getType() != "" && newFp.getType() != fp.getType()) {
b30b6c
    DVGui::error(tr("Can't change file extension"));
b30b6c
    return false;
b30b6c
  }
b30b6c
  if (newFp.getType() == "") newFp = newFp.withType(fp.getType());
b30b6c
  if (newFp.getFrame() != TFrameId::EMPTY_FRAME &&
b30b6c
      newFp.getFrame() != TFrameId::NO_FRAME) {
b30b6c
    DVGui::error(tr("Can't set a drawing number"));
b30b6c
    return false;
b30b6c
  }
b30b6c
  if (newFp.getDots() != fp.getDots()) {
b30b6c
    if (fp.getDots() == ".")
b30b6c
      newFp = newFp.withNoFrame();
b30b6c
    else if (fp.getDots() == "..")
b30b6c
      newFp = newFp.withFrame(TFrameId::EMPTY_FRAME);
b30b6c
  }
b30b6c
  newFp = newFp.withParentDir(fp.getParentDir());
b30b6c
b30b6c
  // se sono uguali non devo rinominare nulla
b30b6c
  if (newFp == fp) return false;
b30b6c
b30b6c
  if (TSystem::doesExistFileOrLevel(newFp)) {
b30b6c
    DVGui::error(tr("Can't rename. File already exists: ") + toQString(newFp));
b30b6c
    return false;
b30b6c
  }
b30b6c
b30b6c
  try {
b30b6c
    TSystem::renameFileOrLevel_throw(newFp, fp, true);
b30b6c
    IconGenerator::instance()->remove(fp);
b30b6c
    if (fp.getType() == "tnz") {
b30b6c
      /* TFilePath folder = fp.getParentDir() + (fp.getName() + "_files");
b30b6c
TFilePath newFolder = newFp.getParentDir() + (newFp.getName() + "_files");
b30b6c
TSystem::renameFile(newFolder, folder);
b30b6c
*/
b30b6c
      TFilePath sceneIconFp    = ToonzScene::getIconPath(fp);
b30b6c
      TFilePath sceneIconNewFp = ToonzScene::getIconPath(newFp);
b30b6c
      if (TFileStatus(sceneIconFp).doesExist()) {
b30b6c
        if (TFileStatus(sceneIconNewFp).doesExist())
b30b6c
          TSystem::deleteFile(sceneIconNewFp);
b30b6c
        TSystem::renameFile(sceneIconNewFp, sceneIconFp);
b30b6c
      }
b30b6c
    }
b30b6c
b30b6c
  } catch (...) {
b30b6c
    DVGui::error(tr("Couldn't rename ") + toQString(fp) + " to " +
b30b6c
                 toQString(newFp));
b30b6c
    return false;
b30b6c
  }
b30b6c
b30b6c
  fp = newFp;
b30b6c
  return true;
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
QMenu *SceneBrowser::getContextMenu(QWidget *parent, int index) {
b30b6c
  auto isOldLevelType = [](TFilePath &path) -> bool {
b30b6c
    return path.getType() == "tzp" || path.getType() == "tzu";
b30b6c
  };
b30b6c
b30b6c
  bool ret = true;
b30b6c
b30b6c
  // TODO: spostare in questa classe anche la definizione delle azioni?
b30b6c
  FileSelection *fs =
b30b6c
      dynamic_cast<fileselection *="">(m_itemViewer->getPanel()->getSelection());</fileselection>
b30b6c
  if (!fs) return 0;
b30b6c
  std::vector<tfilepath> files;</tfilepath>
b30b6c
  fs->getSelectedFiles(files);
b30b6c
b30b6c
  QMenu *menu        = new QMenu(parent);
b30b6c
  CommandManager *cm = CommandManager::instance();
b30b6c
b30b6c
  if (files.empty()) {
b30b6c
    menu->addAction(cm->getAction(MI_ShowFolderContents));
b30b6c
    menu->addAction(cm->getAction(MI_SelectAll));
b30b6c
    if (!Preferences::instance()->isWatchFileSystemEnabled()) {
b30b6c
      menu->addAction(cm->getAction(MI_RefreshTree));
b30b6c
    }
b30b6c
    return menu;
b30b6c
  }
b30b6c
b30b6c
  if (files.size() == 1 && files[0].getType() == "tnz") {
b30b6c
    menu->addAction(cm->getAction(MI_LoadScene));
b30b6c
  }
b30b6c
b30b6c
  bool areResources = true;
b30b6c
  bool areScenes    = false;
b30b6c
  int i, j;
b30b6c
  for (i = 0; i < (int)files.size(); i++) {
b30b6c
    TFileType::Type type = TFileType::getInfo(files[i]);
b30b6c
    if (areResources && !TFileType::isResource(type)) areResources = false;
b30b6c
    if (!areScenes && TFileType::isScene(type)) areScenes = true;
b30b6c
  }
b30b6c
b30b6c
  bool areFullcolor = true;
b30b6c
  for (i = 0; i < (int)files.size(); i++) {
b30b6c
    TFileType::Type type = TFileType::getInfo(files[i]);
b30b6c
    if (!TFileType::isFullColor(type)) {
b30b6c
      areFullcolor = false;
b30b6c
      break;
b30b6c
    }
b30b6c
  }
b30b6c
b30b6c
  TFilePath clickedFile;
b30b6c
  if (0 <= index && index < (int)m_items.size())
b30b6c
    clickedFile = m_items[index].m_path;
b30b6c
b30b6c
  if (areResources) {
b30b6c
    QString title;
b30b6c
    if (clickedFile != TFilePath() && clickedFile.getType() == "tnz")
b30b6c
      title = tr("Load As Sub-xsheet");
b30b6c
    else
b30b6c
      title = tr("Load");
b30b6c
    QAction *action = new QAction(title, menu);
b30b6c
    ret             = ret &&
b30b6c
          connect(action, SIGNAL(triggered()), this, SLOT(loadResources()));
b30b6c
    menu->addAction(action);
b30b6c
    menu->addSeparator();
b30b6c
  }
b30b6c
b30b6c
  menu->addAction(cm->getAction(MI_DuplicateFile));
b30b6c
  if (!areScenes) {
b30b6c
    menu->addAction(cm->getAction(MI_Copy));
b30b6c
    menu->addAction(cm->getAction(MI_Paste));
b30b6c
  }
b30b6c
  menu->addAction(cm->getAction(MI_Clear));
b30b6c
  menu->addAction(cm->getAction(MI_ShowFolderContents));
b30b6c
  menu->addAction(cm->getAction(MI_SelectAll));
b30b6c
  menu->addAction(cm->getAction(MI_FileInfo));
b30b6c
  if (!clickedFile.isEmpty() &&
b30b6c
      (clickedFile.getType() == "tnz" || clickedFile.getType() == "tab")) {
b30b6c
    menu->addSeparator();
b30b6c
    menu->addAction(cm->getAction(MI_AddToBatchRenderList));
b30b6c
    menu->addAction(cm->getAction(MI_AddToBatchCleanupList));
b30b6c
  }
b30b6c
b30b6c
  for (i = 0; i < files.size(); i++)
b30b6c
    if (!TFileType::isViewable(TFileType::getInfo(files[i]))) break;
b30b6c
  if (i == files.size()) {
b30b6c
    std::string type = files[0].getType();
b30b6c
    for (j = 0; j < files.size(); j++)
b30b6c
      if (isOldLevelType(files[j])) break;
b30b6c
    if (j == files.size()) menu->addAction(cm->getAction(MI_ViewFile));
b30b6c
b30b6c
    for (j = 0; j < files.size(); j++) {
b30b6c
      if ((files[0].getType() == "pli" && files[j].getType() != "pli") ||
b30b6c
          (files[0].getType() != "pli" && files[j].getType() == "pli"))
b30b6c
        break;
b30b6c
      else if ((isOldLevelType(files[0]) && !isOldLevelType(files[j])) ||
b30b6c
               (!isOldLevelType(files[0]) && isOldLevelType(files[j])))
b30b6c
        break;
b30b6c
    }
b30b6c
    if (j == files.size()) {
b30b6c
      menu->addAction(cm->getAction(MI_ConvertFiles));
b30b6c
      // iwsw commented out temporarily
b30b6c
      // menu->addAction(cm->getAction(MI_ToonShadedImageToTLV));
b30b6c
    }
b30b6c
    if (areFullcolor) menu->addAction(cm->getAction(MI_SeparateColors));
b30b6c
b30b6c
    if (!areFullcolor) menu->addSeparator();
b30b6c
  }
b30b6c
  if (files.size() == 1 && files[0].getType() != "tnz") {
b30b6c
    QAction *action = new QAction(tr("Rename"), menu);
b30b6c
    ret             = ret && connect(action, SIGNAL(triggered()), this,
b30b6c
                         SLOT(renameAsToonzLevel()));
b30b6c
    menu->addAction(action);
b30b6c
  }
b30b6c
#ifdef LEVO
b30b6c
b30b6c
  if (files.size() == 2 &&
b30b6c
      (files[0].getType() == "tif" || files[0].getType() == "tiff" ||
b30b6c
       files[0].getType() == "png" || files[0].getType() == "TIF" ||
b30b6c
       files[0].getType() == "TIFF" || files[0].getType() == "PNG") &&
b30b6c
      (files[1].getType() == "tif" || files[1].getType() == "tiff" ||
b30b6c
       files[1].getType() == "png" || files[1].getType() == "TIF" ||
b30b6c
       files[1].getType() == "TIFF" || files[1].getType() == "PNG")) {
b30b6c
    QAction *action = new QAction(tr("Convert to Painted TLV"), menu);
b30b6c
    ret             = ret && connect(action, SIGNAL(triggered()), this,
b30b6c
                         SLOT(convertToPaintedTlv()));
b30b6c
    menu->addAction(action);
b30b6c
  }
b30b6c
  if (areFullcolor) {
b30b6c
    QAction *action = new QAction(tr("Convert to Unpainted TLV"), menu);
b30b6c
    ret             = ret && connect(action, SIGNAL(triggered()), this,
b30b6c
                         SLOT(convertToUnpaintedTlv()));
b30b6c
    menu->addAction(action);
b30b6c
    menu->addSeparator();
b30b6c
  }
b30b6c
#endif
b30b6c
b30b6c
  if (!clickedFile.isEmpty() && (clickedFile.getType() == "tnz")) {
b30b6c
    menu->addSeparator();
b30b6c
    menu->addAction(cm->getAction(MI_CollectAssets));
b30b6c
    menu->addAction(cm->getAction(MI_ImportScenes));
b30b6c
    menu->addAction(cm->getAction(MI_ExportScenes));
b30b6c
  }
b30b6c
b30b6c
  DvDirVersionControlNode *node = dynamic_cast<dvdirversioncontrolnode *="">(</dvdirversioncontrolnode>
b30b6c
      m_folderTreeView->getCurrentNode());
b30b6c
  if (node) {
b30b6c
    // Check Version Control Status
b30b6c
    DvItemListModel::Status status =
b30b6c
        (DvItemListModel::Status)m_itemViewer->getModel()
b30b6c
            ->getItemData(index, DvItemListModel::VersionControlStatus)
b30b6c
            .toInt();
b30b6c
b30b6c
    // Remove the added actions
b30b6c
    if (status == DvItemListModel::VC_Missing) menu->clear();
b30b6c
b30b6c
    QMenu *vcMenu = new QMenu(tr("Version Control"), parent);
b30b6c
    QAction *action;
b30b6c
b30b6c
    if (status == DvItemListModel::VC_ReadOnly ||
b30b6c
        (status == DvItemListModel::VC_ToUpdate && files.size() == 1)) {
b30b6c
      if (status == DvItemListModel::VC_ReadOnly) {
b30b6c
        action = vcMenu->addAction(tr("Edit"));
b30b6c
        ret    = ret && connect(action, SIGNAL(triggered()), this,
b30b6c
                             SLOT(editVersionControl()));
b30b6c
b30b6c
        TFilePath path       = files.at(0);
b30b6c
        std::string fileType = path.getType();
b30b6c
        if (fileType == "tlv" || fileType == "pli" || path.getDots() == "..") {
b30b6c
          action = vcMenu->addAction(tr("Edit Frame Range..."));
b30b6c
          ret    = ret && connect(action, SIGNAL(triggered()), this,
b30b6c
                               SLOT(editFrameRangeVersionControl()));
b30b6c
        }
b30b6c
      } else {
b30b6c
        action = vcMenu->addAction(tr("Edit"));
b30b6c
        ret    = ret && connect(action, SIGNAL(triggered()), this,
b30b6c
                             SLOT(updateAndEditVersionControl()));
b30b6c
      }
b30b6c
    }
b30b6c
b30b6c
    if (status == DvItemListModel::VC_Modified) {
b30b6c
      action = vcMenu->addAction(tr("Put..."));
b30b6c
      ret    = ret && connect(action, SIGNAL(triggered()), this,
b30b6c
                           SLOT(putVersionControl()));
b30b6c
b30b6c
      action = vcMenu->addAction(tr("Revert"));
b30b6c
      ret    = ret && connect(action, SIGNAL(triggered()), this,
b30b6c
                           SLOT(revertVersionControl()));
b30b6c
    }
b30b6c
b30b6c
    if (status == DvItemListModel::VC_ReadOnly ||
b30b6c
        status == DvItemListModel::VC_ToUpdate) {
b30b6c
      action = vcMenu->addAction(tr("Get"));
b30b6c
      ret    = ret && connect(action, SIGNAL(triggered()), this,
b30b6c
                           SLOT(getVersionControl()));
b30b6c
b30b6c
      if (status == DvItemListModel::VC_ReadOnly) {
b30b6c
        action = vcMenu->addAction(tr("Delete"));
b30b6c
        ret    = ret && connect(action, SIGNAL(triggered()), this,
b30b6c
                             SLOT(deleteVersionControl()));
b30b6c
      }
b30b6c
b30b6c
      vcMenu->addSeparator();
b30b6c
b30b6c
      if (files.size() == 1) {
b30b6c
        action         = vcMenu->addAction(tr("Get Revision..."));
b30b6c
        TFilePath path = files.at(0);
b30b6c
        if (path.getDots() == "..")
b30b6c
          ret = ret && connect(action, SIGNAL(triggered()), this,
b30b6c
                               SLOT(getRevisionVersionControl()));
b30b6c
        else
b30b6c
          ret = ret && connect(action, SIGNAL(triggered()), this,
b30b6c
                               SLOT(getRevisionHistory()));
b30b6c
      } else if (files.size() > 1) {
b30b6c
        action = vcMenu->addAction("Get Revision...");
b30b6c
        ret    = ret && connect(action, SIGNAL(triggered()), this,
b30b6c
                             SLOT(getRevisionVersionControl()));
b30b6c
      }
b30b6c
    }
b30b6c
b30b6c
    if (status == DvItemListModel::VC_Edited) {
b30b6c
      action = vcMenu->addAction(tr("Unlock"));
b30b6c
      ret    = ret && connect(action, SIGNAL(triggered()), this,
b30b6c
                           SLOT(unlockVersionControl()));
b30b6c
    }
b30b6c
b30b6c
    if (status == DvItemListModel::VC_Unversioned) {
b30b6c
      action = vcMenu->addAction(tr("Put..."));
b30b6c
      ret    = ret && connect(action, SIGNAL(triggered()), this,
b30b6c
                           SLOT(putVersionControl()));
b30b6c
    }
b30b6c
b30b6c
    if (status == DvItemListModel::VC_Locked && files.size() == 1) {
b30b6c
      action = vcMenu->addAction(tr("Unlock"));
b30b6c
      ret    = ret && connect(action, SIGNAL(triggered()), this,
b30b6c
                           SLOT(unlockVersionControl()));
b30b6c
b30b6c
      action = vcMenu->addAction(tr("Edit Info"));
b30b6c
      ret    = ret && connect(action, SIGNAL(triggered()), this,
b30b6c
                           SLOT(showLockInformation()));
b30b6c
    }
b30b6c
b30b6c
    if (status == DvItemListModel::VC_Missing) {
b30b6c
      action = vcMenu->addAction(tr("Get"));
b30b6c
      ret    = ret && connect(action, SIGNAL(triggered()), this,
b30b6c
                           SLOT(getVersionControl()));
b30b6c
b30b6c
      if (files.size() == 1) {
b30b6c
        vcMenu->addSeparator();
b30b6c
        action         = vcMenu->addAction(tr("Revision History..."));
b30b6c
        TFilePath path = files.at(0);
b30b6c
        if (path.getDots() == "..")
b30b6c
          ret = ret && connect(action, SIGNAL(triggered()), this,
b30b6c
                               SLOT(getRevisionVersionControl()));
b30b6c
        else
b30b6c
          ret = ret && connect(action, SIGNAL(triggered()), this,
b30b6c
                               SLOT(getRevisionHistory()));
b30b6c
      }
b30b6c
    }
b30b6c
b30b6c
    if (status == DvItemListModel::VC_PartialLocked) {
b30b6c
      action = vcMenu->addAction(tr("Get"));
b30b6c
      ret    = ret && connect(action, SIGNAL(triggered()), this,
b30b6c
                           SLOT(getVersionControl()));
b30b6c
      if (files.size() == 1) {
b30b6c
        action = vcMenu->addAction(tr("Edit Frame Range..."));
b30b6c
        ret    = ret && connect(action, SIGNAL(triggered()), this,
b30b6c
                             SLOT(editFrameRangeVersionControl()));
b30b6c
b30b6c
        action = vcMenu->addAction(tr("Edit Info"));
b30b6c
        ret    = ret && connect(action, SIGNAL(triggered()), this,
b30b6c
                             SLOT(showFrameRangeLockInfo()));
b30b6c
      }
b30b6c
b30b6c
    } else if (status == DvItemListModel::VC_PartialEdited) {
b30b6c
      action = vcMenu->addAction(tr("Get"));
b30b6c
      ret    = ret && connect(action, SIGNAL(triggered()), this,
b30b6c
                           SLOT(getVersionControl()));
b30b6c
b30b6c
      if (files.size() == 1) {
b30b6c
        action = vcMenu->addAction(tr("Unlock Frame Range"));
b30b6c
        ret    = ret && connect(action, SIGNAL(triggered()), this,
b30b6c
                             SLOT(unlockFrameRangeVersionControl()));
b30b6c
b30b6c
        action = vcMenu->addAction(tr("Edit Info"));
b30b6c
        ret    = ret && connect(action, SIGNAL(triggered()), this,
b30b6c
                             SLOT(showFrameRangeLockInfo()));
b30b6c
      }
b30b6c
    } else if (status == DvItemListModel::VC_PartialModified) {
b30b6c
      action = vcMenu->addAction(tr("Get"));
b30b6c
      ret    = ret && connect(action, SIGNAL(triggered()), this,
b30b6c
                           SLOT(getVersionControl()));
b30b6c
b30b6c
      if (files.size() == 1) {
b30b6c
        action = vcMenu->addAction(tr("Put..."));
b30b6c
        ret    = ret && connect(action, SIGNAL(triggered()), this,
b30b6c
                             SLOT(putFrameRangeVersionControl()));
b30b6c
b30b6c
        action = vcMenu->addAction(tr("Revert"));
b30b6c
        ret    = ret && connect(action, SIGNAL(triggered()), this,
b30b6c
                             SLOT(revertFrameRangeVersionControl()));
b30b6c
      }
b30b6c
    }
b30b6c
b30b6c
    if (!vcMenu->isEmpty()) {
b30b6c
      menu->addSeparator();
b30b6c
      menu->addMenu(vcMenu);
b30b6c
    }
b30b6c
  }
b30b6c
b30b6c
  if (!Preferences::instance()->isWatchFileSystemEnabled()) {
b30b6c
    menu->addSeparator();
b30b6c
    menu->addAction(cm->getAction(MI_RefreshTree));
b30b6c
  }
b30b6c
b30b6c
  assert(ret);
b30b6c
b30b6c
  return menu;
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::startDragDrop() {
b30b6c
  TRepetitionGuard guard;
b30b6c
  if (!guard.hasLock()) return;
b30b6c
b30b6c
  FileSelection *fs =
b30b6c
      dynamic_cast<fileselection *="">(m_itemViewer->getPanel()->getSelection());</fileselection>
b30b6c
  if (!fs) return;
b30b6c
  std::vector<tfilepath> files;</tfilepath>
b30b6c
  fs->getSelectedFiles(files);
b30b6c
  if (files.empty()) return;
b30b6c
b30b6c
  QList<qurl> urls;</qurl>
b30b6c
  for (int i = 0; i < (int)files.size(); i++) {
b30b6c
    if (TSystem::doesExistFileOrLevel(files[i]))
b30b6c
      urls.append(QUrl::fromLocalFile(
b30b6c
          QString::fromStdWString(files[i].getWideString())));
b30b6c
  }
b30b6c
  if (urls.isEmpty()) return;
b30b6c
b30b6c
  QMimeData *mimeData = new QMimeData;
b30b6c
  mimeData->setUrls(urls);
b30b6c
  QDrag *drag    = new QDrag(this);
b30b6c
  QSize iconSize = m_itemViewer->getPanel()->getIconSize();
b30b6c
  QPixmap icon   = IconGenerator::instance()->getIcon(files[0]);
b30b6c
  QPixmap dropThumbnail =
b30b6c
      scalePixmapKeepingAspectRatio(icon, iconSize, Qt::transparent);
b30b6c
  if (!dropThumbnail.isNull()) drag->setPixmap(dropThumbnail);
b30b6c
  drag->setMimeData(mimeData);
b30b6c
  Qt::DropAction dropAction = drag->exec(Qt::CopyAction);
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
bool SceneBrowser::dropMimeData(QTreeWidgetItem *parent, int index,
b30b6c
                               const QMimeData *data, Qt::DropAction action) {
b30b6c
  return false;
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::onTreeFolderChanged() {
b96f40
  // Commented by KD
b30b6c
  DvDirModelNode *node = m_folderTreeView->getCurrentNode();
b96f40
  //if (node)
b96f40
  //  node->visualizeContent(this);
b96f40
  //else
b96f40
  //  setFolder(TFilePath());
b30b6c
  m_itemViewer->resetVerticalScrollBar();
b30b6c
  m_itemViewer->updateContentSize();
b30b6c
  m_itemViewer->getPanel()->update();
b30b6c
  m_frameCountReader.stopReading();
b30b6c
  IconGenerator::instance()->clearRequests();
b30b6c
b30b6c
  DvDirModelFileFolderNode *fileFolderNode =
b30b6c
      dynamic_cast<dvdirmodelfilefoldernode *="">(node);</dvdirmodelfilefoldernode>
b30b6c
  if (fileFolderNode) emit treeFolderChanged(fileFolderNode->getPath());
6b56d2
6b56d2
  // Restore scroll position
6b56d2
  m_itemViewer->verticalScrollBar()->setValue(m_currentScroll);
6b56d2
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::changeFolder(const QModelIndex &index) {}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::onDataChanged(const QModelIndex &topLeft,
b30b6c
                                const QModelIndex &bottomRight) {
b30b6c
  onTreeFolderChanged();
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
bool SceneBrowser::acceptDrop(const QMimeData *data) const {
b30b6c
  // se il browser non sta visualizzando un folder standard non posso accettare
b30b6c
  // nessun drop
b30b6c
  if (getFolder() == TFilePath()) return false;
b30b6c
b30b6c
  if (data->hasFormat("application/vnd.toonz.levels") ||
b30b6c
      data->hasFormat("application/vnd.toonz.currentscene") ||
b30b6c
      data->hasFormat("application/vnd.toonz.drawings") ||
b30b6c
      acceptResourceDrop(data->urls()))
b30b6c
    return true;
b30b6c
b30b6c
  return false;
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
bool SceneBrowser::drop(const QMimeData *mimeData) {
b30b6c
  // se il browser non sta visualizzando un folder standard non posso accettare
b30b6c
  // nessun drop
b30b6c
  TFilePath folderPath = getFolder();
b30b6c
  if (folderPath == TFilePath()) return false;
b30b6c
b30b6c
  if (mimeData->hasFormat(CastItems::getMimeFormat())) {
b30b6c
    const CastItems *items = dynamic_cast<const *="" castitems="">(mimeData);</const>
b30b6c
    if (!items) return false;
b30b6c
b30b6c
    int i;
b30b6c
    for (i = 0; i < items->getItemCount(); i++) {
b30b6c
      CastItem *item = items->getItem(i);
b30b6c
      if (TXshSimpleLevel *sl = item->getSimpleLevel()) {
b30b6c
        TFilePath levelPath = sl->getPath().withParentDir(getFolder());
b30b6c
        IoCmd::saveLevel(levelPath, sl, false);
b30b6c
      } else if (TXshSoundLevel *level = item->getSoundLevel()) {
b30b6c
        TFilePath soundPath = level->getPath().withParentDir(getFolder());
b30b6c
        IoCmd::saveSound(soundPath, level, false);
b30b6c
      }
b30b6c
    }
b30b6c
    refreshFolder(getFolder());
b30b6c
    return true;
b30b6c
  } else if (mimeData->hasFormat("application/vnd.toonz.currentscene")) {
b30b6c
    TFilePath scenePath;
b30b6c
    ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
b30b6c
    if (scene->isUntitled()) {
b30b6c
      bool ok;
b30b6c
      QString sceneName =
b30b6c
          QInputDialog::getText(this, tr("Save Scene"), tr("Scene name:"),
b30b6c
                                QLineEdit::Normal, QString(), &ok);
b30b6c
      if (!ok || sceneName == "") return false;
b30b6c
      scenePath = folderPath + sceneName.toStdWString();
b30b6c
    } else
b30b6c
      scenePath = folderPath + scene->getSceneName();
b30b6c
    return IoCmd::saveScene(scenePath, false);
b30b6c
  } else if (mimeData->hasFormat("application/vnd.toonz.drawings")) {
b30b6c
    TFilmstripSelection *s =
b30b6c
        dynamic_cast<tfilmstripselection *="">(TSelection::getCurrent());</tfilmstripselection>
b30b6c
    if (!s) return false;
b30b6c
    TXshSimpleLevel *sl = TApp::instance()->getCurrentLevel()->getSimpleLevel();
b30b6c
    if (!sl) return false;
b30b6c
b30b6c
    std::wstring levelName = sl->getName();
b30b6c
    folderPath +=
b30b6c
        TFilePath(levelName + ::to_wstring(sl->getPath().getDottedType()));
b30b6c
    if (TSystem::doesExistFileOrLevel(folderPath)) {
b30b6c
      QString question = "Level " + toQString(folderPath) +
b30b6c
                         " already exists\nDo you want to duplicate it?";
b30b6c
      int ret = DVGui::MsgBox(question, QObject::tr("Duplicate"),
b30b6c
                              QObject::tr("Don't Duplicate"), 0);
b30b6c
      if (ret == 2 || ret == 0) return false;
b30b6c
      TFilePath path = folderPath;
b30b6c
      NameBuilder *nameBuilder =
b30b6c
          NameBuilder::getBuilder(::to_wstring(path.getName()));
b30b6c
      do
b30b6c
        levelName = nameBuilder->getNext();
b30b6c
      while (TSystem::doesExistFileOrLevel(path.withName(levelName)));
b30b6c
      folderPath = path.withName(levelName);
b30b6c
    }
b30b6c
    assert(!TSystem::doesExistFileOrLevel(folderPath));
b30b6c
b30b6c
    TXshSimpleLevel *newSl = new TXshSimpleLevel();
b30b6c
    newSl->setType(sl->getType());
b30b6c
    newSl->clonePropertiesFrom(sl);
b30b6c
    newSl->setName(levelName);
b30b6c
    newSl->setPalette(sl->getPalette());
b30b6c
    newSl->setScene(sl->getScene());
b30b6c
    std::set<tframeid> frames = s->getSelectedFids();</tframeid>
b30b6c
    for (auto const &fid : frames) {
b30b6c
      newSl->setFrame(fid, sl->getFrame(fid, false));
b30b6c
    }
b30b6c
b30b6c
    IoCmd::saveLevel(folderPath, newSl, false);
b30b6c
    refreshFolder(folderPath.getParentDir());
b30b6c
    return true;
b30b6c
  } else if (mimeData->hasUrls()) {
b30b6c
    int count = 0;
b30b6c
    for (const QUrl &url : mimeData->urls()) {
b30b6c
      TFilePath srcFp(url.toLocalFile().toStdWString());
b30b6c
      TFilePath dstFp = srcFp.withParentDir(folderPath);
b30b6c
      if (dstFp != srcFp) {
b30b6c
        if (!TSystem::copyFileOrLevel(dstFp, srcFp))
b30b6c
          DVGui::error(tr("There was an error copying %1 to %2")
b30b6c
                           .arg(toQString(srcFp))
b30b6c
                           .arg(toQString(dstFp)));
b30b6c
      }
b30b6c
    }
b30b6c
    refreshFolder(folderPath);
b30b6c
    return true;
b30b6c
  } else
b30b6c
    return false;
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::loadResources() {
b30b6c
  FileSelection *fs =
b30b6c
      dynamic_cast<fileselection *="">(m_itemViewer->getPanel()->getSelection());</fileselection>
b30b6c
  if (!fs) return;
b30b6c
b30b6c
  std::vector<tfilepath> filePaths;</tfilepath>
b30b6c
  fs->getSelectedFiles(filePaths);
b30b6c
b30b6c
  if (filePaths.empty()) return;
b30b6c
b30b6c
  IoCmd::LoadResourceArguments args;
b30b6c
  args.resourceDatas.assign(filePaths.begin(), filePaths.end());
b30b6c
b30b6c
  IoCmd::loadResources(args);
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b30b6c
namespace {
b30b6c
b30b6c
bool parsePathName(const QString &fullpath, QString &parentPath, QString &name,
b30b6c
                   QString &format) {
b30b6c
  int index = fullpath.lastIndexOf('\\');
b30b6c
  if (index == -1) index = fullpath.lastIndexOf('/');
b30b6c
b30b6c
  QString filename;
b30b6c
b30b6c
  if (index != -1) {
b30b6c
    parentPath = fullpath.left(index + 1);
b30b6c
    filename   = fullpath.right(fullpath.size() - index - 1);
b30b6c
  } else {
b30b6c
    parentPath = "";
b30b6c
    filename   = fullpath;
b30b6c
  }
b30b6c
b30b6c
  index = filename.lastIndexOf('.');
b30b6c
b30b6c
  if (index <= 0) return false;
b30b6c
b30b6c
  format = filename.right(filename.size() - index - 1);
b30b6c
  if (format == "") return false;
b30b6c
b30b6c
  index--;
b30b6c
  if (!filename.at(index).isDigit()) return false;
b30b6c
b30b6c
  while (index >= 0 && filename.at(index).isDigit()) index--;
b30b6c
b30b6c
  if (index < 0) return false;
b30b6c
b30b6c
  name = filename.left(index + 1);
b30b6c
b30b6c
  return true;
b30b6c
}
b30b6c
b30b6c
//---------------------------------------------------------
b30b6c
b30b6c
void getLevelFiles(const QString &parentPath, const QString &name,
b30b6c
                   const QString &format, QStringList &pathIn) {
b30b6c
  QString dummy, dummy1, filter = "*." + format;
b30b6c
  QDir dir(parentPath, filter);
b30b6c
  QStringList list = dir.entryList();
b30b6c
b30b6c
  for (int i = 0; i < list.size(); i++) {
b30b6c
    QString item = list.at(i);
b30b6c
    QString itemName;
b30b6c
    if (!parsePathName(item, dummy, itemName, dummy1) || name != itemName)
b30b6c
      continue;
b30b6c
b30b6c
    pathIn.push_back(item);
b30b6c
  }
b30b6c
}
b30b6c
b30b6c
//---------------------------------------------------------
b30b6c
b30b6c
QString getFrame(const QString &filename) {
b30b6c
  int index = filename.lastIndexOf('.');
b30b6c
b30b6c
  if (index <= 0) return "";
b30b6c
b30b6c
  index--;
b30b6c
  if (!filename.at(index).isDigit()) return "";
b30b6c
b30b6c
  int to, from;
b30b6c
  to = from = index;
b30b6c
  while (from >= 0 && filename.at(from).isDigit()) from--;
b30b6c
b30b6c
  if (from < 0) return "";
b30b6c
b30b6c
  char padStr[5];
b30b6c
  padStr[4] = '\0';
b30b6c
b30b6c
  int i, frame = 0;
b30b6c
b30b6c
  QString number = filename.mid(from + 1, to - from);
b30b6c
  for (i = 0; i < 4 - number.size(); i++) padStr[i] = '0';
b30b6c
  for (i = 0; i < number.size(); i++)
b30b6c
#if QT_VERSION >= 0x050500
b30b6c
    padStr[4 - number.size() + i] = number.at(i).toLatin1();
b30b6c
#else
b30b6c
    padStr[4 - number.size() + i] = number.at(i).toAscii();
b30b6c
#endif
b30b6c
  return QString(padStr);
b30b6c
}
b30b6c
b30b6c
//------------------------------------------------------------------
b30b6c
b30b6c
//-----------------------------------------------------------
b30b6c
b30b6c
void renameSingleFileOrToonzLevel(const QString &fullpath) {
b30b6c
  TFilePath fpin(fullpath.toStdString());
b30b6c
b30b6c
  RenameAsToonzPopup popup(
b30b6c
      QString::fromStdWString(fpin.withoutParentDir().getWideString()));
b30b6c
  if (popup.exec() != QDialog::Accepted) return;
b30b6c
b30b6c
  std::string name = popup.getName().toStdString();
b30b6c
b30b6c
  if (name == fpin.getName()) {
b30b6c
    DVGui::error(QString(
b30b6c
        QObject::tr("The specified name is already assigned to the %1 file.")
b30b6c
            .arg(fullpath)));
b30b6c
    return;
b30b6c
  }
b30b6c
b30b6c
  if (popup.doOverwrite())
b30b6c
    TSystem::renameFileOrLevel(fpin.withName(name), fpin, true);
b30b6c
  else
b30b6c
    TSystem::copyFileOrLevel(fpin.withName(name), fpin);
b30b6c
}
b30b6c
b30b6c
//----------------------------------------------------------
b30b6c
b30b6c
void doRenameAsToonzLevel(const QString &fullpath) {
b30b6c
  QString parentPath, name, format;
b30b6c
b30b6c
  if (!parsePathName(fullpath, parentPath, name, format)) {
b30b6c
    renameSingleFileOrToonzLevel(fullpath);
b30b6c
    return;
b30b6c
  }
b30b6c
b30b6c
  QStringList pathIn;
b30b6c
b30b6c
  getLevelFiles(parentPath, name, format, pathIn);
b30b6c
b30b6c
  if (pathIn.empty()) return;
b30b6c
b30b6c
  while (name.endsWith('_') || name.endsWith('.') || name.endsWith(' '))
b30b6c
    name.chop(1);
b30b6c
b30b6c
  RenameAsToonzPopup popup(name, pathIn.size());
b30b6c
  if (popup.exec() != QDialog::Accepted) return;
b30b6c
b30b6c
  name = popup.getName();
b30b6c
b30b6c
  QString levelOutStr = parentPath + "/" + name + ".." + format;
b30b6c
b30b6c
  TFilePath levelOut(levelOutStr.toStdWString());
b30b6c
  if (TSystem::doesExistFileOrLevel(levelOut)) {
b30b6c
    QApplication::restoreOverrideCursor();
b30b6c
    int ret = DVGui::MsgBox(
b30b6c
        QObject::tr("Warning: level %1 already exists; overwrite?")
b30b6c
            .arg(toQString(levelOut)),
b30b6c
        QObject::tr("Yes"), QObject::tr("No"), 1);
b30b6c
    QApplication::setOverrideCursor(Qt::WaitCursor);
b30b6c
    if (ret == 2 || ret == 0) return;
b30b6c
    TSystem::removeFileOrLevel(levelOut);
b30b6c
  }
b30b6c
b30b6c
  int i;
b30b6c
  for (i = 0; i < pathIn.size(); i++) {
b30b6c
    QString padStr = getFrame(pathIn[i]);
b30b6c
    if (padStr == "") continue;
b30b6c
    QString pathOut = parentPath + "/" + name + "." + padStr + "." + format;
b30b6c
b30b6c
    if (popup.doOverwrite()) {
b30b6c
      if (!QFile::rename(parentPath + "/" + pathIn[i], pathOut)) {
b30b6c
        QString tmp(parentPath + "/" + pathIn[i]);
b30b6c
        DVGui::error(QString(
b30b6c
            QObject::tr("It is not possible to rename the %1 file.").arg(tmp)));
b30b6c
        return;
b30b6c
      }
b30b6c
    } else if (!QFile::copy(parentPath + "/" + pathIn[i], pathOut)) {
b30b6c
      QString tmp(parentPath + "/" + pathIn[i]);
b30b6c
      DVGui::error(QString(
b30b6c
          QObject::tr("It is not possible to copy the %1 file.").arg(tmp)));
b30b6c
b30b6c
      return;
b30b6c
    }
b30b6c
  }
b30b6c
}
b30b6c
b30b6c
}  // namespace
b30b6c
b30b6c
//-------------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::renameAsToonzLevel() {
b30b6c
  std::vector<tfilepath> filePaths;</tfilepath>
b30b6c
  FileSelection *fs =
b30b6c
      dynamic_cast<fileselection *="">(m_itemViewer->getPanel()->getSelection());</fileselection>
b30b6c
  if (!fs) return;
b30b6c
  fs->getSelectedFiles(filePaths);
b30b6c
  if (filePaths.size() != 1) return;
b30b6c
b30b6c
  doRenameAsToonzLevel(QString::fromStdWString(filePaths[0].getWideString()));
b30b6c
b30b6c
  QApplication::restoreOverrideCursor();
b30b6c
b30b6c
  FileBrowser::refreshFolder(filePaths[0].getParentDir());
b30b6c
}
b30b6c
b30b6c
#ifdef LEVO
b30b6c
b96f40
void SceneBrowser::convertToUnpaintedTlv() {
b30b6c
  std::vector<tfilepath> filePaths;</tfilepath>
b30b6c
  FileSelection *fs =
b30b6c
      dynamic_cast<fileselection *="">(m_itemViewer->getPanel()->getSelection());</fileselection>
b30b6c
  if (!fs) return;
b30b6c
  fs->getSelectedFiles(filePaths);
b30b6c
b30b6c
  QStringList sl;
b30b6c
  sl << "Apply Autoclose                        "
b30b6c
     << "Don't Apply Autoclose                          ";
b30b6c
  bool ok;
b30b6c
  QString autoclose = QInputDialog::getItem(
b30b6c
      this, tr("Convert To Unpainted Tlv"), "", sl, 0, false, &ok);
b30b6c
  if (!ok) return;
b30b6c
b30b6c
  QApplication::setOverrideCursor(Qt::WaitCursor);
b30b6c
b30b6c
  int i, totFrames = 0;
b30b6c
  std::vector<convert2tlv *=""> converters;</convert2tlv>
b30b6c
  for (i = 0; i < filePaths.size(); i++) {
b30b6c
    Convert2Tlv *converter =
b30b6c
        new Convert2Tlv(filePaths[i], TFilePath(), TFilePath(), -1, -1,
b30b6c
                        autoclose == sl.at(0), TFilePath(), 0, 0, 0);
b30b6c
b30b6c
    if (TSystem::doesExistFileOrLevel(converter->m_levelOut)) {
b30b6c
      QApplication::restoreOverrideCursor();
b30b6c
      int ret = DVGui::MsgBox(tr("Warning: level %1 already exists; overwrite?")
b30b6c
                                  .arg(toQString(converter->m_levelOut)),
b30b6c
                              tr("Yes"), tr("No"), 1);
b30b6c
      QApplication::setOverrideCursor(Qt::WaitCursor);
b30b6c
      if (ret == 2 || ret == 0) {
b30b6c
        delete converter;
b30b6c
        continue;
b30b6c
      }
b30b6c
      TSystem::removeFileOrLevel(converter->m_levelOut);
b30b6c
    }
b30b6c
b30b6c
    totFrames += converter->getFramesToConvertCount();
b30b6c
    converters.push_back(converter);
b30b6c
  }
b30b6c
b30b6c
  if (converters.empty()) {
b30b6c
    QApplication::restoreOverrideCursor();
b30b6c
    return;
b30b6c
  }
b30b6c
b30b6c
  ProgressDialog pb("", "Cancel", 0, totFrames);
b30b6c
  int j, l, k = 0;
b30b6c
  for (i = 0; i < converters.size(); i++) {
b30b6c
    std::string errorMessage;
b30b6c
    if (!converters[i]->init(errorMessage)) {
b30b6c
      converters[i]->abort();
b30b6c
      DVGui::error(QString::fromStdString(errorMessage));
b30b6c
      delete converters[i];
b30b6c
      converters[i] = 0;
b30b6c
      continue;
b30b6c
    }
b30b6c
b30b6c
    int count = converters[i]->getFramesToConvertCount();
b30b6c
b30b6c
    pb.setLabelText("Generating level " + toQString(converters[i]->m_levelOut));
b30b6c
    pb.show();
b30b6c
b30b6c
    for (j = 0; j < count; j++) {
b30b6c
      std::string errorMessage = "";
b30b6c
      if (!converters[i]->convertNext(errorMessage) || pb.wasCanceled()) {
b30b6c
        for (l = i; l < converters.size(); l++) {
b30b6c
          converters[l]->abort();
b30b6c
          delete converters[i];
b30b6c
          converters[i] = 0;
b30b6c
        }
b30b6c
        if (errorMessage != "")
b30b6c
          DVGui::error(QString::fromStdString(errorMessage));
b30b6c
        QApplication::restoreOverrideCursor();
b96f40
        SceneBrowser::refreshFolder(filePaths[0].getParentDir());
b30b6c
        return;
b30b6c
      }
b30b6c
      pb.setValue(++k);
b30b6c
    }
b30b6c
    TFilePath levelOut(converters[i]->m_levelOut);
b30b6c
    delete converters[i];
b30b6c
    IconGenerator::instance()->invalidate(levelOut);
b30b6c
b30b6c
    converters[i] = 0;
b30b6c
  }
b30b6c
b30b6c
  QApplication::restoreOverrideCursor();
b30b6c
  pb.hide();
b30b6c
  DVGui::info(tr("Done: All Levels  converted to TLV Format"));
b30b6c
b96f40
  SceneBrowser::refreshFolder(filePaths[0].getParentDir());
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::convertToPaintedTlv() {
b30b6c
  std::vector<tfilepath> filePaths;</tfilepath>
b30b6c
  FileSelection *fs =
b30b6c
      dynamic_cast<fileselection *="">(m_itemViewer->getPanel()->getSelection());</fileselection>
b30b6c
  if (!fs) return;
b30b6c
  fs->getSelectedFiles(filePaths);
b30b6c
b30b6c
  if (filePaths.size() != 2) return;
b30b6c
b30b6c
  QStringList sl;
b30b6c
  sl << "Apply Autoclose                      "
b30b6c
     << "Don't Apply Autoclose                        ";
b30b6c
  bool ok;
b30b6c
  QString autoclose = QInputDialog::getItem(this, tr("Convert To Painted Tlv"),
b30b6c
                                            "", sl, 0, false, &ok);
b30b6c
  if (!ok) return;
b30b6c
b30b6c
  QApplication::setOverrideCursor(Qt::WaitCursor);
b30b6c
b30b6c
  Convert2Tlv *converter =
b30b6c
      new Convert2Tlv(filePaths[0], filePaths[1], TFilePath(), -1, -1,
b30b6c
                      autoclose == sl.at(0), TFilePath(), 0, 0, 0);
b30b6c
b30b6c
  if (TSystem::doesExistFileOrLevel(converter->m_levelOut)) {
b30b6c
    QApplication::restoreOverrideCursor();
b30b6c
    int ret = DVGui::MsgBox(tr("Warning: level %1 already exists; overwrite?")
b30b6c
                                .arg(toQString(converter->m_levelOut)),
b30b6c
                            tr("Yes"), tr("No"), 1);
b30b6c
    QApplication::setOverrideCursor(Qt::WaitCursor);
b30b6c
    if (ret == 2 || ret == 0) {
b30b6c
      QApplication::restoreOverrideCursor();
b30b6c
      return;
b30b6c
    }
b30b6c
    TSystem::removeFileOrLevel(converter->m_levelOut);
b30b6c
  }
b30b6c
b30b6c
  std::string errorMessage;
b30b6c
  if (!converter->init(errorMessage)) {
b30b6c
    converter->abort();
b30b6c
    delete converter;
b30b6c
    DVGui::error(QString::fromStdString(errorMessage));
b30b6c
    QApplication::restoreOverrideCursor();
b30b6c
    return;
b30b6c
  }
b30b6c
  int count = converter->getFramesToConvertCount();
b30b6c
b30b6c
  ProgressDialog pb("Generating level " + toQString(converter->m_levelOut),
b30b6c
                    "Cancel", 0, count);
b30b6c
  pb.show();
b30b6c
b30b6c
  for (int i = 0; i < count; i++) {
b30b6c
    errorMessage = "";
b30b6c
    if (!converter->convertNext(errorMessage) || pb.wasCanceled()) {
b30b6c
      converter->abort();
b30b6c
      delete converter;
b30b6c
      if (errorMessage != "")
b30b6c
        DVGui::error(QString::fromStdString(errorMessage));
b30b6c
      QApplication::restoreOverrideCursor();
b96f40
      SceneBrowser::refreshFolder(filePaths[0].getParentDir());
b30b6c
      return;
b30b6c
    }
b30b6c
b30b6c
    pb.setValue(i + 1);
b30b6c
  }
b30b6c
b30b6c
  TFilePath levelOut(converter->m_levelOut);
b30b6c
  delete converter;
b30b6c
  IconGenerator::instance()->invalidate(levelOut);
b30b6c
b30b6c
  QApplication::restoreOverrideCursor();
b30b6c
  pb.hide();
b30b6c
  DVGui::info(tr("Done: 2 Levels  converted to TLV Format"));
b30b6c
b30b6c
  fs->selectNone();
b96f40
  SceneBrowser::refreshFolder(filePaths[0].getParentDir());
b30b6c
}
b30b6c
#endif
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
225725
void SceneBrowser::onSceneSwitched() {
378ade
  ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
378ade
  TFilePath scenesFolder = scene->getScenePath().getParentDir();
378ade
  //TFilePath scenesFolder = TProjectManager::instance()->getCurrentProject()->getScenesPath();
225725
  setFolder(scenesFolder, true);
225725
}
225725
225725
//-----------------------------------------------------------------------------
225725
b96f40
void SceneBrowser::onSelectedItems(const std::set<int> &indexes) {</int>
b30b6c
  std::set<tfilepath> filePaths;</tfilepath>
b30b6c
  std::set<int>::const_iterator it;</int>
b30b6c
b30b6c
  // pass the frameId list for reuse
b30b6c
  std::list<std::vector<tframeid>> frameIDs;</std::vector<tframeid>
b30b6c
b30b6c
  if (indexes.empty()) {  // inform selection is released
b30b6c
    emit filePathsSelected(filePaths, frameIDs);
b30b6c
    return;
b30b6c
  }
b30b6c
b30b6c
  for (it = indexes.begin(); it != indexes.end(); ++it) {
b30b6c
    filePaths.insert(m_items[*it].m_path);
b30b6c
    frameIDs.insert(frameIDs.begin(), m_items[*it].m_frameIds);
b30b6c
  }
b30b6c
b30b6c
  // reuse the list of TFrameId in order to skip loadInfo() when loading the
b30b6c
  // level with sequencial frames.
b30b6c
  emit filePathsSelected(filePaths, frameIDs);
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::onClickedItem(int index) {
b30b6c
  if (0 <= index && index < (int)m_items.size()) {
b30b6c
    // if the folder is clicked, then move the current folder
b30b6c
    TFilePath fp = m_items[index].m_path;
b30b6c
    if (m_items[index].m_isFolder) {
b30b6c
      setFolder(fp, true);
b30b6c
      QModelIndex index = m_folderTreeView->currentIndex();
b30b6c
      if (index.isValid()) m_folderTreeView->scrollTo(index);
b30b6c
    } else
b30b6c
      emit filePathClicked(fp);
b30b6c
  }
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::onDoubleClickedItem(int index) {
b30b6c
  // TODO: Avoid duplicate code with onClickedItem().
b30b6c
  if (0 <= index && index < (int)m_items.size()) {
b30b6c
    // if the folder is clicked, then move the current folder
b30b6c
    TFilePath fp = m_items[index].m_path;
b30b6c
    if (m_items[index].m_isFolder) {
b30b6c
      setFolder(fp, true);
b30b6c
      QModelIndex index = m_folderTreeView->currentIndex();
b30b6c
      if (index.isValid()) m_folderTreeView->scrollTo(index);
b30b6c
    } else
b30b6c
      emit filePathDoubleClicked(fp);
b30b6c
  }
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::refreshFolder(const TFilePath &folderPath) {
b96f40
  std::set<scenebrowser *="">::iterator it;</scenebrowser>
b96f40
  for (it = activePreproductionBoards.begin(); it != activePreproductionBoards.end(); ++it) {
b96f40
    SceneBrowser *browser = *it;
b30b6c
    DvDirModel::instance()->refreshFolder(folderPath);
b30b6c
    if (browser->getFolder() == folderPath) {
b30b6c
      browser->setFolder(folderPath, false, true);
b30b6c
    }
b30b6c
  }
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::updateItemViewerPanel() {
b96f40
  std::set<scenebrowser *="">::iterator it;</scenebrowser>
b96f40
  for (it = activePreproductionBoards.begin(); it != activePreproductionBoards.end(); ++it) {
b96f40
    SceneBrowser *browser = *it;
b30b6c
    browser->m_itemViewer->getPanel()->update();
b30b6c
  }
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::getExpandedFolders(DvDirModelNode *node,
b30b6c
                                     QList<dvdirmodelnode *=""> &expandedNodes) {</dvdirmodelnode>
b30b6c
  if (!node) return;
b30b6c
  QModelIndex newIndex = DvDirModel::instance()->getIndexByNode(node);
b30b6c
  if (!m_folderTreeView->isExpanded(newIndex)) return;
b30b6c
  expandedNodes.push_back(node);
b30b6c
b30b6c
  int i = 0;
b30b6c
  for (i = 0; i < node->getChildCount(); i++)
b30b6c
    getExpandedFolders(node->getChild(i), expandedNodes);
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::refresh() {
b30b6c
  TFilePath originalFolder(
b30b6c
      m_folder);  // setFolder is invoked by Qt throughout the following...
b30b6c
b30b6c
  int dx                   = m_folderTreeView->verticalScrollBar()->value();
b30b6c
  DvDirModelNode *rootNode = DvDirModel::instance()->getNode(QModelIndex());
b30b6c
b30b6c
  QModelIndex index = DvDirModel::instance()->getIndexByNode(rootNode);
b30b6c
b30b6c
  bool vcEnabled = m_folderTreeView->refreshVersionControlEnabled();
b30b6c
b30b6c
  m_folderTreeView->setRefreshVersionControlEnabled(false);
b30b6c
  DvDirModel::instance()->refreshFolderChild(index);
b30b6c
  m_folderTreeView->setRefreshVersionControlEnabled(vcEnabled);
b30b6c
b30b6c
  QList<dvdirmodelnode *=""> expandedNodes;</dvdirmodelnode>
b30b6c
  int i;
b30b6c
  for (i = 0; i < rootNode->getChildCount(); i++)
b30b6c
    getExpandedFolders(rootNode->getChild(i), expandedNodes);
b30b6c
b30b6c
  for (i = 0; i < expandedNodes.size(); i++) {
b30b6c
    DvDirModelNode *node = expandedNodes[i];
b30b6c
    if (!node || !node->hasChildren()) continue;
b30b6c
    QModelIndex ind = DvDirModel::instance()->getIndexByNode(node);
b30b6c
    if (!ind.isValid()) continue;
b30b6c
    m_folderTreeView->expand(ind);
b30b6c
  }
b30b6c
  m_folderTreeView->verticalScrollBar()->setValue(dx);
b30b6c
b30b6c
  setFolder(originalFolder, false, true);
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b399ae
void SceneBrowser::newScene() {
6b56d2
6b56d2
  m_currentScroll = m_itemViewer->verticalScrollBar()->value();
6b56d2
b30b6c
  TFilePath parentFolder = getFolder();
f96d7f
  QString sceneName;
9b8bdb
  TFilePath scenePath;
9b8bdb
  ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
9b8bdb
  if (scene->isUntitled()) {
9b8bdb
      bool ok;
f96d7f
      sceneName =
9b8bdb
          QInputDialog::getText(this, tr("Save Scene"), tr("Scene name:"),
9b8bdb
                                QLineEdit::Normal, QString(), &ok);
f96d7f
      if (!ok || sceneName == "") return;
4ca039
    } else {
f96d7f
      sceneName = QString::fromWCharArray( scene->getSceneName().c_str() );
4ca039
  }
f96d7f
  QString prefix;
f96d7f
  QString number;
f96d7f
  for(int j = 0; j
f96d7f
    QChar c;
f96d7f
    c = sceneName.at(sceneName.length()-1-j);
f96d7f
    if (c.isDigit()) {
f96d7f
      number = QString(c) + number;
f96d7f
    } else {
f96d7f
      prefix = sceneName;
f96d7f
      prefix.truncate(sceneName.length()-j);
f96d7f
      break;
f96d7f
    }
f96d7f
  }
e3baae
  if (number.length()==0) {
e4bfa2
    //prefix+="-";
e3baae
    number="000";
e3baae
  }
f96d7f
  int i = number.toInt();
9b8bdb
  do {
40caca
    QString number_ext = QStringLiteral("%1").arg(++i, number.length(), 10, QLatin1Char('0'));
40caca
    scenePath = parentFolder + (prefix.toStdWString()+number_ext.toStdWString()+L".tnz");
9b8bdb
  } while (TFileStatus(scenePath).doesExist());
9b8bdb
  
9b8bdb
  if (!IoCmd::saveSceneIfNeeded(QObject::tr("Change project"))) return;
9b8bdb
  IoCmd::newScene();
9b8bdb
  IoCmd::saveScene(scenePath, false);
9b8bdb
  return;
9b8bdb
b30b6c
  if (parentFolder == TFilePath() || !TFileStatus(parentFolder).isDirectory())
b30b6c
    return;
b30b6c
  QString tempName(tr("New Folder"));
b30b6c
  std::wstring folderName = tempName.toStdWString();
b30b6c
  TFilePath folderPath    = parentFolder + folderName;
9b8bdb
  //int i                   = 1;
b30b6c
  while (TFileStatus(folderPath).doesExist())
b30b6c
    folderPath = parentFolder + (folderName + L" " + std::to_wstring(++i));
b30b6c
b30b6c
  try {
b30b6c
    TSystem::mkDir(folderPath);
b30b6c
b30b6c
  } catch (...) {
b30b6c
    DVGui::error(tr("It is not possible to create the %1 folder.")
b30b6c
                     .arg(toQString(folderPath)));
b30b6c
    return;
b30b6c
  }
b30b6c
b30b6c
  DvDirModel *model = DvDirModel::instance();
b30b6c
b30b6c
  QModelIndex parentFolderIndex = m_folderTreeView->currentIndex();
b30b6c
  model->refresh(parentFolderIndex);
b30b6c
  m_folderTreeView->expand(parentFolderIndex);
b30b6c
b30b6c
  std::wstring newFolderName = folderPath.getWideName();
b30b6c
  QModelIndex newFolderIndex =
b30b6c
      model->childByName(parentFolderIndex, newFolderName);
b30b6c
  if (newFolderIndex.isValid()) {
b30b6c
    m_folderTreeView->setCurrentIndex(newFolderIndex);
b30b6c
    m_folderTreeView->scrollTo(newFolderIndex);
b30b6c
    m_folderTreeView->QAbstractItemView::edit(newFolderIndex);
b30b6c
  }
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::showEvent(QShowEvent *) {
b96f40
  activePreproductionBoards.insert(this);
b30b6c
  // refresh
b30b6c
  if (getFolder() != TFilePath())
b30b6c
    setFolder(getFolder(), false, true);
b30b6c
  else if (getDayDateString() != "")
b30b6c
    setHistoryDay(getDayDateString());
b30b6c
  m_folderTreeView->scrollTo(m_folderTreeView->currentIndex());
b30b6c
b30b6c
  // Refresh SVN
b30b6c
  DvDirVersionControlNode *vcNode = dynamic_cast<dvdirversioncontrolnode *="">(</dvdirversioncontrolnode>
b30b6c
      m_folderTreeView->getCurrentNode());
b30b6c
  if (vcNode) m_folderTreeView->refreshVersionControl(vcNode);
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::hideEvent(QHideEvent *) {
b96f40
  activePreproductionBoards.erase(this);
b30b6c
  m_itemViewer->getPanel()->getItemViewPlayDelegate()->resetPlayWidget();
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::makeCurrentProjectVisible() {}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::enableGlobalSelection(bool enabled) {
b30b6c
  m_folderTreeView->enableGlobalSelection(enabled);
b30b6c
  m_itemViewer->enableGlobalSelection(enabled);
b30b6c
}
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::selectNone() { m_itemViewer->selectNone(); }
b30b6c
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::enableDoubleClickToOpenScenes() {
b30b6c
  // perhaps this should disconnect existing signal handlers first
b30b6c
  connect(this, SIGNAL(filePathDoubleClicked(const TFilePath &)), this,
b30b6c
          SLOT(tryToOpenScene(const TFilePath &)));
b30b6c
}
b30b6c
6081f1
void SceneBrowser::enableSingleClickToOpenScenes() {
6081f1
  // perhaps this should disconnect existing signal handlers first
6081f1
  connect(this, SIGNAL(filePathClicked(const TFilePath &)), this,
6081f1
          SLOT(tryToOpenScene(const TFilePath &)));
6081f1
}
6081f1
b30b6c
//-----------------------------------------------------------------------------
b30b6c
b96f40
void SceneBrowser::tryToOpenScene(const TFilePath &filePath) {
b30b6c
  if (filePath.getType() == "tnz") {
b30b6c
    IoCmd::loadScene(filePath);
b30b6c
  }
b30b6c
}
b30b6c
b30b6c
//=============================================================================
b30b6c
b30b6c
OpenFloatingPanel openPreproductionBoardPane(MI_OpenPreproductionBoard, "PreproductionBoard",
b30b6c
                                  QObject::tr("Preproduction Board"));