447 lines
17 KiB
C++
Executable File
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
|