12#include <QLoggingCategory>
36 if (m_scene->selectedElements().empty()) {
37 QApplication::clipboard()->clear();
42 QDataStream stream(&itemData, QIODevice::WriteOnly);
44 serializeItems(m_scene->selectedItems(), stream);
46 auto mimeData = std::make_unique<QMimeData>();
50 auto *registry = m_scene->icRegistry();
51 QMap<QString, QByteArray> usedBlobs;
52 for (
auto *elm : m_scene->selectedElements()) {
53 if (elm->isEmbedded() && !elm->blobName().isEmpty()) {
54 const QString &name = elm->blobName();
55 if (!usedBlobs.contains(name) && registry->hasBlob(name)) {
56 usedBlobs[name] = registry->blob(name);
60 if (!usedBlobs.isEmpty()) {
63 QDataStream regStream(®Bytes, QIODevice::WriteOnly);
64 regStream << usedBlobs;
68 QByteArray regBytesV2;
69 QDataStream regStreamV2(®BytesV2, QIODevice::WriteOnly);
70 regStreamV2.setVersion(QDataStream::Qt_5_12);
71 regStreamV2 << usedBlobs;
75 QApplication::clipboard()->setMimeData(mimeData.release());
80 if (m_scene->selectedElements().isEmpty()) {
81 QApplication::clipboard()->clear();
86 auto *registry = m_scene->icRegistry();
87 QMap<QString, QByteArray> usedBlobs;
88 for (
auto *elm : m_scene->selectedElements()) {
89 if (elm->isEmbedded() && !elm->blobName().isEmpty()) {
90 const QString &name = elm->blobName();
91 if (!usedBlobs.contains(name) && registry->hasBlob(name)) {
92 usedBlobs[name] = registry->blob(name);
98 QDataStream stream(&itemData, QIODevice::WriteOnly);
100 serializeAndDelete(m_scene->selectedItems(), stream);
102 auto mimeData = std::make_unique<QMimeData>();
105 if (!usedBlobs.isEmpty()) {
108 QDataStream regStream(®Bytes, QIODevice::WriteOnly);
109 regStream << usedBlobs;
113 QByteArray regBytesV2;
114 QDataStream regStreamV2(®BytesV2, QIODevice::WriteOnly);
115 regStreamV2.setVersion(QDataStream::Qt_5_12);
116 regStreamV2 << usedBlobs;
120 QApplication::clipboard()->setMimeData(mimeData.release());
125 const auto *mimeData = QApplication::clipboard()->mimeData();
134 QMap<QString, QByteArray> clipboardBlobs;
137 QDataStream regStream(®Bytes, QIODevice::ReadOnly);
138 regStream.setVersion(QDataStream::Qt_5_12);
142 QDataStream regStream(®Bytes, QIODevice::ReadOnly);
158 const bool needsMacro = !clipboardBlobs.isEmpty() && !itemData.isEmpty();
160 m_scene->undoStack()->beginMacro(tr(
"Paste"));
163 if (!clipboardBlobs.isEmpty()) {
164 auto *registry = m_scene->icRegistry();
165 for (
auto it = clipboardBlobs.cbegin(); it != clipboardBlobs.cend(); ++it) {
166 if (!registry->hasBlob(it.key())) {
172 if (!itemData.isEmpty()) {
173 QDataStream stream(&itemData, QIODevice::ReadOnly);
175 deserializeAndAdd(stream, version);
179 m_scene->undoStack()->endMacro();
193 QSize mappedSize = viewTransform.mapRect(sourceRect).size().toSize();
204 QImage image(mappedSize, QImage::Format_ARGB32_Premultiplied);
205 image.fill(Qt::transparent);
207 QPainter painter(&image);
209 painter.setOpacity(0.0);
210 scene->render(&painter, QRectF(QPointF(), mappedSize), sourceRect);
218 auto *view = m_scene->
view();
220 qCDebug(zero) <<
"Ctrl + Drag action triggered.";
221 const auto selectedElements = m_scene->selectedElements();
223 if (selectedElements.isEmpty()) {
230 const auto items = m_scene->items();
232 for (
auto *item : items) {
240 for (
auto *element : selectedElements) {
241 rect = rect.united(element->sceneBoundingRect());
245 rect = rect.adjusted(-8, -8, 8, 8);
247 const QImage image =
buildDragImage(m_scene, view->transform(), rect);
250 for (
auto *item : items) {
258 QDataStream stream(&itemData, QIODevice::WriteOnly);
262 serializeItems(m_scene->selectedItems(), stream);
264 auto mimeData = std::make_unique<QMimeData>();
267 auto *drag =
new QDrag(m_scene);
268 drag->setMimeData(mimeData.release());
269 drag->setPixmap(QPixmap::fromImage(image));
271 QPointF offset = view->transform().map(mousePos - rect.topLeft());
272 drag->setHotSpot(offset.toPoint());
274 drag->exec(Qt::CopyAction, Qt::CopyAction);
279void ClipboardManager::serializeItems(
const QList<QGraphicsItem *> &items, QDataStream &stream)
283 QPointF center(0.0, 0.0);
284 int itemsQuantity = 0;
286 for (
auto *item : items) {
288 center += item->pos();
293 stream << center /
static_cast<qreal
>(itemsQuantity);
297void ClipboardManager::serializeAndDelete(
const QList<QGraphicsItem *> &items, QDataStream &stream)
299 serializeItems(items, stream);
300 m_scene->deleteAction();
303QList<QGraphicsItem *> ClipboardManager::deserializeAndAdd(QDataStream &stream,
const QVersionNumber &version,
304 std::optional<QPointF> fixedOffset)
306 m_scene->clearSelection();
308 QPointF center; stream >> center;
310 QHash<quint64, Port *> portMap;
316 const QPointF offset = fixedOffset ? *fixedOffset
317 : (m_scene->mousePos() - center - QPointF(32.0, 32.0));
319 m_scene->receiveCommand(
new AddItemsCommand(itemList, m_scene));
321 for (
auto *item : itemList) {
323 item->setPos((item->pos() + offset));
327 m_scene->resizeScene();
333 if (m_scene->selectedElements().empty()) {
339 QDataStream writeStream(&itemData, QIODevice::WriteOnly);
341 serializeItems(m_scene->selectedItems(), writeStream);
345 QDataStream readStream(&itemData, QIODevice::ReadOnly);
348 const auto added = deserializeAndAdd(readStream, version, step);
351 for (
auto *item : added) {
352 item->setSelected(
true);
ClipboardManager: handles copy, cut, paste and clone-drag operations.
All QUndoCommand subclasses and the CommandUtils helper namespace.
Common logging utilities, the Pandaception error type, and helper macros.
#define qCDebug(category)
Connection: a wire that connects an output port to an input port in the circuit scene.
Shared numeric constants used across layers.
Abstract base class for all graphical circuit elements.
Extended QGraphicsView with zoom, pan, and fast-rendering modes.
MIME type string constants for drag-and-drop operations.
Main circuit editing scene with undo/redo and user interaction.
Lightweight Sentry helpers gated behind HAVE_SENTRY.
void sentryBreadcrumb(const char *category, const QString &message)
Deserialization/serialization context structs passed through load()/save() call chains.
Circuit and waveform file serialization/deserialization utilities.
RAII guard that temporarily stops the simulation while in scope.
void paste()
Pastes items from the system clipboard into the scene.
static QImage buildDragImage(Scene *scene, const QTransform &viewTransform, const QRectF &sourceRect)
Renders sourceRect of scene, mapped through viewTransform, into a transparent-filled QImage bounded b...
void cut()
Cuts the currently selected items (copy + delete).
ClipboardManager(Scene *scene)
void cloneDrag(const QPointF &mousePos)
Initiates a clone-drag (Ctrl+drag) of the current selection.
static bool canPaste(const QMimeData *mimeData)
Returns whether mimeData carries circuit data paste() accepts.
void copy()
Copies the currently selected items to the system clipboard.
static constexpr int kMaxDragImageDimension
Undo command that registers/unregisters a blob in the IC registry.
Main circuit editing scene.
GraphicsView * view() const
Returns the GraphicsView currently displaying this scene.
static QList< QGraphicsItem * > deserialize(QDataStream &stream, SerializationContext &context)
Deserializes items from stream until the stream is exhausted.
static void serialize(const QList< QGraphicsItem * > &items, QDataStream &stream, SerializationOptions options)
Serializes items to stream in the current .panda binary format.
static QMap< QString, QByteArray > readBoundedBlobMap(QDataStream &stream)
Reads a QMap<QString,QByteArray> from stream with bounds checking.
static void writePandaHeader(QDataStream &stream)
Writes the .panda circuit file header to stream.
static QVersionNumber readPandaHeader(QDataStream &stream)
Reads and validates the .panda circuit file header; returns the stored version number.
RAII guard that stops the simulation on construction and restarts it on destruction.
constexpr int gridSize
Scene grid unit in pixels (elements snap to gridSize/2).
constexpr const char * CloneDrag
Current MIME type for clone-drag (Ctrl+drag within the scene).
constexpr const char * ClipboardLegacy
Legacy clipboard MIME type retained for backward compatibility.
constexpr const char * BlobRegistry
constexpr const char * BlobRegistryV2
constexpr const char * Clipboard
Current MIME type for clipboard copy/paste data.