annotate historywidget.cpp @ 344:ccc55539e066

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