From 5b3c7c43256f726a05c1e88e9d921e5f58786f2e Mon Sep 17 00:00:00 2001 From: shun-iwasawa Date: Jun 02 2016 11:55:00 +0000 Subject: Refresh the current folder items of the File Browser automatically (#376) * refresh file browser items automatically * monitor directory tree * remove refresh button * add a new folder to monitored paths --- diff --git a/toonz/sources/toonz/dvdirtreeview.cpp b/toonz/sources/toonz/dvdirtreeview.cpp index c84e260..f2521e8 100644 --- a/toonz/sources/toonz/dvdirtreeview.cpp +++ b/toonz/sources/toonz/dvdirtreeview.cpp @@ -27,6 +27,7 @@ #include #include #include +#include using namespace DVGui; @@ -292,6 +293,8 @@ DvDirTreeView::DvDirTreeView(QWidget *parent) setIndentation(14); setAlternatingRowColors(true); + m_dirFileSystemWatcher = new QFileSystemWatcher(this); + //Connect all possible changes that can alter the //bottom horizontal scrollbar to resize contents... connect( @@ -306,7 +309,21 @@ DvDirTreeView::DvDirTreeView(QWidget *parent) this->model(), SIGNAL(layoutChanged()), this, SLOT(resizeToConts())); + connect( + this, SIGNAL(expanded(const QModelIndex &)), + this, SLOT(onExpanded(const QModelIndex &))); + + connect( + this, SIGNAL(collapsed(const QModelIndex &)), + this, SLOT(onCollapsed(const QModelIndex &))); + + connect( + m_dirFileSystemWatcher, SIGNAL(directoryChanged(const QString &)), + this, SLOT(onMonitoredDirectoryChanged(const QString &))); + setAcceptDrops(true); + + updateWatcher(); } //----------------------------------------------------------------------------- @@ -1528,6 +1545,79 @@ DvItemListModel::Status DvDirTreeView::getItemVersionControlStatus( return DvItemListModel::VC_None; } +/*- Refresh monitoring paths according to expand/shrink state of the folder tree -*/ +void DvDirTreeView::updateWatcher() +{ + if (!m_dirFileSystemWatcher->directories().isEmpty()) + m_dirFileSystemWatcher->removePaths(m_dirFileSystemWatcher->directories()); + + QStringList paths; + getExpandedPathsRecursive(rootIndex(), paths); + + m_dirFileSystemWatcher->addPaths(paths); +} + +void DvDirTreeView::getExpandedPathsRecursive(const QModelIndex& index, QStringList& paths) +{ + DvDirModelNode* node = DvDirModel::instance()->getNode(index); + DvDirModelFileFolderNode* fileFolderNode = dynamic_cast(node); + if (fileFolderNode) + { + QString path = toQString(fileFolderNode->getPath()); + if (!paths.contains(path)) + { + paths.append(path); + } + } + /*- serch child nodes if this node is expanded -*/ + if (index!=rootIndex() && !isExpanded(index)) + return; + + int count = DvDirModel::instance()->rowCount(index); + for (int r = 0; r < count; r++) + { + QModelIndex child = DvDirModel::instance()->index(r, 0, index); + getExpandedPathsRecursive(child, paths); + } +} + +void DvDirTreeView::onExpanded(const QModelIndex & index) +{ + QStringList paths; + getExpandedPathsRecursive(index, paths); + m_dirFileSystemWatcher->addPaths(paths); +} + +void DvDirTreeView::onCollapsed(const QModelIndex & index) +{ + QStringList paths; + int count = DvDirModel::instance()->rowCount(index); + for (int r = 0; r < count; r++) + { + QModelIndex child = DvDirModel::instance()->index(r, 0, index); + getExpandedPathsRecursive(child, paths); + } + m_dirFileSystemWatcher->removePaths(paths); +} + +void DvDirTreeView::onMonitoredDirectoryChanged(const QString & dirPath) +{ + DvDirModel::instance()->refreshFolder(TFilePath(dirPath)); + + /*- the change may be adding of a new folder, which is needed to be added to the monitored paths -*/ + DvDirModelNode* node = DvDirModel::instance()->getNode(rootIndex())->getNodeByPath(TFilePath(dirPath)); + if (!node) return; + QStringList paths; + for (int c = 0; c < node->getChildCount(); c++) + { + DvDirModelFileFolderNode* childNode = dynamic_cast(node->getChild(c)); + if (childNode) + paths.append(toQString(childNode->getPath())); + } + /*- if there are paths which are already being monitored, they will be ignored. -*/ + m_dirFileSystemWatcher->addPaths(paths); +} + //============================================================================= // NodeEditor //----------------------------------------------------------------------------- diff --git a/toonz/sources/toonz/dvdirtreeview.h b/toonz/sources/toonz/dvdirtreeview.h index 35f79f8..6b0b545 100644 --- a/toonz/sources/toonz/dvdirtreeview.h +++ b/toonz/sources/toonz/dvdirtreeview.h @@ -28,6 +28,7 @@ class DvDirModel; class DvDirModelNode; class DvDirVersionControlNode; class DvDirTreeView; +class QFileSystemWatcher; //============================================================== @@ -145,6 +146,10 @@ public slots: void onRefreshStatusDone(const QString &); void onRefreshStatusError(const QString &); + void onExpanded(const QModelIndex &); + void onCollapsed(const QModelIndex &); + void onMonitoredDirectoryChanged(const QString &); + protected: QSize sizeHint() const; @@ -175,6 +180,11 @@ private: // Using for version control node refreshing DvDirVersionControlNode *m_currentRefreshedNode; + + QFileSystemWatcher * m_dirFileSystemWatcher; + /*- Refresh monitoring paths according to expand/shrink state of the folder tree -*/ + void updateWatcher(); + void getExpandedPathsRecursive(const QModelIndex&, QStringList&); }; //********************************************************************************** diff --git a/toonz/sources/toonz/dvitemview.cpp b/toonz/sources/toonz/dvitemview.cpp index b569643..a39b0df 100644 --- a/toonz/sources/toonz/dvitemview.cpp +++ b/toonz/sources/toonz/dvitemview.cpp @@ -1881,11 +1881,12 @@ DvItemViewerButtonBar::DvItemViewerButtonBar(DvItemViewer *itemViewer, QWidget * // actions->addAction(tableView); // addAction(tableView); addSeparator(); - + // button to export file list to csv QAction *exportFileListAction = new QAction(tr("Export File List"), this); addAction(exportFileListAction); addSeparator(); + connect(exportFileListAction, SIGNAL(triggered()), itemViewer->getPanel(), SLOT(exportFileList())); connect(folderUp, SIGNAL(triggered()), SIGNAL(folderUp())); diff --git a/toonz/sources/toonz/filebrowser.cpp b/toonz/sources/toonz/filebrowser.cpp index 52f3fc4..fcc3935 100644 --- a/toonz/sources/toonz/filebrowser.cpp +++ b/toonz/sources/toonz/filebrowser.cpp @@ -75,6 +75,7 @@ #include #include #include +#include // tcg includes #include "tcg/boost/range_utility.h" @@ -179,6 +180,8 @@ FileBrowser::FileBrowser(QWidget *parent, Qt::WFlags flags, bool noContextMenu, DvItemViewerButtonBar *buttonBar = new DvItemViewerButtonBar(m_itemViewer, box); DvItemViewerPanel *viewerPanel = m_itemViewer->getPanel(); + m_fileSystemWatcher = new QFileSystemWatcher(this); + viewerPanel->addColumn(DvItemListModel::FileType, 50); viewerPanel->addColumn(DvItemListModel::FrameCount, 50); viewerPanel->addColumn(DvItemListModel::FileSize, 50); @@ -260,6 +263,9 @@ FileBrowser::FileBrowser(QWidget *parent, Qt::WFlags flags, bool noContextMenu, // when the history changes, enable/disable the history buttons accordingly ret = ret && connect(this, SIGNAL(historyChanged(bool, bool)), buttonBar, SLOT(onHistoryChanged(bool, bool))); + // check out the update of the current folder + ret = ret && connect(m_fileSystemWatcher, SIGNAL(directoryChanged(const QString&)), this, SLOT(onFileSystemChanged(const QString&))); + // store the first item("Root") in the history m_indexHistoryList.append(m_folderTreeView->currentIndex()); m_currentPosition = 0; @@ -397,6 +403,18 @@ void FileBrowser::clearHistory() } //----------------------------------------------------------------------------- +/*! update the current folder when changes detected from QFileSystemWatcher +*/ +void FileBrowser::onFileSystemChanged(const QString& folderPath) +{ + //changes may create/delete of folder, so update the DvDirModel + QModelIndex parentFolderIndex = m_folderTreeView->currentIndex(); + DvDirModel::instance()->refresh(parentFolderIndex); + + refreshCurrentFolderItems(); +} + +//----------------------------------------------------------------------------- void FileBrowser::sortByDataModel(DataType dataType, bool isDiscendent) { @@ -502,30 +520,18 @@ void FileBrowser::removeFilterType(const QString &type) //----------------------------------------------------------------------------- -void FileBrowser::setFolder(const TFilePath &fp, bool expandNode) +void FileBrowser::refreshCurrentFolderItems() { - if (fp == m_folder) - return; - - //set the current folder path - m_folder = fp; - m_dayDateString = ""; - //set the folder name - if (fp == TFilePath()) - m_folderName->setText(""); - else - m_folderName->setText(toQString(fp)); - m_items.clear(); // put the parent directory item - TFilePath parentFp = fp.getParentDir(); - if (parentFp != TFilePath("") && parentFp != fp) + TFilePath parentFp = m_folder.getParentDir(); + if (parentFp != TFilePath("") && parentFp != m_folder) m_items.push_back(Item(parentFp, true, false)); // register the all folder items by using the folde tree model DvDirModel *model = DvDirModel::instance(); - QModelIndex currentIndex = model->getIndexByPath(fp); + QModelIndex currentIndex = model->getIndexByPath(m_folder); if (currentIndex.isValid()) { for (int i = 0; i < model->rowCount(currentIndex); i++) { QModelIndex tmpIndex = model->index(i, 0, currentIndex); @@ -541,26 +547,28 @@ void FileBrowser::setFolder(const TFilePath &fp, bool expandNode) } } } - } else - setUnregisteredFolder(fp); + } + else + setUnregisteredFolder(m_folder); // register the file items - if (fp != TFilePath()) { + if (m_folder != TFilePath()) { TFilePathSet files; TFilePathSet all_files; // for updating m_multiFileItemMap - TFileStatus fpStatus(fp); + TFileStatus fpStatus(m_folder); //if the item is link, then set the link target of it if (fpStatus.isLink()) { - QFileInfo info(toQString(fp)); + QFileInfo info(toQString(m_folder)); setFolder(TFilePath(info.symLinkTarget().toStdWString())); return; } if (fpStatus.doesExist() && fpStatus.isDirectory() && fpStatus.isReadable()) { try { - TSystem::readDirectory(files, all_files, fp); - } catch (...) { + TSystem::readDirectory(files, all_files, m_folder); + } + catch (...) { } } TFilePathSet::iterator it; @@ -579,7 +587,8 @@ void FileBrowser::setFolder(const TFilePath &fp, bool expandNode) it->getType() != "tpl" && TFileType::getInfo(*it) == TFileType::UNKNOW_FILE) continue; - } else if (!m_filter.contains(QString::fromStdString(it->getType()))) + } + else if (!m_filter.contains(QString::fromStdString(it->getType()))) continue; //store the filtered file paths m_items.push_back(Item(*it)); @@ -642,6 +651,30 @@ void FileBrowser::setFolder(const TFilePath &fp, bool expandNode) setOrderType(Name); setIsDiscendentOrder(true); sortByDataModel(currentDataType, discendentOrder); +} + +//----------------------------------------------------------------------------- + +void FileBrowser::setFolder(const TFilePath &fp, bool expandNode, bool forceUpdate) +{ + if (fp == m_folder && !forceUpdate) + return; + + //set the current folder path + m_folder = fp; + m_dayDateString = ""; + //set the folder name + if (fp == TFilePath()) + m_folderName->setText(""); + else + m_folderName->setText(toQString(fp)); + + /*- reset the watching path -*/ + m_fileSystemWatcher->removePaths(m_fileSystemWatcher->directories()); + if (fp != TFilePath()) + m_fileSystemWatcher->addPath(toQString(fp)); + + refreshCurrentFolderItems(); m_folderTreeView->setCurrentNode(fp, expandNode); } @@ -2027,7 +2060,7 @@ void FileBrowser::refreshFolder(const TFilePath &folderPath) FileBrowser *browser = *it; DvDirModel::instance()->refreshFolder(folderPath); if (browser->getFolder() == folderPath) { - browser->setFolder(folderPath); + browser->setFolder(folderPath, false, true); } } } @@ -2081,7 +2114,7 @@ void FileBrowser::refresh() } m_folderTreeView->verticalScrollBar()->setValue(dx); - setFolder(originalFolder); + setFolder(originalFolder, false, true); } //----------------------------------------------------------------------------- @@ -2168,7 +2201,7 @@ void FileBrowser::showEvent(QShowEvent *) activeBrowsers.insert(this); // refresh if (getFolder() != TFilePath()) - setFolder(getFolder()); + setFolder(getFolder(), false, true); else if (getDayDateString() != "") setHistoryDay(getDayDateString()); m_folderTreeView->scrollTo(m_folderTreeView->currentIndex()); diff --git a/toonz/sources/toonz/filebrowser.h b/toonz/sources/toonz/filebrowser.h index 86f1483..3f4efdc 100644 --- a/toonz/sources/toonz/filebrowser.h +++ b/toonz/sources/toonz/filebrowser.h @@ -22,6 +22,7 @@ class QTreeWidgetItem; class QSplitter; class DvDirModelNode; class DvDirTreeView; +class QFileSystemWatcher; //----------------------------------------------------------------------------- @@ -91,7 +92,7 @@ public: const QStringList &getFilterTypes() const { return m_filter; } void removeFilterType(const QString &type); - void setFolder(const TFilePath &fp, bool expandNode = false); + void setFolder(const TFilePath &fp, bool expandNode = false, bool forceUpdate = false); // process when inputting the folder which is not regitered in the folder tree // (e.g. UNC path in Windows) void setUnregisteredFolder(const TFilePath &fp); @@ -179,6 +180,8 @@ protected slots: void onVersionControlCommandDone(const QStringList &files); + void onFileSystemChanged(const QString& folderPath); + signals: void filePathClicked(const TFilePath &); @@ -228,10 +231,14 @@ private: QStringList m_filter; std::map m_multiFileItemMap; + QFileSystemWatcher* m_fileSystemWatcher; + private: void readFrameCount(Item &item); void readInfo(Item &item); + void refreshCurrentFolderItems(); + DvItemListModel::Status getItemVersionControlStatus(const FileBrowser::Item &item); }; diff --git a/toonz/sources/toonz/mainwindow.cpp b/toonz/sources/toonz/mainwindow.cpp index 6378b39..bcd99e1 100644 --- a/toonz/sources/toonz/mainwindow.cpp +++ b/toonz/sources/toonz/mainwindow.cpp @@ -1946,7 +1946,7 @@ void MainWindow::defineActions() createViewerAction(V_ShowHideFullScreen, tr("Show//Hide Full Screen"), ""); CommandManager::instance()->setToggleTexts(V_ShowHideFullScreen, tr("Full Screen Mode"), tr("Exit Full Screen Mode")); - createMiscAction(MI_RefreshTree, "Refresh Folder Tree", ""); + createMiscAction(MI_RefreshTree, tr("Refresh Folder Tree"), ""); createToolOptionsAction("A_ToolOption_GlobalKey", tr("Global Key"), "");