PDA

View Full Version : display image from database using c++ model



jfinn88
25th October 2016, 19:22
I'm having some issues understanding how to display an image stored in a database in QML I would like to use a C++ model to do this. I believe from what I seen I will need an QQuickImageProvider and to over ride the requestImage() method.

Not quite sure how to set up the Image provider - subclass the image provider and over ride requestImage() ?

Not sure how to use the model and Image provider to display image in QML scrollView - model combines with ImageProvider to display image ?

I have a drop list for displaying the images name and once a user selects a image from the list I want the image to load into a scroll view...

I set up my database schema as such:



"CREATE TABLE IF NOT EXISTS picTable (id INT PRIMARY KEY, picName TEXT, pic BLOB)"


QML code


Item {
id:checkList_item
implicitHeight: 600
implicitWidth: 1000

signal exit()

Rectangle {
id: checkList_Rect
anchors.fill: parent
radius: 10
border.width:4
border.color: "black"
layer.enabled: true
enabled: true
opacity: enabled ? 1.0 : .3
layer.effect: DropShadow {
horizontalOffset: 8
verticalOffset: 8
radius: 8.0
samples: 16
color: "#80000000"
source: checkList_Rect
}
gradient: Gradient {
GradientStop {
position: 0
color: "#ffffff"
}

GradientStop {
position: 1
color: "#262626"
}
}
//---Saves check list to database---//
Action{
id: action_saveCheckList
onTriggered: {
/*
* saves check list to database
* saves the date the check list was verfied
* operator that verified check list
* Engineer who verified check list
*/
}
}

//---Closes Check List Dialog---//
Action{
id: action_exit
enabled:!inSequence
onTriggered: {
//checkList_item.exit();
window_contents.state = ""
}
}

//---Calls function after QML loads---//
Component.onCompleted: {
//---calls initalize function--//
PictureModel.init();
}

FocusScope{
id: focusScope1
anchors.rightMargin: 0
anchors.bottomMargin: 0
anchors.leftMargin: 0
anchors.topMargin: 0
anchors.fill:parent

//---List Check List Currently in the database---//
ComboBox {
id: checkList_comboBox
width: 130
height: 48
anchors.left: parent.left
anchors.leftMargin: 50
anchors.top: parent.top
anchors.topMargin: 41
implicitHeight: 30
implicitWidth: 130
KeyNavigation.tab: addCheckListItem
activeFocusOnTab: true
model: PictureModel
textRole: "picName"
style: userListCombo
Keys.onReturnPressed: {
checkList_comboBox.focus = false;
addItem.focus = true;
}
}

//---Component for comboBox Style---//
Component {
id: userListCombo
ComboBoxStyle {
id: userListcomboxstyle
textColor: "black"
selectionColor: "yellow"
selectedTextColor: "black"
background: Rectangle {
id: comboBackgroundRect
color: "#f9f9f9"
radius: 8
height: 22
width: 67
border.color: control.activeFocus ? "yellow" : "#242424"
border.width: control.activeFocus ? 4 : 2
Image {
id: name
width: 12
height: 12
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: 5
source: "/combo_expand.png"
}
}
}
}

//---Rect to hold Image---//
Rectangle {
id: chekListView_rect
radius: 8
width: 1000
height: 400
anchors.left: parent.left
anchors.leftMargin: 10
anchors.right: parent.right
anchors.rightMargin: 10
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: -5
border{
color: "black"
width: 3
}
//---Adds ScrollBars---//
ScrollView{
id: userEvent_scrollView
anchors.fill: parent
//---Enables flickable Area---//
flickableItem.interactive: true
verticalScrollBarPolicy: Qt.ScrollBarAsNeeded
style: edit_scrollbar_style
//---Display image from C++ model---//
Image{
//source:
}
}
}

//---Custom ScrollBar Component---//
Component{
id: edit_scrollbar_style
ScrollViewStyle {
transientScrollBars: false
handle: Item {
implicitWidth: 17
implicitHeight: 25
Rectangle {
color: "#424246"
radius: 6
anchors.fill: parent
anchors.topMargin: 6
anchors.leftMargin: 4
anchors.rightMargin: 4
anchors.bottomMargin: 6
}
}
decrementControl: Rectangle{
implicitWidth: 17
implicitHeight: 17
radius: 6
color:"#626262"

Image{
anchors.centerIn: parent
width: 15
height: 15
source: "up_arrow.png"
}
Rectangle {
implicitWidth: 17
implicitHeight: 5
color:"#626262"
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
}

}
incrementControl: Rectangle{
implicitWidth: 17
implicitHeight: 17
radius: 6
color:"#626262"
Image{
anchors.centerIn: parent
width: 15
height: 15
source: "down_arrow.png"
}
Rectangle {
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
implicitWidth: 17
implicitHeight: 5
color:"#626262"
}

}
scrollBarBackground: Rectangle {
implicitWidth: 17
implicitHeight: 25
color:"grey"
}

}
}
}
}
}


