0

I have a program that allows for a user to create a profile that saves values using qsettings, the user accesses their profile by clicking on the name in a qlistwidget. I am trying to save the names of the profiles by using a text file but I am having trouble saving more than one profile name at a time. thank you! here is the code:

for saving a profilename to the text document

void Profile::writeProfilenames()
{
    QString profilename = ui->lineEdit_profilename->text();
    profilename = profilename.simplified();
    QFile pfile("profilenames.txt");
    if (!pfile.open(QFile::WriteOnly | QIODevice::Text))
    {
        return;
    }

    QTextStream out(&pfile);
    out << profilename;
    pfile.flush();
    pfile.close();

}

for retrieving the profile names from the document

void Profile::readProfilenames()
{
    QFile pfile("profilenames.txt");
    if (!pfile.open(QIODevice::ReadOnly |
                       QIODevice::Text))
   {
        return;
   }

    QString proname = pfile.readLine();
    QListWidgetItem *itm = new QListWidgetItem;
    itm->setText(proname);
    ui->listWidget_profiles->insertItem(0,itm);
}

P.S. if you know of a better way to do this then feel free to share! (with example please)

theChef613
  • 127
  • 1
  • 9

2 Answers2

1

I don't quite see why you're saving the list of names in a text file, while the settings themselves are saved in a platform-specific fashion using QSettings.

The code you show has several problems:

  1. Presumably you don't want to "write" the name to the file, overwriting the existing contents at the beginning, but specifically to append to the file. You also must specify a writable path to the file, so far you're using the current working directory that is: variable, not under your control, and not necessarily writable. Your code also doesn't handle repeated names.

  2. QFile is a proper C++ class, and embodies the RAII principles. You don't have to do anything to flush and close the file. The compiler takes care of generating the proper code for you. That's why you're using C++ and not C, after all. Yes, your code compiles, but it reads like C, and such verbosity is unnecessary and counterproductive.

  3. You're only retrieving one name from the file. You want to retrieve all of them.

I'd say that you should dispense with the file access, set up your application's identification, a crucial prerequisite to using QSettings, and, finally, use them:

struct Profile {
  QString name;
  int age;
}

void saveProfiles(const QList<Profile> & profiles)
{
  QSettings s;
  s.beginWriteArray("profiles");
  for (int i = 0; i < profiles.size(); ++i) {
    s.setArrayIndex(i);
    const Profile & p = profiles.at(i);
    s.setValue("name", p.name);
    s.setValue("age", p.age);
  }
  s.endArray(); //optional
}

QList<Profile> loadProfiles()
{
  QList<Profile> profiles;
  QSettings s;
  int size = s.beginReadArray("profiles");
  for (int i = 0; i < size; ++i) {
    s.setArrayIndex(i);
    Profile p;
    p.name = s.value("name").toString();
    p.age = s.value("age").toInt();
    profiles << p;
  }
  s.endArray(); // optional
  return profiles;
}

int main(int argc, char ** argv) {
  QApplication app(argc, argv);
  app.setOrganizationName("fluxD613"); // ideally use setOrganizationDomain instead
  app.setApplicationName("fluxer");
  ...
  return app.exec();
}
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
  • I implement qsettings in another forum/window and the profilename is just "keyword" that is passed over to the other forum to tell what settings to use. will this code still work? also i am getting the following errors that i am having trouble resolve: in `saveProfilenames` the compiler says that there is an expected initializer before '&' tokenbefore and that `p` was not declared in this scope. if I take at the address operator, it compiles just fine.If I understand the code correctly, this creates a QList of profilenames that i can then add to the listwidget? thanks for the help – theChef613 Jul 29 '14 at 01:28
  • @fluxD613 It was a reference, it's fixed. – Kuba hasn't forgotten Monica Jul 29 '14 at 03:13
  • where do the actual names of the profiles that the user makes go? for example the ui-> lineedit->text() – theChef613 Jul 29 '14 at 04:14
  • @fluxD613 It's up to you. You can put them in `Profile.name`, or `Profile.profileName` or whatever. I don't know what you want to do, you have to figure it out. – Kuba hasn't forgotten Monica Jul 29 '14 at 11:28
0

After a lot more research and trial and error I came up with the following code that does the trick: this function is implemented when I close the profiles dialog window and return to the main window using QCloseEvent.

 void Profile::writeProfilenames()
{
QFile pfile("profilenames.txt");
if (!pfile.open(QFile::WriteOnly | QIODevice::Text))
{
    return;
}

for(int row = 0; row < ui->listWidget_profiles->count(); row++)
{
    QListWidgetItem *item = ui->listWidget_profiles->item(row);
    QTextStream out(&pfile);
    out << item->text().simplified() << "\n";
}

pfile.close();

}

reading the list of profilenames is implemented when I open the dialog window just under ui->setup(this).

void Profile::readProfilenames()
{

QFile pfile("profilenames.txt");
if (!pfile.open(QIODevice::ReadOnly |
                       QIODevice::Text))
   {
    return;
   }
QTextStream in(&pfile);
while (!in.atEnd())
{
    QString line = in.readLine();
    QListWidgetItem *item = new QListWidgetItem;
    item->setText(line);
    ui->listWidget_profiles->addItem(item);
}

pfile.close();

}

I am now working on making sure the user does not enter a profilename that already exists and deleting a profilename from the QListWidget.

theChef613
  • 127
  • 1
  • 9