1 | /******************************************************************* |
2 | * bugzillalib.h |
3 | * Copyright 2009, 2011 Dario Andres Rodriguez <andresbajotierra@gmail.com> |
4 | * Copyright 2012 George Kiagiadakis <kiagiadakis.george@gmail.com> |
5 | * |
6 | * This program is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU General Public License as |
8 | * published by the Free Software Foundation; either version 2 of |
9 | * the License, or (at your option) any later version. |
10 | * |
11 | * This program is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | * GNU General Public License for more details. |
15 | * |
16 | * You should have received a copy of the GNU General Public License |
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
18 | * |
19 | ******************************************************************/ |
20 | |
21 | #ifndef BUGZILLALIB__H |
22 | #define BUGZILLALIB__H |
23 | |
24 | #include <QtCore/QObject> |
25 | #include <QtCore/QMap> |
26 | #include <QtCore/QStringList> |
27 | #include <QtXml/QDomDocument> |
28 | |
29 | #include <kxmlrpcclient/client.h> |
30 | |
31 | namespace KIO { class Job; } |
32 | class KJob; |
33 | class QString; |
34 | class QByteArray; |
35 | |
36 | //Typedefs for Bug Report Listing |
37 | typedef QMap<QString, QString> BugMap; //Report basic fields map |
38 | typedef QList<BugMap> BugMapList; //List of reports |
39 | |
40 | //Main bug report data, full fields + comments |
41 | class BugReport |
42 | { |
43 | public: |
44 | enum Status { |
45 | UnknownStatus, |
46 | Unconfirmed, |
47 | New, |
48 | Assigned, |
49 | Reopened, |
50 | Resolved, |
51 | NeedsInfo, |
52 | Verified, |
53 | Closed |
54 | }; |
55 | |
56 | enum Resolution { |
57 | UnknownResolution, |
58 | NotResolved, |
59 | Fixed, |
60 | Invalid, |
61 | WontFix, |
62 | Later, |
63 | Remind, |
64 | Duplicate, |
65 | WorksForMe, |
66 | Moved, |
67 | Upstream, |
68 | Downstream, |
69 | WaitingForInfo, |
70 | Backtrace, |
71 | Unmaintained |
72 | }; |
73 | |
74 | BugReport() |
75 | : m_isValid(false), |
76 | m_status(UnknownStatus), |
77 | m_resolution(UnknownResolution) |
78 | {} |
79 | |
80 | void setBugNumber(const QString & value) { |
81 | setData("bug_id" , value); |
82 | } |
83 | QString bugNumber() const { |
84 | return getData("bug_id" ); |
85 | } |
86 | int bugNumberAsInt() const { |
87 | return getData("bug_id" ).toInt(); |
88 | } |
89 | |
90 | void setShortDescription(const QString & value) { |
91 | setData("short_desc" , value); |
92 | } |
93 | QString shortDescription() const { |
94 | return getData("short_desc" ); |
95 | } |
96 | |
97 | void setProduct(const QString & value) { |
98 | setData("product" , value); |
99 | } |
100 | QString product() const { |
101 | return getData("product" ); |
102 | } |
103 | |
104 | void setComponent(const QString & value) { |
105 | setData("component" , value); |
106 | } |
107 | QString component() const { |
108 | return getData("component" ); |
109 | } |
110 | |
111 | void setVersion(const QString & value) { |
112 | setData("version" , value); |
113 | } |
114 | QString version() const { |
115 | return getData("version" ); |
116 | } |
117 | |
118 | void setOperatingSystem(const QString & value) { |
119 | setData("op_sys" , value); |
120 | } |
121 | QString operatingSystem() const { |
122 | return getData("op_sys" ); |
123 | } |
124 | |
125 | void setPlatform(const QString & value) { |
126 | setData("rep_platform" , value); |
127 | } |
128 | QString platform() const { |
129 | return getData("rep_platform" ); |
130 | } |
131 | |
132 | void setBugStatus(const QString &status); |
133 | QString bugStatus() const { |
134 | return getData("bug_status" ); |
135 | } |
136 | |
137 | void setResolution(const QString &resolution); |
138 | QString resolution() const { |
139 | return getData("resolution" ); |
140 | } |
141 | |
142 | Status statusValue() const { |
143 | return m_status; |
144 | } |
145 | |
146 | Resolution resolutionValue() const { |
147 | return m_resolution; |
148 | } |
149 | |
150 | void setPriority(const QString & value) { |
151 | setData("priority" , value); |
152 | } |
153 | QString priority() const { |
154 | return getData("priority" ); |
155 | } |
156 | |
157 | void setBugSeverity(const QString & value) { |
158 | setData("bug_severity" , value); |
159 | } |
160 | QString bugSeverity() const { |
161 | return getData("bug_severity" ); |
162 | } |
163 | |
164 | void setKeywords(const QStringList & keywords) { |
165 | setData("keywords" , keywords.join("," )); |
166 | } |
167 | QStringList keywords() const { |
168 | return getData("keywords" ).split(','); |
169 | } |
170 | |
171 | void setDescription(const QString & desc) { |
172 | m_commentList.insert(0, desc); |
173 | } |
174 | QString description() const { |
175 | return m_commentList.at(0); |
176 | } |
177 | |
178 | void (const QStringList & comm) { |
179 | m_commentList.append(comm); |
180 | } |
181 | QStringList () const { |
182 | return m_commentList.mid(1); |
183 | } |
184 | |
185 | void setMarkedAsDuplicateOf(const QString & dupID) { |
186 | setData("dup_id" , dupID); |
187 | } |
188 | QString markedAsDuplicateOf() const { |
189 | return getData("dup_id" ); |
190 | } |
191 | |
192 | void setVersionFixedIn(const QString & dupID) { |
193 | setData("cf_versionfixedin" , dupID); |
194 | } |
195 | QString versionFixedIn() const { |
196 | return getData("cf_versionfixedin" ); |
197 | } |
198 | |
199 | void setValid(bool valid) { |
200 | m_isValid = valid; |
201 | } |
202 | bool isValid() const { |
203 | return m_isValid; |
204 | } |
205 | |
206 | /** |
207 | * @return true if the bug report is still open |
208 | * @note false does not mean, that the bug report is closed, |
209 | * as the status could be unknown |
210 | */ |
211 | bool isOpen() const { |
212 | return isOpen(m_status); |
213 | } |
214 | |
215 | static bool isOpen(Status status) { |
216 | return (status == Unconfirmed || status == New || status == Assigned || status == Reopened); |
217 | } |
218 | |
219 | /** |
220 | * @return true if the bug report is closed |
221 | * @note false does not mean, that the bug report is still open, |
222 | * as the status could be unknown |
223 | */ |
224 | bool isClosed() const { |
225 | return isClosed(m_status); |
226 | } |
227 | |
228 | static bool isClosed(Status status) { |
229 | return (status == Resolved || status == NeedsInfo || status == Verified || status == Closed); |
230 | } |
231 | |
232 | static Status parseStatus(const QString &text); |
233 | static Resolution parseResolution(const QString &text); |
234 | |
235 | private: |
236 | void setData(const QString & key, const QString & val) { |
237 | m_dataMap.insert(key, val); |
238 | } |
239 | QString getData(const QString & key) const { |
240 | return m_dataMap.value(key); |
241 | } |
242 | |
243 | bool m_isValid; |
244 | Status m_status; |
245 | Resolution m_resolution; |
246 | |
247 | BugMap m_dataMap; |
248 | QStringList ; |
249 | }; |
250 | |
251 | //XML parser that creates a BugReport object |
252 | class BugReportXMLParser |
253 | { |
254 | public: |
255 | explicit BugReportXMLParser(const QByteArray &); |
256 | |
257 | BugReport parse(); |
258 | |
259 | bool isValid() const { |
260 | return m_valid; |
261 | } |
262 | |
263 | private: |
264 | QString getSimpleValue(const QString &); |
265 | |
266 | bool m_valid; |
267 | QDomDocument m_xml; |
268 | }; |
269 | |
270 | class BugListCSVParser |
271 | { |
272 | public: |
273 | explicit BugListCSVParser(const QByteArray&); |
274 | |
275 | bool isValid() const { |
276 | return m_isValid; |
277 | } |
278 | |
279 | BugMapList parse(); |
280 | |
281 | private: |
282 | bool m_isValid; |
283 | QByteArray m_data; |
284 | }; |
285 | |
286 | class Component |
287 | { |
288 | public: |
289 | Component(const QString& name, bool active): m_name(name), m_active(active) {} |
290 | |
291 | QString name() const { return m_name; } |
292 | bool active() const { return m_active; } |
293 | |
294 | private: |
295 | QString m_name; |
296 | bool m_active; |
297 | }; |
298 | |
299 | class Version |
300 | { |
301 | public: |
302 | |
303 | Version(const QString& name, bool active): m_name(name), m_active(active) {} |
304 | |
305 | QString name() const { return m_name; } |
306 | bool active() const { return m_active; } |
307 | |
308 | private: |
309 | QString m_name; |
310 | bool m_active; |
311 | }; |
312 | |
313 | |
314 | class Product |
315 | { |
316 | public: |
317 | |
318 | Product(const QString& name, bool active): m_name(name), m_active(active) {} |
319 | |
320 | bool isActive() const { return m_active; } |
321 | |
322 | void addComponent(const Component& component) { |
323 | m_allComponents.append(component.name()); |
324 | } |
325 | |
326 | void addVersion(const Version& version) { |
327 | m_allVersions.append(version.name()); |
328 | |
329 | if (version.active()) { |
330 | m_activeVersions.append(version.name()); |
331 | } else { |
332 | m_inactiveVersions.append(version.name()); |
333 | } |
334 | } |
335 | |
336 | QStringList components() const { return m_allComponents; } |
337 | |
338 | QStringList allVersions() const { return m_allVersions; } |
339 | QStringList activeVersions() const { return m_activeVersions; } |
340 | QStringList inactiveVersions() const { return m_inactiveVersions; } |
341 | |
342 | private: |
343 | |
344 | QString m_name; |
345 | bool m_active; |
346 | |
347 | QStringList m_allComponents; |
348 | |
349 | QStringList m_allVersions; |
350 | QStringList m_activeVersions; |
351 | QStringList m_inactiveVersions; |
352 | |
353 | }; |
354 | |
355 | class BugzillaManager : public QObject |
356 | { |
357 | Q_OBJECT |
358 | |
359 | public: |
360 | // Note: it expect the bugTrackerUrl parameter to contain the trailing slash. |
361 | // so it should be "https://bugs.kde.org/", not "https://bugs.kde.org" |
362 | explicit BugzillaManager(const QString &bugTrackerUrl, QObject *parent = 0); |
363 | |
364 | /* Login methods */ |
365 | void tryLogin(const QString&, const QString&); |
366 | bool getLogged() const; |
367 | |
368 | QString getUsername() const; |
369 | |
370 | /* Bugzilla Action methods */ |
371 | void fetchBugReport(int, QObject * jobOwner = 0); |
372 | |
373 | void searchBugs(const QStringList & products, const QString & severity, |
374 | const QString & date_start, const QString & date_end , QString ); |
375 | |
376 | void sendReport(const BugReport & report); |
377 | |
378 | void attachTextToReport(const QString & text, const QString & filename, |
379 | const QString & description, int bugId, const QString & ); |
380 | |
381 | void addMeToCC(int bugId); |
382 | |
383 | void fetchProductInfo(const QString &); |
384 | |
385 | /* Misc methods */ |
386 | QString urlForBug(int bug_number) const; |
387 | |
388 | void stopCurrentSearch(); |
389 | |
390 | private Q_SLOTS: |
391 | /* Slots to handle KJob::finished */ |
392 | void fetchBugJobFinished(KJob*); |
393 | void searchBugsJobFinished(KJob*); |
394 | void fetchProductInfoFinished(const QVariantMap&); |
395 | |
396 | void callMessage(const QList<QVariant> & result, const QVariant & id); |
397 | void callFault(int errorCode, const QString & errorString, const QVariant &id); |
398 | |
399 | Q_SIGNALS: |
400 | /* Bugzilla actions finished successfully */ |
401 | void loginFinished(bool); |
402 | void bugReportFetched(BugReport, QObject *); |
403 | void searchFinished(const BugMapList &); |
404 | void reportSent(int); |
405 | void attachToReportSent(int); |
406 | void addMeToCCFinished(int); |
407 | void productInfoFetched(Product); |
408 | |
409 | /* Bugzilla actions had errors */ |
410 | void loginError(const QString & errorMsg, const QString & extendedErrorMsg = QString()); |
411 | void bugReportError(const QString &, QObject *); |
412 | void searchError(const QString &); |
413 | void sendReportError(const QString & errorMsg, const QString & extendedErrorMsg = QString()); |
414 | void sendReportErrorInvalidValues(); //To use default values |
415 | void attachToReportError(const QString & errorMsg, const QString & extendedErrorMsg = QString()); |
416 | void addMeToCCError(const QString & errorMsg, const QString & extendedErrorMsg = QString()); |
417 | void productInfoError(); |
418 | |
419 | private: |
420 | QString m_bugTrackerUrl; |
421 | QString m_username; |
422 | bool m_logged; |
423 | |
424 | KIO::Job * m_searchJob; |
425 | KXmlRpc::Client *m_xmlRpcClient; |
426 | }; |
427 | |
428 | #endif |
429 | |