Added after 20 minutes:

C++ here is the model code

header prototype


//---Data struct for stored checkLists---//
struct PictureModelStruct{
QString id;
QString picname;
QPixmap pic;
};

class PictureModel : public QAbstractListModel{

Q_OBJECT

public:
explicit PictureModel(QObject *parent = 0);

~PictureModel();

void setContext(QQmlContext* root);

Q_INVOKABLE void insertPic();

Q_INVOKABLE void displayPic();

enum pictureRoles{idRole= Qt::UserRole + 1, nameRole, picRole};

int rowCount(const QModelIndex & parent) const;

QHash<int, QByteArray> roleNames() const;

QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const;

Q_INVOKABLE void addPicture(const PictureModelStruct &picList);

Q_INVOKABLE bool dbConnect();

Q_INVOKABLE void init();

Q_INVOKABLE bool selectPictureName();

signals:
void showBusy(bool busy_state);

public slots:

private:
//---Databse Class Instances---//
QList<PictureModelStruct> m_picList;
QSqlDatabase m_selectPictureDB;
};




//---Constructor subclasses ListModel & ImageLoader---//
PictureModel::PictureModel(QObject *parent) : QAbstractListModel(parent),
QQuickImageProvider(QQmlImageProviderBase::Image, QQmlImageProviderBase::ForceAsynchronousImageLoadi ng){

}

QPixmap PictureModel::requestPixmap(const QString &id, QSize *size, const QSize &reqSize){


}

//---Destructor---//
PictureModel::~PictureModel(){

}

//---init() is called after QML loads---//
void PictureModel::init(){
//insertPic();
displayPic();
selectPictureName();
}

//---Connect to BLOB database---//
bool PictureModel::dbConnect(){
//---check if database is connected---//
if(!m_selectPictureDB.isValid()){
qDebug() << "PictureModel::dbConnect() error in connecting to DB";
m_selectPictureDB = QSqlDatabase::addDatabase("QSQLITE", "conn5");
m_selectPictureDB.setDatabaseName(Paths::root() + "/pictures.db");
qDebug() << "PictureModel::dbConnect() database connection path: "+Paths::root()+"/pictures.db";
m_selectPictureDB.open();

QStringList tables = m_selectPictureDB.tables();
if(!tables.contains("picTable")){
QSqlQuery q("", m_selectPictureDB);
q.exec("CREATE TABLE IF NOT EXISTS picTable (id INT PRIMARY KEY, picName TEXT, pic BLOB)");
qDebug() << "PictureModel::dbConnect() created picTable";
}
}
else{
qDebug() <<"PictureModel::dbConnect() connected to DB" ;
m_selectPictureDB.open();
}
return m_selectPictureDB.isValid();
}

//---Inserts a pic into BLOB database
void PictureModel::insertPic(){
dbConnect();

QImage image("flower3.jpg");
qDebug() << image.size();
QByteArray inByteArray;
QBuffer buffer(&inByteArray);
buffer.open(QIODevice::WriteOnly);
image.save(&buffer, "jpg");

QSqlQuery query(m_selectPictureDB);
bool sqlBool = query.prepare("INSERT INTO picTable (id, picName, pic) VALUES (?, ?, ?)");
query.addBindValue(5);
query.addBindValue("flower");
query.addBindValue(inByteArray);

if(sqlBool){
if(query.exec()){
qDebug() << "PictureModel::insertPic() sql insert executed fine!";
}
}
else{
qDebug() << "PictureModel::isertPic() sql insert did not execute!";
}
}

