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