31 #include "templates/quiz/quizeditor.h"
33 #include "miscellaneous/iconfactory.h"
34 #include "templates/quiz/quizquestion.h"
35 #include "core/templatefactory.h"
36 #include "core/templatecore.h"
37 #include "core/templateentrypoint.h"
42 #include <QDomDocument>
43 #include <QDomElement>
47 QuizEditor::QuizEditor(
TemplateCore *core, QWidget *parent)
52 QRegExpValidator *author_validator =
new QRegExpValidator(
this);
53 QRegExpValidator *title_validator =
new QRegExpValidator(
this);
54 QRegExpValidator *option_validator =
new QRegExpValidator(
this);
56 author_validator->setRegExp(QRegExp(
".{,50}"));
57 title_validator->setRegExp(QRegExp(
".{,100}"));
58 option_validator->setRegExp(QRegExp(
".{,60}"));
60 m_ui->m_txtAuthor->lineEdit()->setValidator(author_validator);
61 m_ui->m_txtName->lineEdit()->setValidator(title_validator);
62 m_ui->m_txtAnswerOne->setValidator(option_validator);
63 m_ui->m_txtAnswerTwo->setValidator(option_validator);
64 m_ui->m_txtAnswerThree->setValidator(option_validator);
65 m_ui->m_txtAnswerFour->setValidator(option_validator);
66 m_ui->m_txtQuestion->setMaxLength(160);
69 QList<QWidget*> tab_order_widgets;
70 tab_order_widgets << m_ui->m_txtQuestion << m_ui->m_btnAnswerOne << m_ui->m_txtAnswerOne <<
71 m_ui->m_btnAnswerTwo << m_ui->m_txtAnswerTwo <<
72 m_ui->m_btnAnswerThree << m_ui->m_txtAnswerThree <<
73 m_ui->m_btnAnswerFour << m_ui->m_txtAnswerFour <<
74 m_ui->m_txtAuthor->lineEdit() << m_ui->m_txtName->lineEdit() <<
75 m_ui->m_listQuestions << m_ui->m_btnQuestionAdd << m_ui->m_btnQuestionRemove <<
76 m_ui->m_btnQuestionUp << m_ui->m_btnQuestionDown;
78 for (
int i = 1; i < tab_order_widgets.size(); i++) {
79 setTabOrder(tab_order_widgets.at(i - 1), tab_order_widgets.at(i));
82 m_ui->m_txtNumberOfQuestions->lineEdit()->setEnabled(
false);
86 m_ui->m_txtAuthor->lineEdit()->setPlaceholderText(tr(
"Author of this quiz"));
87 m_ui->m_txtName->lineEdit()->setPlaceholderText(tr(
"Name of this quiz"));
89 m_ui->m_btnAnswerOne->setProperty(
"id", 0);
90 m_ui->m_btnAnswerTwo->setProperty(
"id", 1);
91 m_ui->m_btnAnswerThree->setProperty(
"id", 2);
92 m_ui->m_btnAnswerFour->setProperty(
"id", 3);
94 m_ui->m_btnQuestionAdd->setIcon(factory->
fromTheme(
"item-add"));
95 m_ui->m_btnQuestionRemove->setIcon(factory->
fromTheme(
"item-remove"));
96 m_ui->m_btnQuestionUp->setIcon(factory->
fromTheme(
"move-up"));
97 m_ui->m_btnQuestionDown->setIcon(factory->
fromTheme(
"move-down"));
99 m_iconNo = factory->
fromTheme(
"dialog-no");
100 m_iconYes = factory->
fromTheme(
"dialog-yes");
102 m_ui->m_btnAnswerOne->setIcon(m_iconNo);
103 m_ui->m_btnAnswerTwo->setIcon(m_iconNo);
104 m_ui->m_btnAnswerThree->setIcon(m_iconNo);
105 m_ui->m_btnAnswerFour->setIcon(m_iconNo);
107 connect(m_ui->m_txtAuthor->lineEdit(), SIGNAL(textChanged(QString)),
this, SLOT(updateAuthorStatus()));
108 connect(m_ui->m_txtName->lineEdit(), SIGNAL(textChanged(QString)),
this, SLOT(updateNameStatus()));
110 connect(m_ui->m_btnQuestionAdd, SIGNAL(clicked()),
this, SLOT(addQuestion()));
111 connect(m_ui->m_btnQuestionRemove, SIGNAL(clicked()),
this, SLOT(removeQuestion()));
112 connect(m_ui->m_listQuestions, SIGNAL(currentRowChanged(
int)),
this, SLOT(loadQuestion(
int)));
114 connect(m_ui->m_btnAnswerOne, SIGNAL(clicked()),
this, SLOT(saveQuestion()));
115 connect(m_ui->m_btnAnswerTwo, SIGNAL(clicked()),
this, SLOT(saveQuestion()));
116 connect(m_ui->m_btnAnswerThree, SIGNAL(clicked()),
this, SLOT(saveQuestion()));
117 connect(m_ui->m_btnAnswerFour, SIGNAL(clicked()),
this, SLOT(saveQuestion()));
119 connect(m_ui->m_txtAnswerOne, SIGNAL(textEdited(QString)),
this, SLOT(saveQuestion()));
120 connect(m_ui->m_txtAnswerTwo, SIGNAL(textEdited(QString)),
this, SLOT(saveQuestion()));
121 connect(m_ui->m_txtAnswerThree, SIGNAL(textEdited(QString)),
this, SLOT(saveQuestion()));
122 connect(m_ui->m_txtAnswerFour, SIGNAL(textEdited(QString)),
this, SLOT(saveQuestion()));
123 connect(m_ui->m_txtQuestion, SIGNAL(textChanged()),
this, SLOT(saveQuestion()));
125 connect(m_ui->m_btnQuestionUp, SIGNAL(clicked()),
this, SLOT(moveQuestionUp()));
126 connect(m_ui->m_btnQuestionDown, SIGNAL(clicked()),
this, SLOT(moveQuestionDown()));
128 setEditorsEnabled(
false);
129 updateQuestionCount();
132 qRegisterMetaType<QuizQuestion>(
"QuizQuestion");
135 QuizEditor::~QuizEditor() {
136 qDebug(
"Destroying QuizEditor instance.");
142 QList<QuizQuestion> questions;
144 for (
int i = 0; i < m_ui->m_listQuestions->count(); i++) {
145 questions.append(m_ui->m_listQuestions->item(i)->data(Qt::UserRole).value<
QuizQuestion>());
152 return m_ui->m_txtName->lineEdit()->text();
156 return m_ui->m_txtAuthor->lineEdit()->text();
159 void QuizEditor::updateQuestionCount() {
160 m_ui->m_txtNumberOfQuestions->lineEdit()->setText(QString::number(m_ui->m_listQuestions->count()));
162 if (m_ui->m_listQuestions->count() > 0) {
163 m_ui->m_txtNumberOfQuestions->setStatus(WidgetWithStatus::Ok, tr(
"Quiz contains at least one question."));
166 m_ui->m_txtNumberOfQuestions->setStatus(WidgetWithStatus::Error, tr(
"Quiz does not contain any questions."));
170 void QuizEditor::addQuestion(
const QString &question,
const QStringList &answers,
int correct_answer) {
173 new_question.setQuestion(question);
174 new_question.setCorrectAnswer(correct_answer);
176 int answer_index = 0;
177 foreach (
const QString &answer, answers) {
178 new_question.setAnswer(answer_index++, answer);
181 int marked_question = m_ui->m_listQuestions->currentRow();
182 QListWidgetItem *new_item =
new QListWidgetItem();
183 new_item->setText(new_question.question());
184 new_item->setData(Qt::UserRole, QVariant::fromValue(new_question));
186 if (m_ui->m_listQuestions->count() == 0) {
188 setEditorsEnabled(
true);
190 m_ui->m_btnQuestionRemove->setEnabled(
true);
192 m_ui->m_listQuestions->insertItem(0, new_item);
193 m_ui->m_listQuestions->setCurrentRow(0);
196 m_ui->m_listQuestions->insertItem(marked_question + 1, new_item);
197 m_ui->m_listQuestions->setCurrentRow(marked_question + 1);
200 updateQuestionCount();
203 void QuizEditor::addQuestion() {
204 addQuestion(tr(
"How many cats do you have?"),
205 QStringList() << tr(
"I hate cats!") << tr(
"I have two nice kittens.") <<
206 tr(
"I have seven beasts.") << tr(
"Cats? Well, we own eleven dogs."),
213 void QuizEditor::loadQuestion(
int index) {
214 m_ui->m_txtQuestion->blockSignals(
true);
215 m_ui->m_txtAnswerOne->blockSignals(
true);
216 m_ui->m_txtAnswerTwo->blockSignals(
true);
217 m_ui->m_txtAnswerThree->blockSignals(
true);
218 m_ui->m_txtAnswerFour->blockSignals(
true);
219 m_ui->m_btnAnswerOne->blockSignals(
true);
220 m_ui->m_btnAnswerTwo->blockSignals(
true);
221 m_ui->m_btnAnswerThree->blockSignals(
true);
222 m_ui->m_btnAnswerFour->blockSignals(
true);
227 m_ui->m_txtQuestion->setText(question.question());
228 m_ui->m_txtAnswerOne->setText(question.answerOne());
229 m_ui->m_txtAnswerTwo->setText(question.answerTwo());
230 m_ui->m_txtAnswerThree->setText(question.answerThree());
231 m_ui->m_txtAnswerFour->setText(question.answerFour());
232 m_ui->m_btnAnswerOne->setIcon(question.
correctAnswer() == 0 ? m_iconYes : m_iconNo);
233 m_ui->m_btnAnswerTwo->setIcon(question.
correctAnswer() == 1 ? m_iconYes : m_iconNo);
234 m_ui->m_btnAnswerThree->setIcon(question.
correctAnswer() == 2 ? m_iconYes : m_iconNo);
235 m_ui->m_btnAnswerFour->setIcon(question.
correctAnswer() == 3 ? m_iconYes : m_iconNo);
237 m_activeQuestion = question;
240 m_ui->m_txtQuestion->setText(QString());
241 m_ui->m_txtAnswerOne->setText(QString());
242 m_ui->m_txtAnswerTwo->setText(QString());
243 m_ui->m_txtAnswerThree->setText(QString());
244 m_ui->m_txtAnswerFour->setText(QString());
245 m_ui->m_btnAnswerOne->setIcon(m_iconNo);
246 m_ui->m_btnAnswerTwo->setIcon(m_iconNo);
247 m_ui->m_btnAnswerThree->setIcon(m_iconNo);
248 m_ui->m_btnAnswerFour->setIcon(m_iconNo);
251 m_ui->m_txtQuestion->blockSignals(
false);
252 m_ui->m_txtAnswerOne->blockSignals(
false);
253 m_ui->m_txtAnswerTwo->blockSignals(
false);
254 m_ui->m_txtAnswerThree->blockSignals(
false);
255 m_ui->m_txtAnswerFour->blockSignals(
false);
256 m_ui->m_btnAnswerOne->blockSignals(
false);
257 m_ui->m_btnAnswerTwo->blockSignals(
false);
258 m_ui->m_btnAnswerThree->blockSignals(
false);
259 m_ui->m_btnAnswerFour->blockSignals(
false);
261 QTimer::singleShot(0,
this, SLOT(configureUpDown()));
264 void QuizEditor::removeQuestion() {
265 int current_row = m_ui->m_listQuestions->currentRow();
267 if (current_row >= 0) {
268 if (m_ui->m_listQuestions->count() == 1) {
270 setEditorsEnabled(
false);
272 m_ui->m_btnQuestionRemove->setEnabled(
false);
275 delete m_ui->m_listQuestions->takeItem(current_row);
278 updateQuestionCount();
283 void QuizEditor::saveQuestion() {
286 if (button_sender != NULL) {
288 m_activeQuestion.setCorrectAnswer(button_sender->property(
"id").toInt());
293 m_ui->m_btnAnswerOne->setIcon(m_iconYes);
294 m_ui->m_btnAnswerTwo->setIcon(m_iconNo);
295 m_ui->m_btnAnswerThree->setIcon(m_iconNo);
296 m_ui->m_btnAnswerFour->setIcon(m_iconNo);
300 m_ui->m_btnAnswerOne->setIcon(m_iconNo);
301 m_ui->m_btnAnswerTwo->setIcon(m_iconYes);
302 m_ui->m_btnAnswerThree->setIcon(m_iconNo);
303 m_ui->m_btnAnswerFour->setIcon(m_iconNo);
307 m_ui->m_btnAnswerOne->setIcon(m_iconNo);
308 m_ui->m_btnAnswerTwo->setIcon(m_iconNo);
309 m_ui->m_btnAnswerThree->setIcon(m_iconYes);
310 m_ui->m_btnAnswerFour->setIcon(m_iconNo);
314 m_ui->m_btnAnswerOne->setIcon(m_iconNo);
315 m_ui->m_btnAnswerTwo->setIcon(m_iconNo);
316 m_ui->m_btnAnswerThree->setIcon(m_iconNo);
317 m_ui->m_btnAnswerFour->setIcon(m_iconYes);
321 m_ui->m_btnAnswerOne->setIcon(m_iconNo);
322 m_ui->m_btnAnswerTwo->setIcon(m_iconNo);
323 m_ui->m_btnAnswerThree->setIcon(m_iconNo);
324 m_ui->m_btnAnswerFour->setIcon(m_iconNo);
329 m_activeQuestion.setQuestion(m_ui->m_txtQuestion->toPlainText());
330 m_activeQuestion.setAnswer(0, m_ui->m_txtAnswerOne->text());
331 m_activeQuestion.setAnswer(1, m_ui->m_txtAnswerTwo->text());
332 m_activeQuestion.setAnswer(2, m_ui->m_txtAnswerThree->text());
333 m_activeQuestion.setAnswer(3, m_ui->m_txtAnswerFour->text());
335 m_ui->m_listQuestions->currentItem()->setData(Qt::UserRole, QVariant::fromValue(m_activeQuestion));
336 m_ui->m_listQuestions->currentItem()->setText(m_activeQuestion.question());
341 void QuizEditor::moveQuestionUp() {
342 int index = m_ui->m_listQuestions->currentRow();
344 m_ui->m_listQuestions->insertItem(index - 1, m_ui->m_listQuestions->takeItem(index));
345 m_ui->m_listQuestions->setCurrentRow(index - 1);
350 void QuizEditor::moveQuestionDown() {
351 int index = m_ui->m_listQuestions->currentRow();
353 m_ui->m_listQuestions->insertItem(index + 1, m_ui->m_listQuestions->takeItem(index));
354 m_ui->m_listQuestions->setCurrentRow(index + 1);
359 void QuizEditor::configureUpDown() {
360 if (m_ui->m_listQuestions->count() > 1) {
361 int index = m_ui->m_listQuestions->currentRow();
364 m_ui->m_btnQuestionUp->setEnabled(
false);
365 m_ui->m_btnQuestionDown->setEnabled(
true);
367 else if (index == m_ui->m_listQuestions->count() - 1) {
368 m_ui->m_btnQuestionUp->setEnabled(
true);
369 m_ui->m_btnQuestionDown->setEnabled(
false);
372 m_ui->m_btnQuestionUp->setEnabled(
true);
373 m_ui->m_btnQuestionDown->setEnabled(
true);
377 m_ui->m_btnQuestionUp->setEnabled(
false);
378 m_ui->m_btnQuestionDown->setEnabled(
false);
382 void QuizEditor::setEditorsEnabled(
bool enabled) {
383 m_ui->m_groupQuestionEditor->setEnabled(enabled);
386 void QuizEditor::checkName() {
387 if (m_ui->m_txtName->lineEdit()->text().simplified().isEmpty()) {
388 m_ui->m_txtName->setStatus(WidgetWithStatus::Error, tr(
"Enter the name of the quiz."));
391 m_ui->m_txtName->setStatus(WidgetWithStatus::Ok, tr(
"Name is okay."));
395 void QuizEditor::checkAuthor() {
396 if (m_ui->m_txtAuthor->lineEdit()->text().simplified().isEmpty()) {
397 m_ui->m_txtAuthor->setStatus(WidgetWithStatus::Error, tr(
"Enter the name of the author of the quiz."));
400 m_ui->m_txtAuthor->setStatus(WidgetWithStatus::Ok, tr(
"Enter the name of the author of the quiz."));
404 void QuizEditor::updateNameStatus() {
410 void QuizEditor::updateAuthorStatus() {
418 !m_ui->m_txtName->lineEdit()->text().simplified().isEmpty() &&
419 !m_ui->m_txtAuthor->lineEdit()->text().simplified().isEmpty() &&
424 QDomDocument bundle_document;
425 bundle_document.setContent(bundle_data);
427 QDomNodeList items = bundle_document.documentElement().elementsByTagName(
"item");
429 for (
int i = 0; i < items.size(); i++) {
430 QDomNode item = items.at(i);
432 if (item.isElement()) {
433 QString question = item.namedItem(
"question").toElement().text();
434 int correct_answer = item.namedItem(
"answer").toElement().text().toInt();
435 QDomNodeList answer_items = item.toElement().elementsByTagName(
"option");
436 QList<QString> answers;
438 for (
int j = 0; j < answer_items.size(); j++) {
439 answers.append(answer_items.at(j).toElement().text());
442 if (question.isEmpty() || answers.size() < 2 || answers.size() > 4) {
447 addQuestion(question, answers, correct_answer);
456 m_ui->m_txtAuthor->lineEdit()->setText(bundle_document.documentElement().namedItem(
"author").namedItem(
"name").toElement().text());
457 m_ui->m_txtName->lineEdit()->setText(bundle_document.documentElement().namedItem(
"title").toElement().text());
467 QDomDocument source_document = qApp->templateManager()->generateBundleHeader(
core()->entryPoint()->typeIndentifier(),
468 m_ui->m_txtAuthor->lineEdit()->text(),
470 m_ui->m_txtName->lineEdit()->text(),
473 FIND_DATA_ELEMENT(data_element, source_document);
476 QDomElement item_element = source_document.createElement(
"item");
479 QDomElement question_element = source_document.createElement(
"question");
480 QDomElement answer_one_element = source_document.createElement(
"option");
481 QDomElement answer_two_element = source_document.createElement(
"option");
482 QDomElement answer_three_element = source_document.createElement(
"option");
483 QDomElement answer_four_element = source_document.createElement(
"option");
484 QDomElement answer_number_element = source_document.createElement(
"answer");
486 question_element.appendChild(source_document.createTextNode(question.question()));
487 answer_one_element.appendChild(source_document.createTextNode(question.answerOne()));
488 answer_two_element.appendChild(source_document.createTextNode(question.answerTwo()));
489 answer_three_element.appendChild(source_document.createTextNode(question.answerThree()));
490 answer_four_element.appendChild(source_document.createTextNode(question.answerFour()));
491 answer_number_element.appendChild(source_document.createTextNode(QString::number(question.
correctAnswer())));
493 item_element.appendChild(question_element);
494 item_element.appendChild(answer_one_element);
495 item_element.appendChild(answer_two_element);
496 item_element.appendChild(answer_three_element);
497 item_element.appendChild(answer_four_element);
498 item_element.appendChild(answer_number_element);
500 data_element.appendChild(item_element);
503 return source_document.toString(XML_BUNDLE_INDENTATION);
QString projectName()
Access to project name of current editor.
bool canGenerateApplications()
Specifies if template can generate applications or not.
QString generateBundleData()
Generates RAW data which represent data of this template.
TemplateCore * core() const
Access to associated template core.
void changed()
Emitted everytime any child widget of editor changes its contents.
Represents the editor of the template.
QList< QuizQuestion > activeQuestions() const
Access to list of added questions.
Icon theme manipulator and provider.
bool loadBundleData(const QString &bundle_data)
Loads editor state from XML bundle.
int correctAnswer() const
Access to inde of correct answer.
The core class container for single template.
QString authorName()
Access to author name of current editor.
QIcon fromTheme(const QString &name)
Returns icon from active theme.
virtual void launch()
Executed when given template with this editor is launched.
static IconFactory * instance()
Singleton getter.
Container for one question.