//---Displays pic stored in BLOB database---//
void PictureModel::displayPic(){
dbConnect();
QByteArray outByteArray;
QSqlQuery query(m_selectPictureDB);
bool sqlBool;
sqlBool = query.prepare("SELECT pic FROM picTable");
if (sqlBool){
qDebug() << "prepare sql display pic executed fine!";
if(query.exec()){
qDebug() << "execute sql display pic executed fine!";
}
else{
qDebug() << "execute sql display pic did not execute";
}
}
else{
qDebug() << "prepare sql display pic did not execute";
}

PictureModelStruct picList;
beginResetModel();
m_picList.clear();

while (query.next()){
picList.id = query.value(0).toString();
picList.picname = query.value(1).toString();
outByteArray = query.value(2).toByteArray();
picList.pic = QPixmap::fromImage(QImage::fromData(outByteArray, "jpg"));
addPicture(picList);
}

endResetModel();
emit showBusy(false);
m_selectPictureDB.close();
}

//---Function is called in xmui.cpp---//
void PictureModel::setContext(QQmlContext* root){

//---Sets rootContext for model to be used in userListModel QML---//
root->setContextProperty("PictureModel", this);
}

int PictureModel::rowCount(const QModelIndex &parent) const{
Q_UNUSED(parent);
return m_picList.count();
}

QHash<int, QByteArray> PictureModel::roleNames() const{
QHash<int, QByteArray> roleNames;
roleNames.insert(nameRole, "picName");
return roleNames;
}

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

QVariant text;

if(role == nameRole){
PictureModelStruct pList = m_picList.at(index.row());
text = pList.picname;
}
return text;
}

void PictureModel::addPicture(const PictureModelStruct &picList){
beginInsertRows(QModelIndex(), 0, 0);
m_picList.insert(0, picList);
endInsertRows();
}

//---Selects name of pictures from DB for display---//
bool PictureModel::selectPictureName(){
dbConnect();
emit showBusy(true);
QSqlQuery selectQuery(m_selectPictureDB);
bool sqlBool;
sqlBool = selectQuery.prepare("SELECT DISTINCT picName FROM picTable ORDER BY picName ASC");
if(sqlBool){
if(selectQuery.exec()){
qDebug()<<"PictureModel::selectPictureName() select picName sql statement executed fine";
}
}
else{
emit xmui->alertMsg(QMessageBox::Warning, "Database selectPicture Error Message 1", "Error: sql select script..."+selectQuery.lastError().text());
qDebug()<<"PictureModel::selectPictureName() Error with sql statement execution " << selectQuery.lastError();
return selectQuery.exec();
}

PictureModelStruct picList;
beginResetModel();
m_picList.clear();

while (selectQuery.next()){
picList.picname = selectQuery.value(1).toString();
addPicture(picList);
}
endResetModel();
emit showBusy(false);
m_selectPictureDB.close();
return selectQuery.exec();
}


updated header file



//---Data struct for stored checkLists---//
struct PictureModelStruct{
QString id;
QString picname;
QPixmap pic;
};

class PictureModel : public QAbstractListModel, QQuickImageProvider{

Q_OBJECT

public:
explicit PictureModel(QObject *parent = 0);

~PictureModel();

void setContext(QQmlContext* root);

QPixmap requestPixmap(const QString &id, QSize *size, const QSize &reqSize);

Q_INVOKABLE void insertPic();

Q_INVOKABLE void displayPic();

enum pictureRoles{idRole= Qt::UserRole + 1, nameRole, picRole};

int rowCount(const QModelIndex & parent) const;

QHash<int, QByteArray> roleNames() const;

QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const;

Q_INVOKABLE void addPicture(const PictureModelStruct &picList);

Q_INVOKABLE bool dbConnect();

Q_INVOKABLE void init();

Q_INVOKABLE bool selectPictureName();

signals:
void showBusy(bool busy_state);

public slots:

private:
//---Databse Class Instances---//
QList<PictureModelStruct> m_picList;
QSqlDatabase m_selectPictureDB;
};


Added after 9 minutes:

thought about adding a call to requestImage() and pass it the id and image from the database...



requestPixmap(picList.id, picList.pic, QSize::scaled(20,20, Qt::IgnoreAspectRatio));


Added after 7 minutes:

change form pixMap to Image

Added after 25 minutes:

updated c++ functions


//---Constructor subclasses ListModel & ImageLoader---//
PictureModel::PictureModel(QObject *parent) : QSqlQueryModel(parent),
QQuickImageProvider(QQmlImageProviderBase::Image, QQmlImageProviderBase::ForceAsynchronousImageLoadi ng){

}

