Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QSqlRelationalTableModel with multiple Joins?
Forum Updated to NodeBB v4.3 + New Features

QSqlRelationalTableModel with multiple Joins?

Scheduled Pinned Locked Moved Unsolved General and Desktop
67 Posts 4 Posters 25.1k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D devhobby
    8 Feb 2018, 18:46

    @JonB said in QSqlRelationalTableModel with multiple Joins?:

    @devhobby

    I think we use QTableWidget, not just QTableView.

    http://www.qtcentre.org/threads/46245-QTableWidgetItem-setflags-strange-behavior?p=209282#post209282 shows you accessing QTableWidgetItem. http://doc.qt.io/qt-5/qtablewidget.html#item

    http://doc.qt.io/qt-5/qtablewidget.html#details:

    The QTableWidget class provides an item-based table view with a default model.
    Table widgets provide standard table display facilities for applications. The items in a QTableWidget are provided by QTableWidgetItem.
    If you want a table that uses your own data model you should use QTableView rather than this class.

    But for QTableView I previously gave you http://www.qtcentre.org/threads/38338-Can-t-edit-my-QTableView-cells?p=176235#post176235:

    Qt::ItemFlags MyTableModel::flags (const QModelIndex &index) const
    {
       return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
    }
    

    At this point I don't even know which of the 2 (table view/table widget) is the most appropriate for my situation.

    The last post you linked says to reimplement the method flags() but I don't understand: after inheriting from AbstractItemModel (and reimplementing the method), what am I supposed to do?

    J Offline
    J Offline
    JonB
    wrote on 8 Feb 2018, 19:20 last edited by JonB 2 Aug 2018, 19:26
    #33

    @devhobby
    I'm going back to your very original post and thinking about what you're actually trying to achieve anyway. The code we're talking about is all well & good, if you want to proceed, but I'm wondering about your expectations of the interface.

    In your pic of Employee table only, you have 1 row per employee. When you say:

    I want to join the Employee table with EmployeePosition and EmployeeResource so that I can also see, for each employee, their positions and resources (if they have any!)

    what are you expecting the table interface to be for the multiple positions & resources you say employees have?

    It's all very well to say:

    What I need, hence, is a full outer join
    The query above gives me everything I want to know and see on the Table View

    [I'm trusting that your code implements FULL OUTER JOIN] but left to its own devices this will mean you have many rows per employee, for each position/resource variant. Is that what you intend??

    One thing to understand: when you're using QSqlRelationalTableModel so that you can "look up" position/resource names, the combobox you'll get will only ever allow single selection, if you're imagining that it might provide multiple selection it won't.

    1 Reply Last reply
    1
    • J JonB
      8 Feb 2018, 18:51

      @devhobby
      Look at the last bit I just added to my post above.

      To make it [QSqlQueryModel] read-write, you must subclass it and reimplement setData() and flags().

      (And BTW when you've done that there won't be any "iterating over items and setting the editable flag", your items will be editable through your reimplementation of QSqlQueryModel::flags().)

      You understand how to "subclass", and how to "reimplement [override] virtual methods", don't you?

      D Offline
      D Offline
      devhobby
      wrote on 8 Feb 2018, 19:25 last edited by devhobby 2 Aug 2018, 19:39
      #34

      @JonB said in QSqlRelationalTableModel with multiple Joins?:

      @devhobby
      Look at the last bit I just added to my post above.

      To make it [QSqlQueryModel] read-write, you must subclass it and reimplement setData() and flags().

      (And BTW when you've done that there won't be any "iterating over items and setting the editable flag", your items will be editable through your reimplementation of QSqlQueryModel::flags().)

      You understand how to "subclass", and how to "reimplement [override] virtual methods", don't you?

      I have my CustomModel class now deriving from QSqlQueryModel

      #ifndef CUSTOMMODEL_H
      #define CUSTOMMODEL_H
      #include <QSqlQueryModel>
      
      class CustomModel : public QSqlQueryModel
      {
          Q_OBJECT
          
      public:
          bool setData(const QModelIndex &index, const QVariant &value, int role) override;
          Qt::ItemFlags flags(const QModelIndex &index) const override;
      };
      
      #endif
      

      The problem is...

      0_1518117868934_4f8b1d3f-c5cf-43c9-b900-be0b15d1ac81-image.png

      The linker somehow can't match the signatures... weird.

      I checked this link for example [ https://code.woboq.org/qt5/qtbase/src/corelib/itemmodels/qabstractitemmodel.h.html ]

      and both setData() and flags() are the same way I overloaded them...

      J 1 Reply Last reply 8 Feb 2018, 19:29
      0
      • D devhobby
        8 Feb 2018, 19:25

        @JonB said in QSqlRelationalTableModel with multiple Joins?:

        @devhobby
        Look at the last bit I just added to my post above.

        To make it [QSqlQueryModel] read-write, you must subclass it and reimplement setData() and flags().

        (And BTW when you've done that there won't be any "iterating over items and setting the editable flag", your items will be editable through your reimplementation of QSqlQueryModel::flags().)

        You understand how to "subclass", and how to "reimplement [override] virtual methods", don't you?

        I have my CustomModel class now deriving from QSqlQueryModel

        #ifndef CUSTOMMODEL_H
        #define CUSTOMMODEL_H
        #include <QSqlQueryModel>
        
        class CustomModel : public QSqlQueryModel
        {
            Q_OBJECT
            
        public:
            bool setData(const QModelIndex &index, const QVariant &value, int role) override;
            Qt::ItemFlags flags(const QModelIndex &index) const override;
        };
        
        #endif
        

        The problem is...

        0_1518117868934_4f8b1d3f-c5cf-43c9-b900-be0b15d1ac81-image.png

        The linker somehow can't match the signatures... weird.

        I checked this link for example [ https://code.woboq.org/qt5/qtbase/src/corelib/itemmodels/qabstractitemmodel.h.html ]

        and both setData() and flags() are the same way I overloaded them...

        J Offline
        J Offline
        JonB
        wrote on 8 Feb 2018, 19:29 last edited by JonB 2 Aug 2018, 19:51
        #35

        @devhobby
        Now you're talking C++ esotericism, and I'm a Python Qt guy anyway. This one is your problem! :) Sometimes signatures don't match if you don't get your consts just right? What about the Q_INVOKABLE?

        https://stackoverflow.com/questions/33781346/how-to-write-setdata-in-qsqlquerymodelqabstractitemmodel is an example of what claims to work? (Oohh, it uses Q_DECL_OVERRIDE for your override?)

        D 1 Reply Last reply 8 Feb 2018, 19:53
        1
        • J JonB
          8 Feb 2018, 19:29

          @devhobby
          Now you're talking C++ esotericism, and I'm a Python Qt guy anyway. This one is your problem! :) Sometimes signatures don't match if you don't get your consts just right? What about the Q_INVOKABLE?

          https://stackoverflow.com/questions/33781346/how-to-write-setdata-in-qsqlquerymodelqabstractitemmodel is an example of what claims to work? (Oohh, it uses Q_DECL_OVERRIDE for your override?)

          D Offline
          D Offline
          devhobby
          wrote on 8 Feb 2018, 19:53 last edited by devhobby 2 Aug 2018, 20:01
          #36

          @JonB said in QSqlRelationalTableModel with multiple Joins?:

          @devhobby
          Oohh, it uses Q_DECL_OVERRIDE for your override?

          Yes, it is ALSO that.

          Something strange is going on here...

          I'll try tagging someone @SGaist @VRonin

          --- HEADER FILE ---

          #ifndef MYMODEL_H
          #define MYMODEL_H
          
          #include <QObject>
          #include <QSqlQueryModel>
          
          class MyModel : public QSqlQueryModel
          {
              Q_OBJECT
          
          public:
              MyModel(QObject *parent = 0);
          
              Qt::ItemFlags flags(const QModelIndex &index) const override;
              bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
          };
          
          #endif // MYMODEL_H
          

          --- CPP FILE ---

          #include "mymodel.h"
          
          MyModel::MyModel(QObject *parent) : QSqlQueryModel(parent)
          {
          }
          
          Qt::ItemFlags MyModel::flags(const QModelIndex &index) const
          {
          
          }
          
          bool MyModel::setData(const QModelIndex &index, const QVariant &value, int role)
          {
          
          }
          

          0_1518119620573_1720abc4-b3c2-4451-9dda-e5b727282cf3-image.png

          1 Reply Last reply
          0
          • S Offline
            S Offline
            SGaist
            Lifetime Qt Champion
            wrote on 8 Feb 2018, 19:57 last edited by
            #37

            Your CPP file contains an error, the default value should be in the declaration of the function.

            If you are using Qt >= 5.7, you can simply use the override keyword as C++11 support is mandatory since that version. Q_DECL_OVERRIDE was used to allow compatibly with non-C++11 enabled compilers.

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            J D 2 Replies Last reply 8 Feb 2018, 20:00
            2
            • S SGaist
              8 Feb 2018, 19:57

              Your CPP file contains an error, the default value should be in the declaration of the function.

              If you are using Qt >= 5.7, you can simply use the override keyword as C++11 support is mandatory since that version. Q_DECL_OVERRIDE was used to allow compatibly with non-C++11 enabled compilers.

              J Offline
              J Offline
              JonB
              wrote on 8 Feb 2018, 20:00 last edited by
              #38

              @SGaist You're a hero ;-) It takes you like 1 minute to spot it & reply!

              1 Reply Last reply
              1
              • S SGaist
                8 Feb 2018, 19:57

                Your CPP file contains an error, the default value should be in the declaration of the function.

                If you are using Qt >= 5.7, you can simply use the override keyword as C++11 support is mandatory since that version. Q_DECL_OVERRIDE was used to allow compatibly with non-C++11 enabled compilers.

                D Offline
                D Offline
                devhobby
                wrote on 8 Feb 2018, 20:01 last edited by devhobby 2 Aug 2018, 20:01
                #39

                @SGaist said in QSqlRelationalTableModel with multiple Joins?:

                Your CPP file contains an error, the default value should be in the declaration of the function.

                If you are using Qt >= 5.7, you can simply use the override keyword as C++11 support is mandatory since that version. Q_DECL_OVERRIDE was used to allow compatibly with non-C++11 enabled compilers.

                I hoped it was just that...

                0_1518120023429_f174cbae-ee6a-42fa-b713-287d8d891eff-image.png

                I moved the default value in the header file, same issue

                [ I will update the code posted above so that I don't repost it everytime ]

                1 Reply Last reply
                0
                • S Offline
                  S Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on 8 Feb 2018, 20:22 last edited by
                  #40

                  Did you try re-running qmake before building ?

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  D 1 Reply Last reply 8 Feb 2018, 20:55
                  2
                  • S SGaist
                    8 Feb 2018, 20:22

                    Did you try re-running qmake before building ?

                    D Offline
                    D Offline
                    devhobby
                    wrote on 8 Feb 2018, 20:55 last edited by
                    #41

                    @SGaist

                    Did you try re-running qmake before building ?

                    Thank you, sir! That solved it :)

                    @JonB

                    I'm going back to your very original post and thinking about what you're actually trying to achieve anyway. The code we're talking about is all well & good, if you want to proceed, but I'm wondering about your expectations of the interface.

                    Back to the original post... at the moment I can successfully double-click items and edit them.

                    How they are edited and how the edit is going to affect the table and the database is something I believe I can do by myself now.

                    I guess I've caught the mechanism behind it!

                    BUT

                    One thing that has remained unresolved is the fact that anytime I change a field (setData() is called) the edited cell must change its background color.

                    I still don't get this one.

                    P.S: @JonB I wanted to thank you too. It's amazing the way you're helping me. I just can't thank you enough :)

                    1 Reply Last reply
                    1
                    • S Offline
                      S Offline
                      SGaist
                      Lifetime Qt Champion
                      wrote on 8 Feb 2018, 20:57 last edited by
                      #42

                      Do you mean you want to mark the cell as "edited" ?

                      Interested in AI ? www.idiap.ch
                      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                      D 1 Reply Last reply 8 Feb 2018, 20:59
                      0
                      • S SGaist
                        8 Feb 2018, 20:57

                        Do you mean you want to mark the cell as "edited" ?

                        D Offline
                        D Offline
                        devhobby
                        wrote on 8 Feb 2018, 20:59 last edited by devhobby 2 Aug 2018, 21:00
                        #43

                        @SGaist said in QSqlRelationalTableModel with multiple Joins?:

                        Do you mean you want to mark the cell as "edited" ?

                        Yes but... my way!

                        I want to change it's background color to, say, Cyan.

                        This way the user, before committing the changes, can take a look and see what is going to really change in the database.

                        1 Reply Last reply
                        0
                        • S Offline
                          S Offline
                          SGaist
                          Lifetime Qt Champion
                          wrote on 8 Feb 2018, 21:06 last edited by
                          #44

                          One way could be to keep a vector of edited cells that you update when setData is called with the EditRole and that you will use when data is called for the BackgroundRole and you return the colour you want.

                          Interested in AI ? www.idiap.ch
                          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                          D 1 Reply Last reply 8 Feb 2018, 21:29
                          1
                          • S SGaist
                            8 Feb 2018, 21:06

                            One way could be to keep a vector of edited cells that you update when setData is called with the EditRole and that you will use when data is called for the BackgroundRole and you return the colour you want.

                            D Offline
                            D Offline
                            devhobby
                            wrote on 8 Feb 2018, 21:29 last edited by
                            #45

                            @SGaist said in QSqlRelationalTableModel with multiple Joins?:

                            One way could be to keep a vector of edited cells that you update when setData is called with the EditRole and that you will use when data is called for the BackgroundRole and you return the colour you want.

                            Thank you. The problem is I can't find the method which allows me to change te color to a cell. I guess something like setBackgroundColor(row,column)

                            1 Reply Last reply
                            0
                            • S Offline
                              S Offline
                              SGaist
                              Lifetime Qt Champion
                              wrote on 8 Feb 2018, 21:34 last edited by
                              #46

                              Because there's none. Do you have a custom setData method ? If so you should emit the dataChanged signal properly and it should trigger an update of the view which should request all the roles including the one for background colour.

                              Interested in AI ? www.idiap.ch
                              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                              D 1 Reply Last reply 8 Feb 2018, 21:57
                              0
                              • S SGaist
                                8 Feb 2018, 21:34

                                Because there's none. Do you have a custom setData method ? If so you should emit the dataChanged signal properly and it should trigger an update of the view which should request all the roles including the one for background colour.

                                D Offline
                                D Offline
                                devhobby
                                wrote on 8 Feb 2018, 21:57 last edited by
                                #47

                                @SGaist said in QSqlRelationalTableModel with multiple Joins?:

                                which should request all the roles including the one for background colour.

                                That! I don't know how to make such a request for the table view.

                                1 Reply Last reply
                                0
                                • S Offline
                                  S Offline
                                  SGaist
                                  Lifetime Qt Champion
                                  wrote on 8 Feb 2018, 21:59 last edited by
                                  #48

                                  That's what dataChanged is for.

                                  Interested in AI ? www.idiap.ch
                                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                                  D 1 Reply Last reply 8 Feb 2018, 22:25
                                  2
                                  • S SGaist
                                    8 Feb 2018, 21:59

                                    That's what dataChanged is for.

                                    D Offline
                                    D Offline
                                    devhobby
                                    wrote on 8 Feb 2018, 22:25 last edited by
                                    #49

                                    @SGaist said in QSqlRelationalTableModel with multiple Joins?:

                                    That's what dataChanged is for.

                                    In fact I emit the signal including the role

                                    emit dataChanged(index, index, roleArray);
                                    

                                    roleArray includes Qt::BackgroundColor

                                    Now what? Where do I select the color the cell has to become?

                                    1 Reply Last reply
                                    0
                                    • S Offline
                                      S Offline
                                      SGaist
                                      Lifetime Qt Champion
                                      wrote on 8 Feb 2018, 22:27 last edited by
                                      #50

                                      Re-implement the data method and handle the BackgroundRole special case there.

                                      Interested in AI ? www.idiap.ch
                                      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                                      D 1 Reply Last reply 8 Feb 2018, 22:44
                                      1
                                      • S SGaist
                                        8 Feb 2018, 22:27

                                        Re-implement the data method and handle the BackgroundRole special case there.

                                        D Offline
                                        D Offline
                                        devhobby
                                        wrote on 8 Feb 2018, 22:44 last edited by
                                        #51

                                        @SGaist said in QSqlRelationalTableModel with multiple Joins?:

                                        Re-implement the data method and handle the BackgroundRole special case there.

                                        I now return the red color when the role is Qt::BackgroundColor

                                        if (!item.isValid())
                                           return QVariant();
                                        
                                        if(role == Qt::BackgroundRole)
                                            return QColor(255, 0, 0);
                                        
                                        return QVariant();
                                        

                                        My Table View now is all red without changing anything!

                                        Also, is it good to return a default-constructed QVariant when no particular criteria are met?

                                        J 1 Reply Last reply 8 Feb 2018, 22:48
                                        0
                                        • D devhobby
                                          8 Feb 2018, 22:44

                                          @SGaist said in QSqlRelationalTableModel with multiple Joins?:

                                          Re-implement the data method and handle the BackgroundRole special case there.

                                          I now return the red color when the role is Qt::BackgroundColor

                                          if (!item.isValid())
                                             return QVariant();
                                          
                                          if(role == Qt::BackgroundRole)
                                              return QColor(255, 0, 0);
                                          
                                          return QVariant();
                                          

                                          My Table View now is all red without changing anything!

                                          Also, is it good to return a default-constructed QVariant when no particular criteria are met?

                                          J Offline
                                          J Offline
                                          JonB
                                          wrote on 8 Feb 2018, 22:48 last edited by JonB 2 Aug 2018, 22:50
                                          #52

                                          @devhobby

                                          My Table View now is all red without changing anything!

                                          Have you understood you now need to look up the cell coordinates (item) in the vector of changed cells, as per:

                                          @SGaist said in QSqlRelationalTableModel with multiple Joins?:

                                          One way could be to keep a vector of edited cells that you update when setData is called with the EditRole and that you will use when data is called for the BackgroundRole and you return the colour you want.

                                          D 1 Reply Last reply 8 Feb 2018, 23:12
                                          1

                                          42/67

                                          8 Feb 2018, 20:57

                                          • Login

                                          • Login or register to search.
                                          42 out of 67
                                          • First post
                                            42/67
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Users
                                          • Groups
                                          • Search
                                          • Get Qt Extensions
                                          • Unsolved