forked from qt-creator/qt-creator
QmlDesigner: Track folders expanded/collapsed state in AssetsLibrary
Fixes: QDS-13791 Change-Id: I6d30e6d1d79da99466f0fa7b762267701bc2d2e2 Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
This commit is contained in:
@@ -48,6 +48,19 @@ TreeViewDelegate {
|
|||||||
root.depth -= root.assetsView.rootPathDepth
|
root.depth -= root.assetsView.rootPathDepth
|
||||||
root.initialDepth = root.depth
|
root.initialDepth = root.depth
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// expand/collapse folder based on its stored expanded state
|
||||||
|
if (root.__isDirectory) {
|
||||||
|
// if the folder expand state is not stored yet, stores it as true (expanded)
|
||||||
|
root.assetsModel.initializeExpandState(root.__itemPath)
|
||||||
|
|
||||||
|
let expandState = assetsModel.folderExpandState(root.__itemPath)
|
||||||
|
|
||||||
|
if (expandState)
|
||||||
|
root.assetsView.expand(root.__currentRow)
|
||||||
|
else
|
||||||
|
root.assetsView.collapse(root.__currentRow)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// workaround for a bug -- might be fixed by https://codereview.qt-project.org/c/qt/qtdeclarative/+/442721
|
// workaround for a bug -- might be fixed by https://codereview.qt-project.org/c/qt/qtdeclarative/+/442721
|
||||||
@@ -295,6 +308,8 @@ TreeViewDelegate {
|
|||||||
} else {
|
} else {
|
||||||
root.assetsView.expand(root.__currentRow)
|
root.assetsView.expand(root.__currentRow)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assetsModel.saveExpandState(root.__itemPath, root.expanded)
|
||||||
}
|
}
|
||||||
|
|
||||||
function reloadImage() {
|
function reloadImage() {
|
||||||
|
@@ -93,7 +93,6 @@ TreeView {
|
|||||||
function onDirectoryCreated(path)
|
function onDirectoryCreated(path)
|
||||||
{
|
{
|
||||||
root.__createdDirectories.push(path)
|
root.__createdDirectories.push(path)
|
||||||
|
|
||||||
updateRowsTimer.restart()
|
updateRowsTimer.restart()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,15 +117,7 @@ TreeView {
|
|||||||
// updating rows for safety: the rows might have been created before the
|
// updating rows for safety: the rows might have been created before the
|
||||||
// directory (esp. the root path) has been loaded, so we must make sure all rows are
|
// directory (esp. the root path) has been loaded, so we must make sure all rows are
|
||||||
// expanded -- otherwise, the tree may not become visible.
|
// expanded -- otherwise, the tree may not become visible.
|
||||||
|
|
||||||
updateRowsTimer.restart()
|
updateRowsTimer.restart()
|
||||||
|
|
||||||
let idx = assetsModel.indexForPath(path)
|
|
||||||
let row = root.rowAtIndex(idx)
|
|
||||||
let column = root.columnAtIndex(idx)
|
|
||||||
|
|
||||||
if (row >= root.rootPathRow && !root.isExpanded(row))
|
|
||||||
root.expand(row)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onRootPathChanged()
|
function onRootPathChanged()
|
||||||
@@ -180,9 +171,9 @@ TreeView {
|
|||||||
let index = assetsModel.indexForPath(dirPath)
|
let index = assetsModel.indexForPath(dirPath)
|
||||||
let row = root.rowAtIndex(index)
|
let row = root.rowAtIndex(index)
|
||||||
|
|
||||||
if (row > 0)
|
if (row > 0) {
|
||||||
root.expand(row)
|
root.expand(row)
|
||||||
else if (row === -1 && assetsModel.indexIsValid(index)) {
|
} else if (row === -1 && assetsModel.indexIsValid(index)) {
|
||||||
// It is possible that this directory, dirPath, was created inside of a parent
|
// It is possible that this directory, dirPath, was created inside of a parent
|
||||||
// directory that was not yet expanded in the TreeView. This can happen with the
|
// directory that was not yet expanded in the TreeView. This can happen with the
|
||||||
// bridge plugin. In such a situation, we don't have a "row" for it yet, so we have
|
// bridge plugin. In such a situation, we don't have a "row" for it yet, so we have
|
||||||
@@ -194,6 +185,8 @@ TreeView {
|
|||||||
root.expand(row)
|
root.expand(row)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assetsModel.saveExpandState(dirPath, root.isExpanded(row))
|
||||||
}
|
}
|
||||||
|
|
||||||
// we have no way to know beyond doubt here if updateRows() was called due
|
// we have no way to know beyond doubt here if updateRows() was called due
|
||||||
@@ -215,10 +208,10 @@ TreeView {
|
|||||||
function __doExpandAll()
|
function __doExpandAll()
|
||||||
{
|
{
|
||||||
let expandedAny = false
|
let expandedAny = false
|
||||||
for (let nRow = 0; nRow < root.rows; ++nRow) {
|
for (let r = 0; r < root.rows; ++r) {
|
||||||
let index = root.__modelIndex(nRow)
|
let index = root.__modelIndex(r)
|
||||||
if (assetsModel.isDirectory(index) && !root.isExpanded(nRow)) {
|
if (assetsModel.isDirectory(index) && !root.isExpanded(r)) {
|
||||||
root.expand(nRow);
|
root.expand(r)
|
||||||
expandedAny = true
|
expandedAny = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -352,15 +345,14 @@ TreeView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Keys.onRightPressed: {
|
Keys.onRightPressed: {
|
||||||
root.toggleDirectoryState("expand")
|
root.expandFolder(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
Keys.onLeftPressed: {
|
Keys.onLeftPressed: {
|
||||||
root.toggleDirectoryState("collapse")
|
root.expandFolder(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleDirectoryState(action) {
|
function expandFolder(expand) {
|
||||||
|
|
||||||
let index = root.currentFilePath ? assetsModel.indexForPath(root.currentFilePath)
|
let index = root.currentFilePath ? assetsModel.indexForPath(root.currentFilePath)
|
||||||
: root.__modelIndex(root.firstRow)
|
: root.__modelIndex(root.firstRow)
|
||||||
|
|
||||||
@@ -369,9 +361,11 @@ TreeView {
|
|||||||
|
|
||||||
let row = root.rowAtIndex(index)
|
let row = root.rowAtIndex(index)
|
||||||
|
|
||||||
if (action === "expand")
|
assetsModel.saveExpandState(root.currentFilePath, expand)
|
||||||
|
|
||||||
|
if (expand)
|
||||||
root.expand(row)
|
root.expand(row)
|
||||||
else if (action === "collapse")
|
else
|
||||||
root.collapse(row)
|
root.collapse(row)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -177,8 +177,18 @@ bool AssetsLibraryModel::deleteFolderRecursively(const QModelIndex &folderIndex)
|
|||||||
{
|
{
|
||||||
auto idx = mapToSource(folderIndex);
|
auto idx = mapToSource(folderIndex);
|
||||||
bool ok = m_sourceFsModel->remove(idx);
|
bool ok = m_sourceFsModel->remove(idx);
|
||||||
if (!ok)
|
|
||||||
|
if (ok) {
|
||||||
|
Utils::FilePath parentPath = Utils::FilePath::fromString(filePath(folderIndex));
|
||||||
|
const QStringList paths = s_folderExpandStateHash.keys();
|
||||||
|
|
||||||
|
for (const QString &path : paths) {
|
||||||
|
if (Utils::FilePath::fromString(path).isChildOf(parentPath))
|
||||||
|
s_folderExpandStateHash.remove(path);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
qWarning() << __FUNCTION__ << " could not remove folder recursively: " << m_sourceFsModel->filePath(idx);
|
qWarning() << __FUNCTION__ << " could not remove folder recursively: " << m_sourceFsModel->filePath(idx);
|
||||||
|
}
|
||||||
|
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
@@ -205,6 +215,44 @@ bool AssetsLibraryModel::isSameOrDescendantPath(const QUrl &source, const QStrin
|
|||||||
return srcPath == targetPath || targetPath.isChildOf(srcPath);
|
return srcPath == targetPath || targetPath.isChildOf(srcPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AssetsLibraryModel::folderExpandState(const QString &path) const
|
||||||
|
{
|
||||||
|
return s_folderExpandStateHash.value(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssetsLibraryModel::initializeExpandState(const QString &path)
|
||||||
|
{
|
||||||
|
if (!s_folderExpandStateHash.contains(path))
|
||||||
|
saveExpandState(path, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssetsLibraryModel::saveExpandState(const QString &path, bool expand)
|
||||||
|
{
|
||||||
|
s_folderExpandStateHash.insert(path, expand);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssetsLibraryModel::updateExpandPath(const Utils::FilePath &oldPath, const Utils::FilePath &newPath)
|
||||||
|
{
|
||||||
|
// update parent folder expand state
|
||||||
|
bool value = s_folderExpandStateHash.take(oldPath.toFSPathString());
|
||||||
|
saveExpandState(newPath.toFSPathString(), value);
|
||||||
|
|
||||||
|
const QStringList paths = s_folderExpandStateHash.keys();
|
||||||
|
|
||||||
|
for (const QString &path : paths) {
|
||||||
|
Utils::FilePath childPath = Utils::FilePath::fromString(path);
|
||||||
|
|
||||||
|
// update subfolders expand states
|
||||||
|
if (childPath.isChildOf(oldPath)) {
|
||||||
|
QString relativePath = Utils::FilePath::calcRelativePath(path, oldPath.toFSPathString());
|
||||||
|
Utils::FilePath newChildPath = newPath.pathAppended(relativePath);
|
||||||
|
|
||||||
|
value = s_folderExpandStateHash.take(path);
|
||||||
|
saveExpandState(newChildPath.toFSPathString(), value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool AssetsLibraryModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
|
bool AssetsLibraryModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
|
||||||
{
|
{
|
||||||
QString path = m_sourceFsModel->filePath(sourceParent);
|
QString path = m_sourceFsModel->filePath(sourceParent);
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
namespace Utils {
|
namespace Utils {
|
||||||
class FileSystemWatcher;
|
class FileSystemWatcher;
|
||||||
|
class FilePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
QT_FORWARD_DECLARE_CLASS(QFileSystemModel)
|
QT_FORWARD_DECLARE_CLASS(QFileSystemModel)
|
||||||
@@ -51,6 +52,10 @@ public:
|
|||||||
Q_INVOKABLE bool allFilePathsAreTextures(const QStringList &filePaths) const;
|
Q_INVOKABLE bool allFilePathsAreTextures(const QStringList &filePaths) const;
|
||||||
Q_INVOKABLE bool allFilePathsAreComposedEffects(const QStringList &filePaths) const;
|
Q_INVOKABLE bool allFilePathsAreComposedEffects(const QStringList &filePaths) const;
|
||||||
Q_INVOKABLE bool isSameOrDescendantPath(const QUrl &source, const QString &target) const;
|
Q_INVOKABLE bool isSameOrDescendantPath(const QUrl &source, const QString &target) const;
|
||||||
|
Q_INVOKABLE bool folderExpandState(const QString &path) const;
|
||||||
|
Q_INVOKABLE void initializeExpandState(const QString &path);
|
||||||
|
Q_INVOKABLE void saveExpandState(const QString &path, bool expand);
|
||||||
|
void updateExpandPath(const Utils::FilePath &oldPath, const Utils::FilePath &newPath);
|
||||||
|
|
||||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override
|
int columnCount(const QModelIndex &parent = QModelIndex()) const override
|
||||||
{
|
{
|
||||||
@@ -80,6 +85,7 @@ private:
|
|||||||
QFileSystemModel *m_sourceFsModel = nullptr;
|
QFileSystemModel *m_sourceFsModel = nullptr;
|
||||||
bool m_isEmpty = true;
|
bool m_isEmpty = true;
|
||||||
Utils::FileSystemWatcher *m_fileWatcher = nullptr;
|
Utils::FileSystemWatcher *m_fileWatcher = nullptr;
|
||||||
|
inline static QHash<QString, bool> s_folderExpandStateHash;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
@@ -427,11 +427,17 @@ void AssetsLibraryWidget::handleAssetsDrop(const QList<QUrl> &urls, const QStrin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!src.renameFile(dest) && src.isDir()) {
|
bool isDir = src.isDir();
|
||||||
QString message = tr("Failed to move folder \"%1\". "
|
|
||||||
"The folder might contain subfolders or one of its files is in use.")
|
if (src.renameFile(dest)) {
|
||||||
.arg(src.fileName());
|
if (isDir)
|
||||||
Core::AsynchronousMessageBox::warning(tr("Folder move failure"), message);
|
m_assetsModel->updateExpandPath(src, dest);
|
||||||
|
} else if (isDir) {
|
||||||
|
Core::AsynchronousMessageBox::warning(
|
||||||
|
tr("Folder move failure"),
|
||||||
|
tr("Failed to move folder \"%1\". The folder might contain subfolders or one of its files is in use.")
|
||||||
|
.arg(src.fileName())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user