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. [Solved] Saving List from QAbstractItemModel
Forum Updated to NodeBB v4.3 + New Features

[Solved] Saving List from QAbstractItemModel

Scheduled Pinned Locked Moved General and Desktop
20 Posts 3 Posters 8.6k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    B Offline
    BrawnyLad
    wrote on last edited by
    #1

    I am happy as a puppy with displaying a QStringList using QAbstractItemModel and QListView! However, I, quite a beginner, am having trouble finding information about developing this functionality farther.

    The user can edit the displayed list. Ideally the displayed list would also present option buttons "Cancel" and "Save File." If the latter is chosen, the altered list should be saved. Any suggestions for how this can be done, (as explicitly as possible -- please don't underestimate my ignorance!) would be gratefully accepted.

    If the model display can't include buttons, I would like to know how to save the changes made in the model display; I could then pop-up a message box asking if the altered list should be saved or discarded.

    If it helps, here is the method that displays the list:

    @
    void MainWindow::reviewSetup()
    {

     QStringList textList;
    

    //This generates the list
    textList=topScene->generateFileText();
    foreach(DispDiagramScene *scene,dispSceneList) {
    textList.append(scene->generateFileText());
    }

    // This makes the model and displays it
    QAbstractItemModel *model = new QStringListModel(textList);
    QListView *view = new QListView;
    view->setModel(model);
    view->show();
    }
    @

    Thank you.

    1 Reply Last reply
    0
    • D Offline
      D Offline
      DerManu
      wrote on last edited by
      #2

      You can either just create a button on your window that saves the stringlist externally or subclass QStringListModel to add a function like "save". The latter is the cleaner method. I wouldn't integrate the save/cancel buttons into the view, rather place them below it.

      The saving itself works with QFile and QTextStream, string by string, approximately like this:
      @
      QFile file("./bla/blubb");
      if (file.open(QFile::WriteOnly|QFile::Truncate))
      {
      QTextStream stream(&file);
      for each string in the model
      stream << theString << "\n";
      } else
      // couldn't open file
      @

      1 Reply Last reply
      0
      • B Offline
        B Offline
        BrawnyLad
        wrote on last edited by
        #3

        Thank you, DerManu!

        I am taking "baby steps" to follow your directions. You suggested I subclass QStringListModel. I created a file QStringListButtonsModel.cpp for the subclass.

        Here it is in its entirety:

        @
        #include <QStringListModel>
        #include "QStringListModel.h"

        class QSTringListButtonsModel : public QStringListModel {
        public:
        QStringLIstButtonsModel(){} // Default constructor

        // put button declarations here

        };

        @

        1. I changed my one reference to QStringListModel, to QStringListButtonsModel, and I get the error "C2061: syntax error :identifier 'QStringListButtonsModel'

        2. I am at a loss as to how to specify button methods. It seems there are so many button functions. And in particular, I don't know how to determine where buttons are placed in the window.

        Is there an example somewhere that I could follow?

        Thanks in Advance!

        1 Reply Last reply
        0
        • B Offline
          B Offline
          BrawnyLad
          wrote on last edited by
          #4

          P.S. I changed line 2 to
          #include "qstringlistmodel.h"

          1 Reply Last reply
          0
          • B Offline
            B Offline
            BrawnyLad
            wrote on last edited by
            #5

            Also I should note that the upper case "T" in the class name is a typo in the example above ONLY; not in my actual project.

            1 Reply Last reply
            0
            • D Offline
              D Offline
              DerManu
              wrote on last edited by
              #6

              I think there's a little misconception. I didn't mean that you include a button into the model. That would be completely against the sense of "model-view" programming. You would include something that belongs to the view (the button) into the model and thus would break the modularization.

              The model should get a function that corresponds to an action (button press) in the user interface. In this case, a function that's called "save" for example and takes a QString for the filename where to save the contents of the model. This way, the model doesn't need to know anything about the user interface and whether a button caused the save function to be called or an automatic save algorithm triggered it. So we have preserved the decoupling of model and view.

              On your main window, you just place a normal button and make it call the save function after asking the user for a filename via QFileDialog.

              If you want your button aligned with the ListView displaying the strings, use a corresponding layout in QtDesigner.
              If you want that button tighly integrated with the view, you'd need to subclass the view, too. But for the beginning I'd not recommend doing that (not because it's very hard, but because I don't see the benefit of adding a save-button permanently to a view, compared to just placing it with a layout).

              1 Reply Last reply
              0
              • B Offline
                B Offline
                BrawnyLad
                wrote on last edited by
                #7

                Thanks again.
                I haven't been able to determine why my effort at subclassing QStringListModel doesn't work (described above), so my only hope is adding a button more directly. However, when I try that, by including the abstract model into a layout, I get an error.

                Here is my code:

                @
                QAbstractItemModel *model = new QStringListModel(textList);
                QListView *view = new QListView;

                QPushButton *quitButton = new QPushButton("Quit");
                QObject::connect(quitButton, SIGNAL(clicked()),qApp,SLOT(quit()));
                QVBoxLayout *layout = new QVBoxLayout;
                layout->addWidget(model);
                layout->addWidget(quitButton);
                
                QWidget window;
                window.setLayout(layout);
                
                window.show();
                

                @

                The error I get is
                C2664: ‘QBoxLayout::addWidget’: cannot convert parameter 1 from ‘QAbstractItemModel*’ to ‘QWidget *’

                1 Reply Last reply
                0
                • S Offline
                  S Offline
                  Sam
                  wrote on last edited by
                  #8

                  The above error is coz you are trying to add a model to a layout

                  @layout->addWidget(model);@

                  you should try setting the model to QListView and adding it to the layout like:

                  @view->setModel(model)
                  layout->addWidget(view)@

                  1 Reply Last reply
                  0
                  • B Offline
                    B Offline
                    BrawnyLad
                    wrote on last edited by
                    #9

                    Thank you!!! (I wondered if there was a way to tell it to treat it like a widget.)

                    The only problem now is that the view disappears immediately; its appearance is just a flash. This wasn't the case when I used
                    view->show();
                    to manifest the list.

                    This problem isn't due to the list model; if I create a layout with just a button it, too, only flashes.

                    I'm once again scratching my head...

                    1 Reply Last reply
                    0
                    • S Offline
                      S Offline
                      Sam
                      wrote on last edited by
                      #10

                      Is the above code written inside main.cpp. If yes then do check that you have added something like :-

                      @int main(int argc, char *argv[])
                      {
                      QApplication a(argc, argv);

                      // above code

                      return a.exec();
                      }@

                      Otherwise you can share the code here so that we can easily check for the same.

                      If you are writing the above code inside a QMainWindow constructor

                      then you can directly use

                      @QFrame *frame = new QFrame(this);
                      setCentralWidget(frame);
                      frame->setLayout(layout);@

                      1 Reply Last reply
                      0
                      • B Offline
                        B Offline
                        BrawnyLad
                        wrote on last edited by
                        #11

                        Hi and thanks again!
                        This code is not in the main (and the main looks like your example main). Instead it is in a method:

                        void MainWindow::reviewSetup()
                        {

                        QMessageBox questionBox;
                        QWidget window;
                        QStringList textList;
                        QStringList changedTextList;
                        

                        // make a list (next four lines)
                        textList=topScene->generateFileText();
                        foreach(DispDiagramScene *scene,dispSceneList) {
                        textList.append(scene->generateFileText());
                        }

                        QAbstractItemModel *model = new QStringListModel(textList);
                        QListView *view = new QListView;
                        
                        QPushButton *quitButton = new QPushButton("Quit");
                        QObject::connect(quitButton, SIGNAL(clicked()),qApp,SLOT(quit()));
                        QVBoxLayout *layout = new QVBoxLayout;
                        
                        
                        view->setModel(model);
                        layout->addWidget(view);
                        layout->addWidget(quitButton);
                        
                        window.setLayout(layout);
                        window.show();
                        

                        }

                        I'm not familiar with QFrame. Are you suggesting that I use the three lines you provided verbatim, instead of the final two lines in my existing code (the window code)?

                        Much obliged!

                        1 Reply Last reply
                        0
                        • D Offline
                          D Offline
                          DerManu
                          wrote on last edited by
                          #12

                          Well whatever you create on the stack is deleted when leaving the scope in which it was created. If you want anything to persist, create it on the heap (and you'll need to take care of memory management yourself). So in this case, you should be creating QWidget on the heap. (not QWidget window; but QWidget *window = new QWidget;)

                          (PS: use code tags around larger portions of code, see the "<>" button above the reply text box)

                          1 Reply Last reply
                          0
                          • S Offline
                            S Offline
                            Sam
                            wrote on last edited by
                            #13

                            [quote author="BrawnyLad" date="1344959664"] Are you suggesting that I use the three lines you provided verbatim, instead of the final two lines in my existing code (the window code)?

                            [/quote]

                            Yes , try and check if it works.

                            1 Reply Last reply
                            0
                            • D Offline
                              D Offline
                              DerManu
                              wrote on last edited by
                              #14

                              [quote author="Sam" date="1344960186"]
                              [quote author="BrawnyLad" date="1344959664"] Are you suggesting that I use the three lines you provided verbatim, instead of the final two lines in my existing code (the window code)?

                              [/quote]

                              Yes , try and check if it works.
                              [/quote]
                              No, it won't work as intended. First of all QFrame and QWidget don't make a functional difference here. Second he doesn't want to set the central widget of his main window, but create a new floating window, is that correct?

                              1 Reply Last reply
                              0
                              • S Offline
                                S Offline
                                Sam
                                wrote on last edited by
                                #15

                                [quote author="DerManu" date="1344960164"]Well whatever you create on the stack is deleted when leaving the scope in which it was created. If you want anything to persist, create it on the heap (and you'll need to take care of memory management yourself). So in this case, you should be creating QWidget on the heap. (not QWidget window; but QWidget *window = new QWidget;)

                                [/quote]
                                i was about to write the same thing. Thanks DerManu :)

                                1 Reply Last reply
                                0
                                • S Offline
                                  S Offline
                                  Sam
                                  wrote on last edited by
                                  #16

                                  [quote author="DerManu" date="1344960274"]
                                  [quote author="Sam" date="1344960186"]
                                  [quote author="BrawnyLad" date="1344959664"] Are you suggesting that I use the three lines you provided verbatim, instead of the final two lines in my existing code (the window code)?

                                  [/quote]

                                  Yes , try and check if it works.
                                  [/quote]
                                  No, it won't work as intended. First of all QFrame and QWidget don't make a functional difference here. Second he doesn't want to set the central widget of his main window, but create a new floating window, is that correct?
                                  [/quote]

                                  Yes QFrame and QWidget doesnt make much difference here. The main thing is to create on heap instead of stack. If it is a floating widget then widget->show() can be used otherwise setCentralWidget() in order to add it to MainWindow.

                                  Edit: For a sample application i was using QFrame so pasted the same code. use QWidget :)

                                  1 Reply Last reply
                                  0
                                  • B Offline
                                    B Offline
                                    BrawnyLad
                                    wrote on last edited by
                                    #17

                                    Thank you DerManu and Sam!

                                    With your help I was able to succeed!

                                    When you say "You'll need to take care of memory management yourself", that means I'll have to delete the QWidget when I am done with it, right? In Qt I can do that with a simple command, (rather than by subclassing QWidget to create a destructor)?

                                    1 Reply Last reply
                                    0
                                    • B Offline
                                      B Offline
                                      BrawnyLad
                                      wrote on last edited by
                                      #18

                                      Can I do it as simply as:

                                      window->setAttribute(Qt::WA_DeleteOnClose);
                                      ?

                                      1 Reply Last reply
                                      0
                                      • D Offline
                                        D Offline
                                        DerManu
                                        wrote on last edited by
                                        #19

                                        Yes, if that is your requirement. I.e. it won't be shown again once it is closed.

                                        1 Reply Last reply
                                        0
                                        • B Offline
                                          B Offline
                                          BrawnyLad
                                          wrote on last edited by
                                          #20

                                          Thank you again, DerManu. (I'll close this thread now.)

                                          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