I have a small .ui composed of (I am putting only the major components involved in the problem):
1) N.1 QGraphicsView
2) N.1 QTableView
3) N.1 QPushButton

After uploading images on the QGraphicsView the user is able to capture part of images by drawing boxes using the mouse around the feature of interest. The box operation is done in the class Square.
Everytime the user wants to save the extracted box, using a right click there is a small dialog box that opens up asking to name the image exracted. After hitting accept in the dialog this feature (or box) is stored as row of a QTableView. Now if the user wants to erase a box simply double-click on the box and using the QPushButton it should erase the selected box, and index of the QTableView, but this is not happening. Very recently I was able to successfully implement an SQL statement that takes care of erasing the rows index (only SQL) and not the implementation itself of the QModelIndex due to my not enough knowledge of this tool offered by Qt5. Although I have been reading a lot on official documentation and finding useful sources
Some of the ways I tried so far to make this work:
1) I created a scaffold of SQL using QSQLITE that is handling all the SQL operations, recently I added an additional operation that erase the parameters as it possible to see below. I am erasing only the index related to the QTableView as this should also erase all the remaining fields. See the SQL statements below:
dataleftcamera.h
class dataLeftCamera : public QObject
{
Q_OBJECT
public:
explicit dataLeftCamera(QObject *parent = nullptr);
QString getError() const { return mError; }
bool addItem(Parameters* mParameters);
bool updateItem(int itemId, Parameters* mParameters);
bool removeItem(int itemId);
QSqlDatabase getDatabase();
private:
QString mError;
QSqlDatabase mDatabaseLeft;
};
dataleftcamera.cpp
bool dataLeftCamera::removeItem(int itemId)
{
QSqlQuery qry;
qry.prepare("DELETE FROM leftCamTable WHERE id = ?");
qry.addBindValue(itemId);
bool ok = qry.exec();
if(!ok) {
mError = qry.lastError().text();
qDebug() << mError;
}
}
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
// Set up Constructor
connect(ui->eraseSquare, SIGNAL(clicked()), this, SLOT(on_eraseSquare_clicked(QModelIndex)));
}
The users can draws as much box as would like. Notice that here is where the class Square described above square = new Square(select); comes into play:
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());
square = new Square(select);
square->setActiveState(true);
currentSelection = selections.size();
selections.append(square);
leftScene->addItem(square->getGraphics());
ui->graphicsView->show();
}
else
{
start = fromScenePoint;
end = toScenePoint;
}
}
void MainWindow::on_eraseSquare_clicked(const QModelIndex &index)
{
int row = index.row();
Param currentData;
int ItemId = index.sibling(row, 0).data().toInt();
mDatabaseLeftCamera->removeItem(ItemId);
mModelLeftCamera->select();
ui->tableView->show();
}
Double-click to re-activate the box:
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);
}
}
square.cpp
Square::Square(QRectF newarea)
{
colorActive = Qt::red;
colorInactive = Qt::darkRed;
mItemSquare = new QGraphicsRectItem(newarea);
mItemSquare->setPen(QPen(colorActive));
gfx = new QGraphicsItemGroup();
gfx->addToGroup(mItemSquare);
index = -1;
}
Square::~Square() {}
QRectF Square::boundingRect() const { return QRectF(0,0,50,50); }
QGraphicsItemGroup *Square::getGraphics() { return gfx; }
bool Square::removeRows(int position, int rows, const QModelIndex &index)
{
beginRemoveRows(QModelIndex(), position, position+rows-1);
for (int row = 0; row < rows; ++row) {
stringList.removeAt(position);
}
endRemoveRows();
return true;
}
void Square::setModelIndex(const QModelIndex &)
{
// Needed?
}
void Square::beginRemoveRows(const QModelIndex &parent, int first, int last)
{
// Needed?
}
void Square::endRemoveRows()
{
// Needed?
}
square.h
class Square : public QObject
{
Q_OBJECT
public:
explicit Square(QRectF newarea);
~Square();
QGraphicsRectItem *mItemSquare;
bool pressed;
bool drawStarted;
int selectedTool, index;
QPixmap mPix;
QGraphicsItemGroup* getGraphics();
bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex());
void setModelIndex(const QModelIndex&);
void setPen(QPen newpen);
void updateColor(QColor active, QColor inactive);
public slots:
void setActiveState(bool newactive);
void setVisible(bool newstate);
protected:
void beginRemoveRows(const QModelIndex &parent, int first, int last);
void endRemoveRows();
}
2) I was reading many sources such as this one and this other source. It seems that QTableView should be sub-classed in order to re-implement
beginRemoveRows and endRemoveRows. But at the same time I am not sure this should be done.
3) A third way I was trying to understand if feasible is to create a function on the class Square like this one:
void Square::setModelIndex(const QModelIndex &)
{
// possible solution?
}
Should the implementation be at this point something like the following?

I have been stuck on this problem for some days now and have no additional ideas to move on. Thanks so much for pointing in the right direction for implementing QModelIndex function and solving this issue.
Aucun commentaire:
Enregistrer un commentaire