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
basicmlearningeditor.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/mlearning/basicmlearningeditor.h"
32 
33 #include "miscellaneous/application.h"
34 #include "miscellaneous/iconfactory.h"
35 #include "core/templatefactory.h"
36 #include "core/templatecore.h"
37 #include "core/templateentrypoint.h"
38 
39 #include <QTimer>
40 
41 
42 BasicmLearningEditor::BasicmLearningEditor(TemplateCore *core, QWidget *parent)
43  : TemplateEditor(core, parent), m_ui(new Ui::BasicmLearningEditor) {
44  m_ui->setupUi(this);
45 
46  // Set validators.
47  QRegExpValidator *author_validator = new QRegExpValidator(this);
48  QRegExpValidator *title_validator = new QRegExpValidator(this);
49 
50  author_validator->setRegExp(QRegExp(".{,50}"));
51  title_validator->setRegExp(QRegExp(".{,100}"));
52 
53  m_ui->m_txtAuthor->lineEdit()->setValidator(author_validator);
54  m_ui->m_txtName->lineEdit()->setValidator(title_validator);
55 
56  // Set tab order.
57  QList<QWidget*> tab_order_widgets;
58  tab_order_widgets << m_ui->m_txtTitle->lineEdit() << m_ui->m_txtDescription <<
59  m_ui->m_txtAuthor->lineEdit() << m_ui->m_txtName->lineEdit() <<
60  m_ui->m_listItems << m_ui->m_btnItemAdd << m_ui->m_btnItemRemove <<
61  m_ui->m_btnItemUp << m_ui->m_btnItemDown;
62 
63  for (int i = 1; i < tab_order_widgets.size(); i++) {
64  setTabOrder(tab_order_widgets.at(i - 1), tab_order_widgets.at(i));
65  }
66 
67 
68  m_ui->m_txtTitle->lineEdit()->setPlaceholderText(tr("Title of the item"));
69  m_ui->m_txtNumberOfItems->lineEdit()->setEnabled(false);
70  m_ui->m_txtAuthor->lineEdit()->setPlaceholderText(tr("Author of this collection"));
71  m_ui->m_txtName->lineEdit()->setPlaceholderText(tr("Name of this collection"));
72 
74 
75  m_ui->m_btnItemAdd->setIcon(factory->fromTheme("item-add"));
76  m_ui->m_btnItemRemove->setIcon(factory->fromTheme("item-remove"));
77  m_ui->m_btnItemUp->setIcon(factory->fromTheme("move-up"));
78  m_ui->m_btnItemDown->setIcon(factory->fromTheme("move-down"));
79 
80  connect(m_ui->m_txtTitle->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(checkTitle(QString)));
81  connect(m_ui->m_btnItemAdd, SIGNAL(clicked()), this, SLOT(addNewItem()));
82  connect(m_ui->m_btnItemRemove, SIGNAL(clicked()), this, SLOT(removeSelectedItem()));
83  connect(m_ui->m_txtDescription, SIGNAL(textChanged()), this, SLOT(saveItem()));
84  connect(m_ui->m_txtTitle->lineEdit(), SIGNAL(textEdited(QString)), this, SLOT(saveItem()));
85  connect(m_ui->m_listItems, SIGNAL(currentRowChanged(int)), this, SLOT(displayItem(int)));
86  connect(m_ui->m_btnItemUp, SIGNAL(clicked()), this, SLOT(moveItemUp()));
87  connect(m_ui->m_btnItemDown, SIGNAL(clicked()), this, SLOT(moveItemDown()));
88  connect(m_ui->m_txtAuthor->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(onAuthorChanged(QString)));
89  connect(m_ui->m_txtName->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(onNameChanged(QString)));
90 
91  checkTitle(m_ui->m_txtTitle->lineEdit()->text());
92  checkAuthor();
93  checkName();
94  setEditorsEnabled(false);
95  updateItemCount();
96 }
97 
98 BasicmLearningEditor::~BasicmLearningEditor() {
99  delete m_ui;
100 }
101 
102 bool BasicmLearningEditor::loadBundleData(const QString &bundle_data) {
103  QDomDocument bundle_document;
104  bundle_document.setContent(bundle_data);
105 
106  QDomNodeList items = bundle_document.documentElement().elementsByTagName("item");
107 
108  for (int i = 0; i < items.size(); i++) {
109  QDomNode item = items.at(i);
110 
111  if (item.isElement()) {
112  QString title = item.namedItem("item_title").toElement().text();
113  QString description = item.namedItem("item_description").toElement().text();
114 
115  if (title.isEmpty() || description.isEmpty()) {
116  // TODO: error
117  continue;
118  }
119  else {
120  addNewItem(title, description);
121  }
122  }
123  else {
124  continue;
125  }
126  }
127 
128  // Load author & name.
129  m_ui->m_txtAuthor->lineEdit()->setText(bundle_document.documentElement().namedItem("author").namedItem("name").toElement().text());
130  m_ui->m_txtName->lineEdit()->setText(bundle_document.documentElement().namedItem("title").toElement().text());
131 
132  return true;
133 }
134 
136  return m_ui->m_txtName->lineEdit()->text();
137 }
138 
140  return m_ui->m_txtAuthor->lineEdit()->text();
141 }
142 
143 void BasicmLearningEditor::addNewItem(const QString &title, const QString &description) {
144  int marked_item = m_ui->m_listItems->currentRow();
145  BasicmLearningItem new_item;
146  QListWidgetItem *new_item_view = new QListWidgetItem();
147 
148  new_item.setTitle(title);
149  new_item.setDescription(description);
150 
151  new_item_view->setText(new_item.title());
152  new_item_view->setData(Qt::UserRole, QVariant::fromValue(new_item));
153 
154  if (m_ui->m_listItems->count() == 0) {
155  // We are adding first item.
156  setEditorsEnabled(true);
157 
158  m_ui->m_btnItemRemove->setEnabled(true);
159 
160  m_ui->m_listItems->insertItem(0, new_item_view);
161  m_ui->m_listItems->setCurrentRow(0);
162  }
163  else {
164  m_ui->m_listItems->insertItem(marked_item + 1, new_item_view);
165  m_ui->m_listItems->setCurrentRow(marked_item + 1);
166  }
167 
168  updateItemCount();
169 }
170 
171 void BasicmLearningEditor::addNewItem() {
172  addNewItem(tr("Prague"), tr("Prague is the city which lies in the heart of Europe."));
173  launch();
174  emit changed();
175 }
176 
177 void BasicmLearningEditor::checkAuthor() {
178  if (m_ui->m_txtAuthor->lineEdit()->text().isEmpty()) {
179  m_ui->m_txtAuthor->setStatus(WidgetWithStatus::Error,
180  tr("No author is specified."));
181  }
182  else {
183  m_ui->m_txtAuthor->setStatus(WidgetWithStatus::Ok,
184  tr("Author is specified."));
185  }
186 }
187 
188 void BasicmLearningEditor::checkName() {
189  if (m_ui->m_txtName->lineEdit()->text().isEmpty()) {
190  m_ui->m_txtName->setStatus(WidgetWithStatus::Error,
191  tr("No collection title is specified."));
192  }
193  else {
194  m_ui->m_txtName->setStatus(WidgetWithStatus::Ok,
195  tr("Collection title is specified."));
196  }
197 }
198 
199 void BasicmLearningEditor::onAuthorChanged(const QString& new_author) {
200  Q_UNUSED(new_author)
201 
202  checkAuthor();
203 
204  launch();
205  emit changed();
206 }
207 
208 void BasicmLearningEditor::onNameChanged(const QString& new_name) {
209  Q_UNUSED(new_name)
210 
211  checkName();
212 
213  launch();
214  emit changed();
215 }
216 
217 void BasicmLearningEditor::configureUpDown() {
218  if (m_ui->m_listItems->count() > 1) {
219  int index = m_ui->m_listItems->currentRow();
220 
221  if (index == 0) {
222  m_ui->m_btnItemUp->setEnabled(false);
223  m_ui->m_btnItemDown->setEnabled(true);
224  }
225  else if (index == m_ui->m_listItems->count() - 1) {
226  m_ui->m_btnItemUp->setEnabled(true);
227  m_ui->m_btnItemDown->setEnabled(false);
228  }
229  else {
230  m_ui->m_btnItemUp->setEnabled(true);
231  m_ui->m_btnItemDown->setEnabled(true);
232  }
233  }
234  else {
235  m_ui->m_btnItemUp->setEnabled(false);
236  m_ui->m_btnItemDown->setEnabled(false);
237  }
238 }
239 
240 QList<BasicmLearningItem> BasicmLearningEditor::activeItems() const {
241  QList<BasicmLearningItem> questions;
242 
243  for (int i = 0; i < m_ui->m_listItems->count(); i++) {
244  questions.append(m_ui->m_listItems->item(i)->data(Qt::UserRole).value<BasicmLearningItem>());
245  }
246 
247  return questions;
248 }
249 
251  return !activeItems().isEmpty();
252 }
253 
255  /*if (!canGenerateApplications()) {
256  return QString();
257  }*/
258 
259  QDomDocument source_document = qApp->templateManager()->generateBundleHeader(core()->entryPoint()->typeIndentifier(),
260  m_ui->m_txtAuthor->lineEdit()->text(),
261  QString(),
262  m_ui->m_txtName->lineEdit()->text(),
263  QString(),
264  "1");
265  FIND_DATA_ELEMENT(data_element, source_document);
266 
267  foreach (const BasicmLearningItem &item, activeItems()) {
268  QDomElement item_element = source_document.createElement("item");
269 
270  // Fill in details about question.
271  QDomElement title_element = source_document.createElement("item_title");
272  QDomElement description_element = source_document.createElement("item_description");
273 
274  title_element.appendChild(source_document.createTextNode(item.title()));
275  description_element.appendChild(source_document.createTextNode(item.description()));
276 
277  item_element.appendChild(title_element);
278  item_element.appendChild(description_element);
279 
280  data_element.appendChild(item_element);
281  }
282 
283  return source_document.toString(XML_BUNDLE_INDENTATION);
284 }
285 
286 void BasicmLearningEditor::updateItemCount() {
287  m_ui->m_txtNumberOfItems->lineEdit()->setText(QString::number(m_ui->m_listItems->count()));
288 
289  if (m_ui->m_listItems->count() > 0) {
290  m_ui->m_txtNumberOfItems->setStatus(WidgetWithStatus::Ok, tr("Collection contains at least one item."));
291  }
292  else {
293  m_ui->m_txtNumberOfItems->setStatus(WidgetWithStatus::Error, tr("Collection does not contain any items."));
294  }
295 }
296 
297 void BasicmLearningEditor::removeSelectedItem() {
298  int current_row = m_ui->m_listItems->currentRow();
299 
300  if (current_row >= 0) {
301  if (m_ui->m_listItems->count() == 1) {
302  // We are removing last visible question.
303  setEditorsEnabled(false);
304 
305  m_ui->m_btnItemRemove->setEnabled(false);
306  }
307 
308  delete m_ui->m_listItems->takeItem(current_row);
309  }
310 
311  updateItemCount();
312  launch();
313  emit changed();
314 }
315 
316 void BasicmLearningEditor::saveItem() {
317  m_activeItem.setTitle(m_ui->m_txtTitle->lineEdit()->text());
318  m_activeItem.setDescription(m_ui->m_txtDescription->toPlainText());
319 
320  m_ui->m_listItems->currentItem()->setData(Qt::UserRole, QVariant::fromValue(m_activeItem));
321  m_ui->m_listItems->currentItem()->setText(m_activeItem.title());
322 
323  emit changed();
324 }
325 
326 void BasicmLearningEditor::displayItem(int index) {
327  if (index >= 0) {
328  BasicmLearningItem item = m_ui->m_listItems->item(index)->data(Qt::UserRole).value<BasicmLearningItem>();
329 
330  m_ui->m_txtTitle->lineEdit()->setText(item.title());
331  m_ui->m_txtDescription->setText(item.description());
332  m_activeItem = item;
333  }
334  else {
335  m_ui->m_txtTitle->lineEdit()->clear();
336  m_ui->m_txtDescription->clear();
337  }
338 
339  QTimer::singleShot(0, this, SLOT(configureUpDown()));
340 }
341 
342 void BasicmLearningEditor::checkTitle(const QString &title) {
343  if (title.simplified().isEmpty()) {
344  m_ui->m_txtTitle->setStatus(WidgetWithStatus::Error, tr("Please, enter some title."));
345  }
346  else {
347  m_ui->m_txtTitle->setStatus(WidgetWithStatus::Ok, tr("Title seems to be okay."));
348  }
349 }
350 
351 void BasicmLearningEditor::moveItemUp() {
352  int index = m_ui->m_listItems->currentRow();
353 
354  m_ui->m_listItems->insertItem(index - 1, m_ui->m_listItems->takeItem(index));
355  m_ui->m_listItems->setCurrentRow(index - 1);
356 
357  emit changed();
358 }
359 
360 void BasicmLearningEditor::moveItemDown() {
361  int index = m_ui->m_listItems->currentRow();
362 
363  m_ui->m_listItems->insertItem(index + 1, m_ui->m_listItems->takeItem(index));
364  m_ui->m_listItems->setCurrentRow(index + 1);
365 
366  emit changed();
367 }
368 
369 void BasicmLearningEditor::setEditorsEnabled(bool enabled) {
370  m_ui->m_groupItemEditor->setEnabled(enabled);
371 }
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.
QString authorName()
Access to author 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.
bool loadBundleData(const QString &bundle_data)
Loads editor state from XML bundle.
Icon theme manipulator and provider.
Definition: iconfactory.h:47
The core class container for single template.
Definition: templatecore.h:43
QString projectName()
Access to project name of current editor.
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