diff --git a/src/libs/utils/treemodel.cpp b/src/libs/utils/treemodel.cpp index b705f00711a..61a6a8974c1 100644 --- a/src/libs/utils/treemodel.cpp +++ b/src/libs/utils/treemodel.cpp @@ -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(idx.internalPointer()) : m_root; QTC_ASSERT(item, return 0); - QTC_ASSERT(item->m_model == this, return 0); + QTC_ASSERT(item->m_model == static_cast(this), return 0); return item; } diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp b/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp index 8189e7b98ef..c0531ebf379 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp @@ -34,9 +34,11 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -46,12 +48,14 @@ #include #include +#include #include #include #include #include #include #include +#include #include 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() diff --git a/src/plugins/cmakeprojectmanager/configmodel.cpp b/src/plugins/cmakeprojectmanager/configmodel.cpp index 0ab1b6c25ba..f87ffb967da 100644 --- a/src/plugins/cmakeprojectmanager/configmodel.cpp +++ b/src/plugins/cmakeprojectmanager/configmodel.cpp @@ -33,6 +33,7 @@ #include #include #include +#include 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(m)) { + m = sfpm->sourceModel(); + mIdx = sfpm->mapToSource(mIdx); + } + auto model = qobject_cast(m); + QTC_ASSERT(model, return DataItem()); + const QModelIndex modelIdx = mIdx; + + Utils::TreeItem *item = model->itemForIndex(modelIdx); + auto cmti = dynamic_cast(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::configurationChanges() const { const QList 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"; diff --git a/src/plugins/cmakeprojectmanager/configmodel.h b/src/plugins/cmakeprojectmanager/configmodel.h index 0bb06f59b50..adf6edc87e3 100644 --- a/src/plugins/cmakeprojectmanager/configmodel.h +++ b/src/plugins/cmakeprojectmanager/configmodel.h @@ -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 configurationChanges() const; private: diff --git a/src/plugins/cmakeprojectmanager/configmodelitemdelegate.cpp b/src/plugins/cmakeprojectmanager/configmodelitemdelegate.cpp index b2b19b837e2..f5d24b5174c 100644 --- a/src/plugins/cmakeprojectmanager/configmodelitemdelegate.cpp +++ b/src/plugins/cmakeprojectmanager/configmodelitemdelegate.cpp @@ -19,59 +19,117 @@ #include "configmodelitemdelegate.h" #include "configmodel.h" +#include +#include + #include +#include +#include +#include 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); - - 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 -{ - if (QComboBox* cb = qobject_cast(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 = 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; + } } + + return QStyledItemDelegate::createEditor(parent, option, index); } -void ConfigModelItemDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const +void ConfigModelItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { - if (QComboBox* cb = qobject_cast(editor)) - // save the current text of the combo box as the current value of the item - model->setData(index, cb->currentText(), Qt::EditRole); - else - QStyledItemDelegate::setModelData(editor, model, 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(editor); + edit->setFileName(Utils::FileName::fromUserInput(data.value)); + return; + } else if (!data.values.isEmpty()) { + auto edit = static_cast(editor); + edit->setCurrentText(data.value); + return; + } else if (data.type == ConfigModel::DataItem::BOOLEAN) { + auto edit = static_cast(editor); + edit->setChecked(index.data(Qt::CheckStateRole).toBool()); + edit->setText(data.value); + return; + } else if (data.type == ConfigModel::DataItem::STRING) { + auto edit = static_cast(editor); + edit->setText(data.value); + return; + } + } + QStyledItemDelegate::setEditorData(editor, index); +} + +void ConfigModelItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const +{ + 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(editor); + if (edit->rawPath() != data.value) + model->setData(index, edit->fileName().toUserOutput(), Qt::EditRole); + return; + } else if (!data.values.isEmpty()) { + auto edit = static_cast(editor); + model->setData(index, edit->currentText(), Qt::EditRole); + return; + } else if (data.type == ConfigModel::DataItem::BOOLEAN) { + auto edit = static_cast(editor); + model->setData(index, edit->text(), Qt::EditRole); + } else if (data.type == ConfigModel::DataItem::STRING) { + auto edit = static_cast(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 diff --git a/src/plugins/cmakeprojectmanager/configmodelitemdelegate.h b/src/plugins/cmakeprojectmanager/configmodelitemdelegate.h index 8c20f7b8313..ce5571b6be2 100644 --- a/src/plugins/cmakeprojectmanager/configmodelitemdelegate.h +++ b/src/plugins/cmakeprojectmanager/configmodelitemdelegate.h @@ -18,20 +18,30 @@ #pragma once +#include #include +#include + namespace CMakeProjectManager { class ConfigModelItemDelegate : public QStyledItemDelegate { Q_OBJECT -public: - ConfigModelItemDelegate(QObject* parent=0); - ~ConfigModelItemDelegate(); - 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; +public: + 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; + +private: + Utils::FileName m_base; + QComboBox m_measurement; }; } // namespace CMakeProjectManager