comparison src/historywidget.cpp @ 370:b9c153e00e84

Move source files to src/
author Chris Cannam
date Thu, 24 Mar 2011 10:27:51 +0000
parents historywidget.cpp@4811eb34e819
children f051d210521e
comparison
equal deleted inserted replaced
369:19cce6d2c470 370:b9c153e00e84
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 EasyMercurial
5
6 Based on HgExplorer by Jari Korhonen
7 Copyright (c) 2010 Jari Korhonen
8 Copyright (c) 2011 Chris Cannam
9 Copyright (c) 2011 Queen Mary, University of London
10
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation; either version 2 of the
14 License, or (at your option) any later version. See the file
15 COPYING included with this distribution for more information.
16 */
17
18 #include "historywidget.h"
19
20 #include "changesetscene.h"
21 #include "panned.h"
22 #include "panner.h"
23 #include "grapher.h"
24 #include "debug.h"
25 #include "uncommitteditem.h"
26
27 #include <iostream>
28
29 #include <QGridLayout>
30
31 HistoryWidget::HistoryWidget() :
32 m_showUncommitted(false),
33 m_refreshNeeded(false)
34 {
35 m_panned = new Panned;
36 m_panner = new Panner;
37
38 m_panned->setDragMode(QGraphicsView::ScrollHandDrag);
39 m_panned->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
40
41 QGridLayout *layout = new QGridLayout;
42 layout->addWidget(m_panned, 0, 0);
43 layout->addWidget(m_panner, 0, 1);
44 m_panner->setMaximumWidth(80);
45 m_panner->connectToPanned(m_panned);
46
47 setLayout(layout);
48 }
49
50 HistoryWidget::~HistoryWidget()
51 {
52 clearChangesets();
53 }
54
55 QGraphicsScene *HistoryWidget::scene()
56 {
57 return m_panned->scene();
58 }
59
60 void HistoryWidget::clearChangesets()
61 {
62 foreach (Changeset *cs, m_changesets) delete cs;
63 m_changesets.clear();
64 }
65
66 void HistoryWidget::setCurrent(QStringList ids, QString branch,
67 bool showUncommitted)
68 {
69 if (m_currentIds == ids &&
70 m_currentBranch == branch &&
71 m_showUncommitted == showUncommitted) return;
72
73 DEBUG << "HistoryWidget::setCurrent: " << ids.size() << " ids, "
74 << "showUncommitted: " << showUncommitted << endl;
75
76 m_currentIds.clear();
77 m_currentBranch = branch;
78 m_showUncommitted = showUncommitted;
79
80 if (ids.empty()) return;
81
82 foreach (QString id, ids) {
83 m_currentIds.push_back(id);
84 }
85
86 m_refreshNeeded = true;
87 }
88
89 void HistoryWidget::parseNewLog(QString log)
90 {
91 DEBUG << "HistoryWidget::parseNewLog: log has " << log.length() << " chars" << endl;
92 Changesets csets = Changeset::parseChangesets(log);
93 DEBUG << "HistoryWidget::parseNewLog: log has " << csets.size() << " changesets" << endl;
94 replaceChangesets(csets);
95 m_refreshNeeded = true;
96 }
97
98 void HistoryWidget::parseIncrementalLog(QString log)
99 {
100 DEBUG << "HistoryWidget::parseIncrementalLog: log has " << log.length() << " chars" << endl;
101 Changesets csets = Changeset::parseChangesets(log);
102 DEBUG << "HistoryWidget::parseIncrementalLog: log has " << csets.size() << " changesets" << endl;
103 if (!csets.empty()) {
104 addChangesets(csets);
105 }
106 m_refreshNeeded = true;
107 }
108
109 void HistoryWidget::replaceChangesets(Changesets csets)
110 {
111 QSet<QString> oldIds;
112 foreach (Changeset *cs, m_changesets) {
113 oldIds.insert(cs->id());
114 }
115
116 QSet<QString> newIds;
117 foreach (Changeset *cs, csets) {
118 if (!oldIds.contains(cs->id())) {
119 newIds.insert(cs->id());
120 }
121 }
122
123 if (newIds.size() == csets.size()) {
124 // completely new set, unrelated to the old: don't mark new
125 m_newIds.clear();
126 } else {
127 m_newIds = newIds;
128 }
129
130 clearChangesets();
131 m_changesets = csets;
132 }
133
134 void HistoryWidget::addChangesets(Changesets csets)
135 {
136 m_newIds.clear();
137
138 if (csets.empty()) return;
139
140 foreach (Changeset *cs, csets) {
141 m_newIds.insert(cs->id());
142 }
143
144 DEBUG << "addChangesets: " << csets.size() << " new changesets have ("
145 << m_changesets.size() << " already)" << endl;
146
147 csets << m_changesets;
148 m_changesets = csets;
149 }
150
151 void HistoryWidget::update()
152 {
153 if (m_refreshNeeded) {
154 layoutAll();
155 }
156 }
157
158 void HistoryWidget::layoutAll()
159 {
160 m_refreshNeeded = false;
161
162 setChangesetParents();
163
164 ChangesetScene *scene = new ChangesetScene();
165 ChangesetItem *tipItem = 0;
166
167 QGraphicsScene *oldScene = m_panned->scene();
168
169 m_panned->setScene(0);
170 m_panner->setScene(0);
171
172 delete oldScene;
173
174 QGraphicsItem *toFocus = 0;
175
176 if (!m_changesets.empty()) {
177 Grapher g(scene);
178 try {
179 g.layout(m_changesets,
180 m_showUncommitted ? m_currentIds : QStringList(),
181 m_currentBranch);
182 } catch (std::string s) {
183 std::cerr << "Internal error: Layout failed: " << s << std::endl;
184 }
185 toFocus = g.getUncommittedItem();
186 if (!toFocus) {
187 toFocus = g.getItemFor(m_changesets[0]);
188 }
189 }
190
191 m_panned->setScene(scene);
192 m_panner->setScene(scene);
193
194 updateNewAndCurrentItems();
195
196 if (toFocus) {
197 toFocus->ensureVisible();
198 }
199
200 connectSceneSignals();
201 }
202
203 void HistoryWidget::setChangesetParents()
204 {
205 for (int i = 0; i < m_changesets.size(); ++i) {
206 Changeset *cs = m_changesets[i];
207 // Need to reset this, as Grapher::layout will recalculate it
208 // and we don't want to end up with twice the children for
209 // each parent...
210 cs->setChildren(QStringList());
211 }
212 for (int i = 0; i+1 < m_changesets.size(); ++i) {
213 Changeset *cs = m_changesets[i];
214 if (cs->parents().empty()) {
215 QStringList list;
216 list.push_back(m_changesets[i+1]->id());
217 cs->setParents(list);
218 }
219 }
220 }
221
222 void HistoryWidget::updateNewAndCurrentItems()
223 {
224 QGraphicsScene *scene = m_panned->scene();
225 if (!scene) return;
226
227 QList<QGraphicsItem *> items = scene->items();
228 foreach (QGraphicsItem *it, items) {
229
230 ChangesetItem *csit = dynamic_cast<ChangesetItem *>(it);
231 if (!csit) continue;
232
233 QString id = csit->getChangeset()->id();
234
235 bool current = m_currentIds.contains(id);
236 if (current) {
237 DEBUG << "id " << id << " is current" << endl;
238 }
239 bool newid = m_newIds.contains(id);
240 if (newid) {
241 DEBUG << "id " << id << " is new" << endl;
242 }
243
244 if (csit->isCurrent() != current || csit->isNew() != newid) {
245 csit->setCurrent(current);
246 csit->setNew(newid);
247 csit->update();
248 }
249 }
250 }
251
252 void HistoryWidget::connectSceneSignals()
253 {
254 ChangesetScene *scene = qobject_cast<ChangesetScene *>(m_panned->scene());
255 if (!scene) return;
256
257 connect(scene, SIGNAL(commit()),
258 this, SIGNAL(commit()));
259
260 connect(scene, SIGNAL(revert()),
261 this, SIGNAL(revert()));
262
263 connect(scene, SIGNAL(diffWorkingFolder()),
264 this, SIGNAL(diffWorkingFolder()));
265
266 connect(scene, SIGNAL(showSummary()),
267 this, SIGNAL(showSummary()));
268
269 connect(scene, SIGNAL(showWork()),
270 this, SIGNAL(showWork()));
271
272 connect(scene, SIGNAL(newBranch()),
273 this, SIGNAL(newBranch()));
274
275 connect(scene, SIGNAL(noBranch()),
276 this, SIGNAL(noBranch()));
277
278 connect(scene, SIGNAL(updateTo(QString)),
279 this, SIGNAL(updateTo(QString)));
280
281 connect(scene, SIGNAL(diffToCurrent(QString)),
282 this, SIGNAL(diffToCurrent(QString)));
283
284 connect(scene, SIGNAL(diffToParent(QString, QString)),
285 this, SIGNAL(diffToParent(QString, QString)));
286
287 connect(scene, SIGNAL(showSummary(Changeset *)),
288 this, SIGNAL(showSummary(Changeset *)));
289
290 connect(scene, SIGNAL(mergeFrom(QString)),
291 this, SIGNAL(mergeFrom(QString)));
292
293 connect(scene, SIGNAL(newBranch(QString)),
294 this, SIGNAL(newBranch(QString)));
295
296 connect(scene, SIGNAL(tag(QString)),
297 this, SIGNAL(tag(QString)));
298 }