#include "main_window.h"
bool MainWindow::saveChangesBeforeProceeding(QString parentFunction, bool close)
{
if (current_db_open && this->isWindowModified()) {
switch (QMessageBox::information(this, parentFunction, tr("Save changes before proceeding?"), tr("&Save"), tr("&Discard"), tr("Cancel"), 0, 2)) {
case 0: current_db_open = false;
save(); if (close) {closeDB();}; return false;
break;
case 1: current_db_open = false;
if (close) {closeDB();}; return false;
break;
case 2: return true;
break;
}
} else if (current_db_open && (!this->isWindowModified())) {
if (close) {closeDB();}; return false;
}
return false;
}
void MainWindow::newDB()
{
this->setEnabled(false);
bool cancelled = saveChangesBeforeProceeding(tr("New database"), true);
if (cancelled) { this->setEnabled(true); return; }
bool ok;
QString db_name = QInputDialog::getText(this, tr("New database"), tr("Database name:"), QLineEdit::Normal, tr("Untitled database"), &ok);
QString saveDBName;
if (!ok) { this->setEnabled(true); return; }
if (!db_name.isEmpty()) {
saveDBName = QFileDialog::getSaveFileName(this, tr("Create database file"), tr("%1.itdb").arg(db_name), tr("iTest databases (*.itdb)"));
} else {
saveDBName = QFileDialog::getSaveFileName(this, tr("Create database file"), tr("untitled.itdb"), tr("iTest databases (*.itdb)"));
}
QFile file(saveDBName);
if (!file.open(QFile::WriteOnly | QFile::Text))
{
QMessageBox::critical(this, tr("Create database file"), tr("Cannot write file %1:\n%2.").arg(saveDBName).arg(file.errorString()));
this->setWindowTitle(tr("iTest - Database Editor"));
this->setEnabled(true); return;
}
setProgress(10); QTextStream sfile(&file);
sfile.setCodec("CP 1250");
sfile << "[ITEST_VERSION]\n" << ver << endl;
sfile << "[ITEST_DB_VERSION]\n" << db_ver << endl;
sfile << "[DB_NAME]\n" << db_name << endl;
sfile << "[DB_DATE]\n" << endl;
sfile << "[DB_DATE_ULSD]\ntrue" << endl;
sfile << "[DB_COMMENTS]\n" << endl;
sfile << "[DB_QNUM]\n0" << endl;
sfile << "[DB_SNUM]\n0" << endl;
sfile << "[DB_FLAGS]" << endl;
sfile << "--------------------\n";
for (int i = 0; i < 20; ++i) {sfile << "[DB_F" << i << "]\n" << endl;}
sfile << "[DB_FLAGS_END]";
setProgress(50); enableAll(); clearAll();
DBIDatabaseNameLineEdit->setText( db_name );
current_db_file = saveDBName;
current_db_name = db_name;
current_db_open = true;
addRecent(saveDBName);
this->setWindowTitle(tr("%1[*] - iTest - Database Editor").arg(current_db_name));
this->setWindowModified(false);
statusBar()->showMessage(tr("Ready"), 10000);
setProgress(100); setProgress(-1); actionEdit_questions->setChecked(true);
actionUse_last_save_date->setChecked(true);
DBIUseLastSaveDateCheckBox->setChecked(true);
DBIDateEdit->setDateTime(QDateTime::currentDateTime());
DBIDateEdit->setEnabled(false);
setPage(actionEdit_questions);
this->setEnabled(true);
}
void MainWindow::save() { saveDB(current_db_file); }
void MainWindow::saveAs()
{
QString db_name = DBIDatabaseNameLineEdit->text();
QString saveDBName = QFileDialog::getSaveFileName(this, tr("Save database"), QString("%1.itdb").arg(db_name), tr("iTest databases (*.itdb)"));
if (!saveDBName.isNull() || saveDBName.isEmpty()) { addRecent(saveDBName); saveDB(saveDBName); }
}
void MainWindow::saveDB(QString db_file_name)
{
this->setEnabled(false); qApp->processEvents();
QString db_name = DBIDatabaseNameLineEdit->text();
QString use_last_save_date; QString db_date;
if (actionUse_last_save_date->isChecked()) {
db_date = QDateTime::currentDateTime().toString("yyyy.MM.dd-hh:mm");
use_last_save_date = "true";
} else {
db_date = DBIDateEdit->dateTime().toString("yyyy.MM.dd-hh:mm");
use_last_save_date = "false";
}
QString db_comments = removeLineBreaks(ECTextEdit->toHtml());
QFile file(db_file_name);
if (!file.open(QFile::WriteOnly | QFile::Text))
{
QMessageBox::critical(this, tr("Save database"), tr("Cannot write file %1:\n%2.").arg(db_file_name).arg(file.errorString()));
this->setEnabled(true); return;
}
setProgress(5); QTextStream sfile(&file); QString q_file_name;
sfile.setCodec("CP 1250");
sfile << "[ITEST_VERSION]\n" << ver << endl;
sfile << "[ITEST_DB_VERSION]\n" << db_ver << endl;
sfile << "[DB_NAME]\n" << db_name << endl;
sfile << "[DB_DATE]\n" << db_date << endl;
sfile << "[DB_DATE_ULSD]\n" << use_last_save_date << endl;
sfile << "[DB_COMMENTS]\n" << db_comments << endl;
sfile << "[DB_QNUM]\n" << current_db_questions.size() << endl;
sfile << "[DB_SNUM]\n" << current_db_sessions.size() << endl;
sfile << "[DB_FLAGS]" << endl;
for (int i = 0; i < 20; ++i)
{if (current_db_fe[i]) {sfile << "+";} else {sfile << "-";}} sfile << endl;
for (int i = 0; i < 20; ++i)
{sfile << "[DB_F" << i << "]" << endl; sfile << current_db_f[i] << endl;}
sfile << "[DB_FLAGS_END]" << endl;
setProgress(10); int count = current_db_questions.size() + current_db_sessions.size();
uint n = current_db_questions.size();
for (int i = 0; i < LQListWidget->count(); ++i) {
sfile << current_db_questions.value(LQListWidget->item(i))->allProperties() << endl;
setProgress((90/(i+1)*count)+10); }
QMapIterator<QDateTime, Session *> i(current_db_sessions);
while (i.hasNext()) { i.next(); n++;
sfile << i.value()->sessionData() << endl;
for (int s = 0; s < i.value()->numStudents(); ++s) {
sfile << i.value()->student(s)->studentData() << endl;
}
setProgress((90/n*count)+10); }
current_db_name = db_name;
current_db_date = db_date;
current_db_comments = db_comments;
current_db_file = db_file_name;
if (actionUse_last_save_date->isChecked()) {
DBIDateEdit->setDateTime(QDateTime::fromString(current_db_date, "yyyy.MM.dd-hh:mm"));
}
this->setWindowTitle(tr("%1[*] - iTest - Database Editor").arg(current_db_name));
this->setWindowModified(false);
statusBar()->showMessage(tr("Database saved"), 10000);
setProgress(100); setProgress(-1); this->setEnabled(true);
}
void MainWindow::open()
{
bool cancelled = saveChangesBeforeProceeding(tr("Open database"), true);
if (!cancelled) {
QString openDBName = QFileDialog::getOpenFileName(this, tr("Open database file"), "", tr("iTest databases (*.itdb);;All files (*.*)"));
if (!openDBName.isNull()) { addRecent(openDBName); openDB(openDBName); }
}
}
void MainWindow::openRecent()
{
if (recentDBsListWidget->currentIndex().isValid()) {
addRecent(recentDBsListWidget->currentItem()->text());
openDB(recentDBsListWidget->currentItem()->text());
}
}
void MainWindow::openRecent(QListWidgetItem * item)
{
QString buffer = item->text();
addRecent(buffer);
openDB(buffer);
}
void MainWindow::openDB(QString openDBName)
{
if (openDBName.isNull()) { return; }
this->setEnabled(false); qApp->processEvents();
QFile file(openDBName);
if (!file.open(QFile::ReadOnly | QFile::Text))
{
QMessageBox::critical(this, tr("Open database"), tr("Cannot read file %1:\n%2.").arg(openDBName).arg(file.errorString()));
this->setEnabled(true); return;
}
setProgress(3); QTextStream rfile(&file);
rfile.setCodec("CP 1250");
QString db_buffer; float version; float db_version; QString db_name;
QString db_date; QString db_comments; int db_qnum; bool db_fxxe[20];
QString db_f[20]; QString q_file_name; QString db_ulsd; int s_lenum;
QuestionItem * item; QStringList answers; int db_snum; int s_snum;
QStringList bufferlist; QuestionItem::Answer ans;
QuestionItem::Answer c_ans;
db_buffer = rfile.readLine();
if (db_buffer != "[ITEST_VERSION]")
{ errorInvalidDBFile(tr("Open database"), openDBName); return; }
db_buffer = rfile.readLine();
version = db_buffer.toFloat();
db_buffer = rfile.readLine();
if (db_buffer != "[ITEST_DB_VERSION]")
{ errorInvalidDBFile(tr("Open database"), openDBName); return; }
db_buffer = rfile.readLine();
db_version = db_buffer.toFloat();
if ((version > f_ver) && (db_version == f_db_ver))
{ QMessageBox::information(this, tr("iTest version notice"), tr("There is a newer version of iTest available.\nNonetheless, this version is able to open the database file you selected,\nbut you are most probably missing a whole bunch of cool new features.")); }
if ((version > f_ver) && (db_version > f_db_ver))
{ QMessageBox::critical(this, tr("iTest version notice"), tr("You need a newer version of iTest to open this database file.")); this->setEnabled(true); return; }
if (rfile.readLine() != "[DB_NAME]")
{ errorInvalidDBFile(tr("Open database"), openDBName); return; }
db_name = rfile.readLine();
if (rfile.readLine() != "[DB_DATE]")
{ errorInvalidDBFile(tr("Open database"), openDBName); return; }
db_date = rfile.readLine();
if (rfile.readLine() != "[DB_DATE_ULSD]")
{ errorInvalidDBFile(tr("Open database"), openDBName); return; }
db_ulsd = rfile.readLine();
if (rfile.readLine() != "[DB_COMMENTS]")
{ errorInvalidDBFile(tr("Open database"), openDBName); return; }
db_comments = rfile.readLine();
if (rfile.readLine() != "[DB_QNUM]")
{ errorInvalidDBFile(tr("Open database"), openDBName); return; }
db_qnum = rfile.readLine().toInt();
if (rfile.readLine() != "[DB_SNUM]")
{ errorInvalidDBFile(tr("Open database"), openDBName); return; }
db_snum = rfile.readLine().toInt();
if (rfile.readLine() != "[DB_FLAGS]")
{ errorInvalidDBFile(tr("Open database"), openDBName); return; }
setProgress(6); db_buffer = rfile.readLine();
for (int i = 0; i < 20; ++i) {
if (db_buffer.at(i) == '+') {db_fxxe[i] = true;} else if (db_buffer.at(i) == '-')
{db_fxxe[i] = false;} else { errorInvalidDBFile(tr("Open database"), openDBName); return; }
}
for (int i = 0; i < 20; ++i) {
if (rfile.readLine() != QString("[DB_F%1]").arg(i)) { errorInvalidDBFile(tr("Open database"), openDBName); return; }
db_f[i] = rfile.readLine();
}
if (rfile.readLine() != "[DB_FLAGS_END]") { errorInvalidDBFile(tr("Open database"), openDBName); return; }
setProgress(10); int count = db_qnum + db_snum;
for (int i = 0; i < db_qnum; ++i) {
answers.clear();
if (rfile.readLine() != "[Q_NAME]") { errorInvalidDBFile(tr("Open database"), openDBName); return; }
item = new QuestionItem (rfile.readLine());
if (rfile.readLine() != "[Q_FLAG]") { errorInvalidDBFile(tr("Open database"), openDBName); return; }
item->setFlag(rfile.readLine().toInt());
if (rfile.readLine() != "[Q_DIFFICULTY]") { errorInvalidDBFile(tr("Open database"), openDBName); return; }
item->setDifficulty(rfile.readLine().toInt());
if (rfile.readLine() != "[Q_TEXT]") { errorInvalidDBFile(tr("Open database"), openDBName); return; }
item->setText(rfile.readLine());
if (rfile.readLine() != "[Q_ANSA]") { errorInvalidDBFile(tr("Open database"), openDBName); return; }
answers << rfile.readLine();
if (rfile.readLine() != "[Q_ANSA_C]") { errorInvalidDBFile(tr("Open database"), openDBName); return; }
answers << rfile.readLine();
if (rfile.readLine() != "[Q_ANSB]") { errorInvalidDBFile(tr("Open database"), openDBName); return; }
answers << rfile.readLine();
if (rfile.readLine() != "[Q_ANSB_C]") { errorInvalidDBFile(tr("Open database"), openDBName); return; }
answers << rfile.readLine();
if (rfile.readLine() != "[Q_ANSC]") { errorInvalidDBFile(tr("Open database"), openDBName); return; }
answers << rfile.readLine();
if (rfile.readLine() != "[Q_ANSC_C]") { errorInvalidDBFile(tr("Open database"), openDBName); return; }
answers << rfile.readLine();
if (rfile.readLine() != "[Q_ANSD]") { errorInvalidDBFile(tr("Open database"), openDBName); return; }
answers << rfile.readLine();
if (rfile.readLine() != "[Q_ANSD_C]") { errorInvalidDBFile(tr("Open database"), openDBName); return; }
answers << rfile.readLine();
if (rfile.readLine() != "[Q_ICNT]") { errorInvalidDBFile(tr("Open database"), openDBName); return; }
item->setIncorrectAnsCount(rfile.readLine().toUInt());
if (rfile.readLine() != "[Q_CCNT]") { errorInvalidDBFile(tr("Open database"), openDBName); return; }
item->setCorrectAnsCount(rfile.readLine().toUInt());
if (rfile.readLine() != "[Q_END]") { errorInvalidDBFile(tr("Open database"), openDBName); return; }
item->setAnswers(answers);
QListWidgetItem * q_item = new QListWidgetItem (item->name());
LQListWidget->addItem(q_item);
current_db_questions.insert(q_item, item);
switch (item->difficulty()) {
case 0: q_item->setIcon(QIcon(QString::fromUtf8(":/images/images/easy.png"))); break;
case 1: q_item->setIcon(QIcon(QString::fromUtf8(":/images/images/medium.png"))); break;
case 2: q_item->setIcon(QIcon(QString::fromUtf8(":/images/images/difficult.png"))); break;
default: q_item->setIcon(QIcon(QString::fromUtf8(":/images/images/easy.png"))); break;
}
setQuestionItemColour(q_item, item->flag());
setProgress((85/(i+1)*count)+10); }
for (int i = 0; i < db_qnum; ++i) {
if (rfile.atEnd()) { break; }
if (rfile.readLine() != "[SESSION]") { continue; }
Session * session = new Session;
session->setName(rfile.readLine());
session->setDateTimeFromString(rfile.readLine());
session->setPassMark(rfile.readLine().toInt());
s_snum = rfile.readLine().toInt();
s_lenum = rfile.readLine().toInt();
for (int le = 0; le < s_lenum; ++le) {
bufferlist.clear();
bufferlist = rfile.readLine().split(';');
if (bufferlist.count() == 6) {
session->addLogEntry(bufferlist.at(0).toInt(),
bufferlist.at(1).toInt(),
bufferlist.at(2).toInt(),
bufferlist.at(3).toInt(),
bufferlist.at(4).toInt(),
bufferlist.at(5).toInt(),
rfile.readLine());
} else {
session->addLogEntry(255, 255, 255, 0, 0, 0, rfile.readLine());
}
}
for (int s = 0; s < s_snum; ++s) {
if (rfile.atEnd()) { break; }
if (rfile.readLine() != "[STUDENT]") { continue; }
Student * student = new Student (rfile.readLine());
if (rfile.readLine() == "true") { student->setReady(true); }
else { student->setReady(false); }
student->setNumber(rfile.readLine().toInt());
student->setScore(rfile.readLine().toInt());
int numresults = rfile.readLine().toInt();
QMap<QString, QuestionAnswer> * results = new QMap<QString, QuestionAnswer>;
for (int a = 0; a < numresults; ++a) {
db_buffer = rfile.readLine();
ans = (QuestionItem::Answer)rfile.readLine().toInt();
c_ans = (QuestionItem::Answer)rfile.readLine().toInt();
QuestionAnswer qans (c_ans, ans);
results->insert(db_buffer, qans);
}
student->setResults(results);
session->addStudent(student);
}
current_db_sessions.insert(session->dateTime(), session);
QListWidgetItem * item = new QListWidgetItem (QString("%1 - %2").arg(session->dateTimeToString()).arg(session->name()));
VSSLSListWidget->insertItem(0, item);
item->setData(Qt::UserRole, session->dateTime());
setProgress((85/(db_qnum+i+1)*count)+10); }
DBIDatabaseNameLineEdit->setText( db_name );
DBIDateEdit->setDateTime( QDateTime::fromString(db_date, "yyyy.MM.dd-hh:mm") );
if (db_ulsd == "true") {
DBIUseLastSaveDateCheckBox->setChecked(true);
actionUse_last_save_date->setChecked(true);
DBIDateEdit->setEnabled(false);
} else if (db_ulsd == "false") {
DBIUseLastSaveDateCheckBox->setChecked(false);
actionUse_last_save_date->setChecked(false);
DBIDateEdit->setEnabled(true);
}
ECTextEdit->setHtml( db_comments );
for (int i = 0; i < 20; ++i) {current_db_fe[i] = db_fxxe[i];}
for (int i = 0; i < 20; ++i) {current_db_f[i] = db_f[i];}
setProgress(97); setFlags(); loadFlags();
setProgress(98); enableAll();
setProgress(99); current_db_file = openDBName;
current_db_name = db_name;
current_db_date = db_date;
current_db_comments = db_comments;
current_db_open = true;
this->setWindowTitle(tr("%1[*] - iTest - Database Editor").arg(current_db_name));
this->setWindowModified(false);
statusBar()->showMessage(tr("Database open"), 10000);
setProgress(100); setProgress(-1); actionEdit_questions->setChecked(true);
mainStackedWidget->setCurrentIndex(1); updateGeometry();
this->setEnabled(true);
}
void MainWindow::closeDB()
{
bool cancelled = saveChangesBeforeProceeding(tr("Close database"), false);
if (!cancelled) {
clearAll(); disableAll(); current_db_open = false;
this->setWindowTitle(tr("iTest - Database Editor"));
this->setWindowModified(false);
setProgress(100); setProgress(-1); mainStackedWidget->setCurrentIndex(0); updateGeometry();
statusBar()->showMessage(tr("Database closed"), 10000);
}
}