Blame | Last modification | View Log | RSS feed
#include "Gate_BASE.h"
Gate_BASE::Gate_BASE(int gateID, gType gateType,
int numInputs, int gateLevel,
QGraphicsItem *parent) :
QGraphicsObject(parent)
{
setFlags(ItemIsSelectable);
auxSelected = false;
this->gateID = gateID;
this->gateType = gateType;
this->numInputs = numInputs;
this->gateLevel = gateLevel;
this->enqueued = false;
this->xSize = BASE_GATE_SIZE_X + ADDITONAL_INPUTS * qMax(numInputs, 1);
this->ySize = BASE_GATE_SIZE_Y + ADDITONAL_INPUTS * qMax(numInputs, 1);
// Create the default pens to draw with
this->defaultPen = QPen(QColor(COLOR_MAIN), DEFAULT_LINE_WIDTH, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
this->defaultBrush = QBrush(Qt::NoBrush);
this->defaultFont = QFont("Consolas", 20);
this->selectedPen = QPen(QColor(COLOR_MAIN_SELECTED), DEFAULT_LINE_WIDTH, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
this->highlightedPen = QPen(QColor(COLOR_MAIN_SELECTED), DEFAULT_LINE_WIDTH, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
// Calculate local and global points for inputs
float spacer = float(this->ySize - BORDER_OFFSET * 2) / (numInputs + 1);
for (int i = 0; i < numInputs; i++) {
QPointF point = QPointF(0, this->ySize - BORDER_OFFSET - (spacer * i + spacer));
this->inputPoints.push_back(point);
QPointF scenePoint = QPointF(this->scenePos().x(), this->scenePos().y() - BORDER_OFFSET - (spacer * i + spacer));
this->gateInputPoints.push_back(scenePoint);
}
// Output point will always be centered on the right edge
this->outputPoint = QPointF(this->xSize, this->ySize / 2);
this->gateOutputPoint = QPointF(this->scenePos().x() + this->xSize, this->scenePos().y() + this->ySize / 2);
// Reset I/O values to 'X'
for (int i = 0; i < numInputs; i++) {
inputValues.append(logicValue_X);
inputFaultyValues.append(logicValue_X);
}
outputValue = logicValue_X;
outputFaultyValue = logicValue_X;
#ifdef _DEBUG
this->debugPen = QPen(QColor(COLOR_DEBUG), 1, Qt::DashLine);
this->debugBrush = QBrush(Qt::NoBrush);
this->debugSelectedPen = QPen(QColor(COLOR_DEBUG_SELECTED), 1, Qt::DashLine);
this->debugErrorPen = QPen(QColor(COLOR_DEBUG_ERROR), 2, Qt::DashLine);
#endif
}
Gate_BASE::~Gate_BASE()
{
}
QRectF Gate_BASE::boundingRect() const
{
return QRectF(0, 0, xSize, ySize);
}
QPainterPath Gate_BASE::shape() const
{
QPainterPath path;
path.addRect(BORDER_OFFSET, BORDER_OFFSET, xSize - BORDER_OFFSET * 2, ySize - BORDER_OFFSET * 2);
return path;
}
/**
* Sets the position of this gate (centered) on the scene
*/
void Gate_BASE::setCanvasPosition(int x, int y)
{
canvasPoint.setX(x);
canvasPoint.setY(y);
// Canvas position correlates to the center of the gate
this->setPos(x - xSize / 2, y - ySize / 2);
// Calculate points for inputs
float spacer = float(this->ySize - BORDER_OFFSET * 2) / (numInputs + 1);
this->gateInputPoints.clear();
for (int i = 0; i < numInputs; i++) {
QPointF scenePoint = QPointF(this->scenePos().x(), this->scenePos().y() + BORDER_OFFSET + (spacer * i + spacer));
this->gateInputPoints.push_back(scenePoint);
}
// Output point will always be centered on the right edge
this->gateOutputPoint = QPointF(this->scenePos().x() + this->xSize, this->scenePos().y() + this->ySize / 2);
}
/**
* Sets the color of the drawing pen
*/
void Gate_BASE::setHighlight(bool state, QColor color)
{
auxSelected = state;
if (state) {
highlightedPen.setColor(color);
setZValue(SELECTED_Z);
} else {
setZValue(GATE_DEFAULT_Z);
}
update();
}
/**
* Resets the gate's value to unknown 'X'
*/
void Gate_BASE::reset()
{
// Reset I/O values to 'X'
for (int i = 0; i < numInputs; i++) {
inputValues[i] = logicValue_X;
inputFaultyValues[i] = logicValue_X;
}
outputValue = logicValue_X;
outputFaultyValue = logicValue_X;
// Reset connected wires
for (int i = 0; i < gateInputWires.size(); i++)
gateInputWires[i]->setValue(logicValue_X, logicValue_X, false);
for (int i = 0; i < gateOutputWires.size(); i++)
gateOutputWires[i]->setValue(logicValue_X, logicValue_X, false);
enqueued = false;
update();
}
/**
* Sets a specific input to this gate
*/
void Gate_BASE::setInputValue(int input, logicValue value, logicValue faultyValue)
{
// If the input has changed, queue this gate for simulation
if (inputValues[input] != value || inputFaultyValues[input] != faultyValue)
emit enqueueSim(this);
inputValues[input] = value;
inputFaultyValues[input] = faultyValue;
}
/**
* Sets the output value of this gate
*/
void Gate_BASE::setOutputValue(logicValue value, logicValue faultyValue)
{
outputValue = value;
outputFaultyValue = faultyValue;
}
/**
* Updates flag to indicate queued status
*/
void Gate_BASE::setEnqueued(bool value)
{
enqueued = value;
update();
}
void Gate_BASE::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
// Update status bar with information on this gate
QString status = QString("Gate %1 ").arg(gateID);
if (fanInGates.size() != 0)
status += "| Input Gates: ";
for (int i = 0; i < fanInGates.size(); i++) {
status += QString("%1 ").arg(fanInGates[i]->gateID);
if (inputValues[i] == logicValue_0) status += "(0/";
else if (inputValues[i] == logicValue_1) status += "(1/";
else status += "(X/";
if (inputFaultyValues[i] == logicValue_0) status += "0) ";
else if (inputFaultyValues[i] == logicValue_1) status += "1) ";
else status += "X) ";
}
if (fanOutGates.size() != 0) {
status += "| Output Gates: ";
for (int i = 0; i < fanOutGates.size(); i++)
status += QString("%1 ").arg(fanOutGates[i]->gateID);
if (outputValue == logicValue_0) status += "(0/";
else if (outputValue == logicValue_1) status += "(1/";
else status += "(X/";
if (outputFaultyValue == logicValue_0) status += "0) ";
else if (outputFaultyValue == logicValue_1) status += "1) ";
else status += "X) ";
}
emit updateStatus(status);
// On gate selection, highlight the input and output gates/wires
setZValue(1);
setHighlight(true, QColor(COLOR_MAIN_SELECTED));
for (int i = 0; i < fanInGates.size(); i++)
fanInGates[i]->setHighlight(true, QColor(COLOR_INPUT_SELECTED));
for (int i = 0; i < fanOutGates.size(); i++)
fanOutGates[i]->setHighlight(true, QColor(COLOR_OUTPUT_SELECTED));
for (int i = 0; i < gateInputWires.size(); i++)
gateInputWires[i]->setHighlight(true, QColor(COLOR_INPUT_SELECTED));
for (int i = 0; i < gateOutputWires.size(); i++)
gateOutputWires[i]->setHighlight(true, QColor(COLOR_OUTPUT_SELECTED));
event->accept();
}
/*
void Gate_BASE::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
{
QMenu menu;
menu.addAction(injectValueAction);
menu.exec(event->screenPos());
event->accept();
}
void Gate_BASE::createActions()
{
injectValueAction = new QAction("&Inject Value/Fault", this);
}
*/