mainwindow.cpp Example File

itemviews/pixelator/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 "imagemodel.h"
  #include "mainwindow.h"
  #include "pixeldelegate.h"

  #include <QtWidgets>
  #ifndef QT_NO_PRINTER
  #include <QPrinter>
  #include <QPrintDialog>
  #endif

  MainWindow::MainWindow()
  {
      currentPath = QDir::homePath();
      model = new ImageModel(this);

      QWidget *centralWidget = new QWidget;

      view = new QTableView;
      view->setShowGrid(false);
      view->horizontalHeader()->hide();
      view->verticalHeader()->hide();
      view->horizontalHeader()->setMinimumSectionSize(1);
      view->verticalHeader()->setMinimumSectionSize(1);
      view->setModel(model);

      PixelDelegate *delegate = new PixelDelegate(this);
      view->setItemDelegate(delegate);

      QLabel *pixelSizeLabel = new QLabel(tr("Pixel size:"));
      QSpinBox *pixelSizeSpinBox = new QSpinBox;
      pixelSizeSpinBox->setMinimum(4);
      pixelSizeSpinBox->setMaximum(32);
      pixelSizeSpinBox->setValue(12);

      QMenu *fileMenu = new QMenu(tr("&File"), this);
      QAction *openAction = fileMenu->addAction(tr("&Open..."));
      openAction->setShortcuts(QKeySequence::Open);

      printAction = fileMenu->addAction(tr("&Print..."));
      printAction->setEnabled(false);
      printAction->setShortcut(QKeySequence::Print);

      QAction *quitAction = fileMenu->addAction(tr("E&xit"));
      quitAction->setShortcuts(QKeySequence::Quit);

      QMenu *helpMenu = new QMenu(tr("&Help"), this);
      QAction *aboutAction = helpMenu->addAction(tr("&About"));

      menuBar()->addMenu(fileMenu);
      menuBar()->addSeparator();
      menuBar()->addMenu(helpMenu);

      connect(openAction, &QAction::triggered, this, &MainWindow::chooseImage);
      connect(printAction, &QAction::triggered, this, &MainWindow::printImage);
      connect(quitAction, &QAction::triggered, qApp, &QCoreApplication::quit);
      connect(aboutAction, &QAction::triggered, this, &MainWindow::showAboutBox);
      typedef void (QSpinBox::*QSpinBoxIntSignal)(int);
      connect(pixelSizeSpinBox, static_cast<QSpinBoxIntSignal>(&QSpinBox::valueChanged),
              delegate, &PixelDelegate::setPixelSize);
      connect(pixelSizeSpinBox, static_cast<QSpinBoxIntSignal>(&QSpinBox::valueChanged),
              this, &MainWindow::updateView);

      QHBoxLayout *controlsLayout = new QHBoxLayout;
      controlsLayout->addWidget(pixelSizeLabel);
      controlsLayout->addWidget(pixelSizeSpinBox);
      controlsLayout->addStretch(1);

      QVBoxLayout *mainLayout = new QVBoxLayout;
      mainLayout->addWidget(view);
      mainLayout->addLayout(controlsLayout);
      centralWidget->setLayout(mainLayout);

      setCentralWidget(centralWidget);

      setWindowTitle(tr("Pixelator"));
      resize(640, 480);
  }

  void MainWindow::chooseImage()
  {
      QString fileName = QFileDialog::getOpenFileName(this,
          tr("Choose an image"), currentPath, "*");

      if (!fileName.isEmpty())
          openImage(fileName);
  }

  void MainWindow::openImage(const QString &fileName)
  {
      QImage image;

      if (image.load(fileName)) {
          model->setImage(image);
          if (!fileName.startsWith(":/")) {
              currentPath = fileName;
              setWindowTitle(tr("%1 - Pixelator").arg(currentPath));
          }

          printAction->setEnabled(true);
          updateView();
      }
  }

  void MainWindow::printImage()
  {
  #if !defined(QT_NO_PRINTER) && !defined(QT_NO_PRINTDIALOG)
      if (model->rowCount(QModelIndex())*model->columnCount(QModelIndex()) > 90000) {
          QMessageBox::StandardButton answer;
          answer = QMessageBox::question(this, tr("Large Image Size"),
                  tr("The printed image may be very large. Are you sure that "
                     "you want to print it?"),
          QMessageBox::Yes | QMessageBox::No);
          if (answer == QMessageBox::No)
              return;
      }

      QPrinter printer(QPrinter::HighResolution);

      QPrintDialog dlg(&printer, this);
      dlg.setWindowTitle(tr("Print Image"));

      if (dlg.exec() != QDialog::Accepted) {
          return;
      }

      QPainter painter;
      painter.begin(&printer);

      int rows = model->rowCount(QModelIndex());
      int columns = model->columnCount(QModelIndex());
      int sourceWidth = (columns + 1) * ItemSize;
      int sourceHeight = (rows + 1) * ItemSize;

      painter.save();

      double xscale = printer.pageRect().width() / double(sourceWidth);
      double yscale = printer.pageRect().height() / double(sourceHeight);
      double scale = qMin(xscale, yscale);

      painter.translate(printer.paperRect().x() + printer.pageRect().width() / 2,
                        printer.paperRect().y() + printer.pageRect().height() / 2);
      painter.scale(scale, scale);
      painter.translate(-sourceWidth / 2, -sourceHeight / 2);

      QStyleOptionViewItem option;
      QModelIndex parent = QModelIndex();

      QProgressDialog progress(tr("Printing..."), tr("Cancel"), 0, rows, this);
      progress.setWindowModality(Qt::ApplicationModal);
      float y = ItemSize / 2;

      for (int row = 0; row < rows; ++row) {
          progress.setValue(row);
          qApp->processEvents();
          if (progress.wasCanceled())
              break;

          float x = ItemSize / 2;

          for (int column = 0; column < columns; ++column) {
              option.rect = QRect(int(x), int(y), ItemSize, ItemSize);
              view->itemDelegate()->paint(&painter, option,
                                          model->index(row, column, parent));
              x = x + ItemSize;
          }
          y = y + ItemSize;
      }
      progress.setValue(rows);

      painter.restore();
      painter.end();

      if (progress.wasCanceled()) {
          QMessageBox::information(this, tr("Printing canceled"),
              tr("The printing process was canceled."), QMessageBox::Cancel);
      }
  #else
      QMessageBox::information(this, tr("Printing canceled"),
          tr("Printing is not supported on this Qt build"), QMessageBox::Cancel);
  #endif
  }

  void MainWindow::showAboutBox()
  {
      QMessageBox::about(this, tr("About the Pixelator example"),
          tr("This example demonstrates how a standard view and a custom\n"
             "delegate can be used to produce a specialized representation\n"
             "of data in a simple custom model."));
  }

  void MainWindow::updateView()
  {
      view->resizeColumnsToContents();
      view->resizeRowsToContents();
  }