forked from qt-creator/qt-creator
ProjectExplorer: Fix undefined behavior regarding ShowMoreItem
Introduce ITargetItem interface for TargetItem and ShowMoreItem. Fixes: QTCREATORBUG-31074 Change-Id: I8aa15b985ac3a18b44169f93520057837e1718ea Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
@@ -194,11 +194,38 @@ public:
|
||||
TargetSetupPageWrapper *m_targetSetupPageWrapper = nullptr;
|
||||
};
|
||||
|
||||
class ShowMoreItem : public TreeItem
|
||||
class ITargetItem : public TypedTreeItem<TreeItem, TargetGroupItem>
|
||||
{
|
||||
public:
|
||||
enum { DefaultPage = 0 }; // Build page.
|
||||
|
||||
ITargetItem(Project *project, Id kitId, const Tasks &issues)
|
||||
: m_project(project)
|
||||
, m_kitId(kitId)
|
||||
, m_kitIssues(issues)
|
||||
{}
|
||||
|
||||
virtual Target *target() const = 0;
|
||||
virtual void updateSubItems() = 0;
|
||||
virtual void addToContextMenu(QMenu *menu, bool isSelectable) = 0;
|
||||
|
||||
bool isEnabled() const { return target() != nullptr; }
|
||||
|
||||
public:
|
||||
QPointer<Project> m_project; // Not owned.
|
||||
Id m_kitId;
|
||||
int m_currentChild = DefaultPage;
|
||||
bool m_kitErrorsForProject = false;
|
||||
bool m_kitWarningForProject = false;
|
||||
Tasks m_kitIssues;
|
||||
};
|
||||
|
||||
class ShowMoreItem : public ITargetItem
|
||||
{
|
||||
public:
|
||||
ShowMoreItem(TargetGroupItemPrivate *p)
|
||||
: m_p(p)
|
||||
: ITargetItem(nullptr, Id(), Tasks())
|
||||
, m_p(p)
|
||||
{}
|
||||
|
||||
QVariant data(int column, int role) const override
|
||||
@@ -230,6 +257,13 @@ public:
|
||||
return Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;
|
||||
}
|
||||
|
||||
// ITargetItem
|
||||
Target *target() const override {
|
||||
return nullptr;
|
||||
}
|
||||
void updateSubItems() override {}
|
||||
void addToContextMenu(QMenu *, bool) override {}
|
||||
|
||||
private:
|
||||
TargetGroupItemPrivate *m_p;
|
||||
};
|
||||
@@ -274,13 +308,11 @@ void TargetGroupItemPrivate::ensureWidget()
|
||||
//
|
||||
// Third level: The per-kit entries (inactive or with a 'Build' and a 'Run' subitem)
|
||||
//
|
||||
class TargetItem : public TypedTreeItem<TreeItem, TargetGroupItem>
|
||||
class TargetItem : public ITargetItem
|
||||
{
|
||||
public:
|
||||
enum { DefaultPage = 0 }; // Build page.
|
||||
|
||||
TargetItem(Project *project, Id kitId, const Tasks &issues)
|
||||
: m_project(project), m_kitId(kitId), m_kitIssues(issues)
|
||||
: ITargetItem(project, kitId, issues)
|
||||
{
|
||||
m_kitWarningForProject = containsType(m_kitIssues, Task::TaskType::Warning);
|
||||
m_kitErrorsForProject = containsType(m_kitIssues, Task::TaskType::Error);
|
||||
@@ -288,12 +320,12 @@ public:
|
||||
updateSubItems();
|
||||
}
|
||||
|
||||
Target *target() const
|
||||
Target *target() const override
|
||||
{
|
||||
return m_project->target(m_kitId);
|
||||
}
|
||||
|
||||
void updateSubItems();
|
||||
void updateSubItems() override;
|
||||
|
||||
Qt::ItemFlags flags(int column) const override
|
||||
{
|
||||
@@ -332,7 +364,7 @@ public:
|
||||
|
||||
case Qt::FontRole: {
|
||||
QFont font = parent()->data(column, role).value<QFont>();
|
||||
if (TargetItem *targetItem = parent()->currentTargetItem()) {
|
||||
if (ITargetItem *targetItem = parent()->currentTargetItem()) {
|
||||
Target *t = targetItem->target();
|
||||
if (t && t->id() == m_kitId && m_project == ProjectManager::startupProject())
|
||||
font.setBold(true);
|
||||
@@ -384,7 +416,7 @@ public:
|
||||
m_project->addTargetForKit(KitManager::kit(m_kitId));
|
||||
} else {
|
||||
// Go to Run page, when on Run previously etc.
|
||||
TargetItem *previousItem = parent()->currentTargetItem();
|
||||
ITargetItem *previousItem = parent()->currentTargetItem();
|
||||
m_currentChild = previousItem ? previousItem->m_currentChild : DefaultPage;
|
||||
m_project->setActiveTarget(target(), SetActive::Cascade);
|
||||
parent()->setData(column, QVariant::fromValue(static_cast<TreeItem *>(this)),
|
||||
@@ -413,7 +445,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
void addToContextMenu(QMenu *menu, bool isSelectable)
|
||||
void addToContextMenu(QMenu *menu, bool isSelectable) override
|
||||
{
|
||||
Kit *kit = KitManager::kit(m_kitId);
|
||||
QTC_ASSERT(kit, return);
|
||||
@@ -493,16 +525,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
bool isEnabled() const { return target() != nullptr; }
|
||||
|
||||
public:
|
||||
QPointer<Project> m_project; // Not owned.
|
||||
Id m_kitId;
|
||||
int m_currentChild = DefaultPage;
|
||||
bool m_kitErrorsForProject = false;
|
||||
bool m_kitWarningForProject = false;
|
||||
Tasks m_kitIssues;
|
||||
|
||||
private:
|
||||
enum class IconOverlay {
|
||||
Add,
|
||||
@@ -744,13 +766,13 @@ QVariant TargetGroupItem::data(int column, int role) const
|
||||
return d->m_displayName;
|
||||
|
||||
if (role == ActiveItemRole) {
|
||||
if (TargetItem *item = currentTargetItem())
|
||||
if (ITargetItem *item = currentTargetItem())
|
||||
return item->data(column, role);
|
||||
return QVariant::fromValue<TreeItem *>(const_cast<TargetGroupItem *>(this));
|
||||
}
|
||||
|
||||
if (role == PanelWidgetRole) {
|
||||
if (TargetItem *item = currentTargetItem())
|
||||
if (ITargetItem *item = currentTargetItem())
|
||||
return item->data(column, role);
|
||||
|
||||
d->ensureWidget();
|
||||
@@ -776,16 +798,16 @@ Qt::ItemFlags TargetGroupItem::flags(int) const
|
||||
return Qt::NoItemFlags;
|
||||
}
|
||||
|
||||
TargetItem *TargetGroupItem::currentTargetItem() const
|
||||
ITargetItem *TargetGroupItem::currentTargetItem() const
|
||||
{
|
||||
return targetItem(d->m_project->activeTarget());
|
||||
}
|
||||
|
||||
TargetItem *TargetGroupItem::targetItem(Target *target) const
|
||||
ITargetItem *TargetGroupItem::targetItem(Target *target) const
|
||||
{
|
||||
if (target) {
|
||||
Id needle = target->id(); // Unconfigured project have no active target.
|
||||
return findFirstLevelChild([needle](TargetItem *item) { return item->m_kitId == needle; });
|
||||
return findFirstLevelChild([needle](ITargetItem *item) { return item->m_kitId == needle; });
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -854,7 +876,7 @@ void TargetGroupItemPrivate::rebuildContents()
|
||||
|
||||
void TargetGroupItemPrivate::handleTargetAdded(Target *target)
|
||||
{
|
||||
if (TargetItem *item = q->targetItem(target))
|
||||
if (ITargetItem *item = q->targetItem(target))
|
||||
item->updateSubItems();
|
||||
ensureShowMoreItem();
|
||||
q->update();
|
||||
@@ -862,7 +884,7 @@ void TargetGroupItemPrivate::handleTargetAdded(Target *target)
|
||||
|
||||
void TargetGroupItemPrivate::handleTargetRemoved(Target *target)
|
||||
{
|
||||
if (TargetItem *item = q->targetItem(target))
|
||||
if (ITargetItem *item = q->targetItem(target))
|
||||
item->updateSubItems();
|
||||
ensureShowMoreItem();
|
||||
q->parent()->setData(0, QVariant::fromValue(static_cast<TreeItem *>(q)),
|
||||
@@ -871,7 +893,7 @@ void TargetGroupItemPrivate::handleTargetRemoved(Target *target)
|
||||
|
||||
void TargetGroupItemPrivate::handleTargetChanged(Target *target)
|
||||
{
|
||||
if (TargetItem *item = q->targetItem(target))
|
||||
if (ITargetItem *item = q->targetItem(target))
|
||||
item->updateSubItems();
|
||||
ensureShowMoreItem();
|
||||
q->setData(0, QVariant(), ItemActivatedFromBelowRole);
|
||||
|
@@ -15,11 +15,11 @@ class Target;
|
||||
|
||||
namespace Internal {
|
||||
|
||||
class TargetItem;
|
||||
class ITargetItem;
|
||||
class TargetGroupItemPrivate;
|
||||
|
||||
// Second level: Special case for the Build & Run item (with per-kit subItems)
|
||||
class TargetGroupItem : public Utils::TypedTreeItem<TargetItem /*, ProjectItem */>
|
||||
class TargetGroupItem : public Utils::TypedTreeItem<ITargetItem /*, ProjectItem */>
|
||||
{
|
||||
public:
|
||||
TargetGroupItem(const QString &displayName, Project *project);
|
||||
@@ -29,8 +29,8 @@ public:
|
||||
bool setData(int column, const QVariant &data, int role) override;
|
||||
Qt::ItemFlags flags(int) const override;
|
||||
|
||||
TargetItem *currentTargetItem() const;
|
||||
TargetItem *targetItem(Target *target) const;
|
||||
ITargetItem *currentTargetItem() const;
|
||||
ITargetItem *targetItem(Target *target) const;
|
||||
|
||||
private:
|
||||
const std::unique_ptr<TargetGroupItemPrivate> d;
|
||||
|
Reference in New Issue
Block a user