ErrorReportDialog.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include "EditorDefs.h"
  9. #include "ErrorReportDialog.h"
  10. // Qt
  11. #include <QClipboard>
  12. #include <QDesktopServices>
  13. #include <QFile>
  14. #include <QKeyEvent>
  15. #include <QMenu>
  16. #include <QUrl>
  17. #include <QDateTime>
  18. // AzToolsFramework
  19. #include <AzToolsFramework/API/ToolsApplicationAPI.h>
  20. #include <AzToolsFramework/API/ViewPaneOptions.h>
  21. // Editor
  22. #include "ErrorReportTableModel.h"
  23. #include "Viewport.h"
  24. #include "Util/Mailer.h"
  25. #include "GameEngine.h"
  26. #include "LyViewPaneNames.h"
  27. AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
  28. #include <ui_ErrorReportDialog.h>
  29. AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
  30. //////////////////////////////////////////////////////////////////////////
  31. CErrorReportDialog* CErrorReportDialog::m_instance = nullptr;
  32. // CErrorReportDialog dialog
  33. //////////////////////////////////////////////////////////////////////////
  34. void CErrorReportDialog::RegisterViewClass()
  35. {
  36. AzToolsFramework::ViewPaneOptions options;
  37. options.showInMenu = false;
  38. AzToolsFramework::RegisterViewPane<CErrorReportDialog>(LyViewPane::ErrorReport, LyViewPane::CategoryOther, options);
  39. }
  40. CErrorReportDialog::CErrorReportDialog(QWidget* parent)
  41. : QWidget(parent)
  42. , ui(new Ui::CErrorReportDialog)
  43. , m_errorReportModel(new CErrorReportTableModel(this))
  44. , m_sortIndicatorColumn(-1)
  45. , m_sortIndicatorOrder(Qt::AscendingOrder)
  46. {
  47. ui->setupUi(this);
  48. ui->treeView->setModel(m_errorReportModel);
  49. ui->treeView->header()->setContextMenuPolicy(Qt::CustomContextMenu);
  50. ui->treeView->header()->setSectionsMovable(true);
  51. ui->treeView->viewport()->setMouseTracking(true);
  52. ui->treeView->viewport()->installEventFilter(this);
  53. ui->treeView->header()->setSectionResizeMode(CErrorReportTableModel::ColumnSeverity, QHeaderView::ResizeToContents);
  54. ui->treeView->header()->resizeSection(CErrorReportTableModel::ColumnCount, 30);
  55. ui->treeView->header()->resizeSection(CErrorReportTableModel::ColumnText, 200);
  56. ui->treeView->header()->resizeSection(CErrorReportTableModel::ColumnFile, 150);
  57. ui->treeView->header()->resizeSection(CErrorReportTableModel::ColumnObject, 150);
  58. ui->treeView->header()->resizeSection(CErrorReportTableModel::ColumnModule, 100);
  59. ui->treeView->header()->resizeSection(CErrorReportTableModel::ColumnDescription, 100);
  60. ui->treeView->header()->resizeSection(CErrorReportTableModel::ColumnAssetScope, 200);
  61. connect(ui->treeView, SIGNAL(clicked(QModelIndex)), this, SLOT(OnReportItemClick(QModelIndex)));
  62. connect(ui->treeView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(OnReportItemDblClick(QModelIndex)));
  63. connect(ui->treeView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(OnReportItemRClick()));
  64. connect(ui->treeView->header(), SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(OnReportColumnRClick()));
  65. connect(ui->treeView->header(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), this, SLOT(OnSortIndicatorChanged(int,Qt::SortOrder)));
  66. ui->treeView->AddGroup(CErrorReportTableModel::ColumnModule);
  67. ui->treeView->header()->setSortIndicator(-1, Qt::AscendingOrder);
  68. m_instance = this;
  69. //CErrorReport *report,
  70. //m_pErrorReport = report;
  71. m_pErrorReport = nullptr;
  72. }
  73. CErrorReportDialog::~CErrorReportDialog()
  74. {
  75. m_instance = nullptr;
  76. }
  77. //////////////////////////////////////////////////////////////////////////
  78. void CErrorReportDialog::Open(CErrorReport* pReport)
  79. {
  80. if (!m_instance)
  81. {
  82. GetIEditor()->OpenView(LyViewPane::ErrorReport);
  83. }
  84. if (!m_instance)
  85. {
  86. return;
  87. }
  88. m_instance->SetReport(pReport);
  89. m_instance->UpdateErrors();
  90. m_instance->setFocus();
  91. }
  92. //////////////////////////////////////////////////////////////////////////
  93. void CErrorReportDialog::Close()
  94. {
  95. if (m_instance)
  96. {
  97. /*
  98. CCryMemFile memFile( new BYTE[256], 256, 256 );
  99. CArchive ar( &memFile, CArchive::store );
  100. m_instance->m_wndReport.SerializeState( ar );
  101. ar.Close();
  102. UINT nSize = (UINT)memFile.GetLength();
  103. LPBYTE pbtData = memFile.Detach();
  104. CXTRegistryManager regManager;
  105. regManager.WriteProfileBinary( "Dialogs\\ErrorReport", "Configuration", pbtData, nSize);
  106. if ( pbtData )
  107. delete [] pbtData;
  108. */
  109. m_instance->close();
  110. }
  111. }
  112. //////////////////////////////////////////////////////////////////////////
  113. void CErrorReportDialog::Clear()
  114. {
  115. if (m_instance)
  116. {
  117. m_instance->SetReport(nullptr);
  118. m_instance->UpdateErrors();
  119. }
  120. }
  121. bool CErrorReportDialog::eventFilter(QObject* watched, QEvent* event)
  122. {
  123. if (event->type() == QEvent::MouseMove && watched == ui->treeView->viewport())
  124. {
  125. QMouseEvent* ev = static_cast<QMouseEvent*>(event);
  126. const QModelIndex index = ui->treeView->indexAt(ev->pos());
  127. QRect rect = ui->treeView->visualRect(index);
  128. rect.moveTopLeft(ui->treeView->viewport()->mapToGlobal(rect.topLeft()));
  129. const QRect target = fontMetrics().boundingRect(rect, index.data(Qt::TextAlignmentRole).toInt(), index.data().toString());
  130. if (index.column() == CErrorReportTableModel::ColumnObject && target.contains(QCursor::pos()))
  131. {
  132. ui->treeView->viewport()->setCursor(Qt::PointingHandCursor);
  133. }
  134. else
  135. {
  136. ui->treeView->viewport()->setCursor(Qt::ArrowCursor);
  137. }
  138. }
  139. return QWidget::eventFilter(watched, event);
  140. }
  141. // CErrorReportDialog message handlers
  142. void CErrorReportDialog::SetReport(CErrorReport* report)
  143. {
  144. m_pErrorReport = report;
  145. m_errorReportModel->setErrorReport(report);
  146. }
  147. void CErrorReportDialog::UpdateErrors()
  148. {
  149. m_errorReportModel->setErrorReport(m_pErrorReport);
  150. }
  151. //////////////////////////////////////////////////////////////////////////
  152. #define ID_REMOVE_ITEM 1
  153. #define ID_SORT_ASC 2
  154. #define ID_SORT_DESC 3
  155. #define ID_GROUP_BYTHIS 4
  156. #define ID_SHOW_GROUPBOX 5
  157. #define ID_SHOW_FIELDCHOOSER 6
  158. #define ID_COLUMN_BESTFIT 7
  159. #define ID_COLUMN_ARRANGEBY 100
  160. #define ID_COLUMN_ALIGMENT 200
  161. #define ID_COLUMN_ALIGMENT_LEFT ID_COLUMN_ALIGMENT + 1
  162. #define ID_COLUMN_ALIGMENT_RIGHT ID_COLUMN_ALIGMENT + 2
  163. #define ID_COLUMN_ALIGMENT_CENTER ID_COLUMN_ALIGMENT + 3
  164. #define ID_COLUMN_SHOW 500
  165. void CErrorReportDialog::OnReportColumnRClick()
  166. {
  167. QHeaderView* header = ui->treeView->header();
  168. int column = header->logicalIndexAt(ui->treeView->mapFromGlobal(QCursor::pos()));
  169. if (column < 0)
  170. {
  171. return;
  172. }
  173. QMenu menu;
  174. QAction* actionSortAscending = menu.addAction(tr("Sort &Ascending"));
  175. QAction* actionSortDescending = menu.addAction(tr("Sort Des&cending"));
  176. menu.addSeparator();
  177. QAction* actionGroupByThis = menu.addAction(tr("&Group by this field"));
  178. QAction* actionGroupByBox = menu.addAction(tr("Group &by box"));
  179. menu.addSeparator();
  180. QAction* actionRemoveItem = menu.addAction(tr("&Remove column"));
  181. QAction* actionFieldChooser = menu.addAction(tr("Field &Chooser"));
  182. menu.addSeparator();
  183. QAction* actionBestFit = menu.addAction(tr("Best &Fit"));
  184. actionGroupByBox->setCheckable(true);
  185. actionGroupByBox->setChecked(ui->treeView->IsGroupsShown());
  186. // create arrange by items
  187. QMenu menuArrange;
  188. const int nColumnCount = m_errorReportModel->columnCount();
  189. for (int nColumn = 0; nColumn < nColumnCount; nColumn++)
  190. {
  191. if (!header->isSectionHidden(nColumn))
  192. {
  193. const QString sCaption = m_errorReportModel->headerData(nColumn, Qt::Horizontal).toString();
  194. if (!sCaption.isEmpty())
  195. {
  196. menuArrange.addAction(sCaption)->setData(nColumn);
  197. }
  198. }
  199. }
  200. menuArrange.addSeparator();
  201. QAction* actionClearGroups = menuArrange.addAction(tr("Clear groups"));
  202. menuArrange.setTitle(tr("Arrange By"));
  203. menu.insertMenu(actionSortAscending, &menuArrange);
  204. // create columns items
  205. QMenu menuColumns;
  206. for (int nColumn = 0; nColumn < nColumnCount; nColumn++)
  207. {
  208. const QString sCaption = m_errorReportModel->headerData(nColumn, Qt::Horizontal).toString();
  209. //if (!sCaption.isEmpty())
  210. QAction* action = menuColumns.addAction(sCaption);
  211. action->setCheckable(true);
  212. action->setChecked(!ui->treeView->header()->isSectionHidden(nColumn));
  213. }
  214. menuColumns.setTitle(tr("Columns"));
  215. menu.insertMenu(menuArrange.menuAction(), &menuColumns);
  216. //create Text alignment submenu
  217. QMenu menuAlign;
  218. QAction* actionAlignLeft = menuAlign.addAction(tr("Align Left"));
  219. QAction* actionAlignRight = menuAlign.addAction(tr("Align Right"));
  220. QAction* actionAlignCenter = menuAlign.addAction(tr("Align Center"));
  221. actionAlignLeft->setCheckable(true);
  222. actionAlignRight->setCheckable(true);
  223. actionAlignCenter->setCheckable(true);
  224. const int alignment = m_errorReportModel->headerData(column, Qt::Horizontal, Qt::TextAlignmentRole).toInt();
  225. actionAlignLeft->setChecked(alignment & Qt::AlignLeft);
  226. actionAlignRight->setChecked(alignment & Qt::AlignRight);
  227. actionAlignCenter->setChecked(alignment & Qt::AlignHCenter);
  228. menuAlign.setTitle(tr("&Alignment"));
  229. menu.insertMenu(actionBestFit, &menuAlign);
  230. // track menu
  231. QAction* nMenuResult = menu.exec(QCursor::pos());
  232. // arrange by items
  233. if (menuArrange.actions().contains(nMenuResult))
  234. {
  235. // group by item
  236. if (actionClearGroups == nMenuResult)
  237. {
  238. ui->treeView->ClearGroups();
  239. }
  240. else
  241. {
  242. column = nMenuResult->data().toInt();
  243. ui->treeView->ToggleSortOrder(column);
  244. }
  245. }
  246. // process Alignment options
  247. if (nMenuResult == actionAlignLeft)
  248. {
  249. m_errorReportModel->setHeaderData(column, Qt::Horizontal, Qt::AlignLeft, Qt::TextAlignmentRole);
  250. }
  251. else if (nMenuResult == actionAlignRight)
  252. {
  253. m_errorReportModel->setHeaderData(column, Qt::Horizontal, Qt::AlignRight, Qt::TextAlignmentRole);
  254. }
  255. else if (nMenuResult == actionAlignCenter)
  256. {
  257. m_errorReportModel->setHeaderData(column, Qt::Horizontal, Qt::AlignCenter, Qt::TextAlignmentRole);
  258. }
  259. // process column selection item
  260. if (menuColumns.actions().contains(nMenuResult))
  261. {
  262. ui->treeView->header()->setSectionHidden(menuColumns.actions().indexOf(nMenuResult), !nMenuResult->isChecked());
  263. }
  264. // other general items
  265. if (nMenuResult == actionSortAscending || nMenuResult == actionSortDescending)
  266. {
  267. ui->treeView->sortByColumn(column, nMenuResult == actionSortAscending ? Qt::AscendingOrder : Qt::DescendingOrder);
  268. }
  269. else if (nMenuResult == actionFieldChooser)
  270. {
  271. //OnShowFieldChooser();
  272. }
  273. else if (nMenuResult == actionBestFit)
  274. {
  275. ui->treeView->resizeColumnToContents(column);
  276. }
  277. else if (nMenuResult == actionRemoveItem)
  278. {
  279. ui->treeView->header()->setSectionHidden(column, true);
  280. }
  281. // other general items
  282. else if (nMenuResult == actionGroupByThis)
  283. {
  284. ui->treeView->AddGroup(column);
  285. ui->treeView->ShowGroups(true);
  286. }
  287. else if (nMenuResult == actionGroupByBox)
  288. {
  289. ui->treeView->ShowGroups(!ui->treeView->IsGroupsShown());
  290. }
  291. }
  292. #define ID_POPUP_COLLAPSEALLGROUPS 1
  293. #define ID_POPUP_EXPANDALLGROUPS 2
  294. //////////////////////////////////////////////////////////////////////////
  295. void CErrorReportDialog::CopyToClipboard()
  296. {
  297. QString str;
  298. const QModelIndexList selRows = ui->treeView->selectionModel()->selectedRows();
  299. for (const QModelIndex& index : selRows)
  300. {
  301. const CErrorRecord* pRecord = index.data(Qt::UserRole).value<const CErrorRecord*>();
  302. if (pRecord)
  303. {
  304. str += pRecord->GetErrorText();
  305. if (pRecord->pObject)
  306. {
  307. str += QString::fromLatin1(" [Object: %1]").arg(pRecord->pObject->GetName());
  308. }
  309. str += QString::fromLatin1("\r\n");
  310. }
  311. }
  312. if (!str.isEmpty())
  313. {
  314. QApplication::clipboard()->setText(str);
  315. }
  316. }
  317. //////////////////////////////////////////////////////////////////////////
  318. void CErrorReportDialog::OnReportItemRClick()
  319. {
  320. const QModelIndex index = ui->treeView->indexAt(ui->treeView->viewport()->mapFromGlobal(QCursor::pos()));
  321. if (!index.isValid())
  322. {
  323. return;
  324. }
  325. if (ui->treeView->model()->hasChildren(index))
  326. {
  327. QMenu menu;
  328. menu.addAction(tr("Collapse &All Groups"), ui->treeView, SLOT(collapseAll()));
  329. menu.addAction(tr("E&xpand All Groups"), ui->treeView, SLOT(expandAll()));
  330. // track menu
  331. menu.exec(QCursor::pos());
  332. }
  333. else
  334. {
  335. QMenu menu;
  336. //menu.addAction(tr("Select Object(s)")); // TODO: does nothing?
  337. menu.addAction(tr("Copy Warning(s) To Clipboard"), this, SLOT(CopyToClipboard()));
  338. menu.addAction(tr("E-mail Error Report"), this, SLOT(SendInMail()));
  339. menu.addAction(tr("Open in Excel"), this, SLOT(OpenInExcel()));
  340. // track menu
  341. menu.exec(QCursor::pos());
  342. }
  343. }
  344. //////////////////////////////////////////////////////////////////////////
  345. void CErrorReportDialog::SendInMail()
  346. {
  347. if (!m_pErrorReport)
  348. {
  349. return;
  350. }
  351. // Send E-Mail.
  352. QString textMsg;
  353. for (int i = 0; i < m_errorReportModel->rowCount(); ++i)
  354. {
  355. const CErrorRecord* err = m_errorReportModel->index(i, 0).data(Qt::UserRole).value<const CErrorRecord*>();
  356. textMsg += err->GetErrorText() + QString::fromLatin1("\n");
  357. }
  358. std::vector<const char*> who;
  359. const QString subject = QString::fromLatin1("Level %1 Error Report").arg(GetIEditor()->GetGameEngine()->GetLevelPath());
  360. CMailer::SendMail(subject.toUtf8().data(), textMsg.toUtf8().data(), who, who, true);
  361. }
  362. //////////////////////////////////////////////////////////////////////////
  363. void CErrorReportDialog::OpenInExcel()
  364. {
  365. if (!m_pErrorReport)
  366. {
  367. return;
  368. }
  369. const QString levelName = Path::GetFileName(GetIEditor()->GetGameEngine()->GetLevelName());
  370. const QString filename = QString::fromLatin1("ErrorList_%1_%2.csv").arg(levelName).arg(QDateTime::currentDateTime().toString("yyyy-MM-dd-HH-mm-ss"));
  371. // Save to temp file.
  372. QFile f(filename);
  373. if (f.open(QIODevice::WriteOnly))
  374. {
  375. for (int i = 0; i < m_errorReportModel->rowCount(); ++i)
  376. {
  377. const CErrorRecord* err = m_errorReportModel->index(i, 0).data(Qt::UserRole).value<const CErrorRecord*>();
  378. QString text = err->GetErrorText();
  379. text.replace(',', '.');
  380. text.replace('\t', ',');
  381. f.write((text + QString::fromLatin1("\n")).toUtf8().data());
  382. }
  383. f.close();
  384. QDesktopServices::openUrl(QUrl::fromLocalFile(filename));
  385. }
  386. else
  387. {
  388. Warning("Failed to save %s", (const char*)filename.toUtf8().data());
  389. }
  390. }
  391. //////////////////////////////////////////////////////////////////////////
  392. void CErrorReportDialog::OnReportItemClick(const QModelIndex& index)
  393. {
  394. QRect rect = ui->treeView->visualRect(index);
  395. rect.moveTopLeft(ui->treeView->viewport()->mapToGlobal(rect.topLeft()));
  396. const QRect target = fontMetrics().boundingRect(rect, index.data(Qt::TextAlignmentRole).toInt(), index.data().toString());
  397. if (index.column() == CErrorReportTableModel::ColumnObject && target.contains(QCursor::pos()))
  398. {
  399. OnReportHyperlink(index);
  400. }
  401. /*
  402. if (pItemNotify->pColumn->GetItemIndex() == COLUMN_CHECK)
  403. {
  404. m_wndReport.Populate();
  405. }
  406. */
  407. }
  408. //////////////////////////////////////////////////////////////////////////
  409. void CErrorReportDialog::keyPressEvent(QKeyEvent* event)
  410. {
  411. if (event->matches(QKeySequence::Copy))
  412. {
  413. CopyToClipboard();
  414. event->accept();
  415. }
  416. else
  417. {
  418. QWidget::keyPressEvent(event);
  419. }
  420. }
  421. //////////////////////////////////////////////////////////////////////////
  422. void CErrorReportDialog::OnReportItemDblClick(const QModelIndex& index)
  423. {
  424. bool bDone = false;
  425. const CErrorRecord* pError = index.data(Qt::UserRole).value<const CErrorRecord*>();
  426. if (pError && pError->pObject != nullptr)
  427. {
  428. CUndo undo("Select Object(s)");
  429. // Clear other selection.
  430. GetIEditor()->ClearSelection();
  431. // Select this object.
  432. GetIEditor()->SelectObject(pError->pObject);
  433. CViewport* vp = GetIEditor()->GetActiveView();
  434. if (vp)
  435. {
  436. vp->CenterOnSelection();
  437. }
  438. bDone = true;
  439. }
  440. if (!bDone && pError && GetIEditor()->GetActiveView())
  441. {
  442. float x, y, z;
  443. if (GetPositionFromString(pError->error, &x, &y, &z))
  444. {
  445. CViewport* vp = GetIEditor()->GetActiveView();
  446. Matrix34 tm = vp->GetViewTM();
  447. tm.SetTranslation(Vec3(x, y, z));
  448. vp->SetViewTM(tm);
  449. }
  450. }
  451. /*
  452. if (index.isValid())
  453. {
  454. TRACE(_T("Double Click on row %d\n"),
  455. index.row());
  456. CErrorMessageRecord* pRecord = DYNAMIC_DOWNCAST(CErrorMessageRecord, pItemNotify->pRow->GetRecord());
  457. if (pRecord)
  458. {
  459. {
  460. m_wndReport.Populate();
  461. }
  462. }
  463. }
  464. */
  465. }
  466. void CErrorReportDialog::OnSortIndicatorChanged(int logicalIndex, Qt::SortOrder order)
  467. {
  468. if (logicalIndex == 0)
  469. {
  470. ui->treeView->header()->setSortIndicator(m_sortIndicatorColumn, m_sortIndicatorOrder);
  471. }
  472. else
  473. {
  474. m_sortIndicatorColumn = logicalIndex;
  475. m_sortIndicatorOrder = order;
  476. }
  477. }
  478. //////////////////////////////////////////////////////////////////////////
  479. void CErrorReportDialog::OnReportHyperlink(const QModelIndex& index)
  480. {
  481. const CErrorRecord* pError = index.data(Qt::UserRole).value<const CErrorRecord*>();
  482. bool bDone = false;
  483. if (pError && pError->pObject != nullptr)
  484. {
  485. CUndo undo("Select Object(s)");
  486. // Clear other selection.
  487. GetIEditor()->ClearSelection();
  488. // Select this object.
  489. GetIEditor()->SelectObject(pError->pObject);
  490. bDone = true;
  491. }
  492. if (!bDone && pError && GetIEditor()->GetActiveView())
  493. {
  494. float x, y, z;
  495. if (GetPositionFromString(pError->error, &x, &y, &z))
  496. {
  497. CViewport* vp = GetIEditor()->GetActiveView();
  498. Matrix34 tm = vp->GetViewTM();
  499. tm.SetTranslation(Vec3(x, y, z));
  500. vp->SetViewTM(tm);
  501. }
  502. }
  503. }
  504. /*
  505. //////////////////////////////////////////////////////////////////////////
  506. void CErrorReportDialog::OnShowFieldChooser()
  507. {
  508. CMainFrm* pMainFrm = (CMainFrame*)AfxGetMainWnd();
  509. if (pMainFrm)
  510. {
  511. bool bShow = !pMainFrm->m_wndFieldChooser.IsVisible();
  512. pMainFrm->ShowControlBar(&pMainFrm->m_wndFieldChooser, bShow, false);
  513. }
  514. }
  515. */
  516. #include <moc_ErrorReportDialog.cpp>