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
Forum Updated to NodeBB v4.3 + New Features

setModelData crashes program

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