From b317b611d3afaeb3870ac02153dd75b18b90e3f5 Mon Sep 17 00:00:00 2001 From: Neil Horne <15316949+elecpower@users.noreply.github.com> Date: Fri, 12 Jun 2026 11:45:10 +1000 Subject: [PATCH] fix(cpn): prevent drag'n'drop and paste if incompatible boards (#7376) --- companion/src/modelslist.cpp | 46 ++++++++++++++++++++++++++---------- companion/src/modelslist.h | 12 +++++++--- 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/companion/src/modelslist.cpp b/companion/src/modelslist.cpp index c4961f35e..2b24d040e 100644 --- a/companion/src/modelslist.cpp +++ b/companion/src/modelslist.cpp @@ -145,7 +145,8 @@ ModelsListModel::ModelsListModel(RadioData * radioData, QObject * parent): rootItem = new ModelListItem(labels); // uniqueId and version for drag/drop operations (see encodeHeaderData()) mimeHeaderData.instanceId = QUuid::createUuid(); - mimeHeaderData.dataVersion = 1; + mimeHeaderData.dataVersion = MIME_HEADER_DATA_VERSION; + mimeHeaderData.board = getCurrentBoard(); refresh(); //connect(this, &QAbstractItemModel::rowsAboutToBeRemoved, this, &ModelsListModel::onRowsAboutToBeRemoved); @@ -336,7 +337,10 @@ bool ModelsListModel::canDropMimeData(const QMimeData * data, Qt::DropAction act //qDebug() << action << row << column << parent.row(); // we do not accept dropped general settings right now (user must copy/paste those) - if (hasHeaderMimeData(data) && hasModelsMimeData(data) && (row > -1 || parent.isValid())) + if (hasHeaderMimeData(data) && + hasCompatibleBoardMimeData(data) && + hasModelsMimeData(data) && + (row > -1 || parent.isValid())) return true; return false; @@ -472,8 +476,6 @@ void ModelsListModel::encodeModelsData(const QModelIndexList & indexes, QByteArr return; QDataStream out(data, QIODevice::WriteOnly); - Board::Type board = getCurrentBoard(); - out << board; out << mdlCnt; foreach (const QModelIndex &index, indexes) { @@ -500,6 +502,7 @@ void ModelsListModel::encodeHeaderData(QByteArray * data) const QDataStream stream(data, QIODevice::WriteOnly); stream << mimeHeaderData.dataVersion; stream << mimeHeaderData.instanceId; + stream << mimeHeaderData.board; } void ModelsListModel::encodeFileData(QByteArray * data) const @@ -514,8 +517,16 @@ bool ModelsListModel::decodeHeaderData(const QMimeData * mimeData, MimeHeaderDat QByteArray data = mimeData->data("application/x-companion-radiodata-header"); QDataStream stream(&data, QIODevice::ReadOnly); stream >> header->dataVersion >> header->instanceId; - return true; + + if (header->dataVersion >= 2) { + stream >> header->board; + } else { + header->board = Board::BOARD_UNKNOWN; + } + + return stream.status() == QDataStream::Ok; } + return false; } @@ -542,9 +553,8 @@ bool ModelsListModel::decodeMimeData(const QMimeData * mimeData, QVectordata("application/x-companion-modeldata"); QDataStream in(&clipboard, QIODevice::ReadOnly); - Board::Type board; int mdlCnt; - in >> board >> mdlCnt; + in >> mdlCnt; for (int i = 1; i <= mdlCnt; i++) { QByteArray *buffer = new QByteArray(); @@ -589,16 +599,15 @@ bool ModelsListModel::decodeMimeData(const QMimeData * mimeData, QVectorhasFormat("application/x-companion-modeldata")) { + if (hasCompatibleBoardMimeData(mimeData) && + mimeData->hasFormat("application/x-companion-modeldata")) { QByteArray data = mimeData->data("application/x-companion-modeldata"); QDataStream in(&data, QIODevice::ReadOnly); - Board::Type board; - in >> board >> ret; + in >> ret; } return ret; @@ -767,6 +776,19 @@ void ModelsListModel::setFilename(QString & name) filename = name; } +Board::Type ModelsListModel::getMimeDataBoard(const QMimeData * mimeData) const +{ + MimeHeaderData header; + decodeHeaderData(mimeData, &header); + return header.board; +} + +// returns true if mime data board type is the same as this data model +bool ModelsListModel::hasCompatibleBoardMimeData(const QMimeData * mimeData) const +{ + return (getMimeDataBoard(mimeData) == mimeHeaderData.board); +} + /* ModelsListProxyModel */ diff --git a/companion/src/modelslist.h b/companion/src/modelslist.h index 7c4fba902..c0e7f150a 100644 --- a/companion/src/modelslist.h +++ b/companion/src/modelslist.h @@ -73,14 +73,17 @@ class ModelListItem }; +#define MIME_HEADER_DATA_VERSION 2 + class ModelsListModel : public QAbstractItemModel { Q_OBJECT public: struct MimeHeaderData { - QUuid instanceId; - quint16 dataVersion; + QUuid instanceId{}; + quint16 dataVersion{0}; + Board::Type board{Board::BOARD_UNKNOWN}; }; ModelsListModel(RadioData * radioData, QObject *parent = nullptr); @@ -115,17 +118,20 @@ class ModelsListModel : public QAbstractItemModel QMimeData * getHeaderMimeData(QMimeData * mimeData = nullptr) const; QMimeData * getFileMimeData(QMimeData * mimeData = nullptr) const; QUuid getMimeDataSourceId(const QMimeData * mimeData) const; + Board::Type getMimeDataBoard(const QMimeData * mimeData) const; + bool hasSupportedMimeData(const QMimeData * mimeData) const; bool hasModelsMimeData(const QMimeData * mimeData) const; bool hasGeneralMimeData(const QMimeData * mimeData) const; bool hasHeaderMimeData(const QMimeData * mimeData) const; bool hasOwnMimeData(const QMimeData * mimeData) const; bool hasFileMimeData(const QMimeData * mimeData) const; + bool hasCompatibleBoardMimeData(const QMimeData * mimeData) const; static bool decodeFileData(const QMimeData * mimeData, QString * filedata); static bool decodeHeaderData(const QMimeData * mimeData, MimeHeaderData * header); static bool decodeMimeData(const QMimeData * mimeData, QVector * models = nullptr, GeneralSettings * gs = nullptr, bool * hasGenSet = nullptr); - static int countModelsInMimeData(const QMimeData * mimeData); + int countModelsInMimeData(const QMimeData * mimeData) const; QModelIndex getIndexForModel(const int modelIndex, QModelIndex parent = QModelIndex()); int getModelIndex(const QModelIndex & index) const;