mainwindow.cpp Example File

graphicsview/diagramscene/mainwindow.cpp
/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/
#include "arrow.h" #include "diagramitem.h" #include "diagramscene.h" #include "diagramtextitem.h" #include "mainwindow.h" #include <QtWidgets> const int InsertTextButton = 10; MainWindow::MainWindow() { createActions(); createToolBox(); createMenus(); scene = new DiagramScene(itemMenu, this); scene->setSceneRect(QRectF(0, 0, 5000, 5000)); connect(scene, SIGNAL(itemInserted(DiagramItem*)), this, SLOT(itemInserted(DiagramItem*))); connect(scene, SIGNAL(textInserted(QGraphicsTextItem*)), this, SLOT(textInserted(QGraphicsTextItem*))); connect(scene, SIGNAL(itemSelected(QGraphicsItem*)), this, SLOT(itemSelected(QGraphicsItem*))); createToolbars(); QHBoxLayout *layout = new QHBoxLayout; layout->addWidget(toolBox); view = new QGraphicsView(scene); layout->addWidget(view); QWidget *widget = new QWidget; widget->setLayout(layout); setCentralWidget(widget); setWindowTitle(tr("Diagramscene")); setUnifiedTitleAndToolBarOnMac(true); } void MainWindow::backgroundButtonGroupClicked(QAbstractButton *button) { QList<QAbstractButton *> buttons = backgroundButtonGroup->buttons(); foreach (QAbstractButton *myButton, buttons) { if (myButton != button) button->setChecked(false); } QString text = button->text(); if (text == tr("Blue Grid")) scene->setBackgroundBrush(QPixmap(":/images/background1.png")); else if (text == tr("White Grid")) scene->setBackgroundBrush(QPixmap(":/images/background2.png")); else if (text == tr("Gray Grid")) scene->setBackgroundBrush(QPixmap(":/images/background3.png")); else scene->setBackgroundBrush(QPixmap(":/images/background4.png")); scene->update(); view->update(); } void MainWindow::buttonGroupClicked(int id) { QList<QAbstractButton *> buttons = buttonGroup->buttons(); foreach (QAbstractButton *button, buttons) { if (buttonGroup->button(id) != button) button->setChecked(false); } if (id == InsertTextButton) { scene->setMode(DiagramScene::InsertText); } else { scene->setItemType(DiagramItem::DiagramType(id)); scene->setMode(DiagramScene::InsertItem); } } void MainWindow::deleteItem() { foreach (QGraphicsItem *item, scene->selectedItems()) { if (item->type() == Arrow::Type) { scene->removeItem(item); Arrow *arrow = qgraphicsitem_cast<Arrow *>(item); arrow->startItem()->removeArrow(arrow); arrow->endItem()->removeArrow(arrow); delete item; } } foreach (QGraphicsItem *item, scene->selectedItems()) { if (item->type() == DiagramItem::Type) qgraphicsitem_cast<DiagramItem *>(item)->removeArrows(); scene->removeItem(item); delete item; } } void MainWindow::pointerGroupClicked(int) { scene->setMode(DiagramScene::Mode(pointerTypeGroup->checkedId())); } void MainWindow::bringToFront() { if (scene->selectedItems().isEmpty()) return; QGraphicsItem *selectedItem = scene->selectedItems().first(); QList<QGraphicsItem *> overlapItems = selectedItem->collidingItems(); qreal zValue = 0; foreach (QGraphicsItem *item, overlapItems) { if (item->zValue() >= zValue && item->type() == DiagramItem::Type) zValue = item->zValue() + 0.1; } selectedItem->setZValue(zValue); } void MainWindow::sendToBack() { if (scene->selectedItems().isEmpty()) return; QGraphicsItem *selectedItem = scene->selectedItems().first(); QList<QGraphicsItem *> overlapItems = selectedItem->collidingItems(); qreal zValue = 0; foreach (QGraphicsItem *item, overlapItems) { if (item->zValue() <= zValue && item->type() == DiagramItem::Type) zValue = item->zValue() - 0.1; } selectedItem->setZValue(zValue); } void MainWindow::itemInserted(DiagramItem *item) { pointerTypeGroup->button(int(DiagramScene::MoveItem))->setChecked(true); scene->setMode(DiagramScene::Mode(pointerTypeGroup->checkedId())); buttonGroup->button(int(item->diagramType()))->setChecked(false); } void MainWindow::textInserted(QGraphicsTextItem *) { buttonGroup->button(InsertTextButton)->setChecked(false); scene->setMode(DiagramScene::Mode(pointerTypeGroup->checkedId())); } void MainWindow::currentFontChanged(const QFont &) { handleFontChange(); } void MainWindow::fontSizeChanged(const QString &) { handleFontChange(); } void MainWindow::sceneScaleChanged(const QString &scale) { double newScale = scale.left(scale.indexOf(tr("%"))).toDouble() / 100.0; QMatrix oldMatrix = view->matrix(); view->resetMatrix(); view->translate(oldMatrix.dx(), oldMatrix.dy()); view->scale(newScale, newScale); } void MainWindow::textColorChanged() { textAction = qobject_cast<QAction *>(sender()); fontColorToolButton->setIcon(createColorToolButtonIcon( ":/images/textpointer.png", qvariant_cast<QColor>(textAction->data()))); textButtonTriggered(); } void MainWindow::itemColorChanged() { fillAction = qobject_cast<QAction *>(sender()); fillColorToolButton->setIcon(createColorToolButtonIcon( ":/images/floodfill.png", qvariant_cast<QColor>(fillAction->data()))); fillButtonTriggered(); } void MainWindow::lineColorChanged() { lineAction = qobject_cast<QAction *>(sender()); lineColorToolButton->setIcon(createColorToolButtonIcon( ":/images/linecolor.png", qvariant_cast<QColor>(lineAction->data()))); lineButtonTriggered(); } void MainWindow::textButtonTriggered() { scene->setTextColor(qvariant_cast<QColor>(textAction->data())); } void MainWindow::fillButtonTriggered() { scene->setItemColor(qvariant_cast<QColor>(fillAction->data())); } void MainWindow::lineButtonTriggered() { scene->setLineColor(qvariant_cast<QColor>(lineAction->data())); } void MainWindow::handleFontChange() { QFont font = fontCombo->currentFont(); font.setPointSize(fontSizeCombo->currentText().toInt()); font.setWeight(boldAction->isChecked() ? QFont::Bold : QFont::Normal); font.setItalic(italicAction->isChecked()); font.setUnderline(underlineAction->isChecked()); scene->setFont(font); } void MainWindow::itemSelected(QGraphicsItem *item) { DiagramTextItem *textItem = qgraphicsitem_cast<DiagramTextItem *>(item); QFont font = textItem->font(); fontCombo->setCurrentFont(font); fontSizeCombo->setEditText(QString().setNum(font.pointSize())); boldAction->setChecked(font.weight() == QFont::Bold); italicAction->setChecked(font.italic()); underlineAction->setChecked(font.underline()); } void MainWindow::about() { QMessageBox::about(this, tr("About Diagram Scene"), tr("The <b>Diagram Scene</b> example shows " "use of the graphics framework.")); } void MainWindow::createToolBox() { buttonGroup = new QButtonGroup(this); buttonGroup->setExclusive(false); connect(buttonGroup, SIGNAL(buttonClicked(int)), this, SLOT(buttonGroupClicked(int))); QGridLayout *layout = new QGridLayout; layout->addWidget(createCellWidget(tr("Conditional"), DiagramItem::Conditional), 0, 0); layout->addWidget(createCellWidget(tr("Process"), DiagramItem::Step),0, 1); layout->addWidget(createCellWidget(tr("Input/Output"), DiagramItem::Io), 1, 0); QToolButton *textButton = new QToolButton; textButton->setCheckable(true); buttonGroup->addButton(textButton, InsertTextButton); textButton->setIcon(QIcon(QPixmap(":/images/textpointer.png"))); textButton->setIconSize(QSize(50, 50)); QGridLayout *textLayout = new QGridLayout; textLayout->addWidget(textButton, 0, 0, Qt::AlignHCenter); textLayout->addWidget(new QLabel(tr("Text")), 1, 0, Qt::AlignCenter); QWidget *textWidget = new QWidget; textWidget->setLayout(textLayout); layout->addWidget(textWidget, 1, 1); layout->setRowStretch(3, 10); layout->setColumnStretch(2, 10); QWidget *itemWidget = new QWidget; itemWidget->setLayout(layout); backgroundButtonGroup = new QButtonGroup(this); connect(backgroundButtonGroup, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(backgroundButtonGroupClicked(QAbstractButton*))); QGridLayout *backgroundLayout = new QGridLayout; backgroundLayout->addWidget(createBackgroundCellWidget(tr("Blue Grid"), ":/images/background1.png"), 0, 0); backgroundLayout->addWidget(createBackgroundCellWidget(tr("White Grid"), ":/images/background2.png"), 0, 1); backgroundLayout->addWidget(createBackgroundCellWidget(tr("Gray Grid"), ":/images/background3.png"), 1, 0); backgroundLayout->addWidget(createBackgroundCellWidget(tr("No Grid"), ":/images/background4.png"), 1, 1); backgroundLayout->setRowStretch(2, 10); backgroundLayout->setColumnStretch(2, 10); QWidget *backgroundWidget = new QWidget; backgroundWidget->setLayout(backgroundLayout); toolBox = new QToolBox; toolBox->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Ignored)); toolBox->setMinimumWidth(itemWidget->sizeHint().width()); toolBox->addItem(itemWidget, tr("Basic Flowchart Shapes")); toolBox->addItem(backgroundWidget, tr("Backgrounds")); } void MainWindow::createActions() { toFrontAction = new QAction(QIcon(":/images/bringtofront.png"), tr("Bring to &Front"), this); toFrontAction->setShortcut(tr("Ctrl+F")); toFrontAction->setStatusTip(tr("Bring item to front")); connect(toFrontAction, SIGNAL(triggered()), this, SLOT(bringToFront())); sendBackAction = new QAction(QIcon(":/images/sendtoback.png"), tr("Send to &Back"), this); sendBackAction->setShortcut(tr("Ctrl+T")); sendBackAction->setStatusTip(tr("Send item to back")); connect(sendBackAction, SIGNAL(triggered()), this, SLOT(sendToBack())); deleteAction = new QAction(QIcon(":/images/delete.png"), tr("&Delete"), this); deleteAction->setShortcut(tr("Delete")); deleteAction->setStatusTip(tr("Delete item from diagram")); connect(deleteAction, SIGNAL(triggered()), this, SLOT(deleteItem())); exitAction = new QAction(tr("E&xit"), this); exitAction->setShortcuts(QKeySequence::Quit); exitAction->setStatusTip(tr("Quit Scenediagram example")); connect(exitAction, SIGNAL(triggered()), this, SLOT(close())); boldAction = new QAction(tr("Bold"), this); boldAction->setCheckable(true); QPixmap pixmap(":/images/bold.png"); boldAction->setIcon(QIcon(pixmap)); boldAction->setShortcut(tr("Ctrl+B")); connect(boldAction, SIGNAL(triggered()), this, SLOT(handleFontChange())); italicAction = new QAction(QIcon(":/images/italic.png"), tr("Italic"), this); italicAction->setCheckable(true); italicAction->setShortcut(tr("Ctrl+I")); connect(italicAction, SIGNAL(triggered()), this, SLOT(handleFontChange())); underlineAction = new QAction(QIcon(":/images/underline.png"), tr("Underline"), this); underlineAction->setCheckable(true); underlineAction->setShortcut(tr("Ctrl+U")); connect(underlineAction, SIGNAL(triggered()), this, SLOT(handleFontChange())); aboutAction = new QAction(tr("A&bout"), this); aboutAction->setShortcut(tr("F1")); connect(aboutAction, SIGNAL(triggered()), this, SLOT(about())); } void MainWindow::createMenus() { fileMenu = menuBar()->addMenu(tr("&File")); fileMenu->addAction(exitAction); itemMenu = menuBar()->addMenu(tr("&Item")); itemMenu->addAction(deleteAction); itemMenu->addSeparator(); itemMenu->addAction(toFrontAction); itemMenu->addAction(sendBackAction); aboutMenu = menuBar()->addMenu(tr("&Help")); aboutMenu->addAction(aboutAction); } void MainWindow::createToolbars() { editToolBar = addToolBar(tr("Edit")); editToolBar->addAction(deleteAction); editToolBar->addAction(toFrontAction); editToolBar->addAction(sendBackAction); fontCombo = new QFontComboBox(); connect(fontCombo, SIGNAL(currentFontChanged(QFont)), this, SLOT(currentFontChanged(QFont))); fontSizeCombo = new QComboBox; fontSizeCombo->setEditable(true); for (int i = 8; i < 30; i = i + 2) fontSizeCombo->addItem(QString().setNum(i)); QIntValidator *validator = new QIntValidator(2, 64, this); fontSizeCombo->setValidator(validator); connect(fontSizeCombo, SIGNAL(currentIndexChanged(QString)), this, SLOT(fontSizeChanged(QString))); fontColorToolButton = new QToolButton; fontColorToolButton->setPopupMode(QToolButton::MenuButtonPopup); fontColorToolButton->setMenu(createColorMenu(SLOT(textColorChanged()), Qt::black)); textAction = fontColorToolButton->menu()->defaultAction(); fontColorToolButton->setIcon(createColorToolButtonIcon(":/images/textpointer.png", Qt::black)); fontColorToolButton->setAutoFillBackground(true); connect(fontColorToolButton, SIGNAL(clicked()), this, SLOT(textButtonTriggered())); fillColorToolButton = new QToolButton; fillColorToolButton->setPopupMode(QToolButton::MenuButtonPopup); fillColorToolButton->setMenu(createColorMenu(SLOT(itemColorChanged()), Qt::white)); fillAction = fillColorToolButton->menu()->defaultAction(); fillColorToolButton->setIcon(createColorToolButtonIcon( ":/images/floodfill.png", Qt::white)); connect(fillColorToolButton, SIGNAL(clicked()), this, SLOT(fillButtonTriggered())); lineColorToolButton = new QToolButton; lineColorToolButton->setPopupMode(QToolButton::MenuButtonPopup); lineColorToolButton->setMenu(createColorMenu(SLOT(lineColorChanged()), Qt::black)); lineAction = lineColorToolButton->menu()->defaultAction(); lineColorToolButton->setIcon(createColorToolButtonIcon( ":/images/linecolor.png", Qt::black)); connect(lineColorToolButton, SIGNAL(clicked()), this, SLOT(lineButtonTriggered())); textToolBar = addToolBar(tr("Font")); textToolBar->addWidget(fontCombo); textToolBar->addWidget(fontSizeCombo); textToolBar->addAction(boldAction); textToolBar->addAction(italicAction); textToolBar->addAction(underlineAction); colorToolBar = addToolBar(tr("Color")); colorToolBar->addWidget(fontColorToolButton); colorToolBar->addWidget(fillColorToolButton); colorToolBar->addWidget(lineColorToolButton); QToolButton *pointerButton = new QToolButton; pointerButton->setCheckable(true); pointerButton->setChecked(true); pointerButton->setIcon(QIcon(":/images/pointer.png")); QToolButton *linePointerButton = new QToolButton; linePointerButton->setCheckable(true); linePointerButton->setIcon(QIcon(":/images/linepointer.png")); pointerTypeGroup = new QButtonGroup(this); pointerTypeGroup->addButton(pointerButton, int(DiagramScene::MoveItem)); pointerTypeGroup->addButton(linePointerButton, int(DiagramScene::InsertLine)); connect(pointerTypeGroup, SIGNAL(buttonClicked(int)), this, SLOT(pointerGroupClicked(int))); sceneScaleCombo = new QComboBox; QStringList scales; scales << tr("50%") << tr("75%") << tr("100%") << tr("125%") << tr("150%"); sceneScaleCombo->addItems(scales); sceneScaleCombo->setCurrentIndex(2); connect(sceneScaleCombo, SIGNAL(currentIndexChanged(QString)), this, SLOT(sceneScaleChanged(QString))); pointerToolbar = addToolBar(tr("Pointer type")); pointerToolbar->addWidget(pointerButton); pointerToolbar->addWidget(linePointerButton); pointerToolbar->addWidget(sceneScaleCombo); } QWidget *MainWindow::createBackgroundCellWidget(const QString &text, const QString &image) { QToolButton *button = new QToolButton; button->setText(text); button->setIcon(QIcon(image)); button->setIconSize(QSize(50, 50)); button->setCheckable(true); backgroundButtonGroup->addButton(button); QGridLayout *layout = new QGridLayout; layout->addWidget(button, 0, 0, Qt::AlignHCenter); layout->addWidget(new QLabel(text), 1, 0, Qt::AlignCenter); QWidget *widget = new QWidget; widget->setLayout(layout); return widget; } QWidget *MainWindow::createCellWidget(const QString &text, DiagramItem::DiagramType type) { DiagramItem item(type, itemMenu); QIcon icon(item.image()); QToolButton *button = new QToolButton; button->setIcon(icon); button->setIconSize(QSize(50, 50)); button->setCheckable(true); buttonGroup->addButton(button, int(type)); QGridLayout *layout = new QGridLayout; layout->addWidget(button, 0, 0, Qt::AlignHCenter); layout->addWidget(new QLabel(text), 1, 0, Qt::AlignCenter); QWidget *widget = new QWidget; widget->setLayout(layout); return widget; } QMenu *MainWindow::createColorMenu(const char *slot, QColor defaultColor) { QList<QColor> colors; colors << Qt::black << Qt::white << Qt::red << Qt::blue << Qt::yellow; QStringList names; names << tr("black") << tr("white") << tr("red") << tr("blue") << tr("yellow"); QMenu *colorMenu = new QMenu(this); for (int i = 0; i < colors.count(); ++i) { QAction *action = new QAction(names.at(i), this); action->setData(colors.at(i)); action->setIcon(createColorIcon(colors.at(i))); connect(action, SIGNAL(triggered()), this, slot); colorMenu->addAction(action); if (colors.at(i) == defaultColor) colorMenu->setDefaultAction(action); } return colorMenu; } QIcon MainWindow::createColorToolButtonIcon(const QString &imageFile, QColor color) { QPixmap pixmap(50, 80); pixmap.fill(Qt::transparent); QPainter painter(&pixmap); QPixmap image(imageFile); // Draw icon centred horizontally on button. QRect target(4, 0, 42, 43); QRect source(0, 0, 42, 43); painter.fillRect(QRect(0, 60, 50, 80), color); painter.drawPixmap(target, image, source); return QIcon(pixmap); } QIcon MainWindow::createColorIcon(QColor color) { QPixmap pixmap(20, 20); QPainter painter(&pixmap); painter.setPen(Qt::NoPen); painter.fillRect(QRect(0, 0, 20, 20), color); return QIcon(pixmap); }