forked from qt-creator/qt-creator
Autotest: Introduce ItemDataCache
Change-Id: Icbd703a8ddd3c5dea4a90d2c32c1866764bc0267 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -111,7 +111,6 @@ TestNavigationWidget::TestNavigationWidget(QWidget *parent) :
|
|||||||
connect(sm, &ProjectExplorer::SessionManager::startupProjectChanged,
|
connect(sm, &ProjectExplorer::SessionManager::startupProjectChanged,
|
||||||
this, [this](ProjectExplorer::Project * /*project*/) {
|
this, [this](ProjectExplorer::Project * /*project*/) {
|
||||||
m_expandedStateCache.clear();
|
m_expandedStateCache.clear();
|
||||||
m_itemUseCache.clear();
|
|
||||||
});
|
});
|
||||||
connect(m_model, &TestTreeModel::testTreeModelChanged,
|
connect(m_model, &TestTreeModel::testTreeModelChanged,
|
||||||
this, &TestNavigationWidget::reapplyCachedExpandedState);
|
this, &TestNavigationWidget::reapplyCachedExpandedState);
|
||||||
@@ -237,22 +236,12 @@ QList<QToolButton *> TestNavigationWidget::createToolButtons()
|
|||||||
|
|
||||||
void TestNavigationWidget::updateExpandedStateCache()
|
void TestNavigationWidget::updateExpandedStateCache()
|
||||||
{
|
{
|
||||||
// raise generation for cached items and drop anything reaching 10th generation
|
m_expandedStateCache.evolve();
|
||||||
const QList<QString> cachedNames = m_itemUseCache.keys();
|
|
||||||
for (const QString &cachedName : cachedNames) {
|
|
||||||
auto it = m_itemUseCache.find(cachedName);
|
|
||||||
if (it.value()++ >= 10) {
|
|
||||||
m_itemUseCache.erase(it);
|
|
||||||
m_expandedStateCache.remove(cachedName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Utils::TreeItem *rootNode : *m_model->rootItem()) {
|
for (Utils::TreeItem *rootNode : *m_model->rootItem()) {
|
||||||
rootNode->forAllChildren([this](Utils::TreeItem *child) {
|
rootNode->forAllChildren([this](Utils::TreeItem *child) {
|
||||||
auto childItem = static_cast<TestTreeItem *>(child);
|
m_expandedStateCache.insert(static_cast<TestTreeItem *>(child),
|
||||||
const QString cacheName = childItem->cacheName();
|
m_view->isExpanded(child->index()));
|
||||||
m_expandedStateCache.insert(cacheName, m_view->isExpanded(childItem->index()));
|
|
||||||
m_itemUseCache[cacheName] = 0; // explicitly mark as 0-generation
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -328,16 +317,15 @@ void TestNavigationWidget::onRunThisTestTriggered(TestRunMode runMode)
|
|||||||
|
|
||||||
void TestNavigationWidget::reapplyCachedExpandedState()
|
void TestNavigationWidget::reapplyCachedExpandedState()
|
||||||
{
|
{
|
||||||
for (Utils::TreeItem *rootNode : *m_model->rootItem()) {
|
using namespace Utils;
|
||||||
rootNode->forAllChildren([this](Utils::TreeItem *child) {
|
for (TreeItem *rootNode : *m_model->rootItem()) {
|
||||||
auto childItem = static_cast<TestTreeItem *>(child);
|
rootNode->forAllChildren([this](TreeItem *child) {
|
||||||
const QString cacheName = childItem->cacheName();
|
optional<bool> cached = m_expandedStateCache.get(static_cast<TestTreeItem *>(child));
|
||||||
const auto it = m_expandedStateCache.find(cacheName);
|
if (cached.has_value()) {
|
||||||
if (it == m_expandedStateCache.end())
|
QModelIndex index = child->index();
|
||||||
return;
|
if (m_view->isExpanded(index) != cached.value())
|
||||||
QModelIndex index = child->index();
|
m_view->setExpanded(index, cached.value());
|
||||||
if (m_view->isExpanded(index) != it.value())
|
}
|
||||||
m_view->setExpanded(index, it.value());
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -27,6 +27,8 @@
|
|||||||
|
|
||||||
#include "testrunner.h"
|
#include "testrunner.h"
|
||||||
|
|
||||||
|
#include "testtreemodel.h"
|
||||||
|
|
||||||
#include <coreplugin/inavigationwidgetfactory.h>
|
#include <coreplugin/inavigationwidgetfactory.h>
|
||||||
|
|
||||||
#include <utils/navigationtreeview.h>
|
#include <utils/navigationtreeview.h>
|
||||||
@@ -47,12 +49,8 @@ class ProgressIndicator;
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace Autotest {
|
namespace Autotest {
|
||||||
|
|
||||||
class TestTreeModel;
|
|
||||||
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
class TestTreeSortFilterModel;
|
|
||||||
class TestTreeView;
|
class TestTreeView;
|
||||||
|
|
||||||
class TestNavigationWidget : public QWidget
|
class TestNavigationWidget : public QWidget
|
||||||
@@ -86,8 +84,7 @@ private:
|
|||||||
Utils::ProgressIndicator *m_progressIndicator;
|
Utils::ProgressIndicator *m_progressIndicator;
|
||||||
QTimer *m_progressTimer;
|
QTimer *m_progressTimer;
|
||||||
QFrame *m_missingFrameworksWidget;
|
QFrame *m_missingFrameworksWidget;
|
||||||
QHash<QString, bool> m_expandedStateCache;
|
ItemDataCache<bool> m_expandedStateCache;
|
||||||
QHash<QString, int> m_itemUseCache;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class TestNavigationWidgetFactory : public Core::INavigationWidgetFactory
|
class TestNavigationWidgetFactory : public Core::INavigationWidgetFactory
|
||||||
|
@@ -92,7 +92,6 @@ void TestTreeModel::setupParsingConnections()
|
|||||||
synchronizeTestFrameworks(); // we might have project settings
|
synchronizeTestFrameworks(); // we might have project settings
|
||||||
m_parser->onStartupProjectChanged(project);
|
m_parser->onStartupProjectChanged(project);
|
||||||
m_checkStateCache.clear(); // TODO persist to project settings?
|
m_checkStateCache.clear(); // TODO persist to project settings?
|
||||||
m_itemUseCache.clear();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance();
|
CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance();
|
||||||
@@ -295,22 +294,12 @@ void TestTreeModel::rebuild(const QList<Utils::Id> &frameworkIds)
|
|||||||
|
|
||||||
void TestTreeModel::updateCheckStateCache()
|
void TestTreeModel::updateCheckStateCache()
|
||||||
{
|
{
|
||||||
// raise generation for cached items and drop anything reaching 10th generation
|
m_checkStateCache.evolve();
|
||||||
const QList<QString> cachedNames = m_itemUseCache.keys();
|
|
||||||
for (const QString &cachedName : cachedNames) {
|
|
||||||
auto it = m_itemUseCache.find(cachedName);
|
|
||||||
if (it.value()++ >= 10) {
|
|
||||||
m_itemUseCache.erase(it);
|
|
||||||
m_checkStateCache.remove(cachedName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Utils::TreeItem *rootNode : *rootItem()) {
|
for (Utils::TreeItem *rootNode : *rootItem()) {
|
||||||
rootNode->forAllChildren([this](Utils::TreeItem *child) {
|
rootNode->forAllChildren([this](Utils::TreeItem *child) {
|
||||||
auto childItem = static_cast<TestTreeItem *>(child);
|
auto childItem = static_cast<TestTreeItem *>(child);
|
||||||
const QString cacheName = childItem->cacheName();
|
m_checkStateCache.insert(childItem, childItem->checked());
|
||||||
m_checkStateCache.insert(cacheName, childItem->checked());
|
|
||||||
m_itemUseCache[cacheName] = 0; // explicitly mark as 0-generation
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -436,8 +425,8 @@ void TestTreeModel::insertItemInParent(TestTreeItem *item, TestTreeItem *root, b
|
|||||||
delete item;
|
delete item;
|
||||||
} else {
|
} else {
|
||||||
// restore former check state if available
|
// restore former check state if available
|
||||||
auto cached = m_checkStateCache.find(item->cacheName());
|
Utils::optional<Qt::CheckState> cached = m_checkStateCache.get(item);
|
||||||
if (cached != m_checkStateCache.end())
|
if (cached.has_value())
|
||||||
item->setData(0, cached.value(), Qt::CheckStateRole);
|
item->setData(0, cached.value(), Qt::CheckStateRole);
|
||||||
else
|
else
|
||||||
applyParentCheckState(parentNode, item);
|
applyParentCheckState(parentNode, item);
|
||||||
@@ -526,8 +515,8 @@ void TestTreeModel::handleParseResult(const TestParseResult *result, TestTreeIte
|
|||||||
// restore former check state if available
|
// restore former check state if available
|
||||||
newItem->forAllChildren([this](Utils::TreeItem *child) {
|
newItem->forAllChildren([this](Utils::TreeItem *child) {
|
||||||
auto childItem = static_cast<TestTreeItem *>(child);
|
auto childItem = static_cast<TestTreeItem *>(child);
|
||||||
auto cached = m_checkStateCache.find(childItem->cacheName());
|
Utils::optional<Qt::CheckState> cached = m_checkStateCache.get(childItem);
|
||||||
if (cached != m_checkStateCache.end())
|
if (cached.has_value())
|
||||||
childItem->setData(0, cached.value(), Qt::CheckStateRole);
|
childItem->setData(0, cached.value(), Qt::CheckStateRole);
|
||||||
});
|
});
|
||||||
// it might be necessary to "split" created item
|
// it might be necessary to "split" created item
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
#include "testconfiguration.h"
|
#include "testconfiguration.h"
|
||||||
#include "testtreeitem.h"
|
#include "testtreeitem.h"
|
||||||
|
|
||||||
|
#include <utils/algorithm.h>
|
||||||
#include <utils/treemodel.h>
|
#include <utils/treemodel.h>
|
||||||
|
|
||||||
#include <QSortFilterProxyModel>
|
#include <QSortFilterProxyModel>
|
||||||
@@ -38,6 +39,40 @@ namespace Autotest {
|
|||||||
namespace Internal {
|
namespace Internal {
|
||||||
class AutotestPluginPrivate;
|
class AutotestPluginPrivate;
|
||||||
class TestCodeParser;
|
class TestCodeParser;
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class ItemDataCache
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void insert(TestTreeItem *item, const T &value) { m_cache[item->cacheName()] = {0, value}; }
|
||||||
|
void evolve()
|
||||||
|
{
|
||||||
|
auto it = m_cache.begin(), end = m_cache.end();
|
||||||
|
while (it != end)
|
||||||
|
it = it->generation++ >= maxGen ? m_cache.erase(it) : ++it;
|
||||||
|
}
|
||||||
|
|
||||||
|
Utils::optional<T> get(TestTreeItem *item)
|
||||||
|
{
|
||||||
|
auto entry = m_cache.find(item->cacheName());
|
||||||
|
if (entry == m_cache.end())
|
||||||
|
return Utils::nullopt;
|
||||||
|
entry->generation = 0;
|
||||||
|
return Utils::make_optional(entry->value);
|
||||||
|
};
|
||||||
|
|
||||||
|
void clear() { m_cache.clear(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr int maxGen = 10;
|
||||||
|
struct Entry
|
||||||
|
{
|
||||||
|
int generation = 0;
|
||||||
|
T value;
|
||||||
|
};
|
||||||
|
QHash<QString, Entry> m_cache;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|
||||||
class TestParseResult;
|
class TestParseResult;
|
||||||
@@ -104,8 +139,7 @@ private:
|
|||||||
QList<TestTreeItem *> testItemsByName(TestTreeItem *root, const QString &testName);
|
QList<TestTreeItem *> testItemsByName(TestTreeItem *root, const QString &testName);
|
||||||
|
|
||||||
Internal::TestCodeParser *m_parser = nullptr;
|
Internal::TestCodeParser *m_parser = nullptr;
|
||||||
QHash<QString, Qt::CheckState> m_checkStateCache;
|
Internal::ItemDataCache<Qt::CheckState> m_checkStateCache;
|
||||||
QHash<QString, int> m_itemUseCache;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
Reference in New Issue
Block a user