A vector graphics editor built with C++17 and Qt6. Supports drawing, editing, and styling shapes on a canvas with undo/redo, clipboard operations, SVG import/export, and inline text editing.
All shape tools follow click-and-drag creation with a live transient preview:
- Rectangle and Rounded Rectangle
- Circle
- Line
- Hexagon (regular, 6 vertices computed from center + radius)
- Free Sketch (freehand polyline, records points during drag)
- Text (click to place, type inline, Enter/Escape to finish)
- Select Tool: Click a shape to select it (bounding box + resize handle shown).
- Move: Drag a selected shape's bounding box to reposition.
- Resize: Drag the bottom-right handle to scale.
- Clipboard: Right-click context menu with Cut, Copy, Paste, Delete.
- Stroke Width: SpinBox (1–20 px), applies to selected shape immediately.
- Stroke Color / Fill Color: QColorDialog pickers. Changes are undoable.
- Font Family / Font Size: QFontComboBox and SpinBox for text shapes.
- Full command-based undo/redo via
UndoRedoManager. - Every shape add, delete, move, resize, and property change is tracked.
- New actions clear the redo stack (linear history).
- Open: File → Open parses an SVG file into diagram shapes (
SvgParser+ShapetoTag). - Save / Save As: File → Save exports the diagram back to SVG (
RevSvgParser). - New: File → New clears the canvas.
Supported SVG elements: <rect>, <circle>, <line>, <polyline>, <polygon>, <text>.
Diagramowns shapes viastd::vector<std::unique_ptr<GraphicsObject>>.CanvasownsDiagram,SvgParser,RevSvgParser,Clipboard,UndoRedoManagerviastd::unique_ptr.- Qt-managed widgets (toolbars, actions, labels) use raw pointers — Qt handles their lifetime.
- Non-owning raw pointers (
curr_shape_,editing_text_shape_) for temporary references.
GraphicsObject (abstract base)
├── Rectangle (x, y, width, height, rx, ry)
├── Circle (x, y, diameter — cx/cy/r derived)
├── Line (x1, y1, x2, y2)
├── Hexagon (x, y, diameter — 6 vertices from cx/cy/r)
├── FreeSketch (QVector<QPoint> sketch_points_)
└── TextShape (text_, font_, font_size_, baseline)
Virtual interface: Draw(), Contains(), Resize(), Move(), AtHandle(), DrawHandle(), SetXAnch(), SetYAnch(), Clone().
Commandbase storesinitial_state_andfinal_state_(each aShapeState= index + cloned shape).ShapeAddCmd: undo removes at index, redo re-inserts clone.ShapeDeleteCmd: undo re-inserts, redo removes.ShapeModifyCmd: undo/redo swap cloned snapshots at index.UndoRedoManagerholds undo/redo stacks ofunique_ptr<Command>.
- Import:
SvgParser::Parse()reads file line-by-line →ShapetoTagdispatches by tag name →MakeRect(),MakeCircle(), etc. push shapes toDiagram. - Export:
RevSvgParser::WriteToFile()iteratesDiagram, dynamic_casts each shape →RectToTag(),CircleToTag(), etc. write SVG tags to file. - Helper classes:
AttributeGetter(extracts attribute values from tag strings),CleanStr(string trimming),DefaultAttributes(fallback values).
InteractionMode enum drives canvas behavior:
None → DrawRect / DrawRoundedRect / DrawCircle / DrawLine /
DrawHexagon / DrawFreeSketch / DrawText /
TextEdit / SelectTool → OnShape → ShapeMove / ShapeResize / CutCopy
Assignment_1/
├── CMakeLists.txt
├── include/ # All headers
│ ├── canvas.h # Canvas widget + InteractionMode enum
│ ├── diagram.h # Shape collection (model)
│ ├── main_window.h # MainWindow with toolbars/menus
│ ├── graphics_object.h # Abstract base class
│ ├── rectangle.h / circle.h / line.h / hexagon.h
│ ├── free_sketch.h / text_shape.h
│ ├── command.h # Command base + ShapeState
│ ├── shape_add_cmd.h / shape_delete_cmd.h / shape_modify_cmd.h
│ ├── undo_redo.h # UndoRedoManager + CommandType enum
│ ├── clipboard.h
│ ├── svg_parser.h / rev_svg_parser.h / process_shape_tag.h
│ ├── attribute_getter.h / clean_str.h / default_attributes.h
│ └── ...
│
├── src/
│ ├── core/ # Canvas (split across files) + Diagram + main
│ │ ├── canvas.cpp # Constructor / destructor
│ │ ├── canvas_file_ops.cpp # Open, Save, SaveAs, New, Undo, Redo
│ │ ├── canvas_setters.cpp # SetFillColor, SetStrokeColor, SetStrokeWidth, font setters
│ │ ├── canvas_paint.cpp # paintEvent, mouseMoveEvent
│ │ ├── canvas_mouse_press.cpp # mousePressEvent dispatcher
│ │ ├── canvas_draw_press.cpp # HandleDrawPress (shape creation)
│ │ ├── canvas_text_press.cpp # HandleTextDrawPress, HandleTextEditPress
│ │ ├── canvas_select_press.cpp # HandleSelectPress, HandleOnShapePress
│ │ ├── canvas_clipboard.cpp # HandleRightClick (context menu)
│ │ ├── canvas_mouse_release.cpp# mouseReleaseEvent
│ │ ├── canvas_key_events.cpp # keyPressEvent (text input)
│ │ ├── diagram.cpp
│ │ └── main.cpp
│ │
│ ├── shapes/ # Shape implementations
│ │ ├── graphics_object.cpp
│ │ ├── rectangle.cpp / circle.cpp / line.cpp / hexagon.cpp
│ │ ├── free_sketch.cpp # Constructor, Draw, Move, Clone
│ │ ├── free_sketch_ops.cpp # Resize, AtHandle, SetAnch
│ │ ├── text_shape.cpp # Constructor, getters/setters, UpdateBoundingBox
│ │ ├── text_shape_draw.cpp # Draw, DrawBbox, Contains, Resize
│ │ └── text_shape_ops.cpp # Move, DrawHandle, AtHandle, Clone
│ │
│ ├── commands/ # Command pattern
│ │ ├── command.cpp / clipboard.cpp / undo_redo.cpp
│ │ └── shape_add_cmd.cpp / shape_delete_cmd.cpp / shape_modify_cmd.cpp
│ │
│ ├── ui/ # Main window
│ │ ├── main_window.cpp # Constructor, CreateMenu, CreateToolbar, CreateColorbar
│ │ ├── main_window_actions.cpp # CreateActions (all signal/slot connections)
│ │ └── main_window_properties.cpp # CreatePropertiesBar (stroke width, font controls)
│ │
│ └── parser/ # SVG import / export
│ ├── svg_parser.cpp
│ ├── process_shape_tag.cpp # MakeRect, MakeCircle, MakeLine, MakeText
│ ├── process_shape_tag_complex.cpp # MakePolyline, MakePolygon
│ ├── rev_svg_parser.cpp # Shape-to-tag converters (Rect/Circle/Line/Polyline/Polygon/Text)
│ ├── rev_svg_parser_write.cpp # WriteToFile, SetFileName, GetFileName
│ ├── attribute_getter.cpp / clean_str.cpp / default_attributes.cpp
│ └── ...
│
└── build/ # CMake build output
All source files are kept under 100 lines.
- Qt 6 (Core, Gui, Widgets)
- C++17 compiler (g++ 9+)
- CMake 3.16+
cd Assignment_1
mkdir -p build && cd build
cmake ..
make
./VectorEditorDeveloped as part of COP290 (Design Practices in Computer Science), IIT Delhi, by Prof. Smruti Ranjan Sarangi.