1/*******************************************************************
2* productmapping.cpp
3* Copyright 2009 Dario Andres Rodriguez <andresbajotierra@gmail.com>
4*
5* This program is free software; you can redistribute it and/or
6* modify it under the terms of the GNU General Public License as
7* published by the Free Software Foundation; either version 2 of
8* the License, or (at your option) any later version.
9*
10* This program is distributed in the hope that it will be useful,
11* but WITHOUT ANY WARRANTY; without even the implied warranty of
12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13* GNU General Public License for more details.
14*
15* You should have received a copy of the GNU General Public License
16* along with this program. If not, see <http://www.gnu.org/licenses/>.
17*
18******************************************************************/
19
20#include "productmapping.h"
21
22#include <KConfig>
23#include <KConfigGroup>
24#include <KDebug>
25
26#include "bugzillalib.h"
27#include "crashedapplication.h"
28
29ProductMapping::ProductMapping(const CrashedApplication * crashedApp, BugzillaManager * bzManager, QObject * parent)
30 : QObject(parent)
31 , m_crashedAppPtr(crashedApp)
32 , m_bugzillaManagerPtr(bzManager)
33 , m_bugzillaProductDisabled(false)
34 , m_bugzillaVersionDisabled(false)
35
36{
37 //Default "fallback" values
38 m_bugzillaProduct = crashedApp->fakeExecutableBaseName();
39 m_bugzillaComponent = QLatin1String("general");
40 m_bugzillaVersionString = QLatin1String("unspecified");
41 m_relatedBugzillaProducts = QStringList() << m_bugzillaProduct;
42
43 map(crashedApp->fakeExecutableBaseName());
44
45 //Get valid versions
46 connect(m_bugzillaManagerPtr, SIGNAL(productInfoFetched(Product)),
47 this, SLOT(checkProductInfo(Product)));
48
49 m_bugzillaManagerPtr->fetchProductInfo(m_bugzillaProduct);
50}
51
52void ProductMapping::map(const QString & appName)
53{
54 mapUsingInternalFile(appName);
55 getRelatedProductsUsingInternalFile(m_bugzillaProduct);
56}
57
58void ProductMapping::mapUsingInternalFile(const QString & appName)
59{
60 KConfig mappingsFile(QString::fromLatin1("mappings"), KConfig::NoGlobals, "appdata");
61 const KConfigGroup mappings = mappingsFile.group("Mappings");
62 if (mappings.hasKey(appName)) {
63 QString mappingString = mappings.readEntry(appName);
64 if (!mappingString.isEmpty()) {
65 QStringList list = mappingString.split('|', QString::SkipEmptyParts);
66 if (list.count()==2) {
67 m_bugzillaProduct = list.at(0);
68 m_bugzillaComponent = list.at(1);
69 m_relatedBugzillaProducts = QStringList() << m_bugzillaProduct;
70 } else {
71 kWarning() << "Error while reading mapping entry. Sections found " << list.count();
72 }
73 } else {
74 kWarning() << "Error while reading mapping entry. Entry exists but it is empty "
75 "(or there was an error when reading)";
76 }
77 }
78}
79
80void ProductMapping::getRelatedProductsUsingInternalFile(const QString & bugzillaProduct)
81{
82 //ProductGroup -> kontact=kdepim
83 //Groups -> kdepim=kontact|kmail|korganizer|akonadi|pimlibs..etc
84
85 KConfig mappingsFile(QString::fromLatin1("mappings"), KConfig::NoGlobals, "appdata");
86 const KConfigGroup productGroup = mappingsFile.group("ProductGroup");
87
88 //Get groups of the application
89 QStringList groups;
90 if (productGroup.hasKey(bugzillaProduct)) {
91 QString group = productGroup.readEntry(bugzillaProduct);
92 if (group.isEmpty()) {
93 kWarning() << "Error while reading mapping entry. Entry exists but it is empty "
94 "(or there was an error when reading)";
95 return;
96 }
97 groups = group.split('|', QString::SkipEmptyParts);
98 }
99
100 //All KDE apps use the KDE Platform (basic libs)
101 groups << QLatin1String("kdeplatform");
102
103 //Add the product itself
104 m_relatedBugzillaProducts = QStringList() << m_bugzillaProduct;
105
106 //Get related products of each related group
107 Q_FOREACH( const QString & group, groups ) {
108 const KConfigGroup bzGroups = mappingsFile.group("BZGroups");
109 if (bzGroups.hasKey(group)) {
110 QString bzGroup = bzGroups.readEntry(group);
111 if (!bzGroup.isEmpty()) {
112 QStringList relatedGroups = bzGroup.split('|', QString::SkipEmptyParts);
113 if (relatedGroups.size()>0) {
114 m_relatedBugzillaProducts.append(relatedGroups);
115 }
116 } else {
117 kWarning() << "Error while reading mapping entry. Entry exists but it is empty "
118 "(or there was an error when reading)";
119 }
120 }
121 }
122}
123
124void ProductMapping::checkProductInfo(const Product & product)
125{
126 // check whether the product itself is disabled for new reports,
127 // which usually means that product/application is unmaintained.
128 m_bugzillaProductDisabled = !product.isActive();
129
130 // check whether the product on bugzilla contains the expected component
131 if (! product.components().contains(m_bugzillaComponent)) {
132 m_bugzillaComponent = QLatin1String("general");
133 }
134
135 // find the appropriate version to use on bugzilla
136 const QString version = m_crashedAppPtr->version();
137 const QStringList& allVersions = product.allVersions();
138
139 if (allVersions.contains(version)) {
140 //The version the crash application provided is a valid bugzilla version: use it !
141 m_bugzillaVersionString = version;
142 } else if (version.endsWith(QLatin1String(".00"))) {
143 //check if there is a version on bugzilla with just ".0"
144 const QString shorterVersion = version.left(version.size() - 1);
145 if (allVersions.contains(shorterVersion)) {
146 m_bugzillaVersionString = shorterVersion;
147 }
148 }
149
150 // check whether that verions is disabled for new reports, which
151 // usually means that version is outdated and not supported anymore.
152 const QStringList& inactiveVersions = product.inactiveVersions();
153 m_bugzillaVersionDisabled = inactiveVersions.contains(m_bugzillaVersionString);
154
155}
156
157QStringList ProductMapping::relatedBugzillaProducts() const
158{
159 return m_relatedBugzillaProducts;
160}
161
162QString ProductMapping::bugzillaProduct() const
163{
164 return m_bugzillaProduct;
165}
166
167QString ProductMapping::bugzillaComponent() const
168{
169 return m_bugzillaComponent;
170}
171
172QString ProductMapping::bugzillaVersion() const
173{
174 return m_bugzillaVersionString;
175}
176
177bool ProductMapping::bugzillaProductDisabled() const
178{
179 return m_bugzillaProductDisabled;
180}
181
182bool ProductMapping::bugzillaVersionDisabled() const
183{
184 return m_bugzillaVersionDisabled;
185}
186