Add missing QT_{BEGIN,END}_NAMESPACE
[profile/ivi/qtdeclarative.git] / src / qml / qml / qqmlerror.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qqmlerror.h"
43 #include "qqmlglobal_p.h"
44
45 #include <QtCore/qdebug.h>
46 #include <QtCore/qfile.h>
47 #include <QtCore/qstringlist.h>
48
49 QT_BEGIN_NAMESPACE
50
51 /*!
52     \class QQmlError
53     \since 5.0
54     \inmodule QtQml
55     \brief The QQmlError class encapsulates a QML error.
56
57     QQmlError includes a textual description of the error, as well
58     as location information (the file, line, and column). The toString()
59     method creates a single-line, human-readable string containing all of
60     this information, for example:
61     \code
62     file:///home/user/test.qml:7:8: Invalid property assignment: double expected
63     \endcode
64
65     You can use qDebug() or qWarning() to output errors to the console. This method
66     will attempt to open the file indicated by the error
67     and include additional contextual information.
68     \code
69     file:///home/user/test.qml:7:8: Invalid property assignment: double expected
70             y: "hello"
71                ^
72     \endcode
73
74     Note that the QtQuick 1 version is named QDeclarativeError
75
76     \sa QQuickView::errors(), QQmlComponent::errors()
77 */
78 class QQmlErrorPrivate
79 {
80 public:
81     QQmlErrorPrivate();
82
83     QUrl url;
84     QString description;
85     quint16 line;
86     quint16 column;
87 };
88
89 QQmlErrorPrivate::QQmlErrorPrivate()
90 : line(0), column(0)
91 {
92 }
93
94 /*!
95     Creates an empty error object.
96 */
97 QQmlError::QQmlError()
98 : d(0)
99 {
100 }
101
102 /*!
103     Creates a copy of \a other.
104 */
105 QQmlError::QQmlError(const QQmlError &other)
106 : d(0)
107 {
108     *this = other;
109 }
110
111 /*!
112     Assigns \a other to this error object.
113 */
114 QQmlError &QQmlError::operator=(const QQmlError &other)
115 {
116     if (!other.d) {
117         delete d;
118         d = 0;
119     } else {
120         if (!d) d = new QQmlErrorPrivate;
121         d->url = other.d->url;
122         d->description = other.d->description;
123         d->line = other.d->line;
124         d->column = other.d->column;
125     }
126     return *this;
127 }
128
129 /*!
130     \internal 
131 */
132 QQmlError::~QQmlError()
133 {
134     delete d; d = 0;
135 }
136
137 /*!
138     Returns true if this error is valid, otherwise false.
139 */
140 bool QQmlError::isValid() const
141 {
142     return d != 0;
143 }
144
145 /*!
146     Returns the url for the file that caused this error.
147 */
148 QUrl QQmlError::url() const
149 {
150     if (d) return d->url;
151     else return QUrl();
152 }
153
154 /*!
155     Sets the \a url for the file that caused this error.
156 */
157 void QQmlError::setUrl(const QUrl &url)
158 {
159     if (!d) d = new QQmlErrorPrivate;
160     d->url = url;
161 }
162
163 /*!
164     Returns the error description.
165 */
166 QString QQmlError::description() const
167 {
168     if (d) return d->description;
169     else return QString();
170 }
171
172 /*!
173     Sets the error \a description.
174 */
175 void QQmlError::setDescription(const QString &description)
176 {
177     if (!d) d = new QQmlErrorPrivate;
178     d->description = description;
179 }
180
181 /*!
182     Returns the error line number.
183 */
184 int QQmlError::line() const
185 {
186     if (d) return qmlSourceCoordinate(d->line);
187     else return -1;
188 }
189
190 /*!
191     Sets the error \a line number.
192 */
193 void QQmlError::setLine(int line)
194 {
195     if (!d) d = new QQmlErrorPrivate;
196     d->line = qmlSourceCoordinate(line);
197 }
198
199 /*!
200     Returns the error column number.
201 */
202 int QQmlError::column() const
203 {
204     if (d) return qmlSourceCoordinate(d->column);
205     else return -1;
206 }
207
208 /*!
209     Sets the error \a column number.
210 */
211 void QQmlError::setColumn(int column)
212 {
213     if (!d) d = new QQmlErrorPrivate;
214     d->column = qmlSourceCoordinate(column);
215 }
216
217 /*!
218     Returns the error as a human readable string.
219 */
220 QString QQmlError::toString() const
221 {
222     QString rv;
223
224     QUrl u(url());
225     int l(line());
226
227     if (u.isEmpty()) {
228         rv = QLatin1String("<Unknown File>");
229     } else if (l != -1) {
230         rv = u.toString() + QLatin1Char(':') + QString::number(l);
231
232         int c(column());
233         if (c != -1)
234             rv += QLatin1Char(':') + QString::number(c);
235     } else {
236         rv = u.toString();
237     }
238
239     rv += QLatin1String(": ") + description();
240
241     return rv;
242 }
243
244 /*!
245     \relates QQmlError
246     \fn QDebug operator<<(QDebug debug, const QQmlError &error)
247
248     Outputs a human readable version of \a error to \a debug.
249 */
250
251 QDebug operator<<(QDebug debug, const QQmlError &error)
252 {
253     debug << qPrintable(error.toString());
254
255     QUrl url = error.url();
256
257     if (error.line() > 0 && url.scheme() == QLatin1String("file")) {
258         QString file = url.toLocalFile();
259         QFile f(file);
260         if (f.open(QIODevice::ReadOnly)) {
261             QByteArray data = f.readAll();
262             QTextStream stream(data, QIODevice::ReadOnly);
263 #ifndef QT_NO_TEXTCODEC
264             stream.setCodec("UTF-8");
265 #endif
266             const QString code = stream.readAll();
267             const QStringList lines = code.split(QLatin1Char('\n'));
268
269             if (lines.count() >= error.line()) {
270                 const QString &line = lines.at(error.line() - 1);
271                 debug << "\n    " << qPrintable(line);
272
273                 if(error.column() > 0) {
274                     int column = qMax(0, error.column() - 1);
275                     column = qMin(column, line.length()); 
276
277                     QByteArray ind;
278                     ind.reserve(column);
279                     for (int i = 0; i < column; ++i) {
280                         const QChar ch = line.at(i);
281                         if (ch.isSpace())
282                             ind.append(ch.unicode());
283                         else
284                             ind.append(' ');
285                     }
286                     ind.append('^');
287                     debug << "\n    " << ind.constData();
288                 }
289             }
290         }
291     }
292     return debug;
293 }
294
295 QT_END_NAMESPACE