QImage PictureModel::requestImage(const QString &id, QSize *size, const QSize &reqSize){
Q_UNUSED(id);
Q_UNUSED(size);
Q_UNUSED(reqSize);
//return QImage::fromData(this->record(id.toInt(), "jpg"));
}

//---Destructor---//
PictureModel::~PictureModel(){

}

//---init() is called after QML loads---//
void PictureModel::init(){
//insertPic();
displayPic();
selectPictureName();
}

//---Connect to BLOB database---//
bool PictureModel::dbConnect(){
//---check if database is connected---//
if(!m_selectPictureDB.isValid()){
qDebug() << "PictureModel::dbConnect() error in connecting to DB";
m_selectPictureDB = QSqlDatabase::addDatabase("QSQLITE", "conn5");
m_selectPictureDB.setDatabaseName(Paths::root() + "/pictures.db");
qDebug() << "PictureModel::dbConnect() database connection path: "+Paths::root()+"/pictures.db";
m_selectPictureDB.open();

QStringList tables = m_selectPictureDB.tables();
if(!tables.contains("picTable")){
QSqlQuery q("", m_selectPictureDB);
q.exec("CREATE TABLE IF NOT EXISTS picTable (id INT PRIMARY KEY, picName TEXT, pic BLOB)");
qDebug() << "PictureModel::dbConnect() created picTable";
}
}
else{
qDebug() <<"PictureModel::dbConnect() connected to DB" ;
m_selectPictureDB.open();
}
return m_selectPictureDB.isValid();
}

//---Inserts a pic into BLOB database
void PictureModel::insertPic(){
dbConnect();

QImage image("flower3.jpg");
qDebug() << image.size();
QByteArray inByteArray;
QBuffer buffer(&inByteArray);
buffer.open(QIODevice::WriteOnly);
image.save(&buffer, "jpg");

QSqlQuery query(m_selectPictureDB);
bool sqlBool = query.prepare("INSERT INTO picTable (id, picName, pic) VALUES (?, ?, ?)");
query.addBindValue(5);
query.addBindValue("flower");
query.addBindValue(inByteArray);

if(sqlBool){
if(query.exec()){
qDebug() << "PictureModel::insertPic() sql insert executed fine!";
}
}
else{
qDebug() << "PictureModel::isertPic() sql insert did not execute!";
}
}

//---Displays pic stored in BLOB database---//
void PictureModel::displayPic(){
dbConnect();
QByteArray outByteArray;
QSqlQuery query(m_selectPictureDB);
bool sqlBool;
sqlBool = query.prepare("SELECT pic FROM picTable");
if (sqlBool){
qDebug() << "prepare sql display pic executed fine!";
if(query.exec()){
qDebug() << "execute sql display pic executed fine!";
}
else{
qDebug() << "execute sql display pic did not execute";
}
}
else{
qDebug() << "prepare sql display pic did not execute";
}

PictureModelStruct picList;
beginResetModel();
m_picList.clear();

while (query.next()){
picList.id = query.value(0).toString();
picList.picname = query.value(1).toString();
outByteArray = query.value(2).toByteArray();
picList.pic = QPixmap::fromImage(QImage::fromData(outByteArray, "jpg"));
addPicture(picList);

//requestImage(picList.id, QSize(20, 20), QSize(20, 20));
}

endResetModel();
emit showBusy(false);
m_selectPictureDB.close();
}

//---Function is called in xmui.cpp---//
void PictureModel::setContext(QQmlContext* root){

//---Sets rootContext for model to be used in userListModel QML---//
root->setContextProperty("PictureModel", this);
}

int PictureModel::rowCount(const QModelIndex &parent) const{
Q_UNUSED(parent);
return m_picList.count();
}

QHash<int, QByteArray> PictureModel::roleNames() const{
QHash<int, QByteArray> roleNames;
roleNames.insert(nameRole, "picName");
return roleNames;
}

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

QVariant text;

if(role == nameRole){
PictureModelStruct pList = m_picList.at(index.row());
text = pList.picname;
}
return text;
}

void PictureModel::addPicture(const PictureModelStruct &picList){
beginInsertRows(QModelIndex(), 0, 0);
m_picList.insert(0, picList);
endInsertRows();
}

