Save object to a file



  • I'm trying to save an object called f to a file, getting errors: no match for operator << in stream << f

    here is the function:

    @void FilmWriter::saveFilm(Film& f){
    QString fileName = QFileDialog::getSaveFileName(this,("Save File"));
    if (fileName != "") {
    QFile file(fileName);
    if (!file.open(QIODevice::WriteOnly)) {
    QMessageBox::critical(this, ("Error"),("Could not open file"));// error message
    } else {
    QTextStream stream(&file);
    stream << f;
    stream.flush();
    file.close();
    }
    }

    }
    @
    These are 2 functions are in a different class filmInput

    @void FilmInput::getFilm(){
    Film f1(titleEdit->toPlainText(),durationEdit->toPlainText().toInt() ,directorEdit->toPlainText(),
    QDate::fromString(relDateEdit->toPlainText(),"dd/MM/YYYY"));;
    obtainFilmData(f1);
    }

    void FilmInput::obtainFilmData(Film &f){
    saveFilm(f);
    }
    @
    Please let me know if you need any more information?


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    If you want to use streams with your custom objects, you have to define the QTextStream's operator for them otherwise QTextStream won't be able to serialize them.



  • thanks I added this function to define toString

    QString Film::toString()
    {
    return m_title + " " + m_duration + " " + m_director + " " + m_releaseDate.toString();
    }

    now I am getting error:
    debug/filminput.o:C:\Unisa\COS3711\assignments\Ass1Q1-build-desktop/../Ass1Q1/filminput.cpp:63: undefined reference to `FilmInput::saveFilm(Film&)'
    collect2: ld returned 1 exit status
    mingw32-make[1]: *** [debug\Ass1Q1.exe] Error 1
    mingw32-make: *** [debug] Error 2
    The process "C:/Qt/2010.04/mingw/bin/mingw32-make.exe" exited with code %2.
    Error while building project Ass1Q1 (target: Desktop)
    When executing build step 'Make'


  • Lifetime Qt Champion

    School work ?

    It seems the compiler doesn't know about saveFilm



  • Yes it's an assignment I'm doing. I don't understand how it doesn't see it because saveFilm is a function in class FilmWriter which is included in class definition for class FilmInput which is has a function which calls saveFilm.


  • Lifetime Qt Champion

    Without the code it's difficult to comment



  • @#ifndef FILM_H
    #define FILM_H

    #include <QWidget>
    #include <QString>
    #include <QDate>

    class Film:public QWidget{
    public:
    Film(QString t,int dur,QString dir,QDate r);
    Film();
    void setTitle(QString t);
    void setDuration(int dur);
    void setDirector(QString dir);
    void setReleaseDate(QDate r);
    QString getTitle() const;
    int getDuration() const;
    QString getDirector() const;
    QDate getReleaseDate() const;
    QString toString();

    private:
    QString m_title;
    int m_duration;
    QString m_director;
    QDate m_releaseDate;

    };

    #endif // FILM_H

    #ifndef FILMWRITER_H
    #define FILMWRITER_H
    #include "Film.h"
    #include <QtGui>
    #include <QFile>

    class FilmWriter: public Film{

    public:
    void saveFilm(Film& f);

    };
    #endif // FILMWRITER_H

    #ifndef FILMINPUT_H
    #define FILMINPUT_H

    #include <QMainWindow>
    #include "Film.h"
    #include "FilmWriter.h"
    #include <QLabel>
    #include <QTextEdit>
    #include <QPushButton>

    namespace Ui {
    class FilmInput;
    }

    class FilmInput : public QMainWindow
    {
    Q_OBJECT

    public:
    explicit FilmInput(QWidget parent = 0);
    ~FilmInput();
    void obtainFilmData(Film& f);
    void saveFilm(Film& f);
    public slots:
    void getFilm();
    private:
    Ui::FilmInput ui;
    //widgets
    QMainWindow
    window;
    QLabel
    infoLabel;
    QLabel* titleLabel;
    QLabel* durationLabel;
    QLabel* directorLabel;
    QLabel* relDateLabel;
    QTextEdit* titleEdit;
    QTextEdit* durationEdit;
    QTextEdit* directorEdit;
    QTextEdit* relDateEdit;
    QPushButton* saveBtn;
    QPushButton* cancelBtn;
    Film f;
    //sets up gui and connects signals and slots
    void setUpGui();
    };

    #endif // FILMINPUT_H

    #include "Film.h"
    #include <QDate>
    #include <QString>

    Film::Film(QString t,int dur,QString dir,QDate r):m_title(t),m_duration(dur),m_director(dir),m_releaseDate(r){

    }

    Film::Film(){
    }

    void Film::setTitle(QString t){
    m_title = t;
    }

    void Film::setDuration(int dur){
    m_duration = dur;
    }

    void Film::setDirector(QString dir){
    m_director = dir;
    }

    void Film::setReleaseDate(QDate r){
    m_releaseDate = r;
    }

    QString Film::getTitle() const{
    return QString("%1").arg(m_title);
    }

    int Film::getDuration() const{
    return m_duration;
    }
    QString Film::getDirector() const{
    return QString("%1").arg(m_director);
    }
    QDate Film::getReleaseDate() const{
    return m_releaseDate;
    }
    QString Film::toString()
    {
    return m_title + " " + m_duration + " " + m_director + " " + m_releaseDate.toString();
    }

    #include "FilmWriter.h"
    #include <QtGui>
    #include <QFileDialog>
    #include <QFile>
    #include <QMessageBox>
    #include <QObject>
    #include <QTextStream>

    void FilmWriter::saveFilm(Film& f){
    QString fileName = QFileDialog::getSaveFileName(this,("Save File"));
    if (fileName != "") {
    QFile file(fileName);
    if (!file.open(QIODevice::WriteOnly)) {
    QMessageBox::critical(this, ("Error"),("Could not open file"));// error message
    } else {
    QTextStream stream(&file);
    stream << f.toString();
    stream.flush();
    file.close();
    }
    }

    }

    #include "filminput.h"
    #include "ui_filminput.h"
    #include <QtGui>
    #include "Film.h"
    #include "FilmWriter.h"
    #include <QTextEdit>
    #include <QDate>
    #include <QString>

    FilmInput::FilmInput(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::FilmInput)
    {
    ui->setupUi(this);
    setUpGui();
    }

    FilmInput::~FilmInput()
    {
    delete ui;
    }

    void FilmInput::setUpGui(){
    //initialise widgets
    infoLabel = new QLabel("Please enter film data which will be saved to a file",this);
    titleLabel = new QLabel("Film Title",this);
    durationLabel = new QLabel("Film Duration",this);
    directorLabel = new QLabel("Film Director",this);
    relDateLabel = new QLabel("Film Release Date",this);
    titleEdit = new QTextEdit(this);
    durationEdit = new QTextEdit(this);
    directorEdit = new QTextEdit(this);
    relDateEdit = new QTextEdit(this);
    saveBtn = new QPushButton("Save Film",this);
    cancelBtn = new QPushButton("Cancel",this);
    //set layout
    QFormLayout* layout = new QFormLayout();
    layout->addWidget(infoLabel);
    layout->addWidget(titleLabel);
    layout->addWidget(titleEdit);
    layout->addWidget(durationLabel);
    layout->addWidget(durationEdit);
    layout->addWidget(directorLabel);
    layout->addWidget(directorEdit);
    layout->addWidget(relDateLabel);
    layout->addWidget(relDateEdit);
    layout->addWidget(saveBtn);
    layout->addWidget(cancelBtn);

    this->ui->widget->setLayout(layout);
    this->setWindowTitle("Film Archive");
    connect(saveBtn,SIGNAL(clicked()),this, SLOT(getFilm()));
    connect(cancelBtn,SIGNAL(clicked()),this,SLOT(close()));
    

    }

    void FilmInput::getFilm(){
    Film f1(titleEdit->toPlainText(),durationEdit->toPlainText().toInt() ,directorEdit->toPlainText(),
    QDate::fromString(relDateEdit->toPlainText(),"dd/MM/YYYY"));;
    obtainFilmData(f1);
    }

    void FilmInput::obtainFilmData(Film &f){
    saveFilm(f);
    }

    #include <QtGui/QApplication>
    #include "filminput.h"

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

    FilmInput w;
    w.show();
    
    return a.exec&#40;&#41;;
    

    }
    @


  • Lifetime Qt Champion

    saveFilm is not a member of FilmInput.

    Besides that, please, got through the examples and the documentation of Qt, that would be beneficial to you.

    I don't want to sound rude but what you wrote here will not do for an assignment.

    Why does Film inherit QWidget ?
    Why does FilmWriter inherit Film if it's only function is to write a Film given as a parameter ?
    Why do you use a UI file if you create your interface by hand anyway ?



  • I thought that FilmWriter would need to inherit Film in order to create an object of type Film. Film inheriting QWidget is a mistake as it is left over from the question which was one class called film inheriting QWidget which I have to break up into 3 classes and then add functionality. Also the UI file was created automatically for me with Qt creator. I will look up some info on interfaces. So the question is to have the saveFilm function in the filmWriter class, how do I get it to work like that rather than making saveFilm a member of FilmInput and removing the FilmWriter class?


  • Lifetime Qt Champion

    No it doesn't, as long as it knows how to use Film.

    For the rest it's essentially doc reading



  • if I take out #include "Film.h" in FilmWriter there is a problem with the FilmWriter class, if I then take out : public Film there is a problem with the func saveFilm because it's parameter is of type Film. So how do I make it know how to use Film?


  • Lifetime Qt Champion

    This is C/C++ basic knowledge. Without the header file how would your class know anything about Film ?

    What problem would it be ?



  • well it wouldn't know about Film without the header file. Are you saying that it doesn't need to be a child of Film but just include the header?


  • Lifetime Qt Champion

    Yes, it's exactly what I'm saying



  • Ok great. But now after the changes I am still getting the same error :-?
    :: error: collect2: ld returned 1 exit status


  • Lifetime Qt Champion

    If you are talking about the saveFilm problem and the message didn't changed, then saveFilm is still not a member of FilmInput.

    Isn't it a member of FilmWriter ?



  • Yes and I don't want it to be a member of FilmInput, I want it to be member of FilmWriter only and somehow (I don't know how) be called in FilmInput. I thought if I included the FilmWriter header it would work, but obviously I must do something else.


  • Lifetime Qt Champion

    FilmWriter is a class, how do you call a function from a class ?



  • You create an object and call the function with the object. That's it! Ok so now you have helped me to get rid of that error, thanks a lot. Another question, when I click on the save film button which invokes saveFilm the program crashes, should I start a new thread because this is a new question or can you still help me on this one?


  • Lifetime Qt Champion

    Run your application through the debugger, it will tell you where the crash occurs



  • I got this: The inferior stopped because it received a signal from the operating system
    signal name: SIGSEGV
    Signal meaning: Segmentation fault
    then it is pointing to line 2185 in qglobal.h
    inline QFlags operator&(Enum f) const { QFlags g; g.i = i & f; return g; }


  • Lifetime Qt Champion

    What does the stack trace look like ?
    The lines under qglobal.h ?



  • I have a print screen, how do I post a pic on here?


  • Lifetime Qt Champion

    You have to use a picture hosting service or a public dropbox folder etc...





  • https://www.dropbox.com/s/mosnz8o23elipn5/Qtstack.jpg

    doesn't work with a space in the name


  • Lifetime Qt Champion

    Looks strange... Just to be on the safe side, delete the build directory completely and re-run your application.



  • ok now it doesn't run again with a bunch of errors:

    Running build steps for project Ass1Q1...
    Configuration unchanged, skipping qmake step.
    Starting: "C:/Qt/2010.04/mingw/bin/mingw32-make.exe" -w
    mingw32-make: Entering directory C:/Unisa/COS3711/assignments/Ass1Q1-build-desktop' C:/Qt/2010.04/mingw/bin/mingw32-make -f Makefile.Debug mingw32-make[1]: Entering directoryC:/Unisa/COS3711/assignments/Ass1Q1-build-desktop'
    g++ -c -g -frtti -fexceptions -mthreads -Wall -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DQT_NEEDS_QMAIN -I"........\Qt\2010.04\qt\include\QtCore" -I"........\Qt\2010.04\qt\include\QtGui" -I"........\Qt\2010.04\qt\include" -I"........\Qt\2010.04\qt\include\ActiveQt" -I"debug" -I"." -I"..\Ass1Q1" -I"." -I"........\Qt\2010.04\qt\mkspecs\win32-g++" -o debug\FilmWriter.o ..\Ass1Q1\FilmWriter.cpp
    ..\Ass1Q1\FilmWriter.cpp: In member function 'void FilmWriter::saveFilm(Film&)':
    ..\Ass1Q1\FilmWriter.cpp:10: error: no matching function for call to 'QFileDialog::getSaveFileName(FilmWriter* const, const char [10])'
    ........\Qt\2010.04\qt\include\QtGui/../../src/gui/dialogs/qfiledialog.h:216: note: candidates are: static QString QFileDialog::getSaveFileName(QWidget*, const QString&, const QString&, const QString&, QString*, QFlagsQFileDialog::Option)
    ..\Ass1Q1\FilmWriter.cpp:14: error: no matching function for call to 'QMessageBox::critical(FilmWriter* const, const char [6], const char [20])'
    ........\Qt\2010.04\qt\include\QtGui/../../src/gui/dialogs/qmessagebox.h:202: note: candidates are: static QMessageBox::StandardButton QMessageBox::critical(QWidget*, const QString&, const QString&, QFlagsQMessageBox::StandardButton, QMessageBox::StandardButton)
    ........\Qt\2010.04\qt\include\QtGui/../../src/gui/dialogs/qmessagebox.h:262: note: static int QMessageBox::critical(QWidget*, const QString&, const QString&, int, int, int)
    ........\Qt\2010.04\qt\include\QtGui/../../src/gui/dialogs/qmessagebox.h:265: note: static int QMessageBox::critical(QWidget*, const QString&, const QString&, const QString&, const QString&, const QString&, int, int)
    ........\Qt\2010.04\qt\include\QtGui/../../src/gui/dialogs/qmessagebox.h:272: note: static int QMessageBox::critical(QWidget*, const QString&, const QString&, QMessageBox::StandardButton, QMessageBox::StandardButton)
    mingw32-make[1]: Leaving directory C:/Unisa/COS3711/assignments/Ass1Q1-build-desktop' mingw32-make: Leaving directoryC:/Unisa/COS3711/assignments/Ass1Q1-build-desktop'
    mingw32-make[1]: *** [debug/FilmWriter.o] Error 1
    mingw32-make: *** [debug] Error 2
    The process "C:/Qt/2010.04/mingw/bin/mingw32-make.exe" exited with code %2.
    Error while building project Ass1Q1 (target: Desktop)
    When executing build step 'Make'


  • Lifetime Qt Champion

    FilmWriter is not a QWidget, you can't pass it as a parent when you call QFileDialog::getSaveFileName



  • If I make FilmWriter a QWidget the program runs but when I click on the save film button it crashes with: "this application has requested the runtime to terminate it in an unusual way. Please contact the application's support team for more information."

    Despite the crash, the program runs without any errors as you can see:
    Running build steps for project Ass1Q1...
    Configuration unchanged, skipping qmake step.
    Starting: "C:/Qt/2010.04/mingw/bin/mingw32-make.exe" -w
    mingw32-make: Entering directory C:/Unisa/COS3711/assignments/Ass1Q1-build-desktop' C:/Qt/2010.04/mingw/bin/mingw32-make -f Makefile.Debug mingw32-make[1]: Entering directoryC:/Unisa/COS3711/assignments/Ass1Q1-build-desktop'
    mingw32-make[1]: Nothing to be done for first'. mingw32-make[1]: Leaving directoryC:/Unisa/COS3711/assignments/Ass1Q1-build-desktop'
    mingw32-make: Leaving directory `C:/Unisa/COS3711/assignments/Ass1Q1-build-desktop'
    The process "C:/Qt/2010.04/mingw/bin/mingw32-make.exe" exited normally.


  • Lifetime Qt Champion

    Because you don't initialize it properly.

    Don't make FilmWriter inherit QWidget and don't make it a parent of the QFileDialog, it doesn't make any sense.

    For your tests just call QFileDialog::getSaveFileName().



  • ok now I'm confused!?! I am calling getSaveFileNAme

    void FilmWriter::saveFilm(Film& f){
    QString fileName = QFileDialog::getSaveFileName(this,("Save File"));
    if (fileName != "") {
    QFile file(fileName);
    if (!file.open(QIODevice::WriteOnly)) {
    QMessageBox::critical(this, ("Error"),("Could not open file"));// error message
    } else {
    QTextStream stream(&file);
    stream << f.toString();
    stream.flush();
    file.close();
    }
    }

    }


  • Lifetime Qt Champion

    change "this" by 0,

    FilmWriter is not a QWidget and should not be just for the purpose of giving QFileDialog::getSaveFileName a parent.



  • ca you give me the line QString fileName = QFileDialog::getSaveFileName();
    because I don't know what's wrong here?


  • Lifetime Qt Champion

    Just call

    @
    QString fileName = QFileDialog()::getSaveFileName(0, tr("Save File..."));
    @

    Please, check the documentation



  • thank you very much I did try that but it also didn't work...Needed to change the 'this' for the QMessageBox also. Can I just ask why would pointing to this(itself) be the wrong thing to do?


  • Lifetime Qt Champion

    Because FilmWriter is not a widget.

    And while you where inheriting QWidget, you never initialized it properly


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.