BuildmLearn Toolkit  2.0.4
BuildmLearn Toolkit is an easy-to-use program that helps users make mobile apps without any knowledge of application development.
 All Classes Functions Enumerations Groups Pages
quizeditor.cpp
1 /*
2  Copyright (c) 2012, BuildmLearn Contributors listed at http://buildmlearn.org/people/
3  All rights reserved.
4 
5  Redistribution and use in source and binary forms, with or without
6  modification, are permitted provided that the following conditions are met:
7 
8  * Redistributions of source code must retain the above copyright notice, this
9  list of conditions and the following disclaimer.
10 
11  * Redistributions in binary form must reproduce the above copyright notice,
12  this list of conditions and the following disclaimer in the documentation
13  and/or other materials provided with the distribution.
14 
15  * Neither the name of the BuildmLearn nor the names of its
16  contributors may be used to endorse or promote products derived from
17  this software without specific prior written permission.
18 
19  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 
31 #include "templates/quiz/quizeditor.h"
32 
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"
38 
39 #include <QToolTip>
40 #include <QTimer>
41 #include <QShowEvent>
42 #include <QDomDocument>
43 #include <QDomElement>
44 #include <QDomAttr>
45 
46 
47 QuizEditor::QuizEditor(TemplateCore *core, QWidget *parent)
48  : TemplateEditor(core, parent), m_ui(new Ui::QuizEditor) {
49  m_ui->setupUi(this);
50 
51  // Set validators.
52  QRegExpValidator *author_validator = new QRegExpValidator(this);
53  QRegExpValidator *title_validator = new QRegExpValidator(this);
54  QRegExpValidator *option_validator = new QRegExpValidator(this);
55 
56  author_validator->setRegExp(QRegExp(".{,50}"));
57  title_validator->setRegExp(QRegExp(".{,100}"));
58  option_validator->setRegExp(QRegExp(".{,60}"));
59 
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);
67 
68  // Set tab order.
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;
77 
78  for (int i = 1; i < tab_order_widgets.size(); i++) {
79  setTabOrder(tab_order_widgets.at(i - 1), tab_order_widgets.at(i));
80  }
81 
82  m_ui->m_txtNumberOfQuestions->lineEdit()->setEnabled(false);
83 
85 
86  m_ui->m_txtAuthor->lineEdit()->setPlaceholderText(tr("Author of this quiz"));
87  m_ui->m_txtName->lineEdit()->setPlaceholderText(tr("Name of this quiz"));
88 
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);
93 
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"));
98 
99  m_iconNo = factory->fromTheme("dialog-no");
100  m_iconYes = factory->fromTheme("dialog-yes");
101 
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);
106 
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()));
109 
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)));
113 
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()));
118 
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()));
124 
125  connect(m_ui->m_btnQuestionUp, SIGNAL(clicked()), this, SLOT(moveQuestionUp()));
126  connect(m_ui->m_btnQuestionDown, SIGNAL(clicked()), this, SLOT(moveQuestionDown()));
127 
128  setEditorsEnabled(false);
129  updateQuestionCount();
130  checkName();
131  checkAuthor();
132  qRegisterMetaType<QuizQuestion>("QuizQuestion");
133 }
134 
135 QuizEditor::~QuizEditor() {
136  qDebug("Destroying QuizEditor instance.");
137 
138  delete m_ui;
139 }
140 
141 QList<QuizQuestion> QuizEditor::activeQuestions() const {
142  QList<QuizQuestion> questions;
143 
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>());
146  }
147 
148  return questions;
149 }
150 
152  return m_ui->m_txtName->lineEdit()->text();
153 }
154 
156  return m_ui->m_txtAuthor->lineEdit()->text();
157 }
158 
159 void QuizEditor::updateQuestionCount() {
160  m_ui->m_txtNumberOfQuestions->lineEdit()->setText(QString::number(m_ui->m_listQuestions->count()));
161 
162  if (m_ui->m_listQuestions->count() > 0) {
163  m_ui->m_txtNumberOfQuestions->setStatus(WidgetWithStatus::Ok, tr("Quiz contains at least one question."));
164  }
165  else {
166  m_ui->m_txtNumberOfQuestions->setStatus(WidgetWithStatus::Error, tr("Quiz does not contain any questions."));
167  }
168 }
169 
170 void QuizEditor::addQuestion(const QString &question, const QStringList &answers, int correct_answer) {
171  QuizQuestion new_question;
172 
173  new_question.setQuestion(question);
174  new_question.setCorrectAnswer(correct_answer);
175 
176  int answer_index = 0;
177  foreach (const QString &answer, answers) {
178  new_question.setAnswer(answer_index++, answer);
179  }
180 
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));
185 
186  if (m_ui->m_listQuestions->count() == 0) {
187  // We are adding first question.
188  setEditorsEnabled(true);
189 
190  m_ui->m_btnQuestionRemove->setEnabled(true);
191 
192  m_ui->m_listQuestions->insertItem(0, new_item);
193  m_ui->m_listQuestions->setCurrentRow(0);
194  }
195  else {
196  m_ui->m_listQuestions->insertItem(marked_question + 1, new_item);
197  m_ui->m_listQuestions->setCurrentRow(marked_question + 1);
198  }
199 
200  updateQuestionCount();
201 }
202 
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."),
207  2);
208 
209  launch();
210  emit changed();
211 }
212 
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);
223 
224  if (index >= 0) {
225  QuizQuestion question = m_ui->m_listQuestions->item(index)->data(Qt::UserRole).value<QuizQuestion>();
226 
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);
236 
237  m_activeQuestion = question;
238  }
239  else {
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);
249  }
250 
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);
260 
261  QTimer::singleShot(0, this, SLOT(configureUpDown()));
262 }
263 
264 void QuizEditor::removeQuestion() {
265  int current_row = m_ui->m_listQuestions->currentRow();
266 
267  if (current_row >= 0) {
268  if (m_ui->m_listQuestions->count() == 1) {
269  // We are removing last visible question.
270  setEditorsEnabled(false);
271 
272  m_ui->m_btnQuestionRemove->setEnabled(false);
273  }
274 
275  delete m_ui->m_listQuestions->takeItem(current_row);
276  }
277 
278  updateQuestionCount();
279  launch();
280  emit changed();
281 }
282 
283 void QuizEditor::saveQuestion() {
284  PlainToolButton *button_sender = dynamic_cast<PlainToolButton*>(sender());
285 
286  if (button_sender != NULL) {
287  // User clicked some of the "answer" buttons.
288  m_activeQuestion.setCorrectAnswer(button_sender->property("id").toInt());
289 
290  // Change icons.
291  switch (m_activeQuestion.correctAnswer()) {
292  case 0:
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);
297  break;
298 
299  case 1:
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);
304  break;
305 
306  case 2:
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);
311  break;
312 
313  case 3:
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);
318  break;
319 
320  default:
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);
325  break;
326  }
327  }
328 
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());
334 
335  m_ui->m_listQuestions->currentItem()->setData(Qt::UserRole, QVariant::fromValue(m_activeQuestion));
336  m_ui->m_listQuestions->currentItem()->setText(m_activeQuestion.question());
337 
338  emit changed();
339 }
340 
341 void QuizEditor::moveQuestionUp() {
342  int index = m_ui->m_listQuestions->currentRow();
343 
344  m_ui->m_listQuestions->insertItem(index - 1, m_ui->m_listQuestions->takeItem(index));
345  m_ui->m_listQuestions->setCurrentRow(index - 1);
346 
347  emit changed();
348 }
349 
350 void QuizEditor::moveQuestionDown() {
351  int index = m_ui->m_listQuestions->currentRow();
352 
353  m_ui->m_listQuestions->insertItem(index + 1, m_ui->m_listQuestions->takeItem(index));
354  m_ui->m_listQuestions->setCurrentRow(index + 1);
355 
356  emit changed();
357 }
358 
359 void QuizEditor::configureUpDown() {
360  if (m_ui->m_listQuestions->count() > 1) {
361  int index = m_ui->m_listQuestions->currentRow();
362 
363  if (index == 0) {
364  m_ui->m_btnQuestionUp->setEnabled(false);
365  m_ui->m_btnQuestionDown->setEnabled(true);
366  }
367  else if (index == m_ui->m_listQuestions->count() - 1) {
368  m_ui->m_btnQuestionUp->setEnabled(true);
369  m_ui->m_btnQuestionDown->setEnabled(false);
370  }
371  else {
372  m_ui->m_btnQuestionUp->setEnabled(true);
373  m_ui->m_btnQuestionDown->setEnabled(true);
374  }
375  }
376  else {
377  m_ui->m_btnQuestionUp->setEnabled(false);
378  m_ui->m_btnQuestionDown->setEnabled(false);
379  }
380 }
381 
382 void QuizEditor::setEditorsEnabled(bool enabled) {
383  m_ui->m_groupQuestionEditor->setEnabled(enabled);
384 }
385 
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."));
389  }
390  else {
391  m_ui->m_txtName->setStatus(WidgetWithStatus::Ok, tr("Name is okay."));
392  }
393 }
394 
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."));
398  }
399  else {
400  m_ui->m_txtAuthor->setStatus(WidgetWithStatus::Ok, tr("Enter the name of the author of the quiz."));
401  }
402 }
403 
404 void QuizEditor::updateNameStatus() {
405  checkName();
406  launch();
407  emit changed();
408 }
409 
410 void QuizEditor::updateAuthorStatus() {
411  checkAuthor();
412  launch();
413  emit changed();
414 }
415 
417  return
418  !m_ui->m_txtName->lineEdit()->text().simplified().isEmpty() &&
419  !m_ui->m_txtAuthor->lineEdit()->text().simplified().isEmpty() &&
420  !activeQuestions().isEmpty();
421 }
422 
423 bool QuizEditor::loadBundleData(const QString &bundle_data) {
424  QDomDocument bundle_document;
425  bundle_document.setContent(bundle_data);
426 
427  QDomNodeList items = bundle_document.documentElement().elementsByTagName("item");
428 
429  for (int i = 0; i < items.size(); i++) {
430  QDomNode item = items.at(i);
431 
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;
437 
438  for (int j = 0; j < answer_items.size(); j++) {
439  answers.append(answer_items.at(j).toElement().text());
440  }
441 
442  if (question.isEmpty() || answers.size() < 2 || answers.size() > 4) {
443  // TODO: error
444  continue;
445  }
446  else {
447  addQuestion(question, answers, correct_answer);
448  }
449  }
450  else {
451  continue;
452  }
453  }
454 
455  // Load author & name.
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());
458 
459  return true;
460 }
461 
463  /*if (!canGenerateApplications()) {
464  return QString();
465  }*/
466 
467  QDomDocument source_document = qApp->templateManager()->generateBundleHeader(core()->entryPoint()->typeIndentifier(),
468  m_ui->m_txtAuthor->lineEdit()->text(),
469  QString(),
470  m_ui->m_txtName->lineEdit()->text(),
471  QString(),
472  "1");
473  FIND_DATA_ELEMENT(data_element, source_document);
474 
475  foreach (const QuizQuestion &question, activeQuestions()) {
476  QDomElement item_element = source_document.createElement("item");
477 
478  // Fill in details about question.
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");
485 
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())));
492 
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);
499 
500  data_element.appendChild(item_element);
501  }
502 
503  return source_document.toString(XML_BUNDLE_INDENTATION);
504 }
Editor for Quiz.
Definition: quizeditor.h:51
QString projectName()
Access to project name of current editor.
Definition: quizeditor.cpp:151
bool canGenerateApplications()
Specifies if template can generate applications or not.
Definition: quizeditor.cpp:416
QString generateBundleData()
Generates RAW data which represent data of this template.
Definition: quizeditor.cpp:462
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.
Definition: quizeditor.cpp:141
Tool button without frame.
Icon theme manipulator and provider.
Definition: iconfactory.h:47
bool loadBundleData(const QString &bundle_data)
Loads editor state from XML bundle.
Definition: quizeditor.cpp:423
int correctAnswer() const
Access to inde of correct answer.
The core class container for single template.
Definition: templatecore.h:43
QString authorName()
Access to author name of current editor.
Definition: quizeditor.cpp:155
QIcon fromTheme(const QString &name)
Returns icon from active theme.
Definition: iconfactory.h:58
virtual void launch()
Executed when given template with this editor is launched.
static IconFactory * instance()
Singleton getter.
Definition: iconfactory.cpp:48
Container for one question.
Definition: quizquestion.h:41