Unsolved Reading image from QSqlTableModel
-
Index is your point of access to the model. See QModelIndex::data.
-
@SGaist
I tried the following:QVariant fixImg; fixImg = index.data (Qt::DisplayRole); QPixmap pixMap2; pixMap2 = fixImg.value<QPixmap>(); qDebug() << "pixMap2 size: " << pixMap2.size (); qDebug() << "pixMap2 width: " << pixMap2.width ();
No error message, but the size is 0. Did I miss a step?
Thank you. -
Do you store a QPixmap in your model for that role ?
-
It's a QByteArray.
-
@SGaist
I ranQVariant fixImg(index.data (Qt::EditRole)); qDebug() << "QVariant type: " << fixImg.type ();
and the result was
QVariant type: QVariant::QString -
@gabor53 said in Reading image from QSqlTableModel:
It's a QByteArray.
QByteArray of what? What and how are you storing in the DB? What is the data type of the corresponding column?
-
@jsulm
QByteArray of the original image. The data type of that column is BLOB. -
@gabor53
i asked in a post before:QByteArray ba = fixModel->record (1).value ("Pic").toByteArray (); qDebug() << ba.size() << ba;
in your delegates paint() method (if really a QByteArray is returned) do the following:
if( index.column() == NUMBER_OF_PIXMAP_COLUMN ) { QByteArray ba = index.data( ROLE_USED_IN_MODEL ).toByteArray(); QPixmap pix; pix.loadFromData ( ba ); painter->save(); painter->translate( option.rect.topLeft() ); painter->drawPixmap( pix ); painter->restore(); }
I you should probably post your model code to avoid further guessing.
-
- I don't like
index.column() == NUMBER_OF_PIXMAP_COLUMN
as it ties the delegate to a single model so I consider it bad design,view->setItemDelegateForColumn()
should be used instead. index.data( ROLE_USED_IN_MODEL )
it's aQSqlTableModel
so just deleteROLE_USED_IN_MODEL
and use the default- It's a
QStyledItemDelegate
so let's use style
void FixViewDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { QPixmap loadedImage; loadedImage.loadFromData(index.data().toByteArray()); const QWidget *widget = option.widget; QStyle *style = widget ? widget->style() : QApplication::style(); style->drawItemPixmap(painter,option.rect,Qt::AlignCenter,loadedImage); }
- I don't like
-
This post is deleted! -
@VRonin
Thank you. It runs without error, but paint nothing in the view. -
How do you save your image in the database? do you save it via Qt? can you show us the save part of the code?
-
@VRonin
Sure. I also addedqDebug() << "loadedImage size: " << loadedImage.size ();
and the result is
loadedImage size: QSize(0, 0)I save the image via Qt like this:
#include "review.h" #include "ui_review.h" Review::Review(QWidget* parent) : QDialog(parent), ui(new Ui::Review) { ui->setupUi(this); connect(this, &Review::RecAdded, this, &Review::updateTable); } Review::~Review() { delete ui; } void Review::dispRev(QString sID, QString& name, QString& whatChosen, QString& fileNameChosen, QString& materialChosen, QString& colorChosen, QString& description, QDate& adoptDate, QString& SignedbyChosen, QString& history, QString& age, QString& notesTemp) { name = name.simplified (); description = description.simplified (); ui->ID_display_Label->setText (sID); ui->Name_Disp_Label->setText (name); ui->What_Display_Label->setText (whatChosen); ui->MadeOf_Disp_Label->setText (materialChosen); ui->Color_Disp_Label->setText (colorChosen); ui->textBrowser_Descr->setText (description); adoptDateStr = adoptDate.toString ("MM/dd/yyyy"); ui->AdoptionDate_Disp_Label->setText (adoptDateStr); ui->SignedBy_Disp_label->setText (SignedbyChosen); ui->textBrowser_History->setText (history); ui->Age_Display_Label_2->setText (age); ui->textBrowser_Notes->setText (notesTemp); QPixmap pix2(fileNameChosen); int w = 0; int h = 0; w = ui->Image_Display_Label->width (); h = ui->Image_Display_Label->height (); ui->Image_Display_Label->setPixmap (pix2.scaled(w, h, Qt::KeepAspectRatio)); QFile fileReview(fileNameChosen); if(fileReview.open (QIODevice::ReadOnly)) { fileByteArray = fileReview.readAll (); } nameReview = name; whatReview = whatChosen; fileNameReview = fileNameChosen; materialReview = materialChosen; colorReview = colorChosen; descriptionReview = description; adoptDateReview = adoptDate; SignedbyReview = SignedbyChosen; historyReview = history; sIDReview = sID; ageReview = age; notesReview = notesTemp; } void Review::on_pushButton_Add_to_DB_clicked() { // date = adoptDateReview.toString ("MM/dd/yyyy"); qDebug() << "date in review.cpp: " << date; QSqlDatabase db = QSqlDatabase::addDatabase ("QSQLITE", "writedb"); db.setDatabaseName (fileQstring); QSqlQuery querys(db); if(!db.open ()) { qDebug() << "The database is not open (submit)!"; } else { qDebug() << "The database is open (submit)!"; } querys.prepare("INSERT INTO Items (ID, Name, Pic, Description, AdoptDate, History, Age, Notes, Color, Material, Signed, What) VALUES(:ID, :Name, :Pic, :Description, :AdoptDate, :History, :Age, :Notes, :Color, :Material, :Signed, :What)" ); querys.bindValue (":ID", sIDReview); querys.bindValue (":Name", nameReview); querys.bindValue (":Pic", fileByteArray); querys.bindValue (":Description", descriptionReview); querys.bindValue (":AdoptDate", adoptDateStr); querys.bindValue (":History", historyReview); querys.bindValue (":Age", ageReview); querys.bindValue (":Notes", notesReview); querys.bindValue (":Color", colorReview); querys.bindValue (":Material", materialReview); querys.bindValue (":Signed", SignedbyReview); querys.bindValue (":What", whatReview); bool result = querys.exec (); if(!result) { qDebug() << "Error inserting into the main db!" << querys.lastError (); QMessageBox::warning (this, "Add to Database Warning", "<b><font size='16' color='red'>Error 1002: The Friend was not added to the database."); } else { qDebug() << "Entered FunctAdd OK loop."; QMessageBox::information (this, "Confirmation", "<b><font size = '16' color = 'green'>The Friend was added to the database.</font>"); emit RecAdded (); } } void Review::on_pushButton_Fix_clicked() { Additem* mAdditem = new Additem(this); mAdditem->FixFriend (sIDReview, nameReview, whatReview, fileNameReview, materialReview, colorReview, descriptionReview, date, SignedbyReview, historyReview, ageReview, notesReview); mAdditem->show (); } void Review::updateTable() { qDebug() << "Entered updateTable!"; MainWindow* mMainWindow = new MainWindow(this); mMainWindow->Addview (); mMainWindow->show (); }
Data in the db is stored as BLOB.
-
You don't do anything in case
fileReview.open
fails so you might be storing empty QByteArrays in your database. -
@SGaist
I tried to add a record and I got an error message:
The database is open (submit)!
Error inserting into the main db! QSqlError("", "Parameter count mismatch", "")I'm not sure this has anything to do with the original issue.
I checked a Pic field in the db using DB Browser and there is binary data in the Pic column.
I also made the following changes:if(loadedImage.loadFromData (index.data ().toByteArray ()) != true) { qDebug() << "Fiximage not loaded"; } else { qDebug() << "Fiximage IS loaded"; };
The result was Fiximage not loaded
-
Error inserting into the main db! QSqlError("", "Parameter count mismatch", "")
I'm not sure this has anything to do with the original issue
It does.
SQLitesome/all of Qt's SQLite drivers do not support named binding and apparently Qt is not smart enough to go around it seamlessly.use positional binding instead, see http://doc.qt.io/qt-5/qsqlquery.html#approaches-to-binding-values
You should use the
?
version instead of the:id
version.You can check what your database can do using
db.driver()->hasFeature()
in your casedb.driver()->hasFeature(QSqlDriver::NamedPlaceholders)
will return falseEDIT:
@SGaist is right, corrected my post
-
@VRonin SQLite does since some times already and Qt 5.10 should have proper support for that. Until then, positional is the safest way as you wrote.
-
@SGaist
I redid the query like this:(ID,Name,Pic,What,Material,Color,Description,AdoptDate,Signed,History,Age,Notes)" "VALUES(?,?,?,?,?,?,?,?,?,?,?,?)"); querys.bindValue (0, sIDReview); querys.bindValue (1, nameReview); querys.bindValue (2, fileByteArray); querys.bindValue (3, whatReview); querys.bindValue (4, materialReview); querys.bindValue (5, colorReview); querys.bindValue (6, descriptionReview); querys.bindValue (7, adoptDateStr); querys.bindValue (8, SignedbyReview); querys.bindValue (9, historyReview); querys.bindValue (10, ageReview); querys.bindValue (11, notesReview); bool result = querys.exec ();
It gave me this error :
Error inserting into the main db! QSqlError("", "Parameter count mismatch", "")
External WM_DESTROY received for QWidgetWindow(0x24d75c10, name="ReviewWindow") , parent: QWindow(0x0) , transient parent: QWidgetWindow(0x24d7a4b0, name="AdditemWindow")Changing
explicit Review(QWidget* parent = 0);
to
explicit Review(QWidget* parent = Q_NULLPTR);
in review.h
solved everything except the Parameter count mismatch. -
can you try using
addBindValue
instead ofbindValue
? -
@VRonin
I changed as you recommended:querys.prepare ("INSERT INTO Items (ID,Name,Pic,What,Material,Color,Description,AdoptDate,Signed,History,Age,Notes)" "VALUES(?,?,?,?,?,?,?,?,?,?,?,?)"); querys.addBindValue (sIDReview); querys.addBindValue (nameReview); querys.addBindValue (fileByteArray); querys.addBindValue (whatReview); querys.addBindValue (materialReview); querys.addBindValue (colorReview); querys.addBindValue (descriptionReview); querys.addBindValue (adoptDateStr); querys.addBindValue (SignedbyReview); querys.addBindValue (historyReview); querys.addBindValue (ageReview); querys.addBindValue (notesReview); bool result = querys.exec ();
Still the same error message.