Page 1 of 2 12 LastLast
Results 1 to 20 of 24

Thread: Populate Listview from Database

  1. #1
    Join Date
    Jul 2016
    Posts
    26
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows Android

    Question Populate Listview from Database

    I want to populate listview ( a specific page in my app ) from a database .

    Currently the page is static and look like this

    image: https://s32.postimg.org/vrsdrl2p1/man.png

    code :
    Qt Code:
    1. import QtQuick 2.6
    2. import QtQuick.Layouts 1.1
    3. import QtQuick.Controls 2.0
    4.  
    5.  
    6. Pane {
    7. padding: 0
    8.  
    9. property var delegateComponentMap: {
    10. "page": itemDelegateComponent
    11.  
    12. }
    13.  
    14. Component {
    15. id: itemDelegateComponent
    16.  
    17. ItemDelegate {
    18. text: labelText
    19. width: parent.width
    20. }
    21. }
    22.  
    23.  
    24.  
    25.  
    26.  
    27.  
    28. ColumnLayout {
    29. id: column
    30. spacing: 40
    31. anchors.fill: parent
    32. anchors.topMargin: 20
    33.  
    34. Label {
    35. id: label1
    36. Layout.fillWidth: true
    37. wrapMode: Label.Wrap
    38. horizontalAlignment: Qt.AlignHCenter
    39. text: "Offline Pages "
    40. }
    41.  
    42. ListView {
    43. id: listView
    44.  
    45. Layout.fillWidth: true
    46. Layout.fillHeight: true
    47. clip: true
    48. model: ListModel {
    49. ListElement { type: "ItemDelegate"; labelText: "page1" }
    50. ListElement { type: "ItemDelegate"; labelText: "page2" }
    51. ListElement { type: "ItemDelegate"; labelText: "page3" }
    52.  
    53.  
    54. }
    55. spacing: 5
    56.  
    57. section.property: "type"
    58.  
    59. delegate: Component{
    60.  
    61. Item{
    62. id: aItem
    63. width: listView.width //rowLayout.width. We got width from children elements before, now get width from listView
    64. height: 30
    65.  
    66. RowLayout{
    67.  
    68. id: rowLayout
    69. anchors.fill: parent
    70. spacing: 10
    71.  
    72. Label{
    73. id:page_name
    74. padding: 10
    75. text: labelText
    76. Layout.fillWidth: true // !!! to fill most part of row width
    77.  
    78. }
    79.  
    80.  
    81. Button{
    82.  
    83. text: qsTr("Delete")
    84.  
    85. id: delete_button
    86.  
    87. }
    88. Button{
    89.  
    90. text: qsTr("Update")
    91. id: update_button
    92. }
    93.  
    94.  
    95.  
    96. }
    97. }
    98. }
    99. }
    100.  
    101.  
    102.  
    103.  
    104.  
    105.  
    106.  
    107.  
    108.  
    109. RowLayout{
    110. Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
    111.  
    112. Button{
    113. text:"Update All"
    114.  
    115.  
    116. }
    117. Button{
    118. text:"Delete All"
    119. }
    120. }
    121. }
    122. }
    To copy to clipboard, switch view to plain text mode 

    my databse only has 2 entries ( looks like this ) . the databse is stored in genericelocation

    db : https://s32.postimg.org/jb4nhmoxh/image.png

    how should i approach this task ?

  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: Populate Listview from Database

    If the database is an Sqlite file compatible with QML LocalStorage then you can probably use that to add entries to the QML ListModel you have.

    Alternatively you use a C++ list model for the ListView and expose either an instance of it to QML or register the model as a type an instantiate it from QML.

    For the model there are a couple of approaches:

    - derive from QAbstractListModel and do the database query inside of it

    - derive from QSqlQueryModel and overwrite data() such that it maps QML roles to columns of the base class.

    Cheers,
    _

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

    arcade (31st July 2016)

  4. #3
    Join Date
    Jul 2016
    Posts
    26
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows Android

    Default Re: Populate Listview from Database

    Quote Originally Posted by anda_skoa View Post
    If the database is an Sqlite file compatible with QML LocalStorage then you can probably use that to add entries to the QML ListModel you have.

    Alternatively you use a C++ list model for the ListView and expose either an instance of it to QML or register the model as a type an instantiate it from QML.

    For the model there are a couple of approaches:

    - derive from QAbstractListModel and do the database query inside of it

    - derive from QSqlQueryModel and overwrite data() such that it maps QML roles to columns of the base class.

    Cheers,
    _
    Hello , thanks for answering my question . about the first approach using " QML Localstorage" , i do have a sqlite DB but it is stored in some genericLocation

    i am storing the database at this path

    QString path = QStandardPaths::writableLocation(QStandardPaths::G enericDataLocation);

    Can i still open the database ?

    for ex :

    this is where the db is stored : /home/arcade/.local/share/WTL_appdata/wtl.db

    but this path will be different for everyone right .

  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: Populate Listview from Database

    No, I don't think LocalStorage can be configured for a different path than the one it is using by default.

    You'll have to create a model yourself.
    If you already have database access code then the simplest solution is probably to create your own list model.
    http://doc.qt.io/qt-5/qtquick-modelv...model-subclass

    Cheers,
    _

  6. #5
    Join Date
    Jul 2016
    Posts
    26
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows Android

    Default Re: Populate Listview from Database

    Thanks !! . Just more thing is there any example which i can refer too ?

    An example that fits my case ?

  7. #6
    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: Populate Listview from Database

    The link in my previous comment is about an actual example.

    Cheers,
    _

  8. #7
    Join Date
    Jul 2016
    Posts
    26
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows Android

    Default Re: Populate Listview from Database

    Hello , i am still not sure how to create the model for my need . If possible can you break the task for me ??

    My project goes like this :

    1. all of my program logic is in dbmanager.cpp file
    2. main.cpp is just used to instantiate some files and settings
    3. main.qml holds main UI

    code base : https://github.com/hackertron/W2L/tree/master/UI

  9. #8
    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: Populate Listview from Database

    First you need a data structure that can hold all values for a single list entry, e.g. something like
    Qt Code:
    1. struct ListEntry
    2. {
    3. QString label;
    4. };
    To copy to clipboard, switch view to plain text mode 
    This is like the Animal class in the example.

    Then you need a QAbstractListModel derived class that has a list or vector of that structure.
    Qt Code:
    1. class MyModel : public QAbstractListModel
    2. {
    3.  
    4. private:
    5. QList<ListEntry> m_entries;
    6. };
    To copy to clipboard, switch view to plain text mode 
    Then you need to implement rowCount(), data() and roleNames() like in the example.

    Then you add methods that the database class can call to access the list of entries, so that it can fill it, update it, etc.
    QAbstractItemModel defines a set of protected helper methods that need to be used if the model's content is changed after it has been passed to a view, e.g. calling beingInsertRows() and endInsertRows() when new entries need to be added to "m_entries"

    Cheers,
    _

  10. #9
    Join Date
    Jul 2016
    Posts
    26
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows Android

    Default Re: Populate Listview from Database

    Hello , thanks for the breaking up the steps

    Below is what i have tried

    model.h

    Qt Code:
    1. #include <QAbstractListModel>
    2. #include <QStringList>
    3.  
    4. //![0]
    5. class list
    6. {
    7. public:
    8. list(const QString &title, const QString &id);
    9. //![0]
    10. //type title size id animal list
    11. QString title() const;
    12. QString id() const;
    13.  
    14. private:
    15. QString m_title;
    16. QString m_id;
    17. //![1]
    18. };
    19.  
    20. class listmodel : public QAbstractListModel
    21. {
    22. Q_OBJECT
    23. public:
    24. enum listroles {
    25. titlerole = Qt::UserRole + 1,
    26. idrole
    27. };
    28.  
    29. listmodel(QObject *parent = 0);
    30.  
    31.  
    32. void addpages(const list &list);
    33.  
    34. int rowCount(const QModelIndex & parent = QModelIndex()) const;
    35.  
    36. QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
    37.  
    38. protected:
    39. QHash<int, QByteArray> roleNames() const;
    40. private:
    41. QList<list> m_list;
    42.  
    43. };
    To copy to clipboard, switch view to plain text mode 

    model.cpp

    Qt Code:
    1. #include "model.h"
    2.  
    3. list::list(const QString &title, const QString &id)
    4. : m_title(title), m_id(id)
    5. {
    6. }
    7.  
    8. QString list::title() const
    9. {
    10. return m_title;
    11. }
    12.  
    13. QString list::id() const
    14. {
    15. return m_id;
    16. }
    17.  
    18. listmodel::listmodel(QObject *parent)
    19. {
    20. }
    21.  
    22. void listmodel::addpages(const list &list)
    23. {
    24. beginInsertRows(QModelIndex(), rowCount(), rowCount());
    25. m_list << list;
    26. endInsertRows();
    27. }
    28.  
    29. int listmodel::rowCount(const QModelIndex & parent) const {
    30. Q_UNUSED(parent);
    31. return m_list.count();
    32. }
    33.  
    34. QVariant listmodel::data(const QModelIndex & index, int role) const {
    35. if (index.row() < 0 || index.row() >= m_list.count())
    36. return QVariant();
    37.  
    38. const list &list = m_list[index.row()];
    39. if (role == titlerole)
    40. return list.title();
    41. else if (role == idrole)
    42. return list.id();
    43. return QVariant();
    44. }
    45.  
    46. //![0]
    47. QHash<int, QByteArray> listmodel::roleNames() const {
    48. QHash<int, QByteArray> roles;
    49. roles[titlerole] = "title";
    50. roles[idrole] = "id";
    51. return roles;
    52. }
    53. //![0]
    To copy to clipboard, switch view to plain text mode 


    main.cpp snippet

    Qt Code:
    1. listmodel mod;
    2.  
    3.  
    4. if(!db.open())
    5. {
    6. qDebug() <<"error in opening DB";
    7. }
    8. else
    9. {
    10. qDebug() <<"connected to DB" ;
    11.  
    12. }
    13.  
    14. QVector<QString> page_id;
    15. QVector<QString> rev_id;
    16.  
    17. QSqlQuery quer("SELECT page_ID , page_revision FROM Pages");
    18. while (quer.next()) {
    19. QString i = quer.value(0).toString();
    20. page_id.push_back(i);
    21. QString r = quer.value(1).toString();
    22. rev_id.push_back(r);
    23.  
    24.  
    25. }
    26. for (int i = 0; i < page_id.size(); ++i)
    27. {
    28. qDebug() << page_id.at(i).toLocal8Bit().constData() << endl;
    29. qDebug() << rev_id.at(i).toLocal8Bit().constData() << endl;
    30. mod.addpages(list(page_id.at(i) , rev_id.at(i)));
    31.  
    32.  
    33.  
    34.  
    35. }
    36.  
    37.  
    38.  
    39.  
    40.  
    41. QQmlContext *ctxt = engine.rootContext();
    42. ctxt->setContextProperty("myModel", &mod);
    To copy to clipboard, switch view to plain text mode 

    qml

    Qt Code:
    1. import QtQuick 2.6
    2. import QtQuick.Layouts 1.1
    3. import QtQuick.Controls 1.3
    4. import QtQuick.Window 2.2
    5. import QtQuick.Dialogs 1.2
    6. import QtQuick.Layouts 1.1
    7. import QtQuick.Controls 2.0
    8. import Qt.labs.folderlistmodel 2.1
    9.  
    10. Pane{
    11.  
    12. ListView {
    13. width: 200; height: 250
    14.  
    15. model: myModel
    16. delegate: Text { text: "pages: " + title + ", " + id }
    17.  
    18. }
    19. }
    To copy to clipboard, switch view to plain text mode 

    OUTPUT :
    1.png

    As you can see it's not even close to my original view : https://s32.postimg.org/vrsdrl2p1/man.png

    now i need to add buttons to it but how ?

  11. #10
    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: Populate Listview from Database

    You just changed your model, so you can just keep using your already working QML code.

    Your original QML code just needs to use the new role names or you change your model so that is uses the original role names.

    Cheers,
    _

  12. #11
    Join Date
    Jul 2016
    Posts
    26
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows Android

    Default Re: Populate Listview from Database

    Yeah , i got it

    See this : up.png ( still need to do some work on it , but it's fine for now )

    Now how to actually make it show/hide item dynamically

    ex : when i save a new page it should show that page too . If i remove the page it should remove it from the view too .


    what should i do ?

  13. #12
    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: Populate Listview from Database

    Look at the code you have in listmodel::addpages()

    That adds (in this case appends) a row to the model.
    Removing a row is almost the same, just with beginRemoveRows() and endRemoveRows()

    Cheers,
    _

  14. #13
    Join Date
    Jul 2016
    Posts
    26
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows Android

    Default Re: Populate Listview from Database

    hello . I am trying something like this

    scene : when someone clicks on delete button , i handle it like this

    Qt Code:
    1. Button{
    2. text: "delete"
    3. onClicked: {
    4. dbman.del(id) // this one actually deletes file from db and from system , works fine
    5. mod.deletepages(id) // this is what i am trying to implement
    6. }
    To copy to clipboard, switch view to plain text mode 

    so what mod.deletepages(id) do is get the id of the page and send it to here

    Qt Code:
    1. void listmodel::deletepages(QString pageid)
    2. {
    3.  
    4.  
    5. qDebug() << pageid;
    6. beginRemoveRows(QModelIndex(),remove,remove);
    7. endInsertRows();
    8. }
    To copy to clipboard, switch view to plain text mode 

    now what i have is the value not the index . how to get the index of that value .

    i have tried to use m_list.indexOf(pageid) ;

    but i get error " error: no matching function for call to 'QList<list>::indexOf(QString&)'
    int remove = m_list.indexOf(pageid); "
    ^

    so how to get the index

  15. #14
    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: Populate Listview from Database

    The easiest way is to pass the row index, since the view and the model have the same concept of what a row is

    In your delegate
    Qt Code:
    1. mod.deletepages(model.index)
    To copy to clipboard, switch view to plain text mode 

    In your model
    Qt Code:
    1. void listmodel::deletepages(int row)
    2. {
    3. beginRemoveRows(QModelIndex(), row, row);
    4. m_list.remove(row);
    5. endRemoveRows();
    6. }
    To copy to clipboard, switch view to plain text mode 

    Ideally you don't do two calls from QML though, but have one C++ method that modifies the model and the database.
    Otherwise you could forget one and model and database could get out of sync.

    Cheers,
    _

  16. #15
    Join Date
    Jul 2016
    Posts
    26
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows Android

    Default Re: Populate Listview from Database

    Hello i got the index but i am not able to remove the item from m_list .

    ERROR that i am getting is : error.png


    Added after 8 minutes:


    Yeah i got it . it was removeAt() instead of remove()

    Thanks !!
    Last edited by arcade; 7th August 2016 at 10:58.

  17. #16
    Join Date
    Jul 2016
    Posts
    26
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows Android

    Default Re: Populate Listview from Database

    hey now if i add / save a page offline , i want it to show it in the view too .


    ex : i opened my app click on save button to save page . it should show that saved page in the view too .

    i tried to call the addpages function along with my save page function , but it is not adding or showing it in view .

  18. #17
    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: Populate Listview from Database

    Hmm your addpages() method should append an entry to the list model.

    How do you call it?

    Cheers,
    _

  19. #18
    Join Date
    Jul 2016
    Posts
    26
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows Android

    Default Re: Populate Listview from Database

    Like this

    Qt Code:
    1. save_file(text , pageid , revid , page_title);
    2. listmodel mod;
    3. mod.addpages(list(page_title,QString(pageid)));
    To copy to clipboard, switch view to plain text mode 

  20. #19
    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: Populate Listview from Database

    So you are creating a new model and adding the page there?

    Don't you want to add the "list" entry to the existing model?

    Cheers,
    _

  21. #20
    Join Date
    Jul 2016
    Posts
    26
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows Android

    Default Re: Populate Listview from Database

    Quote Originally Posted by anda_skoa View Post
    So you are creating a new model and adding the page there?

    Don't you want to add the "list" entry to the existing model?

    Cheers,
    _
    yes i want to add it in the same model !!

Similar Threads

  1. Replies: 2
    Last Post: 17th May 2016, 00:50
  2. Replies: 24
    Last Post: 14th March 2016, 09:58
  3. Replies: 0
    Last Post: 16th October 2015, 17:51
  4. Populate QTreeView from database
    By yagabey in forum Qt Programming
    Replies: 15
    Last Post: 26th March 2015, 03:10
  5. Replies: 2
    Last Post: 26th March 2015, 02:56

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.