//---Selects name of pictures from DB for display---//
bool PictureModel::selectPictureName(){
dbConnect();
emit showBusy(true);
QSqlQuery selectQuery(m_selectPictureDB);
bool sqlBool;
sqlBool = selectQuery.prepare("SELECT DISTINCT picName FROM picTable ORDER BY picName ASC");
if(sqlBool){
if(selectQuery.exec()){
qDebug()<<"PictureModel::selectPictureName() select picName sql statement executed fine";
}
}
else{
emit xmui->alertMsg(QMessageBox::Warning, "Database selectPicture Error Message 1", "Error: sql select script..."+selectQuery.lastError().text());
qDebug()<<"PictureModel::selectPictureName() Error with sql statement execution " << selectQuery.lastError();
return selectQuery.exec();
}

PictureModelStruct picList;
beginResetModel();
m_picList.clear();

while (selectQuery.next()){
picList.picname = selectQuery.value(1).toString();
addPicture(picList);
}
endResetModel();
emit showBusy(false);
m_selectPictureDB.close();
return selectQuery.exec();
}

anda_skoa
26th October 2016, 12:05
I'm having some issues understanding how to display an image stored in a database in QML I would like to use a C++ model to do this. I believe from what I seen I will need an QQuickImageProvider and to over ride the requestImage() method.

Yes, that is one option.



Not quite sure how to set up the Image provider - subclass the image provider and over ride requestImage() ?

Yes, or the method that returns QImage, depending on what you have. QImage in your case I think.
And then registering the instance of the provider with the id name scheme it should be used with.

The documentation has a pretty thorough example in the class' detailed description.



Not sure how to use the model and Image provider to display image in QML scrollView - model combines with ImageProvider to display image ?

That is an option, probably the easiest one.

In your code I am missing where you add/register the image provider and how you add the scheme name used there to the image identifiers your data() method hands out.
Maybe you are missing these?

Cheers,
_

jfinn88
26th October 2016, 15:47
Yes I am missing the add/register the image provider not quite sure how to do that will have to read more
Im guessing I need to register the imageProvider with the QML engine like this ex from the doc


QQuickView view;
QQmlEngine *engine = view.engine();
engine->addImageProvider(QLatin1String("colors"), new ColorPixmapProvider);


once its registered though you call it with the id from the QML Image source property like in the doc


Image { source: "image://myimageprovider/image.png" }


I also get lost with how the "id" and scheme name are used to identify the image from data



//---Constructor subclasses ListModel & ImageLoader---//
PictureModel::PictureModel(QObject *parent) : QSqlQueryModel(parent),
QQuickImageProvider(QQmlImageProviderBase::Image, QQmlImageProviderBase::ForceAsynchronousImageLoadi ng){

}

QImage PictureModel::requestImage(const QString &id, QSize *size, const QSize &reqSize){
Q_UNUSED(id);
Q_UNUSED(size);
Q_UNUSED(reqSize);
//return QImage::fromData(this->record(id.toInt(), "jpg"));
}

//---Destructor---//
PictureModel::~PictureModel(){

}

//---Function is called in xmui.cpp---//
void PictureModel::setContext(QQmlContext* root){

//---Sets rootContext for model to be used in userListModel QML---//
root->setContextProperty("PictureModel", this);
}

//---init() is called after QML loads---//
void PictureModel::init(){
//insertPic();
//displayPic();
selectPictureName();
}

//---Connect to BLOB database---//
bool PictureModel::dbConnect(){
//---check if database is connected---//
if(!m_selectPictureDB.isValid()){
qDebug() << "PictureModel::dbConnect() error in connecting to DB";
m_selectPictureDB = QSqlDatabase::addDatabase("QSQLITE", "conn5");
m_selectPictureDB.setDatabaseName(Paths::root() + "/pictures.db");
qDebug() << "PictureModel::dbConnect() database connection path: "+Paths::root()+"/pictures.db";
m_selectPictureDB.open();

QStringList tables = m_selectPictureDB.tables();
if(!tables.contains("picTable")){
QSqlQuery q("", m_selectPictureDB);
q.exec("CREATE TABLE IF NOT EXISTS picTable (id INT PRIMARY KEY, picName TEXT, pic BLOB)");
qDebug() << "PictureModel::dbConnect() created picTable";
}
}
else{
qDebug() <<"PictureModel::dbConnect() connected to DB" ;
m_selectPictureDB.open();
}
return m_selectPictureDB.isValid();
}

