30 , m_previewPopup(previewPopup)
35 m_prevMainPropShortcut =
new QShortcut(QKeySequence(
"["), shortcutParent);
36 m_nextMainPropShortcut =
new QShortcut(QKeySequence(
"]"), shortcutParent);
37 m_prevSecndPropShortcut =
new QShortcut(QKeySequence(
"{"), shortcutParent);
38 m_nextSecndPropShortcut =
new QShortcut(QKeySequence(
"}"), shortcutParent);
39 m_changePrevElmShortcut =
new QShortcut(QKeySequence(
"<"), shortcutParent);
40 m_changeNextElmShortcut =
new QShortcut(QKeySequence(
">"), shortcutParent);
44 m_statusInfo =
new QLabel;
45 m_statusInfo->setObjectName(
"statusInfoLabel");
46 m_ui->statusBar->addPermanentWidget(m_statusInfo);
49void SceneUiBinder::updateStatusInfo()
51 if (!m_bound || !m_bound->
scene() || !m_bound->
view()) {
52 m_statusInfo->clear();
56 auto *scene = m_bound->scene();
57 const int zoomPct = qRound(m_bound->view()->transform().m11() * 100.0);
58 const int selected =
static_cast<int>(scene->selectedElements().size());
59 const int total =
static_cast<int>(scene->elements().size());
60 m_statusInfo->setText(tr(
"Zoom: %1% Selected: %2 / %3").arg(zoomPct).arg(selected).arg(total));
63void SceneUiBinder::addUndoRedoMenu()
69 auto *scene = m_bound->scene();
74 const auto actions = m_ui->menuEdit->actions();
75 if (actions.size() < 2) {
81 m_ui->menuEdit->insertAction(actions.at(0), scene->undoAction());
82 m_ui->menuEdit->insertAction(m_ui->menuEdit->actions().at(1), scene->redoAction());
86 m_ui->mainToolBar->insertAction(m_ui->actionRotateLeft, scene->undoAction());
87 m_ui->mainToolBar->insertAction(m_ui->actionRotateLeft, scene->redoAction());
90void SceneUiBinder::removeUndoRedoMenu()
98 const auto actions = m_ui->menuEdit->actions();
99 if (actions.size() < 2) {
102 m_ui->menuEdit->removeAction(actions.at(0));
103 m_ui->menuEdit->removeAction(actions.at(1));
106 if (
auto *scene = m_bound->scene()) {
107 m_ui->mainToolBar->removeAction(scene->undoAction());
108 m_ui->mainToolBar->removeAction(scene->redoAction());
112void SceneUiBinder::syncZoomActions()
118 m_ui->actionZoomIn->setEnabled(m_bound->view()->canZoomIn());
119 m_ui->actionZoomOut->setEnabled(m_bound->view()->canZoomOut());
125 auto *scene = tab->
scene();
127 qCDebug(zero) <<
"Connecting undo and redo functions to UI menu.";
130 m_palette->updateEmbeddedICList(scene);
132 qCDebug(zero) <<
"Connecting current tab to element editor menu in UI.";
133 m_ui->elementEditor->setScene(scene);
137 connect(scene, &QGraphicsScene::selectionChanged,
this, &SceneUiBinder::updateStatusInfo);
140 m_ui->statusBar->showMessage(msg, 8000);
143 m_ui->statusBar->showMessage(msg, 5000);
145 connect(scene->undoStack(), &QUndoStack::indexChanged,
this, [
this] {
147 m_palette->updateEmbeddedICList(m_bound->scene());
155 connect(m_changePrevElmShortcut, &QShortcut::activated, scene, &
Scene::prevElm);
156 connect(m_changeNextElmShortcut, &QShortcut::activated, scene, &
Scene::nextElm);
158 m_ui->elementEditor->truthTable();
160 connect(scene, &
Scene::icOpenRequested,
this, [
this](
int elementId,
const QString &blobName,
const QString &filePath) {
161 if (!blobName.isEmpty()) {
163 emit openICRequested(blobName, elementId, m_bound->scene()->icRegistry()->blob(blobName));
165 }
else if (!filePath.isEmpty()) {
166 emit loadFileRequested(filePath);
170 emit loadFileRequested(filePath);
173 m_previewPopup->showForIC(ic, screenPos);
178 if (m_previewPopup->isShowActiveFor(ic)) {
179 m_previewPopup->updatePendingPos(screenPos);
181 m_previewPopup->showForIC(ic, screenPos);
185 m_previewPopup->scheduleHide();
194 m_previewPopup->cancelHide();
195 m_previewPopup->hide();
198 if (m_ui->actionPlay->isChecked()) {
199 qCDebug(zero) <<
"Restarting simulation.";
200 tab->simulation()->start();
203 scene->clearSelection();
206 tab->view()->setFastMode(m_ui->actionFastMode->isChecked());
208 m_ui->actionZoomIn->setEnabled(tab->view()->canZoomIn());
209 m_ui->actionZoomOut->setEnabled(tab->view()->canZoomOut());
212 const bool muted = tab->simulation()->isUserMuted();
213 m_ui->actionMute->setChecked(muted);
214 m_ui->actionMute->setText(muted ? tr(
"Unmute") : tr(
"Mute"));
227 auto *scene = m_bound->scene();
229 m_ui->elementEditor->setScene(
nullptr);
231 qCDebug(zero) <<
"Stopping simulation.";
232 m_bound->simulation()->stop();
234 qCDebug(zero) <<
"Disconnecting zoom and simulation signals from UI.";
237 disconnect(scene, &QGraphicsScene::selectionChanged,
this, &SceneUiBinder::updateStatusInfo);
242 qCDebug(zero) <<
"Disconnecting scene shortcuts from previous tab.";
243 disconnect(m_prevMainPropShortcut,
nullptr, scene,
nullptr);
244 disconnect(m_nextMainPropShortcut,
nullptr, scene,
nullptr);
245 disconnect(m_prevSecndPropShortcut,
nullptr, scene,
nullptr);
246 disconnect(m_nextSecndPropShortcut,
nullptr, scene,
nullptr);
247 disconnect(m_changePrevElmShortcut,
nullptr, scene,
nullptr);
248 disconnect(m_changeNextElmShortcut,
nullptr, scene,
nullptr);
255 disconnect(scene->undoStack(), &QUndoStack::indexChanged,
this,
nullptr);
257 qCDebug(zero) <<
"Removing undo and redo actions from UI menu.";
258 removeUndoRedoMenu();
261 m_statusInfo->clear();
Common logging utilities, the Pandaception error type, and helper macros.
#define qCDebug(category)
ElementEditor widget for inspecting and modifying selected circuit element properties.
ElementPalette: manages the left-panel element palette and search UI.
Extended QGraphicsView with zoom, pan, and fast-rendering modes.
IC definition registry with file watching and embedded blob storage.
Integrated Circuit (IC) graphic element that encapsulates a sub-circuit file.
MainWindowUi: hand-written UI class for the MainWindow.
SceneUiBinder: wires the active tab's scene into the shared editor chrome.
Main circuit editing scene with undo/redo and user interaction.
Synchronous cycle-based simulation engine with event-driven clock support.
WorkSpace widget: the complete circuit editing environment for one tab.
Controller for the left-panel element palette, IC list, and search tab.
void zoomChanged()
Emitted whenever the zoom level changes.
Graphic element representing an Integrated Circuit (sub-circuit) box.
SceneUiBinder(MainWindowUi *ui, ElementPalette *palette, ICPreviewPopup *previewPopup, QWidget *shortcutParent, QObject *parent=nullptr)
void bind(WorkSpace *tab)
Connects tab's scene/view/simulation to the chrome and syncs action state.
void unbind()
Tears down the connections established by bind() for the currently bound tab.
void icPreviewRequested(IC *ic, const QPoint &screenPos)
void fileDropRequested(const QString &filePath)
Emitted when a .panda file is dropped onto the canvas from the file manager.
void nextSecndPropShortcut()
Advances the secondary property of selected elements to the next value.
void showStatusMessageRequested(const QString &message)
void prevElm()
Cycles selection backward to the previous element.
void icOpenRequested(int elementId, const QString &blobName, const QString &filePath)
Emitted when an IC element is double-clicked to request opening its sub-circuit.
void icPreviewMoved(IC *ic, const QPoint &screenPos)
void icPreviewCancelRequested(IC *ic)
void prevMainPropShortcut()
Retreats the main property of selected elements to the previous value.
void prevSecndPropShortcut()
Retreats the secondary property of selected elements to the previous value.
void nextMainPropShortcut()
Advances the main property of selected elements to the next value.
void nextElm()
Cycles selection forward to the next element.
void icPreviewHideRequested()
void circuitHasChanged()
Emitted whenever the circuit changes (element added/removed/moved).
void openTruthTableRequested()
Emitted when a TruthTable element is double-clicked to request opening its editor.
void simulationWarning(const QString &message)
Emitted (at most once per initialize()) when a feedback circuit fails to converge.
A widget containing a complete circuit editing environment.
Scene * scene()
Returns the Scene embedded in this workspace.
Simulation * simulation()
Returns the embedded Simulation.
GraphicsView * view()
Returns the GraphicsView embedded in this workspace.