Constantin
Constantin

Reputation: 17818

Qt Data Model With Two Different Views

All, I am having trouble determining a good way to handle this. I have a Data Model, which we will call MyData. I have modelled my data as a QObject and thus it has signals and slots.

To modify any data in the model, you can either connect to its slots, or directly call the slots. When that modification occurs, the model signals that its data has changed. eg:

class MyData : public QObject
{
   ...
public slots:
     void AddPoint(QPointF);

signals:
     void AddedPoint(QPointF);
};

void MyData::AddPoint(QPointF p)
{
    //added the point
    emit AddedPoint(p);
}

Now my views are two seperate things:

  1. I have a QGraphicsViewwhich represents the point using QGraphicsEllipseItem
  2. I have a QListView which uses a QAbstractItemModel to list the points.

I sync these two graphical views using signals and slots (I subclasses QGraphicsItem to inherit from QObject).

The question: When a table makes the change, it signals MyData, which in turn signals AddedPoint which is connected to the QGraphicsView. However, MyData::AddedPoint is also connected to the table, and thus two identical points are added when it attempts to sync. Could anyone offer any advice on how to proceed?


My thoughts and ideas so far:


Edit: MyData is really a "controller/interface" class, the real model uses OpenCV types and as thus I would like to keep it separated from the Qt architecture.

Upvotes: 1

Views: 1684

Answers (1)

pokey909
pokey909

Reputation: 1837

You could derive from QAbstractListModel like this:

class MyData : public QAbstractListModel
{
    Q_OBJECT
public:
    enum CustomRoles {
        PositionRole = Qt::UserRole + 1,
        BoundingRectRole
    };
    MyData(QObject *parent = 0) : QAbstractListModel(parent)
    {
        QHash<int, QByteArray> roles;
        roles[PositionRole] = "Position";
        roles[BoundingRectRole] = "BoundingRect";
        setRoleNames(roles);
    }
    int rowCount(const QModelIndex & parent = QModelIndex()) const
    {
        return points.count();
    }

    QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const
    {
        if (index.row() < 0 || index.row() > points.count())
             return QVariant();

         const QGraphicsEllipseItem &p = points[index.row()];
         QVariant actualData;
         if (role == Qt::DisplayRole)
             actualData = "some point";
         else if (role == PositionRole)
             actualData = p.scenePos();
         else if (role == BoundingRectRole)
             actualData = p.boundingRect();

         return actualData;
    }

public slots:
    void addPoint(int x, int y)
    {
        beginInsertRows(QModelIndex(), rowCount(), rowCount());
        QGraphicsEllipseItem *it = new QGraphicsEllipseItem(0,0, 5, 5);
        it->setPos(x,y);
        points << it;
        endInsertRows();
    }

private:
    QVector<QGraphicsEllipseItem*> points;
};

Now you can add this model simply to your QListView and in your QGraphicsScene connect to the rowsInserted(...) and/or rowsRemoved(...) signal of the model.

I also can recommend reading this

Upvotes: 5

Related Questions