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
Qt 6.11 is out! See what's new in the release blog

setModelData crashes program

Scheduled Pinned Locked Moved Unsolved General and Desktop
29 Posts 8 Posters 14.9k 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.
  • 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