Chris@57: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@46: Chris@57: /* Chris@57: EasyMercurial Chris@57: Chris@57: Based on HgExplorer by Jari Korhonen Chris@57: Copyright (c) 2010 Jari Korhonen Chris@644: Copyright (c) 2013 Chris Cannam Chris@644: Copyright (c) 2013 Queen Mary, University of London Chris@57: Chris@57: This program is free software; you can redistribute it and/or Chris@57: modify it under the terms of the GNU General Public License as Chris@57: published by the Free Software Foundation; either version 2 of the Chris@57: License, or (at your option) any later version. See the file Chris@57: COPYING included with this distribution for more information. Chris@57: */ Chris@46: Chris@46: #include "connectionitem.h" Chris@145: #include "uncommitteditem.h" Chris@46: Chris@46: #include "changesetitem.h" Chris@53: #include "changeset.h" Chris@53: #include "colourset.h" Chris@516: #include "textabbrev.h" Chris@46: Chris@46: #include Chris@516: #include Chris@46: Chris@46: QRectF Chris@46: ConnectionItem::boundingRect() const Chris@46: { Chris@516: if (!(m_child || m_uncommitted)) return QRectF(); Chris@53: float xscale = 100; Chris@53: float yscale = 90; Chris@46: float size = 50; Chris@145: Chris@145: int c_col, c_row; Chris@145: if (m_child) { Chris@145: c_col = m_child->column(); c_row = m_child->row(); Chris@145: } else { Chris@145: c_col = m_uncommitted->column(); c_row = m_uncommitted->row(); Chris@145: } Chris@145: Chris@516: int p_col, p_row; Chris@516: if (m_parent) { Chris@516: p_col = m_parent->column(); p_row = m_parent->row(); Chris@516: } else { Chris@516: p_col = c_col - 1; p_row = c_row + 1; Chris@516: } Chris@516: Chris@145: return QRectF(xscale * c_col + size/2 - 2, Chris@387: yscale * c_row + size - 22, Chris@390: xscale * p_col - xscale * c_col + 6, Chris@387: yscale * p_row - yscale * c_row - size + 44) Chris@46: .normalized(); Chris@46: } Chris@46: Chris@46: void Chris@46: ConnectionItem::paint(QPainter *paint, const QStyleOptionGraphicsItem *, QWidget *) Chris@46: { Chris@516: if (!(m_child || m_uncommitted)) return; Chris@46: QPainterPath p; Chris@53: Chris@53: paint->save(); Chris@53: Chris@506: int alpha = 255; Chris@506: if (m_child && m_child->isClosed()) alpha = 90; Chris@506: Chris@53: ColourSet *colourSet = ColourSet::instance(); Chris@145: QString branch; Chris@145: if (m_child) branch = m_child->getChangeset()->branch(); Chris@145: else branch = m_uncommitted->branch(); Chris@145: QColor branchColour = colourSet->getColourFor(branch); Chris@145: Chris@506: branchColour.setAlpha(alpha); Chris@506: Chris@145: Qt::PenStyle ls = Qt::SolidLine; Chris@145: if (!m_child) ls = Qt::DashLine; Chris@54: Chris@54: QTransform t = paint->worldTransform(); Chris@54: float scale = std::min(t.m11(), t.m22()); Chris@145: if (scale < 0.2) { Chris@145: paint->setPen(QPen(branchColour, 0, ls)); Chris@54: } else { Chris@145: paint->setPen(QPen(branchColour, 2, ls)); Chris@54: } Chris@53: Chris@53: float xscale = 100; Chris@53: Chris@53: float yscale = 90; Chris@46: float size = 50; Chris@153: float ygap = yscale - size - 2; Chris@53: Chris@145: int c_col, c_row; Chris@145: if (m_child) { Chris@145: c_col = m_child->column(); c_row = m_child->row(); Chris@145: } else { Chris@145: c_col = m_uncommitted->column(); c_row = m_uncommitted->row(); Chris@145: } Chris@53: Chris@516: int p_col, p_row; Chris@516: if (m_parent) { Chris@516: p_col = m_parent->column(); p_row = m_parent->row(); Chris@516: } else { Chris@516: p_col = c_col - 1; p_row = c_row + 1; Chris@516: } Chris@516: Chris@53: float c_x = xscale * c_col + size/2; Chris@53: float p_x = xscale * p_col + size/2; Chris@53: Chris@250: // ensure line reaches the box, even if it's in a small height -- Chris@250: // doesn't matter if we overshoot as the box is opaque and has a Chris@250: // greater Z value Chris@250: p.moveTo(c_x, yscale * c_row + size - 20); Chris@250: Chris@250: p.lineTo(c_x, yscale * c_row + size); Chris@53: Chris@53: if (p_col == c_col) { Chris@53: Chris@53: p.lineTo(p_x, yscale * p_row); Chris@53: Chris@53: } else if (m_type == Split || m_type == Normal) { Chris@53: Chris@53: // place the bulk of the line on the child (i.e. branch) row Chris@53: Chris@53: if (abs(p_row - c_row) > 1) { Chris@53: p.lineTo(c_x, yscale * p_row - ygap); Chris@53: } Chris@53: Chris@53: p.cubicTo(c_x, yscale * p_row, Chris@53: p_x, yscale * p_row - ygap, Chris@53: p_x, yscale * p_row); Chris@53: Chris@53: } else if (m_type == Merge) { Chris@53: Chris@53: // place bulk of the line on the parent row Chris@53: Chris@53: p.cubicTo(c_x, yscale * c_row + size + ygap, Chris@53: p_x, yscale * c_row + size, Chris@53: p_x, yscale * c_row + size + ygap); Chris@53: Chris@53: if (abs(p_row - c_row) > 1) { Chris@53: p.lineTo(p_x, yscale * p_row); Chris@46: } Chris@46: } Chris@53: Chris@516: if (m_parent) { Chris@387: Chris@516: // ensure line reaches the node -- again doesn't matter if we Chris@516: // overshoot Chris@516: p.lineTo(p_x, yscale * p_row + 20); Chris@516: Chris@516: } else { Chris@516: Chris@516: // no parent: merge from closed branch: draw only half the line Chris@516: paint->setClipRect(QRectF((c_x + p_x)/2, yscale * c_row + size - 22, Chris@516: xscale, yscale)); Chris@516: } Chris@516: Chris@46: paint->drawPath(p); Chris@516: Chris@516: if (!m_parent) { Chris@516: Chris@516: // merge from closed branch: draw branch name Chris@516: Chris@516: paint->setClipping(false); Chris@516: Chris@516: QFont f; Chris@516: f.setPixelSize(11); Chris@516: f.setBold(true); Chris@516: f.setItalic(false); Chris@516: paint->setFont(f); Chris@516: Chris@516: QString branch = m_mergedBranch; Chris@516: if (branch == "") branch = "default"; Chris@516: int wid = xscale; Chris@516: branch = TextAbbrev::abbreviate(branch, QFontMetrics(f), wid); Chris@516: paint->drawText((c_x + p_x)/2 - wid - 2, Chris@516: yscale * c_row + size + ygap/2 + 2, Chris@516: branch); Chris@516: } Chris@516: Chris@53: paint->restore(); Chris@46: } Chris@46: Chris@46: