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 QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file. Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qsplashscreen.h"
43
44 #ifndef QT_NO_SPLASHSCREEN
45
46 #include "qapplication.h"
47 #include "qdesktopwidget.h"
48 #include "qpainter.h"
49 #include "qpixmap.h"
50 #include "qtextdocument.h"
51 #include "qtextcursor.h"
52 #include <QtCore/qdebug.h>
53 #include <private/qwidget_p.h>
54
55 QT_BEGIN_NAMESPACE
56
57 class QSplashScreenPrivate : public QWidgetPrivate
58 {
59 Q_DECLARE_PUBLIC(QSplashScreen)
60 public:
61 QPixmap pixmap;
62 QString currStatus;
63 QColor currColor;
64 int currAlign;
65
66 inline QSplashScreenPrivate();
67 };
68
69 /*!
70 \class QSplashScreen
71 \brief The QSplashScreen widget provides a splash screen that can
72 be shown during application startup.
73
74 A splash screen is a widget that is usually displayed when an
75 application is being started. Splash screens are often used for
76 applications that have long start up times (e.g. database or
77 networking applications that take time to establish connections) to
78 provide the user with feedback that the application is loading.
79
80 The splash screen appears in the center of the screen. It may be
81 useful to add the Qt::WindowStaysOnTopHint to the splash widget's
82 window flags if you want to keep it above all the other windows on
83 the desktop.
84
85 Some X11 window managers do not support the "stays on top" flag. A
86 solution is to set up a timer that periodically calls raise() on
87 the splash screen to simulate the "stays on top" effect.
88
89 The most common usage is to show a splash screen before the main
90 widget is displayed on the screen. This is illustrated in the
91 following code snippet in which a splash screen is displayed and
92 some initialization tasks are performed before the application's
93 main window is shown:
94
95 \snippet doc/src/snippets/qsplashscreen/main.cpp 0
96 \dots
97 \snippet doc/src/snippets/qsplashscreen/main.cpp 1
98
99 The user can hide the splash screen by clicking on it with the
100 mouse. Since the splash screen is typically displayed before the
101 event loop has started running, it is necessary to periodically
102 call QApplication::processEvents() to receive the mouse clicks.
103
104 It is sometimes useful to update the splash screen with messages,
105 for example, announcing connections established or modules loaded
106 as the application starts up:
107
108 \snippet doc/src/snippets/code/src_gui_widgets_qsplashscreen.cpp 0
109
110 QSplashScreen supports this with the showMessage() function. If you
111 wish to do your own drawing you can get a pointer to the pixmap
112 used in the splash screen with pixmap(). Alternatively, you can
113 subclass QSplashScreen and reimplement drawContents().
114 */
115
116 /*!
117 Construct a splash screen that will display the \a pixmap.
118
119 There should be no need to set the widget flags, \a f, except
120 perhaps Qt::WindowStaysOnTopHint.
121 */
QSplashScreen(const QPixmap & pixmap,Qt::WindowFlags f)122 QSplashScreen::QSplashScreen(const QPixmap &pixmap, Qt::WindowFlags f)
123 : QWidget(*(new QSplashScreenPrivate()), 0, Qt::SplashScreen | Qt::FramelessWindowHint | f)
124 {
125 setPixmap(pixmap); // Does an implicit repaint
126 }
127
128 /*!
129 \overload
130
131 This function allows you to specify a parent for your splashscreen. The
132 typical use for this constructor is if you have a multiple screens and
133 prefer to have the splash screen on a different screen than your primary
134 one. In that case pass the proper desktop() as the \a parent.
135 */
QSplashScreen(QWidget * parent,const QPixmap & pixmap,Qt::WindowFlags f)136 QSplashScreen::QSplashScreen(QWidget *parent, const QPixmap &pixmap, Qt::WindowFlags f)
137 : QWidget(*new QSplashScreenPrivate, parent, Qt::SplashScreen | f)
138 {
139 d_func()->pixmap = pixmap;
140 setPixmap(d_func()->pixmap); // Does an implicit repaint
141 }
142
143 /*!
144 Destructor.
145 */
~QSplashScreen()146 QSplashScreen::~QSplashScreen()
147 {
148 }
149
150 /*!
151 \reimp
152 */
mousePressEvent(QMouseEvent *)153 void QSplashScreen::mousePressEvent(QMouseEvent *)
154 {
155 hide();
156 }
157
158 /*!
159 This overrides QWidget::repaint(). It differs from the standard
160 repaint function in that it also calls QApplication::flush() to
161 ensure the updates are displayed, even when there is no event loop
162 present.
163 */
repaint()164 void QSplashScreen::repaint()
165 {
166 QWidget::repaint();
167 QApplication::flush();
168 }
169
170 /*!
171 \fn QSplashScreen::messageChanged(const QString &message)
172
173 This signal is emitted when the message on the splash screen
174 changes. \a message is the new message and is a null-string
175 when the message has been removed.
176
177 \sa showMessage(), clearMessage()
178 */
179
180
181
182 /*!
183 Draws the \a message text onto the splash screen with color \a
184 color and aligns the text according to the flags in \a alignment.
185
186 To make sure the splash screen is repainted immediately, you can
187 call \l{QCoreApplication}'s
188 \l{QCoreApplication::}{processEvents()} after the call to
189 showMessage(). You usually want this to make sure that the message
190 is kept up to date with what your application is doing (e.g.,
191 loading files).
192
193 \sa Qt::Alignment, clearMessage()
194 */
showMessage(const QString & message,int alignment,const QColor & color)195 void QSplashScreen::showMessage(const QString &message, int alignment,
196 const QColor &color)
197 {
198 Q_D(QSplashScreen);
199 d->currStatus = message;
200 d->currAlign = alignment;
201 d->currColor = color;
202 emit messageChanged(d->currStatus);
203 repaint();
204 }
205
206 /*!
207 Removes the message being displayed on the splash screen
208
209 \sa showMessage()
210 */
clearMessage()211 void QSplashScreen::clearMessage()
212 {
213 d_func()->currStatus.clear();
214 emit messageChanged(d_func()->currStatus);
215 repaint();
216 }
217
218 /*!
219 Makes the splash screen wait until the widget \a mainWin is displayed
220 before calling close() on itself.
221 */
finish(QWidget * mainWin)222 void QSplashScreen::finish(QWidget *mainWin)
223 {
224 if (mainWin) {
225 #if defined(Q_WS_X11)
226 extern void qt_x11_wait_for_window_manager(QWidget *mainWin, bool);
227 qt_x11_wait_for_window_manager(mainWin, false);
228 #endif
229 }
230 close();
231 }
232
233 /*!
234 Sets the pixmap that will be used as the splash screen's image to
235 \a pixmap.
236 */
setPixmap(const QPixmap & pixmap)237 void QSplashScreen::setPixmap(const QPixmap &pixmap)
238 {
239 Q_D(QSplashScreen);
240
241 d->pixmap = pixmap;
242 setAttribute(Qt::WA_TranslucentBackground, pixmap.hasAlpha());
243
244 QRect r(QPoint(), d->pixmap.size());
245 resize(r.size());
246 move(QApplication::desktop()->screenGeometry().center() - r.center());
247 if (isVisible())
248 repaint();
249 }
250
251 /*!
252 Returns the pixmap that is used in the splash screen. The image
253 does not have any of the text drawn by showMessage() calls.
254 */
pixmap() const255 const QPixmap QSplashScreen::pixmap() const
256 {
257 return d_func()->pixmap;
258 }
259
260 /*!
261 \internal
262 */
QSplashScreenPrivate()263 inline QSplashScreenPrivate::QSplashScreenPrivate() : currAlign(Qt::AlignLeft)
264 {
265 }
266
267 /*!
268 Draw the contents of the splash screen using painter \a painter.
269 The default implementation draws the message passed by showMessage().
270 Reimplement this function if you want to do your own drawing on
271 the splash screen.
272 */
drawContents(QPainter * painter)273 void QSplashScreen::drawContents(QPainter *painter)
274 {
275 Q_D(QSplashScreen);
276 painter->setPen(d->currColor);
277 QRect r = rect().adjusted(5, 5, -5, -5);
278 if (Qt::mightBeRichText(d->currStatus)) {
279 QTextDocument doc;
280 #ifdef QT_NO_TEXTHTMLPARSER
281 doc.setPlainText(d->currStatus);
282 #else
283 doc.setHtml(d->currStatus);
284 #endif
285 doc.setTextWidth(r.width());
286 QTextCursor cursor(&doc);
287 cursor.select(QTextCursor::Document);
288 QTextBlockFormat fmt;
289 fmt.setAlignment(Qt::Alignment(d->currAlign));
290 cursor.mergeBlockFormat(fmt);
291 painter->save();
292 painter->translate(r.topLeft());
293 doc.drawContents(painter);
294 painter->restore();
295 } else {
296 painter->drawText(r, d->currAlign, d->currStatus);
297 }
298 }
299
300 /*!
301 \fn void QSplashScreen::message(const QString &message, int alignment,
302 const QColor &color)
303 \compat
304
305 Use showMessage() instead.
306 */
307
308 /*!
309 \fn void QSplashScreen::clear()
310 \compat
311
312 Use clearMessage() instead.
313 */
314
315 /*! \reimp */
event(QEvent * e)316 bool QSplashScreen::event(QEvent *e)
317 {
318 if (e->type() == QEvent::Paint) {
319 Q_D(QSplashScreen);
320 QPainter painter(this);
321 if (!d->pixmap.isNull())
322 painter.drawPixmap(QPoint(), d->pixmap);
323 drawContents(&painter);
324 }
325 return QWidget::event(e);
326 }
327
328 QT_END_NAMESPACE
329
330 #endif //QT_NO_SPLASHSCREEN
331