Crossfire Server, Trunk  R21219
CREResourcesWindow.cpp
Go to the documentation of this file.
1 #include <Qt>
2 #include <QtWidgets>
3 #include <QScriptValue>
4 #include <stdexcept>
5 
6 #include "CREResourcesWindow.h"
7 #include "CREUtils.h"
8 #include "CREPixmap.h"
9 
10 #include "CREFilter.h"
11 #include "CREFilterDialog.h"
12 #include "CREFilterDefinition.h"
13 
14 #include "CRESettings.h"
15 
16 #include "CREReportDialog.h"
17 #include "CREReportDisplay.h"
18 #include "CREReportDefinition.h"
19 
20 #include "CRETreeItemEmpty.h"
21 #include "CRETreeItemQuest.h"
22 
23 #include "CREAnimationPanel.h"
24 #include "CREArchetypePanel.h"
25 #include "CRETreasurePanel.h"
26 #include "CREArtifactPanel.h"
27 #include "CREFormulaePanel.h"
28 #include "CREFacePanel.h"
29 #include "CREMapPanel.h"
30 #include "CRERegionPanel.h"
31 #include "CREQuestPanel.h"
32 #include "CREMessagePanel.h"
33 #include "CREScriptPanel.h"
34 
35 #include "CREWrapperObject.h"
36 #include "CREWrapperArtifact.h"
37 #include "CREWrapperFormulae.h"
38 
40 #include "Quest.h"
41 #include "QuestManager.h"
42 #include "MessageFile.h"
43 #include "ScriptFileManager.h"
44 
45 #include "CREScriptEngine.h"
46 
47 #include "CRERandomMap.h"
48 #include "CRERandomMapPanel.h"
49 
50 extern "C" {
51 #include "global.h"
52 #include "recipe.h"
53 #include "MessageManager.h"
54 #include "ResourcesManager.h"
55 #include "ScriptFile.h"
56 }
57 
59 {
60  QApplication::setOverrideCursor(Qt::WaitCursor);
61 
62  myDisplay = mode;
63 
64  Q_ASSERT(store);
65  myStore = store;
66  Q_ASSERT(quests);
67  myQuests = quests;
68  Q_ASSERT(messages);
69  myMessages = messages;
70  Q_ASSERT(resources);
71  myResources = resources;
72  Q_ASSERT(scripts);
73  myScripts = scripts;
74 
75  setAttribute(Qt::WA_DeleteOnClose);
76 
77  QVBoxLayout* layout = new QVBoxLayout(this);
78 
79  myFiltersMenu = new QMenu(this);
80  QHBoxLayout* buttons = new QHBoxLayout();
81  myFilterButton = new QPushButton(tr("Filter..."), this);
82  myFilterButton->setMenu(myFiltersMenu);
83  buttons->addWidget(myFilterButton);
84 
85  myReportsMenu = new QMenu(this);
86  QPushButton* report = new QPushButton(tr("Report"), this);
87  report->setMenu(myReportsMenu);
88  buttons->addWidget(report);
89 
90  layout->addLayout(buttons);
91 
92  mySplitter = new QSplitter(this);
93  layout->addWidget(mySplitter);
94  myTree = new QTreeWidget(this);
95  mySplitter->addWidget(myTree);
96  myTree->setIconSize(QSize(32, 32));
97  myTree->setHeaderLabel(tr("All resources"));
98 // myTree->sortByColumn(0, Qt::AscendingOrder);
99 
100 // myTree->setSortingEnabled(true);
101  myTree->setContextMenuPolicy(Qt::CustomContextMenu);
102  connect(myTree, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(treeCustomMenu(const QPoint&)));
103  connect(myTree, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), this, SLOT(tree_currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)));
104 
105  /* dummy panel to display for empty items */
106  CREPanel* dummy = new CREPanel(this);
107  QVBoxLayout* dl = new QVBoxLayout(dummy);
108  dl->addWidget(new QLabel(tr("No details available."), dummy));
109  addPanel("(dummy)", dummy);
110  dummy->setVisible(true);
111  myCurrentPanel = dummy;
112 
113  fillData();
114 
115  connect(&myFiltersMapper, SIGNAL(mapped(QObject*)), this, SLOT(onFilterChange(QObject*)));
116  updateFilters();
117  connect(&myReportsMapper, SIGNAL(mapped(QObject*)), this, SLOT(onReportChange(QObject*)));
118  updateReports();
119 
120  QApplication::restoreOverrideCursor();
121 }
122 
124 {
125  qDeleteAll(myTreeItems);
126  myTreeItems.clear();
127  qDeleteAll(myDisplayedItems);
128  myDisplayedItems.clear();
129  qDeleteAll(myPanels);
130 }
131 
133 {
134  QApplication::setOverrideCursor(Qt::WaitCursor);
135 
136  myTree->clear();
137  qDeleteAll(myTreeItems);
138  myTreeItems.clear();
139  qDeleteAll(myDisplayedItems);
140  myDisplayedItems.clear();
141 
142  QString title;
144  {
145  title = tr("Archetypes");
146  fillArchetypes();
147  }
149  {
150  title = tr("Animations");
151  fillAnimations();
152  }
154  {
155  title = tr("Treasures");
156  fillTreasures();
157  }
159  {
160  title = tr("Formulae");
161  fillFormulae();
162  }
164  {
165  title = tr("Artifacts");
166  fillArtifacts();
167  }
168  if (myDisplay & DisplayFaces)
169  {
170  title = tr("Faces");
171  fillFaces();
172  }
173  if (myDisplay & DisplayMaps)
174  {
175  title = tr("Maps");
176  fillMaps();
177  }
178  if (myDisplay & DisplayQuests)
179  {
180  title = tr("Quests");
181  fillQuests();
182  }
184  {
185  title = tr("NPC dialogs");
186  fillMessages();
187  }
189  {
190  title = tr("Scripts");
191  fillScripts();
192  }
194  {
195  title = tr("Random maps");
196  fillRandomMaps();
197  }
198 
199  if (myDisplay == DisplayAll)
200  title = tr("All resources");
201 
202  if (myTree->topLevelItemCount() == 1)
203  myTree->topLevelItem(0)->setExpanded(true);
204 
205  setWindowTitle(title);
206 
207  myTree->resizeColumnToContents(0);
208 
209  QApplication::restoreOverrideCursor();
210 }
211 
213 {
214  if (myCurrentPanel != NULL)
216 }
217 
218 void CREResourcesWindow::tree_currentItemChanged(QTreeWidgetItem* current, QTreeWidgetItem*)
219 {
220  if (!current || current->data(0, Qt::UserRole).value<void*>() == NULL)
221  return;
222  CRETreeItem* item = reinterpret_cast<CRETreeItem*>(current->data(0, Qt::UserRole).value<void*>());
223  if (!item)
224  return;
225 
226  commitData();
227 
228  CREPanel* newPanel = myPanels[item->getPanelName()];
229  if (!newPanel)
230  {
231 // printf("no panel for %s\n", qPrintable(item->getPanelName()));
232  return;
233  }
234 
235  item->fillPanel(newPanel);
236 
237  if (myCurrentPanel != newPanel)
238  {
239  if (myCurrentPanel)
240  myCurrentPanel->setVisible(false);
241  newPanel->setVisible(true);
242  myCurrentPanel = newPanel;
243  }
244 }
245 
247 {
248  QTreeWidgetItem* animationsNode = CREUtils::animationNode(NULL);
249  myTreeItems.append(new CRETreeItemEmpty());
250  animationsNode->setData(0, Qt::UserRole, QVariant::fromValue<void*>(myTreeItems.last()));
251  myTree->addTopLevelItem(animationsNode);
252 
253  QTreeWidgetItem* item;
254 
255  QStringList animations = myResources->allAnimations();
256  // There is the "bug" animation to consider
257  foreach(QString name, animations)
258  {
259  const animations_struct* anim = myResources->animation(name);
260  item = CREUtils::animationNode(anim, animationsNode);
261  myTreeItems.append(new CRETTreeItem<const animations_struct>(anim, "Animation"));
262  item->setData(0, Qt::UserRole, QVariant::fromValue<void*>(myTreeItems.last()));
263  }
264 
265  addPanel("Animation", new CREAnimationPanel(this));
266 }
267 
269 {
270  QTreeWidgetItem* item, *sub;
271  const treasurelist* list;
272  const treasure* treasure;
273 
274  QTreeWidgetItem* treasures = CREUtils::treasureNode(NULL);
275  myTreeItems.append(new CRETreeItemEmpty());
276  treasures->setData(0, Qt::UserRole, QVariant::fromValue<void*>(myTreeItems.last()));
277  myTree->addTopLevelItem(treasures);
278 
279  QStringList names = myResources->treasureLists();
280 
281  foreach(QString name, names)
282  {
283  list = myResources->treasureList(name);
284  item = CREUtils::treasureNode(list, treasures);
285 
286  myTreeItems.append(new CRETTreeItem<const treasurelist>(list, "Treasure"));
287  item->setData(0, Qt::UserRole, QVariant::fromValue<void*>(myTreeItems.last()));
288  //item->setData(0, Qt::UserRole, allTreasures[t]);
289  if (list->total_chance != 0)
290  item->setText(1, QString::number(list->total_chance));
291 
292  for (treasure = list->items; treasure; treasure = treasure->next)
293  {
294  sub = CREUtils::treasureNode(treasure, list, item);
295  if (treasure->chance)
296  sub->setText(1, QString::number(treasure->chance));
297  myTreeItems.append(new CRETTreeItem<const treasurelist>(list, "Treasure"));
298  sub->setData(0, Qt::UserRole, QVariant::fromValue<void*>(myTreeItems.last()));
299  }
300  }
301 
302  addPanel("Treasure", new CRETreasurePanel(this));
303 }
304 
306 {
307  QTreeWidgetItem* item, *root, *sub;
308  const archt* arch;
309  int added = 0, count = 0;
310 
311  root = CREUtils::archetypeNode(NULL);
312  myTreeItems.append(new CRETreeItemEmpty());
313  root->setData(0, Qt::UserRole, QVariant::fromValue<void*>(myTreeItems.last()));
314  myTree->addTopLevelItem(root);
315 
316  CREWrapperObject* wrapper = NULL;
317 
318  QStringList archs = myResources->archetypes();
319 
320  foreach(QString name, archs)
321  {
322  arch = myResources->archetype(name);
323  count++;
324  if (!wrapper)
325  wrapper = new CREWrapperObject();
326  wrapper->setObject(&arch->clone);
327  if (!myFilter.showItem(wrapper))
328  continue;
329 
330  item = CREUtils::archetypeNode(arch, root);
331  myTreeItems.append(new CRETTreeItem<const archt>(arch, "Archetype"));
332  item->setData(0, Qt::UserRole, QVariant::fromValue<void*>(myTreeItems.last()));
333 
334  for (archt* more = arch->more; more; more = more->more)
335  {
336  sub = CREUtils::archetypeNode(more, item);
337  myTreeItems.append(new CRETTreeItem<const archt>(more, "Archetype"));
338  sub->setData(0, Qt::UserRole, QVariant::fromValue<void*>(myTreeItems.last()));
339  }
340  myDisplayedItems.append(wrapper);
341  wrapper = NULL;
342  added++;
343  }
344 
345  delete wrapper;
346  addPanel("Archetype", new CREArchetypePanel(myStore, this));
347  if (added == count)
348  root->setText(0, tr("%1 [%2 items]").arg(root->text(0)).arg(count));
349  else
350  root->setText(0, tr("%1 [%2 items out of %3]").arg(root->text(0)).arg(added).arg(count));
351 }
352 
354 {
355  const recipe* r;
356  QTreeWidgetItem* root, *form, *sub;
357  CREWrapperFormulae* wrapper = NULL;
358  int count = 0, added = 0, subCount, subAdded;
359 
360  form = new QTreeWidgetItem(myTree, QStringList(tr("Formulae")));
361  myTreeItems.append(new CRETreeItemEmpty());
362  form->setData(0, Qt::UserRole, QVariant::fromValue<void*>(myTreeItems.last()));
363 // myTree->addTopLevelItem(form);
364 
365  for (int ing = 1; ing <= myResources->recipeMaxIngredients() ; ing++)
366  {
367  root = new QTreeWidgetItem(form, QStringList(tr("%1 ingredients").arg(ing)));
368  subCount = 0;
369  subAdded = 0;
370 
371  QStringList recipes = myResources->recipes(ing);
372 
373  foreach(QString name, recipes)
374  {
375  r = myResources->recipe(ing, name);
376  subCount++;
377  count++;
378  if (!wrapper)
379  wrapper = new CREWrapperFormulae();
380  wrapper->setFormulae(r);
381  if (!myFilter.showItem(wrapper))
382  continue;
383 
384  sub = CREUtils::formulaeNode(r, root);
385  myTreeItems.append(new CRETTreeItem<const recipe>(r, "Formulae"));
386  sub->setData(0, Qt::UserRole, QVariant::fromValue<void*>(myTreeItems.last()));
387  myDisplayedItems.append(wrapper);
388  wrapper = NULL;
389  subAdded++;
390  added++;
391  }
392  if (subCount == subAdded)
393  root->setText(0, tr("%1 [%2 items]").arg(root->text(0)).arg(subCount));
394  else
395  root->setText(0, tr("%1 [%2 items out of %3]").arg(root->text(0)).arg(added).arg(subCount));
396  }
397 
398  delete wrapper;
399  addPanel("Formulae", new CREFormulaePanel(this));
400  if (added == count)
401  form->setText(0, tr("%1 [%2 items]").arg(form->text(0)).arg(count));
402  else
403  form->setText(0, tr("%1 [%2 items out of %3]").arg(form->text(0)).arg(added).arg(count));
404 }
405 
407 {
408  QTreeWidgetItem* item, *root, *sub;
409  artifactlist* list;
410  const typedata* data;
411  int count = 0, added = 0;
412 
413  root = new QTreeWidgetItem(myTree, QStringList(tr("Artifacts")));
414  myTreeItems.append(new CRETreeItemEmpty());
415  root->setData(0, Qt::UserRole, QVariant::fromValue<void*>(myTreeItems.last()));
416 
417  CREWrapperArtifact wrapper;
418 
419  for (list = first_artifactlist; list; list = list->next)
420  {
421  int subCount = 0, subAdded = 0;
422  data = get_typedata(list->type);
423 
424  item = new QTreeWidgetItem(root, QStringList(data ? data->name : tr("type %1").arg(list->type)));
425 
426  for (artifact* art = list->items; art; art = art->next)
427  {
428  count++;
429  subCount++;
430  wrapper.setArtifact(art);
431  if (!myFilter.showItem(&wrapper))
432  continue;
433 
434  sub = CREUtils::artifactNode(art, item);
435  myTreeItems.append(new CRETTreeItem<artifact>(art, "Artifact"));
436  sub->setData(0, Qt::UserRole, QVariant::fromValue<void*>(myTreeItems.last()));
437  added++;
438  subAdded++;
439  }
440 
441  if (subCount == subAdded)
442  item->setText(0, tr("%1 [%2 items]").arg(item->text(0)).arg(subCount));
443  else
444  item->setText(0, tr("%1 [%2 items out of %3]").arg(item->text(0)).arg(subAdded).arg(subCount));
445  }
446 
447  addPanel("Artifact", new CREArtifactPanel(this));
448  if (added == count)
449  root->setText(0, tr("%1 [%2 items]").arg(root->text(0)).arg(count));
450  else
451  root->setText(0, tr("%1 [%2 items out of %3]").arg(root->text(0)).arg(added).arg(count));
452 }
453 
455 {
456  QTreeWidgetItem* item, *root;
457  const New_Face* face;
458 
459  root = CREUtils::faceNode(NULL);
460  myTreeItems.append(new CRETreeItemEmpty());
461  root->setData(0, Qt::UserRole, QVariant::fromValue<void*>(myTreeItems.last()));
462  myTree->addTopLevelItem(root);
463 
464  QStringList faces = myResources->faces();
465 
466  foreach(QString name, faces)
467  {
468  face = myResources->face(name);
469  item = CREUtils::faceNode(face, root);
470  myTreeItems.append(new CRETTreeItem<const New_Face>(face, "Face"));
471  item->setData(0, Qt::UserRole, QVariant::fromValue<void*>(myTreeItems.last()));
472  }
473 
474  addPanel("Face", new CREFacePanel(this));
475 }
476 
478 {
479  return left->displayName().compare(right->displayName(), Qt::CaseInsensitive) < 0;
480 }
481 
483 {
484  bool full = false;
485  if (myDisplay == DisplayMaps)
486  {
487  QStringList headers;
488  headers << tr("Maps") << tr("Experience");
489  myTree->setHeaderLabels(headers);
490  myTree->sortByColumn(0, Qt::AscendingOrder);
491  full = true;
492  }
493 
494  QTreeWidgetItem* regionNode, *root, *leaf;
495 
496  root = CREUtils::mapNode(NULL);
497  myTreeItems.append(new CRETreeItemEmpty());
498  root->setData(0, Qt::UserRole, QVariant::fromValue<void*>(myTreeItems.last()));
499  myTree->addTopLevelItem(root);
500 
501  QHash<QString, region*> regions;
502  for (region* reg = first_region; reg; reg = reg->next)
503  {
504  regions[reg->name] = reg;
505  }
506 
507  QStringList names = regions.keys();
508  names.sort();
509 
510  int totalMaps = 0;
511 
512  foreach(QString name, names)
513  {
514  QList<CREMapInformation*> maps = myStore->getMapsForRegion(name);
515  qSort(maps.begin(), maps.end(), sortMapInformation);
516  regionNode = CREUtils::regionNode(name, maps.size(), root);
517  myTreeItems.append(new CRETTreeItem<region>(regions[name], "Region"));
518  regionNode->setData(0, Qt::UserRole, QVariant::fromValue<void*>(myTreeItems.last()));
519  foreach(CREMapInformation* map, maps)
520  {
521  leaf = CREUtils::mapNode(map, regionNode);
522  myTreeItems.append(new CRETTreeItem<CREMapInformation>(map, "Map"));
523  leaf->setData(0, Qt::UserRole, QVariant::fromValue<void*>(myTreeItems.last()));
524  if (full)
525  leaf->setText(1, tr("%1").arg(QString::number(map->experience()), 20));
526 
528  myDisplayedItems.append(map->clone());
529  }
530 
531  totalMaps += maps.size();
532  }
533 
534  if (full)
535  {
536  root->setExpanded(true);
537  myTree->resizeColumnToContents(0);
538  myTree->resizeColumnToContents(1);
539  }
540  root->setText(0, tr("Maps [%1 items]").arg(totalMaps));
541 
542  addPanel("Region", new CRERegionPanel(this));
543  addPanel("Map", new CREMapPanel(myScripts, this));
544 }
545 
547 {
548  QTreeWidgetItem* item, *root;
549 
550  root = CREUtils::questsNode();
551  myTreeItems.append(new CRETreeItemQuest(NULL, root, this));
552  root->setData(0, Qt::UserRole, QVariant::fromValue<void*>(myTreeItems.last()));
553  myTree->addTopLevelItem(root);
554 
555  QStringList codes;
556  const New_Face* face;
557 
558  foreach(Quest* quest, myQuests->quests())
559  {
560  face = myResources->face(quest->face());
561  if (face != NULL)
562  quest->setFaceNumber(face->number);
563  codes.append(quest->code());
564  }
565  codes.sort();
566 
567  foreach(QString code, codes)
568  {
569  Quest* quest = myQuests->getByCode(code);
570  item = CREUtils::questNode(quest, root);
571  myTreeItems.append(new CRETreeItemQuest(quest, item, this));
572  item->setData(0, Qt::UserRole, QVariant::fromValue<void*>(myTreeItems.last()));
573  }
574 
575  addPanel("Quest", new CREQuestPanel(myQuests, myMessages, this));
576 }
577 
579 {
580  QTreeWidgetItem* item, *root;
581 
582  root = CREUtils::messagesNode();
583  myTreeItems.append(new CRETreeItemEmpty());
584  root->setData(0, Qt::UserRole, QVariant::fromValue<void*>(myTreeItems.last()));
585  myTree->addTopLevelItem(root);
586 
587  foreach(MessageFile* message, myMessages->messages())
588  {
589  item = CREUtils::messageNode(message, root);
590  myTreeItems.append(new CRETTreeItem<MessageFile>(message, "Message"));
591  item->setData(0, Qt::UserRole, QVariant::fromValue<void*>(myTreeItems.last()));
592  }
593 
594  addPanel("Message", new CREMessagePanel(myMessages, myQuests, this));
595 }
596 
597 static bool scriptLessThan(const ScriptFile* left, const ScriptFile* right)
598 {
599  return left->path().compare(right->path()) < 0;
600 }
601 
603 {
604  QTreeWidgetItem* item, *root;
605 
606  root = CREUtils::scriptsNode();
607  myTreeItems.append(new CRETreeItemEmpty());
608  root->setData(0, Qt::UserRole, QVariant::fromValue<void*>(myTreeItems.last()));
609  myTree->addTopLevelItem(root);
610 
611  QList<ScriptFile*> scripts = myScripts->scripts();
612  qSort(scripts.begin(), scripts.end(), scriptLessThan);
613 
614  foreach(ScriptFile* script, scripts)
615  {
616  item = CREUtils::scriptNode(script, root);
617  myTreeItems.append(new CRETTreeItem<ScriptFile>(script, "Script"));
618  item->setData(0, Qt::UserRole, QVariant::fromValue<void*>(myTreeItems.last()));
619  }
620 
621  addPanel("Script", new CREScriptPanel(this));
622 }
623 
624 void CREResourcesWindow::addPanel(QString name, CREPanel* panel)
625 {
626  panel->setVisible(false);
627  myPanels[name] = panel;
628  mySplitter->addWidget(panel);
629 }
630 
632 {
633  CREFilterDialog dlg;
634  if (dlg.exec() != QDialog::Accepted)
635  return;
636 
637  /* sending this signal will ultimately call our own updateFilters() */
638  emit filtersModified();
639 }
640 
642 {
643  CREReportDialog dlg;
644  if (dlg.exec() != QDialog::Accepted)
645  return;
646 
647  /* sending this signal will ultimately call our own updateReports() */
648  emit reportsModified();
649 }
650 
652 {
654  settings.loadFilters(myFilters);
655 
656  myFiltersMenu->clear();
657 
658  if (myFilters.filters().size() > 0)
659  {
660  QAction* clear = new QAction(tr("(none)"), this);
661  connect(clear, SIGNAL(triggered()), this, SLOT(clearFilter()));
662  myFiltersMenu->addAction(clear);
663 
664  foreach(CREFilterDefinition* filter, myFilters.filters())
665  {
666  QAction* a = new QAction(filter->name(), this);
667  myFiltersMenu->addAction(a);
668  myFiltersMapper.setMapping(a, filter);
669  connect(a, SIGNAL(triggered()), &myFiltersMapper, SLOT(map()));
670  }
671 
672  myFiltersMenu->addSeparator();
673  }
674 
675  QAction* quick = new QAction(tr("Quick filter..."), this);
676  connect(quick, SIGNAL(triggered()), this, SLOT(onQuickFilter()));
677  myFiltersMenu->addAction(quick);
678  QAction* dialog = new QAction(tr("Filters definition..."), this);
679  connect(dialog, SIGNAL(triggered()), this, SLOT(onFilter()));
680  myFiltersMenu->addAction(dialog);
681 
682  clearFilter();
683 }
684 
686 {
687  CREFilterDefinition* filter = qobject_cast<CREFilterDefinition*>(object);
688  if (filter == NULL)
689  return;
690  myFilter.setFilter(filter->filter());
691  fillData();
692  myFilterButton->setText(tr("Filter: %1").arg(filter->name()));
693 }
694 
696 {
697  bool ok;
698  QString filter = QInputDialog::getText(this, tr("Quick filter"), tr("Filter:"), QLineEdit::Normal, myFilter.filter(), &ok);
699  if (!ok)
700  return;
701  if (filter.isEmpty())
702  {
703  clearFilter();
704  return;
705  }
706  myFilter.setFilter(filter);
707  fillData();
708  myFilterButton->setText(tr("Filter: %1").arg(filter));
709 }
710 
712 {
713  myFilter.setFilter(QString());
714  fillData();
715  myFilterButton->setText(tr("Filter..."));
716 }
717 
719 {
721  settings.loadReports(myReports);
722 
723  myReportsMenu->clear();
724 
725  if (myReports.reports().size() > 0)
726  {
727  foreach(CREReportDefinition* report, myReports.reports())
728  {
729  QAction* a = new QAction(report->name(), this);
730  myReportsMenu->addAction(a);
731  myReportsMapper.setMapping(a, report);
732  connect(a, SIGNAL(triggered()), &myReportsMapper, SLOT(map()));
733  }
734 
735  myReportsMenu->addSeparator();
736  }
737 
738  QAction* dialog = new QAction(tr("Reports definition..."), this);
739  connect(dialog, SIGNAL(triggered()), this, SLOT(onReport()));
740  myReportsMenu->addAction(dialog);
741 }
742 
744 {
745  CREReportDefinition* report = qobject_cast<CREReportDefinition*>(object);
746  if (report == NULL)
747  return;
748 
749  QProgressDialog progress(tr("Generating report..."), tr("Abort report"), 0, myDisplayedItems.size() - 1, this);
750  progress.setWindowTitle(tr("Report: '%1'").arg(report->name()));
751  progress.setWindowModality(Qt::WindowModal);
752 
753  QStringList headers = report->header().split("\n");
754  QStringList fields = report->itemDisplay().split("\n");
755  QString sort = report->itemSort();
756 
757  QString text("<table><thead><tr>");
758 
759  foreach(QString header, headers)
760  {
761  text += "<th>" + header + "</th>";
762  }
763  text += "</tr></thead><tbody>";
764 
765  CREScriptEngine engine;
766  std::vector<QScriptValue> items;
767  std::for_each(myDisplayedItems.begin(), myDisplayedItems.end(),
768  [&items, &engine] (QObject* item) { items.push_back(engine.newQObject(item)); });
769 
770  if (!sort.isEmpty())
771  {
772  try
773  {
774  progress.setLabelText(tr("Sorting items..."));
775 
776  engine.pushContext();
777 
778  sort = "(function(left, right) { return " + sort + "; })";
779  QScriptValue sortFun = engine.evaluate(sort);
780  if (!sortFun.isValid() || engine.hasUncaughtException())
781  throw std::runtime_error("A script error happened while compiling the sort criteria:\n" + engine.uncaughtException().toString().toStdString());
782 
783  std::sort(items.begin(), items.end(), [&sortFun, &engine](QScriptValue left, QScriptValue right) {
784  QScriptValueList args;
785  args.push_back(left);
786  args.push_back(right);
787  auto ret = sortFun.call(QScriptValue(), args);
788  if (!ret.isValid() || engine.hasUncaughtException())
789  {
790  throw std::runtime_error("A script error happened while sorting items:\n" + engine.uncaughtException().toString().toStdString());
791  return false;
792  }
793  return ret.isValid() ? ret.toBoolean() : true;
794  });
795  printf("complete");
796  engine.popContext();
797  }
798  catch (std::runtime_error& ex)
799  {
800  QMessageBox::critical(this, "Script error", ex.what(), QMessageBox::Ok);
801  return;
802  }
803  }
804 
805  progress.setLabelText(tr("Generating items text..."));
806  foreach(QScriptValue item, items)
807  {
808  if (progress.wasCanceled())
809  return;
810 
811  text += "<tr>";
812 
813  engine.pushContext();
814  engine.globalObject().setProperty("item", item);
815 
816  foreach(QString field, fields)
817  {
818  text += "<td>";
819  QString data = engine.evaluate(field).toString();
820  if (engine.hasUncaughtException())
821  {
822  QMessageBox::critical(this, "Script error", "A script error happened while display items:\n" + engine.uncaughtException().toString(), QMessageBox::Ok);
823  return;
824  }
825  text += data;
826  text += "</td>\n";
827  }
828  engine.popContext();
829  text += "</tr>\n";
830 
831  progress.setValue(progress.value() + 1);
832  }
833  text += "</tbody>";
834 
835  QStringList footers = report->footer().split("\n");
836  text += "<tfoot>";
837 
838  foreach(QString footer, footers)
839  {
840  text += "<th>" + footer + "</th>";
841  }
842  text += "</tfoot>";
843 
844  text += "</table>";
845  qDebug() << "report finished";
846 
847  CREReportDisplay display(text, tr("Report: '%1'").arg(report->name()));
848  display.exec();
849  progress.hide();
850 }
851 
852 void CREResourcesWindow::fillItem(const QPoint& pos, QMenu* menu)
853 {
854  QTreeWidgetItem* node = myTree->itemAt(pos);
855  if (!node || node->data(0, Qt::UserRole).value<void*>() == NULL)
856  return;
857  CRETreeItem* item = reinterpret_cast<CRETreeItem*>(node->data(0, Qt::UserRole).value<void*>());
858  if (!item)
859  return;
860 
861  item->fillContextMenu(menu);
862 }
863 
864 void CREResourcesWindow::treeCustomMenu(const QPoint & pos)
865 {
866  QMenu menu;
867 
869  {
870  QAction* addMessage = new QAction("add message", &menu);
871  connect(addMessage, SIGNAL(triggered(bool)), this, SLOT(addMessage(bool)));
872  menu.addAction(addMessage);
873  }
874 
875  if (myDisplay & DisplayQuests)
876  {
877  QAction* addQuest = new QAction("add quest", &menu);
878  connect(addQuest, SIGNAL(triggered(bool)), this, SLOT(addQuest(bool)));
879  menu.addAction(addQuest);
880  }
881 
882  fillItem(pos, &menu);
883 
884  if (menu.actions().size() == 0)
885  return;
886  menu.exec(myTree->mapToGlobal(pos));
887 }
888 
890 {
892  /*
893  myQuests->quests().removeAll(quest);
894  fillData();
895  delete quest;
896  */
897 }
898 
900 {
901  Quest* quest = new Quest();
902  quest->setCode("(new quest)");
903  myQuests->quests().append(quest);
904  fillData();
905 }
906 
908 {
909  MessageFile* file = new MessageFile("<new file>");
910  file->setModified();
911  myMessages->messages().append(file);
912  fillData();
913 }
914 
916 {
917  return myResources;
918 }
919 
920 static bool sortRandomMap(const CRERandomMap* left, const CRERandomMap* right)
921 {
922  int name = left->map()->displayName().compare(right->map()->displayName(), Qt::CaseInsensitive);
923  if (name == 0)
924  {
925  if (left->x() < right->x())
926  return true;
927  if (left->x() == right->x() && left->y() < right->y())
928  return true;
929  return false;
930  }
931  return name < 0;
932 }
933 
935 {
936  bool full = false;
938  {
939  QStringList headers;
940  headers << tr("Random maps") << tr("Final map") << tr("Depth");
941  myTree->setHeaderLabels(headers);
942  myTree->sortByColumn(0, Qt::AscendingOrder);
943  full = true;
944  }
945 
946  QTreeWidgetItem* root = CREUtils::mapNode(NULL);
947  myTreeItems.append(new CRETreeItemEmpty());
948  root->setData(0, Qt::UserRole, QVariant::fromValue<void*>(myTreeItems.last()));
949  myTree->addTopLevelItem(root);
950 
951  QList<CRERandomMap*> maps = myStore->randomMaps();
952  qSort(maps.begin(), maps.end(), sortRandomMap);
953  foreach(CRERandomMap* map, maps)
954  {
955  QString source(tr("from %1 [%2, %3]").arg(map->map()->name()).arg(map->x()).arg(map->y()));
956  QStringList data(source);
957  if (full)
958  {
959  data << map->parameters()->final_map << QString::number(map->parameters()->dungeon_depth);
960  }
961  QTreeWidgetItem* leaf = new QTreeWidgetItem(root, QStringList(data));
962  myTreeItems.append(new CRETTreeItem<CRERandomMap>(map, "Random map"));
963  leaf->setData(0, Qt::UserRole, QVariant::fromValue<void*>(myTreeItems.last()));
964  }
965 
966  root->setText(0, tr("Random maps [%1]").arg(maps.size()));
967 
968  if (full)
969  {
970  root->setExpanded(true);
971  myTree->resizeColumnToContents(0);
972  }
973 
974  addPanel("Random map", new CRERandomMapPanel(this));
975 }
const New_Face * face(const QString &name) const
const QString & face() const
Definition: Quest.cpp:89
void deleteQuest(Quest *quest)
QHash< QString, QPointer< CREPanel > > myPanels
QList< MessageFile * > & messages()
QStringList recipes(int count) const
static QTreeWidgetItem * animationNode(QTreeWidgetItem *parent)
Definition: CREUtils.cpp:186
static QTreeWidgetItem * archetypeNode(QTreeWidgetItem *parent)
Definition: CREUtils.cpp:15
static QTreeWidgetItem * artifactNode(QTreeWidgetItem *parent)
Definition: CREUtils.cpp:42
Definition: Quest.h:32
const QString & path() const
Definition: ScriptFile.cpp:36
const treasurelist * treasureList(const QString &name)
QList< CREReportDefinition * > & reports()
struct artifactstruct * items
Definition: artifact.h:30
char final_map[RM_SIZE]
Definition: random_map.h:52
void tree_currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)
QList< CREMapInformation * > getMapsForRegion(const QString &region)
static QTreeWidgetItem * questsNode()
Definition: CREUtils.cpp:216
int x() const
const QString & itemDisplay() const
const animations_struct * animation(const QString &name) const
object clone
Definition: object.h:470
const QString & code() const
Definition: Quest.cpp:63
CREMapInformation * clone() const
static bool sortRandomMap(const CRERandomMap *left, const CRERandomMap *right)
QSignalMapper myFiltersMapper
virtual QString getPanelName() const =0
static struct struct_region_info ** regions
Definition: mapper.c:459
static QTreeWidgetItem * formulaeNode(const recipe *recipe, QTreeWidgetItem *parent)
Definition: CREUtils.cpp:141
struct obj object
Definition: object.h:465
static QTreeWidgetItem * faceNode(QTreeWidgetItem *parent)
Definition: CREUtils.cpp:173
QStringList archetypes() const
virtual void fillPanel(QWidget *panel)=0
struct titlestruct title
QStringList allAnimations() const
QList< CREFilterDefinition * > & filters()
uint16_t number
Definition: face.h:15
static QTreeWidgetItem * questNode(const Quest *quest, QTreeWidgetItem *parent)
Definition: CREUtils.cpp:221
const typedata * get_typedata(int itemtype)
Definition: item.c:335
int16_t total_chance
Definition: treasure.h:84
CREMapInformationManager * myStore
void onReportChange(QObject *object)
void setModified(bool modified=true)
const recipestruct * recipe(int ingredients, const QString &name) const
const QString & footer() const
struct artifactliststruct * next
Definition: artifact.h:29
void setFilter(const QString &filter)
Definition: CREFilter.cpp:33
bool showItem(QObject *item)
Definition: CREFilter.cpp:8
CREFilterDefinitionManager myFilters
void setObject(const object *obj)
QList< CRETreeItem * > myTreeItems
static char root[500]
Definition: mapper.c:365
void onFilterChange(QObject *object)
static QTreeWidgetItem * scriptNode(const ScriptFile *script, QTreeWidgetItem *parent)
Definition: CREUtils.cpp:243
struct regiondef * next
Definition: map.h:277
Definition: map.h:276
const QString & itemSort() const
MessageManager * myMessages
QStringList faces() const
const ResourcesManager * resourcesManager() const
struct archt * more
Definition: object.h:469
static QTreeWidgetItem * scriptsNode()
Definition: CREUtils.cpp:239
QSignalMapper myReportsMapper
EXTERN Animations * animations
Definition: global.h:163
const archt * archetype(const QString &name) const
CREResourcesWindow(CREMapInformationManager *store, QuestManager *quests, MessageManager *messages, ResourcesManager *resources, ScriptFileManager *scripts, QWidget *parent, DisplayMode mode=DisplayAll)
void setCode(const QString &code)
Definition: Quest.cpp:68
const RMParms * parameters() const
const QString & filter() const
Definition: CREFilter.cpp:28
EXTERN artifactlist * first_artifactlist
Definition: global.h:121
static bool scriptLessThan(const ScriptFile *left, const ScriptFile *right)
QuestManager * myQuests
void setFormulae(const recipe *rec)
void addPanel(QString name, CREPanel *panel)
struct treasurestruct * items
Definition: treasure.h:90
const QString & header() const
QList< QObject * > myDisplayedItems
uint8_t chance
Definition: treasure.h:70
const char * name
Definition: define.h:91
QList< ScriptFile * > scripts() const
QList< CRERandomMap * > randomMaps()
static QTreeWidgetItem * messagesNode()
Definition: CREUtils.cpp:229
struct treasurestruct treasure
ScriptFileManager * myScripts
ResourcesManager * myResources
const QString & name() const
int dungeon_depth
Definition: random_map.h:80
void treeCustomMenu(const QPoint &pos)
DisplayMode
bool sortMapInformation(const CREMapInformation *left, const CREMapInformation *right)
struct Settings settings
Definition: init.c:40
static QTreeWidgetItem * regionNode(const QString &name, int count, QTreeWidgetItem *parent)
Definition: CREUtils.cpp:201
virtual void commitData()
Definition: CREPanel.cpp:11
const QString & name() const
const QString & displayName() const
void setFaceNumber(int face)
Definition: Quest.cpp:107
QPushButton * myFilterButton
static quest_definition * quests
Definition: quest.c:93
static QTreeWidgetItem * messageNode(const MessageFile *message, QTreeWidgetItem *parent)
Definition: CREUtils.cpp:234
static QTreeWidgetItem * treasureNode(QTreeWidgetItem *parent)
Definition: CREUtils.cpp:83
const CREMapInformation * map() const
int recipeMaxIngredients() const
EXTERN region * first_region
Definition: global.h:119
CREReportDefinitionManager myReports
void loadFilters(CREFilterDefinitionManager &filters)
Definition: CRESettings.cpp:48
QList< const Quest * > quests() const
struct treasurestruct * next
Definition: treasure.h:66
void setArtifact(const artifact *art)
virtual void fillContextMenu(QMenu *)
Definition: CRETreeItem.h:16
const QString & filter() const
void fillItem(const QPoint &pos, QMenu *menu)
void loadReports(CREReportDefinitionManager &reports)
Definition: CRESettings.cpp:60
struct artifactstruct * next
Definition: artifact.h:18
int y() const
Quest * getByCode(const QString &code)
static QTreeWidgetItem * mapNode(QTreeWidgetItem *parent)
Definition: CREUtils.cpp:206
QStringList treasureLists() const
Definition: main.c:88