int PictureModel::rowCount(const QModelIndex &parent) const{
Q_UNUSED(parent);
return m_picList.count();
}

QHash<int, QByteArray> PictureModel::roleNames() const{
QHash<int, QByteArray> roleNames;
roleNames.insert(idRole, "id");
roleNames.insert(nameRole, "picName");
roleNames.insert(picRole, "pic");
return roleNames;
}

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

QVariant text;
//QImage image;

if(role == nameRole){
PictureModelStruct pList = m_picList.at(index.row());
text = pList.picName;
}

// if(role == idRole){
// PictureModelStruct pList = m_picList.at(index.row());
// text = pList.id;
// }
// else if(role == picRole){
// PictureModelStruct pList = m_picList.at(index.row());
// image = pList.pic;
// }
return text;
}

void PictureModel::addPicture(const PictureModelStruct &picList){
beginInsertRows(QModelIndex(), 0, 0);
m_picList.insert(0, picList);
endInsertRows();
}

//---Inserts a pic into database---//
void PictureModel::insertPic(){
dbConnect();

QImage image("flower2.jpg");
qDebug() << image.size();
QByteArray inByteArray;
QBuffer buffer(&inByteArray);
buffer.open(QIODevice::WriteOnly);
image.save(&buffer, "jpg");

QSqlQuery query(m_selectPictureDB);
bool sqlBool = query.prepare("INSERT INTO picTable (id, picName, pic) VALUES (?, ?, ?)");
query.addBindValue(1);
query.addBindValue("flower2");
query.addBindValue(inByteArray);

if(sqlBool){
if(query.exec()){
qDebug() << "PictureModel::insertPic() sql insert executed fine!";
}
}
else{
qDebug() << "PictureModel::isertPic() sql insert did not execute!";
}
}

//---Displays pic stored in database---//
void PictureModel::displayPic(){
dbConnect();
QByteArray outByteArray;
QSqlQuery query(m_selectPictureDB);
bool sqlBool;
sqlBool = query.prepare("SELECT pic FROM picTable");
if (sqlBool){
qDebug() << "prepare sql display pic executed fine!";
if(query.exec()){
qDebug() << "execute sql display pic executed fine!";
}
else{
qDebug() << "execute sql display pic did not execute";
}
}
else{
qDebug() << "prepare sql display pic did not execute";
}

PictureModelStruct picList;
beginResetModel();
m_picList.clear();
while (query.next()){
picList.id = query.value(0).toString();
picList.picName = query.value(1).toString();
//outByteArray = query.value(2).toByteArray();
//picList.pic = QPixmap::fromImage(QImage::fromData(outByteArray, "jpg"));
addPicture(picList);
//requestImage(picList.id, QSize(20, 20), QSize(20, 20));
}
endResetModel();
emit showBusy(false);
m_selectPictureDB.close();
}

//---Selects name of pictures from DB for display---//
bool PictureModel::selectPictureName(){
dbConnect();
emit showBusy(true);
QSqlQuery selectQuery(m_selectPictureDB);
QByteArray outByteArray;
bool sqlBool;
sqlBool = selectQuery.prepare("SELECT DISTINCT picName FROM picTable ORDER BY picName ASC");
if(sqlBool){
if(selectQuery.exec()){
qDebug()<<"PictureModel::selectPictureName() select picName sql statement executed fine";
}
}
else{
emit xmui->alertMsg(QMessageBox::Warning, "Database selectPicture Error Message 1", "Error: sql select script..."+selectQuery.lastError().text());
qDebug()<<"PictureModel::selectPictureName() Error with sql statement execution " << selectQuery.lastError();
return selectQuery.exec();
}

PictureModelStruct picList;
beginResetModel();
m_picList.clear();

while (selectQuery.next()){
picList.id = selectQuery.value(0).toString();
picList.picName = selectQuery.value(1).toString();
//outByteArray = selectQuery.value(2).toByteArray();
//picList.pic = QPixmap::fromImage(QImage::fromData(outByteArray, "jpg"));
addPicture(picList);
}
endResetModel();
emit showBusy(false);
m_selectPictureDB.close();
return selectQuery.exec();
}


update:
cant seem to register the imageProvider properly not sure if im passing the parameter correctly to addImageProvider method


