fix(cpn): prevent drag'n'drop and paste if incompatible boards (#7376)

This commit is contained in:
Neil Horne
2026-06-12 11:45:10 +10:00
committed by GitHub
parent be1913dc5f
commit b317b611d3
2 changed files with 43 additions and 15 deletions
+34 -12
View File
@@ -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, QVector<ModelDa
QByteArray clipboard = mimeData->data("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, QVector<ModelDa
return ret;
}
// static
int ModelsListModel::countModelsInMimeData(const QMimeData * mimeData)
int ModelsListModel::countModelsInMimeData(const QMimeData * mimeData) const
{
int ret = 0;
if (mimeData->hasFormat("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
*/
+9 -3
View File
@@ -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<ModelData> * 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;