Utils: Introduce a class template TypedTreeItem

For better typesafety on the user side (and optional) for items with uniformly
typed children.  Use it for UniformTreeModels, and consequently WatchModel
to get rid of some of the static_casts there.

Change-Id: Ic20e507036e180c24997b236230f0f71b285202c
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
hjk
2016-06-09 15:26:33 +02:00
parent a823caa396
commit e2ba0aca9b
5 changed files with 36 additions and 23 deletions

View File

@@ -188,13 +188,32 @@ private:
TreeItem *m_parent; // Not owned.
TreeModel *m_model; // Not owned.
QVector<TreeItem *> m_children; // Owned.
QStringList *m_displays;
Qt::ItemFlags m_flags;
protected:
QVector<TreeItem *> m_children; // Owned.
friend class TreeModel;
};
// A TreeItem with children all of the same type.
template <class ChildType>
class TypedTreeItem : public TreeItem
{
public:
void sortChildren(const std::function<bool(const ChildType *, const ChildType *)> &lessThan)
{
return TreeItem::sortChildren([lessThan](const TreeItem *a, const TreeItem *b) {
return lessThan(static_cast<const ChildType *>(a), static_cast<const ChildType *>(b));
});
}
template <typename Predicate>
void forAllChildren(const Predicate &pred) const {
return TreeItem::forAllChildren<ChildType *, Predicate>(pred);
}
};
// A general purpose multi-level model where each item can have its
// own (TreeItem-derived) type.
class QTCREATOR_UTILS_EXPORT TreeModel : public QAbstractItemModel

View File

@@ -2418,9 +2418,8 @@ void QmlEnginePrivate::insertSubItems(WatchItem *parent, const QVariantList &pro
}
if (boolSetting(SortStructMembers)) {
parent->sortChildren([](const TreeItem *item1, const TreeItem *item2) -> bool {
return static_cast<const WatchItem *>(item1)->name
< static_cast<const WatchItem *>(item2)->name;
parent->sortChildren([](const WatchItem *item1, const WatchItem *item2) {
return item1->name < item2->name;
});
}

View File

@@ -394,15 +394,12 @@ public:
quint64 addrstep;
};
static bool sortByName(const Utils::TreeItem *a, const Utils::TreeItem *b)
static bool sortByName(const WatchItem *a, const WatchItem *b)
{
auto aa = static_cast<const WatchItem *>(a);
auto bb = static_cast<const WatchItem *>(b);
if (a->sortGroup != b->sortGroup)
return a->sortGroup > b->sortGroup;
if (aa->sortGroup != bb->sortGroup)
return aa->sortGroup > bb->sortGroup;
return aa->name < bb->name;
return a->name < b->name;
}
void WatchItem::parseHelper(const GdbMi &input, bool maySort)

View File

@@ -39,7 +39,7 @@ namespace Internal {
class GdbMi;
class WatchItem : public Utils::TreeItem
class WatchItem : public Utils::TypedTreeItem<WatchItem>
{
public:
WatchItem();

View File

@@ -1253,16 +1253,14 @@ void WatchHandler::cleanup()
m_model->m_separatedView->hide();
}
static bool sortByName(const TreeItem *a, const TreeItem *b)
static bool sortByName(const WatchItem *a, const WatchItem *b)
{
auto aa = static_cast<const WatchItem *>(a);
auto bb = static_cast<const WatchItem *>(b);
return aa->name < bb->name;
return a->name < b->name;
}
void WatchHandler::insertItems(const GdbMi &data)
{
QSet<TreeItem *> itemsToSort;
QSet<WatchItem *> itemsToSort;
const bool sortStructMembers = boolSetting(SortStructMembers);
foreach (const GdbMi &child, data.children()) {
@@ -1274,10 +1272,10 @@ void WatchHandler::insertItems(const GdbMi &data)
const bool added = insertItem(item);
if (added && item->level() == 2)
itemsToSort.insert(item->parent());
itemsToSort.insert(static_cast<WatchItem *>(item->parent()));
}
foreach (TreeItem *toplevel, itemsToSort)
foreach (WatchItem *toplevel, itemsToSort)
toplevel->sortChildren(&sortByName);
}
@@ -1303,7 +1301,7 @@ bool WatchHandler::insertItem(WatchItem *item)
item->update();
item->forAllChildren<WatchItem *>([this](WatchItem *sub) { m_model->showEditValue(sub); });
item->forAllChildren([this](WatchItem *sub) { m_model->showEditValue(sub); });
return !found;
}
@@ -1349,16 +1347,16 @@ void WatchHandler::resetWatchers()
void WatchHandler::notifyUpdateStarted(const QStringList &inames)
{
auto marker = [](TreeItem *it) { static_cast<WatchItem *>(it)->outdated = true; };
auto marker = [](WatchItem *item) { item->outdated = true; };
if (inames.isEmpty()) {
m_model->forSecondLevelItems([marker](WatchItem *item) {
item->forAllChildren<WatchItem *>(marker);
item->forAllChildren(marker);
});
} else {
for (auto iname : inames) {
if (WatchItem *item = m_model->findItem(iname))
item->forAllChildren<WatchItem *>(marker);
item->forAllChildren(marker);
}
}