ProjectExplorer: Add LayoutBuilder ability to operate on QGridLayout

Also, make it possible to extend an existing layout.

Change-Id: Idcbc7ace967e575dd743c7d748f4d3b751668f7a
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
hjk
2020-09-17 17:02:16 +02:00
parent 4376bc1e39
commit 250c55f308
2 changed files with 98 additions and 55 deletions

View File

@@ -60,22 +60,44 @@ void ProjectConfigurationAspect::addToLayout(LayoutBuilder &)
// LayoutBuilder // LayoutBuilder
LayoutBuilder::LayoutBuilder(QWidget *parent) LayoutBuilder::LayoutBuilder(QWidget *parent, LayoutType layoutType)
: m_layout(new QFormLayout(parent))
{ {
m_layout->setContentsMargins(0, 0, 0, 0); if (layoutType == FormLayout) {
if (auto fl = qobject_cast<QFormLayout *>(m_layout)) m_formLayout = new QFormLayout(parent);
fl->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow); m_formLayout->setContentsMargins(0, 0, 0, 0);
m_formLayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
} else {
m_gridLayout = new QGridLayout(parent);
m_gridLayout->setContentsMargins(0, 0, 0, 0);
}
}
LayoutBuilder::LayoutBuilder(QLayout *layout)
{
if (auto fl = qobject_cast<QFormLayout *>(layout)) {
m_formLayout = fl;
} else if (auto grid = qobject_cast<QGridLayout *>(layout)) {
m_gridLayout = grid;
m_currentGridRow = grid->rowCount();
m_currentGridColumn = 0;
}
} }
LayoutBuilder::~LayoutBuilder() LayoutBuilder::~LayoutBuilder()
{ {
flushPendingItems(); flushPendingFormItems();
} }
LayoutBuilder &LayoutBuilder::startNewRow() LayoutBuilder &LayoutBuilder::startNewRow()
{ {
flushPendingItems(); if (m_formLayout)
flushPendingFormItems();
if (m_gridLayout) {
if (m_currentGridColumn != 0) {
++m_currentGridRow;
m_currentGridColumn = 0;
}
}
return *this; return *this;
} }
@@ -86,69 +108,76 @@ LayoutBuilder &LayoutBuilder::addRow(const LayoutItem &item)
return *this; return *this;
} }
void LayoutBuilder::flushPendingItems() void LayoutBuilder::flushPendingFormItems()
{ {
if (m_pendingItems.isEmpty()) QTC_ASSERT(m_formLayout, return);
if (m_pendingFormItems.isEmpty())
return; return;
if (auto fl = qobject_cast<QFormLayout *>(m_layout)) {
// If there are more than two items, we cram the last ones in one hbox. // If there are more than two items, we cram the last ones in one hbox.
if (m_pendingItems.size() > 2) { if (m_pendingFormItems.size() > 2) {
auto hbox = new QHBoxLayout; auto hbox = new QHBoxLayout;
hbox->setContentsMargins(0, 0, 0, 0); hbox->setContentsMargins(0, 0, 0, 0);
for (int i = 1; i < m_pendingItems.size(); ++i) { for (int i = 1; i < m_pendingFormItems.size(); ++i) {
if (QWidget *w = m_pendingItems.at(i).widget) if (QWidget *w = m_pendingFormItems.at(i).widget)
hbox->addWidget(w); hbox->addWidget(w);
else if (QLayout *l = m_pendingItems.at(i).layout) else if (QLayout *l = m_pendingFormItems.at(i).layout)
hbox->addItem(l); hbox->addItem(l);
else else
QTC_CHECK(false); QTC_CHECK(false);
} }
while (m_pendingItems.size() >= 2) while (m_pendingFormItems.size() >= 2)
m_pendingItems.takeLast(); m_pendingFormItems.takeLast();
m_pendingItems.append(LayoutItem(hbox)); m_pendingFormItems.append(LayoutItem(hbox));
} }
if (m_pendingItems.size() == 1) { // One one item given, so this spans both columns. if (m_pendingFormItems.size() == 1) { // One one item given, so this spans both columns.
if (auto layout = m_pendingItems.at(0).layout) if (auto layout = m_pendingFormItems.at(0).layout)
fl->addRow(layout); m_formLayout->addRow(layout);
else if (auto widget = m_pendingItems.at(0).widget) else if (auto widget = m_pendingFormItems.at(0).widget)
fl->addRow(widget); m_formLayout->addRow(widget);
} else if (m_pendingItems.size() == 2) { // Normal case, both columns used. } else if (m_pendingFormItems.size() == 2) { // Normal case, both columns used.
if (auto label = m_pendingItems.at(0).widget) { if (auto label = m_pendingFormItems.at(0).widget) {
if (auto layout = m_pendingItems.at(1).layout) if (auto layout = m_pendingFormItems.at(1).layout)
fl->addRow(label, layout); m_formLayout->addRow(label, layout);
else if (auto widget = m_pendingItems.at(1).widget) else if (auto widget = m_pendingFormItems.at(1).widget)
fl->addRow(label, widget); m_formLayout->addRow(label, widget);
} else { } else {
if (auto layout = m_pendingItems.at(1).layout) if (auto layout = m_pendingFormItems.at(1).layout)
fl->addRow(m_pendingItems.at(0).text, layout); m_formLayout->addRow(m_pendingFormItems.at(0).text, layout);
else if (auto widget = m_pendingItems.at(1).widget) else if (auto widget = m_pendingFormItems.at(1).widget)
fl->addRow(m_pendingItems.at(0).text, widget); m_formLayout->addRow(m_pendingFormItems.at(0).text, widget);
}
} else {
QTC_CHECK(false);
} }
} else { } else {
QTC_CHECK(false); QTC_CHECK(false);
} }
m_pendingItems.clear(); m_pendingFormItems.clear();
} }
QLayout *LayoutBuilder::layout() const QLayout *LayoutBuilder::layout() const
{ {
return m_layout; if (m_formLayout)
return m_formLayout;
return m_gridLayout;
} }
LayoutBuilder &LayoutBuilder::addItem(LayoutItem item) LayoutBuilder &LayoutBuilder::addItem(LayoutItem item)
{ {
if (item.widget && !item.widget->parent())
item.widget->setParent(layout()->parentWidget());
if (item.aspect) { if (item.aspect) {
item.aspect->addToLayout(*this); item.aspect->addToLayout(*this);
} else { } else {
if (item.widget && !item.widget->parent()) if (m_gridLayout) {
item.widget->setParent(m_layout->parentWidget()); if (auto widget = item.widget)
m_pendingItems.append(item); m_gridLayout->addWidget(widget, m_currentGridRow, m_currentGridColumn, 1, item.span, item.align);
m_currentGridColumn += item.span;
} else {
m_pendingFormItems.append(item);
}
} }
return *this; return *this;
} }

