Files
qt5-legatus-legacy/Lts/Plugins/ParticipantManagement/Gui/ParticipantSelection/participant_selection.cpp
T
2026-08-13 18:33:10 +02:00

447 lines
17 KiB
C++
Executable File

/**
* @RDE_HEADER@
* GUI Plugin for ParticipantManagement - Participant Edit
* $Id$
* $HeadURL$
* $Author$
* Created by Patric Karwat, SLSE, 2016-10-17
*/
#include "participant_selection.h"
//#include "participant_selection_model.h"
#include "ui_participant_selection.h"
#include <Common/participant_edit_model.h>
#include <Common/participant_beautify_view.h>
#include <Common/participant_tree_edit_handler.h>
#include <ParticipantManagement/logger.h>
#include <LtsSession/lts_session.h>
#include <LtsDataView/search_model.h>
#include <ParticipantManagement/ppm_operator_rights.h>
#include <Plugins/AdvancedSymbology/asb_data_plugin_interface.h>
//#include <LtsUtilsSettings/settings.h>
#include <PluginInterfaces/gui_plugin_interface.h>
#include <Plugins/ParticipantManagement/ppm_participants_gui_plugin_interface.h>
#include <Plugins/ParticipantManagement/ppm_templates_gui_plugin_interface.h>
#include <Plugins/ParticipantManagement/ppm_data_plugin_interface.h>
#include <QTreeView>
#include <QTableView>
#include <QAction>
#include <QHeaderView>
#include <QTimer>
namespace ParticipantManagement
{
int ParticipantSelection::s_preselectedParty = 2;
ParticipantSelection::ParticipantSelection(LtsSession::LtsSession *session, QWidget *parent)
: LtsWidgets::LtsFramelessDialog(parent, LtsWidgets::Behaviour::Modal)
, m_dtc(nullptr)
, m_ppmGuiCbxIfc(nullptr)
, m_session(session)
, m_ui(new Ui::ParticipantSelection)
, m_logger(getLogger("ParticipantSelection"))
{
m_ui->setupUi(this);
// this will make the tree view look like a table
m_ui->tableViewSelection->treeView()->setIndentation(0);
m_ui->tableViewSelection->treeView()->setItemsExpandable(false);
// add buttons to switch between a tree view and a table view
connect(m_ui->pbTreeView, &QPushButton::clicked, this, &ParticipantSelection::onSwitchToTreeView);
connect(m_ui->pbTableView, &QPushButton::clicked, this, &ParticipantSelection::onSwitchToTableView);
m_ui->treeViewSelection->treeView()->setContextMenuPolicy(Qt::CustomContextMenu);
m_ui->tableViewSelection->treeView()->setContextMenuPolicy(Qt::CustomContextMenu);
setStyleSheet(QStringLiteral("QToolTip { background-color: #ffffff; }"));
}
ParticipantSelection::~ParticipantSelection()
{
delete m_ui;
}
bool ParticipantSelection::init()
{
if (!m_session->getDtc<ParticipantManagement::DataInterface>(m_dtc))
return false;
if (!m_session->getForeignGuiInterface<ParticipantManagement::ForeignGuiComboboxInterface>(m_ppmGuiCbxIfc))
return false;
m_session->getForeignDataInterface<AdvancedSymbology::DataInterface>(m_asb);
connect(m_ui->ltsDialogButtonBox->getButton(LtsWidgets::DialogButton::Ok), &QPushButton::clicked, this, &ParticipantSelection::accept);
connect(m_ui->ltsDialogButtonBox->getButton(LtsWidgets::DialogButton::Close), &QPushButton::clicked, this, &ParticipantSelection::reject);
// interfaces ...............................................................................................................
if (!m_dtc || !m_ppmGuiCbxIfc)
return false;
// tree model ...............................................................................................................
m_model = new ParticipantEditModel(this, m_dtc, m_asb);
// connect(m_model, &ParticipantSelectionModel::internalDataChanged, this, &ParticipantSelection::slotChangesMade);
// proxy model for the tree view ............................................................................................
m_proxyTree = new ParticipantTreeFilterProxyModel(this);
m_proxyTree->setSourceModel(m_model);
m_ui->treeViewSelection->setModel(m_proxyTree);
m_ui->treeViewSelection->setContextMenuPolicy(Qt::CustomContextMenu);
#ifndef LTS_DEBUG
m_ui->treeViewSelection->setColumnHidden(ParticipantEditModel::ColParticipantId, true);
#endif
// proxy model for the table view ...........................................................................................
m_proxyTable = new ParticipantTableFilterProxyModel(this);
m_proxyTable->setSourceModel(m_model);
connect(m_ui->tableViewSelection, &LtsDataView::LtsDataView::filterChanged,
m_proxyTable, &ParticipantTableFilterProxyModel::onFilter);
connect(m_ui->tableViewSelection, &LtsDataView::LtsDataView::sortOrderChanged,
this, &ParticipantSelection::onSortTableView);
connect(m_model, &ParticipantEditModel::internalDataChanged,
m_proxyTable, &ParticipantTableFilterProxyModel::init);
connect(m_ui->tableViewSelection, &LtsDataView::LtsDataView::doubleClicked,
this, &ParticipantSelection::accept);
connect(m_ui->treeViewSelection, &LtsDataView::LtsDataView::doubleClicked,
this, &ParticipantSelection::accept);
m_ui->tableViewSelection->setModel(m_proxyTable);
m_ui->tableViewSelection->setContextMenuPolicy(Qt::CustomContextMenu);
#ifndef LTS_DEBUG
m_ui->tableViewSelection->setColumnHidden(ParticipantEditModel::ColParticipantId, true);
#endif
// party combo box ..........................................................................................................
connect(m_ui->cbParty, static_cast<void (LtsWidgets::LtsComboBox::*)(int)>(&LtsWidgets::LtsComboBox::currentIndexChanged),
this, &ParticipantSelection::onPartyChanged); // This is a direct connection as the receiver lives in this same thread.
m_ppmGuiCbxIfc->fillPartyComboBox(m_ui->cbParty,
ForeignGuiComboboxInterface::CbxPartyFilter::NormalPool);
// // tree handler .............................................................................................................
// m_pTreehandler = new ParticipantTreeEditHandler(m_ui->treeViewSelection, m_dtc, nullptr, false, this);
// connect(m_pTreehandler, &ParticipantTreeEditHandler::signalSelectionChanged, this, &ParticipantSelection::onEnaDisa);
// connect(m_ui->tableViewSelection->treeView(), &QTreeView::customContextMenuRequested,
// m_pTreehandler, &ParticipantTreeEditHandler::showContextMenu);
// ..........................................................................................................................
const int idx = m_ui->cbParty->findData(s_preselectedParty);
if (idx >= 0)
m_ui->cbParty->setCurrentIndex(idx);
// synchronize tree view and table view .....................................................................................
// filtering
connect(m_ui->treeViewSelection, &LtsDataView::LtsDataView::filterChanged,
this, [this](){ onFilterChanged(m_ui->treeViewSelection->searchModel(), m_ui->tableViewSelection->searchModel()); });
connect(m_ui->tableViewSelection, &LtsDataView::LtsDataView::filterChanged,
this, [this](){ onFilterChanged(m_ui->tableViewSelection->searchModel(), m_ui->treeViewSelection->searchModel()); });
// selection
connect(m_ui->treeViewSelection, &LtsDataView::LtsDataView::selectionChanged,
this, &ParticipantSelection::onSelectionChangedInTree);
connect(m_ui->tableViewSelection, &LtsDataView::LtsDataView::selectionChanged,
this, &ParticipantSelection::onSelectionChangedInTable);
// column width
connect(m_ui->treeViewSelection->searchView()->header(), &QHeaderView::sectionResized,
this, [this](int column, int oldWidth, int newWidth)
{
Q_UNUSED(oldWidth);
onColumnWidthChanged(m_ui->tableViewSelection->searchView(), column, newWidth);
});
connect(m_ui->tableViewSelection->searchView()->header(), &QHeaderView::sectionResized,
this, [this](int column, int oldWidth, int newWidth)
{
Q_UNUSED(oldWidth);
onColumnWidthChanged(m_ui->treeViewSelection->searchView(), column, newWidth);
});
// ..........................................................................................................................
m_model->setUnitsSelectable(false);
onSwitchToTreeView();
onPartyChanged();
onEnaDisa();
return true;
}
void ParticipantSelection::setMultiSelectionEnabled(bool enabled)
{
if (enabled)
{
m_ui->treeViewSelection->setSelectionMode(QAbstractItemView::SelectionMode::MultiSelection);
m_ui->tableViewSelection->setSelectionMode(QAbstractItemView::SelectionMode::MultiSelection);
}
else
{
m_ui->treeViewSelection->setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection);
m_ui->tableViewSelection->setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection);
}
}
void ParticipantSelection::setParticipantSelected(int partyId, int participantId)
{
if (participantId <= 0)
return;
m_ui->cbParty->setCurrentIndex(m_ui->cbParty->findData(partyId));
// As the slot that update the table/tree is a DirectConnection, we can go on here and will find the index.
const QModelIndex index = m_model->indexFromParticipantId(participantId);
onSelectionChangedInTable(QItemSelection(index, index),{});
onSelectionChangedInTree(QItemSelection(index, index),{});
}
//void ParticipantSelection::retranslate()
//{
// translate(m_ui, tr("Select Participants"));
//}
void ParticipantSelection::accept()
{
QModelIndexList indexList = m_ui->tableViewSelection->selectionModel()->selectedIndexes();
if (indexList.isEmpty())
return;
LtsWidgets::LtsFramelessDialog::accept();
m_proxyTable->resetMapping();
m_proxyTable->init();
QVector<int> participantIds;
participantIds.reserve(indexList.size());
for (const auto &index : qAsConst(indexList))
{
QModelIndex sourceIndex = m_proxyTable->mapToSource(index);
if (index.column() != 0)
continue;
participantIds << m_model->privateData(sourceIndex)->participant.id();
}
emit selectedParticipants(participantIds);
}
void ParticipantSelection::onPartyChanged()
{
const int newPartyId = m_ui->cbParty->currentData().toInt();
s_preselectedParty = newPartyId;
m_proxyTable->resetMapping();
m_proxyTable->disableSorting();
if (m_model->onReinitModel(newPartyId))
{
m_ui->treeViewSelection->expandAll();
m_ui->treeViewSelection->resizeHeadersByContent();
}
m_proxyTable->init();
// Some icons in the table view won't update automatically after initialization (maybe a timing issue?).
// Workaround: emit dataChanged on the first items (up to 50 rows, since more will not be visible after reinit)
// with a slight delay of 100 msecs to force an update.
QTimer *timer = new QTimer(this);
timer->singleShot(100, this, [this, timer]()
{
m_ui->tableViewSelection->treeView()->dataChanged
(
m_proxyTable->index(0, 0),
m_proxyTable->index(std::min(50, m_proxyTable->rowCount()), 0),
{ Qt::DecorationRole }
);
timer->deleteLater();
});
}
void ParticipantSelection::onChangesMade()
{
onEnaDisa();
if (m_model->onReinitModel(s_preselectedParty))
beautifyTreeView(m_ui->treeViewSelection->treeView(), m_model, true);
}
void ParticipantSelection::onBeautifyTreeView()
{
beautifyTreeView(m_ui->treeViewSelection->treeView(), m_model, true);
}
void ParticipantSelection::onEnaDisa()
{
// OK only enabled if there's at least one item selected.
}
void ParticipantSelection::onSwitchToTreeView()
{
m_ui->pbTreeView->setEnabled(false);
m_ui->pbTableView->setEnabled(true);
m_ui->tableViewSelection->hide();
m_ui->treeViewSelection->show();
m_ui->treeViewSelection->expandAll();
if (!m_ui->treeViewSelection->selectionModel()->selectedIndexes().isEmpty()) // scroll to selection
{
const QModelIndex &proxyIndex = m_ui->treeViewSelection->selectionModel()->selectedIndexes().first();
m_ui->treeViewSelection->scrollTo(proxyIndex);
} // if
onEnaDisa();
}
void ParticipantSelection::onSwitchToTableView()
{
m_ui->pbTreeView->setEnabled(true);
m_ui->pbTableView->setEnabled(false);
m_ui->treeViewSelection->hide();
m_ui->tableViewSelection->show();
if (!m_ui->tableViewSelection->selectionModel()->selectedIndexes().isEmpty()) // scroll to selection
{
const QModelIndex &proxyIndex = m_ui->tableViewSelection->selectionModel()->selectedIndexes().first();
m_ui->tableViewSelection->scrollTo(proxyIndex);
} // if
onEnaDisa();
}
void ParticipantSelection::onSelectionChangedInTree(const QItemSelection &selected, const QItemSelection &deselected)
{
m_ui->tableViewSelection->blockSignals(true);
QModelIndexList indexes = deselected.indexes();
for (const QModelIndex &sourceIndex : qAsConst(indexes))
{
QModelIndex proxyIndex = m_proxyTable->mapFromSource(sourceIndex);
if (m_ui->tableViewSelection->selectionModel()->selectedIndexes().contains(proxyIndex))
m_ui->tableViewSelection->selectionModel()->select(proxyIndex, { QItemSelectionModel::Deselect, QItemSelectionModel::Rows });
} // for
indexes = selected.indexes();
for (const QModelIndex &sourceIndex : qAsConst(indexes))
{
QModelIndex proxyIndex = m_proxyTable->mapFromSource(sourceIndex);
if (!m_ui->tableViewSelection->selectionModel()->selectedIndexes().contains(proxyIndex))
m_ui->tableViewSelection->selectionModel()->select(proxyIndex, { QItemSelectionModel::Select, QItemSelectionModel::Rows });
} // for
m_ui->tableViewSelection->blockSignals(false);
m_ui->ltsDialogButtonBox->getButton(LtsWidgets::DialogButton::Ok)->setEnabled(m_ui->treeViewSelection->selectedRows().count() > 0);
}
void ParticipantSelection::onSelectionChangedInTable(const QItemSelection &selected, const QItemSelection &deselected)
{
m_ui->treeViewSelection->blockSignals(true);
QModelIndexList indexes = deselected.indexes();
for (const QModelIndex &sourceIndex : qAsConst(indexes))
{
QModelIndex proxyIndex = m_proxyTree->mapFromSource(sourceIndex);
if (m_ui->treeViewSelection->selectionModel()->selectedIndexes().contains(proxyIndex))
m_ui->treeViewSelection->selectionModel()->select(proxyIndex, { QItemSelectionModel::Deselect, QItemSelectionModel::Rows });
} // for
indexes = selected.indexes();
for (const QModelIndex &sourceIndex : qAsConst(indexes))
{
QModelIndex proxyIndex = m_proxyTree->mapFromSource(sourceIndex);
if (!m_ui->treeViewSelection->selectionModel()->selectedIndexes().contains(proxyIndex))
m_ui->treeViewSelection->selectionModel()->select(proxyIndex, { QItemSelectionModel::Select, QItemSelectionModel::Rows });
} // for
m_ui->treeViewSelection->blockSignals(false);
m_ui->ltsDialogButtonBox->getButton(LtsWidgets::DialogButton::Ok)->setEnabled(m_ui->tableViewSelection->selectedRows().count() > 0);
}
void ParticipantSelection::onFilterChanged(LtsDataView::SearchModel *from, LtsDataView::SearchModel *to)
{
for (int column = 0; column < to->columnCount(); ++column)
{
QModelIndex fromIndex = from->index(0, column, QModelIndex());
QModelIndex toIndex = to->index(0, column, QModelIndex());
QVariant columnFilter = from->data(fromIndex, Qt::EditRole);
QVariant comboBoxData = from->data(fromIndex, LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole);
if (columnFilter != to->data(toIndex, Qt::EditRole))
{
to->setData(toIndex, columnFilter, Qt::EditRole);
to->setData(toIndex, from->data(fromIndex, Qt::DisplayRole).toString(), Qt::DisplayRole);
} // if
else if (comboBoxData != to->data(toIndex, LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole))
{
to->setData(toIndex, comboBoxData, LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole);
LtsWidgets::ComboboxFilterContent comboFilterContent = LtsWidgets::ComboboxFilterContent::fromVariant(
m_model->headerData(column, Qt::Horizontal, LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole)
);
if (comboBoxData.toInt() == 0)
{
to->setData(toIndex, tr("<no filter>"), Qt::DisplayRole);
} // if
else
{
for (const LtsWidgets::ComboboxFilterData &data : qAsConst(comboFilterContent.data))
if (data.data == comboBoxData)
{
to->setData(toIndex, data.text, Qt::DisplayRole);
break;
} // if
} // else
} // else if
} // for
// undo selection
m_ui->tableViewSelection->blockSignals(true);
m_ui->tableViewSelection->selectionModel()->clearSelection();
m_ui->tableViewSelection->blockSignals(false);
m_ui->treeViewSelection->blockSignals(true);
m_ui->treeViewSelection->selectionModel()->clearSelection();
m_ui->treeViewSelection->blockSignals(false);
}
void ParticipantSelection::onSortTableView(int column, Qt::SortOrder order)
{
QModelIndex sourceIndex;
if (!m_ui->treeViewSelection->selectionModel()->selectedIndexes().isEmpty()) // store selected item
{
QModelIndex proxyIndex = m_ui->tableViewSelection->selectionModel()->selectedIndexes().first();
sourceIndex = m_proxyTable->mapToSource(proxyIndex);
m_ui->tableViewSelection->blockSignals(true);
m_ui->tableViewSelection->selectionModel()->select(proxyIndex, { QItemSelectionModel::Deselect, QItemSelectionModel::Rows });
m_ui->tableViewSelection->blockSignals(false);
} // if
m_proxyTable->onSort(column, order);
if (sourceIndex != QModelIndex()) // reselect item with new index
{
QModelIndex proxyIndex = m_proxyTable->mapFromSource(sourceIndex);
m_ui->tableViewSelection->blockSignals(true);
m_ui->tableViewSelection->selectionModel()->select(proxyIndex, { QItemSelectionModel::Select, QItemSelectionModel::Rows });
m_ui->tableViewSelection->blockSignals(false);
m_ui->tableViewSelection->scrollTo(proxyIndex);
} // if
}
void ParticipantSelection::onColumnWidthChanged(QTreeView *to, const int &column, const int &width)
{
if (to->columnWidth(column) != width)
to->setColumnWidth(column, width);
}
} //namespace ParticipantManagement