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