mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
#1830 AppFwk : Add context menu to control state for multiple items
This commit is contained in:
parent
a0a28fee36
commit
5994ef1393
@ -9,6 +9,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
MainWindow window;
|
||||
window.setWindowTitle("Ceetron Application Framework Test Application");
|
||||
window.resize(1000, 810);
|
||||
window.show();
|
||||
|
||||
return app.exec();
|
||||
|
@ -40,10 +40,9 @@
|
||||
#include "cafPdmObject.h"
|
||||
#include "cafPdmUiTreeSelectionQModel.h"
|
||||
|
||||
#include "cafQTreeViewStateSerializer.h"
|
||||
|
||||
#include <QTreeView>
|
||||
#include <QLabel>
|
||||
#include <QMenu>
|
||||
#include <QTreeView>
|
||||
|
||||
|
||||
namespace caf
|
||||
@ -111,24 +110,202 @@ void PdmUiTreeSelectionEditor::configureAndUpdateUi(const QString& uiConfigName)
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void PdmUiTreeSelectionEditor::slotSetSelectionStateForIndex(int index, bool isSelected)
|
||||
void PdmUiTreeSelectionEditor::slotSetSelectionStateForIndex(int index, bool setSelected)
|
||||
{
|
||||
unsigned int unsignedValue = static_cast<unsigned int>(index);
|
||||
std::vector<int> indices;
|
||||
indices.push_back(index);
|
||||
|
||||
QVariant fieldValue = field()->uiValue();
|
||||
QList<QVariant> valuesSelectedInField = fieldValue.toList();
|
||||
|
||||
if (!isSelected)
|
||||
{
|
||||
valuesSelectedInField.removeAll(QVariant(unsignedValue));
|
||||
setSelectionStateForIndices(indices, setSelected);
|
||||
}
|
||||
else
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void PdmUiTreeSelectionEditor::customMenuRequested(const QPoint& pos)
|
||||
{
|
||||
QMenu menu;
|
||||
|
||||
{
|
||||
std::vector<int> items = selectedCheckableItems();
|
||||
if (items.size() > 0)
|
||||
{
|
||||
{
|
||||
QAction* act = new QAction("Set Selected On", this);
|
||||
connect(act, SIGNAL(triggered()), SLOT(slotSetSelectedOn()));
|
||||
|
||||
menu.addAction(act);
|
||||
}
|
||||
|
||||
{
|
||||
QAction* act = new QAction("Set Selected Off", this);
|
||||
connect(act, SIGNAL(triggered()), SLOT(slotSetSelectedOff()));
|
||||
|
||||
menu.addAction(act);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<int> items = selectedHeaderItems();
|
||||
if (items.size() > 0)
|
||||
{
|
||||
{
|
||||
QAction* act = new QAction("Set Sub Items On", this);
|
||||
connect(act, SIGNAL(triggered()), SLOT(slotSetSubItemsOn()));
|
||||
|
||||
menu.addAction(act);
|
||||
}
|
||||
|
||||
{
|
||||
QAction* act = new QAction("Set Sub Items Off", this);
|
||||
connect(act, SIGNAL(triggered()), SLOT(slotSetSubItemsOff()));
|
||||
|
||||
menu.addAction(act);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (menu.actions().size() > 0)
|
||||
{
|
||||
// Qt doc: QAbstractScrollArea and its subclasses that map the context menu event to coordinates of the viewport().
|
||||
QPoint globalPos = m_treeView->viewport()->mapToGlobal(pos);
|
||||
|
||||
menu.exec(globalPos);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void PdmUiTreeSelectionEditor::slotSetSelectedOn()
|
||||
{
|
||||
std::vector<int> items = selectedCheckableItems();
|
||||
if (items.size() > 0)
|
||||
{
|
||||
setSelectionStateForIndices(items, true);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void PdmUiTreeSelectionEditor::slotSetSelectedOff()
|
||||
{
|
||||
std::vector<int> items = selectedCheckableItems();
|
||||
if (items.size() > 0)
|
||||
{
|
||||
setSelectionStateForIndices(items, false);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void PdmUiTreeSelectionEditor::slotSetSubItemsOn()
|
||||
{
|
||||
caf::PdmUiTreeSelectionQModel* treeSelectionQModel = dynamic_cast<caf::PdmUiTreeSelectionQModel*>(m_treeView->model());
|
||||
|
||||
std::vector<int> items = selectedHeaderItems();
|
||||
for (auto i : items)
|
||||
{
|
||||
std::vector<int> children = treeSelectionQModel->allSubItemIndices(i);
|
||||
|
||||
setSelectionStateForIndices(children, true);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void PdmUiTreeSelectionEditor::slotSetSubItemsOff()
|
||||
{
|
||||
caf::PdmUiTreeSelectionQModel* treeSelectionQModel = dynamic_cast<caf::PdmUiTreeSelectionQModel*>(m_treeView->model());
|
||||
|
||||
std::vector<int> items = selectedHeaderItems();
|
||||
for (auto i : items)
|
||||
{
|
||||
std::vector<int> children = treeSelectionQModel->allSubItemIndices(i);
|
||||
|
||||
setSelectionStateForIndices(children, false);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<int> PdmUiTreeSelectionEditor::selectedCheckableItems() const
|
||||
{
|
||||
std::vector<int> items;
|
||||
|
||||
caf::PdmUiTreeSelectionQModel* treeSelectionQModel = dynamic_cast<caf::PdmUiTreeSelectionQModel*>(m_treeView->model());
|
||||
if (treeSelectionQModel)
|
||||
{
|
||||
QModelIndexList selectedIndexes = m_treeView->selectionModel()->selectedIndexes();
|
||||
|
||||
for (auto mi : selectedIndexes)
|
||||
{
|
||||
auto optionItem = treeSelectionQModel->optionItem(mi);
|
||||
if (!optionItem->isHeading())
|
||||
{
|
||||
items.push_back(treeSelectionQModel->optionItemIndex(mi));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<int> PdmUiTreeSelectionEditor::selectedHeaderItems() const
|
||||
{
|
||||
std::vector<int> items;
|
||||
|
||||
caf::PdmUiTreeSelectionQModel* treeSelectionQModel = dynamic_cast<caf::PdmUiTreeSelectionQModel*>(m_treeView->model());
|
||||
if (treeSelectionQModel)
|
||||
{
|
||||
QModelIndexList selectedIndexes = m_treeView->selectionModel()->selectedIndexes();
|
||||
|
||||
for (auto mi : selectedIndexes)
|
||||
{
|
||||
auto optionItem = treeSelectionQModel->optionItem(mi);
|
||||
if (optionItem->isHeading())
|
||||
{
|
||||
items.push_back(treeSelectionQModel->optionItemIndex(mi));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void PdmUiTreeSelectionEditor::setSelectionStateForIndices(const std::vector<int>& indices, bool setSelected)
|
||||
{
|
||||
std::vector<unsigned int> selectedIndices;
|
||||
{
|
||||
QVariant fieldValue = field()->uiValue();
|
||||
QList<QVariant> fieldValueSelection = fieldValue.toList();
|
||||
|
||||
for (auto v : fieldValueSelection)
|
||||
{
|
||||
selectedIndices.push_back(v.toUInt());
|
||||
}
|
||||
}
|
||||
|
||||
for (auto index : indices)
|
||||
{
|
||||
unsigned int unsignedIndex = static_cast<unsigned int>(index);
|
||||
|
||||
if (setSelected)
|
||||
{
|
||||
bool isIndexPresent = false;
|
||||
for (QVariant v : valuesSelectedInField)
|
||||
for (auto indexInField : selectedIndices)
|
||||
{
|
||||
unsigned int indexInField = v.toUInt();
|
||||
if (indexInField == unsignedValue)
|
||||
if (indexInField == unsignedIndex)
|
||||
{
|
||||
isIndexPresent = true;
|
||||
}
|
||||
@ -136,11 +313,22 @@ void PdmUiTreeSelectionEditor::slotSetSelectionStateForIndex(int index, bool isS
|
||||
|
||||
if (!isIndexPresent)
|
||||
{
|
||||
valuesSelectedInField.push_back(QVariant(unsignedValue));
|
||||
selectedIndices.push_back(unsignedIndex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedIndices.erase(std::remove(selectedIndices.begin(), selectedIndices.end(), unsignedIndex), selectedIndices.end());
|
||||
}
|
||||
}
|
||||
|
||||
this->setValueToField(valuesSelectedInField);
|
||||
QList<QVariant> fieldValueSelection;
|
||||
for (auto v : selectedIndices)
|
||||
{
|
||||
fieldValueSelection.push_back(QVariant(v));
|
||||
}
|
||||
|
||||
this->setValueToField(fieldValueSelection);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -151,6 +339,10 @@ QWidget* PdmUiTreeSelectionEditor::createEditorWidget(QWidget * parent)
|
||||
m_treeView = new QTreeView(parent);
|
||||
|
||||
m_treeView->setHeaderHidden(true);
|
||||
m_treeView->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
m_treeView->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
|
||||
connect(m_treeView, SIGNAL(customContextMenuRequested(QPoint)), SLOT(customMenuRequested(QPoint)));
|
||||
|
||||
return m_treeView;
|
||||
}
|
||||
|
@ -63,7 +63,18 @@ protected:
|
||||
virtual void configureAndUpdateUi(const QString& uiConfigName);
|
||||
|
||||
private slots:
|
||||
void slotSetSelectionStateForIndex(int index, bool isSelected);
|
||||
void slotSetSelectionStateForIndex(int index, bool setSelected);
|
||||
void customMenuRequested(const QPoint& pos);
|
||||
|
||||
void slotSetSelectedOn();
|
||||
void slotSetSelectedOff();
|
||||
void slotSetSubItemsOn();
|
||||
void slotSetSubItemsOff();
|
||||
|
||||
private:
|
||||
std::vector<int> selectedCheckableItems() const;
|
||||
std::vector<int> selectedHeaderItems() const;
|
||||
void setSelectionStateForIndices(const std::vector<int>& indices, bool setSelected);
|
||||
|
||||
private:
|
||||
QPointer<QTreeView> m_treeView;
|
||||
|
@ -83,6 +83,21 @@ int caf::PdmUiTreeSelectionQModel::optionItemCount() const
|
||||
return m_options.size();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const caf::PdmOptionItemInfo* caf::PdmUiTreeSelectionQModel::optionItem(const QModelIndex &index) const
|
||||
{
|
||||
if (index.isValid())
|
||||
{
|
||||
int opIndex = optionItemIndex(index);
|
||||
|
||||
return &(m_options[opIndex]);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -90,9 +105,9 @@ Qt::ItemFlags caf::PdmUiTreeSelectionQModel::flags(const QModelIndex &index) con
|
||||
{
|
||||
if (index.isValid())
|
||||
{
|
||||
int optionItemIndex = toOptionItemIndex(index);
|
||||
int opIndex = optionItemIndex(index);
|
||||
|
||||
if (!m_options[optionItemIndex].isHeading())
|
||||
if (!m_options[opIndex].isHeading())
|
||||
{
|
||||
return QAbstractItemModel::flags(index) | Qt::ItemIsUserCheckable;
|
||||
}
|
||||
@ -109,20 +124,20 @@ QModelIndex caf::PdmUiTreeSelectionQModel::index(int row, int column, const QMod
|
||||
if (!hasIndex(row, column, parent))
|
||||
return QModelIndex();
|
||||
|
||||
int optionItemIndex = -1;
|
||||
int opIndex = -1;
|
||||
if (parent.isValid())
|
||||
{
|
||||
optionItemIndex = toOptionItemIndex(parent) + row + 1;
|
||||
opIndex = optionItemIndex(parent) + row + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
optionItemIndex = m_zeroLevelRowToOptionIndex.at(row);
|
||||
opIndex = m_zeroLevelRowToOptionIndex.at(row);
|
||||
}
|
||||
|
||||
CAF_ASSERT(optionItemIndex > -1);
|
||||
CAF_ASSERT(optionItemIndex < m_options.size());
|
||||
CAF_ASSERT(opIndex > -1);
|
||||
CAF_ASSERT(opIndex < m_options.size());
|
||||
|
||||
return createIndex(row, column, optionItemIndex);
|
||||
return createIndex(row, column, opIndex);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -141,7 +156,7 @@ QModelIndex caf::PdmUiTreeSelectionQModel::parent(const QModelIndex &child) cons
|
||||
if (!child.isValid())
|
||||
return QModelIndex();
|
||||
|
||||
return m_optionsTreeData[toOptionItemIndex(child)].parentModelIndex;
|
||||
return m_optionsTreeData[optionItemIndex(child)].parentModelIndex;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -154,7 +169,7 @@ int caf::PdmUiTreeSelectionQModel::rowCount(const QModelIndex &parent /*= QModel
|
||||
return m_zeroLevelRowCount;
|
||||
}
|
||||
|
||||
return m_optionsTreeData[toOptionItemIndex(parent)].childCount;
|
||||
return m_optionsTreeData[optionItemIndex(parent)].childCount;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -166,13 +181,13 @@ QVariant caf::PdmUiTreeSelectionQModel::data(const QModelIndex &index, int role
|
||||
{
|
||||
CAF_ASSERT(index.internalId() < m_options.size());
|
||||
|
||||
int optionItemIndex = toOptionItemIndex(index);
|
||||
int opIndex = optionItemIndex(index);
|
||||
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
return m_options[optionItemIndex].optionUiText();
|
||||
return m_options[opIndex].optionUiText();
|
||||
}
|
||||
else if (role == Qt::CheckStateRole && !m_options[optionItemIndex].isHeading())
|
||||
else if (role == Qt::CheckStateRole && !m_options[opIndex].isHeading())
|
||||
{
|
||||
CAF_ASSERT(m_uiFieldHandle);
|
||||
|
||||
@ -182,7 +197,7 @@ QVariant caf::PdmUiTreeSelectionQModel::data(const QModelIndex &index, int role
|
||||
for (QVariant v : valuesSelectedInField)
|
||||
{
|
||||
int indexInField = v.toInt();
|
||||
if (indexInField == optionItemIndex)
|
||||
if (indexInField == opIndex)
|
||||
{
|
||||
return Qt::Checked;
|
||||
}
|
||||
@ -204,7 +219,7 @@ bool caf::PdmUiTreeSelectionQModel::setData(const QModelIndex &index, const QVar
|
||||
{
|
||||
bool isSelected = value.toBool();
|
||||
|
||||
emit signalSelectionStateForIndexHasChanged(toOptionItemIndex(index), isSelected);
|
||||
emit signalSelectionStateForIndexHasChanged(optionItemIndex(index), isSelected);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -212,6 +227,36 @@ bool caf::PdmUiTreeSelectionQModel::setData(const QModelIndex &index, const QVar
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
int caf::PdmUiTreeSelectionQModel::optionItemIndex(const QModelIndex& modelIndex) const
|
||||
{
|
||||
CAF_ASSERT(modelIndex.isValid());
|
||||
CAF_ASSERT(modelIndex.internalId() < m_options.size());
|
||||
|
||||
return modelIndex.internalId();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<int> caf::PdmUiTreeSelectionQModel::allSubItemIndices(int headingIndex) const
|
||||
{
|
||||
std::vector<int> children;
|
||||
|
||||
int parentLevel = m_options[headingIndex].level();
|
||||
|
||||
int currentIndex = headingIndex + 1;
|
||||
while (currentIndex < m_options.size() && m_options[currentIndex].level() > parentLevel)
|
||||
{
|
||||
children.push_back(currentIndex);
|
||||
currentIndex++;
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -288,13 +333,3 @@ void caf::PdmUiTreeSelectionQModel::computeOptionItemTreeData()
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
int caf::PdmUiTreeSelectionQModel::toOptionItemIndex(const QModelIndex& modelIndex) const
|
||||
{
|
||||
CAF_ASSERT(modelIndex.isValid());
|
||||
CAF_ASSERT(modelIndex.internalId() < m_options.size());
|
||||
|
||||
return modelIndex.internalId();
|
||||
}
|
||||
|
@ -73,6 +73,9 @@ public:
|
||||
void setOptions(caf::PdmUiFieldEditorHandle* field, const QList<caf::PdmOptionItemInfo>& options);
|
||||
|
||||
int optionItemCount() const;
|
||||
const caf::PdmOptionItemInfo* optionItem(const QModelIndex &index) const;
|
||||
int optionItemIndex(const QModelIndex& modelIndex) const;
|
||||
std::vector<int> allSubItemIndices(int headingIndex) const;
|
||||
|
||||
virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
|
||||
@ -87,7 +90,6 @@ signals:
|
||||
|
||||
private:
|
||||
void computeOptionItemTreeData();
|
||||
int toOptionItemIndex(const QModelIndex& modelIndex) const;
|
||||
|
||||
private:
|
||||
QList<caf::PdmOptionItemInfo> m_options;
|
||||
|
Loading…
Reference in New Issue
Block a user