Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

+354
View File
@@ -0,0 +1,354 @@
/**
* @RDE_HEADER@
*
* TableView for dynamic topics
*
* $Id$
* $HeadURL$
* $Author$
*/
#include "sampleview.h"
#include "samplemodel.h"
#include "topicselector.h"
#include "detailviewdlg.h"
#include <QHeaderView>
#include <QMenu>
#include <QFile>
#include <QFileDialog>
#include <QMessageBox>
SampleView::SampleView(QWidget *parent)
: QTableView(parent)
, m_proxyModel(new SampleSortModel(this))
, m_model(new SampleModel(this))
, m_topicSelector(nullptr)
, m_playTimer(this)
, m_repeat(false)
, m_bConnected(false)
, m_logger(DdsView::getLogger("SampleView"))
{
init();
}
void SampleView::init()
{
m_proxyModel->setSourceModel(m_model);
setModel(m_proxyModel);
sortByColumn(0, Qt::AscendingOrder);
setSelectionBehavior(SelectRows);
setSelectionMode(QAbstractItemView::SingleSelection);
setSortingEnabled(true);
horizontalHeader()->setStretchLastSection(true);
setAcceptDrops(true);
setDragEnabled(true);
setDragDropMode(QAbstractItemView::DragDrop);
setDropIndicatorShown(true);
setDefaultDropAction(Qt::MoveAction);
setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::EditKeyPressed);
// verticalHeader()->hide();
connect(this, &SampleView::doubleClicked, this, &SampleView::onTableDoubleClicked);
setContextMenuPolicy(Qt::CustomContextMenu);
connect(this, &SampleView::customContextMenuRequested, this, &SampleView::onCustomContextMenuRequested);
connect(&m_playTimer, &QTimer::timeout, this, [this]() { onPlayTimerTimeout(); });
m_playTimer.setSingleShot(true);
// Todo: Model vs. ProxyModel? Column always correct?
hideColumn(static_cast<int>(SampleModel::Column::TypeName));
}
SampleView::~SampleView()
{
delete m_model;
delete m_proxyModel;
}
int SampleView::currentRow() const
{
return m_proxyModel->currentRow();
}
void SampleView::setCurrentRow(int row)
{
m_proxyModel->setCurrentRow(row);
}
void SampleView::onLoadSampleList()
{
QString filename = QFileDialog::getOpenFileName(this, tr("Load Sample List"), QString(), tr("Sample List Files (*.spl);;All Files(*)"));
if (filename.isEmpty())
return;
QFile f(filename);
if (!f.open(QFile::ReadOnly))
{
QMessageBox::warning(this, tr("File not readable"), tr("The selected file is not readable"));
return;
}
QDomDocument doc;
if (!doc.setContent(&f))
{
QMessageBox::warning(this, tr("File not readable"), tr("The selected file is no valid XML"));
f.close();
return;
}
f.close();
m_model->onClear();
QDomElement de = doc.documentElement();
if (de.nodeName() != QLatin1String("Samples"))
{
QMessageBox::warning(this, tr("File not readable"), tr("The XML file has no valid Root Item."));
return;
}
QDomNodeList dnl = de.childNodes();
int errCount = 0;
for (int i = 0; i < dnl.size(); ++i)
{
QDomNode dn = dnl.at(i);
if (!dn.isElement())
continue;
QDomElement innerDe = dn.toElement();
if (innerDe.nodeName() != QLatin1String("Sample"))
continue;
SampleModel::SampleData sample;
bool succ = sample.fromXml(innerDe);
if (succ)
m_model->addRow(sample);
else
++errCount;
}
if (errCount > 0)
QMessageBox::warning(this,
tr("Not all samples could be read"),
tr("There were %1 samples that could not be read from file.").arg(errCount));
}
void SampleView::onSaveSampleList()
{
QString selectedFilter;
QString filename = QFileDialog::getSaveFileName(this, tr("Save Sample List"), QString(),
tr("Sample List Files (*.spl);;All Files(*)"),
&selectedFilter);
if (filename.isEmpty())
return;
if (selectedFilter.contains(QLatin1String("spl")) && !filename.endsWith(QLatin1String(".spl")))
filename += QLatin1String(".spl");
QFile f(filename);
if (!f.open(QFile::WriteOnly))
return;
QDomDocument doc(QLatin1String("Samples"));
QDomElement root = doc.createElement(QLatin1String("Samples"));
doc.appendChild(root);
for (int i = 0; i < m_proxyModel->rowCount(); ++i)
{
QModelIndex mi = m_proxyModel->index(i, 0);
QModelIndex sourceMi = m_proxyModel->mapToSource(mi);
SampleModel::SampleData sample = m_model->sampleData(sourceMi);
sample.toXml(doc, root);
}
f.write(doc.toByteArray());
f.close();
}
void SampleView::onTableDoubleClicked(const QModelIndex &mi)
{
QModelIndex sourceMi = m_proxyModel->mapToSource(mi);
if (mi.column() == SampleModel::Column::Description ||
mi.column() == SampleModel::Column::Pause)
return;
const QSharedPointer<dds::core::xtypes::DynamicData> data = m_model->sampleData(sourceMi).legatusData;
DetailViewDlg *dvd = m_model->sampleData(sourceMi).dialog;
if (dvd)
{
dvd->fill(*data.data());
dvd->setWindowTitle(QString::fromLatin1("%1 (%2)").arg(m_model->sampleData(sourceMi).description,
m_model->sampleData(sourceMi).topicName));
}
else
{
dvd = new DetailViewDlg(this);
connect(dvd, &DetailViewDlg::dataChanged, this, &SampleView::onUpdateData);
connect(dvd, &DetailViewDlg::send, this, &SampleView::send);
dvd->init(*data.data(), m_model->sampleData(sourceMi).topicName, RwMode::WriteOnly);
dvd->setBtnsSendOkCancel();
dvd->setWindowTitle(QString::fromLatin1("%1 (%2)").arg(m_model->sampleData(sourceMi).description,
m_model->sampleData(sourceMi).topicName));
m_model->setDialog(sourceMi, dvd);
}
dvd->setConnected(m_bConnected);
dvd->show();
dvd->adjustSize();
}
void SampleView::onSendSample(const QModelIndex &mi)
{
const QSharedPointer<dds::core::xtypes::DynamicData> data = m_model->sampleData(m_proxyModel->mapToSource(mi)).legatusData;
emit dataClicked(*data.data());
}
void SampleView::onCustomContextMenuRequested(const QPoint &p)
{
const auto selIndexes = selectionModel()->selectedRows();
QMenu menu(this);
menu.addAction(tr("New"), this, &SampleView::onNewTopicRequested);
// Only allowg, when a row is selected
if (selIndexes.count() == 1)
menu.addAction(tr("Delete"), this, &SampleView::onDeleteIndex);
if (selIndexes.size() == 1)
menu.addAction(tr("Copy"), this, &SampleView::onCopyTelegram);
if (!m_copiedSampleData.topicName.isEmpty())
menu.addAction(tr("Paste"), this, &SampleView::onPasteTelegram);
if (m_model->rowCount() != 0)
menu.addAction(tr("Clear"), m_model, &SampleModel::onClear);
// Only allow, when a row is selected:
if (selIndexes.count() != 0 && m_bConnected)
menu.addAction(tr("Send"), this, &SampleView::onSendIndex);
// Only allow, when a row is selected:
if (selIndexes.size() == 1)
menu.addAction(tr("Set current"), this, &SampleView::onSetCurrent);
menu.addSeparator();
// Only allow saving all, when at least one row is available
if (m_model->rowCount() != 0)
menu.addAction(tr("Save all"), this, &SampleView::onSaveSampleList);
menu.addAction(tr("Load"), this, &SampleView::onLoadSampleList);
menu.exec(this->viewport()->mapToGlobal(p));
}
void SampleView::onNewTopicRequested()
{
if (!m_topicSelector)
{
m_topicSelector = new TopicSelector(TopicSelector::Usage::SampleSkeletons, this);
connect(m_topicSelector, &TopicSelector::data, this, &SampleView::onAdd);
}
m_topicSelector->show();
}
void SampleView::onAdd(const dds::core::xtypes::DynamicData &data, const QString &topicName)
{
m_model->addRow(data, topicName);
for (int i = 0; i < m_model->columnCount(QModelIndex()); ++i)
resizeColumnToContents(i);
}
void SampleView::onCopyTelegram()
{
const auto selIndexes = selectedIndexes();
if (selIndexes.isEmpty())
return;
QModelIndex sourceMi = m_proxyModel->mapToSource(selIndexes.value(0));
m_copiedSampleData = m_model->sampleData(sourceMi);
}
void SampleView::onPasteTelegram()
{
if (m_copiedSampleData.topicName.isEmpty())
return;
m_model->addRow(m_copiedSampleData);
}
void SampleView::onDeleteIndex()
{
QModelIndex sourceMi = m_proxyModel->mapToSource(selectedIndexes().value(0));
m_model->deleteRow(sourceMi);
}
void SampleView::onSendIndex()
{
const auto selIndexes = selectedIndexes();
if (selIndexes.isEmpty())
return;
QModelIndex sourceMi = m_proxyModel->mapToSource(selIndexes.value(0));
const SampleModel::SampleData sampleData = m_model->sampleData(sourceMi);
emit send(sampleData.legatusData, sampleData.topicName);
}
void SampleView::onUpdateData(const QSharedPointer<dds::core::xtypes::DynamicData> &data,
const QString &topicName)
{
DetailViewDlg *dlg = qobject_cast<DetailViewDlg *>(sender());
if (!dlg)
return;
QModelIndex index = m_model->indexByDialog(dlg);
if (index.isValid())
m_model->updateRow(index, data, topicName);
}
void SampleView::onSetCurrent()
{
QModelIndex mi = selectedIndexes().value(0);
m_proxyModel->setCurrentRow(mi.row());
verticalHeader()->resizeSections(QHeaderView::ResizeToContents);
}
void SampleView::onPlayChecked(bool down)
{
// Unchecked
if (!down)
{
m_playTimer.stop();
return;
}
// If no valid row, start from first row
if (currentRow() < 0)
setCurrentRow(0);
onPlayTimerTimeout(false);
}
void SampleView::onPlayTimerTimeout(bool moveOn)
{
// Move to next row
if (moveOn)
{
setCurrentRow(currentRow() + 1);
// If moved beyond end
if (currentRow() < 0)
{
// start over
if (m_repeat)
setCurrentRow(0);
else
{
// or stop
emit playerActive(false);
return;
}
}
}
const SampleModel::SampleData sampleData = m_model->sampleData(m_proxyModel->mapToSource(m_proxyModel->index(currentRow(), 0)));
if (sampleData.legatusData)
emit send(sampleData.legatusData, sampleData.topicName);
int pause = m_model->sampleData(m_proxyModel->index(currentRow(), 0)).pause;
if (pause > 0)
m_playTimer.start(pause);
else
emit playerActive(false);
}