mainwindow.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. /*************************************************************************
  2. * Copyright (c) 2011 AT&T Intellectual Property
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * https://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors: Details at https://graphviz.org
  9. *************************************************************************/
  10. #include "mainwindow.h"
  11. #include "config.h"
  12. #include "csettings.h"
  13. #include "mdichild.h"
  14. #include <QStringList>
  15. #include <QtWidgets>
  16. #include <optional>
  17. #include <qframe.h>
  18. #include <string_view>
  19. QTextEdit *globTextEdit;
  20. int errorPipe(char *errMsg) {
  21. globTextEdit->setText(globTextEdit->toPlainText() +
  22. QString::fromUtf8(errMsg));
  23. return 0;
  24. }
  25. static void freeList(char **lp, int count) {
  26. for (int i = 0; i < count; i++)
  27. free(lp[i]);
  28. free(lp);
  29. }
  30. static int LoadPlugins(QComboBox &cb, GVC_t *gvc, const char *kind,
  31. const QStringList &more, std::string_view prefer) {
  32. int count;
  33. char **lp = gvPluginList(gvc, kind, &count);
  34. std::optional<int> idx;
  35. cb.clear();
  36. for (int id = 0; id < count; id++) {
  37. cb.addItem(QString::fromUtf8(lp[id]));
  38. if (!idx.has_value() && prefer == lp[id])
  39. idx = id;
  40. }
  41. freeList(lp, count);
  42. /* Add additional items if supplied */
  43. cb.addItems(more);
  44. if (idx.has_value())
  45. cb.setCurrentIndex(*idx);
  46. return idx.value_or(0);
  47. }
  48. void CMainWindow::createConsole() {
  49. QDockWidget *dock = new QDockWidget(tr("Output Console"), nullptr);
  50. QTextEdit *textEdit = new QTextEdit(dock);
  51. dock->setAllowedAreas(Qt::BottomDockWidgetArea | Qt::TopDockWidgetArea);
  52. addDockWidget(Qt::BottomDockWidgetArea, dock);
  53. QVBoxLayout *vL = new QVBoxLayout();
  54. textEdit->setObjectName(QStringLiteral("textEdit"));
  55. globTextEdit = textEdit;
  56. agseterrf(errorPipe);
  57. vL->addWidget(textEdit);
  58. vL->setContentsMargins(1, 1, 1, 1);
  59. QFrame *fr = new QFrame(dock);
  60. vL->addWidget(fr);
  61. QPushButton *logNewBtn =
  62. new QPushButton(QIcon(QStringLiteral(":/images/new.png")), {}, fr);
  63. QPushButton *logSaveBtn =
  64. new QPushButton(QIcon(QStringLiteral(":/images/save.png")), {}, fr);
  65. QHBoxLayout *consoleLayout = new QHBoxLayout();
  66. consoleLayout->addWidget(logNewBtn);
  67. connect(logNewBtn, &QPushButton::clicked, this, &CMainWindow::slotNewLog);
  68. connect(logSaveBtn, &QPushButton::clicked, this, &CMainWindow::slotSaveLog);
  69. consoleLayout->addWidget(logSaveBtn);
  70. consoleLayout->addStretch();
  71. consoleLayout->setContentsMargins(1, 1, 1, 1);
  72. fr->setLayout(consoleLayout);
  73. QFrame *mainFrame = new QFrame(dock);
  74. mainFrame->setLayout(vL);
  75. dock->setWidget(mainFrame);
  76. }
  77. static const QStringList xtra = {QStringLiteral("NONE")};
  78. CMainWindow::CMainWindow(const QStringList &files) {
  79. QWidget *centralwidget = new QWidget(this);
  80. centralwidget->setObjectName(QStringLiteral("centralwidget"));
  81. QVBoxLayout *verticalLayout_2 = new QVBoxLayout(centralwidget);
  82. verticalLayout_2->setObjectName(QStringLiteral("verticalLayout_2"));
  83. QVBoxLayout *verticalLayout = new QVBoxLayout();
  84. verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
  85. mdiArea = new QMdiArea(centralwidget);
  86. mdiArea->setObjectName(QStringLiteral("mdiArea"));
  87. verticalLayout->addWidget(mdiArea);
  88. verticalLayout_2->setContentsMargins(1, 1, 1, 1);
  89. verticalLayout_2->addLayout(verticalLayout);
  90. setCentralWidget(centralwidget);
  91. centralwidget->layout()->setContentsMargins(1, 1, 1, 1);
  92. prevChild = nullptr;
  93. createConsole();
  94. connect(mdiArea, &QMdiArea::subWindowActivated, this,
  95. &CMainWindow::slotRefreshMenus);
  96. frmSettings = new CFrmSettings();
  97. actions();
  98. menus();
  99. toolBars();
  100. statusBar();
  101. updateMenus();
  102. readSettings();
  103. setWindowTitle(tr("GVEdit"));
  104. this->resize(1024, 900);
  105. this->move(0, 0);
  106. setUnifiedTitleAndToolBarOnMac(true);
  107. QComboBox *cb =
  108. frmSettings->findChild<QComboBox *>(QStringLiteral("cbLayout"));
  109. dfltLayoutIdx = LoadPlugins(*cb, frmSettings->gvc, "layout", {}, "dot");
  110. cb = frmSettings->findChild<QComboBox *>(QStringLiteral("cbExtension"));
  111. dfltRenderIdx = LoadPlugins(*cb, frmSettings->gvc, "device", xtra, "png");
  112. statusBar()->showMessage(tr("Ready"));
  113. setWindowIcon(QIcon(QStringLiteral(":/images/icon.png")));
  114. // load files specified in command line , one time task
  115. for (const QString &file : files) {
  116. addFile(file);
  117. }
  118. }
  119. void CMainWindow::closeEvent(QCloseEvent *event) {
  120. mdiArea->closeAllSubWindows();
  121. if (mdiArea->currentSubWindow()) {
  122. event->ignore();
  123. } else {
  124. writeSettings();
  125. event->accept();
  126. }
  127. }
  128. void CMainWindow::slotNew() {
  129. MdiChild *child = createMdiChild();
  130. child->newFile();
  131. child->show();
  132. }
  133. void CMainWindow::addFile(const QString &fileName) {
  134. if (!fileName.isEmpty()) {
  135. QMdiSubWindow *existing = findMdiChild(fileName);
  136. if (existing) {
  137. mdiArea->setActiveSubWindow(existing);
  138. return;
  139. }
  140. MdiChild *child = createMdiChild();
  141. if (child->loadFile(fileName)) {
  142. statusBar()->showMessage(tr("File loaded"), 2000);
  143. child->show();
  144. slotRun(child);
  145. } else {
  146. child->close();
  147. }
  148. }
  149. }
  150. void CMainWindow::slotOpen() {
  151. QStringList filters{
  152. QStringLiteral("*.cpp"),
  153. QStringLiteral("*.cxx"),
  154. QStringLiteral("*.cc"),
  155. };
  156. QFileDialog fd;
  157. fd.setNameFilter(QStringLiteral("XML (*.xml)"));
  158. QString fileName = fd.getOpenFileName(this);
  159. addFile(fileName);
  160. }
  161. void CMainWindow::slotSave() {
  162. if (activeMdiChild() && activeMdiChild()->save())
  163. statusBar()->showMessage(tr("File saved"), 2000);
  164. }
  165. void CMainWindow::slotSaveAs() {
  166. if (activeMdiChild() && activeMdiChild()->saveAs())
  167. statusBar()->showMessage(tr("File saved"), 2000);
  168. }
  169. void CMainWindow::slotCut() {
  170. if (activeMdiChild())
  171. activeMdiChild()->cut();
  172. }
  173. void CMainWindow::slotCopy() {
  174. if (activeMdiChild())
  175. activeMdiChild()->copy();
  176. }
  177. void CMainWindow::slotPaste() {
  178. if (activeMdiChild())
  179. activeMdiChild()->paste();
  180. }
  181. void CMainWindow::slotAbout() {
  182. QString abs(tr("<b>GVEdit</b> Graph File Editor For Graphviz"
  183. " version: 1.02\n"
  184. "Graphviz version: "));
  185. abs += tr(gvcVersion(frmSettings->gvc));
  186. QMessageBox::about(this, tr("About GVEdit"), abs);
  187. }
  188. void CMainWindow::setChild() {
  189. if (prevChild != activeMdiChild()) {
  190. const QString msg =
  191. QStringLiteral("working on %1\n").arg(activeMdiChild()->currentFile());
  192. errorPipe(msg.toLatin1().data());
  193. prevChild = activeMdiChild();
  194. }
  195. }
  196. void CMainWindow::slotSettings() {
  197. setChild();
  198. frmSettings->showSettings(activeMdiChild());
  199. }
  200. void CMainWindow::slotRun(MdiChild *m) {
  201. setChild();
  202. if (m)
  203. frmSettings->runSettings(m);
  204. else
  205. frmSettings->runSettings(activeMdiChild());
  206. }
  207. void CMainWindow::slotNewLog() { globTextEdit->clear(); }
  208. void CMainWindow::slotSaveLog() {
  209. if (globTextEdit->toPlainText().trimmed().isEmpty()) {
  210. QMessageBox::warning(this, tr("GvEdit"), tr("Nothing to save!"),
  211. QMessageBox::Ok, QMessageBox::Ok);
  212. return;
  213. }
  214. QString fileName = QFileDialog::getSaveFileName(
  215. this, tr("Open File"), QStringLiteral("/"), tr("Text File(*.*)"));
  216. if (!fileName.isEmpty()) {
  217. QFile file(fileName);
  218. if (!file.open(QFile::WriteOnly | QFile::Text)) {
  219. QMessageBox::warning(this, tr("MDI"),
  220. tr("Cannot write file %1:\n%2.")
  221. .arg(fileName)
  222. .arg(file.errorString()));
  223. return;
  224. }
  225. QTextStream out(&file);
  226. out << globTextEdit->toPlainText();
  227. }
  228. }
  229. void CMainWindow::updateFileMenu() {
  230. if (!activeMdiChild()) {
  231. saveAct->setEnabled(false);
  232. saveAsAct->setEnabled(false);
  233. pasteAct->setEnabled(false);
  234. closeAct->setEnabled(false);
  235. closeAllAct->setEnabled(false);
  236. tileAct->setEnabled(false);
  237. cascadeAct->setEnabled(false);
  238. nextAct->setEnabled(false);
  239. previousAct->setEnabled(false);
  240. separatorAct->setVisible(false);
  241. settingsAct->setEnabled(false);
  242. layoutAct->setEnabled(false);
  243. } else {
  244. saveAct->setEnabled(true);
  245. saveAsAct->setEnabled(true);
  246. pasteAct->setEnabled(true);
  247. closeAct->setEnabled(true);
  248. closeAllAct->setEnabled(true);
  249. tileAct->setEnabled(true);
  250. cascadeAct->setEnabled(true);
  251. nextAct->setEnabled(true);
  252. previousAct->setEnabled(true);
  253. separatorAct->setVisible(true);
  254. settingsAct->setEnabled(true);
  255. layoutAct->setEnabled(true);
  256. if (activeMdiChild()->textCursor().hasSelection()) {
  257. cutAct->setEnabled(true);
  258. copyAct->setEnabled(true);
  259. } else {
  260. cutAct->setEnabled(false);
  261. copyAct->setEnabled(false);
  262. }
  263. }
  264. }
  265. void CMainWindow::slotRefreshMenus() { updateMenus(); }
  266. void CMainWindow::updateMenus() {
  267. this->updateFileMenu();
  268. this->updateWindowMenu();
  269. }
  270. void CMainWindow::updateWindowMenu() {
  271. mWindow->clear();
  272. mWindow->addAction(closeAct);
  273. mWindow->addAction(closeAllAct);
  274. mWindow->addSeparator();
  275. mWindow->addAction(tileAct);
  276. mWindow->addAction(cascadeAct);
  277. mWindow->addSeparator();
  278. mWindow->addAction(nextAct);
  279. mWindow->addAction(previousAct);
  280. mWindow->addAction(separatorAct);
  281. QList<QMdiSubWindow *> windows = mdiArea->subWindowList();
  282. separatorAct->setVisible(!windows.isEmpty());
  283. for (int i = 0; i < windows.size(); ++i) {
  284. QMdiSubWindow *window = windows.at(i);
  285. if (window->widget()->inherits("MdiChild")) {
  286. MdiChild *child = qobject_cast<MdiChild *>(window->widget());
  287. QString text;
  288. if (i < 9) {
  289. text = tr("&%1 %2").arg(i + 1).arg(child->userFriendlyCurrentFile());
  290. } else {
  291. text = tr("%1 %2").arg(i + 1).arg(child->userFriendlyCurrentFile());
  292. }
  293. QAction *action = mWindow->addAction(text);
  294. action->setCheckable(true);
  295. action->setChecked(child == activeMdiChild());
  296. connect(action, &QAction::triggered, this,
  297. [this, window] { activateChild(window); });
  298. }
  299. }
  300. }
  301. MdiChild *CMainWindow::createMdiChild() {
  302. MdiChild *child = new MdiChild;
  303. child->parentFrm = this;
  304. QMdiSubWindow *s = mdiArea->addSubWindow(child);
  305. s->resize(800, 600);
  306. s->move(mdiArea->subWindowList().count() * 5,
  307. mdiArea->subWindowList().count() * 5);
  308. connect(child, &MdiChild::copyAvailable, cutAct, &QAction::setEnabled);
  309. connect(child, &MdiChild::copyAvailable, copyAct, &QAction::setEnabled);
  310. child->layoutIdx = dfltLayoutIdx;
  311. child->renderIdx = dfltRenderIdx;
  312. return child;
  313. }
  314. void CMainWindow::actions() {
  315. newAct =
  316. new QAction(QIcon(QStringLiteral(":/images/new.png")), tr("&New"), this);
  317. newAct->setShortcuts(QKeySequence::New);
  318. newAct->setStatusTip(tr("Create a new file"));
  319. connect(newAct, &QAction::triggered, this, &CMainWindow::slotNew);
  320. openAct = new QAction(QIcon(QStringLiteral(":/images/open.png")),
  321. tr("&Open..."), this);
  322. openAct->setShortcuts(QKeySequence::Open);
  323. openAct->setStatusTip(tr("Open an existing file"));
  324. connect(openAct, &QAction::triggered, this, &CMainWindow::slotOpen);
  325. saveAct = new QAction(QIcon(QStringLiteral(":/images/save.png")), tr("&Save"),
  326. this);
  327. saveAct->setShortcuts(QKeySequence::Save);
  328. saveAct->setStatusTip(tr("Save the document to disk"));
  329. connect(saveAct, &QAction::triggered, this, &CMainWindow::slotSave);
  330. saveAsAct = new QAction(tr("Save &As..."), this);
  331. saveAsAct->setShortcuts(QKeySequence::SaveAs);
  332. saveAsAct->setStatusTip(tr("Save the document under a new name"));
  333. connect(saveAsAct, &QAction::triggered, this, &CMainWindow::slotSaveAs);
  334. exitAct = new QAction(tr("E&xit"), this);
  335. exitAct->setShortcuts(QKeySequence::Quit);
  336. exitAct->setStatusTip(tr("Exit the application"));
  337. connect(exitAct, &QAction::triggered, qApp, &QApplication::closeAllWindows);
  338. cutAct =
  339. new QAction(QIcon(QStringLiteral(":/images/cut.png")), tr("Cu&t"), this);
  340. cutAct->setShortcuts(QKeySequence::Cut);
  341. cutAct->setStatusTip(tr("Cut the current selection's contents to the "
  342. "clipboard"));
  343. connect(cutAct, &QAction::triggered, this, &CMainWindow::slotCut);
  344. copyAct = new QAction(QIcon(QStringLiteral(":/images/copy.png")), tr("&Copy"),
  345. this);
  346. copyAct->setShortcuts(QKeySequence::Copy);
  347. copyAct->setStatusTip(tr("Copy the current selection's contents to the "
  348. "clipboard"));
  349. connect(copyAct, &QAction::triggered, this, &CMainWindow::slotCopy);
  350. pasteAct = new QAction(QIcon(QStringLiteral(":/images/paste.png")),
  351. tr("&Paste"), this);
  352. pasteAct->setShortcuts(QKeySequence::Paste);
  353. pasteAct->setStatusTip(tr("Paste the clipboard's contents into the current "
  354. "selection"));
  355. connect(pasteAct, &QAction::triggered, this, &CMainWindow::slotPaste);
  356. closeAct = new QAction(tr("Cl&ose"), this);
  357. closeAct->setStatusTip(tr("Close the active window"));
  358. connect(closeAct, &QAction::triggered, mdiArea,
  359. &QMdiArea::closeActiveSubWindow);
  360. closeAllAct = new QAction(tr("Close &All"), this);
  361. closeAllAct->setStatusTip(tr("Close all the windows"));
  362. connect(closeAllAct, &QAction::triggered, mdiArea,
  363. &QMdiArea::closeAllSubWindows);
  364. tileAct = new QAction(tr("&Tile"), this);
  365. tileAct->setStatusTip(tr("Tile the windows"));
  366. connect(tileAct, &QAction::triggered, mdiArea, &QMdiArea::tileSubWindows);
  367. cascadeAct = new QAction(tr("&Cascade"), this);
  368. cascadeAct->setStatusTip(tr("Cascade the windows"));
  369. connect(cascadeAct, &QAction::triggered, mdiArea,
  370. &QMdiArea::cascadeSubWindows);
  371. nextAct = new QAction(tr("Ne&xt"), this);
  372. nextAct->setShortcuts(QKeySequence::NextChild);
  373. nextAct->setStatusTip(tr("Move the focus to the next window"));
  374. connect(nextAct, &QAction::triggered, mdiArea,
  375. &QMdiArea::activateNextSubWindow);
  376. previousAct = new QAction(tr("Pre&vious"), this);
  377. previousAct->setShortcuts(QKeySequence::PreviousChild);
  378. previousAct->setStatusTip(tr("Move the focus to the previous window"));
  379. connect(previousAct, &QAction::triggered, mdiArea,
  380. &QMdiArea::activatePreviousSubWindow);
  381. separatorAct = new QAction(this);
  382. separatorAct->setSeparator(true);
  383. aboutAct = new QAction(tr("&About"), this);
  384. aboutAct->setStatusTip(tr("Show the application's About box"));
  385. connect(aboutAct, &QAction::triggered, this, &CMainWindow::slotAbout);
  386. settingsAct = new QAction(QIcon(QStringLiteral(":/images/settings.png")),
  387. tr("Settings"), this);
  388. settingsAct->setStatusTip(tr("Show Graphviz Settings"));
  389. connect(settingsAct, &QAction::triggered, this, &CMainWindow::slotSettings);
  390. settingsAct->setShortcut(QKeySequence(Qt::SHIFT | Qt::Key_F5));
  391. layoutAct = new QAction(QIcon(QStringLiteral(":/images/run.png")),
  392. tr("Layout"), this);
  393. layoutAct->setStatusTip(tr("Layout the active graph"));
  394. connect(layoutAct, &QAction::triggered, this, [this] { slotRun(); });
  395. layoutAct->setShortcut(QKeySequence(Qt::Key_F5));
  396. }
  397. void CMainWindow::menus() {
  398. mFile = menuBar()->addMenu(tr("&File"));
  399. mEdit = menuBar()->addMenu(tr("&Edit"));
  400. mWindow = menuBar()->addMenu(tr("&Window"));
  401. mGraph = menuBar()->addMenu(tr("&Graph"));
  402. mHelp = menuBar()->addMenu(tr("&Help"));
  403. mFile->addAction(newAct);
  404. mFile->addAction(openAct);
  405. mFile->addAction(saveAct);
  406. mFile->addAction(saveAsAct);
  407. mFile->addSeparator();
  408. mFile->addAction(exitAct);
  409. mEdit->addAction(cutAct);
  410. mEdit->addAction(copyAct);
  411. mEdit->addAction(pasteAct);
  412. mGraph->addAction(settingsAct);
  413. mGraph->addAction(layoutAct);
  414. mGraph->addSeparator();
  415. updateWindowMenu();
  416. connect(mWindow, &QMenu::aboutToShow, this, &CMainWindow::slotRefreshMenus);
  417. mHelp->addAction(aboutAct);
  418. }
  419. void CMainWindow::toolBars() {
  420. tbFile = addToolBar(tr("File"));
  421. tbFile->addAction(newAct);
  422. tbFile->addAction(openAct);
  423. tbFile->addAction(saveAct);
  424. tbEdit = addToolBar(tr("Edit"));
  425. tbEdit->addAction(cutAct);
  426. tbEdit->addAction(copyAct);
  427. tbEdit->addAction(pasteAct);
  428. tbGraph = addToolBar(tr("Graph"));
  429. tbGraph->addAction(settingsAct);
  430. tbGraph->addAction(layoutAct);
  431. }
  432. void CMainWindow::readSettings() {
  433. // first try new settings
  434. {
  435. QSettings settings(QStringLiteral("Graphviz"), QStringLiteral("gvedit"));
  436. if (settings.contains(QStringLiteral("pos")) &&
  437. settings.contains(QStringLiteral("size"))) {
  438. QPoint pos =
  439. settings.value(QStringLiteral("pos"), QPoint(200, 200)).toPoint();
  440. QSize size =
  441. settings.value(QStringLiteral("size"), QSize(400, 400)).toSize();
  442. move(pos);
  443. resize(size);
  444. return;
  445. }
  446. }
  447. // fall back to old settings
  448. QSettings settings(QStringLiteral("Trolltech"),
  449. QStringLiteral("MDI Example"));
  450. QPoint pos =
  451. settings.value(QStringLiteral("pos"), QPoint(200, 200)).toPoint();
  452. QSize size = settings.value(QStringLiteral("size"), QSize(400, 400)).toSize();
  453. move(pos);
  454. resize(size);
  455. }
  456. void CMainWindow::writeSettings() {
  457. QSettings settings(QStringLiteral("Graphviz"), QStringLiteral("gvedit"));
  458. settings.setValue(QStringLiteral("pos"), pos());
  459. settings.setValue(QStringLiteral("size"), size());
  460. }
  461. MdiChild *CMainWindow::activeMdiChild() {
  462. if (QMdiSubWindow *activeSubWindow = mdiArea->activeSubWindow()) {
  463. if (activeSubWindow->widget()->inherits("MdiChild"))
  464. return qobject_cast<MdiChild *>(activeSubWindow->widget());
  465. return qobject_cast<ImageViewer *>(activeSubWindow->widget())->graphWindow;
  466. }
  467. return 0;
  468. }
  469. QMdiSubWindow *CMainWindow::findMdiChild(const QString &fileName) {
  470. QString canonicalFilePath = QFileInfo(fileName).canonicalFilePath();
  471. foreach (QMdiSubWindow *window, mdiArea->subWindowList()) {
  472. if (window->widget()->inherits("MdiChild")) {
  473. MdiChild *mdiChild = qobject_cast<MdiChild *>(window->widget());
  474. if (mdiChild->currentFile() == canonicalFilePath)
  475. return window;
  476. } else {
  477. MdiChild *mdiChild =
  478. qobject_cast<ImageViewer *>(window->widget())->graphWindow;
  479. if (mdiChild->currentFile() == canonicalFilePath)
  480. return window;
  481. }
  482. }
  483. return 0;
  484. }
  485. void CMainWindow::activateChild(QWidget *window) {
  486. if (!window)
  487. return;
  488. mdiArea->setActiveSubWindow(qobject_cast<QMdiSubWindow *>(window));
  489. }