annotate historywidget.cpp @ 365:1482f5b9f9dc feature_101

Add an explosion of menus and many keyboard shortcuts.
author Chris Cannam
date Fri, 18 Mar 2011 13:14:14 +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 }