dimanche 10 février 2019

How to erase QGraphicsRectItem from QTableView which is also a record of an SQLITE database

I am designing an interface with a lot of controls. However I prepared a small minimal application that describes the problem that I have. The application consists of:

1) N.1 QTableView

2) N.1 QGraphicsView

3) N.1 Pushbutton

4) N.2 ListView

The GUI is shown below:

main GUI

With the mouse I am able to draw a box (red square) indicated. As soon as I draw the box (and I can click to create points too as shown) I create the first row in the QTableView with some default parameters. As soon as I draw the second box I create another row in the QTableView and so on until I draw a third box.

After drawing the third box the user can decide to re-acrivate again the first box by doubleClicking on the first box previously drawn and the same for the others.

Using the Pushbutton I would like to erase the points+box, The box itself is also related to a specific row in the QTableView. Remember: as soon as I draw a box, a row is added on the QTableView and the option of drawing the point(s) comes after that.

In other words, how do I make SQLITE understand that if I erase a specific item (a box in this case) on the QTableView that also that specific record should disappear from the QTableView?

Possible solutions I tried:

1) Going through the official documentation of SQLITE, however nothing in particular was related to this specific problem

2) I was able to write an erase function related to the button, but it is only general, which means that I click it and all points+box are gone and the software crushes because the rows in the QTableView are still there and related to the box.

The partial solution I arrived is below:

mainwindow.h

public:
    QList<DataRegion*> selections;
    int currentSelection;
private:
    QList<QGraphicsRectItem*> leftMatchPoints;

private slots:
    void clearSceneLeft();
    void on_eraseLPointsBtn_clicked();

mainwindow.cpp

void MainWindow::clearSceneLeft()
{
    if (selections.size() > 0) {
        qDeleteAll(selections);
        selections.clear();
        currentSelection = -1;
    }
    for(int p=0;p<leftMatchPoints.size();p++)
    {
        leftScene->removeItem(leftMatchPoints[p]);
        delete leftMatchPoints[p];
    }
    leftMatchPoints.clear();
}


void MainWindow::on_eraseLPointsBtn_clicked()
{
    clearSceneLeft();
}

See below the snipped of code related to this problem:

On the constructor I create a temporary folder where to load the data of the database realated to the QTableView:

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    currentSelection = -1;

    // temporary folder
    temporaryFolder = "/path/to/folder/tempDBFolder/tmp.db";
    QFile dbRem(temporaryFolder);
    dbRem.remove();
    mDatabaseLeftCamera->inizializationDatabaseLeftCamera(temporaryFolder);
    mDatabaseLeftCamera->configurationDatabaseLeftCamera();
    mModelLeftCamera = new QSqlTableModel(this, mDatabaseLeftCamera->getDatabase());
    mModelLeftCamera->setTable("leftCamTable");
    mModelLeftCamera->select();
    ui->recordLeftTableView->setModel(mModelLeftCamera);
    ui->recordLeftTableView->setItemDelegate(new ImageDelegate(this));
    ui->recordLeftTableView->showColumn(true);
}

mainwindow.cpp

Here is where right after drawing the box I create the row on the QTableView:

void MainWindow::onRubberBandUpdate(const QRect &viewportRect, const QPointF &fromScenePoint, const QPointF &toScenePoint)
{
    if(viewportRect.isNull() && fromScenePoint.isNull() && toScenePoint.isNull() && imageLoaded)
    {
        if(currentSelection >= 0)
            selections[currentSelection]->setActiveState(false);
        QRectF select;
        select.setCoords(start.x(), start.y(), end.x(), end.y());
        DataRegion *region = new DataRegion(select);

        // link the box to the table
        leftCamParameters *boxParam = new leftCamParameters();
        SelectionData tmpdat = boxParam->getData();

        // getting the A-B-C-D Coordinates
        tmpdat.mACoord.setX((int)select.topLeft().x());
        tmpdat.mACoord.setY((int)select.topLeft().y());

        // plus additional parameters

        boxParam->setData(tmpdat);
        mDatabaseLeftCamera->addItem(boxParam);
        mModelLeftCamera->select();
        ui->recordLeftTableView->show();

        currentSelection = selections.size();
        selections.append(region);
        leftScene->addItem(region->getGraphics());
        ui->leftView->show();
    }
    else
    {
        start = fromScenePoint;
        end = toScenePoint;
    }
}

Here is where I activate again the box by doubleClicking

void MainWindow::onSceneDoubleClick(QPointF point)
{
    QList<QGraphicsItem*> foundItems = leftScene->items(point);
    if(foundItems.size() > 0 && foundItems[0]->group() != nullptr)
    {
        int i = 0;
        for(i=0;i<selections.size();i++)
        {
            if(selections[i]->getGraphics() == foundItems[0]->group())
            {
                break;
            }
        }
        if(currentSelection >= 0)
            selections[currentSelection]->setActiveState(false);

        currentSelection = i;
        selections[currentSelection]->setActiveState(true);
        QRectF rect = selections[currentSelection]->getBox()->rect();
        start.setX(rect.left());
        start.setY(rect.top());
        end.setX(rect.right());
        end.setY(rect.bottom());
    }
}

Expected result: As soon as I activate a box through doubleClick, I push the button and erase that box only and its related row on the QTableView.

Actual result: I can erase box+points from the QGraphicsView but the specific row related to that specific box still exists on the QTableView causing the software to crush.

Thanks for pointing in the right direction or shed light on this issue.

Aucun commentaire:

Enregistrer un commentaire