/**************************************************************************** ** ** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved. ** ** This file is part of the example classes of the Qt Toolkit. ** ** This file may be used under the terms of the GNU General Public ** License versions 2.0 or 3.0 as published by the Free Software ** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Alternatively you may (at ** your option) use any later version of the GNU General Public ** License if such license has been publicly approved by Trolltech ASA ** (or its successors, if any) and the KDE Free Qt Foundation. In ** addition, as a special exception, Trolltech gives you certain ** additional rights. These rights are described in the Trolltech GPL ** Exception version 1.1, which can be found at ** http://www.trolltech.com/products/qt/gplexception/ and in the file ** GPL_EXCEPTION.txt in this package. ** ** Please review the following information to ensure GNU General ** Public Licensing requirements will be met: ** http://trolltech.com/products/qt/licenses/licensing/opensource/. If ** you are unsure which license is appropriate for your use, please ** review the following information: ** http://trolltech.com/products/qt/licenses/licensing/licensingoverview ** or contact the sales department at sales@trolltech.com. ** ** In addition, as a special exception, Trolltech, as the sole ** copyright holder for Qt Designer, grants users of the Qt/Eclipse ** Integration plug-in the right for the Qt/Eclipse Integration to ** link to functionality provided by Qt Designer and its related ** libraries. ** ** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, ** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE. Trolltech reserves all rights not expressly ** granted herein. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ****************************************************************************/ #include <QtGui> #include "mainwindow.h" #include "mdichild.h" MainWindow::MainWindow() { mdiArea = new QMdiArea; setCentralWidget(mdiArea); connect(mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow *)), this, SLOT(updateMenus())); windowMapper = new QSignalMapper(this); connect(windowMapper, SIGNAL(mapped(QWidget *)), this, SLOT(setActiveSubWindow(QWidget *))); createActions(); createMenus(); createToolBars(); createStatusBar(); updateMenus(); readSettings(); setWindowTitle(tr("MDI")); } void MainWindow::closeEvent(QCloseEvent *event) { mdiArea->closeAllSubWindows(); if (activeMdiChild()) { event->ignore(); } else { writeSettings(); event->accept(); } } void MainWindow::newFile() { MdiChild *child = createMdiChild(); child->newFile(); child->show(); } void MainWindow::open() { QString fileName = QFileDialog::getOpenFileName(this); if (!fileName.isEmpty()) { QMdiSubWindow *existing = findMdiChild(fileName); if (existing) { mdiArea->setActiveSubWindow(existing); return; } MdiChild *child = createMdiChild(); if (child->loadFile(fileName)) { statusBar()->showMessage(tr("File loaded"), 2000); child->show(); } else { child->close(); } } } void MainWindow::save() { if (activeMdiChild() && activeMdiChild()->save()) statusBar()->showMessage(tr("File saved"), 2000); } void MainWindow::saveAs() { if (activeMdiChild() && activeMdiChild()->saveAs()) statusBar()->showMessage(tr("File saved"), 2000); } void MainWindow::cut() { if (activeMdiChild()) activeMdiChild()->cut(); } void MainWindow::copy() { if (activeMdiChild()) activeMdiChild()->copy(); } void MainWindow::paste() { if (activeMdiChild()) activeMdiChild()->paste(); } void MainWindow::about() { QMessageBox::about(this, tr("About MDI"), tr("The <b>MDI</b> example demonstrates how to write multiple " "document interface applications using Qt.")); } void MainWindow::updateMenus() { bool hasMdiChild = (activeMdiChild() != 0); saveAct->setEnabled(hasMdiChild); saveAsAct->setEnabled(hasMdiChild); pasteAct->setEnabled(hasMdiChild); closeAct->setEnabled(hasMdiChild); closeAllAct->setEnabled(hasMdiChild); tileAct->setEnabled(hasMdiChild); cascadeAct->setEnabled(hasMdiChild); nextAct->setEnabled(hasMdiChild); previousAct->setEnabled(hasMdiChild); separatorAct->setVisible(hasMdiChild); bool hasSelection = (activeMdiChild() && activeMdiChild()->textCursor().hasSelection()); cutAct->setEnabled(hasSelection); copyAct->setEnabled(hasSelection); } void MainWindow::updateWindowMenu() { windowMenu->clear(); windowMenu->addAction(closeAct); windowMenu->addAction(closeAllAct); windowMenu->addSeparator(); windowMenu->addAction(tileAct); windowMenu->addAction(cascadeAct); windowMenu->addSeparator(); windowMenu->addAction(nextAct); windowMenu->addAction(previousAct); windowMenu->addAction(separatorAct); QList<QMdiSubWindow *> windows = mdiArea->subWindowList(); separatorAct->setVisible(!windows.isEmpty()); for (int i = 0; i < windows.size(); ++i) { MdiChild *child = qobject_cast<MdiChild *>(windows.at(i)->widget()); QString text; if (i < 9) { text = tr("&%1 %2").arg(i + 1) .arg(child->userFriendlyCurrentFile()); } else { text = tr("%1 %2").arg(i + 1) .arg(child->userFriendlyCurrentFile()); } QAction *action = windowMenu->addAction(text); action->setCheckable(true); action ->setChecked(child == activeMdiChild()); connect(action, SIGNAL(triggered()), windowMapper, SLOT(map())); windowMapper->setMapping(action, windows.at(i)); } } MdiChild *MainWindow::createMdiChild() { MdiChild *child = new MdiChild; mdiArea->addSubWindow(child); connect(child, SIGNAL(copyAvailable(bool)), cutAct, SLOT(setEnabled(bool))); connect(child, SIGNAL(copyAvailable(bool)), copyAct, SLOT(setEnabled(bool))); return child; } void MainWindow::createActions() { newAct = new QAction(QIcon(":/images/new.png"), tr("&New"), this); newAct->setShortcut(tr("Ctrl+N")); newAct->setStatusTip(tr("Create a new file")); connect(newAct, SIGNAL(triggered()), this, SLOT(newFile())); openAct = new QAction(QIcon(":/images/open.png"), tr("&Open..."), this); openAct->setShortcut(tr("Ctrl+O")); openAct->setStatusTip(tr("Open an existing file")); connect(openAct, SIGNAL(triggered()), this, SLOT(open())); saveAct = new QAction(QIcon(":/images/save.png"), tr("&Save"), this); saveAct->setShortcut(tr("Ctrl+S")); saveAct->setStatusTip(tr("Save the document to disk")); connect(saveAct, SIGNAL(triggered()), this, SLOT(save())); saveAsAct = new QAction(tr("Save &As..."), this); saveAsAct->setStatusTip(tr("Save the document under a new name")); connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs())); exitAct = new QAction(tr("E&xit"), this); exitAct->setShortcut(tr("Ctrl+Q")); exitAct->setStatusTip(tr("Exit the application")); connect(exitAct, SIGNAL(triggered()), qApp, SLOT(closeAllWindows())); cutAct = new QAction(QIcon(":/images/cut.png"), tr("Cu&t"), this); cutAct->setShortcut(tr("Ctrl+X")); cutAct->setStatusTip(tr("Cut the current selection's contents to the " "clipboard")); connect(cutAct, SIGNAL(triggered()), this, SLOT(cut())); copyAct = new QAction(QIcon(":/images/copy.png"), tr("&Copy"), this); copyAct->setShortcut(tr("Ctrl+C")); copyAct->setStatusTip(tr("Copy the current selection's contents to the " "clipboard")); connect(copyAct, SIGNAL(triggered()), this, SLOT(copy())); pasteAct = new QAction(QIcon(":/images/paste.png"), tr("&Paste"), this); pasteAct->setShortcut(tr("Ctrl+V")); pasteAct->setStatusTip(tr("Paste the clipboard's contents into the current " "selection")); connect(pasteAct, SIGNAL(triggered()), this, SLOT(paste())); closeAct = new QAction(tr("Cl&ose"), this); closeAct->setShortcut(tr("Ctrl+F4")); closeAct->setStatusTip(tr("Close the active window")); connect(closeAct, SIGNAL(triggered()), mdiArea, SLOT(closeActiveSubWindow())); closeAllAct = new QAction(tr("Close &All"), this); closeAllAct->setStatusTip(tr("Close all the windows")); connect(closeAllAct, SIGNAL(triggered()), mdiArea, SLOT(closeAllSubWindows())); tileAct = new QAction(tr("&Tile"), this); tileAct->setStatusTip(tr("Tile the windows")); connect(tileAct, SIGNAL(triggered()), mdiArea, SLOT(tileSubWindows())); cascadeAct = new QAction(tr("&Cascade"), this); cascadeAct->setStatusTip(tr("Cascade the windows")); connect(cascadeAct, SIGNAL(triggered()), mdiArea, SLOT(cascadeSubWindows())); nextAct = new QAction(tr("Ne&xt"), this); nextAct->setStatusTip(tr("Move the focus to the next window")); connect(nextAct, SIGNAL(triggered()), mdiArea, SLOT(activateNextSubWindow())); previousAct = new QAction(tr("Pre&vious"), this); previousAct->setStatusTip(tr("Move the focus to the previous " "window")); connect(previousAct, SIGNAL(triggered()), mdiArea, SLOT(activatePreviousSubWindow())); separatorAct = new QAction(this); separatorAct->setSeparator(true); aboutAct = new QAction(tr("&About"), this); aboutAct->setStatusTip(tr("Show the application's About box")); connect(aboutAct, SIGNAL(triggered()), this, SLOT(about())); aboutQtAct = new QAction(tr("About &Qt"), this); aboutQtAct->setStatusTip(tr("Show the Qt library's About box")); connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt())); } void MainWindow::createMenus() { fileMenu = menuBar()->addMenu(tr("&File")); fileMenu->addAction(newAct); fileMenu->addAction(openAct); fileMenu->addAction(saveAct); fileMenu->addAction(saveAsAct); fileMenu->addSeparator(); QAction *action = fileMenu->addAction(tr("Switch layout direction")); connect(action, SIGNAL(triggered()), this, SLOT(switchLayoutDirection())); fileMenu->addAction(exitAct); editMenu = menuBar()->addMenu(tr("&Edit")); editMenu->addAction(cutAct); editMenu->addAction(copyAct); editMenu->addAction(pasteAct); windowMenu = menuBar()->addMenu(tr("&Window")); updateWindowMenu(); connect(windowMenu, SIGNAL(aboutToShow()), this, SLOT(updateWindowMenu())); menuBar()->addSeparator(); helpMenu = menuBar()->addMenu(tr("&Help")); helpMenu->addAction(aboutAct); helpMenu->addAction(aboutQtAct); } void MainWindow::createToolBars() { fileToolBar = addToolBar(tr("File")); fileToolBar->addAction(newAct); fileToolBar->addAction(openAct); fileToolBar->addAction(saveAct); editToolBar = addToolBar(tr("Edit")); editToolBar->addAction(cutAct); editToolBar->addAction(copyAct); editToolBar->addAction(pasteAct); } void MainWindow::createStatusBar() { statusBar()->showMessage(tr("Ready")); } void MainWindow::readSettings() { QSettings settings("Trolltech", "MDI Example"); QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint(); QSize size = settings.value("size", QSize(400, 400)).toSize(); move(pos); resize(size); } void MainWindow::writeSettings() { QSettings settings("Trolltech", "MDI Example"); settings.setValue("pos", pos()); settings.setValue("size", size()); } MdiChild *MainWindow::activeMdiChild() { if (QMdiSubWindow *activeSubWindow = mdiArea->activeSubWindow()) return qobject_cast<MdiChild *>(activeSubWindow->widget()); return 0; } QMdiSubWindow *MainWindow::findMdiChild(const QString &fileName) { QString canonicalFilePath = QFileInfo(fileName).canonicalFilePath(); foreach (QMdiSubWindow *window, mdiArea->subWindowList()) { MdiChild *mdiChild = qobject_cast<MdiChild *>(window->widget()); if (mdiChild->currentFile() == canonicalFilePath) return window; } return 0; } void MainWindow::switchLayoutDirection() { if (layoutDirection() == Qt::LeftToRight) qApp->setLayoutDirection(Qt::RightToLeft); else qApp->setLayoutDirection(Qt::LeftToRight); } void MainWindow::setActiveSubWindow(QWidget *window) { if (!window) return; mdiArea->setActiveSubWindow(qobject_cast<QMdiSubWindow *>(window)); }