View File

@@ -36,6 +36,11 @@
#include <QVariantMap> #include <QVariantMap>
#include <QWidget> #include <QWidget>
QT_BEGIN_NAMESPACE
class QFormLayout;
class QGridLayout;
QT_END_NAMESPACE
namespace ProjectExplorer { namespace ProjectExplorer {
class Kit; class Kit;
@@ -47,14 +52,18 @@ class Target;
class PROJECTEXPLORER_EXPORT LayoutBuilder class PROJECTEXPLORER_EXPORT LayoutBuilder
{ {
public: public:
explicit LayoutBuilder(QWidget *parent); enum LayoutType { GridLayout, FormLayout };
explicit LayoutBuilder(QWidget *parent, LayoutType layoutType = FormLayout);
explicit LayoutBuilder(QLayout *layout); // Adds to existing layout.
~LayoutBuilder(); ~LayoutBuilder();
class LayoutItem class LayoutItem
{ {
public: public:
LayoutItem(QLayout *layout) : layout(layout) {} LayoutItem(QLayout *layout, int span = 1) : layout(layout), span(span) {}
LayoutItem(QWidget *widget) : widget(widget) {} LayoutItem(QWidget *widget, int span = 1, Qt::Alignment align = {})
: widget(widget), span(span), align(align) {}
LayoutItem(ProjectConfigurationAspect *aspect) : aspect(aspect) {} LayoutItem(ProjectConfigurationAspect *aspect) : aspect(aspect) {}
LayoutItem(const QString &text) : text(text) {} LayoutItem(const QString &text) : text(text) {}
@@ -62,6 +71,8 @@ public:
QWidget *widget = nullptr; QWidget *widget = nullptr;
ProjectConfigurationAspect *aspect = nullptr; ProjectConfigurationAspect *aspect = nullptr;
QString text; QString text;
int span = 1;
Qt::Alignment align;
}; };
template<typename ...Items> template<typename ...Items>
@@ -77,10 +88,13 @@ public:
QLayout *layout() const; QLayout *layout() const;
private: private:
void flushPendingItems(); void flushPendingFormItems();
QLayout *m_layout = nullptr; QFormLayout *m_formLayout = nullptr;
QList<LayoutItem> m_pendingItems; QGridLayout *m_gridLayout = nullptr;
QList<LayoutItem> m_pendingFormItems;
int m_currentGridRow = 0;
int m_currentGridColumn = 0;
}; };
class PROJECTEXPLORER_EXPORT ProjectConfigurationAspect : public QObject class PROJECTEXPLORER_EXPORT ProjectConfigurationAspect : public QObject