Я создал приложение со списком, как показано на этом скриншоте

У меня проблема с функциями сохранения / загрузки. Текст из заголовков (QLineEdit) сохраняется и загружается как обычно. Но когда я пытаюсь сохранить и загрузить строки под заголовками (определяемый пользователем класс с именем «Row»), QString из объекта QLineEdit загружается без символов.
Я проверил, что все сохраненные элементы все еще там, когда я выводил их в QDataStream, и что только QString, принадлежащая объекту QLineEdit объекта Row, пуста, когда предполагается, что он вводится из QDataStream в loading.
Заголовки создаются при запуске программы, а объекты Row создаются, когда пользователь нажимает кнопку добавления (значок + в верхней части), и сохраняются в приватном списке QList listOfRows.
// mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QObject>
#include <QFile>
#include <QLabel>
#include <QMessageBox>
#include "row.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_actionNew_Row_triggered();
void on_actionDelete_Rows_triggered();
void on_actionSelect_All_triggered();
void on_actionSave_triggered();
void on_actionLoad_triggered();
void on_actionShortcuts_triggered();
private:
Ui::MainWindow *ui;
QList<Row*> listOfRows;
void AddHeaderRow();
QLineEdit* headerOne;
QLineEdit* headerTwo;
QLineEdit* headerThree;
QCheckBox* deleteAllSelect;
QLabel* select;
};
#endif // MAINWINDOW_H
-
// mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "row.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
AddHeaderRow();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_actionNew_Row_triggered()
{
// new row
Row* newRow = new Row(this, listOfRows.size());
listOfRows.push_back(newRow);
}
void MainWindow::on_actionDelete_Rows_triggered()
{
// delete row
if(listOfRows.size() != 0)
{
for(auto row : listOfRows)
{
if(row->isToDelete())
{
row->hide();
listOfRows.removeOne(row);
}
}
for(int i = 0; i < listOfRows.size(); i++)
{
listOfRows[i]->reAlign(i);
}
}
}
void MainWindow::on_actionSelect_All_triggered()
{
if(deleteAllSelect->checkState())
{
for(auto row : listOfRows)
{
row->setStateCheckBoxDelete(true);
}
}else
{
for(auto row : listOfRows)
{
row->setStateCheckBoxDelete(false);
}
}
}
void MainWindow::AddHeaderRow()
{
this->headerOne = new QLineEdit;
this->headerTwo = new QLineEdit;
this->headerThree = new QLineEdit;
this->deleteAllSelect = new QCheckBox;
this->select = new QLabel("Select");
ui->horizontalLayout->addWidget(headerOne, 2, Qt::AlignHCenter);
ui->horizontalLayout->addWidget(headerTwo, 2, Qt::AlignHCenter);
ui->horizontalLayout->addWidget(headerThree, 3);
ui->horizontalLayout->addWidget(select, 1, Qt::AlignHCenter);
}
void MainWindow::on_actionSave_triggered()
{
QMessageBox msgBox;
msgBox.setIcon(QMessageBox::Question);
msgBox.setWindowIcon(MainWindow::windowIcon());
msgBox.setWindowTitle("Save");
msgBox.setText("Do you want to save your changes?");
msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Save);
int ret = msgBox.exec();
if(ret == QMessageBox::Save)
{
QString path = "rows.bin";
QFile file(path);
if (file.open(QIODevice::WriteOnly))
{
qDebug() << "File opened!";
QDataStream out(&file);
out << this->headerOne->text() << this->headerTwo->text() << this->headerThree->text();
for(auto row : listOfRows)
{
out << row;
}
file.close();
}
}
}
void MainWindow::on_actionLoad_triggered()
{
QString path = "rows.bin";
QFile file(path);
if(file.exists())
{
if (file.open(QIODevice::ReadOnly))
{
QDataStream in(&file);
QString textOne;
QString textTwo;
QString textThree;
in >> textOne >> textTwo >> textThree;
this->headerOne->setText(textOne);
this->headerTwo->setText(textTwo);
this->headerThree->setText(textThree);
while(!in.atEnd())
{
Row* tempRow = new Row(this);
in >> tempRow;
listOfRows.push_back(tempRow);
qDebug() << "To file: " << tempRow->checkStateOne() << tempRow->checkStateTwo() << tempRow->textFromBox();
}
file.close();
}
}
}
void MainWindow::on_actionShortcuts_triggered()
{
QMessageBox shortcuts;
shortcuts.setWindowTitle("Shortcuts");
shortcuts.setIcon(QMessageBox::Information);
shortcuts.setWindowIcon(MainWindow::windowIcon());
shortcuts.setText("New Row - Ctrl + N\n"
"Delete Selected - Ctrl + D\n"
"Save - Ctrl + S\n"
"Load - Ctrl + L\n");
shortcuts.exec();
}
-
// row.h
#ifndef ROW_H
#define ROW_H
#include <QFrame>
#include <QPainter>
#include <QCheckBox>
#include <QLineEdit>
#include <QList>
#include <QDebug>
#include <QHBoxLayout>
#include <QDataStream>
class Row : public QFrame
{
Q_OBJECT
static const int containerHeight = 40;
public:
Row(QWidget* parent = nullptr, int yPos = 0);
~Row() override;
bool isToDelete() const;
void reAlign(int);
void setStateCheckBoxDelete(bool);
bool checkStateOne() const;
bool checkStateTwo() const;
QString textFromBox() const;
void setCheckStateOne(bool);
void setCheckStateTwo(bool);
void setTextToBox(QString);
private:
QWidget* parent;
QCheckBox* checkBoxOne;
QCheckBox* checkBoxTwo;
QLineEdit* textBox;
QCheckBox* checkBoxDelete;
};
QDataStream& operator<<(QDataStream&, Row&);
QDataStream& operator>>(QDataStream&, Row*);
#endif // ROW_H
-
// row.cpp
#include "row.h"
Row::Row(QWidget* parent, int yPos) : QFrame(parent)
{
QHBoxLayout* layout = new QHBoxLayout();
checkBoxOne = new QCheckBox(this);
checkBoxTwo = new QCheckBox(this);
textBox = new QLineEdit(this);
checkBoxDelete = new QCheckBox(this);
layout->addWidget(checkBoxOne, 2, Qt::Alignment(Qt::AlignHCenter));
layout->addWidget(checkBoxTwo, 2, Qt::Alignment(Qt::AlignHCenter));
layout->addWidget(textBox, 3);
layout->addWidget(checkBoxDelete, 1, Qt::Alignment(Qt::AlignHCenter));
this->parent = parent;
this->setLayout(layout);
this->resize(parent->size().width(), containerHeight);
this->move(0, 50 + containerHeight * (1 + yPos));
this->show();
}
Row::~Row()
{
this->parent = nullptr;
delete parent;
delete checkBoxOne;
delete checkBoxTwo;
delete textBox;
delete checkBoxDelete;
}
bool Row::isToDelete() const
{
return checkBoxDelete->checkState();
}
void Row::reAlign(int yPos)
{
this->move(0, 50 + containerHeight * (1 + yPos));
}
void Row::setStateCheckBoxDelete(bool check)
{
this->checkBoxDelete->setCheckState(Qt::CheckState(check));
}
bool Row::checkStateOne() const
{
return checkBoxOne->checkState();
}
bool Row::checkStateTwo() const
{
return checkBoxTwo->checkState();
}
QString Row::textFromBox() const
{
return textBox->text();
}
void Row::setCheckStateOne(bool check)
{
this->checkBoxOne->setCheckState(Qt::CheckState(check));
}
void Row::setCheckStateTwo(bool check)
{
this->checkBoxTwo->setCheckState(Qt::CheckState(check));
}
void Row::setTextToBox(QString text)
{
this->textBox->setText(text);
}
QDataStream& operator<<(QDataStream& out, Row& row)
{
out << row.checkStateOne();
out << row.checkStateTwo();
out << row.textFromBox();
return out;
}
QDataStream& operator>>(QDataStream& in, Row* row)
{
bool checkOne;
bool checkTwo;
QString text;
in >> checkOne;
in >> checkTwo;
in >> text;
row->setCheckStateOne(checkOne);
row->setCheckStateTwo(checkTwo);
row->setTextToBox(text);
return in;
}
-
// main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
-
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>801</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>Monika's Awesome Widget</string>
</property>
<property name="windowIcon">
<iconset>
<normaloff>../MoniquesUnique/Icons/noun_Elephant_5119.svg</normaloff>../MoniquesUnique/Icons/noun_Elephant_5119.svg</iconset>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>0</y>
<width>781</width>
<height>31</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout"/>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>801</width>
<height>26</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>File</string>
</property>
<addaction name="actionSave"/>
<addaction name="actionLoad"/>
</widget>
<widget class="QMenu" name="menuEdit">
<property name="title">
<string>Edit</string>
</property>
<addaction name="actionNew_Row"/>
<addaction name="actionDelete_Rows"/>
</widget>
<widget class="QMenu" name="menuHelp">
<property name="title">
<string>Help</string>
</property>
<addaction name="actionShortcuts"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuEdit"/>
<addaction name="menuHelp"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<widget class="QToolBar" name="toolBar">
<property name="windowTitle">
<string>toolBar</string>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="actionNew_Row"/>
<addaction name="actionDelete_Rows"/>
<addaction name="actionSave"/>
<addaction name="actionLoad"/>
</widget>
<action name="actionNew_Row">
<property name="icon">
<iconset>
<normaloff>../MoniquesUnique/Icons/plus-circle.svg</normaloff>../MoniquesUnique/Icons/plus-circle.svg</iconset>
</property>
<property name="text">
<string>New Row</string>
</property>
<property name="shortcut">
<string>Ctrl+N</string>
</property>
</action>
<action name="actionDelete_Rows">
<property name="icon">
<iconset>
<normaloff>../MoniquesUnique/Icons/delete.svg</normaloff>../MoniquesUnique/Icons/delete.svg</iconset>
</property>
<property name="text">
<string>Delete Selected</string>
</property>
<property name="shortcut">
<string>Ctrl+D</string>
</property>
</action>
<action name="actionSave">
<property name="icon">
<iconset>
<normaloff>../MoniquesUnique/Icons/save.svg</normaloff>../MoniquesUnique/Icons/save.svg</iconset>
</property>
<property name="text">
<string>Save</string>
</property>
<property name="shortcut">
<string>Ctrl+S</string>
</property>
</action>
<action name="actionLoad">
<property name="icon">
<iconset>
<normaloff>../MoniquesUnique/Icons/briefcase.svg</normaloff>../MoniquesUnique/Icons/briefcase.svg</iconset>
</property>
<property name="text">
<string>Load</string>
</property>
<property name="shortcut">
<string>Ctrl+L</string>
</property>
</action>
<action name="actionShortcuts">
<property name="icon">
<iconset>
<normaloff>../MoniquesUnique/Icons/info.svg</normaloff>../MoniquesUnique/Icons/info.svg</iconset>
</property>
<property name="text">
<string>Shortcuts</string>
</property>
</action>
</widget>
<resources/>
<connections/>
</ui>