bug-fix: * will recursively expand the directory tree causing crash

We build the complete subtree before expanding to avoid crash.
This commit is contained in:
Le Tan 2017-07-14 19:34:29 +08:00
parent eb71c8eff1
commit 5ad99ee9b8
3 changed files with 71 additions and 18 deletions

View File

@ -132,7 +132,7 @@ void VDirectoryTree::updateDirectoryTree()
fillTreeItem(*item, dir->getName(), dir,
QIcon(":/resources/icons/dir_item.svg"));
updateDirectoryTreeOne(item, 1);
buildSubTree(item, 1);
}
if (!restoreCurrentItem()) {
@ -155,12 +155,12 @@ bool VDirectoryTree::restoreCurrentItem()
return false;
}
void VDirectoryTree::updateDirectoryTreeOne(QTreeWidgetItem *p_parent, int depth)
void VDirectoryTree::buildSubTree(QTreeWidgetItem *p_parent, int p_depth)
{
Q_ASSERT(p_parent->childCount() == 0);
if (depth <= 0) {
if (p_depth == 0) {
return;
}
VDirectory *dir = getVDirectory(p_parent);
if (!dir->open()) {
VUtils::showMessage(QMessageBox::Warning, tr("Warning"),
@ -169,16 +169,25 @@ void VDirectoryTree::updateDirectoryTreeOne(QTreeWidgetItem *p_parent, int depth
QMessageBox::Ok, QMessageBox::Ok, this);
return;
}
const QVector<VDirectory *> &subDirs = dir->getSubDirs();
for (int i = 0; i < subDirs.size(); ++i) {
VDirectory *subDir = subDirs[i];
QTreeWidgetItem *item = new QTreeWidgetItem(p_parent);
fillTreeItem(*item, subDir->getName(), subDir,
QIcon(":/resources/icons/dir_item.svg"));
if (p_parent->childCount() > 0) {
// This directory has been built before. Try its children directly.
for (int i = 0; i < p_parent->childCount(); ++i) {
buildSubTree(p_parent->child(i), p_depth -1);
}
} else {
const QVector<VDirectory *> &subDirs = dir->getSubDirs();
for (int i = 0; i < subDirs.size(); ++i) {
VDirectory *subDir = subDirs[i];
QTreeWidgetItem *item = new QTreeWidgetItem(p_parent);
updateDirectoryTreeOne(item, depth - 1);
fillTreeItem(*item, subDir->getName(), subDir,
QIcon(":/resources/icons/dir_item.svg"));
buildSubTree(item, p_depth - 1);
}
}
if (dir->isExpanded()) {
expandItem(p_parent);
}
@ -197,7 +206,6 @@ void VDirectoryTree::handleItemExpanded(QTreeWidgetItem *p_item)
dir->setExpanded(true);
}
// Update @p_item's children items
void VDirectoryTree::updateChildren(QTreeWidgetItem *p_item)
{
Q_ASSERT(p_item);
@ -205,12 +213,14 @@ void VDirectoryTree::updateChildren(QTreeWidgetItem *p_item)
if (nrChild == 0) {
return;
}
for (int i = 0; i < nrChild; ++i) {
QTreeWidgetItem *childItem = p_item->child(i);
if (childItem->childCount() > 0) {
continue;
}
updateDirectoryTreeOne(childItem, 1);
buildSubTree(childItem, 1);
}
}
@ -252,7 +262,7 @@ void VDirectoryTree::updateItemChildren(QTreeWidgetItem *p_item)
item = new QTreeWidgetItem(this);
}
fillTreeItem(*item, dir->getName(), dir, QIcon(":/resources/icons/dir_item.svg"));
updateDirectoryTreeOne(item, 1);
buildSubTree(item, 1);
}
expandItemTree(item);
}
@ -577,6 +587,7 @@ void VDirectoryTree::keyPressEvent(QKeyEvent *event)
if (item) {
item->setExpanded(!item->isExpanded());
}
break;
}
@ -589,6 +600,7 @@ void VDirectoryTree::keyPressEvent(QKeyEvent *event)
QCoreApplication::postEvent(this, downEvent);
return;
}
break;
}
@ -601,6 +613,21 @@ void VDirectoryTree::keyPressEvent(QKeyEvent *event)
QCoreApplication::postEvent(this, upEvent);
return;
}
break;
}
case Qt::Key_Asterisk:
{
if (modifiers == Qt::ShiftModifier) {
// *, by default will expand current item recursively.
// We build the tree recursively before the expanding.
QTreeWidgetItem *item = currentItem();
if (item) {
buildSubTree(item, -1);
}
}
break;
}
@ -730,7 +757,7 @@ QTreeWidgetItem *VDirectoryTree::expandToVDirectory(const VDirectory *p_director
}
int nrChild = pItem->childCount();
if (nrChild == 0) {
updateDirectoryTreeOne(pItem, 1);
buildSubTree(pItem, 1);
}
nrChild = pItem->childCount();
for (int i = 0; i < nrChild; ++i) {
@ -748,11 +775,13 @@ void VDirectoryTree::expandItemTree(QTreeWidgetItem *p_item)
if (!p_item) {
return;
}
VDirectory *dir = getVDirectory(p_item);
int nrChild = p_item->childCount();
for (int i = 0; i < nrChild; ++i) {
expandItemTree(p_item->child(i));
}
if (dir->isExpanded()) {
Q_ASSERT(nrChild > 0);
expandItem(p_item);

View File

@ -40,6 +40,9 @@ public slots:
void newRootDirectory();
void deleteDirectory();
void editDirectoryInfo();
// Clear and re-build the whole directory tree.
// Do not load all the sub-directories at once.
void updateDirectoryTree();
private slots:
@ -58,9 +61,21 @@ protected:
void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE;
private:
void updateDirectoryTreeOne(QTreeWidgetItem *p_parent, int depth);
// Build the subtree of @p_parent recursively to the depth @p_depth.
// Item @p_parent must not be built before.
// Will expand the item if the corresponding directory was expanded before.
// @p_depth: valid only when greater than 0.
void updateDirectoryTreeOne(QTreeWidgetItem *p_parent, int p_depth);
// Build the subtree of @p_parent recursively to the depth @p_depth.
// @p_depth: negative - infinite levels.
// Will expand the item if the corresponding directory was expanded before.
void buildSubTree(QTreeWidgetItem *p_parent, int p_depth);
// Fill the content of a tree item.
void fillTreeItem(QTreeWidgetItem &p_item, const QString &p_name,
VDirectory *p_directory, const QIcon &p_icon);
void initActions();
// Update @p_item's direct children only: deleted, added, renamed.
void updateItemChildren(QTreeWidgetItem *p_item);
@ -72,11 +87,16 @@ private:
void pasteDirectories(VDirectory *p_destDir);
bool copyDirectory(VDirectory *p_destDir, const QString &p_destName,
VDirectory *p_srcDir, bool p_cut);
// Build the subtree of @p_item's children if it has not been built yet.
void updateChildren(QTreeWidgetItem *p_item);
// Expand/create the directory tree nodes to @p_directory.
QTreeWidgetItem *expandToVDirectory(const VDirectory *p_directory);
// Expand the tree under @p_item according to VDirectory.isOpened().
// Expand the currently-built subtree of @p_item according to VDirectory.isExpanded().
void expandItemTree(QTreeWidgetItem *p_item);
QList<QTreeWidgetItem *> getVisibleItems() const;
QList<QTreeWidgetItem *> getVisibleChildItems(const QTreeWidgetItem *p_item) const;
bool restoreCurrentItem();
@ -86,6 +106,7 @@ private:
QVector<QPointer<VDirectory> > m_copiedDirs;
VEditArea *m_editArea;
// Each notebook's current item's VDirectory.
QHash<VNotebook *, VDirectory *> m_notebookCurrentDirMap;
// Actions

View File

@ -637,6 +637,7 @@ void VFileList::showNavigation()
// Generate labels for visible items.
auto items = getVisibleItems();
int itemWidth = rect().width();
for (int i = 0; i < 26 && i < items.size(); ++i) {
QChar key('a' + i);
m_keyMap[key] = items[i];
@ -644,8 +645,10 @@ void VFileList::showNavigation()
QString str = QString(m_majorKey) + key;
QLabel *label = new QLabel(str, this);
label->setStyleSheet(g_vnote->getNavigationLabelStyle(str));
label->move(fileList->visualItemRect(items[i]).topLeft());
label->show();
QRect rect = fileList->visualItemRect(items[i]);
// Display the label at the end to show the file name.
label->move(rect.x() + itemWidth - label->width(), rect.y());
m_naviLabels.append(label);
}
}