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. setModelData crashes program

setModelData crashes program

Scheduled Pinned Locked Moved Unsolved General and Desktop
29 Posts 8 Posters 10.8k Views 3 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.
  • mrjjM Offline
    mrjjM Offline
    mrjj
    Lifetime Qt Champion
    wrote on last edited by mrjj
    #11

    Hi
    You should find the combobox in the widget with
    QComboBox* whatComboEditor = editor->findChild< QComboBox*>();
    if (whatComboEditor ) { ...use it... }
    in the other functions since you now have a real widget in between.
    as you say

    QWidget* WhatFixViewDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const {
      QWidget* w = new QWidget( parent );
    ....
      return w; <<< that is the place holder widget you return as "editor"
    }
    
    1 Reply Last reply
    2
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #12

      In your case, you should call findChild on editor. Your QComboBox is in a layout inside a QWidget so you can't cast it like that directly.

      An alternative would be to create a custom widget which wraps the QComboBox and that you could use in the same manner.

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

      1 Reply Last reply
      3
      • JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by
        #13

        And always check the return result of a qobject_cast<>, for safety, certainly while developing! :)

        JonBJ 1 Reply Last reply
        4
        • G Offline
          G Offline
          gabor53
          wrote on last edited by
          #14

          Thank you. I redid it as recommended and now it looks like this:

          #include "whatfixviewdelegate.h"
          
          WhatFixViewDelegate::WhatFixViewDelegate(QObject* parent) : QStyledItemDelegate(parent) {
          
          }
          
          QWidget* WhatFixViewDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const {
          
            Q_UNUSED(option);
            Q_UNUSED(index);
          
            QWidget* w = new QWidget( parent );
          
            QComboBox* whatComboEditor = new QComboBox(w);
            whatComboEditor->setFrame(true);
            whatComboEditor->setStyleSheet("background-color:rgb(255,217,229);" );
            whatComboEditor->setEditable(true);
          
            whatComboEditor->setMaximumWidth (100);
            whatComboEditor->setMinimumWidth (100);
            whatComboEditor->setMaximumHeight (30);
            whatComboEditor->setMinimumHeight (30);
          
            whatComboEditor->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
          
            QVBoxLayout* whatLayout = new QVBoxLayout;
            whatLayout->addWidget (whatComboEditor, 0, Qt::AlignCenter);
            whatLayout->setMargin (2);
          
            w->setLayout (whatLayout);
          
            QSqlQuery queryLoadWhat("SELECT What FROM  What_Table ORDER BY What asc", db);
          
            while(queryLoadWhat.next()) {
              QString whatItem = queryLoadWhat.value(0).toString();
              whatComboEditor->addItem(whatItem);
            }
            return w;
          }
          
          void WhatFixViewDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const {
            QComboBox* whatComboEditor = editor->findChild<QComboBox*>();
          
            if(whatComboEditor) {
              whatComboEditor->addItem(index.model()->data(index, Qt::EditRole).toString());
              whatComboEditor->setCurrentText(index.model()->data(index, Qt::EditRole).toString());
            }
          }
          
          void WhatFixViewDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const {
            Q_UNUSED(index);
          
            editor->setGeometry(option.rect);
          }
          
          void WhatFixViewDelegate::setModelData(QWidget* editor, QAbstractItemModel* fixModel, const QModelIndex& index) const {
          
            QComboBox* whatComboEditor = editor->findChild<QComboBox*>();
            if (whatComboEditor) {
                QString newWhatText;
              
                newWhatText = whatComboEditor->currentText ();//crashes
                qDebug() << "newWhatText: " <<  whatComboEditor->currentText ();
              
                fixModel->setData (index, newWhatText, Qt::EditRole);
              
                fixModel->submit ();
            }
          }
          
          

          Now it doesn't crash, but when I add an item from the QComboBox, all the data from the line disappears like this:
          0_1506565863276_Capture.JPG
          When I reload the table all the data are back and the newly chosen item is also there (it was saved in the db). What can I add to prevent the data from disappearing?

          VRoninV 1 Reply Last reply
          0
          • G gabor53

            Thank you. I redid it as recommended and now it looks like this:

            #include "whatfixviewdelegate.h"
            
            WhatFixViewDelegate::WhatFixViewDelegate(QObject* parent) : QStyledItemDelegate(parent) {
            
            }
            
            QWidget* WhatFixViewDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const {
            
              Q_UNUSED(option);
              Q_UNUSED(index);
            
              QWidget* w = new QWidget( parent );
            
              QComboBox* whatComboEditor = new QComboBox(w);
              whatComboEditor->setFrame(true);
              whatComboEditor->setStyleSheet("background-color:rgb(255,217,229);" );
              whatComboEditor->setEditable(true);
            
              whatComboEditor->setMaximumWidth (100);
              whatComboEditor->setMinimumWidth (100);
              whatComboEditor->setMaximumHeight (30);
              whatComboEditor->setMinimumHeight (30);
            
              whatComboEditor->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
            
              QVBoxLayout* whatLayout = new QVBoxLayout;
              whatLayout->addWidget (whatComboEditor, 0, Qt::AlignCenter);
              whatLayout->setMargin (2);
            
              w->setLayout (whatLayout);
            
              QSqlQuery queryLoadWhat("SELECT What FROM  What_Table ORDER BY What asc", db);
            
              while(queryLoadWhat.next()) {
                QString whatItem = queryLoadWhat.value(0).toString();
                whatComboEditor->addItem(whatItem);
              }
              return w;
            }
            
            void WhatFixViewDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const {
              QComboBox* whatComboEditor = editor->findChild<QComboBox*>();
            
              if(whatComboEditor) {
                whatComboEditor->addItem(index.model()->data(index, Qt::EditRole).toString());
                whatComboEditor->setCurrentText(index.model()->data(index, Qt::EditRole).toString());
              }
            }
            
            void WhatFixViewDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const {
              Q_UNUSED(index);
            
              editor->setGeometry(option.rect);
            }
            
            void WhatFixViewDelegate::setModelData(QWidget* editor, QAbstractItemModel* fixModel, const QModelIndex& index) const {
            
              QComboBox* whatComboEditor = editor->findChild<QComboBox*>();
              if (whatComboEditor) {
                  QString newWhatText;
                
                  newWhatText = whatComboEditor->currentText ();//crashes
                  qDebug() << "newWhatText: " <<  whatComboEditor->currentText ();
                
                  fixModel->setData (index, newWhatText, Qt::EditRole);
                
                  fixModel->submit ();
              }
            }
            
            

            Now it doesn't crash, but when I add an item from the QComboBox, all the data from the line disappears like this:
            0_1506565863276_Capture.JPG
            When I reload the table all the data are back and the newly chosen item is also there (it was saved in the db). What can I add to prevent the data from disappearing?

            VRoninV Offline
            VRoninV Offline
            VRonin
            wrote on last edited by
            #15

            @gabor53 said in setModelData crashes program:

            What can I add to prevent the data from disappearing?

            Sounds like a model bug. What is fixModel?

            "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
            ~Napoleon Bonaparte

            On a crusade to banish setIndexWidget() from the holy land of Qt

            VRoninV 1 Reply Last reply
            0
            • JonBJ JonB

              And always check the return result of a qobject_cast<>, for safety, certainly while developing! :)

              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by
              #16

              @JNBarchan said in setModelData crashes program:

              And always check the return result of a qobject_cast<>, for safety, certainly while developing! :)

              In my nice (non-Qt) C# background, this kind of casting is built into the language. For qobject_cast<> we write:

              ComboBox cb = editor as CombBox;

              where the as operator returns null if editor cannot be cast to ComboBox at runtime. We use this if editor might not be a ComboBox.

              However, if editor must be/is intended to be a ComboBox, we write:

              ComboBox cb = (ComboBox) editor;

              where the direct cast throws a runtime Exception if editor is not a ComboBox (i.e. as would return null). This saves a lot of code/accidents.

              It would be nice if Qt offered a "variant" of qobject_cast<> in C++ which checked and automatically threw an Exception if the return result is NULL/0....?

              VRoninV 1 Reply Last reply
              0
              • JonBJ JonB

                @JNBarchan said in setModelData crashes program:

                And always check the return result of a qobject_cast<>, for safety, certainly while developing! :)

                In my nice (non-Qt) C# background, this kind of casting is built into the language. For qobject_cast<> we write:

                ComboBox cb = editor as CombBox;

                where the as operator returns null if editor cannot be cast to ComboBox at runtime. We use this if editor might not be a ComboBox.

                However, if editor must be/is intended to be a ComboBox, we write:

                ComboBox cb = (ComboBox) editor;

                where the direct cast throws a runtime Exception if editor is not a ComboBox (i.e. as would return null). This saves a lot of code/accidents.

                It would be nice if Qt offered a "variant" of qobject_cast<> in C++ which checked and automatically threw an Exception if the return result is NULL/0....?

                VRoninV Offline
                VRoninV Offline
                VRonin
                wrote on last edited by
                #17

                you just need to add Q_ASSERT(whatComboEditor); to have that

                "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                ~Napoleon Bonaparte

                On a crusade to banish setIndexWidget() from the holy land of Qt

                JonBJ 1 Reply Last reply
                2
                • VRoninV VRonin

                  you just need to add Q_ASSERT(whatComboEditor); to have that

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by JonB
                  #18

                  @VRonin said in setModelData crashes program:

                  you just need to add Q_ASSERT(whatComboEditor); to have that

                  Ah, OK. It's just that you have to remember to write that every time after each qobject_cast<>, it would be nice to have them combined in one statement. I suppose you would write:

                  Q_ASSERT(whatComboEditor = qobject_cast<>)

                  but is Q_ASSERT code removed in non-debug code and/or does it evaluate its argument more than once (assuming it's a macro)?

                  I would like a qobject_assert_cast<> :)

                  EDIT: Yes, I see you cannot use Q_ASSERT(whatComboEditor = qobject_cast<>) in non-debug as the code gets removed.

                  1 Reply Last reply
                  0
                  • SGaistS Offline
                    SGaistS Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on last edited by
                    #19

                    That's not specific to Q_ASSERT, it's the same for the standard C++ assert. Always test the result of a function and not the function itself.

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

                    1 Reply Last reply
                    1
                    • VRoninV Offline
                      VRoninV Offline
                      VRonin
                      wrote on last edited by
                      #20

                      If you want to use it in code that should still be present in release mode you can use Q_ASSUME

                      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                      ~Napoleon Bonaparte

                      On a crusade to banish setIndexWidget() from the holy land of Qt

                      JonBJ 1 Reply Last reply
                      0
                      • VRoninV VRonin

                        If you want to use it in code that should still be present in release mode you can use Q_ASSUME

                        JonBJ Offline
                        JonBJ Offline
                        JonB
                        wrote on last edited by JonB
                        #21

                        @VRonin said in setModelData crashes program:

                        If you want to use it in code that should still be present in release mode you can use Q_ASSUME

                        Um, I don't think so are you sure: http://doc.qt.io/qt-5/qtglobal.html#Q_ASSUME states it's a compile-time hint, and you get "undefined behaviour" if the condition is false. We need a runtime check of the return result of qobject_cast<>.

                        EDIT: Unless the docs are misleading, and the true implementation is via https://git.merproject.org/faenil/qtbase/commit/3b0ed624351441a2d7be45cf9582fd36955ae860 , which uses Q_ASSERT_X?

                        1 Reply Last reply
                        0
                        • VRoninV Offline
                          VRoninV Offline
                          VRonin
                          wrote on last edited by VRonin
                          #22

                          Q_ASSUME in debug mode is like Q_ASSERT in release mode, if whatComboEditor is null the program would crash anyway so you can't do much worse.

                          The undefined behaviour comes from when you use the return value: if(Q_ASSUME(false)) is undefined behaviour. if it just wraps an operation you do not check anyway, Q_ASSUME does nothing to your compiled binary in release mode

                          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                          ~Napoleon Bonaparte

                          On a crusade to banish setIndexWidget() from the holy land of Qt

                          JonBJ 1 Reply Last reply
                          0
                          • VRoninV VRonin

                            Q_ASSUME in debug mode is like Q_ASSERT in release mode, if whatComboEditor is null the program would crash anyway so you can't do much worse.

                            The undefined behaviour comes from when you use the return value: if(Q_ASSUME(false)) is undefined behaviour. if it just wraps an operation you do not check anyway, Q_ASSUME does nothing to your compiled binary in release mode

                            JonBJ Offline
                            JonBJ Offline
                            JonB
                            wrote on last edited by
                            #23

                            @VRonin
                            That wasn't quite the point, though. I was talking about writing the single-line statement (if Qt won't offer a qboject_assert_cast<>):

                            Q_ASSERT(whatComboEditor = qobject_cast<>)

                            versus

                            Q_ASSUME(whatComboEditor = qobject_cast<>)

                            The point being that it does the assignment. So we do need the expression to evaluate, just we don't need/care to do the "assertion" part of testing the result in release build. This would not work for Q_ASSERT as (I believe) it's a macro which produces nothing (no code at all) in release build. That was when you suggested Q_ASSUME.

                            VRoninV 1 Reply Last reply
                            0
                            • JonBJ JonB

                              @VRonin
                              That wasn't quite the point, though. I was talking about writing the single-line statement (if Qt won't offer a qboject_assert_cast<>):

                              Q_ASSERT(whatComboEditor = qobject_cast<>)

                              versus

                              Q_ASSUME(whatComboEditor = qobject_cast<>)

                              The point being that it does the assignment. So we do need the expression to evaluate, just we don't need/care to do the "assertion" part of testing the result in release build. This would not work for Q_ASSERT as (I believe) it's a macro which produces nothing (no code at all) in release build. That was when you suggested Q_ASSUME.

                              VRoninV Offline
                              VRoninV Offline
                              VRonin
                              wrote on last edited by
                              #24
                              • Q_ASSERT(statement);
                                • Debug: if(!statement) triggerAnAssertion();
                                • Release: ;
                              • Q_ASSUME(statement);
                                • Debug: if(!statement) triggerAnAssertion();
                                • Release: statement;

                              Is the difference clearer now?

                              "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                              ~Napoleon Bonaparte

                              On a crusade to banish setIndexWidget() from the holy land of Qt

                              G JonBJ 2 Replies Last reply
                              1
                              • VRoninV VRonin
                                • Q_ASSERT(statement);
                                  • Debug: if(!statement) triggerAnAssertion();
                                  • Release: ;
                                • Q_ASSUME(statement);
                                  • Debug: if(!statement) triggerAnAssertion();
                                  • Release: statement;

                                Is the difference clearer now?

                                G Offline
                                G Offline
                                gabor53
                                wrote on last edited by
                                #25

                                @VRonin
                                I added

                                 Q_ASSERT(whatComboEditor);
                                

                                but it behaves the same.

                                1 Reply Last reply
                                0
                                • VRoninV VRonin

                                  @gabor53 said in setModelData crashes program:

                                  What can I add to prevent the data from disappearing?

                                  Sounds like a model bug. What is fixModel?

                                  VRoninV Offline
                                  VRoninV Offline
                                  VRonin
                                  wrote on last edited by
                                  #26

                                  @VRonin said in setModelData crashes program:

                                  Sounds like a model bug. What is fixModel?

                                  "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                                  ~Napoleon Bonaparte

                                  On a crusade to banish setIndexWidget() from the holy land of Qt

                                  G 2 Replies Last reply
                                  0
                                  • VRoninV VRonin

                                    @VRonin said in setModelData crashes program:

                                    Sounds like a model bug. What is fixModel?

                                    G Offline
                                    G Offline
                                    gabor53
                                    wrote on last edited by
                                    #27

                                    @VRonin

                                    QSqlTableModel* fixModel = new QSqlTableModel(this);
                                      fixModel->setTable ("Items");
                                      fixModel->setEditStrategy (QSqlTableModel::OnRowChange);
                                      fixModel->setSort (2, Qt::DescendingOrder);
                                    
                                      fixModel->select ();
                                    
                                    1 Reply Last reply
                                    0
                                    • VRoninV VRonin
                                      • Q_ASSERT(statement);
                                        • Debug: if(!statement) triggerAnAssertion();
                                        • Release: ;
                                      • Q_ASSUME(statement);
                                        • Debug: if(!statement) triggerAnAssertion();
                                        • Release: statement;

                                      Is the difference clearer now?

                                      JonBJ Offline
                                      JonBJ Offline
                                      JonB
                                      wrote on last edited by
                                      #28

                                      @VRonin

                                      Is the difference clearer now?

                                      Yep! :) Tx.

                                      1 Reply Last reply
                                      0
                                      • VRoninV VRonin

                                        @VRonin said in setModelData crashes program:

                                        Sounds like a model bug. What is fixModel?

                                        G Offline
                                        G Offline
                                        gabor53
                                        wrote on last edited by gabor53
                                        #29

                                        @VRonin
                                        Any way to go around the problem?
                                        Would it be possible to just redraw the row in which the field was changed?

                                        1 Reply Last reply
                                        0

                                        • Login

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