Commit f4ff4200 authored by Tobias Hunger's avatar Tobias Hunger

CMake: Improve delegates for CMake configuration

Change-Id: Ib1d2bfca1b2faafd36c53f24c6649e73ee0af190
Reviewed-by: Tim Jenssen's avatarTim Jenssen <tim.jenssen@qt.io>
parent 632f2a77
......@@ -986,8 +986,7 @@ int BaseTreeModel::rowCount(const QModelIndex &idx) const
if (idx.column() > 0)
return 0;
const TreeItem *item = itemForIndex(idx);
QTC_ASSERT(item, return 0);
return item->childCount();
return item ? item->childCount() : 0;
}
int BaseTreeModel::columnCount(const QModelIndex &idx) const
......@@ -1112,7 +1111,7 @@ TreeItem *BaseTreeModel::itemForIndex(const QModelIndex &idx) const
CHECK_INDEX(idx);
TreeItem *item = idx.isValid() ? static_cast<TreeItem*>(idx.internalPointer()) : m_root;
QTC_ASSERT(item, return 0);
QTC_ASSERT(item->m_model == this, return 0);
QTC_ASSERT(item->m_model == static_cast<const BaseTreeModel *>(this), return 0);
return item;
}
......
......@@ -34,9 +34,11 @@
#include <coreplugin/icore.h>
#include <coreplugin/find/itemviewfind.h>
#include <projectexplorer/kitmanager.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/target.h>
#include <utils/asconst.h>
#include <utils/detailswidget.h>
#include <utils/fancylineedit.h>
#include <utils/headerviewstretcher.h>
......@@ -46,12 +48,14 @@
#include <QBoxLayout>
#include <QCheckBox>
#include <QComboBox>
#include <QFrame>
#include <QGridLayout>
#include <QLabel>
#include <QPushButton>
#include <QSortFilterProxyModel>
#include <QSpacerItem>
#include <QStyledItemDelegate>
#include <QMenu>
namespace CMakeProjectManager {
......@@ -161,7 +165,8 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
m_configView->setSelectionMode(QAbstractItemView::SingleSelection);
m_configView->setSelectionBehavior(QAbstractItemView::SelectItems);
m_configView->setFrameShape(QFrame::NoFrame);
m_configView->setItemDelegate(new ConfigModelItemDelegate(m_configView));
m_configView->setItemDelegate(new ConfigModelItemDelegate(m_buildConfiguration->project()->projectDirectory(),
m_configView));
QFrame *findWrapper = Core::ItemViewFind::createSearchableWrapper(m_configView, Core::ItemViewFind::LightColored);
findWrapper->setFrameStyle(QFrame::StyledPanel);
......@@ -221,14 +226,17 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
if (m_buildConfiguration->isParsing())
m_showProgressTimer.start();
else
else {
m_configModel->setConfiguration(m_buildConfiguration->completeCMakeConfiguration());
m_configView->expandAll();
}
connect(m_buildConfiguration->target()->project(), &ProjectExplorer::Project::parsingFinished,
this, [this, buildDirChooser, stretcher]() {
updateButtonState();
m_configModel->setConfiguration(m_buildConfiguration->completeCMakeConfiguration());
m_configView->expandAll();
stretcher->stretch();
updateButtonState();
buildDirChooser->triggerChanged(); // refresh valid state...
m_showProgressTimer.stop();
m_progressIndicator->hide();
......@@ -238,6 +246,10 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
m_showProgressTimer.stop();
m_progressIndicator->hide();
});
connect(m_configTextFilterModel, &QAbstractItemModel::modelReset, this, [this, stretcher]() {
m_configView->expandAll();
stretcher->stretch();
});
connect(m_configModel, &QAbstractItemModel::dataChanged,
this, &CMakeBuildSettingsWidget::updateButtonState);
......@@ -321,10 +333,15 @@ void CMakeBuildSettingsWidget::updateButtonState()
void CMakeBuildSettingsWidget::updateAdvancedCheckBox()
{
if (m_showAdvancedCheckBox->isChecked())
if (m_showAdvancedCheckBox->isChecked()) {
m_configFilterModel->setSourceModel(nullptr);
m_configTextFilterModel->setSourceModel(m_configModel);
else
} else {
m_configTextFilterModel->setSourceModel(nullptr);
m_configFilterModel->setSourceModel(m_configModel);
m_configTextFilterModel->setSourceModel(m_configFilterModel);
}
}
void CMakeBuildSettingsWidget::updateFromKit()
......
......@@ -33,6 +33,7 @@
#include <QCoreApplication>
#include <QFont>
#include <QString>
#include <QSortFilterProxyModel>
namespace CMakeProjectManager {
......@@ -154,6 +155,37 @@ void ConfigModel::forceToString(const QModelIndex &idx)
emit dataChanged(valueIdx, valueIdx);
}
ConfigModel::DataItem ConfigModel::dataItemFromIndex(const QModelIndex &idx)
{
const QAbstractItemModel *m = idx.model();
QModelIndex mIdx = idx;
while (auto sfpm = qobject_cast<const QSortFilterProxyModel *>(m)) {
m = sfpm->sourceModel();
mIdx = sfpm->mapToSource(mIdx);
}
auto model = qobject_cast<const ConfigModel *>(m);
QTC_ASSERT(model, return DataItem());
const QModelIndex modelIdx = mIdx;
Utils::TreeItem *item = model->itemForIndex(modelIdx);
auto cmti = dynamic_cast<Internal::ConfigModelTreeItem *>(item);
if (cmti && cmti->dataItem) {
DataItem di;
di.key = cmti->dataItem->key;
di.type = cmti->dataItem->type;
di.isHidden = cmti->dataItem->isHidden;
di.isAdvanced = cmti->dataItem->isAdvanced;
di.inCMakeCache = cmti->dataItem->inCMakeCache;
di.value = cmti->dataItem->currentValue();
di.description = cmti->dataItem->description;
di.values = cmti->dataItem->values;
return di;
}
return DataItem();
}
QList<ConfigModel::DataItem> ConfigModel::configurationChanges() const
{
const QList<InternalDataItem> tmp
......@@ -303,10 +335,6 @@ QVariant ConfigModelTreeItem::data(int column, int role) const
}
// Leaf node:
if (role == ConfigModel::ItemTypeRole)
return dataItem->type;
if (role == ConfigModel::ItemValuesRole)
return dataItem->values;
if (role == ConfigModel::ItemIsAdvancedRole)
return dataItem->isAdvanced ? "1" : "0";
......
......@@ -38,9 +38,7 @@ class ConfigModel : public Utils::TreeModel<>
public:
enum Roles {
ItemTypeRole = Qt::UserRole,
ItemValuesRole,
ItemIsAdvancedRole
ItemIsAdvancedRole = Qt::UserRole,
};
class DataItem {
......@@ -78,6 +76,8 @@ public:
bool canForceToString(const QModelIndex &idx) const;
void forceToString(const QModelIndex &idx);
static DataItem dataItemFromIndex(const QModelIndex &idx);
QList<DataItem> configurationChanges() const;
private:
......
......@@ -19,60 +19,118 @@
#include "configmodelitemdelegate.h"
#include "configmodel.h"
#include <utils/asconst.h>
#include <utils/pathchooser.h>
#include <QComboBox>
#include <QCheckBox>
#include <QLineEdit>
#include <QPainter>
namespace CMakeProjectManager {
ConfigModelItemDelegate::ConfigModelItemDelegate(QObject* parent)
ConfigModelItemDelegate::ConfigModelItemDelegate(const Utils::FileName &base, QObject* parent)
: QStyledItemDelegate(parent)
, m_base(base)
{ }
ConfigModelItemDelegate::~ConfigModelItemDelegate()
{ }
QWidget *ConfigModelItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const
QWidget* ConfigModelItemDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
// ComboBox ony in column 2
if (index.column() != 1)
return QStyledItemDelegate::createEditor(parent, option, index);
if (index.column() == 1) {
ConfigModel::DataItem data = ConfigModel::dataItemFromIndex(index);
if (data.type == ConfigModel::DataItem::FILE || data.type == ConfigModel::DataItem::DIRECTORY) {
auto edit = new Utils::PathChooser(parent);
edit->setFocusPolicy(Qt::StrongFocus);
edit->setBaseFileName(m_base);
edit->setAutoFillBackground(true);
if (data.type == ConfigModel::DataItem::FILE) {
edit->setExpectedKind(Utils::PathChooser::File);
edit->setPromptDialogTitle(tr("Select a file for %1").arg(data.key));
} else {
edit->setExpectedKind(Utils::PathChooser::Directory);
edit->setPromptDialogTitle(tr("Select a directory for %1").arg(data.key));
}
return edit;
} else if (!data.values.isEmpty()) {
auto edit = new QComboBox(parent);
edit->setFocusPolicy(Qt::StrongFocus);
for (const QString &s : Utils::asConst(data.values))
edit->addItem(s);
return edit;
} else if (data.type == ConfigModel::DataItem::BOOLEAN) {
auto edit = new QCheckBox(parent);
edit->setFocusPolicy(Qt::StrongFocus);
return edit;
} else if (data.type == ConfigModel::DataItem::STRING) {
auto edit = new QLineEdit(parent);
edit->setFocusPolicy(Qt::StrongFocus);
return edit;
}
}
auto model = index.model();
auto values = model->data(index, ConfigModel::ItemValuesRole).toStringList();
if (values.isEmpty())
return QStyledItemDelegate::createEditor(parent, option, index);
// Create the combobox and populate it
auto cb = new QComboBox(parent);
cb->addItems(values);
cb->setEditable(true);
return cb;
}
void ConfigModelItemDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
void ConfigModelItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
if (QComboBox* cb = qobject_cast<QComboBox*>(editor)) {
// get the index of the text in the combobox that matches the current value of the itenm
QString currentText = index.data(Qt::EditRole).toString();
int cbIndex = cb->findText(currentText);
// if it is valid, adjust the combobox
if (cbIndex >= 0)
cb->setCurrentIndex(cbIndex);
else
cb->setEditText(currentText);
} else {
QStyledItemDelegate::setEditorData(editor, index);
if (index.column() == 1) {
ConfigModel::DataItem data = ConfigModel::dataItemFromIndex(index);
if (data.type == ConfigModel::DataItem::FILE || data.type == ConfigModel::DataItem::DIRECTORY) {
auto edit = static_cast<Utils::PathChooser *>(editor);
edit->setFileName(Utils::FileName::fromUserInput(data.value));
return;
} else if (!data.values.isEmpty()) {
auto edit = static_cast<QComboBox *>(editor);
edit->setCurrentText(data.value);
return;
} else if (data.type == ConfigModel::DataItem::BOOLEAN) {
auto edit = static_cast<QCheckBox *>(editor);
edit->setChecked(index.data(Qt::CheckStateRole).toBool());
edit->setText(data.value);
return;
} else if (data.type == ConfigModel::DataItem::STRING) {
auto edit = static_cast<QLineEdit *>(editor);
edit->setText(data.value);
return;
}
}
QStyledItemDelegate::setEditorData(editor, index);
}
void ConfigModelItemDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
void ConfigModelItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const
{
if (QComboBox* cb = qobject_cast<QComboBox*>(editor))
// save the current text of the combo box as the current value of the item
model->setData(index, cb->currentText(), Qt::EditRole);
else
if (index.column() == 1) {
ConfigModel::DataItem data = ConfigModel::dataItemFromIndex(index);
if (data.type == ConfigModel::DataItem::FILE || data.type == ConfigModel::DataItem::DIRECTORY) {
auto edit = static_cast<Utils::PathChooser *>(editor);
if (edit->rawPath() != data.value)
model->setData(index, edit->fileName().toUserOutput(), Qt::EditRole);
return;
} else if (!data.values.isEmpty()) {
auto edit = static_cast<QComboBox *>(editor);
model->setData(index, edit->currentText(), Qt::EditRole);
return;
} else if (data.type == ConfigModel::DataItem::BOOLEAN) {
auto edit = static_cast<QCheckBox *>(editor);
model->setData(index, edit->text(), Qt::EditRole);
} else if (data.type == ConfigModel::DataItem::STRING) {
auto edit = static_cast<QLineEdit *>(editor);
model->setData(index, edit->text(), Qt::EditRole);
}
}
QStyledItemDelegate::setModelData(editor, model, index);
}
QSize CMakeProjectManager::ConfigModelItemDelegate::sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
Q_UNUSED(option);
Q_UNUSED(index);
return QSize(100, m_measurement.sizeHint().height());
}
} // namespace CMakeProjectManager
......@@ -18,20 +18,30 @@
#pragma once
#include <QComboBox>
#include <QStyledItemDelegate>
#include <utils/fileutils.h>
namespace CMakeProjectManager {
class ConfigModelItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
ConfigModelItemDelegate(QObject* parent=0);
~ConfigModelItemDelegate();
ConfigModelItemDelegate(const Utils::FileName &base, QObject *parent = nullptr);
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const final;
void setEditorData(QWidget *editor, const QModelIndex &index) const final;
void setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const final;
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const final;
QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
void setEditorData(QWidget* editor, const QModelIndex& index) const override;
void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override;
private:
Utils::FileName m_base;
QComboBox m_measurement;
};
} // namespace CMakeProjectManager
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment