1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the examples of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** You may use this file under the terms of the BSD license as follows:
10 **
11 ** "Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions are
13 ** met:
14 **   * Redistributions of source code must retain the above copyright
15 **     notice, this list of conditions and the following disclaimer.
16 **   * Redistributions in binary form must reproduce the above copyright
17 **     notice, this list of conditions and the following disclaimer in
18 **     the documentation and/or other materials provided with the
19 **     distribution.
20 **   * Neither the name of The Qt Company Ltd nor the names of its
21 **     contributors may be used to endorse or promote products derived
22 **     from this software without specific prior written permission.
23 **
24 **
25 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40 
41 #include <QtGui>
42 
43 #include "imagemodel.h"
44 #include "mainwindow.h"
45 #include "pixeldelegate.h"
46 
47 //! [0]
MainWindow()48 MainWindow::MainWindow()
49 {
50 //! [0]
51     currentPath = QDir::homePath();
52     model = new ImageModel(this);
53 
54     QWidget *centralWidget = new QWidget;
55 
56 //! [1]
57     view = new QTableView;
58     view->setShowGrid(false);
59     view->horizontalHeader()->hide();
60     view->verticalHeader()->hide();
61     view->horizontalHeader()->setMinimumSectionSize(1);
62     view->verticalHeader()->setMinimumSectionSize(1);
63     view->setModel(model);
64 //! [1]
65 
66 //! [2]
67     PixelDelegate *delegate = new PixelDelegate(this);
68     view->setItemDelegate(delegate);
69 //! [2]
70 
71 //! [3]
72     QLabel *pixelSizeLabel = new QLabel(tr("Pixel size:"));
73     QSpinBox *pixelSizeSpinBox = new QSpinBox;
74     pixelSizeSpinBox->setMinimum(4);
75     pixelSizeSpinBox->setMaximum(32);
76     pixelSizeSpinBox->setValue(12);
77 //! [3]
78 
79     QMenu *fileMenu = new QMenu(tr("&File"), this);
80     QAction *openAction = fileMenu->addAction(tr("&Open..."));
81     openAction->setShortcuts(QKeySequence::Open);
82 
83     printAction = fileMenu->addAction(tr("&Print..."));
84     printAction->setEnabled(false);
85     printAction->setShortcut(QKeySequence::Print);
86 
87     QAction *quitAction = fileMenu->addAction(tr("E&xit"));
88     quitAction->setShortcuts(QKeySequence::Quit);
89 
90     QMenu *helpMenu = new QMenu(tr("&Help"), this);
91     QAction *aboutAction = helpMenu->addAction(tr("&About"));
92 
93     menuBar()->addMenu(fileMenu);
94     menuBar()->addSeparator();
95     menuBar()->addMenu(helpMenu);
96 
97     connect(openAction, SIGNAL(triggered()), this, SLOT(chooseImage()));
98     connect(printAction, SIGNAL(triggered()), this, SLOT(printImage()));
99     connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
100     connect(aboutAction, SIGNAL(triggered()), this, SLOT(showAboutBox()));
101 //! [4]
102     connect(pixelSizeSpinBox, SIGNAL(valueChanged(int)),
103             delegate, SLOT(setPixelSize(int)));
104     connect(pixelSizeSpinBox, SIGNAL(valueChanged(int)),
105             this, SLOT(updateView()));
106 //! [4]
107 
108     QHBoxLayout *controlsLayout = new QHBoxLayout;
109     controlsLayout->addWidget(pixelSizeLabel);
110     controlsLayout->addWidget(pixelSizeSpinBox);
111     controlsLayout->addStretch(1);
112 
113     QVBoxLayout *mainLayout = new QVBoxLayout;
114     mainLayout->addWidget(view);
115     mainLayout->addLayout(controlsLayout);
116     centralWidget->setLayout(mainLayout);
117 
118     setCentralWidget(centralWidget);
119 
120     setWindowTitle(tr("Pixelator"));
121     resize(640, 480);
122 //! [5]
123 }
124 //! [5]
125 
chooseImage()126 void MainWindow::chooseImage()
127 {
128     QString fileName = QFileDialog::getOpenFileName(this,
129         tr("Choose an image"), currentPath, "*");
130 
131     if (!fileName.isEmpty())
132         openImage(fileName);
133 }
134 
openImage(const QString & fileName)135 void MainWindow::openImage(const QString &fileName)
136 {
137     QImage image;
138 
139     if (image.load(fileName)) {
140         model->setImage(image);
141         if (!fileName.startsWith(":/")) {
142             currentPath = fileName;
143             setWindowTitle(tr("%1 - Pixelator").arg(currentPath));
144         }
145 
146         printAction->setEnabled(true);
147         updateView();
148     }
149 }
150 
printImage()151 void MainWindow::printImage()
152 {
153 #ifndef QT_NO_PRINTER
154     if (model->rowCount(QModelIndex())*model->columnCount(QModelIndex())
155         > 90000) {
156 	    QMessageBox::StandardButton answer;
157 	    answer = QMessageBox::question(this, tr("Large Image Size"),
158             tr("The printed image may be very large. Are you sure that "
159                "you want to print it?"),
160             QMessageBox::Yes | QMessageBox::No);
161         if (answer == QMessageBox::No)
162             return;
163     }
164 
165     QPrinter printer(QPrinter::HighResolution);
166 
167     QPrintDialog *dlg = new QPrintDialog(&printer, this);
168     dlg->setWindowTitle(tr("Print Image"));
169 
170     if (dlg->exec() != QDialog::Accepted)
171         return;
172 
173     QPainter painter;
174     painter.begin(&printer);
175 
176     int rows = model->rowCount(QModelIndex());
177     int columns = model->columnCount(QModelIndex());
178     int sourceWidth = (columns+1) * ItemSize;
179     int sourceHeight = (rows+1) * ItemSize;
180 
181     painter.save();
182 
183     double xscale = printer.pageRect().width()/double(sourceWidth);
184     double yscale = printer.pageRect().height()/double(sourceHeight);
185     double scale = qMin(xscale, yscale);
186 
187     painter.translate(printer.paperRect().x() + printer.pageRect().width()/2,
188                       printer.paperRect().y() + printer.pageRect().height()/2);
189     painter.scale(scale, scale);
190     painter.translate(-sourceWidth/2, -sourceHeight/2);
191 
192     QStyleOptionViewItem option;
193     QModelIndex parent = QModelIndex();
194 
195     QProgressDialog progress(tr("Printing..."), tr("Cancel"), 0, rows, this);
196     progress.setWindowModality(Qt::ApplicationModal);
197     float y = ItemSize/2;
198 
199     for (int row = 0; row < rows; ++row) {
200         progress.setValue(row);
201         qApp->processEvents();
202         if (progress.wasCanceled())
203             break;
204 
205         float x = ItemSize/2;
206 
207         for (int column = 0; column < columns; ++column) {
208             option.rect = QRect(int(x), int(y), ItemSize, ItemSize);
209             view->itemDelegate()->paint(&painter, option,
210                                         model->index(row, column, parent));
211             x = x + ItemSize;
212         }
213         y = y + ItemSize;
214     }
215     progress.setValue(rows);
216 
217     painter.restore();
218     painter.end();
219 
220     if (progress.wasCanceled()) {
221         QMessageBox::information(this, tr("Printing canceled"),
222             tr("The printing process was canceled."), QMessageBox::Cancel);
223     }
224 #else
225     QMessageBox::information(this, tr("Printing canceled"),
226         tr("Printing is not supported on this Qt build"), QMessageBox::Cancel);
227 #endif
228 }
229 
showAboutBox()230 void MainWindow::showAboutBox()
231 {
232     QMessageBox::about(this, tr("About the Pixelator example"),
233         tr("This example demonstrates how a standard view and a custom\n"
234            "delegate can be used to produce a specialized representation\n"
235            "of data in a simple custom model."));
236 }
237 
238 //! [6]
updateView()239 void MainWindow::updateView()
240 {
241     view->resizeColumnsToContents();
242     view->resizeRowsToContents();
243 }
244 //! [6]
245