11#include <QItemSelection>
20constexpr auto kWaveformMimeType =
"application/x-bewaveddolphin-waveform";
22constexpr auto kLegacyMimeType =
"bdolphin/copydata";
25template <
typename Extract>
26int minAcrossRanges(
int fallback,
const QItemSelection &ranges, Extract extract)
28 int result = fallback;
29 for (
const auto &range : ranges) {
30 result = (std::min)(result, extract(range));
40 return minAcrossRanges(model.columnCount() - 1, ranges, [](
const auto &r) { return r.left(); });
45 return minAcrossRanges(model.rowCount() - 1, ranges, [](
const auto &r) { return r.top(); });
48void copy(
const SignalModel &model,
const QItemSelection &ranges, QDataStream &stream)
50 const int anchorRow =
firstRow(model, ranges);
52 const auto itemList = ranges.indexes();
53 const qint64 sz = itemList.size();
56 for (
const auto &item : itemList) {
57 const int value = model.
value(item.row(), item.column());
60 stream << static_cast<qint64>(item.row() - anchorRow);
61 stream << static_cast<qint64>(item.column() - anchorCol);
62 stream << static_cast<qint64>(value);
69 const int anchorRow =
firstRow(model, ranges);
70 quint64 itemListSize; stream >> itemListSize;
76 constexpr qint64 kBytesPerItem = 3 *
static_cast<qint64
>(
sizeof(quint64));
77 const qint64 available = stream.device() ? stream.device()->bytesAvailable() : 0;
78 const quint64 maxItems = available > 0 ?
static_cast<quint64
>(available / kBytesPerItem) : 0;
79 if (itemListSize > maxItems) {
80 qCWarning(zero) <<
"DolphinClipboard: truncating paste from" << itemListSize
81 <<
"items to" << maxItems <<
"(insufficient stream data)";
82 itemListSize = maxItems;
86 for (quint64 i = 0; i < itemListSize; ++i) {
87 quint64 row; stream >> row;
88 quint64 col; stream >> col;
89 quint64 value; stream >> value;
91 const int newRow =
static_cast<int>(
static_cast<quint64
>(anchorRow) + row);
92 const int newCol =
static_cast<int>(
static_cast<quint64
>(anchorCol) + col);
96 if ((newRow < model.
inputRows()) && (newCol < model.columnCount())) {
97 model.
setValue(newRow, newCol,
static_cast<int>(value));
106 QDataStream stream(&itemData, QIODevice::WriteOnly);
108 copy(model, ranges, stream);
110 auto *mimeData =
new QMimeData();
111 mimeData->setData(kWaveformMimeType, itemData);
112 QApplication::clipboard()->setMimeData(mimeData);
117 const auto *mimeData = QApplication::clipboard()->mimeData();
122 if (mimeData->hasFormat(kLegacyMimeType)) {
123 itemData = mimeData->data(kLegacyMimeType);
126 if (mimeData->hasFormat(kWaveformMimeType)) {
127 itemData = mimeData->data(kWaveformMimeType);
130 if (itemData.isEmpty()) {
134 QDataStream stream(&itemData, QIODevice::ReadOnly);
136 paste(model, ranges, stream);
Common logging utilities, the Pandaception error type, and helper macros.
DolphinClipboard: copy/paste of waveform cell rectangles to/from a data stream.
Circuit and waveform file serialization/deserialization utilities.
SignalModel for the beWavedDolphin waveform table.
static void readDolphinHeader(QDataStream &stream)
Reads and validates the BeWavedDolphin waveform file header.
static void writeDolphinHeader(QDataStream &stream)
Writes the BeWavedDolphin waveform file header to stream.
QStandardItemModel subclass that makes all cells non-editable.
void setValue(int row, int col, int value)
Sets the logic value (0/1) of the cell at (row, col).
int value(int row, int col) const
Returns the logic value (0/1) of the cell at (row, col).
int inputRows() const
Returns the number of input rows (the output rows follow them).
The beWavedDolphin clipboard layer: cell ↔ stream mapping plus the system clipboard transport (MIME w...
int firstRow(const SignalModel &model, const QItemSelection &ranges)
Returns the topmost row index in ranges (clamped to the model's rows).
bool pasteFromClipboard(SignalModel &model, const QItemSelection &ranges)
void copyToClipboard(const SignalModel &model, const QItemSelection &ranges)
int firstColumn(const SignalModel &model, const QItemSelection &ranges)
Returns the leftmost column index in ranges (clamped to the model's columns).
void paste(SignalModel &model, const QItemSelection &ranges, QDataStream &stream)
void copy(const SignalModel &model, const QItemSelection &ranges, QDataStream &stream)