20void PropertyShortcutHandler::applyWithUndo(
GraphicElement *element,
const std::function<
void()> &mutate)
27 QDataStream stream(&oldData, QIODevice::WriteOnly);
32 m_scene->receiveCommand(
new UpdateCommand({element}, oldData, m_scene));
35void PropertyShortcutHandler::adjustMainProperty(
int dir)
41 const auto selected = m_scene->selectedElements();
42 const bool needsMacro = selected.size() > 1;
44 m_scene->undoStack()->beginMacro(tr(
"Cycle element properties"));
47 for (
auto *element : selected) {
50 case ElementType::And:
52 case ElementType::Nand:
53 case ElementType::Nor:
54 case ElementType::Xor:
55 case ElementType::Xnor:
57 case ElementType::Led:
58 case ElementType::TruthTable: {
59 const int newSize = element->
inputSize() + dir;
60 if (newSize >= element->
minInputSize() && newSize <= element->maxInputSize())
61 m_scene->receiveCommand(
new ChangePortSizeCommand(QList<GraphicElement *>{element},
62 newSize, m_scene,
true));
66 case ElementType::InputRotary: {
67 const int newSize = element->
outputSize() + dir;
68 if (newSize >= element->
minOutputSize() && newSize <= element->maxOutputSize())
69 m_scene->receiveCommand(
new ChangePortSizeCommand(QList<GraphicElement *>{element},
70 newSize, m_scene,
false));
73 case ElementType::Clock:
78 case ElementType::Buzzer:
80 applyWithUndo(element, [element, dir] { element->
setFrequency(std::clamp(element->
frequency() + dir * 100.0, 20.0, 20000.0)); });
83 case ElementType::Display16:
85 if (dir < 0 && element->hasColors())
89 case ElementType::Display14:
90 case ElementType::Display7:
92 applyWithUndo(element, [element, dir] { element->
setColor(dir < 0 ? element->previousColor() : element->
nextColor()); });
96 case ElementType::AudioBox:
97 case ElementType::DFlipFlop:
98 case ElementType::DLatch:
99 case ElementType::Demux:
100 case ElementType::IC:
101 case ElementType::InputButton:
102 case ElementType::InputGnd:
103 case ElementType::InputSwitch:
104 case ElementType::InputVcc:
105 case ElementType::JKFlipFlop:
106 case ElementType::JKLatch:
107 case ElementType::Line:
108 case ElementType::Mux:
109 case ElementType::Node:
110 case ElementType::Not:
111 case ElementType::SRFlipFlop:
112 case ElementType::SRLatch:
113 case ElementType::TFlipFlop:
114 case ElementType::Text:
115 case ElementType::Unknown:
120 element->setSelected(
false);
121 element->setSelected(
true);
125 m_scene->undoStack()->endMacro();
131 adjustMainProperty(-1);
136 adjustMainProperty(1);
139void PropertyShortcutHandler::adjustSecondaryProperty(
int dir)
143 const bool needsMacro = selected.size() > 1;
145 m_scene->
undoStack()->beginMacro(tr(
"Cycle element properties"));
148 for (
auto *element : selected) {
150 case ElementType::TruthTable: {
151 const int newSize = element->
outputSize() + dir;
152 if (newSize >= element->
minOutputSize() && newSize <= element->maxOutputSize())
153 m_scene->receiveCommand(
new ChangePortSizeCommand(QList<GraphicElement *>{element},
154 newSize, m_scene,
false));
157 case ElementType::Led:
159 applyWithUndo(element, [element, dir] { element->
setColor(dir < 0 ? element->previousColor() : element->
nextColor()); });
162 case ElementType::And:
163 case ElementType::AudioBox:
164 case ElementType::Buzzer:
165 case ElementType::Clock:
166 case ElementType::DFlipFlop:
167 case ElementType::DLatch:
168 case ElementType::Demux:
169 case ElementType::Display14:
170 case ElementType::Display16:
171 case ElementType::Display7:
172 case ElementType::IC:
173 case ElementType::InputButton:
174 case ElementType::InputGnd:
175 case ElementType::InputRotary:
176 case ElementType::InputSwitch:
177 case ElementType::InputVcc:
178 case ElementType::JKFlipFlop:
179 case ElementType::JKLatch:
180 case ElementType::Line:
181 case ElementType::Mux:
182 case ElementType::Nand:
183 case ElementType::Node:
184 case ElementType::Nor:
185 case ElementType::Not:
186 case ElementType::Or:
187 case ElementType::SRFlipFlop:
188 case ElementType::SRLatch:
189 case ElementType::TFlipFlop:
190 case ElementType::Text:
191 case ElementType::Unknown:
192 case ElementType::Xnor:
193 case ElementType::Xor:
197 element->setSelected(
false);
198 element->setSelected(
true);
202 m_scene->undoStack()->endMacro();
208 adjustSecondaryProperty(-1);
213 adjustSecondaryProperty(1);
218 const auto selected = m_scene->selectedElements();
219 const bool needsMacro = selected.size() > 1;
221 m_scene->undoStack()->beginMacro(tr(
"Morph elements"));
224 for (
auto *element : selected) {
225 const QPointF elmPosition = element->scenePos();
229 if (nextType == ElementType::Unknown) {
continue; }
231 m_scene->receiveCommand(
new MorphCommand(QList<GraphicElement *>{element},
236 auto *item = m_scene->itemAt(elmPosition);
238 item->setSelected(
true);
243 m_scene->undoStack()->endMacro();
249 const auto selected = m_scene->selectedElements();
250 const bool needsMacro = selected.size() > 1;
252 m_scene->undoStack()->beginMacro(tr(
"Morph elements"));
255 for (
auto *element : selected) {
256 const QPointF elmPosition = element->scenePos();
259 if (prevType == ElementType::Unknown) {
continue; }
261 m_scene->receiveCommand(
new MorphCommand(QList<GraphicElement *>{element},
264 auto *item = m_scene->itemAt(elmPosition);
266 item->setSelected(
true);
271 m_scene->undoStack()->endMacro();
All QUndoCommand subclasses and the CommandUtils helper namespace.
Central enumeration types for element types, groups, and signal status.
Abstract base class for all graphical circuit elements.
PropertyShortcutHandler: dispatches keyboard shortcuts that cycle element properties.
Main circuit editing scene with undo/redo and user interaction.
Deserialization/serialization context structs passed through load()/save() call chains.
Circuit and waveform file serialization/deserialization utilities.
static ElementType nextElmType(ElementType type)
Returns the ElementType that follows type in the defined sequence.
static ElementType prevElmType(ElementType type)
Returns the ElementType that precedes type in the defined sequence.
Abstract base class for all graphical circuit elements in wiRedPanda.
virtual void setFrequency(const double freq)
Sets the clock frequency to freq (overridden by clock elements).
ElementType elementType() const
Returns the type identifier for this element.
virtual void setColor(const QString &color)
Sets the element color to color and refreshes the pixmap.
int inputSize() const
Returns the current number of input ports.
int minInputSize() const
Returns the minimum allowed number of input ports.
virtual double frequency() const
Returns the clock frequency in Hz (overridden by Clock; returns 0 for other elements).
int outputSize() const
Returns the current number of output ports.
bool hasFrequency() const
Returns true if this element type exposes a configurable clock frequency.
QString nextColor() const
Returns the name of the next color in the element's color list.
bool hasColors() const
Returns true if this element type supports color selection.
virtual void save(QDataStream &stream, SerializationOptions options) const
int minOutputSize() const
Returns the minimum allowed number of output ports.
QString previousColor() const
Returns the name of the previous color in the element's color list.
Undo command that changes the type of selected elements while preserving connections.
void prevElement()
Morphs each selected element to the previous type in the cycle.
void nextMainProperty()
Increments the primary property of each selected element.
void prevMainProperty()
Decrements the primary property of each selected element.
void nextElement()
Morphs each selected element to the next type in the cycle.
void nextSecondaryProperty()
Increments the secondary property of each selected element.
void prevSecondaryProperty()
Decrements the secondary property of each selected element.
PropertyShortcutHandler(Scene *scene)
Main circuit editing scene.
const QList< GraphicElement * > selectedElements() const
Returns the list of currently selected graphic elements.
QUndoStack * undoStack()
Returns the scene's undo stack.
static void writePandaHeader(QDataStream &stream)
Writes the .panda circuit file header to stream.