wiRedPanda
Logic Circuit Simulator
Loading...
Searching...
No Matches
ExportController.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 <QDesktopServices>
7#include <QDir>
8#include <QLoggingCategory>
9#include <QUrl>
10
15#include "App/Core/Common.h"
17#include "App/Scene/Scene.h"
18#include "App/Scene/Workspace.h"
23
25 : QObject(parent)
26 , m_host(host)
27{
28}
29
31{
32 auto *tab = m_host.currentTab();
33 if (!tab) {
34 return;
35 }
36
37 if (fileName.isEmpty()) {
38 throw PANDACEPTION("Missing file name.");
39 }
40
41 auto elements = tab->scene()->elements();
42
43 if (elements.isEmpty()) {
44 throw PANDACEPTION("The .panda file is empty.");
45 }
46
47 // Pause the simulation while generating code to avoid data races between
48 // the simulation timer and the code generator reading element state.
49 SimulationBlocker simulationBlocker(tab->simulation());
50
51 if (!fileName.endsWith(".ino")) {
52 fileName.append(".ino");
53 }
54
55 ArduinoCodeGen arduino(QDir::home().absoluteFilePath(fileName), elements);
56 arduino.generate();
57 m_host.showStatusMessage(tr("Arduino code successfully generated."), 4000);
58
59 qCDebug(zero) << "Arduino code successfully generated.";
60}
61
63{
64 auto *tab = m_host.currentTab();
65 if (!tab) {
66 return;
67 }
68
69 if (fileName.isEmpty()) {
70 throw PANDACEPTION("Missing file name.");
71 }
72
73 auto elements = tab->scene()->elements();
74
75 if (elements.isEmpty()) {
76 throw PANDACEPTION("The .panda file is empty.");
77 }
78
79 SimulationBlocker simulationBlocker(tab->simulation());
80
81 if (!fileName.endsWith(".sv")) {
82 fileName.append(".sv");
83 }
84
85 SystemVerilogCodeGen verilog(QDir::home().absoluteFilePath(fileName), elements);
86 verilog.generate();
87 m_host.showStatusMessage(tr("SystemVerilog code successfully generated."), 4000);
88
89 qCDebug(zero) << "SystemVerilog code successfully generated.";
90}
91
92void ExportController::exportToWaveFormFile(const QString &fileName)
93{
94 if (fileName.isEmpty()) {
95 throw PANDACEPTION("Missing file name.");
96 }
97
98 // Headless export: a stack instance is never shown/closed, so it cleans up at scope end
99 // (its WA_DeleteOnClose only fires on a close event) — and RAII-frees even if this throws.
100 BewavedDolphin bewavedDolphin(m_host.currentTab()->scene(), false, m_host.dolphinHost());
101 bewavedDolphin.createWaveform(fileName);
102 bewavedDolphin.print();
103}
104
106{
107 BewavedDolphin bewavedDolphin(m_host.currentTab()->scene(), false, m_host.dolphinHost());
108 bewavedDolphin.createWaveform();
109 bewavedDolphin.print();
110}
111
113{
114 Application::guardedSlot(this, [this] {
115 sentryBreadcrumb("export", QStringLiteral("Export to Arduino"));
116 if (!m_host.currentTab()) {
117 return;
118 }
119
120 QString path;
121
122 if (m_host.currentFile().exists()) {
123 path = m_host.currentFile().absolutePath();
124 }
125
126 const QString fileName = FileDialogs::provider()->getSaveFileName(m_host.widget(), tr("Generate Arduino Code"), path, tr("Arduino file") + " (*.ino)").fileName;
127
128 if (!fileName.isEmpty()) {
129 exportToArduino(fileName);
130 }
131 });
132}
133
135{
136 Application::guardedSlot(this, [this] {
137 sentryBreadcrumb("export", QStringLiteral("Export to SystemVerilog"));
138 if (!m_host.currentTab()) {
139 return;
140 }
141
142 QString path;
143
144 if (m_host.currentFile().exists()) {
145 path = m_host.currentFile().absolutePath();
146 }
147
148 const QString fileName = FileDialogs::provider()->getSaveFileName(m_host.widget(), tr("Generate SystemVerilog Code"), path, tr("SystemVerilog file") + " (*.sv)").fileName;
149
150 if (!fileName.isEmpty()) {
151 exportToSystemVerilog(fileName);
152 }
153 });
154}
155
157{
158 Application::guardedSlot(this, [this] {
159 sentryBreadcrumb("export", QStringLiteral("Export to PDF"));
160 auto *tab = m_host.currentTab();
161 if (!tab) {
162 return;
163 }
164
165 // De-select elements so their selection handles don't appear in the export.
166 tab->scene()->clearSelection();
167
168 const QString path = m_host.currentFile().exists() ? m_host.currentFile().absolutePath() : QString();
169 QString pdfFile = FileDialogs::provider()->getSaveFileName(m_host.widget(), tr("Export to PDF"), path, tr("PDF files") + " (*.pdf)").fileName;
170
171 if (pdfFile.isEmpty()) {
172 return;
173 }
174
175 if (!pdfFile.endsWith(".pdf", Qt::CaseInsensitive)) {
176 pdfFile.append(".pdf");
177 }
178
179 CircuitExporter::renderToPdf(tab->scene(), pdfFile);
180 m_host.showStatusMessage(tr("Exported file successfully."), 4000);
181 QDesktopServices::openUrl(QUrl::fromLocalFile(pdfFile));
182 });
183}
184
186{
187 Application::guardedSlot(this, [this] {
188 sentryBreadcrumb("export", QStringLiteral("Export to image"));
189 auto *tab = m_host.currentTab();
190 if (!tab) {
191 return;
192 }
193
194 // De-select elements so their selection handles don't appear in the export.
195 tab->scene()->clearSelection();
196
197 const QString path = m_host.currentFile().exists() ? m_host.currentFile().absolutePath() : QString();
198 QString pngFile = FileDialogs::provider()->getSaveFileName(m_host.widget(), tr("Export to Image"), path, tr("PNG files") + " (*.png)").fileName;
199
200 if (pngFile.isEmpty()) {
201 return;
202 }
203
204 if (!pngFile.endsWith(".png", Qt::CaseInsensitive)) {
205 pngFile.append(".png");
206 }
207
208 CircuitExporter::renderToImage(tab->scene(), pngFile);
209 m_host.showStatusMessage(tr("Exported file successfully."), 4000);
210 QDesktopServices::openUrl(QUrl::fromLocalFile(pngFile));
211 });
212}
Custom QApplication subclass with exception handling and main-window access.
Arduino sketch code generator: translates a circuit into an uploadable .ino file.
BewavedDolphin waveform editor: digital signal creation, display, and export.
CircuitExporter: render a Scene to PDF or PNG image.
Common logging utilities, the Pandaception error type, and helper macros.
#define PANDACEPTION(msg,...)
Definition Common.h:98
#define qCDebug(category)
Definition Common.h:29
ExportController: orchestrates exporting the current circuit to its output formats.
Abstract file dialog interface for testability.
MainWindowHost: the application context that MainWindow's extracted controllers depend on.
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)
RAII guard that temporarily stops the simulation while in scope.
SystemVerilog code generator: translates a circuit into a synthesisable module.
WorkSpace widget: the complete circuit editing environment for one tab.
static void guardedSlot(const QObject *context, Body &&body) noexcept
Wraps a slot body in try/catch and reports any exception synchronously, inside the slot's own stack f...
Generates an Arduino sketch from a flattened list of circuit elements.
void generate()
Generates the Arduino sketch and writes it to the output file.
Waveform editor main window for creating and analyzing digital signal sequences.
void print()
Prints the waveform table to the system printer.
void createWaveform()
Initializes a blank waveform from the current scene's I/O elements.
ExportController(MainWindowHost &host, QObject *parent=nullptr)
void exportToArduino(QString fileName)
Generates an Arduino sketch for the current circuit at fileName.
void exportToWaveFormTerminal()
Prints the beWavedDolphin waveform of the current circuit to the terminal.
void exportToWaveFormFile(const QString &fileName)
Writes the beWavedDolphin waveform of the current circuit to fileName.
void exportToSystemVerilog(QString fileName)
Generates SystemVerilog for the current circuit at fileName.
virtual FileDialogResult getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter)=0
Interface MainWindow provides to its extracted controllers (export, IC, …).
RAII guard that stops the simulation on construction and restarts it on destruction.
Generates a synthesisable SystemVerilog module from a circuit's element graph.
void generate()
Generates the SystemVerilog output file for the circuit.
void renderToImage(Scene *scene, const QString &filePath)
Renders scene to a PNG image file at filePath.
void renderToPdf(Scene *scene, const QString &filePath)
Renders scene to a PDF file at filePath.
FileDialogProvider * provider()
Returns the active provider. Never null.
QString fileName
Selected file path, empty if cancelled.