1 /***************************************************************************
2 * Copyright (C) 2007 by Rajko Albrecht ral@alwins-world.de *
3 * http://kdesvn.alwins-world.de/ *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (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, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
20
21 #include "logitemmodel.h"
22 #include "logmodelhelper.h"
23
24 #include "svnqt/client.h"
25
26 #include <KLocalizedString>
27 #include <QTreeWidget>
28 #include <QMap>
29
SvnLogModel(const svn::LogEntriesMapPtr & _log,const QString & m_name,QObject * parent)30 SvnLogModel::SvnLogModel(const svn::LogEntriesMapPtr &_log, const QString &m_name, QObject *parent)
31 : QAbstractListModel(parent)
32 , m_emptyString()
33 , m_min(-1)
34 , m_max(-1)
35 , m_name()
36 , m_left(-1)
37 , m_right(-1)
38 {
39 setLogData(_log, m_name);
40 }
41
setLogData(const svn::LogEntriesMapPtr & log,const QString & name)42 void SvnLogModel::setLogData(const svn::LogEntriesMapPtr &log, const QString &name)
43 {
44 beginResetModel();
45 m_data.clear();
46 endResetModel();
47 m_name = name;
48 m_left = m_right = -1;
49
50 QMap<long int, SvnLogModelNodePtr> itemMap;
51
52 m_min = m_max = -1;
53
54 if (log->isEmpty()) {
55 return;
56 }
57
58 m_data.reserve(log->count());
59 beginInsertRows(QModelIndex(), 0, log->count() - 1);
60 svn::LogEntriesMap::const_iterator it = log->constBegin();
61 for (; it != log->constEnd(); ++it) {
62 SvnLogModelNodePtr np(new SvnLogModelNode((*it)));
63 m_data.append(np);
64 if ((*it).revision > m_max) {
65 m_max = (*it).revision;
66 }
67 if ((*it).revision < m_min || m_min == -1) {
68 m_min = (*it).revision;
69 }
70 itemMap[(*it).revision] = np;
71 }
72 endInsertRows();
73 QString bef = m_name;
74 qlonglong rev;
75 // YES! I'd checked it: this is much faster than getting list of keys
76 // and iterating over that list!
77 for (long c = m_max; c > -1; --c) {
78 if (!itemMap.contains(c)) {
79 continue;
80 }
81 if (itemMap[c]->realName().isEmpty()) {
82 itemMap[c]->setRealName(bef);
83 }
84 itemMap[c]->copiedFrom(bef, rev);
85 }
86 }
87
min() const88 qlonglong SvnLogModel::min() const
89 {
90 return m_min;
91 }
92
max() const93 qlonglong SvnLogModel::max() const
94 {
95 return m_max;
96 }
97
rowCount(const QModelIndex & parent) const98 int SvnLogModel::rowCount(const QModelIndex &parent) const
99 {
100 Q_UNUSED(parent);
101 return m_data.count();
102 }
103
data(const QModelIndex & index,int role) const104 QVariant SvnLogModel::data(const QModelIndex &index, int role) const
105 {
106 if (!index.isValid() || index.row() >= m_data.count()) {
107 return QVariant();
108 }
109 const SvnLogModelNodePtr &_l = m_data.at(index.row());
110
111 switch (role) {
112 case Qt::DisplayRole:
113 switch (index.column()) {
114 case Revision:
115 return _l->revision();
116 case Author:
117 return _l->author();
118 case Date:
119 return _l->date();
120 case Message:
121 return _l->shortMessage();
122 }
123 break;
124 case Qt::DecorationRole:
125 if (index.column() == 0) {
126 if (index.row() == m_left) {
127 return QIcon::fromTheme(QStringLiteral("kdesvnleft"));
128 }
129 if (index.row() == m_right) {
130 return QIcon::fromTheme(QStringLiteral("kdesvnright"));
131 }
132 return QStringLiteral(" ");
133 }
134 break;
135 }
136 return QVariant();
137 }
138
toRevision(const QModelIndex & index) const139 qlonglong SvnLogModel::toRevision(const QModelIndex &index)const
140 {
141 if (!index.isValid() || index.row() >= m_data.count()) {
142 return -1;
143 }
144 return m_data[index.row()]->revision();
145 }
146
fullMessage(const QModelIndex & index) const147 const QString &SvnLogModel::fullMessage(const QModelIndex &index)const
148 {
149 if (!index.isValid() || index.row() >= m_data.count()) {
150 return m_emptyString;
151 }
152 return m_data[index.row()]->message();
153 }
154
realName(const QModelIndex & index)155 const QString &SvnLogModel::realName(const QModelIndex &index)
156 {
157 if (!index.isValid() || index.row() >= m_data.count()) {
158 return m_emptyString;
159 }
160 return m_data[index.row()]->realName();
161 }
162
columnCount(const QModelIndex &) const163 int SvnLogModel::columnCount(const QModelIndex &)const
164 {
165 return Count;
166 }
167
headerData(int section,Qt::Orientation orientation,int role) const168 QVariant SvnLogModel::headerData(int section, Qt::Orientation orientation, int role) const
169 {
170 Q_UNUSED(orientation);
171 switch (role) {
172 case Qt::DisplayRole:
173 switch (section) {
174 case Revision:
175 return i18n("Revision");
176 case Author:
177 return i18n("Author");
178 case Date:
179 return i18n("Date");
180 case Message:
181 return i18n("Message");
182 }
183 }
184 return QVariant();
185 }
186
indexNode(const QModelIndex & index) const187 SvnLogModelNodePtr SvnLogModel::indexNode(const QModelIndex &index)const
188 {
189 if (!index.isValid() || index.row() >= m_data.count()) {
190 return SvnLogModelNodePtr();
191 }
192 return m_data.at(index.row());
193 }
194
fillChangedPaths(const QModelIndex & index,QTreeWidget * where)195 void SvnLogModel::fillChangedPaths(const QModelIndex &index, QTreeWidget *where)
196 {
197 if (!where || !index.isValid() || index.row() >= m_data.count()) {
198 return;
199 }
200 where->clear();
201 const SvnLogModelNodePtr &_l = m_data.at(index.row());
202 if (_l->changedPaths().isEmpty()) {
203 return;
204 }
205 QList<QTreeWidgetItem *> _list;
206 for (int i = 0; i < _l->changedPaths().count(); ++i) {
207 _list.append(new LogChangePathItem(_l->changedPaths()[i]));
208 }
209 where->addTopLevelItems(_list);
210 where->resizeColumnToContents(0);
211 where->resizeColumnToContents(1);
212 where->resizeColumnToContents(2);
213 where->sortByColumn(1, Qt::AscendingOrder);
214 }
215
leftRow() const216 int SvnLogModel::leftRow()const
217 {
218 return m_left;
219 }
220
rightRow() const221 int SvnLogModel::rightRow()const
222 {
223 return m_right;
224 }
225
setLeftRow(int v)226 void SvnLogModel::setLeftRow(int v)
227 {
228 if (m_right == v) {
229 m_right = -1;
230 }
231 m_left = v;
232 }
233
setRightRow(int v)234 void SvnLogModel::setRightRow(int v)
235 {
236 if (m_left == v) {
237 m_left = -1;
238 }
239 m_right = v;
240 }
241
242 //
243 // SvnLogSortModel
244 //
setSourceModel(QAbstractItemModel * sourceModel)245 void SvnLogSortModel::setSourceModel(QAbstractItemModel *sourceModel)
246 {
247 m_sourceModel = qobject_cast<SvnLogModel*>(sourceModel);
248 QSortFilterProxyModel::setSourceModel(sourceModel);
249 }
250
lessThan(const QModelIndex & source_left,const QModelIndex & source_right) const251 bool SvnLogSortModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
252 {
253 if(source_left.column() != source_right.column() || !m_sourceModel) {
254 return QSortFilterProxyModel::lessThan(source_left, source_right);
255 }
256 const SvnLogModelNodePtr &dataLeft = m_sourceModel->m_data.at(source_left.row());
257 const SvnLogModelNodePtr &dataRight = m_sourceModel->m_data.at(source_right.row());
258 switch (source_left.column()) {
259 case SvnLogModel::Author:
260 return dataLeft->author() < dataRight->author();
261 case SvnLogModel::Revision:
262 return dataLeft->revision() < dataRight->revision();
263 case SvnLogModel::Date:
264 return dataLeft->dateMSec() < dataRight->dateMSec();
265 case SvnLogModel::Message:
266 return dataLeft->message() < dataRight->message();
267 default:
268 break;
269 }
270 return QSortFilterProxyModel::lessThan(source_left, source_right);
271 }
272