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