diff --git a/stuff/profiles/layouts/rooms/Default/menubar_template.xml b/stuff/profiles/layouts/rooms/Default/menubar_template.xml
index 1898a36..8218e71 100644
--- a/stuff/profiles/layouts/rooms/Default/menubar_template.xml
+++ b/stuff/profiles/layouts/rooms/Default/menubar_template.xml
@@ -40,6 +40,8 @@
MI_Preferences
MI_ShortcutPopup
+ MI_ClearCacheFolder
+
MI_Quit
MI_About
diff --git a/toonz/sources/common/tapptools/tenv.cpp b/toonz/sources/common/tapptools/tenv.cpp
index 9918612..fce9708 100644
--- a/toonz/sources/common/tapptools/tenv.cpp
+++ b/toonz/sources/common/tapptools/tenv.cpp
@@ -33,10 +33,9 @@ using namespace TVER;
namespace {
const std::map systemPathMap{
- {"LIBRARY", "library"}, {"STUDIOPALETTE", "studiopalette"},
- {"FXPRESETS", "fxs"}, {"CACHEROOT", "cache"},
- {"PROFILES", "profiles"}, {"CONFIG", "config"},
- {"PROJECTS", "projects"}};
+ {"LIBRARY", "library"}, {"STUDIOPALETTE", "studiopalette"},
+ {"FXPRESETS", "fxs"}, {"PROFILES", "profiles"},
+ {"CONFIG", "config"}, {"PROJECTS", "projects"}};
class EnvGlobals { // singleton
@@ -470,7 +469,7 @@ Variable::Variable(std::string name)
Variable::Variable(std::string name, std::string defaultValue)
: m_imp(VariableSet::instance()->getImp(name)) {
// assert(!m_imp->m_defaultDefined);
- m_imp->m_defaultDefined = true;
+ m_imp->m_defaultDefined = true;
if (!m_imp->m_loaded) m_imp->m_value = defaultValue;
}
@@ -567,11 +566,11 @@ TFilePathSet TEnv::getSystemVarPathSetValue(std::string varName) {
TFilePathSet lst;
EnvGlobals *eg = EnvGlobals::instance();
// if the path is registered by command line argument, then use it
- std::string value = eg->getArgPathValue(varName);
+ std::string value = eg->getArgPathValue(varName);
if (value == "") value = eg->getSystemVarValue(varName);
- int len = (int)value.size();
- int i = 0;
- int j = value.find(';');
+ int len = (int)value.size();
+ int i = 0;
+ int j = value.find(';');
while (j != std::string::npos) {
std::string s = value.substr(i, j - i);
lst.push_back(TFilePath(s));
diff --git a/toonz/sources/tcleanupper/tcleanupper.cpp b/toonz/sources/tcleanupper/tcleanupper.cpp
index 852163e..05746b4 100644
--- a/toonz/sources/tcleanupper/tcleanupper.cpp
+++ b/toonz/sources/tcleanupper/tcleanupper.cpp
@@ -224,7 +224,7 @@ int FarmControllerPort;
TFarmController *FarmController = 0;
string TaskId;
-}
+} // namespace
//========================================================================
//
// searchLevelsToCleanup
@@ -491,6 +491,12 @@ int main(int argc, char *argv[]) {
// questo definisce la registry root e inizializza TEnv
TEnv::setRootVarName(rootVarName);
TEnv::setSystemVarPrefix(systemVarPrefix);
+
+ QCoreApplication::setOrganizationName("OpenToonz");
+ QCoreApplication::setOrganizationDomain("");
+ QCoreApplication::setApplicationName(
+ QString::fromStdString(TEnv::getApplicationName()));
+
TSystem::hasMainLoop(false);
int i;
for (i = 0; i < argc; i++) // tmsg must be set as soon as it's possible
@@ -527,7 +533,7 @@ int main(int argc, char *argv[]) {
TVectorImagePatternStrokeStyle::setRootDir(libraryFolder);
TPalette::setRootDir(libraryFolder);
TImageStyle::setLibraryDir(libraryFolder);
- TFilePath cacheRoot = ToonzFolder::getCacheRootFolder();
+ TFilePath cacheRoot = ToonzFolder::getCacheRootFolder();
if (cacheRoot.isEmpty()) cacheRoot = TEnv::getStuffDir() + "cache";
TImageCache::instance()->setRootDir(cacheRoot);
diff --git a/toonz/sources/tcomposer/tcomposer.cpp b/toonz/sources/tcomposer/tcomposer.cpp
index 3eea750..e3b1d39 100644
--- a/toonz/sources/tcomposer/tcomposer.cpp
+++ b/toonz/sources/tcomposer/tcomposer.cpp
@@ -658,6 +658,11 @@ int main(int argc, char *argv[]) {
TEnv::setRootVarName(rootVarName);
TEnv::setSystemVarPrefix(systemVarPrefix);
+ QCoreApplication::setOrganizationName("OpenToonz");
+ QCoreApplication::setOrganizationDomain("");
+ QCoreApplication::setApplicationName(
+ QString::fromStdString(TEnv::getApplicationName()));
+
QHash::const_iterator argItr =
argumentPathValues.constBegin();
while (argItr != argumentPathValues.constEnd()) {
diff --git a/toonz/sources/toonz/main.cpp b/toonz/sources/toonz/main.cpp
index 8ae73fc..8c2bbeb 100644
--- a/toonz/sources/toonz/main.cpp
+++ b/toonz/sources/toonz/main.cpp
@@ -166,7 +166,7 @@ static void initToonzEnv(QHash &argPathValues) {
QCoreApplication::setOrganizationName("OpenToonz");
QCoreApplication::setOrganizationDomain("");
QCoreApplication::setApplicationName(
- QString::fromStdString(TEnv::getApplicationFullName()));
+ QString::fromStdString(TEnv::getApplicationName()));
/*-- TOONZROOTのPathの確認 --*/
// controllo se la xxxroot e' definita e corrisponde ad un folder esistente
@@ -229,7 +229,7 @@ project->setUseScenePath(TProject::Extras, false);
// Imposto la rootDir per ImageCache
/*-- TOONZCACHEROOTの設定 --*/
- TFilePath cacheDir = ToonzFolder::getCacheRootFolder();
+ TFilePath cacheDir = ToonzFolder::getCacheRootFolder();
if (cacheDir.isEmpty()) cacheDir = TEnv::getStuffDir() + "cache";
TImageCache::instance()->setRootDir(cacheDir);
}
@@ -315,11 +315,10 @@ int main(int argc, char *argv[]) {
QApplication a(argc, argv);
#ifdef MACOSX
-// This workaround is to avoid missing left button problem on Qt5.6.0.
-// To invalidate m_rightButtonClicked in Qt/qnsview.mm, sending NSLeftButtonDown
-// event
-// before NSLeftMouseDragged event propagated to QApplication.
-// See more details in ../mousedragfilter/mousedragfilter.mm.
+ // This workaround is to avoid missing left button problem on Qt5.6.0.
+ // To invalidate m_rightButtonClicked in Qt/qnsview.mm, sending
+ // NSLeftButtonDown event before NSLeftMouseDragged event propagated to
+ // QApplication. See more details in ../mousedragfilter/mousedragfilter.mm.
#include "mousedragfilter.h"
diff --git a/toonz/sources/toonz/mainwindow.cpp b/toonz/sources/toonz/mainwindow.cpp
index 68f6062..a41612c 100644
--- a/toonz/sources/toonz/mainwindow.cpp
+++ b/toonz/sources/toonz/mainwindow.cpp
@@ -57,6 +57,7 @@
#include
#include
#include
+#include
TEnv::IntVar ViewCameraToggleAction("ViewCameraToggleAction", 1);
TEnv::IntVar ViewTableToggleAction("ViewTableToggleAction", 1);
@@ -459,6 +460,7 @@ centralWidget->setLayout(centralWidgetLayout);*/
&MainWindow::onNewToonzRasterLevelButtonPressed);
setCommandHandler("MI_NewRasterLevel", this,
&MainWindow::onNewRasterLevelButtonPressed);
+ setCommandHandler(MI_ClearCacheFolder, this, &MainWindow::clearCacheFolder);
// remove ffmpegCache if still exists from crashed exit
QString ffmpegCachePath =
ToonzFolder::getCacheRootFolder().getQString() + "//ffmpeg";
@@ -1596,6 +1598,7 @@ void MainWindow::defineActions() {
createMenuAction(MI_LoadRecentImage, tr("&Load Recent Image Files"), files);
createMenuFileAction(MI_ClearRecentImage,
tr("&Clear Recent Flipbook Image List"), "");
+ createMenuFileAction(MI_ClearCacheFolder, tr("&Clear Cache Folder"), "");
createRightClickMenuAction(MI_PreviewFx, tr("Preview Fx"), "");
@@ -2337,6 +2340,96 @@ void MainWindow::onNewRasterLevelButtonPressed() {
}
//-----------------------------------------------------------------------------
+// delete unused files / folders in the cache
+void MainWindow::clearCacheFolder() {
+ // currently cache folder is used for following purposes
+ // 1. $CACHE/[ProcessID] : for disk swap of image cache.
+ // To be deleted on exit. Remains on crash.
+ // 2. $CACHE/ffmpeg : ffmpeg cache.
+ // To be cleared on the end of rendering, on exist and on launch.
+ // 3. $CACHE/temp : untitled scene data.
+ // To be deleted on switching or exiting scenes. Remains on crash.
+
+ // So, this function will delete all files / folders in $CACHE
+ // except the following items:
+ // 1. $CACHE/[Current ProcessID]
+ // 2. $CACHE/temp/[Current scene folder] if the current scene is untitled
+
+ TFilePath cacheRoot = ToonzFolder::getCacheRootFolder();
+ if (cacheRoot.isEmpty()) cacheRoot = TEnv::getStuffDir() + "cache";
+
+ TFilePathSet filesToBeRemoved;
+
+ TSystem::readDirectory(filesToBeRemoved, cacheRoot, false);
+
+ // keep the imagecache folder
+ filesToBeRemoved.remove(cacheRoot + std::to_string(TSystem::getProcessId()));
+ // keep the untitled scene data folder
+ if (TApp::instance()->getCurrentScene()->getScene()->isUntitled()) {
+ filesToBeRemoved.remove(cacheRoot + "temp");
+ TFilePathSet untitledData =
+ TSystem::readDirectory(cacheRoot + "temp", false);
+ untitledData.remove(TApp::instance()
+ ->getCurrentScene()
+ ->getScene()
+ ->getScenePath()
+ .getParentDir());
+ filesToBeRemoved.insert(filesToBeRemoved.end(), untitledData.begin(),
+ untitledData.end());
+ }
+
+ // return if there is no files/folders to be deleted
+ if (filesToBeRemoved.size() == 0) {
+ QMessageBox::information(
+ this, tr("Clear Cache Folder"),
+ tr("There are no unused items in the cache folder."));
+ return;
+ }
+
+ QString message(tr("Deleting the following items:\n"));
+ int count = 0;
+ for (const auto &fileToBeRemoved : filesToBeRemoved) {
+ QString dirPrefix =
+ (TFileStatus(fileToBeRemoved).isDirectory()) ? tr(" ") : "";
+ message +=
+ " " + dirPrefix + (fileToBeRemoved - cacheRoot).getQString() + "\n";
+ count++;
+ if (count == 5) break;
+ }
+ if (filesToBeRemoved.size() > 5)
+ message +=
+ tr(" ... and %1 more items\n").arg(filesToBeRemoved.size() - 5);
+
+ message +=
+ tr("\nAre you sure?\n\nN.B. Make sure you are not running another "
+ "process of OpenToonz,\nor you may delete necessary files for it.");
+
+ QMessageBox::StandardButton ret = QMessageBox::question(
+ this, tr("Clear Cache Folder"), message,
+ QMessageBox::StandardButtons(QMessageBox::Ok | QMessageBox::Cancel));
+
+ if (ret != QMessageBox::Ok) return;
+
+ for (const auto &fileToBeRemoved : filesToBeRemoved) {
+ try {
+ if (TFileStatus(fileToBeRemoved).isDirectory())
+ TSystem::rmDirTree(fileToBeRemoved);
+ else
+ TSystem::deleteFile(fileToBeRemoved);
+ } catch (TException &e) {
+ QMessageBox::warning(
+ this, tr("Clear Cache Folder"),
+ tr("Can't delete %1 : ").arg(fileToBeRemoved.getQString()) +
+ QString::fromStdWString(e.getMessage()));
+ } catch (...) {
+ QMessageBox::warning(
+ this, tr("Clear Cache Folder"),
+ tr("Can't delete %1 : ").arg(fileToBeRemoved.getQString()));
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
class ReloadStyle final : public MenuItemHandler {
public:
diff --git a/toonz/sources/toonz/mainwindow.h b/toonz/sources/toonz/mainwindow.h
index 1e7379c..6bdbb26 100644
--- a/toonz/sources/toonz/mainwindow.h
+++ b/toonz/sources/toonz/mainwindow.h
@@ -112,6 +112,7 @@ public:
void onNewVectorLevelButtonPressed();
void onNewToonzRasterLevelButtonPressed();
void onNewRasterLevelButtonPressed();
+ void clearCacheFolder();
QString getLayoutName() { return m_layoutName; }
diff --git a/toonz/sources/toonz/menubar.cpp b/toonz/sources/toonz/menubar.cpp
index cc8d616..f7dc057 100644
--- a/toonz/sources/toonz/menubar.cpp
+++ b/toonz/sources/toonz/menubar.cpp
@@ -117,7 +117,7 @@ void RoomTabWidget::mouseReleaseEvent(QMouseEvent *event) {
//-----------------------------------------------------------------------------
/*! Set a text field with focus in event position to edit tab name.
-*/
+ */
void RoomTabWidget::mouseDoubleClickEvent(QMouseEvent *event) {
if (m_isLocked) return;
int index = tabAt(event->pos());
@@ -1117,6 +1117,8 @@ QMenuBar *StackedMenuBar::createFullMenuBar() {
addMenuItem(fileMenu, MI_Preferences);
addMenuItem(fileMenu, MI_ShortcutPopup);
fileMenu->addSeparator();
+ addMenuItem(fileMenu, MI_ClearCacheFolder);
+ fileMenu->addSeparator();
addMenuItem(fileMenu, MI_Quit);
// Menu' EDIT
diff --git a/toonz/sources/toonz/menubarcommandids.h b/toonz/sources/toonz/menubarcommandids.h
index 3f7dba7..4882888 100644
--- a/toonz/sources/toonz/menubarcommandids.h
+++ b/toonz/sources/toonz/menubarcommandids.h
@@ -346,5 +346,5 @@
#define MI_SeparateColors "MI_SeparateColors"
#define MI_OpenOnlineManual "MI_OpenOnlineManual"
-
+#define MI_ClearCacheFolder "MI_ClearCacheFolder"
#endif
diff --git a/toonz/sources/toonzlib/toonzfolders.cpp b/toonz/sources/toonzlib/toonzfolders.cpp
index a9bc0cf..223e527 100644
--- a/toonz/sources/toonzlib/toonzfolders.cpp
+++ b/toonz/sources/toonzlib/toonzfolders.cpp
@@ -6,6 +6,7 @@
#include "tconvert.h"
#include "toonz/preferences.h"
#include
+#include
using namespace TEnv;
@@ -23,7 +24,7 @@ TFilePath getDesktopPath() {
QStandardPaths::standardLocations(QStandardPaths::DesktopLocation)[0];
return TFilePath(desktopPath);
}
-}
+} // namespace
//-------------------------------------------------------------------
TFilePath ToonzFolder::getModulesDir() {
@@ -107,10 +108,16 @@ TFilePath ToonzFolder::getFxPresetFolder() {
}
TFilePath ToonzFolder::getCacheRootFolder() {
- TFilePath fp = getSystemVarPathValue(getSystemVarPrefix() + "CACHEROOT");
- if (fp == TFilePath())
- fp = getStuffDir() + TEnv::getSystemPathMap().at("CACHEROOT");
- return fp;
+ static enum STATE { FIRSTTIME, OK, NG } state = FIRSTTIME;
+ QString cacheDir =
+ QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
+ if (state == FIRSTTIME) {
+ if (QDir(cacheDir).mkpath("."))
+ state = OK;
+ else
+ state = NG;
+ }
+ return (state == OK) ? TFilePath(cacheDir) : TFilePath();
}
TFilePath ToonzFolder::getProfileFolder() {