Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
Executable
+534
@@ -0,0 +1,534 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
*
|
||||
* TableModel for dynamic topics
|
||||
*
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include "samplemodel.h"
|
||||
#include <QMimeData>
|
||||
#include <QStringList>
|
||||
#include <QDomDocument>
|
||||
#include "detailviewdlg.h"
|
||||
#include "nglsettings.h"
|
||||
#include "xmlhelper.h"
|
||||
|
||||
//
|
||||
// SampleModel::SampleData
|
||||
//
|
||||
QByteArray SampleModel::SampleData::encodeForMime() const
|
||||
{
|
||||
QByteArray encodedData;
|
||||
QDataStream stream(&encodedData, QIODevice::WriteOnly);
|
||||
stream << QString::fromStdString(typeName)
|
||||
<< reinterpret_cast<quint64>(legatusData.data())
|
||||
<< topicName
|
||||
<< description
|
||||
<< pause;
|
||||
|
||||
return encodedData;
|
||||
}
|
||||
|
||||
SampleModel::SampleData SampleModel::SampleData::decodeFromMime(const QByteArray &encodedData)
|
||||
{
|
||||
SampleData ret;
|
||||
QDataStream stream(const_cast<QByteArray *>(&encodedData), QIODevice::ReadOnly);
|
||||
QString tn;
|
||||
quint64 ptr;
|
||||
dds::core::xtypes::DynamicData *dynDataPtr;
|
||||
stream >> tn >> ptr >> ret.topicName >> ret.description >> ret.pause;
|
||||
ret.typeName = tn.toStdString();
|
||||
dynDataPtr = reinterpret_cast<dds::core::xtypes::DynamicData *>(ptr);
|
||||
ret.legatusData = QSharedPointer<dds::core::xtypes::DynamicData>(new dds::core::xtypes::DynamicData(*dynDataPtr));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//
|
||||
// SampleModel
|
||||
//
|
||||
SampleModel::SampleModel(QObject *parent)
|
||||
: QAbstractTableModel(parent)
|
||||
, m_logger(DdsView::getLogger("SampleModel"))
|
||||
{}
|
||||
|
||||
SampleModel::~SampleModel()
|
||||
{
|
||||
for (const SampleData &sd : qAsConst(m_data))
|
||||
delete sd.dialog;
|
||||
}
|
||||
|
||||
int SampleModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid())
|
||||
return 0;
|
||||
return m_data.size();
|
||||
}
|
||||
|
||||
int SampleModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid())
|
||||
return 0;
|
||||
return Column::Maximum + 1;
|
||||
}
|
||||
|
||||
QVariant SampleModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
if (index.column() >= columnCount(QModelIndex()) ||
|
||||
index.row() >= rowCount(QModelIndex()))
|
||||
return QVariant();
|
||||
|
||||
const SampleData &data = m_data[index.row()];
|
||||
|
||||
if (role == Qt::ToolTipRole
|
||||
&& index.column() == Column::TopicName)
|
||||
return QString::fromStdString(data.typeName);
|
||||
|
||||
if (role != Qt::DisplayRole &&
|
||||
role != Qt::EditRole)
|
||||
return QVariant();
|
||||
|
||||
if (data.typeName.empty())
|
||||
return QVariant();
|
||||
|
||||
switch (index.column())
|
||||
{
|
||||
case Column::TopicName:
|
||||
return data.topicName;
|
||||
case Column::Description:
|
||||
return data.description;
|
||||
case Column::TypeName:
|
||||
return QString::fromStdString(data.typeName);
|
||||
case Column::Pause:
|
||||
return data.pause;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool SampleModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
if (!index.isValid() ||
|
||||
role != Qt::EditRole)
|
||||
return false;
|
||||
|
||||
if (index.column() >= columnCount(QModelIndex()) ||
|
||||
index.row() >= rowCount(QModelIndex()))
|
||||
return false;
|
||||
|
||||
SampleData &data = m_data[index.row()];
|
||||
|
||||
bool retVal = false;
|
||||
switch (index.column())
|
||||
{
|
||||
// Non editable!
|
||||
case Column::TopicName:
|
||||
case Column::TypeName:
|
||||
break;
|
||||
case Column::Description:
|
||||
data.description = value.toString();
|
||||
retVal = true;
|
||||
if (data.dialog)
|
||||
data.dialog->setWindowTitle(QString::fromLatin1("%1 (%2)").arg(data.description, data.topicName));
|
||||
break;
|
||||
case Column::Pause:
|
||||
{
|
||||
int i = value.toInt(&retVal);
|
||||
if (retVal)
|
||||
data.pause = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (retVal)
|
||||
emit dataChanged(index, index);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
bool SampleModel::updateRow(const QModelIndex &index,
|
||||
const QSharedPointer<dds::core::xtypes::DynamicData> &data,
|
||||
const QString &topicName)
|
||||
{
|
||||
int row = index.row();
|
||||
if (row < 0 || row >= rowCount(QModelIndex()))
|
||||
return false;
|
||||
|
||||
SampleData &sample = m_data[row];
|
||||
if (sample.legatusData->type() != data->type())
|
||||
return false;
|
||||
|
||||
sample.legatusData = data;
|
||||
sample.topicName = topicName;
|
||||
return true;
|
||||
}
|
||||
|
||||
Qt::DropActions SampleModel::supportedDropActions() const
|
||||
{
|
||||
return Qt::CopyAction | Qt::MoveAction;
|
||||
}
|
||||
|
||||
Qt::DropActions SampleModel::supportedDragActions() const
|
||||
{
|
||||
return Qt::MoveAction | Qt::CopyAction;
|
||||
}
|
||||
|
||||
QVariant SampleModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (role == Qt::DisplayRole && orientation == Qt::Horizontal)
|
||||
{
|
||||
switch (section)
|
||||
{
|
||||
case Column::TopicName:
|
||||
return tr("Topic Name");
|
||||
case Column::Description:
|
||||
return tr("Description");
|
||||
case Column::TypeName:
|
||||
return tr("Type Name");
|
||||
case Column::Pause:
|
||||
return tr("Pause");
|
||||
}
|
||||
}
|
||||
return QAbstractTableModel::headerData(section, orientation, role);
|
||||
}
|
||||
|
||||
std::string SampleModel::typeName(const QModelIndex &index) const
|
||||
{
|
||||
int row = index.row();
|
||||
if (row < 0 || row >= m_data.size())
|
||||
return std::string();
|
||||
return m_data[row].typeName;
|
||||
}
|
||||
|
||||
bool SampleModel::addRow(const SampleData &sample, int position)
|
||||
{
|
||||
if (position < 0 || position > m_data.size())
|
||||
position = m_data.size();
|
||||
|
||||
beginInsertRows(QModelIndex(), position, position);
|
||||
m_data.insert(position, sample);
|
||||
endInsertRows();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SampleModel::deleteRow(const QModelIndex &index)
|
||||
{
|
||||
int position = index.row();
|
||||
if (position < 0 || position > m_data.size())
|
||||
return false;
|
||||
|
||||
beginRemoveRows(QModelIndex(), position, position);
|
||||
delete m_data[position].dialog;
|
||||
m_data.remove(position);
|
||||
endRemoveRows();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SampleModel::onClear()
|
||||
{
|
||||
beginResetModel();
|
||||
auto it = m_data.begin();
|
||||
while (it != m_data.end())
|
||||
{
|
||||
delete (*it).dialog;
|
||||
it = m_data.erase(it);
|
||||
}
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
Qt::ItemFlags SampleModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
Qt::ItemFlags flags = QAbstractTableModel::flags(index) | Qt::ItemIsDropEnabled;
|
||||
|
||||
if (index.isValid())
|
||||
flags |= Qt::ItemIsDragEnabled;
|
||||
|
||||
if (index.column() == Column::Description || index.column() == Column::Pause)
|
||||
flags |= Qt::ItemIsEditable;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
QMimeData *SampleModel::mimeData(const QModelIndexList &indexes) const
|
||||
{
|
||||
QMimeData *mimeData = new QMimeData();
|
||||
|
||||
QModelIndex mi = indexes.value(0);
|
||||
if (!mi.isValid())
|
||||
return mimeData;
|
||||
|
||||
const SampleData &sample = m_data[mi.row()];
|
||||
|
||||
mimeData->setData(QLatin1String("SampleModel/SampleData"), sample.encodeForMime());
|
||||
return mimeData;
|
||||
}
|
||||
|
||||
bool SampleModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
|
||||
int row, int column, const QModelIndex &parent)
|
||||
{
|
||||
Q_UNUSED(column)
|
||||
if (action == Qt::IgnoreAction)
|
||||
return true;
|
||||
|
||||
if ((action != Qt::MoveAction) && (action != Qt::CopyAction))
|
||||
return false;
|
||||
|
||||
if (data->hasFormat(QLatin1String("SampleModel/SampleData")))
|
||||
{
|
||||
const QByteArray encodedData = data->data(QLatin1String("SampleModel/SampleData"));
|
||||
SampleData sample = SampleData::decodeFromMime(encodedData);
|
||||
|
||||
int beginRow;
|
||||
if (row != -1)
|
||||
beginRow = row;
|
||||
else if (parent.isValid())
|
||||
beginRow = parent.row();
|
||||
else
|
||||
beginRow = rowCount(QModelIndex());
|
||||
|
||||
addRow(sample, beginRow);
|
||||
}
|
||||
else if (data->hasFormat(QLatin1String("dds::core::xtypes::DynamicData/Pointer+TopicName")))
|
||||
{
|
||||
QByteArray encodedData = data->data(QLatin1String("dds::core::xtypes::DynamicData/Pointer+TopicName"));
|
||||
QDataStream stream(&encodedData, QIODevice::ReadOnly);
|
||||
while (!stream.atEnd())
|
||||
{
|
||||
SampleData sample;
|
||||
quint64 ptrVal;
|
||||
|
||||
stream >> ptrVal;
|
||||
stream >> sample.topicName;
|
||||
|
||||
dds::core::xtypes::DynamicData *ptr = reinterpret_cast<dds::core::xtypes::DynamicData *>(ptrVal);
|
||||
if (ptr->type_kind() != dds::core::xtypes::TypeKind::STRUCTURE_TYPE)
|
||||
continue;
|
||||
|
||||
sample.legatusData = QSharedPointer<dds::core::xtypes::DynamicData>(new dds::core::xtypes::DynamicData(*ptr));
|
||||
sample.typeName = ptr->type().name();
|
||||
sample.description = sample.topicName;
|
||||
|
||||
int beginRow;
|
||||
if (row != -1)
|
||||
beginRow = row;
|
||||
else if (parent.isValid())
|
||||
beginRow = parent.row();
|
||||
else
|
||||
beginRow = rowCount(QModelIndex());
|
||||
|
||||
addRow(sample, beginRow);
|
||||
}
|
||||
}
|
||||
else if (data->hasFormat(QLatin1String("Text/TopicName+TypeName")))
|
||||
{
|
||||
QByteArray topicName, typeName;
|
||||
QByteArray encodedData = data->data(QLatin1String("Text/TopicName+TypeName"));
|
||||
QDataStream stream(&encodedData, QIODevice::ReadOnly);
|
||||
stream >> topicName;
|
||||
stream >> typeName;
|
||||
|
||||
SampleData sample;
|
||||
|
||||
// TODO: set topicName
|
||||
sample.typeName = typeName.toStdString();
|
||||
sample.topicName = QString::fromLatin1(topicName.data());
|
||||
sample.description = sample.topicName;
|
||||
sample.legatusData = QSharedPointer<dds::core::xtypes::DynamicData>(new dds::core::xtypes::DynamicData(NGLSettings::instance()->dataTopic(sample.topicName).type));
|
||||
|
||||
int beginRow;
|
||||
if (row != -1)
|
||||
beginRow = row;
|
||||
else if (parent.isValid())
|
||||
beginRow = parent.row();
|
||||
else
|
||||
beginRow = rowCount(QModelIndex());
|
||||
|
||||
addRow(sample, beginRow);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QStringList SampleModel::mimeTypes() const
|
||||
{
|
||||
QStringList sl;
|
||||
sl << QLatin1String("SampleModel/SampleData"); // (SampleModel::SampleData)
|
||||
sl << QLatin1String("dds::core::xtypes::DynamicData/Pointer+TopicName"); // (dds::core::xtypes::DynamicData*) & topicName
|
||||
sl << QLatin1String("Text/TopicName+TypeName"); // e.g. "LTS_ExerciseParticipant" & "ParticipantManagement::ExerciseParticipant"
|
||||
return sl;
|
||||
}
|
||||
|
||||
bool SampleModel::addRow(const dds::core::xtypes::DynamicData &data, const QString &topicName, const QString &description)
|
||||
{
|
||||
SampleData id;
|
||||
|
||||
id.typeName = data.type().name();
|
||||
id.topicName = topicName;
|
||||
id.description = description.isEmpty() ? topicName : description;
|
||||
id.legatusData = QSharedPointer<dds::core::xtypes::DynamicData>(new dds::core::xtypes::DynamicData(data.type()));
|
||||
|
||||
return addRow(id);
|
||||
}
|
||||
|
||||
SampleModel::SampleData SampleModel::sampleData(const QModelIndex &index) const
|
||||
{
|
||||
int row = index.row();
|
||||
if (row < 0 || row >= m_data.size())
|
||||
return SampleData();
|
||||
SampleData data = m_data.value(row);
|
||||
//DEBUG_LOG(m_logger) << "intern: " << data.legatusData.data()->type().name();
|
||||
return data;
|
||||
}
|
||||
|
||||
void SampleModel::setDialog(const QModelIndex &index, DetailViewDlg *dlg)
|
||||
{
|
||||
// Dialog will not be destructed! It will be hidden and reused on second usage.
|
||||
// ~SampleModel takes care tp destruct anyways.
|
||||
int row = index.row();
|
||||
if (row < 0 || row >= m_data.size())
|
||||
return;
|
||||
m_data[row].dialog = dlg;
|
||||
}
|
||||
|
||||
QModelIndex SampleModel::indexByDialog(const DetailViewDlg *dlg) const
|
||||
{
|
||||
for (int i = 0; i < m_data.size(); ++i)
|
||||
if (m_data[i].dialog == dlg)
|
||||
return index(i, 0);
|
||||
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
//
|
||||
// SampleSortModel
|
||||
//
|
||||
bool SampleSortModel::lessThan(const QModelIndex &left,
|
||||
const QModelIndex &right) const
|
||||
{
|
||||
if (left.column() != right.column())
|
||||
return QSortFilterProxyModel::lessThan(left, right);
|
||||
SampleModel *srcModel = qobject_cast<SampleModel *>(sourceModel());
|
||||
if (!srcModel)
|
||||
return QSortFilterProxyModel::lessThan(left, right);
|
||||
SampleModel::SampleData dataLeft = srcModel->sampleData(left);
|
||||
SampleModel::SampleData dataRight = srcModel->sampleData(right);
|
||||
switch (left.column())
|
||||
{
|
||||
case SampleModel::Column::TopicName:
|
||||
return dataLeft.topicName < dataRight.topicName;
|
||||
case SampleModel::Column::Description:
|
||||
return dataLeft.description < dataRight.description;
|
||||
case SampleModel::Column::TypeName:
|
||||
return dataLeft.typeName < dataRight.typeName;
|
||||
case SampleModel::Column::Pause:
|
||||
return dataLeft.pause < dataRight.pause;
|
||||
}
|
||||
return QSortFilterProxyModel::lessThan(left, right);
|
||||
}
|
||||
|
||||
void SampleSortModel::sort(int column, Qt::SortOrder order)
|
||||
{
|
||||
QModelIndex ind = index(m_currentRow, 0);
|
||||
int sourceRow = mapToSource(ind).row();
|
||||
QSortFilterProxyModel::sort(column, order);
|
||||
QModelIndex dex = sourceModel()->index(sourceRow, 0);
|
||||
m_currentRow = mapFromSource(dex).row();
|
||||
emit headerDataChanged(Qt::Vertical, m_currentRow, m_currentRow);
|
||||
}
|
||||
|
||||
QVariant SampleSortModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (role != Qt::DisplayRole)
|
||||
return QSortFilterProxyModel::headerData(section, orientation, role);
|
||||
|
||||
if (orientation == Qt::Vertical)
|
||||
{
|
||||
if (section == m_currentRow)
|
||||
return QChar(0x21D2);
|
||||
return QString();
|
||||
}
|
||||
return sourceModel()->headerData(section, orientation, role);
|
||||
}
|
||||
|
||||
void SampleModel::SampleData::toXml(QDomDocument &doc, QDomElement &elem) const
|
||||
{
|
||||
QDomElement deSample = doc.createElement(QLatin1String("Sample"));
|
||||
elem.appendChild(deSample);
|
||||
|
||||
QDomElement deTopicName = doc.createElement(QLatin1String("TopicName"));
|
||||
deSample.appendChild(deTopicName);
|
||||
QDomText deTopicNameContents = doc.createTextNode(topicName);
|
||||
deTopicName.appendChild(deTopicNameContents);
|
||||
|
||||
QDomElement deTypeName = doc.createElement(QLatin1String("TypeName"));
|
||||
deSample.appendChild(deTypeName);
|
||||
QDomText deTypeNameContents = doc.createTextNode(QString::fromStdString(typeName));
|
||||
deTypeName.appendChild(deTypeNameContents);
|
||||
|
||||
QDomElement dePause = doc.createElement(QLatin1String("Pause"));
|
||||
deSample.appendChild(dePause);
|
||||
QDomText dePauseContents = doc.createTextNode(QString::number(pause));
|
||||
dePause.appendChild(dePauseContents);
|
||||
|
||||
XmlHelper::dds2Xml(*legatusData, topicName, doc, deSample);
|
||||
}
|
||||
|
||||
bool SampleModel::SampleData::fromXml(QDomElement &elem)
|
||||
{
|
||||
if (elem.nodeName().compare(QLatin1String("Sample"), Qt::CaseInsensitive) != 0)
|
||||
return false;
|
||||
|
||||
bool succ = false;
|
||||
QDomNodeList dnl = elem.childNodes();
|
||||
for (int i = 0; i < dnl.size(); ++i)
|
||||
{
|
||||
QDomNode dn = dnl.at(i);
|
||||
if (!dn.isElement())
|
||||
continue;
|
||||
QDomElement de = dn.toElement();
|
||||
if (de.nodeName() == QLatin1String("TopicName"))
|
||||
topicName = de.text();
|
||||
else if (de.nodeName() == QLatin1String("Type"))
|
||||
typeName = de.text().toStdString();
|
||||
else if (de.nodeName() == QLatin1String("Pause"))
|
||||
{
|
||||
bool ok;
|
||||
pause = de.text().toInt(&ok);
|
||||
if (!ok)
|
||||
pause = 1000;
|
||||
}
|
||||
else if (de.nodeName() == QLatin1String("DdsData"))
|
||||
{
|
||||
const QString topicName = XmlHelper::topicNameFromXml(de);
|
||||
const TopicDescriptionEx td = NGLSettings::instance()->topicFromTopicName(topicName);
|
||||
const dds::core::xtypes::DynamicData data = XmlHelper::xml2Dds(de, td);
|
||||
dds::core::xtypes::TypeKind kind = dds::core::xtypes::TypeKind::PRIMITIVE_TYPE;
|
||||
try
|
||||
{
|
||||
kind = data.type_kind();
|
||||
}
|
||||
catch (dds::core::Exception &e)
|
||||
{
|
||||
qWarning("dds exception: %s", e.what());
|
||||
continue;
|
||||
}
|
||||
if (kind != dds::core::xtypes::TypeKind::STRUCTURE_TYPE)
|
||||
continue;
|
||||
|
||||
legatusData = QSharedPointer<dds::core::xtypes::DynamicData>(new dds::core::xtypes::DynamicData(data));
|
||||
typeName = data.type().name();
|
||||
succ = (typeName != "Unknown");
|
||||
}
|
||||
}
|
||||
if (topicName.isEmpty())
|
||||
topicName = QString::fromStdString(typeName);
|
||||
if (description.isEmpty())
|
||||
description = topicName;
|
||||
|
||||
return succ;
|
||||
}
|
||||
Reference in new issue
Block a user