(value), true);
}
}
run();
}
void BewavedDolphin::load(QFile &file)
{
const QByteArray content = file.readAll();
const auto wordList(content.split(','));
int rows = wordList.at(0).toInt();
const int cols = wordList.at(1).toInt();
if (rows > m_inputPorts) {
rows = m_inputPorts;
}
if ((cols < 2) || (cols > 2048)) {
throw Pandaception(tr("Invalid number of columns."));
}
setLength(cols, false);
qCDebug(zero) << tr("Update table.");
for (int row = 0; row < rows; ++row) {
for (int col = 0; col < cols; ++col) {
int value = wordList.at(2 + col + row * cols).toInt();
createElement(row, col, value, true);
}
}
run();
}
void BewavedDolphin::on_actionShowNumbers_triggered()
{
m_type = PlotType::Number;
for (int row = 0; row < m_model->rowCount(); ++row) {
for (int col = 0; col < m_model->columnCount(); ++col) {
m_model->setData(m_model->index(row, col), QVariant(), Qt::DecorationRole);
}
}
for (int row = 0; row < m_inputPorts; ++row) {
for (int col = 0; col < m_model->columnCount(); ++col) {
createElement(row, col, m_model->index(row, col).data().toInt());
}
}
qCDebug(zero) << tr("Running simulation.");
run();
}
void BewavedDolphin::on_actionShowWaveforms_triggered()
{
m_type = PlotType::Line;
for (int row = 0; row < m_inputPorts; ++row) {
for (int col = 0; col < m_model->columnCount(); ++col) {
createElement(row, col, m_model->index(row, col).data().toInt());
}
}
qCDebug(zero) << tr("Running simulation.");
run();
}
void BewavedDolphin::on_actionExportToPng_triggered()
{
QString pngFile = QFileDialog::getSaveFileName(this, tr("Export to Image"), m_currentFile.absolutePath(), tr("PNG files (*.png)"));
if (pngFile.isEmpty()) {
return;
}
if (!pngFile.endsWith(".png", Qt::CaseInsensitive)) {
pngFile.append(".png");
}
QRectF sceneRect = m_scene->sceneRect();
QPixmap pixmap(sceneRect.size().toSize());
QPainter painter;
painter.begin(&pixmap);
painter.setRenderHint(QPainter::Antialiasing);
m_scene->render(&painter, QRectF(), sceneRect);
painter.end();
pixmap.toImage().save(pngFile);
}
void BewavedDolphin::on_actionExportToPdf_triggered()
{
QString pdfFile = QFileDialog::getSaveFileName(this, tr("Export to PDF"), m_currentFile.absolutePath(), tr("PDF files (*.pdf)"));
if (pdfFile.isEmpty()) {
return;
}
if (!pdfFile.endsWith(".pdf", Qt::CaseInsensitive)) {
pdfFile.append(".pdf");
}
QPrinter printer(QPrinter::HighResolution);
printer.setPageSize(QPageSize(QPageSize::A4));
printer.setPageOrientation(QPageLayout::Orientation::Landscape);
printer.setOutputFormat(QPrinter::PdfFormat);
printer.setOutputFileName(pdfFile);
QPainter painter;
if (!painter.begin(&printer)) {
throw Pandaception(tr("Could not print this circuit to PDF."));
}
m_scene->render(&painter, QRectF(), m_scene->sceneRect().adjusted(-64, -64, 64, 64));
painter.end();
}
void BewavedDolphin::on_actionAbout_triggered()
{
QMessageBox::about(this,
"beWavedDolphin",
tr("beWavedDolphin is a waveform simulator for the WiRedPanda software developed by the Federal University of São Paulo."
" This project was created in order to help students learn about logic circuits.
"
"Software version: %1
"
"Creators:
"
""
"- Prof. Fábio Cappabianco, Ph.D.
"
"
"
" beWavedDolphin is currently maintained by Prof. Fábio Cappabianco, Ph.D. and Vinícius R. Miguel.
"
" Please file a report at our GitHub page if bugs are found or if you wish for a new functionality to be implemented.
"
"Visit our website!
")
.arg(QApplication::applicationVersion()));
}
void BewavedDolphin::on_actionAboutQt_triggered()
{
QMessageBox::aboutQt(this);
}
wiRedPanda-4.1.12/app/bewaveddolphin.h 0000664 0000000 0000000 00000011206 14440202064 0017535 0 ustar 00root root 0000000 0000000 // Copyright 2015 - 2022, GIBIS-UNIFESP and the WiRedPanda contributors
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "graphicsview.h"
#include "scene.h"
#include
#include
#include
#include
#include
class GraphicsView;
class MainWindow;
class QItemSelection;
class QSaveFile;
namespace Ui
{
class BewavedDolphin;
}
enum class PlotType { Number, Line };
class SignalModel : public QStandardItemModel
{
Q_OBJECT
public:
SignalModel(const int inputs, const int rows, const int columns, QObject *parent = nullptr);
Qt::ItemFlags flags(const QModelIndex &index) const override;
private:
const int m_inputCount;
};
class SignalDelegate : public QItemDelegate
{
Q_OBJECT
public:
SignalDelegate(QObject *parent);
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
};
class BewavedDolphin : public QMainWindow
{
Q_OBJECT
public:
explicit BewavedDolphin(Scene *scene, const bool askConnection = true, MainWindow *parent = nullptr);
~BewavedDolphin() override;
void createWaveform();
void createWaveform(const QString &fileName);
void print();
void saveToTxt(QTextStream &stream);
void show();
protected:
void closeEvent(QCloseEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
private:
Q_DISABLE_COPY(BewavedDolphin)
bool checkSave();
int sectionFirstColumn(const QItemSelection &ranges);
int sectionFirstRow(const QItemSelection &ranges);
void associateToWiredPanda(const QString &fileName);
void copy(const QItemSelection &ranges, QDataStream &stream);
void createElement(const int row, const int col, const int value, const bool isInput = true, const bool changeNext = true);
void createOneElement(const int row, const int col, const bool isInput = true, const bool changeNext = true);
void createZeroElement(const int row, const int col, const bool isInput = true, const bool changeNext = true);
void cut(const QItemSelection &ranges, QDataStream &stream);
void load(QDataStream &stream);
void load(QFile &file);
void load(const QString &fileName);
void loadElements();
void loadFromTerminal();
void loadNewTable();
void loadPixmaps();
void loadSignals(QStringList &inputLabels, QStringList &outputLabels);
void on_actionAboutQt_triggered();
void on_actionAbout_triggered();
void on_actionClear_triggered();
void on_actionCombinational_triggered();
void on_actionCopy_triggered();
void on_actionCut_triggered();
void on_actionExit_triggered();
void on_actionExportToPdf_triggered();
void on_actionExportToPng_triggered();
void on_actionFitScreen_triggered();
void on_actionInvert_triggered();
void on_actionLoad_triggered();
void on_actionPaste_triggered();
void on_actionResetZoom_triggered();
void on_actionSaveAs_triggered();
void on_actionSave_triggered();
void on_actionSetClockWave_triggered();
void on_actionSetLength_triggered();
void on_actionSetTo0_triggered();
void on_actionSetTo1_triggered();
void on_actionShowNumbers_triggered();
void on_actionShowWaveforms_triggered();
void on_actionZoomIn_triggered();
void on_actionZoomOut_triggered();
void on_tableView_selectionChanged();
void paste(const QItemSelection &ranges, QDataStream &stream);
void prepare(const QString &fileName = {});
void resizeScene();
void restoreInputs();
void run();
void run2();
void save(QDataStream &stream);
void save(QSaveFile &file);
void save(const QString &fileName);
void setLength(const int simLength, const bool runSimulation);
void zoomChanged();
Ui::BewavedDolphin *m_ui;
GraphicsView m_view;
MainWindow *m_mainWindow = nullptr;
PlotType m_type = PlotType::Line;
QFileInfo m_currentFile;
QGraphicsScene *m_scene = new QGraphicsScene(this);
QPixmap m_fallingBlue;
QPixmap m_fallingGreen;
QPixmap m_highBlue;
QPixmap m_highGreen;
QPixmap m_lowBlue;
QPixmap m_lowGreen;
QPixmap m_risingBlue;
QPixmap m_risingGreen;
QStandardItemModel *m_model = nullptr;
QTableView *m_signalTableView = new QTableView();
QVector m_outputs;
QVector m_inputs;
QVector m_oldInputValues;
Scene *m_externalScene = nullptr;
Simulation *m_simulation = nullptr;
bool m_edited = false;
const bool m_askConnection;
const double m_scaleFactor = 0.8;
double m_scale = 1.0;
int m_clockPeriod = 0;
int m_inputPorts = 0;
int m_length = 32;
};
wiRedPanda-4.1.12/app/bewaveddolphin.ui 0000664 0000000 0000000 00000032177 14440202064 0017735 0 ustar 00root root 0000000 0000000
BewavedDolphin
0
0
800
600
MainWindow
:/toolbar/dolphin_icon.svg:/toolbar/dolphin_icon.svg
0
0
0
0
0
0
0
toolBar
TopToolBarArea
false
:/dolphin/help.svg:/dolphin/help.svg
About
Ctrl+H
:/dolphin/folder.svg:/dolphin/folder.svg
Load
Ctrl+L
:/dolphin/exit.svg:/dolphin/exit.svg
Exit
Ctrl+W
:/toolbar/wavyIcon.svg:/toolbar/wavyIcon.svg
Combinational
Alt+C
:/dolphin/pdf.svg:/dolphin/pdf.svg
Export to PDF
Ctrl+P
:/dolphin/save.svg:/dolphin/save.svg
Save
Ctrl+S
:/dolphin/save.svg:/dolphin/save.svg
Save As...
Ctrl+Shift+S
:/toolbar/copy.svg:/toolbar/copy.svg
Copy
Ctrl+C
:/dolphin/paste.svg:/dolphin/paste.svg
Paste
Ctrl+V
:/input/0.svg:/input/0.svg
Set to 0
0
:/input/1.svg:/input/1.svg
Set to 1
1
:/input/clock1.svg:/input/clock1.svg
Set clock frequency
Set clock frequency
Alt+W
:/basic/not.svg:/basic/not.svg
Invert
Space
false
Merge
false
Split
:/dolphin/png.svg:/dolphin/png.svg
Export to PNG
Ctrl+Shift+P
:/dolphin/range.svg:/dolphin/range.svg
Set Length
Alt+L
:/toolbar/helpQt.svg:/toolbar/helpQt.svg
About Qt
Ctrl+Shift+H
:/dolphin/zoomIn.svg:/dolphin/zoomIn.svg
Zoom In
Ctrl+=
:/dolphin/zoomOut.svg:/dolphin/zoomOut.svg
Zoom Out
Ctrl+-
:/dolphin/zoomRange.svg:/dolphin/zoomRange.svg
Fit to screen
Fit to screen
Ctrl+Shift+R
:/dolphin/zoomReset.svg:/dolphin/zoomReset.svg
Reset Zoom
Ctrl+Home
:/dolphin/reloadFile.svg:/dolphin/reloadFile.svg
Clear
Alt+X
:/dolphin/cut.svg:/dolphin/cut.svg
Cut
Ctrl+X
Show Numbers
Show Waveforms
wiRedPanda-4.1.12/app/clockdialog.cpp 0000664 0000000 0000000 00000001400 14440202064 0017343 0 ustar 00root root 0000000 0000000 // Copyright 2015 - 2022, GIBIS-UNIFESP and the WiRedPanda contributors
// SPDX-License-Identifier: GPL-3.0-or-later
#include "clockdialog.h"
#include "ui_clockdialog.h"
ClockDialog::ClockDialog(const int currentFrequency, QWidget *parent)
: QDialog(parent)
, m_ui(new Ui::ClockDialog)
{
m_ui->setupUi(this);
m_ui->frequencySpinBox->setValue(currentFrequency);
setWindowTitle(tr("Clock Frequency Selection"));
connect(m_ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(m_ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
}
ClockDialog::~ClockDialog()
{
delete m_ui;
}
int ClockDialog::frequency()
{
return (exec() == QDialog::Accepted) ? m_ui->frequencySpinBox->value() : -1;
}
wiRedPanda-4.1.12/app/clockdialog.h 0000664 0000000 0000000 00000001131 14440202064 0017011 0 ustar 00root root 0000000 0000000 // Copyright 2015 - 2022, GIBIS-UNIFESP and the WiRedPanda contributors
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include
namespace Ui
{
class ClockDialog;
}
//!
//! \brief The clockDialog class handles dialogs for setting the frequency at which a clock ticks
//!
class ClockDialog : public QDialog
{
Q_OBJECT
public:
explicit ClockDialog(const int currentFrequency, QWidget *parent = nullptr);
~ClockDialog() override;
//! Returns the clock frequency in Hz
int frequency();
private:
Q_DISABLE_COPY(ClockDialog)
Ui::ClockDialog *m_ui;
};
wiRedPanda-4.1.12/app/clockdialog.ui 0000664 0000000 0000000 00000006317 14440202064 0017212 0 ustar 00root root 0000000 0000000
ClockDialog
0
0
184
116
Dialog
:/toolbar/wavyIcon.svg:/toolbar/wavyIcon.svg
-
QDialogButtonBox::Cancel|QDialogButtonBox::Ok
-
Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
2
1024
2
-
2
1024
2
Qt::Horizontal
-
Clock Frequency
-
1024
Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing
-
2
Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
frequencySlider
valueChanged(int)
frequencySpinBox
setValue(int)
334
47
499
21
frequencySpinBox
valueChanged(int)
frequencySlider
setValue(int)
499
21
334
47
wiRedPanda-4.1.12/app/commands.cpp 0000664 0000000 0000000 00000060226 14440202064 0016704 0 ustar 00root root 0000000 0000000 // Copyright 2015 - 2022, GIBIS-UNIFESP and the WiRedPanda contributors
// SPDX-License-Identifier: GPL-3.0-or-later
#include "commands.h"
#include "common.h"
#include "elementfactory.h"
#include "globalproperties.h"
#include "graphicelement.h"
#include "qneconnection.h"
#include "qneport.h"
#include "scene.h"
#include "serialization.h"
#include "simulation.h"
#include "simulationblocker.h"
#include
#include
void storeIds(const QList &items, QList &ids)
{
ids.reserve(items.size());
for (auto *item : items) {
if (auto *itemId = dynamic_cast(item)) {
ids.append(itemId->id());
}
}
}
void storeOtherIds(const QList &connections, const QList &ids, QList &otherIds)
{
for (auto *item : connections) {
if (auto *conn = qgraphicsitem_cast(item); conn && (item->type() == QNEConnection::Type)) {
if (auto *port1 = conn->startPort(); port1 && port1->graphicElement() && !ids.contains(port1->graphicElement()->id())) {
otherIds.append(port1->graphicElement()->id());
}
if (auto *port2 = conn->endPort(); port2 && port2->graphicElement() && !ids.contains(port2->graphicElement()->id())) {
otherIds.append(port2->graphicElement()->id());
}
}
}
}
const QList loadList(const QList &items, QList &ids, QList &otherIds)
{
QList elements;
/* Stores selected graphicElements */
for (auto *item : items) {
if (item->type() == GraphicElement::Type) {
if (!elements.contains(item)) {
elements.append(item);
}
}
}
QList connections;
/* Stores all the wires linked to these elements */
for (auto *item : elements) {
if (auto *elm = qgraphicsitem_cast(item)) {
for (auto *port : elm->inputs()) {
for (auto *conn : port->connections()) {
if (!connections.contains(conn)) {
connections.append(conn);
}
}
}
for (auto *port : elm->outputs()) {
for (auto *conn : port->connections()) {
if (!connections.contains(conn)) {
connections.append(conn);
}
}
}
}
}
/* Stores the other wires selected */
for (auto *item : items) {
if (item->type() == QNEConnection::Type) {
if (!connections.contains(item)) {
connections.append(item);
}
}
}
/* Stores the ids of all elements listed in items; */
storeIds(elements + connections, ids);
/* Stores all the elements linked to each connection that will not be deleted. */
storeOtherIds(connections, ids, otherIds);
return elements + connections;
}
const QList findItems(const QList &ids)
{
QList items;
items.reserve(ids.size());
for (const int id : ids) {
if (auto *item = dynamic_cast(ElementFactory::itemById(id))) {
items.append(item);
}
}
if (items.size() != ids.size()) {
throw Pandaception(QObject::tr("One or more items was not found on the scene."));
}
return items;
}
const QList findElements(const QList &ids)
{
QList items;
items.reserve(ids.size());
for (const int id : ids) {
if (auto *item = dynamic_cast(ElementFactory::itemById(id))) {
items.append(item);
}
}
if (items.size() != ids.size()) {
throw Pandaception(QObject::tr("One or more elements was not found on the scene."));
}
return items;
}
QNEConnection *findConn(const int id)
{
return dynamic_cast(ElementFactory::itemById(id));
}
GraphicElement *findElm(const int id)
{
return dynamic_cast(ElementFactory::itemById(id));
}
void saveItems(QByteArray &itemData, const QList &items, const QList &otherIds)
{
itemData.clear();
QDataStream stream(&itemData, QIODevice::WriteOnly);
stream.setVersion(QDataStream::Qt_5_12);
const auto others = findElements(otherIds);
for (auto *elm : others) {
elm->save(stream);
}
Serialization::serialize(items, stream);
}
void addItems(Scene *scene, const QList &items)
{
for (auto *item : items) {
if (item->scene() != scene) {
scene->addItem(item);
}
if (item->type() == GraphicElement::Type) {
item->setSelected(true);
}
}
}
const QList loadItems(Scene *scene, QByteArray &itemData, const QList &ids, QList &otherIds)
{
if (itemData.isEmpty()) {
return {};
}
QDataStream stream(&itemData, QIODevice::ReadOnly);
stream.setVersion(QDataStream::Qt_5_12);
QMap portMap;
const QVersionNumber version = GlobalProperties::version;
for (auto *elm : findElements(otherIds)) {
elm->load(stream, portMap, version);
}
/* Assuming that all connections are stored after the elements, we will deserialize the elements first.
* We will store one additional information: The element IDs! */
const auto items = Serialization::deserialize(stream, portMap, version);
if (items.size() != ids.size()) {
throw Pandaception(QObject::tr("One or more elements were not found on scene. Expected %1, found %2.").arg(ids.size(), items.size()));
}
for (int i = 0; i < items.size(); ++i) {
if (auto *itemId = dynamic_cast(items.at(i))) {
ElementFactory::updateItemId(itemId, ids.at(i));
}
}
addItems(scene, items);
return items;
}
void deleteItems(Scene *scene, const QList &items)
{
/* Delete items on reverse order */
for (auto it = items.rbegin(); it != items.rend(); ++it) {
scene->removeItem(*it);
delete *it;
}
}
AddItemsCommand::AddItemsCommand(const QList &items, Scene *scene, QUndoCommand *parent)
: QUndoCommand(parent)
, m_scene(scene)
{
SimulationBlocker blocker(m_scene->simulation());
const auto items_ = loadList(items, m_ids, m_otherIds);
addItems(m_scene, items_);
setText(tr("Add %1 elements").arg(items_.size()));
}
void AddItemsCommand::undo()
{
qCDebug(zero) << text();
SimulationBlocker blocker(m_scene->simulation());
const auto items = findItems(m_ids);
saveItems(m_itemData, items, m_otherIds);
deleteItems(m_scene, items);
m_scene->setCircuitUpdateRequired();
}
void AddItemsCommand::redo()
{
qCDebug(zero) << text();
SimulationBlocker blocker(m_scene->simulation());
loadItems(m_scene, m_itemData, m_ids, m_otherIds);
m_scene->setCircuitUpdateRequired();
}
DeleteItemsCommand::DeleteItemsCommand(const QList &items, Scene *scene, QUndoCommand *parent)
: QUndoCommand(parent)
, m_scene(scene)
{
SimulationBlocker blocker(m_scene->simulation());
const auto items_ = loadList(items, m_ids, m_otherIds);
setText(tr("Delete %1 elements").arg(items_.size()));
}
void DeleteItemsCommand::undo()
{
qCDebug(zero) << text();
SimulationBlocker blocker(m_scene->simulation());
loadItems(m_scene, m_itemData, m_ids, m_otherIds);
m_scene->setCircuitUpdateRequired();
}
void DeleteItemsCommand::redo()
{
qCDebug(zero) << text();
SimulationBlocker blocker(m_scene->simulation());
const auto items = findItems(m_ids);
saveItems(m_itemData, items, m_otherIds);
deleteItems(m_scene, items);
m_scene->setCircuitUpdateRequired();
}
RotateCommand::RotateCommand(const QList &items, const int angle, Scene *scene, QUndoCommand *parent)
: QUndoCommand(parent)
, m_angle(angle)
, m_scene(scene)
{
setText(tr("Rotate %1 degrees").arg(m_angle));
m_ids.reserve(items.size());
m_positions.reserve(items.size());
for (auto *item : items) {
m_positions.append(item->pos());
item->setPos(item->pos());
m_ids.append(item->id());
}
}
void RotateCommand::undo()
{
qCDebug(zero) << text();
const auto elements = findElements(m_ids);
for (int i = 0; i < elements.size(); ++i) {
auto *elm = elements.at(i);
elm->setRotation(elm->rotation() - m_angle);
elm->setPos(m_positions.at(i));
elm->update();
elm->setSelected(true);
}
m_scene->setAutosaveRequired();
}
void RotateCommand::redo()
{
qCDebug(zero) << text();
const auto elements = findElements(m_ids);
double cx = 0;
double cy = 0;
int sz = 0;
for (auto *elm : elements) {
cx += elm->pos().x();
cy += elm->pos().y();
sz++;
}
if (sz != 0) {
cx /= sz;
cy /= sz;
}
QTransform transform;
transform.translate(cx, cy);
transform.rotate(m_angle);
transform.translate(-cx, -cy);
for (auto *elm : elements) {
elm->setPos(transform.map(elm->pos()));
elm->setRotation(elm->rotation() + m_angle);
}
m_scene->setAutosaveRequired();
}
MoveCommand::MoveCommand(const QList &list, const QList &oldPositions, Scene *scene, QUndoCommand *parent)
: QUndoCommand(parent)
, m_oldPositions(oldPositions)
, m_scene(scene)
{
m_newPositions.reserve(list.size());
m_ids.reserve(list.size());
for (auto *elm : list) {
m_ids.append(elm->id());
m_newPositions.append(elm->pos());
}
setText(tr("Move elements"));
}
void MoveCommand::undo()
{
qCDebug(zero) << text();
const auto elements = findElements(m_ids);
for (int i = 0; i < elements.size(); ++i) {
elements.at(i)->setPos(m_oldPositions.at(i));
}
m_scene->setAutosaveRequired();
}
void MoveCommand::redo()
{
qCDebug(zero) << text();
const auto elements = findElements(m_ids);
for (int i = 0; i < elements.size(); ++i) {
elements.at(i)->setPos(m_newPositions.at(i));
}
m_scene->setAutosaveRequired();
}
UpdateCommand::UpdateCommand(const QList &elements, const QByteArray &oldData, Scene *scene, QUndoCommand *parent)
: QUndoCommand(parent)
, m_oldData(oldData)
, m_scene(scene)
{
m_ids.reserve(elements.size());
QDataStream stream(&m_newData, QIODevice::WriteOnly);
stream.setVersion(QDataStream::Qt_5_12);
for (auto *elm : elements) {
elm->save(stream);
m_ids.append(elm->id());
}
setText(tr("Update %1 elements").arg(elements.size()));
}
void UpdateCommand::undo()
{
qCDebug(zero) << text();
loadData(m_oldData);
m_scene->setCircuitUpdateRequired();
}
void UpdateCommand::redo()
{
qCDebug(zero) << text();
loadData(m_newData);
m_scene->setCircuitUpdateRequired();
}
void UpdateCommand::loadData(QByteArray &itemData)
{
const auto elements = findElements(m_ids);
if (elements.isEmpty()) {
return;
}
QDataStream stream(&itemData, QIODevice::ReadOnly);
stream.setVersion(QDataStream::Qt_5_12);
QMap portMap;
const QVersionNumber version = GlobalProperties::version;
for (auto *elm : elements) {
elm->load(stream, portMap, version);
elm->setSelected(true);
}
}
SplitCommand::SplitCommand(QNEConnection *conn, QPointF mousePos, Scene *scene, QUndoCommand *parent)
: QUndoCommand(parent)
, m_scene(scene)
{
auto *node = ElementFactory::buildElement(ElementType::Node);
/* Align node to Grid */
m_nodePos = mousePos - node->pixmapCenter();
const int gridSize = GlobalProperties::gridSize;
qreal xV = qRound(m_nodePos.x() / gridSize) * gridSize;
qreal yV = qRound(m_nodePos.y() / gridSize) * gridSize;
m_nodePos = QPointF(xV, yV);
/* Rotate line according to angle between p1 and p2 */
const int angle = static_cast(conn->angle());
m_nodeAngle = static_cast(360 - 90 * (std::round(angle / 90.0)));
/* Assigning class attributes */
m_elm1Id = conn->startPort()->graphicElement()->id();
m_elm2Id = conn->endPort()->graphicElement()->id();
m_c1Id = conn->id();
m_c2Id = (new QNEConnection())->id();
m_nodeId = node->id();
setText(tr("Wire split"));
}
void SplitCommand::redo()
{
qCDebug(zero) << text();
auto *conn1 = findConn(m_c1Id);
auto *conn2 = findConn(m_c2Id);
auto *node = findElm(m_nodeId);
auto *elm1 = findElm(m_elm1Id);
auto *elm2 = findElm(m_elm2Id);
if (!conn2) {
conn2 = new QNEConnection();
ElementFactory::updateItemId(conn2, m_c2Id);
}
if (!node) {
node = ElementFactory::buildElement(ElementType::Node);
ElementFactory::updateItemId(node, m_nodeId);
}
if (!conn1 || !conn2 || !elm1 || !elm2 || !node) {
throw Pandaception(tr("Error trying to redo ") + text());
}
node->setPos(m_nodePos);
node->setRotation(m_nodeAngle);
auto *endPort = conn1->endPort();
conn2->setStartPort(node->outputPort());
conn2->setEndPort(endPort);
conn1->setEndPort(node->inputPort());
m_scene->addItem(node);
m_scene->addItem(conn2);
conn1->updatePosFromPorts();
conn2->updatePosFromPorts();
m_scene->setCircuitUpdateRequired();
}
void SplitCommand::undo()
{
qCDebug(zero) << text();
auto *conn1 = findConn(m_c1Id);
auto *conn2 = findConn(m_c2Id);
auto *node = findElm(m_nodeId);
auto *elm1 = findElm(m_elm1Id);
auto *elm2 = findElm(m_elm2Id);
if (!conn1 || !conn2 || !elm1 || !elm2 || !node) {
throw Pandaception(tr("Error trying to undo ") + text());
}
conn1->setEndPort(conn2->endPort());
conn1->updatePosFromPorts();
m_scene->removeItem(conn2);
m_scene->removeItem(node);
delete conn2;
delete node;
m_scene->setCircuitUpdateRequired();
}
MorphCommand::MorphCommand(const QList &elements, ElementType type, Scene *scene, QUndoCommand *parent)
: QUndoCommand(parent)
, m_newType(type)
, m_scene(scene)
{
m_ids.reserve(elements.size());
m_types.reserve(elements.size());
for (auto *oldElm : elements) {
m_ids.append(oldElm->id());
m_types.append(oldElm->elementType());
}
setText(tr("Morph %1 elements to %2").arg(elements.size()).arg(elements.constFirst()->objectName()));
}
void MorphCommand::undo()
{
qCDebug(zero) << text();
auto newElms = findElements(m_ids);
decltype(newElms) oldElms;
oldElms.reserve(m_ids.size());
for (int i = 0; i < m_ids.size(); ++i) {
oldElms << ElementFactory::buildElement(m_types.at(i));
}
transferConnections(newElms, oldElms);
m_scene->setCircuitUpdateRequired();
}
void MorphCommand::redo()
{
qCDebug(zero) << text();
auto oldElms = findElements(m_ids);
decltype(oldElms) newElms;
newElms.reserve(m_ids.size());
for (int i = 0; i < m_ids.size(); ++i) {
newElms << ElementFactory::buildElement(m_newType);
}
transferConnections(oldElms, newElms);
m_scene->setCircuitUpdateRequired();
}
void MorphCommand::transferConnections(QList from, QList to)
{
for (int elm = 0; elm < from.size(); ++elm) {
auto *oldElm = from.at(elm);
auto *newElm = to.at(elm);
newElm->setInputSize(oldElm->inputSize());
newElm->setPos(oldElm->pos());
if ((oldElm->elementType() == ElementType::Not) && (newElm->elementType() == ElementType::Node)) {
newElm->moveBy(16, 16);
}
if ((oldElm->elementType() == ElementType::Node) && (newElm->elementType() == ElementType::Not)) {
newElm->moveBy(-16, -16);
}
if (newElm->isRotatable() && oldElm->isRotatable()) {
newElm->setRotation(oldElm->rotation());
}
if (newElm->hasLabel() && oldElm->hasLabel() && (oldElm->elementType() != ElementType::Buzzer)) {
newElm->setLabel(oldElm->label());
}
if (newElm->hasColors() && oldElm->hasColors()) {
newElm->setColor(oldElm->color());
}
if (newElm->hasFrequency() && oldElm->hasFrequency()) {
newElm->setFrequency(oldElm->frequency());
}
if (newElm->hasTrigger() && oldElm->hasTrigger()) {
newElm->setTrigger(oldElm->trigger());
}
for (int port = 0; port < oldElm->inputSize(); ++port) {
while (!oldElm->inputPort(port)->connections().isEmpty()) {
if (auto *conn = oldElm->inputPort(port)->connections().constFirst(); conn && (conn->endPort() == oldElm->inputPort(port))) {
conn->setEndPort(newElm->inputPort(port));
}
}
}
for (int port = 0; port < oldElm->outputSize(); ++port) {
while (!oldElm->outputPort(port)->connections().isEmpty()) {
if (auto *conn = oldElm->outputPort(port)->connections().constFirst(); conn && (conn->startPort() == oldElm->outputPort(port))) {
conn->setStartPort(newElm->outputPort(port));
}
}
}
const int oldId = oldElm->id();
m_scene->removeItem(oldElm);
delete oldElm;
ElementFactory::updateItemId(newElm, oldId);
m_scene->addItem(newElm);
newElm->updatePortsProperties();
}
}
// FIXME: verticalFlip is rotating on the horizontal axis too
FlipCommand::FlipCommand(const QList &items, const int axis, Scene *scene, QUndoCommand *parent)
: QUndoCommand(parent)
, m_scene(scene)
, m_axis(axis)
{
if (items.isEmpty()) {
return;
}
setText(tr("Flip %1 elements in axis %2").arg(items.size(), axis));
m_ids.reserve(items.size());
m_positions.reserve(items.size());
double xmin = items.constFirst()->pos().rx();
double ymin = items.constFirst()->pos().ry();
double xmax = xmin;
double ymax = ymin;
for (auto *item : items) {
m_positions.append(item->pos());
m_ids.append(item->id());
xmin = qMin(xmin, item->pos().rx());
ymin = qMin(ymin, item->pos().ry());
xmax = qMax(xmax, item->pos().rx());
ymax = qMax(ymax, item->pos().ry());
}
m_minPos = QPointF(xmin, ymin);
m_maxPos = QPointF(xmax, ymax);
}
void FlipCommand::undo()
{
qCDebug(zero) << text();
redo();
}
void FlipCommand::redo()
{
qCDebug(zero) << text();
for (auto *elm : findElements(m_ids)) {
auto pos = elm->pos();
(m_axis == 0) ? pos.setX(m_minPos.rx() + (m_maxPos.rx() - pos.rx()))
: pos.setY(m_minPos.ry() + (m_maxPos.ry() - pos.ry()));
elm->setPos(pos);
if (elm->isRotatable()) {
elm->setRotation(elm->rotation() + 180);
}
}
m_scene->setAutosaveRequired();
}
ChangeInputSizeCommand::ChangeInputSizeCommand(const QList &elements, const int newInputSize, Scene *scene, QUndoCommand *parent)
: QUndoCommand(parent)
, m_scene(scene)
, m_newInputSize(newInputSize)
{
m_ids.reserve(elements.size());
for (auto *elm : elements) {
m_ids.append(elm->id());
}
setText(tr("Change input size to %1").arg(newInputSize));
}
void ChangeInputSizeCommand::redo()
{
qCDebug(zero) << text();
const auto m_elements = findElements(m_ids);
QList serializationOrder;
serializationOrder.reserve(m_elements.size());
m_oldData.clear();
QDataStream stream(&m_oldData, QIODevice::WriteOnly);
stream.setVersion(QDataStream::Qt_5_12);
for (auto *elm : m_elements) {
elm->save(stream);
serializationOrder.append(elm);
for (int port = m_newInputSize; port < elm->inputSize(); ++port) {
for (auto *conn : elm->inputPort(port)->connections()) {
auto *outputPort = conn->startPort();
outputPort->graphicElement()->save(stream);
serializationOrder.append(outputPort->graphicElement());
}
}
}
for (auto *elm : m_elements) {
for (int port = m_newInputSize; port < elm->inputSize(); ++port) {
while (!elm->inputPort(port)->connections().isEmpty()) {
auto *conn = elm->inputPort(port)->connections().constFirst();
conn->save(stream);
m_scene->removeItem(conn);
auto *outputPort = conn->startPort();
elm->inputPort(port)->disconnect(conn);
outputPort->disconnect(conn);
}
}
elm->setInputSize(m_newInputSize);
}
m_order.clear();
for (auto *elm : serializationOrder) {
m_order.append(elm->id());
}
m_scene->setCircuitUpdateRequired();
}
void ChangeInputSizeCommand::undo()
{
qCDebug(zero) << text();
const auto m_elements = findElements(m_ids);
const auto serializationOrder = findElements(m_order);
QDataStream stream(&m_oldData, QIODevice::ReadOnly);
stream.setVersion(QDataStream::Qt_5_12);
QMap portMap;
const QVersionNumber version = GlobalProperties::version;
for (auto *elm : serializationOrder) {
elm->load(stream, portMap, version);
}
for (auto *elm : m_elements) {
for (int in = m_newInputSize; in < elm->inputSize(); ++in) {
auto *conn = new QNEConnection();
conn->load(stream, portMap);
m_scene->addItem(conn);
}
elm->setSelected(true);
}
m_scene->setCircuitUpdateRequired();
}
ChangeOutputSizeCommand::ChangeOutputSizeCommand(const QList &elements, const int newOutputSize, Scene *scene, QUndoCommand *parent)
: QUndoCommand(parent)
, m_scene(scene)
, m_newOutputSize(newOutputSize)
{
m_ids.reserve(elements.size());
for (auto *elm : elements) {
m_ids.append(elm->id());
}
setText(tr("Change input size to %1").arg(newOutputSize));
}
void ChangeOutputSizeCommand::redo()
{
qCDebug(zero) << text();
const auto m_elements = findElements(m_ids);
QList serializationOrder;
m_oldData.clear();
QDataStream stream(&m_oldData, QIODevice::WriteOnly);
stream.setVersion(QDataStream::Qt_5_12);
serializationOrder.reserve(m_elements.size());
for (auto *elm : m_elements) {
elm->save(stream);
serializationOrder.append(elm);
for (int port = m_newOutputSize; port < elm->outputSize(); ++port) {
for (auto *conn : elm->outputPort(port)->connections()) {
auto *inputPort = conn->endPort();
inputPort->graphicElement()->save(stream);
serializationOrder.append(inputPort->graphicElement());
}
}
}
for (auto *elm : m_elements) {
for (int port = m_newOutputSize; port < elm->outputSize(); ++port) {
while (!elm->outputPort(port)->connections().isEmpty()) {
auto *conn = elm->outputPort(port)->connections().constFirst();
conn->save(stream);
m_scene->removeItem(conn);
auto *inputPort = conn->endPort();
elm->outputPort(port)->disconnect(conn);
inputPort->disconnect(conn);
}
}
elm->setOutputSize(m_newOutputSize);
elm->setSelected(true);
}
m_order.clear();
for (auto *elm : serializationOrder) {
m_order.append(elm->id());
}
m_scene->setCircuitUpdateRequired();
}
void ChangeOutputSizeCommand::undo()
{
qCDebug(zero) << text();
const auto elements = findElements(m_ids);
const auto serializationOrder = findElements(m_order);
QDataStream stream(&m_oldData, QIODevice::ReadOnly);
stream.setVersion(QDataStream::Qt_5_12);
QMap portMap;
const QVersionNumber version = GlobalProperties::version;
for (auto *elm : serializationOrder) {
elm->load(stream, portMap, version);
}
for (auto *elm : elements) {
for (int out = m_newOutputSize; out < elm->outputSize(); ++out) {
auto *conn = new QNEConnection;
conn->load(stream, portMap);
m_scene->addItem(conn);
}
elm->setSelected(true);
}
m_scene->setCircuitUpdateRequired();
}
wiRedPanda-4.1.12/app/commands.h 0000664 0000000 0000000 00000013621 14440202064 0016346 0 ustar 00root root 0000000 0000000 // Copyright 2015 - 2022, GIBIS-UNIFESP and the WiRedPanda contributors
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "graphicelement.h"
#include "scene.h"
#include
class QNEConnection;
const QList findElements(const QList &ids);
const QList findItems(const QList &ids);
const QList loadItems(Scene *scene, QByteArray &itemData, const QList &ids, QList &otherIds);
const QList loadList(const QList &items, QList &ids, QList &otherIds);
void addItems(Scene *scene, const QList &items);
void deleteItems(Scene *scene, const QList &items);
void saveItems(QByteArray &itemData, const QList &items, const QList &otherIds);
void storeIds(const QList &items, QList &ids);
void storeOtherIds(const QList &connections, const QList &ids, QList &otherIds);
class AddItemsCommand : public QUndoCommand
{
Q_DECLARE_TR_FUNCTIONS(AddItemsCommand)
public:
//! \param item A list of items in the form of GraphicElements (an IO elem., a gate or an IC)
//! \param editor The editor to which the command will be added to
explicit AddItemsCommand(const QList &items, Scene *scene, QUndoCommand *parent = nullptr);
void redo() override;
void undo() override;
private:
QByteArray m_itemData;
QList m_ids;
QList m_otherIds;
Scene *m_scene;
};
//! Represents a single action of removing a list of elements on the editor
class DeleteItemsCommand : public QUndoCommand
{
Q_DECLARE_TR_FUNCTIONS(DeleteItemsCommand)
public:
//! \param items A list of QGraphicsItems to be removed from the editor
//! \param editor The editor from where the items will be removed
explicit DeleteItemsCommand(const QList &items, Scene *scene, QUndoCommand *parent = nullptr);
void redo() override;
void undo() override;
private:
QByteArray m_itemData;
QList m_ids;
QList m_otherIds;
Scene *m_scene;
};
//! Represents a single action of rotating a list of elements on the editor
class RotateCommand : public QUndoCommand
{
Q_DECLARE_TR_FUNCTIONS(RotateCommand)
public:
//! \param items are the items to be rotated
//! \param angle defines how many degrees will be rotated, in clockwise direction, by this command.
explicit RotateCommand(const QList &items, const int angle, Scene *scene, QUndoCommand *parent = nullptr);
void redo() override;
void undo() override;
private:
//! Defines how many degrees will be rotated, in clockwise direction, in this command.
int m_angle;
QList m_positions;
QList m_ids;
Scene *m_scene;
};
//! Represents a single action of moving a list of actions on the editor
class MoveCommand : public QUndoCommand
{
Q_DECLARE_TR_FUNCTIONS(MoveCommand)
public:
explicit MoveCommand(const QList &list, const QList &oldPositions, Scene *scene, QUndoCommand *parent = nullptr);
void redo() override;
void undo() override;
private:
QList m_newPositions;
QList m_oldPositions;
QPointF m_offset;
QList m_ids;
Scene *m_scene;
};
class UpdateCommand : public QUndoCommand
{
Q_DECLARE_TR_FUNCTIONS(UpdateCommand)
public:
explicit UpdateCommand(const QList &elements, const QByteArray &oldData, Scene *scene, QUndoCommand *parent = nullptr);
void redo() override;
void undo() override;
private:
void loadData(QByteArray &itemData);
QByteArray m_newData;
QByteArray m_oldData;
QList m_ids;
Scene *m_scene;
};
class SplitCommand : public QUndoCommand
{
Q_DECLARE_TR_FUNCTIONS(SplitCommand)
public:
explicit SplitCommand(QNEConnection *conn, QPointF mousePos, Scene *scene, QUndoCommand *parent = nullptr);
void undo() override;
void redo() override;
private:
QPointF m_nodePos;
Scene *m_scene;
int m_c1Id;
int m_c2Id;
int m_elm1Id;
int m_elm2Id;
int m_nodeAngle;
int m_nodeId;
};
class MorphCommand : public QUndoCommand
{
Q_DECLARE_TR_FUNCTIONS(MorphCommand)
public:
explicit MorphCommand(const QList &elements, ElementType type, Scene *scene, QUndoCommand *parent = nullptr);
void redo() override;
void undo() override;
private:
void transferConnections(QList from, QList to);
ElementType m_newType;
QList m_types;
QList m_ids;
Scene *m_scene;
};
class ChangeInputSizeCommand : public QUndoCommand
{
Q_DECLARE_TR_FUNCTIONS(ChangeInputSizeCommand)
public:
explicit ChangeInputSizeCommand(const QList &elements, const int newInputSize, Scene *scene, QUndoCommand *parent = nullptr);
void redo() override;
void undo() override;
private:
QByteArray m_oldData;
QList m_ids;
QList m_order;
Scene *m_scene;
int m_newInputSize;
};
class FlipCommand : public QUndoCommand
{
Q_DECLARE_TR_FUNCTIONS(FlipCommand)
public:
explicit FlipCommand(const QList &items, const int axis, Scene *scene, QUndoCommand *parent = nullptr);
void redo() override;
void undo() override;
private:
QList m_positions;
QList m_ids;
QPointF m_maxPos;
QPointF m_minPos;
Scene *m_scene;
int m_axis;
};
class ChangeOutputSizeCommand : public QUndoCommand
{
Q_DECLARE_TR_FUNCTIONS(ChangeOutputSizeCommand)
public:
explicit ChangeOutputSizeCommand(const QList &elements, const int newOutputSize, Scene *scene, QUndoCommand *parent = nullptr);
void redo() override;
void undo() override;
private:
QByteArray m_oldData;
QList m_ids;
QList m_order;
Scene *m_scene;
int m_newOutputSize;
};
wiRedPanda-4.1.12/app/common.cpp 0000664 0000000 0000000 00000004475 14440202064 0016377 0 ustar 00root root 0000000 0000000 // Copyright 2015 - 2022, GIBIS-UNIFESP and the WiRedPanda contributors
// SPDX-License-Identifier: GPL-3.0-or-later
#include "common.h"
#include "graphicelement.h"
#include "qneport.h"
#include "qneconnection.h"
Q_LOGGING_CATEGORY(zero, "0")
Q_LOGGING_CATEGORY(one, "1")
Q_LOGGING_CATEGORY(two, "2")
Q_LOGGING_CATEGORY(three, "3")
Q_LOGGING_CATEGORY(four, "4")
Q_LOGGING_CATEGORY(five, "5")
void Comment::setVerbosity(const int verbosity)
{
QString rules;
switch (verbosity) {
default: [[fallthrough]];
case 0: rules += "0 = false\n"; [[fallthrough]];
case 1: rules += "1 = false\n"; [[fallthrough]];
case 2: rules += "2 = false\n"; [[fallthrough]];
case 3: rules += "3 = false\n"; [[fallthrough]];
case 4: rules += "4 = false\n"; [[fallthrough]];
case 5: rules += "5 = false\n";
}
QLoggingCategory::setFilterRules(rules);
qSetMessagePattern("%{if-debug}%{line}: %{function} => %{endif}%{message}");
}
Pandaception::Pandaception(const QString &message)
: std::runtime_error(message.toStdString())
{
}
QVector Common::sortGraphicElements(QVector elements)
{
QHash beingVisited;
QHash priorities;
for (auto *elm : elements) {
calculatePriority(elm, beingVisited, priorities);
}
std::sort(elements.begin(), elements.end(), [priorities](const auto &e1, const auto &e2) {
return priorities.value(e1) > priorities.value(e2);
});
return elements;
}
int Common::calculatePriority(GraphicElement *elm, QHash &beingVisited, QHash &priorities)
{
if (!elm) {
return 0;
}
if (beingVisited.contains(elm) && beingVisited.value(elm)) {
return 0;
}
if (priorities.contains(elm)) {
return priorities.value(elm);
}
beingVisited[elm] = true;
int max = 0;
for (auto *port : elm->outputs()) {
for (auto *conn : port->connections()) {
if (auto *successor = conn->endPort()) {
max = qMax(calculatePriority(successor->graphicElement(), beingVisited, priorities), max);
}
}
}
int priority = max + 1;
priorities[elm] = priority;
beingVisited[elm] = false;
return priority;
}
wiRedPanda-4.1.12/app/common.h 0000664 0000000 0000000 00000002616 14440202064 0016037 0 ustar 00root root 0000000 0000000 // Copyright 2015 - 2022, GIBIS-UNIFESP and the WiRedPanda contributors
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include
#include
Q_DECLARE_LOGGING_CATEGORY(zero)
Q_DECLARE_LOGGING_CATEGORY(one)
Q_DECLARE_LOGGING_CATEGORY(two)
Q_DECLARE_LOGGING_CATEGORY(three)
Q_DECLARE_LOGGING_CATEGORY(four)
Q_DECLARE_LOGGING_CATEGORY(five)
#undef qCDebug // to add noquote() and nospace()
#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0)
#define qCDebug(category, ...) \
for (bool qt_category_enabled = category().isDebugEnabled(); qt_category_enabled; qt_category_enabled = false) \
QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC, category().categoryName()).debug(__VA_ARGS__).noquote().nospace()
#else
#define qCDebug(category, ...) QT_MESSAGE_LOGGER_COMMON(category, QtDebugMsg).debug(__VA_ARGS__).noquote().nospace()
#endif
class Comment
{
public:
static void setVerbosity(const int verbosity);
};
class Pandaception : public std::runtime_error
{
public:
explicit Pandaception(const QString &message);
private:
Q_DISABLE_COPY(Pandaception)
};
class GraphicElement;
class Common
{
public:
static QVector sortGraphicElements(QVector elements);
static int calculatePriority(GraphicElement *elm, QHash &beingVisited, QHash &priorities);
};
wiRedPanda-4.1.12/app/element/ 0000775 0000000 0000000 00000000000 14440202064 0016022 5 ustar 00root root 0000000 0000000 wiRedPanda-4.1.12/app/element/and.cpp 0000664 0000000 0000000 00000001062 14440202064 0017267 0 ustar 00root root 0000000 0000000 // Copyright 2015 - 2022, GIBIS-UNIFESP and the WiRedPanda contributors
// SPDX-License-Identifier: GPL-3.0-or-later
#include "and.h"
#include "globalproperties.h"
namespace
{
int id = qRegisterMetaType();
}
And::And(QGraphicsItem *parent)
: GraphicElement(ElementType::And, ElementGroup::Gate, ":/basic/and.svg", tr("AND"), tr("And"), 2, 8, 1, 1, parent)
{
if (GlobalProperties::skipInit) {
return;
}
m_defaultSkins << m_pixmapPath;
m_alternativeSkins = m_defaultSkins;
setPixmap(0);
setCanChangeSkin(true);
}
wiRedPanda-4.1.12/app/element/and.h 0000664 0000000 0000000 00000000452 14440202064 0016736 0 ustar 00root root 0000000 0000000 // Copyright 2015 - 2022, GIBIS-UNIFESP and the WiRedPanda contributors
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "graphicelement.h"
class And : public GraphicElement
{
Q_OBJECT
public:
explicit And(QGraphicsItem *parent = nullptr);
};
Q_DECLARE_METATYPE(And)
wiRedPanda-4.1.12/app/element/buzzer.cpp 0000664 0000000 0000000 00000006273 14440202064 0020057 0 ustar 00root root 0000000 0000000 // Copyright 2015 - 2022, GIBIS-UNIFESP and the WiRedPanda contributors
// SPDX-License-Identifier: GPL-3.0-or-later
#include "buzzer.h"
#include "globalproperties.h"
#include "qneport.h"
#include
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
#include
#else
#include
#include
#endif
#include
namespace
{
int id = qRegisterMetaType();
}
Buzzer::Buzzer(QGraphicsItem *parent)
: GraphicElement(ElementType::Buzzer, ElementGroup::Output, ":/output/buzzer/BuzzerOff.svg", tr("BUZZER"), tr("Buzzer"), 1, 1, 0, 0, parent)
{
if (GlobalProperties::skipInit) {
return;
}
m_defaultSkins = QStringList{
":/output/buzzer/BuzzerOff.svg",
":/output/buzzer/BuzzerOn.svg"
};
m_alternativeSkins = m_defaultSkins;
setPixmap(0);
m_label->setPos(64, 34);
setCanChangeSkin(true);
setHasAudio(true);
setHasLabel(true);
setRotatable(false);
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
m_hasOutputDevice = !QAudioDeviceInfo::defaultOutputDevice().deviceName().isEmpty();
#else
m_hasOutputDevice = !QMediaDevices::defaultAudioOutput().description().isEmpty();
#endif
if (m_hasOutputDevice) {
m_audio = new QSoundEffect(this);
}
}
void Buzzer::refresh()
{
if (!isValid()) {
stop();
return;
}
const Status inputValue = m_inputPorts.constFirst()->status();
(inputValue == Status::Active) ? play() : stop();
}
void Buzzer::setAudio(const QString ¬e)
{
if (note.isEmpty()) {
return;
}
m_note = note;
if (!m_hasOutputDevice) {
return;
}
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
m_audio->setVolume(0.35);
#else
m_audio->setVolume(0.35f);
#endif
m_audio->setSource(QUrl::fromLocalFile(":output/audio/" + note + ".wav"));
m_audio->setLoopCount(QSoundEffect::Infinite); // TODO: fix audio clipping when repeating
}
QString Buzzer::audio() const
{
return m_note;
}
void Buzzer::mute(const bool mute)
{
if (!m_hasOutputDevice) {
return;
}
m_audio->setMuted(mute);
}
void Buzzer::play()
{
if (m_isPlaying) {
return;
}
setPixmap(1);
if (m_hasOutputDevice) {
if (m_audio->source().isEmpty()) {
setAudio("C6");
}
m_audio->play();
}
m_isPlaying = true;
}
void Buzzer::stop()
{
if (!m_isPlaying) {
return;
}
setPixmap(0);
if (m_hasOutputDevice) {
m_audio->stop();
}
m_isPlaying = false;
}
void Buzzer::save(QDataStream &stream) const
{
GraphicElement::save(stream);
QMap map;
map.insert("note", audio());
stream << map;
}
void Buzzer::load(QDataStream &stream, QMap &portMap, const QVersionNumber version)
{
GraphicElement::load(stream, portMap, version);
if (version < VERSION("2.4")) {
return;
}
if (version < VERSION("4.1")) {
QString note; stream >> note;
setAudio(note);
}
if (version >= VERSION("4.1")) {
QMap map; stream >> map;
if (map.contains("note")) {
setAudio(map.value("note").toString());
}
}
}
wiRedPanda-4.1.12/app/element/buzzer.h 0000664 0000000 0000000 00000001611 14440202064 0017513 0 ustar 00root root 0000000 0000000 // Copyright 2015 - 2022, GIBIS-UNIFESP and the WiRedPanda contributors
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "graphicelement.h"
#include
#include
class Buzzer : public GraphicElement
{
Q_OBJECT
public:
explicit Buzzer(QGraphicsItem *parent = nullptr);
Buzzer(const Buzzer &other) : Buzzer(other.parentItem()) {}
QString audio() const override;
void load(QDataStream &stream, QMap &portMap, const QVersionNumber version) override;
void mute(const bool mute = true);
void refresh() override;
void save(QDataStream &stream) const override;
void setAudio(const QString ¬e) override;
private:
void play();
void stop();
QSoundEffect *m_audio = nullptr;
QString m_note;
bool m_isPlaying = false;
bool m_hasOutputDevice = false;
};
Q_DECLARE_METATYPE(Buzzer)
wiRedPanda-4.1.12/app/element/clock.cpp 0000664 0000000 0000000 00000006732 14440202064 0017631 0 ustar 00root root 0000000 0000000 // Copyright 2015 - 2022, GIBIS-UNIFESP and the WiRedPanda contributors
// SPDX-License-Identifier: GPL-3.0-or-later
#include "clock.h"
#include "globalproperties.h"
#include "qneport.h"
#include
using namespace std::chrono_literals;
namespace
{
int id = qRegisterMetaType();
}
Clock::Clock(QGraphicsItem *parent)
: GraphicElementInput(ElementType::Clock, ElementGroup::Input, ":/input/clock1.svg", tr("CLOCK SIGNAL"), tr("Clock"), 0, 0, 1, 1, parent)
{
if (GlobalProperties::skipInit) {
return;
}
m_defaultSkins = QStringList{
":/input/clock0.svg",
":/input/clock1.svg"
};
m_alternativeSkins = m_defaultSkins;
setPixmap(0);
m_locked = false;
setCanChangeSkin(true);
setHasFrequency(true);
setHasLabel(true);
setRotatable(false);
Clock::setFrequency(1.0);
Clock::setOff();
}
void Clock::updateClock()
{
if (m_locked) {
return;
}
if (m_reset) {
resetClock();
return;
}
const auto duration = std::chrono::duration(std::chrono::steady_clock::now() - m_timePoint);
if (duration > m_interval) {
m_timePoint = std::chrono::steady_clock::now();
setOn(!m_isOn);
}
}
bool Clock::isOn(const int port) const
{
Q_UNUSED(port)
return m_isOn;
}
void Clock::setOff()
{
Clock::setOn(false);
}
void Clock::setOn()
{
Clock::setOn(true);
}
void Clock::setOn(const bool value, const int port)
{
Q_UNUSED(port)
m_isOn = value;
setPixmap(static_cast(m_isOn));
outputPort()->setStatus(static_cast(m_isOn));
}
void Clock::save(QDataStream &stream) const
{
GraphicElement::save(stream);
QMap map;
map.insert("frequency", frequency());
map.insert("locked", m_locked);
stream << map;
}
void Clock::load(QDataStream &stream, QMap &portMap, const QVersionNumber version)
{
GraphicElement::load(stream, portMap, version);
if (version < VERSION("1.1")) {
return;
}
if (version < VERSION("4.1")) {
float freq; stream >> freq;
setFrequency(freq);
if (version >= VERSION("3.1")) {
stream >> m_locked;
}
}
if (version >= VERSION("4.1")) {
QMap map; stream >> map;
if (map.contains("frequency")) {
setFrequency(map.value("frequency").toFloat());
}
if (map.contains("locked")) {
m_locked = map.value("locked").toBool();
}
}
}
float Clock::frequency() const
{
return static_cast(m_frequency);
}
void Clock::setFrequency(const float freq)
{
if (qFuzzyIsNull(freq)) {
return;
}
std::chrono::duration auxInterval = 1s / (2 * freq);
if (auxInterval.count() <= 0) {
return;
}
m_interval = auxInterval;
m_frequency = static_cast(freq);
m_timePoint = std::chrono::steady_clock::now();
m_reset = true;
}
void Clock::resetClock()
{
setOn();
m_timePoint = std::chrono::steady_clock::now();
m_reset = false;
}
QString Clock::genericProperties()
{
return QString::number(frequency()) + " Hz";
}
void Clock::setSkin(const bool defaultSkin, const QString &fileName)
{
if (defaultSkin) {
m_alternativeSkins = m_defaultSkins;
} else {
m_alternativeSkins[static_cast(m_isOn)] = fileName;
}
m_usingDefaultSkin = defaultSkin;
setPixmap(static_cast(m_isOn));
}
wiRedPanda-4.1.12/app/element/clock.h 0000664 0000000 0000000 00000002113 14440202064 0017263 0 ustar 00root root 0000000 0000000 // Copyright 2015 - 2022, GIBIS-UNIFESP and the WiRedPanda contributors
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "graphicelementinput.h"
class Clock : public GraphicElementInput
{
Q_OBJECT
public:
explicit Clock(QGraphicsItem *parent = nullptr);
QString genericProperties() override;
bool isOn(const int port = 0) const override;
float frequency() const override;
void load(QDataStream &stream, QMap &portMap, const QVersionNumber version) override;
void resetClock();
void save(QDataStream &stream) const override;
void setFrequency(const float freq) override;
void setOff() override;
void setOn() override;
void setOn(const bool value, const int port = 0) override;
void setSkin(const bool defaultSkin, const QString &fileName) override;
void updateClock();
private:
bool m_isOn = false;
bool m_reset = true;
double m_frequency = 0;
std::chrono::duration m_interval{};
std::chrono::steady_clock::time_point m_timePoint;
};
Q_DECLARE_METATYPE(Clock)
wiRedPanda-4.1.12/app/element/demux.cpp 0000664 0000000 0000000 00000001676 14440202064 0017662 0 ustar 00root root 0000000 0000000 // Copyright 2015 - 2022, GIBIS-UNIFESP and the WiRedPanda contributors
// SPDX-License-Identifier: GPL-3.0-or-later
#include "demux.h"
#include "globalproperties.h"
#include "qneport.h"
namespace
{
int id = qRegisterMetaType();
}
Demux::Demux(QGraphicsItem *parent)
: GraphicElement(ElementType::Demux, ElementGroup::Mux, ":/basic/demux.svg", tr("DEMULTIPLEXER"), tr("Demux"), 2, 2, 2, 2, parent)
{
if (GlobalProperties::skipInit) {
return;
}
m_defaultSkins << m_pixmapPath;
m_alternativeSkins = m_defaultSkins;
setPixmap(0);
setCanChangeSkin(true);
Demux::updatePortsProperties();
}
void Demux::updatePortsProperties()
{
inputPort(0)->setPos(16, 32); inputPort(0)->setName("In");
inputPort(1)->setPos(32, 56); inputPort(1)->setName("S");
outputPort(0)->setPos(48, 16); outputPort(0)->setName("Out0");
outputPort(1)->setPos(48, 48); outputPort(1)->setName("Out1");
}
wiRedPanda-4.1.12/app/element/demux.h 0000664 0000000 0000000 00000000534 14440202064 0017317 0 ustar 00root root 0000000 0000000 // Copyright 2015 - 2022, GIBIS-UNIFESP and the WiRedPanda contributors
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "graphicelement.h"
class Demux : public GraphicElement
{
Q_OBJECT
public:
explicit Demux(QGraphicsItem *parent = nullptr);
void updatePortsProperties() override;
};
Q_DECLARE_METATYPE(Demux)
wiRedPanda-4.1.12/app/element/dflipflop.cpp 0000664 0000000 0000000 00000002756 14440202064 0020517 0 ustar 00root root 0000000 0000000 // Copyright 2015 - 2022, GIBIS-UNIFESP and the WiRedPanda contributors
// SPDX-License-Identifier: GPL-3.0-or-later
#include "dflipflop.h"
#include "globalproperties.h"
#include "qneport.h"
namespace
{
int id = qRegisterMetaType();
}
DFlipFlop::DFlipFlop(QGraphicsItem *parent)
: GraphicElement(ElementType::DFlipFlop, ElementGroup::Memory, pixmapPath(), tr("D-FLIPFLOP"), tr("D-FlipFlop"), 4, 4, 2, 2, parent)
{
if (GlobalProperties::skipInit) {
return;
}
m_defaultSkins << m_pixmapPath;
m_alternativeSkins = m_defaultSkins;
setPixmap(0);
setCanChangeSkin(true);
DFlipFlop::updatePortsProperties();
}
void DFlipFlop::updatePortsProperties()
{
inputPort(0)->setPos( 0, 16); inputPort(0)->setName("Data");
inputPort(1)->setPos( 0, 48); inputPort(1)->setName("Clock");
inputPort(2)->setPos(32, 0); inputPort(2)->setName("~Preset");
inputPort(3)->setPos(32, 64); inputPort(3)->setName("~Clear");
outputPort(0)->setPos(64, 16); outputPort(0)->setName("Q");
outputPort(1)->setPos(64, 48); outputPort(1)->setName("~Q");
inputPort(2)->setRequired(false);
inputPort(3)->setRequired(false);
inputPort(2)->setDefaultStatus(Status::Active);
inputPort(3)->setDefaultStatus(Status::Active);
outputPort(0)->setDefaultStatus(Status::Inactive);
outputPort(1)->setDefaultStatus(Status::Active);
}
void DFlipFlop::updateTheme()
{
setPixmap(pixmapPath());
GraphicElement::updateTheme();
}
wiRedPanda-4.1.12/app/element/dflipflop.h 0000664 0000000 0000000 00000001034 14440202064 0020150 0 ustar 00root root 0000000 0000000 // Copyright 2015 - 2022, GIBIS-UNIFESP and the WiRedPanda contributors
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "graphicelement.h"
#include "thememanager.h"
class DFlipFlop : public GraphicElement
{
Q_OBJECT
public:
explicit DFlipFlop(QGraphicsItem *parent = nullptr);
static QString pixmapPath()
{
return ":/memory/" + ThemeManager::themePath() + "/D-flipflop.svg";
}
void updatePortsProperties() override;
void updateTheme() override;
};
Q_DECLARE_METATYPE(DFlipFlop)
wiRedPanda-4.1.12/app/element/display_14.cpp 0000664 0000000 0000000 00000016321 14440202064 0020502 0 ustar 00root root 0000000 0000000 // Copyright 2015 - 2022, GIBIS-UNIFESP and the WiRedPanda contributors
// SPDX-License-Identifier: GPL-3.0-or-later
#include "display_14.h"
#include "display_7.h"
#include "globalproperties.h"
#include "qneport.h"
#include
namespace
{
int id = qRegisterMetaType();
}
Display14::Display14(QGraphicsItem *parent)
: GraphicElement(ElementType::Display14, ElementGroup::Output, ":/output/counter/counter_14_on.svg", tr("14-SEGMENT DISPLAY"), tr("14-Segment Display"), 15, 15, 0, 0, parent)
{
if (GlobalProperties::skipInit) {
return;
}
m_defaultSkins = QStringList{
":/output/counter/counter_14_off.svg",
":/output/counter/counter_a.svg",
":/output/counter/counter_b.svg",
":/output/counter/counter_c.svg",
":/output/counter/counter_d.svg",
":/output/counter/counter_e.svg",
":/output/counter/counter_f.svg",
":/output/counter/counter_g1.svg",
":/output/counter/counter_g2.svg",
":/output/counter/counter_h.svg",
":/output/counter/counter_j.svg",
":/output/counter/counter_k.svg",
":/output/counter/counter_l.svg",
":/output/counter/counter_m.svg",
":/output/counter/counter_n.svg",
":/output/counter/counter_dp.svg",
};
m_alternativeSkins = m_defaultSkins;
setPixmap(0);
a = QVector(5, m_defaultSkins.at(1));
b = QVector(5, m_defaultSkins.at(2));
c = QVector(5, m_defaultSkins.at(3));
d = QVector(5, m_defaultSkins.at(4));
e = QVector(5, m_defaultSkins.at(5));
f = QVector(5, m_defaultSkins.at(6));
g1 = QVector(5, m_defaultSkins.at(7));
g2 = QVector(5, m_defaultSkins.at(8));
h = QVector(5, m_defaultSkins.at(9));
j = QVector(5, m_defaultSkins.at(10));
k = QVector(5, m_defaultSkins.at(11));
l = QVector(5, m_defaultSkins.at(12));
m = QVector(5, m_defaultSkins.at(13));
n = QVector(5, m_defaultSkins.at(14));
dp = QVector(5, m_defaultSkins.at(15));
Display7::convertAllColors(a);
Display7::convertAllColors(b);
Display7::convertAllColors(c);
Display7::convertAllColors(d);
Display7::convertAllColors(e);
Display7::convertAllColors(f);
Display7::convertAllColors(g1);
Display7::convertAllColors(g2);
Display7::convertAllColors(h);
Display7::convertAllColors(j);
Display7::convertAllColors(k);
Display7::convertAllColors(l);
Display7::convertAllColors(m);
Display7::convertAllColors(n);
Display7::convertAllColors(dp);
setCanChangeSkin(true);
setHasColors(true);
setHasLabel(true);
setRotatable(false);
Display14::updatePortsProperties();
}
void Display14::refresh()
{
update();
}
void Display14::updatePortsProperties()
{
inputPort( 0)->setPos( 0, -8); inputPort(0)->setName("G1 (" + tr("middle left") + ")");
inputPort( 1)->setPos( 0, 8); inputPort(1)->setName("F (" + tr("upper left") + ")");
inputPort( 2)->setPos( 0, 24); inputPort(2)->setName("E (" + tr("lower left") + ")");
inputPort( 3)->setPos( 0, 40); inputPort(3)->setName("D (" + tr("bottom") + ")");
inputPort( 4)->setPos(64, -8); inputPort(4)->setName("A (" + tr("top") + ")");
inputPort( 5)->setPos(64, 8); inputPort(5)->setName("B (" + tr("upper right") + ")");
inputPort( 6)->setPos(64, 24); inputPort(6)->setName("DP (" + tr("dot") + ")");
inputPort( 7)->setPos(64, 40); inputPort(7)->setName("C (" + tr("lower right") + ")");
inputPort( 8)->setPos( 0, 56); inputPort(8)->setName("G2 (" + tr("middle right") + ")");
inputPort( 9)->setPos( 0, 72); inputPort(9)->setName("H (" + tr("middle upper left") + ")");
inputPort(10)->setPos( 0, 88); inputPort(10)->setName("J (" + tr("middle top") + ")");
inputPort(11)->setPos(64, 56); inputPort(11)->setName("K (" + tr("middle upper right") + ")");
inputPort(12)->setPos(64, 72); inputPort(12)->setName("L (" + tr("middle lower right") + ")");
inputPort(13)->setPos(64, 88); inputPort(13)->setName("M (" + tr("middle bottom") + ")");
inputPort(14)->setPos(64, 104); inputPort(14)->setName("N (" + tr("middle lower left") + ")");
for (auto *port : qAsConst(m_inputPorts)) {
port->setRequired(false);
port->setDefaultStatus(Status::Inactive);
}
}
void Display14::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
GraphicElement::paint(painter, option, widget);
if (inputPort(0)->status() == Status::Active) { painter->drawPixmap(0, 0, g1.at(m_colorNumber)); }
if (inputPort(1)->status() == Status::Active) { painter->drawPixmap(0, 0, f.at(m_colorNumber)); }
if (inputPort(2)->status() == Status::Active) { painter->drawPixmap(0, 0, e.at(m_colorNumber)); }
if (inputPort(3)->status() == Status::Active) { painter->drawPixmap(0, 0, d.at(m_colorNumber)); }
if (inputPort(4)->status() == Status::Active) { painter->drawPixmap(0, 0, a.at(m_colorNumber)); }
if (inputPort(5)->status() == Status::Active) { painter->drawPixmap(0, 0, b.at(m_colorNumber)); }
if (inputPort(6)->status() == Status::Active) { painter->drawPixmap(0, 0, dp.at(m_colorNumber)); }
if (inputPort(7)->status() == Status::Active) { painter->drawPixmap(0, 0, c.at(m_colorNumber)); }
if (inputPort(8)->status() == Status::Active) { painter->drawPixmap(0, 0, g2.at(m_colorNumber)); }
if (inputPort(9)->status() == Status::Active) { painter->drawPixmap(0, 0, h.at(m_colorNumber)); }
if (inputPort(10)->status() == Status::Active) { painter->drawPixmap(0, 0, j.at(m_colorNumber)); }
if (inputPort(11)->status() == Status::Active) { painter->drawPixmap(0, 0, k.at(m_colorNumber)); }
if (inputPort(12)->status() == Status::Active) { painter->drawPixmap(0, 0, l.at(m_colorNumber)); }
if (inputPort(13)->status() == Status::Active) { painter->drawPixmap(0, 0, m.at(m_colorNumber)); }
if (inputPort(14)->status() == Status::Active) { painter->drawPixmap(0, 0, n.at(m_colorNumber)); }
}
void Display14::setColor(const QString &color)
{
m_color = color;
if (color == "White") { m_colorNumber = 0; }
if (color == "Red") { m_colorNumber = 1; }
if (color == "Green") { m_colorNumber = 2; }
if (color == "Blue") { m_colorNumber = 3; }
if (color == "Purple") { m_colorNumber = 4; }
}
QString Display14::color() const
{
return m_color;
}
void Display14::save(QDataStream &stream) const
{
GraphicElement::save(stream);
QMap map;
map.insert("color", color());
stream << map;
}
void Display14::load(QDataStream &stream, QMap &portMap, const QVersionNumber version)
{
GraphicElement::load(stream, portMap, version);
if ((VERSION("3.1") <= version) && (version < VERSION("4.1"))) {
QString color_; stream >> color_;
setColor(color_);
}
if (version >= VERSION("4.1")) {
QMap map; stream >> map;
if (map.contains("color")) {
setColor(map.value("color").toString());
}
}
}
wiRedPanda-4.1.12/app/element/display_14.h 0000664 0000000 0000000 00000001555 14440202064 0020152 0 ustar 00root root 0000000 0000000 // Copyright 2015 - 2022, GIBIS-UNIFESP and the WiRedPanda contributors
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "graphicelement.h"
class Display14 : public GraphicElement
{
Q_OBJECT
public:
explicit Display14(QGraphicsItem *parent = nullptr);
QString color() const override;
void load(QDataStream &stream, QMap &portMap, const QVersionNumber version) override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
void refresh() override;
void save(QDataStream &stream) const override;
void setColor(const QString &color) override;
void updatePortsProperties() override;
private:
QString m_color = "Red";
QVector bkg, a, b, c, d, e, f, g1, g2, h, j, k, l, m, n, dp;
int m_colorNumber = 1;
};
Q_DECLARE_METATYPE(Display14)
wiRedPanda-4.1.12/app/element/display_7.cpp 0000664 0000000 0000000 00000015207 14440202064 0020426 0 ustar 00root root 0000000 0000000 // Copyright 2015 - 2022, GIBIS-UNIFESP and the WiRedPanda contributors
// SPDX-License-Identifier: GPL-3.0-or-later
#include "display_7.h"
#include "common.h"
#include "globalproperties.h"
#include "qneport.h"
#include
#include
namespace
{
int id = qRegisterMetaType();
}
Display7::Display7(QGraphicsItem *parent)
: GraphicElement(ElementType::Display7, ElementGroup::Output, ":/output/counter/counter_on.svg", tr("7-SEGMENT DISPLAY"), tr("7-Segment Display"), 8, 8, 0, 0, parent)
{
if (GlobalProperties::skipInit) {
return;
}
m_defaultSkins = QStringList{
":/output/counter/counter_off.svg",
":/output/counter/counter_a.svg",
":/output/counter/counter_b.svg",
":/output/counter/counter_c.svg",
":/output/counter/counter_d.svg",
":/output/counter/counter_e.svg",
":/output/counter/counter_f.svg",
":/output/counter/counter_g.svg",
":/output/counter/counter_dp.svg",
};
m_alternativeSkins = m_defaultSkins;
setPixmap(0);
qCDebug(three) << tr("Allocating pixmaps.");
a = QVector(5, m_defaultSkins.at(1));
b = QVector(5, m_defaultSkins.at(2));
c = QVector(5, m_defaultSkins.at(3));
d = QVector(5, m_defaultSkins.at(4));
e = QVector(5, m_defaultSkins.at(5));
f = QVector(5, m_defaultSkins.at(6));
g = QVector(5, m_defaultSkins.at(7));
dp = QVector(5, m_defaultSkins.at(8));
qCDebug(three) << tr("Converting segments to other colors.");
convertAllColors(a);
convertAllColors(b);
convertAllColors(c);
convertAllColors(d);
convertAllColors(e);
convertAllColors(f);
convertAllColors(g);
convertAllColors(dp);
setCanChangeSkin(true);
setHasColors(true);
setHasLabel(true);
setRotatable(false);
Display7::updatePortsProperties();
}
void Display7::convertAllColors(QVector &pixmaps)
{
QImage tmp(pixmaps.at(0).toImage());
pixmaps[0] = convertColor(tmp, true, true, true);
pixmaps[1] = convertColor(tmp, true, false, false);
pixmaps[2] = convertColor(tmp, false, true, false);
pixmaps[3] = convertColor(tmp, false, false, true);
pixmaps[4] = convertColor(tmp, true, false, true);
}
QPixmap Display7::convertColor(const QImage &source, const bool red, const bool green, const bool blue)
{
QImage target(source);
for (int y = 0; y < target.height(); ++y) {
QRgb *line = reinterpret_cast(target.scanLine(y));
for (int x = 0; x < target.width(); ++x) {
QRgb &rgb = line[x];
const int value = qRed(rgb);
rgb = qRgba(red ? value : 0,
green ? value : 0,
blue ? value : 0,
value);
}
}
return QPixmap::fromImage(target);
}
void Display7::refresh()
{
update();
}
void Display7::updatePortsProperties()
{
inputPort(0)->setPos( 0, 8); inputPort(0)->setName("G (" + tr("middle") + ")");
inputPort(1)->setPos( 0, 24); inputPort(1)->setName("F (" + tr("upper left") + ")");
inputPort(2)->setPos( 0, 40); inputPort(2)->setName("E (" + tr("lower left") + ")");
inputPort(3)->setPos( 0, 56); inputPort(3)->setName("D (" + tr("bottom") + ")");
inputPort(4)->setPos(64, 8); inputPort(4)->setName("A (" + tr("top") + ")");
inputPort(5)->setPos(64, 24); inputPort(5)->setName("B (" + tr("upper right") + ")");
inputPort(6)->setPos(64, 40); inputPort(6)->setName("DP (" + tr("dot") + ")");
inputPort(7)->setPos(64, 56); inputPort(7)->setName("C (" + tr("lower right") + ")");
for (auto *in : qAsConst(m_inputPorts)) {
in->setRequired(false);
in->setDefaultStatus(Status::Inactive);
}
}
void Display7::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
GraphicElement::paint(painter, option, widget);
if (inputPort(0)->status() == Status::Active) { painter->drawPixmap(0, 0, g.at(m_colorNumber)); }
if (inputPort(1)->status() == Status::Active) { painter->drawPixmap(0, 0, f.at(m_colorNumber)); }
if (inputPort(2)->status() == Status::Active) { painter->drawPixmap(0, 0, e.at(m_colorNumber)); }
if (inputPort(3)->status() == Status::Active) { painter->drawPixmap(0, 0, d.at(m_colorNumber)); }
if (inputPort(4)->status() == Status::Active) { painter->drawPixmap(0, 0, a.at(m_colorNumber)); }
if (inputPort(5)->status() == Status::Active) { painter->drawPixmap(0, 0, b.at(m_colorNumber)); }
if (inputPort(6)->status() == Status::Active) { painter->drawPixmap(0, 0, dp.at(m_colorNumber)); }
if (inputPort(7)->status() == Status::Active) { painter->drawPixmap(0, 0, c.at(m_colorNumber)); }
}
void Display7::setColor(const QString &color)
{
m_color = color;
if (color == "White") { m_colorNumber = 0; }
if (color == "Red") { m_colorNumber = 1; }
if (color == "Green") { m_colorNumber = 2; }
if (color == "Blue") { m_colorNumber = 3; }
if (color == "Purple") { m_colorNumber = 4; }
}
QString Display7::color() const
{
return m_color;
}
void Display7::save(QDataStream &stream) const
{
GraphicElement::save(stream);
QMap map;
map.insert("color", color());
stream << map;
}
void Display7::load(QDataStream &stream, QMap