Kelick Tech Hub

Build, learn & keep up — tech, Linux & sports news included.

C++ GUI-based Inventory Project

Advanced•2 weeks•GUI (Qt), MVC, events

The inventory system grows a window: tables, forms, and live search.

Share on X

What you will build

Take inventory management into a real graphical interface with Qt: a sortable product table, add/edit dialogs, live search-as-you-type, and low-stock highlighting. It's event-driven programming — your code waits, the user acts, handlers respond — a fundamentally different rhythm from console apps.

What you will learn

Feature checklist

Starter code

// Qt: a table model over the product list (header sketch)
#include <QAbstractTableModel>
#include <vector>
#include <string>

struct Product { std::string sku, name; double price; int qty; };

class InventoryModel : public QAbstractTableModel {
    std::vector<Product> data_;
public:
    int rowCount(const QModelIndex& = QModelIndex()) const override {
        return (int)data_.size();
    }
    int columnCount(const QModelIndex& = QModelIndex()) const override {
        return 4;  // SKU, Name, Price, Qty
    }
    QVariant data(const QModelIndex& i, int role) const override {
        const Product& p = data_[i.row()];
        if (role == Qt::BackgroundRole && p.qty <= 5 && i.column() == 3)
            return QColor(120, 30, 30);            // low stock highlight
        if (role != Qt::DisplayRole) return {};
        switch (i.column()) {
            case 0: return QString::fromStdString(p.sku);
            case 1: return QString::fromStdString(p.name);
            case 2: return p.price;
            case 3: return p.qty;
        }
        return {};
    }
    void add(Product p) {
        beginInsertRows({}, (int)data_.size(), (int)data_.size());
        data_.push_back(std::move(p));
        endInsertRows();
    }
};

Full walkthrough

Step 1: Understand the Qt bargain before writing code

Qt gives you windows, tables, and dialogs; in exchange your code lives inside its event loop (app.exec()) and its object model. The inventory data stays YOUR code — a std::vector<Product> — and Qt only presents it. Keeping that boundary (plain C++ data, Qt presentation) is the architecture decision everything else follows.

Step 2: Build the model: InventoryModel extends QAbstractTableModel

A QTableView does not hold data — it ASKS a model. InventoryModel wraps the vector<Product> and implements the contract: rowCount() = products size, columnCount() = 4 (SKU, Name, Price, Qty), data(index, role) returns the field for that cell as a QVariant, headerData() names the columns. When the data changes, the model emits signals (beginInsertRows/endInsertRows, dataChanged) — the view redraws because it was TOLD, which is the whole model-view idea.

int InventoryModel::rowCount(const QModelIndex&) const override {
    return (int)data_.size();
}

Step 3: Wire the view: sorting and selection for free

A QTableView over the model, wrapped by QSortFilterProxyModel, gives sortable column headers and as-you-type filtering almost for free: the search box's text goes into the proxy's setFilterFixedString, and the proxy hides non-matching rows WITHOUT touching your data. Row selection comes from the view's selection model — read the selected proxy index, map it back to the source row, and you know which Product the user means.

Step 4: Add/Edit dialogs with validation

A QDialog with line edits for SKU, name, price, quantity; accept only if SKU is non-empty (and unique for Add), price parses to a number ≥ 0, quantity is a non-negative integer. Validation failure shows the problem IN the dialog and keeps it open — a dialog that silently closes on bad data trains users to distrust every button.

Step 5: Highlight low stock inside data()

The model's data() also answers the Qt::BackgroundRole: when a product's qty is below the threshold (10), return a warning tint for that row. The rule lives in the model, so sorting, filtering, and printing all agree on which rows are 'low' — presentation derived from the same data as everything else.

Step 6: Sales and restock buttons adjust the model

Buttons beside the table act on the SELECTED product: Sell asks a quantity (spin box), refuses overselling with a message box (the inventory project's rule, wearing a GUI), decrements, and notifies the view via dataChanged so the row and its low-stock tint update instantly. Restock mirrors it. No button reaches into the vector directly — everything goes through model methods that emit the right signals.

Step 7: Persist to a file (or SQLite) on every change

After each mutation, save the product list (the catalogue's familiar line format, or a QSqlDatabase table if you take the SQLite branch). Load in the model's constructor. The GUI test: add a product, sell some, CLOSE the window, reopen — the table must show the post-sale quantity, or persistence is a rumour.

Common mistakes

Compile and run

g++ -std=c++17 -o gui_inventory gui_inventory.cpp

This is a Qt Widgets app, so it is built with CMake/Qt Creator rather than a bare g++ command (Qt generates code with its moc tool as part of the build). On Windows the built program is build\gui_inventory.exe — or just open the project in Qt Creator and press Run.

Sample run

$ ./build/gui_inventory
(the inventory window opens — sample session)
Window: table shows 2 products loaded from inventory.dat
  USB-CAB | USB Cable      | 1500.00 | 40
  MSE-02  | Wireless Mouse | 4500.00 |  6   <- highlighted: low stock
(you type 'mouse' in the search box — the table filters as you type)
  1 row shown: MSE-02 Wireless Mouse
(you clear the search, select USB Cable, click Sell, quantity 5)
  USB Cable row updates: quantity 40 -> 35
(you select Wireless Mouse and click Sell, quantity 9)
  Dialog: 'Only 6 in stock — sale refused.' (nothing changed)
(you click Add, enter a new product, and it appears in sorted position)
  HDMI-01 | HDMI Cable 2m | 3200.00 | 25
(you close the window and reopen it — every quantity is exactly as you left it)
Saved to inventory.dat on every change — persistence verified.

Try it in your browser

No browser demo is included for this project. Build the C++ version below — that is the real program.

Related Advanced projects

← All 60 projects · Classic site (Learn & Sandbox)

Download Fake GPS