Add Qml documentation
[contrib/qtwebsockets.git] / src / imports / qmlwebsockets / qqmlwebsocket.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtWebSockets 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 Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/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 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 /*!
43     \qmltype WebSocket
44     \instantiates QQmlWebSocket
45
46     \inqmlmodule Qt.WebSockets
47     \brief QML interface to QWebSocket.
48
49     WebSockets is a web technology providing full-duplex communications channels over a single TCP connection.
50     The WebSocket protocol was standardized by the IETF as RFC 6455 in 2011 (see http://tools.ietf.org/html/rfc6455).
51 */
52
53 /*!
54   \qmlproperty QUrl WebSocket::url
55   Server url to connect to. The url must have one of 2 schemes: {ws://} or {wss://}.
56   When not supplied, then {ws://} is used.
57   */
58
59 /*!
60   \qmlproperty Status WebSocket::status
61   Status of the WebSocket.
62
63   The status can have the following values:
64   \list
65   \li WebSockets.Connecting
66   \li WebSockets.Open
67   \li WebSockets.Closing
68   \li WebSockets.Closed
69   \li WebSockets.Error
70   \endlist
71   */
72
73 /*!
74   \qmlproperty QString WebSocket::errorString
75   Contains a description of the last error that occurred. When no error occurrred,
76   this string is empty.
77   */
78
79 /*!
80   \qmlproperty bool WebSocket::active
81   When set to true, a connection is made to the server with the given url.
82   When set to false, the connection is closed.
83   The default value is false.
84   */
85
86 /*!
87   \qmlsignal WebSocket::textMessageReceived(QString message)
88   This signal is emitted when a text message is received.
89   */
90
91 /*!
92   \qmlsignal WebSocket::statusChanged(Status status)
93   This signal is emitted when the status of the WebSocket changes.
94   the \l {WebSocket::status}{status} argument provides the current status.
95
96   \sa WebSocket::status
97   */
98
99 #include "qqmlwebsocket.h"
100 #include <QtWebSockets/QWebSocket>
101
102 QT_BEGIN_NAMESPACE
103
104 QQmlWebSocket::QQmlWebSocket(QObject *parent) :
105     QObject(parent),
106     m_webSocket(),
107     m_status(Closed),
108     m_url(),
109     m_isActive(false),
110     m_componentCompleted(true),
111     m_errorString()
112 {
113 }
114
115 QQmlWebSocket::~QQmlWebSocket()
116 {
117 }
118
119 qint64 QQmlWebSocket::sendTextMessage(const QString &message)
120 {
121     if (m_status != Open) {
122         setErrorString(tr("Messages can only be send when the socket has Open status."));
123         setStatus(Error);
124         return 0;
125     }
126     return m_webSocket->write(message);
127 }
128
129 QUrl QQmlWebSocket::url() const
130 {
131     return m_url;
132 }
133
134 void QQmlWebSocket::setUrl(const QUrl &url)
135 {
136     if (m_url == url) {
137         return;
138     }
139     if (m_webSocket && (m_status == Open)) {
140         m_webSocket->close();
141     }
142     m_url = url;
143     Q_EMIT urlChanged();
144     if (m_webSocket) {
145         m_webSocket->open(m_url);
146     }
147 }
148
149 QQmlWebSocket::Status QQmlWebSocket::status() const
150 {
151     return m_status;
152 }
153
154 QString QQmlWebSocket::errorString() const
155 {
156     return m_errorString;
157 }
158
159 void QQmlWebSocket::classBegin()
160 {
161     m_componentCompleted = false;
162     m_errorString = tr("QQmlWebSocket is not ready.");
163     m_status = Closed;
164 }
165
166 void QQmlWebSocket::componentComplete()
167 {
168     m_webSocket.reset(new (std::nothrow) QWebSocket());
169     if (Q_LIKELY(m_webSocket)) {
170         connect(m_webSocket.data(), SIGNAL(textMessageReceived(QString)), this, SIGNAL(textMessageReceived(QString)));
171         connect(m_webSocket.data(), SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onError(QAbstractSocket::SocketError)));
172         connect(m_webSocket.data(), SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(onStateChanged(QAbstractSocket::SocketState)));
173
174         m_componentCompleted = true;
175
176         open();
177     }
178 }
179
180 void QQmlWebSocket::onError(QAbstractSocket::SocketError error)
181 {
182     Q_UNUSED(error)
183     setErrorString(m_webSocket->errorString());
184     setStatus(Error);
185 }
186
187 void QQmlWebSocket::onStateChanged(QAbstractSocket::SocketState state)
188 {
189     switch (state)
190     {
191         case QAbstractSocket::ConnectingState:
192         case QAbstractSocket::BoundState:
193         case QAbstractSocket::HostLookupState:
194         {
195             setStatus(Connecting);
196             break;
197         }
198         case QAbstractSocket::UnconnectedState:
199         {
200             setStatus(Closed);
201             break;
202         }
203         case QAbstractSocket::ConnectedState:
204         {
205             setStatus(Open);
206             break;
207         }
208         case QAbstractSocket::ClosingState:
209         {
210             setStatus(Closing);
211             break;
212         }
213         default:
214         {
215             setStatus(Connecting);
216             break;
217         }
218     }
219 }
220
221 void QQmlWebSocket::setStatus(QQmlWebSocket::Status status)
222 {
223     if (m_status == status) {
224         return;
225     }
226     m_status = status;
227     if (status != Error) {
228         setErrorString();
229     }
230     Q_EMIT statusChanged(m_status);
231 }
232
233 void QQmlWebSocket::setActive(bool active)
234 {
235     if (m_isActive == active) {
236         return;
237     }
238     m_isActive = active;
239     Q_EMIT activeChanged(m_isActive);
240     if (!m_componentCompleted) {
241         return;
242     }
243     if (m_isActive) {
244         open();
245     } else {
246         close();
247     }
248 }
249
250 bool QQmlWebSocket::isActive() const
251 {
252     return m_isActive;
253 }
254
255 void QQmlWebSocket::open()
256 {
257     if (m_componentCompleted && m_isActive && m_url.isValid() && Q_LIKELY(m_webSocket)) {
258         m_webSocket->open(m_url);
259     }
260 }
261
262 void QQmlWebSocket::close()
263 {
264     if (m_componentCompleted && Q_LIKELY(m_webSocket)) {
265         m_webSocket->close();
266     }
267 }
268
269 void QQmlWebSocket::setErrorString(QString errorString)
270 {
271     if (m_errorString == errorString) {
272         return;
273     }
274     m_errorString = errorString;
275     Q_EMIT errorStringChanged(m_errorString);
276 }
277
278 QT_END_NAMESPACE