Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ПЗ irina.docx
Скачиваний:
0
Добавлен:
01.03.2025
Размер:
1.17 Mб
Скачать

Заключение

В данном курсовом проекте была разработана информационная система для проведения тестирования среди студентов или более широкого круга пользователей.

Были проведены анализ требований, проектирование базы данных и запросов к ней. Разработано приложение, выполняющее все требуемые функции.

Для разработки приложения использовались: C++, Qt, PostgreSQL.

При проведении тестирования клиентского приложения ошибок не обнаружено.

Цель разработки достигнута.

Список использованных источников

  1. PostgreSQL. Серия из шести статей Евгения Балдина, опубликованных в журнале Linux Format (2006—2007).

  2. PostgreSQL. Наиболее продвинутая открытая СУБД в мире. Русскоязычный сайт о PostgreSQL (http://postgresql.ru.net/).

  3. Дж. Уорсли, Дж. Дрейк - PostgreSQL для профессионалов [2003].

  4. Русскоязычный форум по Qt (http://www.prog.org.ru/).

  5. Жасмин Бланшет, Марк Саммерфилд - Qt 4: программирование GUI на С++ [2007].

  6. М. Шлее - Qt Профессиональное программирование на С++[2006].

  7. Официальная документация Qt (http://doc.qt.nokia.com/).

Приложение а (обязательное)

Текст программы

«DBAccess.h»:

#pragma once

#include <QSqlDatabase>

#include "../TS_Lecturer/Question.h"

class DBAccess

{

public:

DBAccess();

bool Connect(const QString& hostName, const QString& databaseName, const QString& userName, const QString& password);

~DBAccess(void);

QStringList GetStudentsList (QString group);

bool AddAnswer (int id, QString GroupName);

QString FindId(QString idCode);

void GetQuestions ();

void ShowQuestions(QTextBrowser *outQuestion, QGridLayout *outAnswer);

void ShowNextQuestion (QTextBrowser *outQuestion, QGridLayout *outAnswer);

void ShowPrevQuestion (QTextBrowser *outQuestion, QGridLayout *outAnswer);

int QuestionNumber;

private:

QSqlDatabase db;

int idTest;

CQuestions questions;

};

«DBAccess.cpp»:

#include "DBAccess.h"

#include <QMessageBox>

#include <QtSql>

#include <QDateTime>

#include <QTextBrowser>

DBAccess::DBAccess(void)

{

db = QSqlDatabase::addDatabase("QPSQL");

QuestionNumber = 0;

}

DBAccess::~DBAccess(void)

{

}

bool DBAccess::Connect(const QString& hostName, const QString& databaseName, const QString& userName, const QString& password)

{

db.setHostName(hostName);

db.setDatabaseName(databaseName);

db.setUserName(userName);

db.setPassword(password);

if (!db.open())

{

QMessageBox::critical(0, "Database Error", db.lastError().text());

return false;

}

return true;

}

QStringList DBAccess::GetStudentsList (QString group)

{

QStringList students;

QSqlQuery query;

QSqlQueryModel model;

model.setQuery(QString("SELECT \"Name\" FROM \"TExaminee\" WHERE \"idGroup\" = (SELECT \"id\" FROM \"TGroup\" WHERE \"Name\" = '%1')").arg(group), db);

if(!model.rowCount())

{

QMessageBox::information(NULL, "Error",

QString("Can't find any students in group %1").arg(group));

}

for (int i = 0; i < model.rowCount(); i++)

{

students.append(model.record(i).value("Name").toString());

}

return students;

}

QString DBAccess::FindId(QString Code)

{

QSqlQuery query;

QSqlQueryModel model;

model.setQuery(QString("SELECT \"id\" FROM \"TExaminee\" WHERE \"Code\" = '%1'").arg(Code), db);

if(!model.rowCount())

{

QMessageBox::critical(0, "Database Error", db.lastError().text());

}

return model.record(0).value(0).toString();

}

bool DBAccess::AddAnswer (int id, QString GroupName)

{

QSqlQueryModel model;

model.setQuery(QString("SELECT \"idSubject\", \"idTest\", \"idExaminator\" FROM \"TCurrentTest\" WHERE \"idGroup\" = (SELECT \"id\" FROM \"TGroup\" WHERE \"Name\" = '%1')").arg(GroupName), db);

if(!model.rowCount())

{

QMessageBox::critical(0, "Database Error", db.lastError().text());

}

int idSubject = model.record(0).value(0).toInt();

idTest = model.record(0).value(1).toInt();

int idExaminator = model.record(0).value(2).toInt();

QSqlQuery query;

query.prepare(QString("INSERT INTO \"TPassedTest\" (\"idExaminee\", \"idSubject\", \"idTest\", \"idExaminator\", \"Date\") VALUES (%1, %2 ,%3, %4, %5::abstime)").arg(id).arg(idSubject).arg(idTest).arg(idExaminator).arg( QDateTime::currentDateTime().toTime_t()));

if(!query.exec())

{

QMessageBox::critical(0, "Database Error", db.lastError().text());

return false;

}

return true;

}

void DBAccess::GetQuestions ()

{

QSqlQueryModel model;

model.setQuery(QString("SELECT \"Content\" FROM \"TQuestion\" WHERE \"idTest\" = '%1'").arg(idTest), db);

if(!model.rowCount())

{

QMessageBox::critical(0, "Database Error", db.lastError().text());

}

for (int i = 0; i < model.rowCount(); i++)

{

questions.AddFromXML(model.record(i).value("Content").toString().toUtf8());

}

}

void DBAccess::ShowQuestions(QTextBrowser *outQuestion, QGridLayout *outAnswer)

{

if (!questions.Questions.isEmpty())

questions.Questions[QuestionNumber].Display(outQuestion, outAnswer);

}

void DBAccess::ShowPrevQuestion (QTextBrowser *outQuestion, QGridLayout *outAnswer)

{

QuestionNumber = qMax(0, QuestionNumber - 1);

ShowQuestions(outQuestion, outAnswer);

}

void DBAccess::ShowNextQuestion (QTextBrowser *outQuestion, QGridLayout *outAnswer)

{

QuestionNumber = qMin(questions.Questions.size() - 1, QuestionNumber + 1);

ShowQuestions(outQuestion, outAnswer);

}

«Question.h»:

#pragma once

#include <QString>

#include <QPair>

#include <QPixmap>

#include <QTextBrowser>

#include <QLayout>

struct HTMLWithPictures

{

QString Content;

class CPicture

{

public:

QString Name;

QPixmap Pixmap;

QString tmpPath;

QString tmpName;

~CPicture();

void UnpackPictures();

};

QVector<CPicture> Pictures;

};

struct CQuestion : public HTMLWithPictures

{

int MaxScore;

QString AnswerType;

struct

{

QVector<HTMLWithPictures> Cases;

QString Manual;

// Enum??

} Answer;

void Display( QTextBrowser *outQuestion, QGridLayout *outAnswer );

};

class CQuestions

{

public:

void LoadFromXML( CQuestion &out, QByteArray xml );

void SaveToXML();

QByteArray OpenFromFile(QString path);

void AddFromXML (QByteArray xml)

{

Questions.resize(Questions.size() + 1);

LoadFromXML(Questions.last(), xml);

};

QVector<CQuestion> Questions;

};

«Question.cpp»:

#include "Question.h"

#include <QDomDocument>

#include <QFile>

#include <QMessageBox>

#include <QLabel>

#include <QRadioButton>

void CQuestions::SaveToXML()

{

/*

QDomDocument doc("QuestionXML");

QDomElement question = doc.createElement("Question");

question.setAttribute("Number", Number);

question.setAttribute("MaxScore", MaxScore);

doc.appendChild(question);

QDomElement tag = doc.createElement("Content");

question.appendChild(tag);

QDomText cont = doc.createTextNode(Content);

tag.appendChild(cont);

QString xml = doc.toString();

QFile out("out.xml");

out.open(QIODevice::WriteOnly);

out.write(xml.toAscii());

*/

}

QByteArray CQuestions::OpenFromFile(QString path)

{

QFile file(path);

if (file.open(QIODevice::ReadOnly))

return file.read(file.size());

return QByteArray();

}

void CQuestions::LoadFromXML( CQuestion &out, QByteArray xml )

{

QDomDocument doc("Question");

doc.setContent(xml);

// "element" is xml's root

QDomElement element = doc.documentElement();

// Loop for every child in "element"

for(QDomNode node1 = element.firstChild(); !node1.isNull(); node1 = node1.nextSibling())

{

QString nodeName = node1.nodeName();

if (nodeName == "Content")

{

// Question's content in HTML:

out.Content = node1.firstChild().toCDATASection().data();

}

else if (nodeName == "Data")

{

// Getting all data entries. So far only pictures are supported

for(QDomNode node2 = node1.firstChild(); !node2.isNull(); node2 = node2.nextSibling())

{

// Picture's filename

QString picName = node2.attributes().namedItem("name").firstChild().toText().data();

// Picture's base64 data -> byte array -> pixmap

QString picData = node2.firstChild().toText().data().trimmed();

QByteArray pixmapData = QByteArray::fromBase64(picData.toAscii());

QPixmap pixmap;

pixmap.loadFromData((uchar *)pixmapData.constData(), pixmapData.size());

if (!picName.isEmpty() && !pixmap.isNull())

{

out.Pictures.resize(out.Pictures.size() + 1);

out.Pictures.last().Name = picName;

out.Pictures.last().Pixmap = pixmap;

}

}

}

else if (nodeName == "Answers")

{

// Answer's type

out.AnswerType = node1.attributes().namedItem("type").firstChild().toText().data();

if (out.AnswerType == "Case")

{

int answerNum = 1;

for(QDomNode node2 = node1.firstChild(); !node2.isNull(); node2 = node2.nextSibling(), answerNum++)

{

//answerNum;

out.MaxScore = node2.attributes().namedItem("score").toText().data().toInt();

for(QDomNode node3 = node2.firstChild(); !node3.isNull(); node3 = node3.nextSibling())

{

if (node3.nodeName() == "Content")

{

out.Answer.Cases.resize(out.Answer.Cases.size() + 1);

// Answer's content in HTML:

out.Answer.Cases.last().Content = node3.firstChild().toCDATASection().data();

}

else if (node3.nodeName() == "Data")

{

for(QDomNode node4 = node3.firstChild(); !node4.isNull(); node4 = node4.nextSibling())

{

// Picture's filename

QString picName = node2.attributes().namedItem("name").firstChild().toText().data();

// Picture's base64 data -> byte array -> pixmap

QString picData = node4.firstChild().toText().data().trimmed();

QByteArray pixmapData = QByteArray::fromBase64(picData.toAscii());

QPixmap pixmap;

pixmap.loadFromData((uchar *)pixmapData.constData(), pixmapData.size());

out.Answer.Cases.last().Pictures.resize(out.Answer.Cases.last().Pictures.size() + 1);

out.Answer.Cases.last().Pictures.last().Name = picName;

out.Answer.Cases.last().Pictures.last().Pixmap = pixmap;

}

}

}

}

} // </Case>

else if (out.AnswerType == "Manual")

{

}

}

}

}

#include <QDir>

#include <QTemporaryFile>

void CQuestion::Display( QTextBrowser *outQuestion, QGridLayout *outAnswer )

{

// Setting question

QStringList searchPath;

for (int i = 0; i < Pictures.size(); i++)

{

Pictures[i].UnpackPictures();

searchPath << Pictures[i].tmpPath;

}

outQuestion->setSearchPaths(searchPath);

outQuestion->setText(Content);

// Clearing answer

QLayoutItem *li;

while (li = outAnswer->takeAt(0))

{

if (QWidget *w = li->widget())

delete w;

else if (QLayout *l = li->layout())

delete l;

delete li;

}

// Setting answer

if (AnswerType == "Case")

{

for (int i = 0, c = 0, r = 0; i < Answer.Cases.size(); i++)

{

QHBoxLayout *layout = new QHBoxLayout(outQuestion);

layout->setSpacing(0);

QRadioButton *rBtn = new QRadioButton(outQuestion);

layout->addWidget(rBtn);

QTextBrowser *tb = new QTextBrowser(outQuestion);

tb->setText(Answer.Cases[i].Content);

tb->setMinimumHeight(30);

layout->addWidget(tb);

outAnswer->addLayout(layout, r, c);

//outAnswer->addWidget(tb, r, c);

if (i & 1)

{

r = 0;

c++;

}

else

r++;

}

}

else if (AnswerType == "Manual")

{

QTextBrowser *tb = new QTextBrowser(outQuestion);

tb->setText(Answer.Manual);

outAnswer->addWidget(tb, 0, 0);

}

}

HTMLWithPictures::CPicture::~CPicture()

{

if (!tmpName.isEmpty())

QFile::remove(tmpName);

if (!tmpPath.isEmpty())

QDir::temp().rmdir(tmpPath);

}

void HTMLWithPictures::CPicture::UnpackPictures()

{

{

QTemporaryFile file;

file.open();

tmpPath = file.fileName();

}

QDir::temp().mkdir(tmpPath);

tmpName = QString("%1/%2").arg(tmpPath).arg(Name);

Pixmap.save(tmpName);

}

«ts_examinee.h»:

#ifndef TS_EXAMINEE_H

#define TS_EXAMINEE_H

#include <QtGui/QMainWindow>

#include "ui_ts_examinee.h"

#include "../TS_Lecturer/Question.h"

#include "DBAccess.h"

class TS_Examinee : public QMainWindow

{

Q_OBJECT

public:

TS_Examinee(QWidget *parent = 0, Qt::WFlags flags = 0);

~TS_Examinee();

private:

Ui::TS_ExamineeClass ui;

/*CQuestions questions;*/

DBAccess db;

private slots:

void on_forwardPushButton_clicked();

void on_backPushButton_clicked();

};

#endif // TS_EXAMINEE_H

«ts_examinee.срр»:

#include "ts_examinee.h"

#include "DBAccess.h"

#include "LoginDialog.h"

#include <QGridLayout>

TS_Examinee::TS_Examinee(QWidget *parent, Qt::WFlags flags)

: QMainWindow(parent, flags)

{

ui.setupUi(this);

db.Connect("localhost", "db_TestingSystem", "postgres", "1q2w3e");

LoginDialog loginDialog;

loginDialog.exec(&db);

db.GetQuestions();

db.ShowQuestions(ui.questionTextBrowser, ui.AnswerGridLayout);

}

TS_Examinee::~TS_Examinee()

{

}

void TS_Examinee::on_backPushButton_clicked()

{

db.ShowPrevQuestion(ui.questionTextBrowser, ui.AnswerGridLayout);

}

void TS_Examinee::on_forwardPushButton_clicked()

{

db.ShowNextQuestion(ui.questionTextBrowser, ui.AnswerGridLayout);

}

«main.cpp»:

#include <QtGui/QApplication>

#include "ts_examinee.h"

int main(int argc, char *argv[])

{

QApplication a(argc, argv);

TS_Examinee w;

w.show();

return a.exec();

}