annotate changesetitem.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@57 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@57 2
Chris@57 3 /*
Chris@57 4 EasyMercurial
Chris@57 5
Chris@57 6 Based on HgExplorer by Jari Korhonen
Chris@57 7 Copyright (c) 2010 Jari Korhonen
Chris@57 8 Copyright (c) 2010 Chris Cannam
Chris@57 9 Copyright (c) 2010 Queen Mary, University of London
Chris@57 10
Chris@57 11 This program is free software; you can redistribute it and/or
Chris@57 12 modify it under the terms of the GNU General Public License as
Chris@57 13 published by the Free Software Foundation; either version 2 of the
Chris@57 14 License, or (at your option) any later version. See the file
Chris@57 15 COPYING included with this distribution for more information.
Chris@57 16 */
Chris@57 17
Chris@43 18 #include "changesetitem.h"
Chris@117 19 #include "changesetdetailitem.h"
Chris@43 20 #include "changeset.h"
Chris@53 21 #include "textabbrev.h"
Chris@53 22 #include "colourset.h"
Chris@117 23 #include "debug.h"
Chris@43 24
Chris@43 25 #include <QPainter>
Chris@117 26 #include <QGraphicsScene>
Chris@132 27 #include <QGraphicsSceneMouseEvent>
Chris@140 28 #include <QMenu>
Chris@140 29 #include <QAction>
Chris@140 30 #include <QLabel>
Chris@140 31 #include <QWidgetAction>
Chris@43 32
Chris@53 33 ChangesetItem::ChangesetItem(Changeset *cs) :
Chris@117 34 m_changeset(cs), m_detail(0),
Chris@133 35 m_showBranch(false), m_column(0), m_row(0), m_wide(false),
Chris@133 36 m_current(false), m_new(false)
Chris@53 37 {
Chris@53 38 m_font = QFont();
Chris@53 39 m_font.setPixelSize(11);
Chris@53 40 m_font.setBold(false);
Chris@53 41 m_font.setItalic(false);
Chris@53 42 }
Chris@53 43
Chris@141 44 QString
Chris@141 45 ChangesetItem::getId()
Chris@141 46 {
Chris@141 47 return m_changeset->id();
Chris@141 48 }
Chris@141 49
Chris@43 50 QRectF
Chris@43 51 ChangesetItem::boundingRect() const
Chris@43 52 {
Chris@55 53 int w = 100;
Chris@55 54 if (m_wide) w = 180;
Chris@55 55 return QRectF(-((w-50)/2 - 1), -30, w - 3, 79);
Chris@43 56 }
Chris@43 57
Chris@43 58 void
Chris@119 59 ChangesetItem::showDetail()
Chris@117 60 {
Chris@119 61 if (m_detail) return;
Chris@117 62 m_detail = new ChangesetDetailItem(m_changeset);
Chris@117 63 m_detail->setZValue(zValue() + 1);
Chris@117 64 scene()->addItem(m_detail);
Chris@117 65 int w = 100;
Chris@117 66 if (m_wide) w = 180;
Chris@124 67 int h = 80;
Chris@124 68 // m_detail->moveBy(x() - (m_detail->boundingRect().width() - 50) / 2,
Chris@124 69 // y() + 60);
Chris@124 70 m_detail->moveBy(x() + (w + 50) / 2 + 10 + 0.5,
Chris@124 71 y() - (m_detail->boundingRect().height() - h) / 2 + 0.5);
Chris@119 72 emit detailShown();
Chris@119 73 }
Chris@119 74
Chris@119 75 void
Chris@119 76 ChangesetItem::hideDetail()
Chris@119 77 {
Chris@124 78 if (!m_detail) return;
Chris@124 79 scene()->removeItem(m_detail);
Chris@119 80 delete m_detail;
Chris@119 81 m_detail = 0;
Chris@119 82 emit detailHidden();
Chris@119 83 }
Chris@119 84
Chris@119 85 void
Chris@119 86 ChangesetItem::mousePressEvent(QGraphicsSceneMouseEvent *e)
Chris@119 87 {
Chris@119 88 DEBUG << "ChangesetItem::mousePressEvent" << endl;
Chris@132 89 if (e->button() == Qt::LeftButton) {
Chris@132 90 if (m_detail) {
Chris@132 91 hideDetail();
Chris@132 92 } else {
Chris@132 93 showDetail();
Chris@132 94 }
Chris@140 95 } else if (e->button() == Qt::RightButton) {
Chris@141 96 if (m_detail) {
Chris@141 97 hideDetail();
Chris@141 98 }
Chris@140 99 activateMenu();
Chris@119 100 }
Chris@117 101 }
Chris@117 102
Chris@117 103 void
Chris@140 104 ChangesetItem::activateMenu()
Chris@140 105 {
Chris@140 106 QMenu *menu = new QMenu;
Chris@141 107 QLabel *label = new QLabel(tr("<qt><b>Revision: </b>%1</qt>")
Chris@140 108 .arg(m_changeset->id()));
Chris@141 109 QWidgetAction *wa = new QWidgetAction(menu);
Chris@140 110 wa->setDefaultWidget(label);
Chris@140 111 menu->addAction(wa);
Chris@140 112 menu->addSeparator();
Chris@141 113
Chris@140 114 QAction *update = menu->addAction(tr("Update to this revision"));
Chris@141 115 connect(update, SIGNAL(triggered()), this, SLOT(updateActivated()));
Chris@141 116
Chris@140 117 menu->addSeparator();
Chris@141 118
Chris@140 119 QAction *diffParent = menu->addAction(tr("Diff against previous revision"));
Chris@141 120 connect(diffParent, SIGNAL(triggered()), this, SLOT(diffToPreviousActivated()));
Chris@140 121 QAction *diffCurrent = menu->addAction(tr("Diff against current revision"));
Chris@141 122 connect(diffCurrent, SIGNAL(triggered()), this, SLOT(diffToCurrentActivated()));
Chris@141 123
Chris@140 124 menu->addSeparator();
Chris@141 125
Chris@140 126 QAction *merge = menu->addAction(tr("Merge from here to current"));
Chris@141 127 connect(merge, SIGNAL(triggered()), this, SLOT(mergeActivated()));
Chris@140 128 QAction *tag = menu->addAction(tr("Tag this revision"));
Chris@141 129 connect(tag, SIGNAL(triggered()), this, SLOT(tagActivated()));
Chris@141 130
Chris@141 131 QAction *a = menu->exec(QCursor::pos());
Chris@141 132 ungrabMouse();
Chris@141 133 if (a) a->trigger();
Chris@140 134 }
Chris@140 135
Chris@141 136 void ChangesetItem::updateActivated() { emit updateTo(getId()); }
Chris@141 137 void ChangesetItem::diffToPreviousActivated() { emit diffToPrevious(getId()); }
Chris@141 138 void ChangesetItem::diffToCurrentActivated() { emit diffToCurrent(getId()); }
Chris@141 139 void ChangesetItem::mergeActivated() { emit mergeFrom(getId()); }
Chris@141 140 void ChangesetItem::tagActivated() { emit tag(getId()); }
Chris@141 141
Chris@140 142 void
Chris@43 143 ChangesetItem::paint(QPainter *paint, const QStyleOptionGraphicsItem *option,
Chris@43 144 QWidget *w)
Chris@43 145 {
Chris@53 146 paint->save();
Chris@53 147
Chris@53 148 ColourSet *colourSet = ColourSet::instance();
Chris@53 149 QColor branchColour = colourSet->getColourFor(m_changeset->branch());
Chris@128 150 QColor userColour = colourSet->getColourFor(m_changeset->author());
Chris@53 151
Chris@53 152 QFont f(m_font);
Chris@53 153
Chris@54 154 QTransform t = paint->worldTransform();
Chris@53 155 float scale = std::min(t.m11(), t.m22());
Chris@53 156 if (scale > 1.0) {
Chris@53 157 int ps = int((f.pixelSize() / scale) + 0.5);
Chris@53 158 if (ps < 8) ps = 8;
Chris@53 159 f.setPixelSize(ps);
Chris@53 160 }
Chris@54 161
Chris@54 162 if (scale < 0.1) {
Chris@54 163 paint->setPen(QPen(branchColour, 0));
Chris@54 164 } else {
Chris@54 165 paint->setPen(QPen(branchColour, 2));
Chris@54 166 }
Chris@53 167
Chris@53 168 paint->setFont(f);
Chris@53 169 QFontMetrics fm(f);
Chris@53 170 int fh = fm.height();
Chris@55 171
Chris@55 172 int width = 100;
Chris@55 173 if (m_wide) width = 180;
Chris@55 174 int x0 = -((width - 50) / 2 - 1);
Chris@55 175
Chris@56 176 int height = 49;
Chris@56 177 QRectF r(x0, 0, width - 3, height);
Chris@53 178 paint->drawRect(r);
Chris@53 179
Chris@133 180 if (m_new) {
Chris@133 181 paint->save();
Chris@133 182 paint->setPen(Qt::yellow);
Chris@133 183 paint->drawRect(QRectF(x0 - 2, -2, width + 1, height + 4));
Chris@133 184 paint->restore();
Chris@133 185 }
Chris@133 186
Chris@128 187 if (m_current) {
Chris@128 188 paint->drawRect(QRectF(x0 - 4, -4, width + 5, height + 8));
Chris@128 189 }
Chris@128 190
Chris@145 191 if (scale < 0.2) {
Chris@53 192 paint->restore();
Chris@53 193 return;
Chris@53 194 }
Chris@53 195
Chris@55 196 paint->fillRect(QRectF(x0 + 0.5, 0.5, width - 4, fh - 0.5),
Chris@55 197 QBrush(userColour));
Chris@53 198
Chris@53 199 paint->setPen(QPen(Qt::white));
Chris@53 200
Chris@55 201 int wid = width - 5;
Chris@128 202 QString person = TextAbbrev::abbreviate(m_changeset->authorName(), fm, wid);
Chris@55 203 paint->drawText(x0 + 3, fm.ascent(), person);
Chris@53 204
Chris@53 205 paint->setPen(QPen(Qt::black));
Chris@53 206
Chris@128 207 QString tags = m_changeset->tags().join(" ").trimmed();
Chris@128 208 if (tags != "") {
Chris@128 209 int tw = fm.width(tags);
Chris@128 210 paint->fillRect(QRectF(x0 + width - 8 - tw, 1, tw + 4, fh - 1),
Chris@128 211 QBrush(Qt::yellow));
Chris@128 212 paint->drawText(x0 + width - 6 - tw, fm.ascent(), tags);
Chris@128 213 }
Chris@128 214
Chris@74 215 if (m_showBranch) {
Chris@56 216 // write branch name
Chris@56 217 f.setBold(true);
Chris@56 218 paint->setFont(f);
Chris@56 219 QString branch = m_changeset->branch();
Chris@74 220 if (branch == "") branch = "default";
Chris@56 221 int wid = width - 3;
Chris@56 222 branch = TextAbbrev::abbreviate(branch, QFontMetrics(f), wid);
Chris@56 223 paint->drawText(x0, -fh + fm.ascent() - 4, branch);
Chris@56 224 f.setBold(false);
Chris@56 225 }
Chris@56 226
Chris@56 227 // f.setItalic(true);
Chris@53 228 fm = QFontMetrics(f);
Chris@53 229 fh = fm.height();
Chris@53 230 paint->setFont(f);
Chris@53 231
Chris@53 232 QString comment = m_changeset->comment().trimmed();
Chris@66 233 comment = comment.replace("\\n", " ");
Chris@53 234 comment = comment.replace(QRegExp("^\"\\s*\\**\\s*"), "");
Chris@53 235 comment = comment.replace(QRegExp("\"$"), "");
Chris@53 236 comment = comment.replace("\\\"", "\"");
Chris@53 237
Chris@55 238 wid = width - 5;
Chris@56 239 int nlines = (height / fh) - 1;
Chris@56 240 if (nlines < 1) nlines = 1;
Chris@53 241 comment = TextAbbrev::abbreviate(comment, fm, wid, TextAbbrev::ElideEnd,
Chris@56 242 "...", nlines);
Chris@53 243
Chris@53 244 QStringList lines = comment.split('\n');
Chris@53 245 for (int i = 0; i < lines.size(); ++i) {
Chris@55 246 paint->drawText(x0 + 3, i * fh + fh + fm.ascent(), lines[i].trimmed());
Chris@53 247 }
Chris@53 248
Chris@53 249 paint->restore();
Chris@43 250 }