Results 1 to 20 of 25

Thread: Getting an image from mysql database (as BLOB field) through subclassed QSqlQueryMode

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Jan 2006
    Location
    Ljubljana
    Posts
    687
    Thanks
    111
    Thanked 4 Times in 4 Posts
    Qt products
    Qt5 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Getting an image from mysql database (as BLOB field) through subclassed QSqlQueryMode

    I am working on Qt/QML app, which connects to mysql database and fetches data from it. Now, how do I fetch image from database (as BLOB field) using QSqlQueryModel? Now, I know how to connect to database, I've written simple read only subclassed QSqlQueryModel, I do know how to get the value of some field, but how do I get image and show it in some QML ListView? Does anyone has some experience and/or example with QQuickImageProvider, is this right way to go?
    Qt 5.3 Opensource & Creator 3.1.2

  2. #2
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Getting an image from mysql database (as BLOB field) through subclassed QSqlQuery

    Your model needs to return some string id for each image when its data() method is called by the view.
    The view's delegate then needs to use that id to construct an "image://" URL.
    Your image provider then needs to convert the BLOB data for that id to a QImage.

    Cheers,
    _

  3. The following user says thank you to anda_skoa for this useful post:

    MarkoSan (14th August 2015)

  4. #3
    Join Date
    Jan 2006
    Location
    Ljubljana
    Posts
    687
    Thanks
    111
    Thanked 4 Times in 4 Posts
    Qt products
    Qt5 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: Getting an image from mysql database (as BLOB field) through subclassed QSqlQuery

    Quote Originally Posted by anda_skoa View Post
    Your model needs to return some string id for each image when its data() method is called by the view.
    The view's delegate then needs to use that id to construct an "image://" URL.
    Your image provider then needs to convert the BLOB data for that id to a QImage.

    Cheers,
    _
    Can you please provide me some example?
    Qt 5.3 Opensource & Creator 3.1.2

  5. #4
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Getting an image from mysql database (as BLOB field) through subclassed QSqlQuery

    Qt Code:
    1. QVariant MyModel::data(const QModelIndex & index, int role) const
    2. {
    3. if (role == ImageRole) {
    4. return QString::number(index.row());
    5. }
    6.  
    7. /// other data
    8. }
    9.  
    10. QImage MyModel::image(const QString &id) const
    11. {
    12. int row = id.toInt();
    13.  
    14. // load BLOB for image on row "row", return
    15. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. Image {
    2. source: "image://mysqlimageprovider/" * model.image
    3. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. QImage MyImageProvider::requestImage(const QString &d, QSize *size, const QSize &requestedSize, bool requestedAutoTransform)
    2. {
    3. QImage image = myModel->image(id);
    4. *size = image.size();
    5. return image;
    6. }
    To copy to clipboard, switch view to plain text mode 

    You could even inherit your model from both the current base class and QQuickImageProvider.

    Cheers,
    _

  6. #5
    Join Date
    Jan 2006
    Location
    Ljubljana
    Posts
    687
    Thanks
    111
    Thanked 4 Times in 4 Posts
    Qt products
    Qt5 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: Getting an image from mysql database (as BLOB field) through subclassed QSqlQuery

    Quote Originally Posted by anda_skoa View Post
    Qt Code:
    1. QVariant MyModel::data(const QModelIndex & index, int role) const
    2. {
    3. if (role == ImageRole) {
    4. return QString::number(index.row());
    5. }
    6.  
    7. /// other data
    8. }
    9.  
    10. QImage MyModel::image(const QString &id) const
    11. {
    12. int row = id.toInt();
    13.  
    14. // load BLOB for image on row "row", return
    15. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. Image {
    2. source: "image://mysqlimageprovider/" * model.image
    3. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. QImage MyImageProvider::requestImage(const QString &d, QSize *size, const QSize &requestedSize, bool requestedAutoTransform)
    2. {
    3. QImage image = myModel->image(id);
    4. *size = image.size();
    5. return image;
    6. }
    To copy to clipboard, switch view to plain text mode 

    You could even inherit your model from both the current base class and QQuickImageProvider.

    Cheers,
    _
    Wow, superb idea! Will try asap!
    Qt 5.3 Opensource & Creator 3.1.2

  7. #6
    Join Date
    Jan 2006
    Location
    Ljubljana
    Posts
    687
    Thanks
    111
    Thanked 4 Times in 4 Posts
    Qt products
    Qt5 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: Getting an image from mysql database (as BLOB field) through subclassed QSqlQuery

    Hmm, it seems I've forgot a little about Qt models, here is my code, first header file:
    Qt Code:
    1. #ifndef UEPEOPLEMODEL_H
    2. #define UEPEOPLEMODEL_H
    3.  
    4. #include <QImage>
    5. #include <QVariant>
    6. #include <QStringList>
    7. #include <QDebug>
    8. #include <QHash>
    9. #include <QByteArray>
    10. #include <QtSql/QSqlError>
    11. #include <QtSql/QSqlQueryModel>
    12. #include <QtSql/QSqlRecord>
    13. #include <QModelIndex>
    14. #include <QQuickImageProvider>
    15.  
    16. #include "../settings/uedefaults.h"
    17.  
    18. class UePeopleModel : public QSqlQueryModel, QQuickImageProvider
    19. {
    20. Q_OBJECT
    21.  
    22. /*
    23. private:
    24.   QHash<int, QByteArray> m_ueRoleNames;
    25.  
    26.   void ueGenerateRoleNames();
    27. */
    28.  
    29. public:
    30. UePeopleModel(QObject *parent=0);
    31. ~UePeopleModel();
    32.  
    33. QVariant data(const QModelIndex &index,
    34. int role) const Q_DECL_OVERRIDE;
    35. // void ueRefresh();
    36. /*
    37.   inline QHash<int, QByteArray> roleNames() const
    38.   { return this->m_ueRoleNames; }
    39. */
    40.  
    41. public:
    42. static const int UePersonNameRole=Qt::UserRole+1;
    43. static const int UePersonImageRole=UePersonNameRole+1;
    44. };
    45.  
    46. #endif // UEPEOPLEMODEL_H
    To copy to clipboard, switch view to plain text mode 
    and its implementation:
    Qt Code:
    1. #include "uepeoplemodel.h"
    2.  
    3. UePeopleModel::UePeopleModel(QObject* parent)
    4. : QSqlQueryModel(parent),
    5. QQuickImageProvider(QQmlImageProviderBase::Image,
    6. 0)
    7. {
    8.  
    9. if(!QSqlDatabase::connectionNames().contains(UePosDatabase::UeDatabaseConnectionNames::DATABASE_CONNECTION_NAME_PEOPLE,
    10. Qt::CaseInsensitive))
    11. {
    12. db=QSqlDatabase::addDatabase(UePosDatabase::DATABASE_DRIVER,
    13. UePosDatabase::UeDatabaseConnectionNames::DATABASE_CONNECTION_NAME_PEOPLE);
    14. } // if
    15.  
    16. db.setHostName(/*this->uePosSettings()->ueDbHostname()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_HOSTNAME);
    17. db.setDatabaseName(/*this->uePosSettings()->ueDbName()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_NAME);
    18. db.setUserName(/*this->uePosSettings()->ueDbUser()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_USERNAME);
    19. db.setPassword(/*this->uePosSettings()->ueDbPassword()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_PASSWORD);
    20.  
    21. if(db.open())
    22. {
    23. this->setQuery(UePosDatabase::UeSqlQueries::UeTablePeople::SQL_QUERY_GET_ALL_PEOPLE,
    24. db);
    25. //this->ueGenerateRoleNames();
    26. }
    27. else
    28. {
    29. qDebug() << db.lastError().text();
    30. }
    31. } // default constructor
    32.  
    33. UePeopleModel::~UePeopleModel()
    34. {
    35. } // default destructor
    36.  
    37. QVariant UePeopleModel::data(const QModelIndex &index,
    38. int role) const
    39. {
    40. // QVariant value;
    41.  
    42. // if(role<Qt::UserRole)
    43. // {
    44. // value=QSqlQueryModel::data(index,
    45. // role);
    46. // }
    47. // else
    48. // {
    49. // int iColumnIndex=role-Qt::UserRole-1;
    50. // QModelIndex modelIndex=this->index(index.row(),
    51. // iColumnIndex);
    52.  
    53. // value=QSqlQueryModel::data(modelIndex,
    54. // Qt::DisplayRole);
    55. // } // if
    56.  
    57. // return value;
    58.  
    59. QVariant value=QSqlQueryModel::data(index,
    60. role);
    61.  
    62. if(value.isValid()&&role==Qt::DisplayRole)
    63. {
    64. switch(index.column())
    65. {
    66. case UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_ID:
    67. return value.toInt();
    68.  
    69. case UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_NAME:
    70. return value.toString();
    71.  
    72. case UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_APPPASSWORD:
    73. return value.toString();
    74.  
    75. case UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_CARD:
    76. return value.toString();
    77.  
    78. case UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_IMAGE:
    79. {
    80. QImage image;
    81.  
    82. image.loadFromData(value.toByteArray());
    83.  
    84. return image;
    85. } // case
    86.  
    87. default:
    88. return value;
    89. } // switch
    90. } // if
    91.  
    92. return QVariant();
    93. } // data
    94.  
    95. /*
    96. void UePeopleModel::ueRefresh()
    97. {
    98.   this->setQuery(UePosDatabase::UeSqlQueries::UeTablePeople::SQL_QUERY_GET_ALL_PEOPLE);
    99. } // ueRefresh
    100. */
    101.  
    102. //void UePeopleModel::ueGenerateRoleNames()
    103. //{
    104. // //this->roleNames().clear();
    105. // m_ueRoleNames.clear();
    106. // for(int iIndex=0; iIndex<this->record().count(); iIndex++)
    107. // {
    108. ///*
    109. // this->roleNames().insert(Qt::UserRole+1+iIndex,
    110. // this->record().fieldName(iIndex).toUtf8());
    111. //*/
    112. // m_ueRoleNames.insert(Qt::UserRole+1+iIndex,
    113. // this->record().fieldName(iIndex).toUtf8());
    114. // } // for
    115. //} // ueGenerateRoleNames
    To copy to clipboard, switch view to plain text mode 
    Am I using Qt:isplayRole in right way or should I implement custom roles? And how do I then use this data()method in qml?
    Qt 5.3 Opensource & Creator 3.1.2

  8. #7
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Getting an image from mysql database (as BLOB field) through subclassed QSqlQuery

    You can use Qt:isplayRole, it is mapped by default to "model.display" in QML.

    However, you need to keep in mind that the QtQuick views, e.g. ListView or TableView, do not deal with model columns, only rows, so you will need custom roles anyway.

    I would suggest to use custom roles for all columns and not use Qt:isplayRole other than maybe for debugging (e.g. with a QWidget based table view).

    So in your data() method you first need to map the role to a column and then proceed with quering the data from the base class.

    Cheers,
    _

  9. The following user says thank you to anda_skoa for this useful post:

    MarkoSan (16th August 2015)

  10. #8
    Join Date
    Jan 2006
    Location
    Ljubljana
    Posts
    687
    Thanks
    111
    Thanked 4 Times in 4 Posts
    Qt products
    Qt5 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows Android

    Lightbulb Re: Getting an image from mysql database (as BLOB field) through subclassed QSqlQuery

    Ok, I am a little lost now. I've done this:
    Qt Code:
    1. #ifndef UEPEOPLEMODEL_H
    2. #define UEPEOPLEMODEL_H
    3.  
    4. #include <QImage>
    5. #include <QVariant>
    6. #include <QStringList>
    7. #include <QDebug>
    8. #include <QHash>
    9. #include <QByteArray>
    10. #include <QtSql/QSqlError>
    11. #include <QtSql/QSqlQueryModel>
    12. #include <QtSql/QSqlRecord>
    13. #include <QModelIndex>
    14. #include <QQuickImageProvider>
    15.  
    16. #include "../settings/uedefaults.h"
    17.  
    18. class UePeopleModel : public QSqlQueryModel, QQuickImageProvider
    19. {
    20. Q_OBJECT
    21.  
    22. public:
    23. UePeopleModel(QObject *parent=0);
    24. ~UePeopleModel();
    25.  
    26. QVariant data(const QModelIndex &index,
    27. int role) const Q_DECL_OVERRIDE;
    28. QImage image(const QString &id) const;
    29. QImage requestImage(const QString &id,
    30. QSize *size,
    31. const QSize &requestedSize);
    32.  
    33. public:
    34. static const int UePersonNameRole=Qt::UserRole+1;
    35. static const int UePersonImageRole=UePersonNameRole+1;
    36. };
    37.  
    38. #endif // UEPEOPLEMODEL_H
    To copy to clipboard, switch view to plain text mode 
    and implementation:
    Qt Code:
    1. #include "uepeoplemodel.h"
    2.  
    3. UePeopleModel::UePeopleModel(QObject* parent)
    4. : QSqlQueryModel(parent),
    5. QQuickImageProvider(QQmlImageProviderBase::Image,
    6. QQmlImageProviderBase::ForceAsynchronousImageLoading)
    7. {
    8.  
    9. if(!QSqlDatabase::connectionNames().contains(UePosDatabase::UeDatabaseConnectionNames::DATABASE_CONNECTION_NAME_PEOPLE,
    10. Qt::CaseInsensitive))
    11. {
    12. db=QSqlDatabase::addDatabase(UePosDatabase::DATABASE_DRIVER,
    13. UePosDatabase::UeDatabaseConnectionNames::DATABASE_CONNECTION_NAME_PEOPLE);
    14. } // if
    15.  
    16. db.setHostName(/*this->uePosSettings()->ueDbHostname()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_HOSTNAME);
    17. db.setDatabaseName(/*this->uePosSettings()->ueDbName()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_NAME);
    18. db.setUserName(/*this->uePosSettings()->ueDbUser()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_USERNAME);
    19. db.setPassword(/*this->uePosSettings()->ueDbPassword()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_PASSWORD);
    20.  
    21. if(db.open())
    22. {
    23. this->setQuery(UePosDatabase::UeSqlQueries::UeTablePeople::SQL_QUERY_GET_ALL_PEOPLE,
    24. db);
    25. //this->ueGenerateRoleNames();
    26. }
    27. else
    28. {
    29. qDebug() << db.lastError().text();
    30. }
    31. } // default constructor
    32.  
    33. UePeopleModel::~UePeopleModel()
    34. {
    35. } // default destructor
    36.  
    37. QVariant UePeopleModel::data(const QModelIndex &index,
    38. int role) const
    39. {
    40. QVariant value=QSqlQueryModel::data(index,
    41. role);
    42. if(value.isValid())
    43. {
    44. switch(role)
    45. {
    46. case UePeopleModel::UePersonNameRole:
    47. {
    48. return value.toString();
    49. } // case
    50.  
    51. case UePeopleModel::UePersonImageRole:
    52. {
    53. return QString::number(index.row());
    54. } // case
    55.  
    56. default:
    57. value=QVariant();
    58. } // switch
    59. } // if
    60.  
    61. return value;
    62. } // data
    63.  
    64. QImage UePeopleModel::image(const QString &id) const
    65. {
    66. int iRow=id.toInt();
    67. } // image
    68.  
    69. QImage UePeopleModel::requestImage(const QString &id,
    70. QSize *size,
    71. const QSize &requestedSize)
    72. {
    73. QImage image=this->image(id);
    74.  
    75. *size = image.size();
    76.  
    77. return image;
    78. } // requestImage
    To copy to clipboard, switch view to plain text mode 
    Now what?
    Qt 5.3 Opensource & Creator 3.1.2

  11. #9
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Getting an image from mysql database (as BLOB field) through subclassed QSqlQuery

    Couple of things:

    - in order to be able to use this class as a QQuickImageProvider, it needs to have a "is-a" relation ship, i.e. publically inherit from QQuickImageProvider
    - in data() it doesn't make sense to use the role as given to query the base class, after all these roles will most often be your custom roles and have no meaning for the base class
    - you are missing the roleNames() override that returns the mapping of role names (used in QML) to role numbers (using in the C++ API).

    Cheers,
    _

  12. The following user says thank you to anda_skoa for this useful post:

    MarkoSan (20th August 2015)

  13. #10
    Join Date
    Jan 2006
    Location
    Ljubljana
    Posts
    687
    Thanks
    111
    Thanked 4 Times in 4 Posts
    Qt products
    Qt5 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows Android

    Angry Re: Getting an image from mysql database (as BLOB field) through subclassed QSqlQuery

    Quote Originally Posted by anda_skoa View Post
    Couple of things:

    - in order to be able to use this class as a QQuickImageProvider, it needs to have a "is-a" relation ship, i.e. publically inherit from QQuickImageProvider
    - in data() it doesn't make sense to use the role as given to query the base class, after all these roles will most often be your custom roles and have no meaning for the base class
    - you are missing the roleNames() override that returns the mapping of role names (used in QML) to role numbers (using in the C++ API).

    Cheers,
    _
    Well, class is publicly inherited from QQuickImageProvider:
    Qt Code:
    1. class UePeopleModel : public QSqlQueryModel, QQuickImageProvider
    To copy to clipboard, switch view to plain text mode 
    I've upgraded function data(), is now ok:
    Qt Code:
    1. QVariant UePeopleModel::data(const QModelIndex &index,
    2. int role) const
    3. {
    4. QVariant value=QSqlQueryModel::data(index,
    5. role);
    6. if(value.isValid())
    7. {
    8. switch(role)
    9. {
    10. case ueRoleName:
    11. {
    12. return value.toString();
    13. } // case
    14.  
    15. case ueRoleImage:
    16. {
    17. return QString::number(index.row());
    18. } // case
    19.  
    20. default:
    21. value=QVariant();
    22. } // switch
    23. } // if
    24.  
    25. return value;
    26. } // data
    To copy to clipboard, switch view to plain text mode 
    But what do I have to put inside method UePeopleModel::image?

    Sincerely yours,
    Marko
    Qt 5.3 Opensource & Creator 3.1.2

  14. #11
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Getting an image from mysql database (as BLOB field) through subclassed QSqlQuery

    Quote Originally Posted by MarkoSan View Post
    Well, class is publicly inherited from QQuickImageProvider:
    Qt Code:
    1. class UePeopleModel : public QSqlQueryModel, QQuickImageProvider
    To copy to clipboard, switch view to plain text mode 
    Nope. Unless your code looks different in reality, this is a private inheritance

    Quote Originally Posted by MarkoSan View Post
    I've upgraded function data(), is now ok:
    Nope, see my last comment.

    Quote Originally Posted by MarkoSan View Post
    But what do I have to put inside method UePeopleModel::image?
    You get the BLOB from the base class for the given row and then load it into a QImage.
    If the BLOB is data in a format known to Qt, then you can probably use QImage::loadFromData().

    Cheers,
    _

Similar Threads

  1. Replies: 4
    Last Post: 16th June 2011, 14:49
  2. Read BLOB from MySQL database
    By zero-n in forum Newbie
    Replies: 3
    Last Post: 22nd May 2011, 19:59
  3. How to update BLOB field in a SQLite database ?
    By aircraftstories in forum Qt Programming
    Replies: 6
    Last Post: 8th April 2011, 20:45
  4. Replies: 2
    Last Post: 17th February 2010, 14:32
  5. Replies: 1
    Last Post: 14th September 2009, 08:48

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.