annotate historywidget.cpp @ 147:465c8d51c6d5

* Don't show tip tag; return to using incremental log on commit
author Chris Cannam
date Wed, 01 Dec 2010 20:19:21 +0000
parents 644bd31e8301
children 2fef6b0dfbe8
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@116 8 Copyright (c) 2010 Chris Cannam
Chris@116 9 Copyright (c) 2010 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@116 31 HistoryWidget::HistoryWidget()
Chris@116 32 {
Chris@116 33 m_panned = new Panned;
Chris@116 34 m_panner = new Panner;
Chris@116 35
Chris@116 36 QGridLayout *layout = new QGridLayout;
Chris@116 37 layout->addWidget(m_panned, 0, 0);
Chris@116 38 layout->addWidget(m_panner, 0, 1);
Chris@116 39 m_panner->setMaximumWidth(80);
Chris@116 40 m_panner->connectToPanned(m_panned);
Chris@116 41
Chris@116 42 setLayout(layout);
Chris@116 43 }
Chris@116 44
Chris@116 45 HistoryWidget::~HistoryWidget()
Chris@116 46 {
Chris@116 47 clearChangesets();
Chris@145 48 }
Chris@145 49
Chris@145 50 QGraphicsScene *HistoryWidget::scene()
Chris@145 51 {
Chris@145 52 return m_panned->scene();
Chris@116 53 }
Chris@116 54
Chris@116 55 void HistoryWidget::clearChangesets()
Chris@116 56 {
Chris@116 57 foreach (Changeset *cs, m_changesets) delete cs;
Chris@116 58 m_changesets.clear();
Chris@116 59 }
Chris@128 60
Chris@145 61 void HistoryWidget::setCurrent(QStringList ids, bool showUncommitted)
Chris@128 62 {
Chris@145 63 if (m_currentIds == ids && m_showUncommitted == showUncommitted) return;
Chris@145 64
Chris@145 65 DEBUG << "HistoryWidget::setCurrent: " << ids.size() << " ids, "
Chris@145 66 << "showUncommitted: " << showUncommitted << endl;
Chris@145 67
Chris@133 68 m_currentIds.clear();
Chris@145 69 m_uncommittedParentId = "";
Chris@145 70 m_showUncommitted = showUncommitted;
Chris@145 71
Chris@145 72 if (ids.empty()) return;
Chris@145 73
Chris@133 74 foreach (QString id, ids) {
Chris@133 75 m_currentIds.push_back(id);
Chris@133 76 }
Chris@128 77
Chris@145 78 if (m_showUncommitted) m_uncommittedParentId = m_currentIds[0];
Chris@145 79 layoutAll();
Chris@128 80 }
Chris@116 81
Chris@120 82 void HistoryWidget::parseNewLog(QString log)
Chris@120 83 {
Chris@120 84 DEBUG << "HistoryWidget::parseNewLog: log has " << log.length() << " chars" << endl;
Chris@122 85 Changesets csets = Changeset::parseChangesets(log);
Chris@120 86 DEBUG << "HistoryWidget::parseNewLog: log has " << csets.size() << " changesets" << endl;
Chris@133 87 replaceChangesets(csets);
Chris@120 88 layoutAll();
Chris@120 89 }
Chris@120 90
Chris@120 91 void HistoryWidget::parseIncrementalLog(QString log)
Chris@120 92 {
Chris@120 93 DEBUG << "HistoryWidget::parseIncrementalLog: log has " << log.length() << " chars" << endl;
Chris@122 94 Changesets csets = Changeset::parseChangesets(log);
Chris@120 95 DEBUG << "HistoryWidget::parseIncrementalLog: log has " << csets.size() << " changesets" << endl;
Chris@120 96 if (!csets.empty()) {
Chris@133 97 addChangesets(csets);
Chris@120 98 layoutAll();
Chris@120 99 }
Chris@120 100 }
Chris@120 101
Chris@133 102 void HistoryWidget::replaceChangesets(Changesets csets)
Chris@133 103 {
Chris@133 104 QSet<QString> oldIds;
Chris@133 105 foreach (Changeset *cs, m_changesets) {
Chris@133 106 oldIds.insert(cs->id());
Chris@133 107 }
Chris@133 108
Chris@133 109 QSet<QString> newIds;
Chris@133 110 foreach (Changeset *cs, csets) {
Chris@133 111 if (!oldIds.contains(cs->id())) {
Chris@133 112 newIds.insert(cs->id());
Chris@133 113 }
Chris@133 114 }
Chris@133 115
Chris@133 116 if (newIds.size() == csets.size()) {
Chris@133 117 // completely new set, unrelated to the old: don't mark new
Chris@133 118 m_newIds.clear();
Chris@133 119 } else {
Chris@133 120 m_newIds = newIds;
Chris@133 121 }
Chris@133 122
Chris@133 123 clearChangesets();
Chris@133 124 m_changesets = csets;
Chris@133 125 }
Chris@133 126
Chris@133 127 void HistoryWidget::addChangesets(Changesets csets)
Chris@133 128 {
Chris@133 129 m_newIds.clear();
Chris@138 130
Chris@138 131 if (csets.empty()) return;
Chris@138 132
Chris@133 133 foreach (Changeset *cs, csets) {
Chris@133 134 m_newIds.insert(cs->id());
Chris@133 135 }
Chris@133 136
Chris@138 137 DEBUG << "addChangesets: " << csets.size() << " new changesets" << endl;
Chris@138 138
Chris@133 139 csets << m_changesets;
Chris@133 140 m_changesets = csets;
Chris@133 141 }
Chris@133 142
Chris@120 143 void HistoryWidget::layoutAll()
Chris@116 144 {
Chris@122 145 setChangesetParents();
Chris@122 146
Chris@119 147 ChangesetScene *scene = new ChangesetScene();
Chris@116 148 ChangesetItem *tipItem = 0;
Chris@116 149
Chris@138 150 QGraphicsScene *oldScene = m_panned->scene();
Chris@138 151
Chris@138 152 m_panned->setScene(0);
Chris@138 153 m_panner->setScene(0);
Chris@138 154
Chris@138 155 delete oldScene;
Chris@138 156
Chris@145 157 QGraphicsItem *toFocus = 0;
Chris@145 158
Chris@120 159 if (!m_changesets.empty()) {
Chris@116 160 Grapher g(scene);
Chris@116 161 try {
Chris@145 162 g.layout(m_changesets, m_uncommittedParentId);
Chris@116 163 } catch (std::string s) {
Chris@116 164 std::cerr << "Internal error: Layout failed: " << s << std::endl;
Chris@116 165 }
Chris@145 166 toFocus = g.getUncommittedItem();
Chris@145 167 if (!toFocus) {
Chris@145 168 toFocus = g.getItemFor(m_changesets[0]);
Chris@145 169 }
Chris@134 170 }
Chris@134 171
Chris@116 172 m_panned->setScene(scene);
Chris@116 173 m_panner->setScene(scene);
Chris@116 174
Chris@133 175 updateNewAndCurrentItems();
Chris@134 176
Chris@145 177 if (toFocus) {
Chris@145 178 toFocus->ensureVisible();
Chris@134 179 }
Chris@141 180
Chris@141 181 connectSceneSignals();
Chris@116 182 }
Chris@116 183
Chris@122 184 void HistoryWidget::setChangesetParents()
Chris@116 185 {
Chris@139 186 for (int i = 0; i < m_changesets.size(); ++i) {
Chris@122 187 Changeset *cs = m_changesets[i];
Chris@123 188 // Need to reset this, as Grapher::layout will recalculate it
Chris@123 189 // and we don't want to end up with twice the children for
Chris@123 190 // each parent...
Chris@123 191 cs->setChildren(QStringList());
Chris@139 192 }
Chris@139 193 for (int i = 0; i+1 < m_changesets.size(); ++i) {
Chris@139 194 Changeset *cs = m_changesets[i];
Chris@116 195 if (cs->parents().empty()) {
Chris@116 196 QStringList list;
Chris@122 197 list.push_back(m_changesets[i+1]->id());
Chris@116 198 cs->setParents(list);
Chris@116 199 }
Chris@116 200 }
Chris@116 201 }
Chris@128 202
Chris@133 203 void HistoryWidget::updateNewAndCurrentItems()
Chris@128 204 {
Chris@128 205 QGraphicsScene *scene = m_panned->scene();
Chris@128 206 if (!scene) return;
Chris@133 207
Chris@128 208 QList<QGraphicsItem *> items = scene->items();
Chris@128 209 foreach (QGraphicsItem *it, items) {
Chris@133 210
Chris@128 211 ChangesetItem *csit = dynamic_cast<ChangesetItem *>(it);
Chris@133 212 if (!csit) continue;
Chris@133 213
Chris@133 214 QString id = csit->getChangeset()->id();
Chris@133 215
Chris@133 216 bool current = m_currentIds.contains(id);
Chris@133 217 if (current) {
Chris@133 218 DEBUG << "id " << id << " is current" << endl;
Chris@133 219 }
Chris@133 220 bool newid = m_newIds.contains(id);
Chris@133 221 if (newid) {
Chris@133 222 DEBUG << "id " << id << " is new" << endl;
Chris@133 223 }
Chris@147 224
Chris@147 225 if (csit->isCurrent() != current || csit->isNew() != newid) {
Chris@147 226 csit->setCurrent(current);
Chris@147 227 csit->setNew(newid);
Chris@147 228 csit->update();
Chris@147 229 }
Chris@128 230 }
Chris@128 231 }
Chris@141 232
Chris@141 233 void HistoryWidget::connectSceneSignals()
Chris@141 234 {
Chris@141 235 ChangesetScene *scene = qobject_cast<ChangesetScene *>(m_panned->scene());
Chris@141 236 if (!scene) return;
Chris@141 237
Chris@141 238 connect(scene, SIGNAL(commit()),
Chris@141 239 this, SIGNAL(commit()));
Chris@141 240
Chris@141 241 connect(scene, SIGNAL(revert()),
Chris@141 242 this, SIGNAL(revert()));
Chris@141 243
Chris@141 244 connect(scene, SIGNAL(diffWorkingFolder()),
Chris@141 245 this, SIGNAL(diffWorkingFolder()));
Chris@141 246
Chris@141 247 connect(scene, SIGNAL(updateTo(QString)),
Chris@141 248 this, SIGNAL(updateTo(QString)));
Chris@141 249
Chris@141 250 connect(scene, SIGNAL(diffToCurrent(QString)),
Chris@141 251 this, SIGNAL(diffToCurrent(QString)));
Chris@141 252
Chris@141 253 connect(scene, SIGNAL(diffToPrevious(QString)),
Chris@141 254 this, SIGNAL(diffToPrevious(QString)));
Chris@141 255
Chris@141 256 connect(scene, SIGNAL(mergeFrom(QString)),
Chris@141 257 this, SIGNAL(mergeFrom(QString)));
Chris@141 258
Chris@141 259 connect(scene, SIGNAL(tag(QString)),
Chris@141 260 this, SIGNAL(tag(QString)));
Chris@141 261 }