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();
}
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();
}