diff --git a/toonz/sources/toonz/filebrowsermodel.cpp b/toonz/sources/toonz/filebrowsermodel.cpp index d349a627..35c93ab7 100644 --- a/toonz/sources/toonz/filebrowsermodel.cpp +++ b/toonz/sources/toonz/filebrowsermodel.cpp @@ -126,6 +126,13 @@ void DvDirModelNode::addChild(DvDirModelNode *child) { //----------------------------------------------------------------------------- +void DvDirModelNode::insertChild(int row, DvDirModelNode *child) { + child->setRow(row); + m_children.insert(m_children.begin() + row, child); +} + +//----------------------------------------------------------------------------- + int DvDirModelNode::getChildCount() { if (!m_childrenValid) refreshChildren(); return (int)m_children.size(); @@ -1108,6 +1115,34 @@ void DvDirModelRootNode::add(std::wstring name, const TFilePath &path) { //----------------------------------------------------------------------------- +void DvDirModelRootNode::refreshDefaultProjectPath() { + removeChildren(8, m_projectDirNodes.size()); + m_projectDirNodes.clear(); + + QString defaultProjectPaths = + Preferences::instance()->getDefaultProjectPath(); + if (!defaultProjectPaths.isEmpty()) { + QStringList projectRoots = + defaultProjectPaths.split(";", QString::SkipEmptyParts); + for (int i = 0; i < projectRoots.size(); i++) { + TFilePath projectRootDir(projectRoots.at(i)); + if (!TFileStatus(projectRootDir).isDirectory()) continue; + std::wstring folderName = L"Projects"; + if (projectRoots.size() > 1) + folderName += + L" (" + projectRootDir.withoutParentDir().getWideString() + L")"; + DvDirModelSpecialFileFolderNode *projectFolderNode = + new DvDirModelSpecialFileFolderNode(this, folderName, projectRootDir); + projectFolderNode->setPixmap(recolorPixmap( + svgToPixmap(getIconThemePath("actions/16/projects_folder.svg")))); + m_projectDirNodes.push_back(projectFolderNode); + insertChild(8 + i, projectFolderNode); + } + } +} + +//----------------------------------------------------------------------------- + void DvDirModelRootNode::refreshChildren() { m_childrenValid = true; if (m_children.empty()) { @@ -1156,6 +1191,28 @@ void DvDirModelRootNode::refreshChildren() { addChild(new DvDirModelHistoryNode(this)); + QString defaultProjectPaths = + Preferences::instance()->getDefaultProjectPath(); + if (!defaultProjectPaths.isEmpty()) { + QStringList projectRoots = + defaultProjectPaths.split(";", QString::SkipEmptyParts); + for (int i = 0; i < projectRoots.size(); i++) { + TFilePath projectRootDir(projectRoots.at(i)); + if (!TFileStatus(projectRootDir).isDirectory()) continue; + std::wstring folderName = L"Projects"; + if (projectRoots.size() > 1) + folderName += + L" (" + projectRootDir.withoutParentDir().getWideString() + L")"; + DvDirModelSpecialFileFolderNode *projectFolderNode = + new DvDirModelSpecialFileFolderNode(this, folderName, + projectRootDir); + projectFolderNode->setPixmap(recolorPixmap( + svgToPixmap(getIconThemePath("actions/16/projects_folder.svg")))); + m_projectDirNodes.push_back(projectFolderNode); + addChild(projectFolderNode); + } + } + TProjectManager *pm = TProjectManager::instance(); TFilePath sandboxProjectPath = pm->getSandboxProjectFolder(); m_projectPaths.insert(sandboxProjectPath); @@ -1289,6 +1346,12 @@ DvDirModelNode *DvDirModelRootNode::getNodeByPath(const TFilePath &path) { if (node) return node; } + // check for the project root folders + for (DvDirModelSpecialFileFolderNode *projectDirNode : m_projectDirNodes) { + DvDirModelNode *node = projectDirNode->getNodeByPath(path); + if (node) return node; + } + // it could be a regular folder, somewhere in the file system if (m_myComputerNode) { for (i = 0; i < m_myComputerNode->getChildCount(); i++) { @@ -1593,12 +1656,15 @@ void DvDirModel::onSceneSwitched() { //----------------------------------------------------------------------------- void DvDirModel::onPreferenceChanged(const QString &prefName) { - if (prefName != "PathAliasPriority") return; - - Preferences::PathAliasPriority priority = - Preferences::instance()->getPathAliasPriority(); DvDirModelRootNode *rootNode = dynamic_cast(m_root); - if (rootNode) + if (!rootNode) return; + if (prefName == "PathAliasPriority") { + Preferences::PathAliasPriority priority = + Preferences::instance()->getPathAliasPriority(); rootNode->updateSceneFolderNodeVisibility(priority == Preferences::ProjectFolderOnly); + } else if (prefName == "DefaultProjectPath") { + rootNode->refreshDefaultProjectPath(); + emit layoutChanged(); + } } diff --git a/toonz/sources/toonz/filebrowsermodel.h b/toonz/sources/toonz/filebrowsermodel.h index 7fd837d6..d1966b1d 100644 --- a/toonz/sources/toonz/filebrowsermodel.h +++ b/toonz/sources/toonz/filebrowsermodel.h @@ -44,6 +44,7 @@ public: void removeChildren(int row, int count); void addChild(DvDirModelNode *child); + void insertChild(int row, DvDirModelNode *child); virtual void visualizeContent(FileBrowser *browser) {} // ????????????? virtual QPixmap getPixmap(bool isOpen) const; @@ -324,11 +325,13 @@ class DvDirModelRootNode final : public DvDirModelNode { std::set m_projectPaths; DvDirModelSceneFolderNode *m_sceneFolderNode; std::vector m_specialNodes; + std::vector m_projectDirNodes; void add(std::wstring name, const TFilePath &path); public: DvDirModelRootNode(); + void refreshDefaultProjectPath(); void refreshChildren() override; int getProjectPathsSize() { return m_projectPaths.size(); } diff --git a/toonz/sources/toonz/icons/dark/actions/16/projects_folder.svg b/toonz/sources/toonz/icons/dark/actions/16/projects_folder.svg new file mode 100644 index 00000000..30cfd877 --- /dev/null +++ b/toonz/sources/toonz/icons/dark/actions/16/projects_folder.svg @@ -0,0 +1,67 @@ + +image/svg+xml + + + diff --git a/toonz/sources/toonz/preferencespopup.cpp b/toonz/sources/toonz/preferencespopup.cpp index 13fc575c..d8fb854c 100644 --- a/toonz/sources/toonz/preferencespopup.cpp +++ b/toonz/sources/toonz/preferencespopup.cpp @@ -443,6 +443,14 @@ QList PreferencesPopup::buildFontStyleList() const { //----------------------------------------------------------------------------- +void PreferencesPopup::onDefaultProjectPathChanged() { + // emit signal to update behavior of the File browser + TApp::instance()->getCurrentScene()->notifyPreferenceChanged( + "DefaultProjectPath"); +} + +//----------------------------------------------------------------------------- + void PreferencesPopup::onAutoSaveChanged() { bool on = getUI(autosaveEnabled)->isChecked(); if (!on) return; @@ -1604,6 +1612,8 @@ QWidget* PreferencesPopup::createGeneralPage() { pathAliasPriorityCB->setItemData(1, scenefolderTooltip, Qt::ToolTipRole); pathAliasPriorityCB->setItemData(2, QString(" "), Qt::ToolTipRole); + m_onEditedFuncMap.insert(defaultProjectPath, + &PreferencesPopup::onDefaultProjectPathChanged); m_onEditedFuncMap.insert(autosaveEnabled, &PreferencesPopup::onAutoSaveChanged); m_onEditedFuncMap.insert(autosaveSceneEnabled, diff --git a/toonz/sources/toonz/preferencespopup.h b/toonz/sources/toonz/preferencespopup.h index a233e733..602c4eb4 100644 --- a/toonz/sources/toonz/preferencespopup.h +++ b/toonz/sources/toonz/preferencespopup.h @@ -135,6 +135,7 @@ private: //--- callbacks --- // General + void onDefaultProjectPathChanged(); void onAutoSaveChanged(); void onAutoSaveOptionsChanged(); void onWatchFileSystemClicked(); diff --git a/toonz/sources/toonz/toonz.qrc b/toonz/sources/toonz/toonz.qrc index e6c5ac0d..f02704c1 100644 --- a/toonz/sources/toonz/toonz.qrc +++ b/toonz/sources/toonz/toonz.qrc @@ -138,6 +138,7 @@ icons/dark/actions/16/fb_down.svg icons/dark/actions/16/viewlist.svg icons/dark/actions/16/viewicon.svg + icons/dark/actions/16/projects_folder.svg icons/dark/actions/16/favorites.svg icons/dark/actions/18/folder_project_root.svg