wiRedPanda
Logic Circuit Simulator
Loading...
Searching...
No Matches
ElementLabel.cpp
Go to the documentation of this file.
1// Copyright 2015 - 2026, GIBIS-UNIFESP and the wiRedPanda contributors
2// SPDX-License-Identifier: GPL-3.0-or-later
3
5
6#include <QApplication>
7#include <QDrag>
8#include <QFileInfo>
9#include <QHBoxLayout>
10#include <QMimeData>
11#include <QMouseEvent>
12
13#include "App/Core/MimeTypes.h"
16
17ElementLabel::ElementLabel(const QPixmap &pixmap, ElementType type, const QString &icFileName, QWidget *parent, bool isEmbedded)
18 : QFrame(parent)
19 , m_elementType(type)
20 , m_pixmap(pixmap)
21 , m_icFileName(icFileName)
22 , m_isEmbedded(isEmbedded)
23{
24 m_iconLabel.setPixmap(pixmap);
25 m_iconLabel.setScaledContents(true);
26 m_iconLabel.setFixedSize(64, 64);
27
28 if (m_isEmbedded) {
29 m_nameLabel.setText(icFileName.toUpper());
30 } else if (type == ElementType::IC) {
31 m_nameLabel.setText(QFileInfo(icFileName).baseName().toUpper());
32 } else {
33 m_nameLabel.setText(ElementFactory::translatedName(type));
34 }
35
36 // Describe what the item is and how to place it. Set on the frame and both child labels
37 // so the tooltip appears wherever the pointer rests on the item.
38 QString tip;
39 if (m_isEmbedded) {
40 tip = tr("Embedded IC: %1").arg(icFileName);
41 } else if (type == ElementType::IC) {
42 tip = tr("IC from file: %1").arg(QFileInfo(icFileName).fileName());
43 } else {
45 }
46 const QString addHint = tr("Drag or double-click to add.");
47 tip = tip.isEmpty() ? addHint : tip + QLatin1Char('\n') + addHint;
48 setToolTip(tip);
49 m_iconLabel.setToolTip(tip);
50 m_nameLabel.setToolTip(tip);
51
52 auto *itemLayout = new QHBoxLayout();
53 itemLayout->setSpacing(6);
54 itemLayout->setObjectName(QStringLiteral("itemLayout"));
55
56 setLayout(itemLayout);
57
58 itemLayout->addWidget(&m_iconLabel);
59 itemLayout->addStretch();
60 itemLayout->addWidget(&m_nameLabel);
61 itemLayout->addStretch();
62 itemLayout->setContentsMargins(0, 0, 0, 0);
63}
64
66{
67 if (m_elementType != ElementType::IC) {
68 m_nameLabel.setText(ElementFactory::translatedName(m_elementType));
69 }
70}
71
72void ElementLabel::mousePressEvent(QMouseEvent *event)
73{
74 // Only remember where the press started. Deferring the drag until the pointer
75 // actually moves leaves the press/release free for double-click detection, which a
76 // blocking drag->exec() on press would otherwise swallow.
77 if (event->button() == Qt::LeftButton) {
78 m_dragStartPos = event->pos();
79 }
80}
81
82void ElementLabel::mouseMoveEvent(QMouseEvent *event)
83{
84 // Empirically confirmed unreachable: this widget never calls setMouseTracking(true), and
85 // QApplication's own event delivery (even via a directly-constructed/injected QMouseEvent,
86 // not just real input) filters out MouseMove events entirely before dispatch when no button
87 // is held and tracking is off -- mouseMoveEvent() itself is simply never invoked in that case,
88 // so event->buttons() is guaranteed non-empty (Qt::LeftButton, the only button this label
89 // reacts to at all) whenever this line runs. Kept as a defensive guard in case that ever changes.
90 if (!(event->buttons() & Qt::LeftButton)) { // LCOV_EXCL_LINE
91 return; // LCOV_EXCL_LINE
92 }
93 if ((event->pos() - m_dragStartPos).manhattanLength() < QApplication::startDragDistance()) {
94 return;
95 }
96 startDrag();
97}
98
100{
101 Q_UNUSED(event)
102 // Drag-free shortcut: add this element straight to the active scene. mimeData()
103 // hands off a freshly-allocated payload the scene takes ownership of.
105}
106
108{
109 return m_elementType;
110}
111
112const QPixmap &ElementLabel::pixmap() const
113{
114 return m_pixmap;
115}
116
117QString ElementLabel::name() const
118{
119 return m_nameLabel.text();
120}
121
123{
124 return m_icFileName;
125}
126
128{
129 return m_isEmbedded;
130}
131
133{
134 // The hot spot is the icon's centre so the element appears centred under
135 // the cursor when dropped onto the scene.
136 QPoint offset = m_iconLabel.pixmap(Qt::ReturnByValue).rect().center();
137
138 auto *drag = new QDrag(parent());
139 drag->setMimeData(mimeData());
140 drag->setPixmap(pixmap());
141 drag->setHotSpot(offset);
142 // CopyAction for both proposed and allowed: placing an element on the scene
143 // always creates a new instance, never moves the palette entry.
144 drag->exec(Qt::CopyAction, Qt::CopyAction);
145}
146
147QMimeData *ElementLabel::mimeData() const
148{
149 QPoint offset = m_iconLabel.pixmap(Qt::ReturnByValue).rect().center();
150 QByteArray itemData;
151 QDataStream stream(&itemData, QIODevice::WriteOnly);
153 stream << offset << m_elementType << m_icFileName << m_isEmbedded << (m_isEmbedded ? m_icFileName : QString());
154
155 auto *mimeData = new QMimeData();
156 mimeData->setData(MimeType::DragDrop, itemData);
157
158 return mimeData;
159}
160
162{
163 m_pixmap = ElementFactory::pixmap(m_elementType);
164 m_iconLabel.setPixmap(m_pixmap);
165}
Singleton factory for all circuit element types.
Draggable element icon+label widget used in the element palette.
Enums::ElementType ElementType
Definition Enums.h:107
MIME type string constants for drag-and-drop operations.
Circuit and waveform file serialization/deserialization utilities.
static QString translatedName(const ElementType type)
Returns the translated human-readable name for type.
static QPixmap pixmap(const ElementType type)
Returns the pixmap icon for the given element type.
static QString description(const ElementType type)
void startDrag()
Initiates a drag operation carrying this label's element type.
void mouseMoveEvent(QMouseEvent *event) override
Starts the drag once the pointer moves past the platform drag threshold.
void addToSceneRequested(QMimeData *mimeData)
QString name() const
Returns the displayed element name.
bool isEmbedded() const
Returns true if this label represents an embedded IC.
void mousePressEvent(QMouseEvent *event) override
const QPixmap & pixmap() const
Returns the icon pixmap shown in this label.
void updateName()
Updates the displayed name to match the current application locale.
QMimeData * mimeData() const
Creates and returns the MIME data payload used for drag-and-drop.
QString icFileName() const
Returns the IC file path, or an empty string for built-in elements.
void mouseDoubleClickEvent(QMouseEvent *event) override
Requests adding this element to the active scene (drag-free shortcut).
void updateTheme()
Updates colors to match the current application theme.
const ElementType & elementType() const
Returns the element type identifier for this label.
ElementLabel(const QPixmap &pixmap, ElementType type, const QString &icFileName, QWidget *parent=nullptr, bool isEmbedded=false)
Constructs an ElementLabel from a pixmap.
static void writePandaHeader(QDataStream &stream)
Writes the .panda circuit file header to stream.
constexpr const char * DragDrop
Current drag-and-drop MIME type for element palette → scene drops.
Definition MimeTypes.h:13