Warning, file /sdk/cervisia/annotateview.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * Copyright (C) 1999-2002 Bernd Gehrmann <bernd@mail.berlios.de> 0003 * Copyright (c) 2003-2008 André Wöbbeking <Woebbeking@kde.org> 0004 * Copyright (c) 2015 Martin Koller <kollix@aon.at> 0005 * 0006 * This program is free software; you can redistribute it and/or modify 0007 * it under the terms of the GNU General Public License as published by 0008 * the Free Software Foundation; either version 2 of the License, or 0009 * (at your option) any later version. 0010 * 0011 * This program is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0014 * GNU General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU General Public License 0017 * along with this program; if not, write to the Free Software 0018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 0019 */ 0020 0021 #include "annotateview.h" 0022 0023 #include <QApplication> 0024 #include <QHeaderView> 0025 #include <kcolorscheme.h> 0026 #include <qpainter.h> 0027 0028 #include "cervisiasettings.h" 0029 #include "loginfo.h" 0030 #include "tooltip.h" 0031 0032 using namespace Cervisia; 0033 0034 class AnnotateViewItem : public QTreeWidgetItem 0035 { 0036 public: 0037 enum { LineNumberColumn, AuthorColumn, ContentColumn }; 0038 0039 AnnotateViewItem(AnnotateView *parent, const LogInfo &logInfo, const QString &content, bool odd, int linenumber); 0040 0041 int lineNumber() const 0042 { 0043 return m_lineNumber; 0044 } 0045 0046 QVariant data(int column, int role) const override; 0047 0048 private: 0049 LogInfo m_logInfo; 0050 QString m_content; 0051 bool m_odd; 0052 int m_lineNumber; 0053 0054 friend class AnnotateView; 0055 friend class AnnotateViewDelegate; 0056 }; 0057 0058 AnnotateViewItem::AnnotateViewItem(AnnotateView *parent, const LogInfo &logInfo, const QString &content, bool odd, int linenumber) 0059 : QTreeWidgetItem(parent) 0060 , m_logInfo(logInfo) 0061 , m_content(content) 0062 , m_odd(odd) 0063 , m_lineNumber(linenumber) 0064 { 0065 } 0066 0067 QVariant AnnotateViewItem::data(int column, int role) const 0068 { 0069 if (role == Qt::DisplayRole) { 0070 switch (column) { 0071 case LineNumberColumn: 0072 return QString::number(m_lineNumber); 0073 case AuthorColumn: 0074 if (m_logInfo.m_author.isNull()) 0075 return QString(); 0076 else 0077 return (m_logInfo.m_author + QChar(' ') + m_logInfo.m_revision); 0078 case ContentColumn: 0079 return m_content; 0080 default:; 0081 }; 0082 0083 return QString(); 0084 } 0085 0086 return QTreeWidgetItem::data(column, role); 0087 } 0088 0089 //--------------------------------------------------------------------- 0090 0091 void AnnotateViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const 0092 { 0093 painter->save(); 0094 0095 auto item = static_cast<AnnotateViewItem *>(view->topLevelItem(index.row())); 0096 0097 QColor backgroundColor; 0098 QColor foregroundColor; 0099 0100 if (item->isSelected() || index.column() == AnnotateViewItem::LineNumberColumn) { 0101 backgroundColor = KColorScheme(QPalette::Active, KColorScheme::Selection).background().color(); 0102 foregroundColor = KColorScheme(QPalette::Active, KColorScheme::Selection).foreground().color(); 0103 } else { 0104 backgroundColor = item->m_odd ? KColorScheme(QPalette::Active, KColorScheme::View).background().color() 0105 : KColorScheme(QPalette::Active, KColorScheme::View).background(KColorScheme::AlternateBackground).color(); 0106 foregroundColor = KColorScheme(QPalette::Active, KColorScheme::View).foreground().color(); 0107 } 0108 0109 painter->setPen(foregroundColor); 0110 painter->fillRect(option.rect, backgroundColor); 0111 0112 QString str = item->text(index.column()); 0113 if (str.isEmpty()) { 0114 painter->restore(); 0115 return; 0116 } 0117 0118 Qt::Alignment align = (index.column() == AnnotateViewItem::LineNumberColumn) ? Qt::AlignRight : option.displayAlignment; 0119 0120 if ((align & (Qt::AlignTop | Qt::AlignBottom)) == 0) 0121 align |= Qt::AlignVCenter; 0122 0123 // only the content shall use the configured font, others use default 0124 // reason: usually you want fixed-width font in sourcecode, but line numbers and revision column look 0125 // nicer when they are not fixed-width 0126 if (index.column() == AnnotateViewItem::ContentColumn) 0127 painter->setFont(view->font()); 0128 else 0129 painter->setFont(QApplication::font()); 0130 0131 painter->drawText(option.rect.x() + BORDER, option.rect.y(), option.rect.width() - 2 * BORDER, option.rect.height(), align, str); 0132 0133 painter->restore(); 0134 } 0135 0136 QSize AnnotateViewDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const 0137 { 0138 QStyleOptionViewItem opt(option); 0139 0140 if (index.column() == AnnotateViewItem::ContentColumn) 0141 opt.font = view->font(); 0142 else 0143 opt.font = QApplication::font(); 0144 0145 QSize s = QStyledItemDelegate::sizeHint(opt, index); 0146 s.setWidth(s.width() + 2 * BORDER); 0147 0148 return s; 0149 } 0150 0151 //--------------------------------------------------------------------- 0152 0153 AnnotateView::AnnotateView(QWidget *parent) 0154 : QTreeWidget(parent) 0155 { 0156 setItemDelegate(new AnnotateViewDelegate(this)); 0157 0158 setFrameStyle(QFrame::WinPanel | QFrame::Sunken); 0159 setAllColumnsShowFocus(true); 0160 setRootIsDecorated(false); 0161 setAutoScroll(false); 0162 setSelectionMode(QAbstractItemView::SingleSelection); // to be able to show the found item 0163 header()->setSectionResizeMode(QHeaderView::ResizeToContents); 0164 header()->setStretchLastSection(false); 0165 header()->hide(); 0166 setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); 0167 setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); 0168 0169 setColumnCount(3); 0170 0171 auto toolTip = new ToolTip(viewport()); 0172 0173 connect(toolTip, SIGNAL(queryToolTip(QPoint, QRect &, QString &)), this, SLOT(slotQueryToolTip(QPoint, QRect &, QString &))); 0174 0175 configChanged(); 0176 0177 connect(CervisiaSettings::self(), SIGNAL(configChanged()), this, SLOT(configChanged())); 0178 } 0179 0180 void AnnotateView::addLine(const LogInfo &logInfo, const QString &content, bool odd) 0181 { 0182 new AnnotateViewItem(this, logInfo, content, odd, topLevelItemCount() + 1); 0183 } 0184 0185 QSize AnnotateView::sizeHint() const 0186 { 0187 QFontMetrics fm(fontMetrics()); 0188 return {100 * fm.width("0"), 10 * fm.lineSpacing()}; 0189 } 0190 0191 void AnnotateView::configChanged() 0192 { 0193 setFont(CervisiaSettings::annotateFont()); 0194 } 0195 0196 void AnnotateView::slotQueryToolTip(const QPoint &viewportPos, QRect &viewportRect, QString &text) 0197 { 0198 if (const AnnotateViewItem *item = static_cast<AnnotateViewItem *>(itemAt(viewportPos))) { 0199 const int column(indexAt(viewportPos).column()); 0200 if ((column == AnnotateViewItem::AuthorColumn) && !item->m_logInfo.m_author.isNull()) { 0201 viewportRect = visualRect(indexAt(viewportPos)); 0202 text = item->m_logInfo.createToolTipText(false); 0203 } 0204 } 0205 } 0206 0207 void AnnotateView::findText(const QString &textToFind, bool up) 0208 { 0209 QTreeWidgetItem *item = currentItem(); 0210 if (!item) { 0211 if (up) 0212 item = topLevelItem(topLevelItemCount() - 1); // last 0213 else 0214 item = topLevelItem(0); // first 0215 } else { 0216 if (up) 0217 item = itemAbove(item); 0218 else 0219 item = itemBelow(item); 0220 } 0221 0222 for (; item && !item->text(AnnotateViewItem::ContentColumn).contains(textToFind, Qt::CaseInsensitive); item = up ? itemAbove(item) : itemBelow(item)) 0223 ; 0224 0225 setCurrentItem(item); 0226 0227 if (item) { 0228 item->setSelected(true); 0229 scrollToItem(item); 0230 } 0231 } 0232 0233 int AnnotateView::currentLine() const 0234 { 0235 QTreeWidgetItem *item = currentItem(); 0236 if (!item) 0237 return -1; 0238 0239 return static_cast<AnnotateViewItem *>(item)->lineNumber(); 0240 } 0241 0242 int AnnotateView::lastLine() const 0243 { 0244 auto item = static_cast<AnnotateViewItem *>(topLevelItem(topLevelItemCount() - 1)); 0245 if (!item) 0246 return 0; 0247 0248 return item->lineNumber(); 0249 } 0250 0251 void AnnotateView::gotoLine(int line) 0252 { 0253 for (auto item = static_cast<AnnotateViewItem *>(topLevelItem(0)); item; item = static_cast<AnnotateViewItem *>(itemBelow(item))) { 0254 if (item->lineNumber() == line) { 0255 setCurrentItem(item); 0256 item->setSelected(true); 0257 scrollToItem(item); 0258 return; 0259 } 0260 } 0261 } 0262 0263 // Local Variables: 0264 // c-basic-offset: 4 0265 // End: