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