annotate historywidget.cpp @ 145:644bd31e8301

* Include the uncommitted item in general graph layout (in case it is not at the head, when other items will need to avoid it)
author Chris Cannam
date Wed, 01 Dec 2010 17:41:14 +0000
parents e6c6b88d19b9
children 465c8d51c6d5
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@133 224
Chris@133 225 csit->setCurrent(current);
Chris@133 226 csit->setNew(newid);
Chris@128 227 }
Chris@128 228 }
Chris@141 229
Chris@141 230 void HistoryWidget::connectSceneSignals()
Chris@141 231 {
Chris@141 232 ChangesetScene *scene = qobject_cast<ChangesetScene *>(m_panned->scene());
Chris@141 233 if (!scene) return;
Chris@141 234
Chris@141 235 connect(scene, SIGNAL(commit()),
Chris@141 236 this, SIGNAL(commit()));
Chris@141 237
Chris@141 238 connect(scene, SIGNAL(revert()),
Chris@141 239 this, SIGNAL(revert()));
Chris@141 240
Chris@141 241 connect(scene, SIGNAL(diffWorkingFolder()),
Chris@141 242 this, SIGNAL(diffWorkingFolder()));
Chris@141 243
Chris@141 244 connect(scene, SIGNAL(updateTo(QString)),
Chris@141 245 this, SIGNAL(updateTo(QString)));
Chris@141 246
Chris@141 247 connect(scene, SIGNAL(diffToCurrent(QString)),
Chris@141 248 this, SIGNAL(diffToCurrent(QString)));
Chris@141 249
Chris@141 250 connect(scene, SIGNAL(diffToPrevious(QString)),
Chris@141 251 this, SIGNAL(diffToPrevious(QString)));
Chris@141 252
Chris@141 253 connect(scene, SIGNAL(mergeFrom(QString)),
Chris@141 254 this, SIGNAL(mergeFrom(QString)));
Chris@141 255
Chris@141 256 connect(scene, SIGNAL(tag(QString)),
Chris@141 257 this, SIGNAL(tag(QString)));
Chris@141 258 }