Work on text drawing
MODIFY
.gitignore
.gitignore
*.user
*.stash
+*.autosave
*.o
Makefile

MODIFY
src/graphics/connection.h
src/graphics/connection.h
@@ -13,7 +13,6 @@ enum class ValueDrawPos { Source, Middle, Destination };
pipeline view.
*/
class Connection : public QGraphicsItem {
-
public:
Connection(Shape *source, Shape *dest);
void setValueDrawPos(ValueDrawPos pos) { m_valuePos = pos, update(); }
@@ -35,6 +34,10 @@ private:
Shape *m_source;
Shape *m_dest;
+ // A list of IO points, which all connect to this widget -
+ // used to form attachment points to this connection
+ QList<QPointF *> m_connectsToThis;
+
// Variables related to the current value of the connection (signal value)
bool m_showValue = false;
int m_value;

MODIFY
src/graphics/pipelinewidget.cpp
src/graphics/pipelinewidget.cpp
PipelineWidget::PipelineWidget(QWidget* parent) : QGraphicsView(parent) {
QGraphicsScene* scene = new QGraphicsScene(this);
- scene->setSceneRect(-200, -200, 400, 400);
scene->setItemIndexMethod(QGraphicsScene::NoIndex);
setScene(scene);
setCacheMode(CacheBackground);
setRenderHint(QPainter::Antialiasing);
+ setRenderHint(QPainter::TextAntialiasing);
setDragMode(QGraphicsView::ScrollHandDrag);
- // Create pipeline objects
- Graphics::Shape* instr_mem = new Graphics::Shape();
- instr_mem->addInput(QStringList() << "Read\nregister 1"
+ // ------------ Create pipeline objects ---------------
+ // Instruction memory
+ Graphics::Shape* registers =
+ new Graphics::Shape(Graphics::ShapeType::Block, 15, 15);
+ registers->addInput(QStringList() << "Read\nregister 1"
<< "Read\nregister 2"
<< "Write\nregister"
<< "Write\ndata");
- instr_mem->addOutput(QStringList() << "Read\ndata 1"
+ registers->addOutput(QStringList() << "Read\ndata 1"
<< "Read\ndata 2");
- instr_mem->setName("Registers");
+ registers->setName("Registers");
+
+ // Data memory
+ Graphics::Shape* data_mem =
+ new Graphics::Shape(Graphics::ShapeType::Block, 50, 5);
+ data_mem->addInput(QStringList() << "Address"
+ << "Write\ndata");
+ data_mem->addOutput(QStringList() << "Read\ndata");
+ data_mem->setName("Data\nmemory");
+
+ // Instruction memory
+ Graphics::Shape* instr_mem =
+ new Graphics::Shape(Graphics::ShapeType::Block, 50, 5);
+ instr_mem->addInput(QStringList() << "Address");
+ instr_mem->addOutput(QStringList() << "Instruction");
+ instr_mem->setName("Instruction\nmemory");
+
+ // PC
+ Graphics::Shape* pc =
+ new Graphics::Shape(Graphics::ShapeType::Block, 30, 3);
+ pc->setName("PC");
// Add pipeline objects to graphics scene
+ scene->addItem(registers);
+ scene->addItem(data_mem);
scene->addItem(instr_mem);
+ scene->addItem(pc);
// Set item positions
- instr_mem->setPos(0, 0);
+ pc->setPos(-250, -100);
+ instr_mem->setPos(-200, 0);
+ registers->setPos(0, 0);
+ data_mem->setPos(200, 0);
}

MODIFY
src/graphics/shape.cpp
src/graphics/shape.cpp
namespace Graphics {
-Shape::Shape() { setCacheMode(DeviceCoordinateCache); }
+Shape::Shape(ShapeType type, int verticalPad, int horizontalPad)
+ : m_verticalPad(verticalPad), m_horizontalPad(horizontalPad), m_type(type) {
+ setCacheMode(DeviceCoordinateCache);
+}
QRectF Shape::boundingRect() const {
if (m_type == ShapeType::Block) {
@@ -12,49 +15,110 @@ QRectF Shape::boundingRect() const {
}
return QRectF();
}
+void Shape::addInput(QString input) { m_inputs.append(input); }
+void Shape::addInput(QStringList inputs) {
+ for (const auto &input : inputs) {
+ addInput(input);
+ }
+}
QRectF Shape::calculateRect() const {
auto fontMetricsObject = QFontMetrics(QFont());
auto nameRect = fontMetricsObject.boundingRect(m_name);
- // Base height on largest number of IO nodes
- int height = m_inputs.size() * nodeHeight;
- height = (m_outputs.size() * nodeHeight > height)
- ? m_outputs.size() * nodeHeight
- : height;
- height += 10 + nameRect.height(); // add padding and height of the name
-
// Get size of the largest left and right IO descriptors
int leftIOsize = 0;
int rightIOsize = 0;
+ int leftHeight = 0;
+ // Iterate over left and right IO descriptors, sum up their heights, and get
+ // the largest width of a descriptor
for (const auto &input : m_inputs) {
- int width = fontMetricsObject.boundingRect(input).width();
+ auto textRect = fontMetricsObject.boundingRect(
+ QRect(0, 0, 200, 200), 0,
+ input); // create a rect large enough to not obstruct the text rect
+ leftHeight += textRect.height();
+ int width = textRect.width();
if (width > leftIOsize) leftIOsize = width;
}
+ // calculate seperate left and right IO descriptor height, and select the
+ // largest
+ int rightHeight = 0;
for (const auto &output : m_outputs) {
- int width = fontMetricsObject.boundingRect(output).width();
+ QRect textRect = fontMetricsObject.boundingRect(
+ QRect(0, 0, 200, 200), 0,
+ output); // create a rect large enough to not obstruct the text rect
+ rightHeight += textRect.height();
+ int width = textRect.width();
if (width > rightIOsize) rightIOsize = width;
}
- int width = nameRect.width() + leftIOsize + rightIOsize +
- 10; // sum up text widths and add some padding
+ // sum up the widths and heights, and add padding
+ int width = nameRect.width() + leftIOsize + rightIOsize + m_horizontalPad +
+ 2 * sidePadding;
+ int height = leftHeight > rightHeight ? leftHeight : rightHeight;
+ height += nameRect.height() + m_verticalPad;
return QRectF(-(width / 2), -(height / 2), width, height);
}
void Shape::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
- QWidget *widget) {
+ QWidget *) {
+ auto boundingRect = calculateRect();
+
switch (m_type) {
case ShapeType::Block: {
- painter->setPen(QPen(Qt::black, 2));
- painter->drawRect(calculateRect());
+ painter->setPen(QPen(Qt::black, 1));
+ painter->drawRect(boundingRect);
} break;
case ShapeType::ALU: {
} break;
case ShapeType::MUX: {
} break;
}
+
+ // Translate text in relation to the bounding rectangle, and draw text
+ QFont font;
+ font.setPointSize(nameFontSize);
+ font.setBold(true);
+ auto fontMetricsObject = QFontMetrics(font);
+ QRectF textRect =
+ fontMetricsObject.boundingRect(QRect(0, 0, 200, 200), 0, m_name);
+ textRect.moveTo(0, 0);
+ textRect.translate(-textRect.width() / 2,
+ -textRect.height() / 2); // center text rect
+ painter->setFont(font);
+ painter->drawText(textRect, m_name);
+
+ // Iterate through node descriptors and draw text
+ font.setPointSize(ioFontSize);
+ font.setBold(false);
+ fontMetricsObject =
+ QFontMetrics(font); // update fontMetrics object to new font
+ painter->setFont(font);
+
+ // Inputs
+ QPointF top = boundingRect.topLeft();
+ for (const auto &input : m_inputs) {
+ textRect =
+ fontMetricsObject.boundingRect(QRect(0, 0, 200, 200), 0, input);
+ textRect.moveTo(top);
+ textRect.translate(sidePadding, 0); // move text away from side
+ painter->drawText(textRect, input);
+ top.setY(top.y() + textRect.height() + nodePadding);
+ }
+
+ // Outputs
+ top = boundingRect.topRight();
+ for (const auto &output : m_outputs) {
+ textRect =
+ fontMetricsObject.boundingRect(QRect(0, 0, 200, 200), 0, output);
+ textRect.moveTo(top);
+ textRect.translate(-textRect.width(), 0);
+ textRect.translate(-sidePadding, 0); // Move text away from side
+ painter->drawText(textRect, output);
+ top.setY(top.y() + textRect.height() + nodePadding);
+ }
}
} // namespace Graphics

MODIFY
src/graphics/shape.h
src/graphics/shape.h
#include <QPen>
namespace Graphics {
-
enum class ShapeType { Block, ALU, MUX };
class Shape : public QGraphicsItem {
public:
- Shape();
+ Shape(ShapeType type = ShapeType::Block, int verticalPad = 0,
+ int horizontalPad = 0);
QRectF boundingRect() const;
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option,
QWidget* widget);
- void addInput(QString input) { m_inputs.append(input); }
+ void addInput(QString input);
void addInput(QStringList input) { m_inputs.append(input); }
- void addOutput(QString output) { m_inputs.append(output); }
- void addOutput(QStringList output) { m_inputs.append(output); }
+ void addOutput(QString output) { m_outputs.append(output); }
+ void addOutput(QStringList output) { m_outputs.append(output); }
void setName(QString name) { m_name = name; }
private:
QRectF calculateRect() const;
- ShapeType m_type = ShapeType::Block;
+ ShapeType m_type;
QString m_name;
+ // Extra size that is added onto each dimension of the shape.
+ // Used to fine-tune the shape of the widget
+ int m_verticalPad;
+ int m_horizontalPad;
+
QList<QString> m_inputs;
QList<QString> m_outputs;
// drawing constants
- qreal nodeHeight = 10;
- qreal nameFontSize = 14;
- qreal ioFontSize = 10;
+ qreal nodeHeight = 20;
+ qreal nameFontSize = 10;
+ qreal ioFontSize = 8;
+ qreal nodePadding = 5; // padding between each text descriptor for a node
+ qreal sidePadding =
+ 3; // padding between an IO description and the side of the shape
};
} // namespace Graphics

Work on text drawing