source: trunk/examples/network/bearercloud/cloud.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 11.3 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the examples of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:BSD$
10** You may use this file under the terms of the BSD license as follows:
11**
12** "Redistribution and use in source and binary forms, with or without
13** modification, are permitted provided that the following conditions are
14** met:
15** * Redistributions of source code must retain the above copyright
16** notice, this list of conditions and the following disclaimer.
17** * Redistributions in binary form must reproduce the above copyright
18** notice, this list of conditions and the following disclaimer in
19** the documentation and/or other materials provided with the
20** distribution.
21** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
22** the names of its contributors may be used to endorse or promote
23** products derived from this software without specific prior written
24** permission.
25**
26** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
37** $QT_END_LICENSE$
38**
39****************************************************************************/
40
41#include "cloud.h"
42#include "bearercloud.h"
43
44#include <qnetworksession.h>
45
46#include <QGraphicsTextItem>
47#include <QGraphicsSvgItem>
48#include <QGraphicsSceneMouseEvent>
49#include <QSvgRenderer>
50#include <QPainter>
51
52#include <QDebug>
53
54#include <math.h>
55
56static QMap<QNetworkConfiguration::BearerType, QSvgRenderer *> svgCache;
57
58//! [0]
59Cloud::Cloud(const QNetworkConfiguration &config, QGraphicsItem *parent)
60: QGraphicsItem(parent), configuration(config), deleteAfterAnimation(false)
61{
62 session = new QNetworkSession(configuration, this);
63 connect(session, SIGNAL(newConfigurationActivated()),
64 this, SLOT(newConfigurationActivated()));
65 connect(session, SIGNAL(stateChanged(QNetworkSession::State)),
66 this, SLOT(stateChanged(QNetworkSession::State)));
67
68 setFlag(ItemIsMovable);
69#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 0))
70 setFlag(ItemSendsGeometryChanges);
71#endif
72 setZValue(1);
73
74 icon = new QGraphicsSvgItem(this);
75 text = new QGraphicsTextItem(this);
76
77 currentScale = 0;
78 finalScale = 1;
79 setTransform(QTransform::fromScale(currentScale, currentScale), false);
80 setOpacity(0);
81
82 newConfigurationActivated();
83}
84//! [0]
85
86Cloud::~Cloud()
87{
88}
89
90void Cloud::setFinalScale(qreal factor)
91{
92 finalScale = factor;
93}
94
95void Cloud::setDeleteAfterAnimation(bool deleteAfter)
96{
97 deleteAfterAnimation = deleteAfter;
98}
99
100void Cloud::calculateForces()
101{
102 if (!scene() || scene()->mouseGrabberItem() == this) {
103 newPos = pos();
104 return;
105 }
106
107 // sum up all the forces push this item away
108 qreal xvel = 0;
109 qreal yvel = 0;
110 QLineF orbitForce;
111 foreach (QGraphicsItem *item, scene()->items()) {
112 // other clouds
113 Cloud *cloud = qgraphicsitem_cast<Cloud *>(item);
114 if (!cloud && item->data(0) != QLatin1String("This Device"))
115 continue;
116
117 qreal factor = 1.0;
118
119 QLineF line(cloud ? item->mapToScene(0, 0) : QPointF(0, 0), mapToScene(0, 0));
120 if (item->data(0) == QLatin1String("This Device"))
121 orbitForce = line;
122
123 if (cloud)
124 factor = cloud->currentScale;
125
126 qreal dx = line.dx();
127 qreal dy = line.dy();
128 double l = 2.0 * (dx * dx + dy * dy);
129 if (l > 0) {
130 xvel += factor * dx * 200.0 / l;
131 yvel += factor * dy * 200.0 / l;
132 }
133 }
134
135 // tendency to stay at a fixed orbit
136 qreal orbit = getRadiusForState(configuration.state());
137 qreal distance = orbitForce.length();
138
139 QLineF unit = orbitForce.unitVector();
140
141 orbitForce.setLength(xvel * unit.dx() + yvel * unit.dy());
142
143 qreal w = 2 - exp(-pow(distance-orbit, 2)/(2 * 50));
144
145 if (distance < orbit) {
146 xvel += orbitForce.dx() * w;
147 yvel += orbitForce.dy() * w;
148 } else {
149 xvel -= orbitForce.dx() * w;
150 yvel -= orbitForce.dy() * w;
151 }
152
153 if (qAbs(xvel) < 0.1 && qAbs(yvel) < 0.1)
154 xvel = yvel = 0;
155
156 QRectF sceneRect = scene()->sceneRect();
157 newPos = pos() + QPointF(xvel, yvel);
158 newPos.setX(qMin(qMax(newPos.x(), sceneRect.left() + 10), sceneRect.right() - 10));
159 newPos.setY(qMin(qMax(newPos.y(), sceneRect.top() + 10), sceneRect.bottom() - 10));
160}
161
162bool Cloud::advance()
163{
164 static const qreal scaleDelta = 0.01;
165
166 bool animated = false;
167
168 if (currentScale < finalScale) {
169 animated = true;
170 currentScale = qMin<qreal>(currentScale + scaleDelta, finalScale);
171 setTransform(QTransform::fromScale(currentScale, currentScale), false);
172 } else if (currentScale > finalScale) {
173 animated = true;
174 currentScale = qMax<qreal>(currentScale - scaleDelta, finalScale);
175 setTransform(QTransform::fromScale(currentScale, currentScale), false);
176 }
177
178 if (newPos != pos()) {
179 setPos(newPos);
180 animated = true;
181 }
182
183 if (opacity() != finalOpacity) {
184 animated = true;
185 if (qAbs(finalScale - currentScale) > 0.0) {
186 // use scale as reference
187 setOpacity(opacity() + scaleDelta * (finalOpacity - opacity()) /
188 qAbs(finalScale - currentScale));
189 } else {
190 setOpacity(finalOpacity);
191 }
192 }
193
194 if (!animated && deleteAfterAnimation)
195 deleteLater();
196
197 return animated;
198}
199
200QRectF Cloud::boundingRect() const
201{
202 return childrenBoundingRect();
203}
204
205void Cloud::paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *)
206{
207}
208
209//! [4]
210QVariant Cloud::itemChange(GraphicsItemChange change, const QVariant &value)
211{
212 switch (change) {
213 case ItemPositionHasChanged:
214 if (BearerCloud *bearercloud = qobject_cast<BearerCloud *>(scene()))
215 bearercloud->cloudMoved();
216 default:
217 ;
218 };
219
220 return QGraphicsItem::itemChange(change, value);
221}
222//! [4]
223
224//! [3]
225void Cloud::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
226{
227 if (event->button() == Qt::LeftButton) {
228 if (session->isOpen())
229 session->close();
230 else
231 session->open();
232
233 event->accept();
234 }
235}
236//! [3]
237
238//! [2]
239void Cloud::stateChanged(QNetworkSession::State state)
240{
241 if (configuration.name().isEmpty())
242 finalOpacity = qreal(0.1);
243 else if (session->state() == QNetworkSession::NotAvailable)
244 finalOpacity = 0.5;
245 else
246 finalOpacity = 1.0;
247
248#if !defined(Q_WS_MAEMO_5) && !defined(Q_WS_MAEMO_6) && \
249 !defined(Q_OS_SYMBIAN) && !defined(Q_OS_WINCE)
250 QString tooltip;
251
252 if (configuration.name().isEmpty())
253 tooltip += tr("<b>HIDDEN NETWORK</b><br>");
254 else
255 tooltip += tr("<b>%1</b><br>").arg(configuration.name());
256
257#ifndef QT_NO_NETWORKINTERFACE
258 const QNetworkInterface interface = session->interface();
259 if (interface.isValid())
260 tooltip += tr("<br>Interface: %1").arg(interface.humanReadableName());
261 tooltip += tr("<br>Id: %1").arg(configuration.identifier());
262#endif
263
264 const QString bearerTypeName = configuration.bearerTypeName();
265 if (!bearerTypeName.isEmpty())
266 tooltip += tr("<br>Bearer: %1").arg(bearerTypeName);
267
268 QString s = tr("<br>State: %1 (%2)");
269 switch (state) {
270 case QNetworkSession::Invalid:
271 s = s.arg(tr("Invalid"));
272 break;
273 case QNetworkSession::NotAvailable:
274 s = s.arg(tr("Not Available"));
275 break;
276 case QNetworkSession::Connecting:
277 s = s.arg(tr("Connecting"));
278 break;
279 case QNetworkSession::Connected:
280 s = s.arg(tr("Connected"));
281 break;
282 case QNetworkSession::Closing:
283 s = s.arg(tr("Closing"));
284 break;
285 case QNetworkSession::Disconnected:
286 s = s.arg(tr("Disconnected"));
287 break;
288 case QNetworkSession::Roaming:
289 s = s.arg(tr("Roaming"));
290 break;
291 default:
292 s = s.arg(tr("Unknown"));
293 }
294
295 if (session->isOpen())
296 s = s.arg(tr("Open"));
297 else
298 s = s.arg(tr("Closed"));
299
300 tooltip += s;
301
302 tooltip += tr("<br><br>Active time: %1 seconds").arg(session->activeTime());
303 tooltip += tr("<br>Received data: %1 bytes").arg(session->bytesReceived());
304 tooltip += tr("<br>Sent data: %1 bytes").arg(session->bytesWritten());
305
306 setToolTip(tooltip);
307#else
308 Q_UNUSED(state);
309#endif
310}
311//! [2]
312
313//! [1]
314void Cloud::newConfigurationActivated()
315{
316 QNetworkConfiguration::BearerType bearerType = configuration.bearerType();
317 if (!svgCache.contains(bearerType)) {
318 QSvgRenderer *renderer = 0;
319 switch (bearerType) {
320 case QNetworkConfiguration::BearerWLAN:
321 renderer = new QSvgRenderer(QLatin1String(":wlan.svg"));
322 break;
323 case QNetworkConfiguration::BearerEthernet:
324 renderer = new QSvgRenderer(QLatin1String(":lan.svg"));
325 break;
326 case QNetworkConfiguration::Bearer2G:
327 renderer = new QSvgRenderer(QLatin1String(":cell.svg"));
328 break;
329 case QNetworkConfiguration::BearerBluetooth:
330 renderer = new QSvgRenderer(QLatin1String(":bluetooth.svg"));
331 break;
332 case QNetworkConfiguration::BearerCDMA2000:
333 case QNetworkConfiguration::BearerWCDMA:
334 case QNetworkConfiguration::BearerHSPA:
335 renderer = new QSvgRenderer(QLatin1String(":umts.svg"));
336 break;
337 default:
338 renderer = new QSvgRenderer(QLatin1String(":unknown.svg"));
339 }
340
341 if (renderer)
342 svgCache.insert(bearerType, renderer);
343 }
344
345 icon->setSharedRenderer(svgCache[bearerType]);
346
347 if (configuration.name().isEmpty()) {
348 text->setPlainText(tr("HIDDEN NETWORK"));
349 } else {
350 if (configuration.type() == QNetworkConfiguration::ServiceNetwork)
351 text->setHtml("<b>" + configuration.name() + "</b>");
352 else
353 text->setPlainText(configuration.name());
354 }
355
356 const qreal height = icon->boundingRect().height() + text->boundingRect().height();
357
358 icon->setPos(icon->boundingRect().width() / -2, height / -2);
359
360 text->setPos(text->boundingRect().width() / -2,
361 height / 2 - text->boundingRect().height());
362
363 stateChanged(session->state());
364}
365//! [1]
366
367qreal Cloud::getRadiusForState(QNetworkConfiguration::StateFlags state)
368{
369 switch (state) {
370 case QNetworkConfiguration::Active:
371 return 100;
372 break;
373 case QNetworkConfiguration::Discovered:
374 return 150;
375 break;
376 case QNetworkConfiguration::Defined:
377 return 200;
378 break;
379 case QNetworkConfiguration::Undefined:
380 return 250;
381 break;
382 default:
383 return 300;
384 }
385}
386
Note: See TracBrowser for help on using the repository browser.