QQuickView view;
QQmlEngine *engine = view.engine();
engine->addImageProvider(QLatin1String("picture"), new PictureModel);

error: QQmlImageProviderBase is an inaccessible base of PictureModel

I have tried it a couple different ways, am I suppose to pass the class that subclasses imageProvider that is the model and has the requestImage() method in it?

anda_skoa
26th October 2016, 16:26
Yes I am missing the add/register the image provider not quite sure how to do that will have to read more
Im guessing I need to register the imageProvider with the QML engine like this ex from the doc

Yes.
E.g. rename "setContext" into "registerWithEngine", pass the engine and do both registrations in that method.



once its registered though you call it with the id from the QML Image source property like in the doc

yes, exactly.



I also get lost with how the "id" and scheme name are used to identify the image from data

Your data() needs to return QUrl objects that use the "image" scheme, your provider id and the image id.

Cheers,
_

jfinn88
26th October 2016, 17:04
Let me try registering it in my set context function

Added after 35 minutes:

Okay I think I have it registered with the qml engine now



//---Function is called in xmui.cpp---//
void PictureModel::registerWithEngine(QQmlEngine *engine){

//---Sets rootContext for model to be used in userListModel QML---//
engine->rootContext()->setContextProperty("PictureModel", this);

//---Registers Image provider with QML Engine---//
engine->addImageProvider(QLatin1String("picture"), new PictureModel);
}


now I'm not sure how to get the data() method over ridden properly for this situation

"return QUrl objects that use the "image" scheme, your provider id and the image id."

I'm not sure how to get the QUrl of the image to return
The image is stored in a data base its pulled out and then reassembled using QImage::fromImage() & QImage::fromData() in my displayPic() method

Is the image id just the idRole ?

I'm not sure what to pass the imageProvider in QML Image source property (imageFromYourProvider.png Is this the provider id ?)

//Picture is the registered imageProvider...



Image{
//source: "image://picture/imageFromYourProvider.png"
}



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

QVariant text;
//QImage image;

if(role == nameRole){
PictureModelStruct pList = m_picList.at(index.row());
text = pList.picName;
}

// if(role == idRole){
// PictureModelStruct pList = m_picList.at(index.row());
// text = pList.id;
// }
// else if(role == picRole){
// PictureModelStruct pList = m_picList.at(index.row());
// image = pList.pic;
// }
return text;
}


Do I still need to add the image to my data Struct created for the model ? Or do I create the QUrl for the image instead (just not sure how to create a QUrl for an image)

anda_skoa
26th October 2016, 18:41
//---Function is called in xmui.cpp---//
void PictureModel::registerWithEngine(QQmlEngine *engine){

//---Sets rootContext for model to be used in userListModel QML---//
engine->rootContext()->setContextProperty("PictureModel", this);

//---Registers Image provider with QML Engine---//
engine->addImageProvider(QLatin1String("picture"), new PictureModel);
}


This looks very wrong.
Why is there a "new PictureModel" instead of "this"?



Is the image id just the idRole ?

The image ID is whatever you use to identifiy a single image.
The ID is what you get as part of the image provider request call, it needs to enable you to return the correct image.

So either some index into an internal list or something that you can use to get the data from the database.



I'm not sure what to pass the imageProvider in QML Image source property (imageFromYourProvider.png Is this the provider id ?)

yes.

The URLs have the form of "image://" + image provider name + "/" + imageId



Do I still need to add the image to my data Struct created for the model ?

That is you choice.
If you add the image to the model entry then the id can simply be the row index of that entry.



Or do I create the QUrl for the image instead (just not sure how to create a QUrl for an image)
That is also possible.
The URLs in this case use the "data" scheme. Not sure how these are correctly formatted, though. They carry the image data as part of the URL string, one of the options aside from image provider.

Cheers,
_

jfinn88
27th October 2016, 16:51
This looks very wrong.
Why is there a "new PictureModel" instead of "this"?


I will work on this part and change to this was working from example and forgot to change it.

anda_skoa
27th October 2016, 18:25
I will work on this part and change to this was working from example and forgot to change it.
Ah, ok.

Then your image URLs should be something like "image://picture/somenumber" if you are using the row index into your element list as the image id part.

Your commented code in requestImage() suggests that you already had that idea, but instead of calling record you can simply access your m_picList and return the "pic" of the respective entry.

Cheers,
_