Subversion Repositories Code-Repo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
335 Kevin 1
#include "Wire.h"
2
 
3
Wire::Wire(QGraphicsItem *parent) :
4
    QGraphicsObject(parent)
5
{
6
    setFlags(ItemIsSelectable);
7
 
8
    createActions();
9
 
10
    this->auxSelected = false;
11
    this->showValues = true;
12
 
13
    // Create the default pens to draw with
14
    this->defaultPen = QPen(QColor(COLOR_MAIN), DEFAULT_LINE_WIDTH, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
15
    this->defaultBrush = QBrush(Qt::NoBrush);
16
    this->selectedPen = QPen(QColor(COLOR_MAIN_SELECTED), DEFAULT_LINE_WIDTH, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
17
    this->highlightedPen = QPen(QColor(COLOR_MAIN_SELECTED), DEFAULT_LINE_WIDTH, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
18
    this->defaultFont = QFont("Consolas", 20);
19
 
20
    this->wireValue = logicValue_X;
21
    this->wireFaultyValue = logicValue_X;
22
    this->valueString = "X/X";
23
 
24
#ifdef _DEBUG
25
    this->debugPen = QPen(QColor(COLOR_DEBUG), 1, Qt::DashLine);
26
    this->debugBrush = QBrush(Qt::NoBrush);
27
    this->debugSelectedPen = QPen(QColor(COLOR_DEBUG_SELECTED), 1, Qt::DashLine);
28
    this->debugErrorPen = QPen(QColor(COLOR_DEBUG_ERROR), 2, Qt::DashLine);
29
#endif
30
}
31
 
32
Wire::~Wire()
33
{
34
 
35
}
36
 
37
QRectF Wire::boundingRect() const
38
{
39
    QMargins margin(SELECTION_WIDTH, SELECTION_WIDTH, SELECTION_WIDTH, SELECTION_WIDTH);
40
    return bRect + margin;
41
}
42
 
43
QPainterPath Wire::shape() const
44
{
45
    return shapeArea;
46
}
47
 
48
void Wire::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
49
{
50
    Q_UNUSED(widget);
51
    Q_UNUSED(option);
52
 
53
#ifdef _DEBUG
54
    painter->save();
55
    painter->setPen((auxSelected) ? debugSelectedPen : debugPen);
56
    painter->setBrush(debugBrush);
57
    painter->drawRect(this->boundingRect());
58
    painter->drawPath(shapeArea);
59
    painter->restore();
60
#endif
61
 
62
    // Set line color accordingly
63
    if (auxSelected) painter->setPen(highlightedPen);
64
    else painter->setPen(defaultPen);
65
    painter->setBrush(defaultBrush);
66
 
67
    // Draw the line
68
    painter->drawPath(line);
69
 
70
    QPainterPath textBox;
71
    textBox.addText(0, 0, defaultFont, valueString);
72
 
73
    // Draw the text (wire value)
74
    if (showValues) {
75
        QPainterPath text;
76
        text.addText(bRect.center().x() - (textBox.boundingRect().width() / 2),
77
                     bRect.center().y() + (textBox.boundingRect().height() / 2) - 2,
78
                     defaultFont, valueString);
79
 
80
        QPainterPathStroker stroker;
81
        stroker.setCapStyle(Qt::RoundCap);
82
        stroker.setJoinStyle(Qt::RoundJoin);
83
        stroker.setWidth(10);
84
        QPainterPath textOutline = stroker.createStroke(text);
85
        painter->save();
86
        painter->setPen(QPen(Qt::white));
87
        painter->setBrush(QBrush(Qt::white));
88
        painter->drawPath(textOutline);
89
        painter->restore();
90
 
91
        painter->drawPath(text);
92
    }
93
}
94
 
95
/**
96
 * Draw line from given point to point
97
 */
98
void Wire::setPoints(Gate_BASE *source, Gate_BASE *sink, int sinkID)
99
{
100
    this->gateOutput = source;
101
    this->gateInput = sink;
102
    this->gateInputID = sinkID;
103
 
104
    // Calculate the bounding box of this line (normalized)
105
    bRect = QRectF(gateOutput->gateOutputPoint, gateInput->gateInputPoints[gateInputID]).normalized();
106
 
107
    // Move box to center of object
108
    QPointF center = bRect.center();
109
    bRect.translate(- center.x(), - center.y());
110
 
111
    // Calculate new I/O points in local coordinates
112
    QPointF tOutput = gateOutput->gateOutputPoint - center;
113
    QPointF tInput = gateInput->gateInputPoints[gateInputID] - center;
114
 
115
    // Draw the line
116
    linePoints.append(tOutput);
117
    linePoints.append(QPointF(bRect.center().x(), tOutput.y()));
118
    linePoints.append(QPointF(bRect.center().x(), tInput.y()));
119
    linePoints.append(tInput);
120
    line.moveTo(linePoints[0]);
121
    for (int i = 1; i < linePoints.size(); i++) {
122
        line.lineTo(linePoints[i]);
123
    }
124
 
125
    // Stroke the line to allow for selection
126
    QPainterPathStroker stroke;
127
    stroke.setWidth(SELECTION_WIDTH);
128
    shapeArea = stroke.createStroke(line);
129
 
130
    // Move wire on canvas to proper location
131
    this->setPos(center.x(), center.y());
132
    prepareGeometryChange();
133
}
134
 
135
/**
136
 * Sets the color of the pen drawing the line
137
 */
138
void Wire::setPenColor(QColor color)
139
{
140
    this->defaultPen.setColor(color);
141
}
142
 
143
/**
144
 * Sets the highlight color when wire is selected
145
 */
146
void Wire::setHighlight(bool state, QColor color)
147
{
148
    auxSelected = state;
149
    if (state) {
150
        highlightedPen.setColor(color);
151
        setZValue(SELECTED_Z);
152
    } else {
153
        setZValue(WIRE_DEFAULT_Z);
154
    }
155
    update();
156
}
157
 
158
/**
159
 * Resets the value of the wire to unknown 'X'
160
 */
161
void Wire::reset()
162
{
163
    setValue(logicValue_X, logicValue_X);
164
    update();
165
}
166
 
167
/**
168
 * Toggles if wire values should be shown
169
 */
170
void Wire::toggleShowValues()
171
{
172
    showValues = !showValues;
173
    update();
174
}
175
 
176
/**
177
 * Sets the value of the wire
178
 */
179
void Wire::setValue(logicValue value, logicValue faultyValue, bool recurse)
180
{
181
    wireValue = value;
182
    wireFaultyValue = faultyValue;
183
 
184
    // Compute the status string
185
    valueString = "";
186
    if (wireValue == logicValue_0) valueString += "0";
187
    else if (wireValue == logicValue_1) valueString += "1";
188
    else valueString += "X";
189
    valueString += "/";
190
    if (wireFaultyValue == logicValue_0) valueString += "0";
191
    else if (wireFaultyValue == logicValue_1) valueString += "1";
192
    else valueString += "X";
193
 
194
    // Propogate value to sink/source gates
195
    gateInput->setInputValue(gateInputID, wireValue, wireFaultyValue);
196
    gateInput->setOutputValue(wireValue, wireFaultyValue);
197
 
198
    // Propogate to gates if necessary
199
    if (recurse) {
200
        for (int i = 0; i < gateOutput->gateOutputWires.size(); i++) {
201
            gateOutput->gateOutputWires[i]->setValue(wireValue, wireFaultyValue, false);
202
        }
203
    }
204
 
205
    update();
206
}
207
 
208
void Wire::mousePressEvent(QGraphicsSceneMouseEvent *event)
209
{
210
    QString status = QString("Wire Source: Gate %1 | Sink: Gate %2 | Value: ").arg(gateOutput->gateID).arg(gateInput->gateID);
211
    status += valueString;
212
    emit updateStatus(status);
213
 
214
    // On selection, highlight sink and source gates
215
    setZValue(1);
216
    setHighlight(true, QColor(COLOR_MAIN_SELECTED));
217
    gateOutput->setHighlight(true, QColor(COLOR_OUTPUT_SELECTED));
218
    gateInput->setHighlight(true, QColor(COLOR_INPUT_SELECTED));
219
    event->accept();
220
}
221
 
222
void Wire::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
223
{
224
    QMenu menu;
225
    menu.addAction(injectValueAction);
226
    menu.addAction(injectFaultAction);
227
    menu.addAction(resetValuesAction);
228
    menu.exec(event->screenPos());
229
    event->accept();
230
}
231
 
232
void Wire::createActions()
233
{
234
    injectValueAction = new QAction("&Set Value", this);
235
    connect(injectValueAction, SIGNAL(triggered()), this, SLOT(promptValue()));
236
 
237
    injectFaultAction = new QAction("&Inject Fault", this);
238
    connect(injectFaultAction, SIGNAL(triggered()), this, SLOT(promptFaultyValue()));
239
 
240
    resetValuesAction = new QAction("&Reset Values", this);
241
    connect(resetValuesAction, SIGNAL(triggered()), this, SLOT(reset()));
242
}
243
 
244
void Wire::promptValue()
245
{
246
    bool ok;
247
    QStringList options;
248
    options << "0" << "1";
249
    QString sel = QInputDialog::getItem(0, "Choose Value", "Enter Value:", options, 0, false, &ok);
250
    if (ok && !sel.isEmpty()) {
251
        if (sel == "0") setValue(logicValue_0, logicValue_0);
252
        else if (sel == "1") setValue(logicValue_1, logicValue_1);
253
        else setValue(logicValue_X, logicValue_X);
254
    }
255
}
256
 
257
void Wire::promptFaultyValue()
258
{
259
    bool ok;
260
    QStringList options;
261
    options << "0" << "1";
262
    QString sel = QInputDialog::getItem(0, "Choose Value", "Enter Faulty Value:", options, 0, false, &ok);
263
    if (ok && !sel.isEmpty()) {
264
        if (sel == "0") setValue(logicValue_1, logicValue_0);
265
        else if (sel == "1") setValue(logicValue_0, logicValue_1);
266
        else setValue(logicValue_X, logicValue_X);
267
    }
268
}