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 9.4k 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
    #9

    Hi
    Just a small question.
    Is this code related to
    https://forum.qt.io/topic/83393/centering-qcombobox-in-table-cell
    where you also used a layout to center the combobox ?
    I wonder if the
    QComboBox* whatComboEditor = qobject_cast<QComboBox*>(editor);
    then is correct ?
    but add check to it
    if (!whatComboEditor) {
    qDebug() << "fail to cast whatComboEditor";
    return;
    }

    G 1 Reply Last reply
    2
    • mrjjM mrjj

      Hi
      Just a small question.
      Is this code related to
      https://forum.qt.io/topic/83393/centering-qcombobox-in-table-cell
      where you also used a layout to center the combobox ?
      I wonder if the
      QComboBox* whatComboEditor = qobject_cast<QComboBox*>(editor);
      then is correct ?
      but add check to it
      if (!whatComboEditor) {
      qDebug() << "fail to cast whatComboEditor";
      return;
      }

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

      @mrjj
      It is related to the referenced post. This is part of the same delegate. I added the suggested check and I got the "fail to cast whatComboEditor" message.
      Here is the whole delegate:

      #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 = qobject_cast<QComboBox*>(editor);
        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 = qobject_cast<QComboBox*>(editor);
        if (!whatComboEditor) {
          qDebug() << "fail to cast whatComboEditor";
          return;
        }
      
      
      
        QString newWhatText;
      
        newWhatText = whatComboEditor->currentText ();//crashes
        qDebug() << "newWhatText: " <<  whatComboEditor->currentText ();
      
        fixModel->setData (index, newWhatText, Qt::EditRole);
      
        fixModel->submit ();
      }
      
      

      What should be the next step? Thank you.

      1 Reply Last reply
      0
      • 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 Online
            JonBJ Online
            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 Online
                  JonBJ Online
                  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 Online
                      JonBJ Online
                      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 Online
                            JonBJ Online
                            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 Online
                                JonBJ Online
                                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 Online
                                          JonBJ Online
                                          JonB
                                          wrote on last edited by
                                          #28

                                          @VRonin

                                          Is the difference clearer now?

                                          Yep! :) Tx.

                                          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