1 /*
2  *  Copyright (C) 1999-2002 Bernd Gehrmann
3  *                          bernd@mail.berlios.de
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18  */
19 
20 
21 #include "loglist.h"
22 
23 #include <qapplication.h>
24 #include <qnamespace.h>
25 
26 #include <QMouseEvent>
27 #include <QKeyEvent>
28 #include <QHeaderView>
29 
30 #include <KConfigGroup>
31 #include <KConfig>
32 #include <klocalizedstring.h>
33 
34 #include "loginfo.h"
35 #include "misc.h"
36 #include "tooltip.h"
37 
38 
39 class LogListViewItem : public QTreeWidgetItem
40 {
41 public:
42 
43     enum { Revision, Author, Date, Branch, Comment, Tags };
44 
45     LogListViewItem(QTreeWidget* list, const Cervisia::LogInfo& logInfo);
46 
47     bool operator<(const QTreeWidgetItem &other) const override;
48 
49 private:
50     static QString truncateLine(const QString &s);
51 
52     Cervisia::LogInfo m_logInfo;
53     friend class LogListView;
54 };
55 
56 
LogListViewItem(QTreeWidget * list,const Cervisia::LogInfo & logInfo)57 LogListViewItem::LogListViewItem(QTreeWidget* list, const Cervisia::LogInfo& logInfo)
58     : QTreeWidgetItem(list),
59       m_logInfo(logInfo)
60 {
61     setText(Revision, logInfo.m_revision);
62     setText(Author, logInfo.m_author);
63     setText(Date, logInfo.dateTimeToString());
64     setText(Comment, truncateLine(logInfo.m_comment));
65 
66     for (Cervisia::LogInfo::TTagInfoSeq::const_iterator it = logInfo.m_tags.begin();
67          it != logInfo.m_tags.end(); ++it)
68     {
69         const Cervisia::TagInfo& tagInfo(*it);
70 
71         if (tagInfo.m_type == Cervisia::TagInfo::OnBranch)
72         {
73             setText(Branch, tagInfo.m_name);
74         }
75     }
76 
77     setText(Tags, logInfo.tagsToString(Cervisia::TagInfo::Tag,
78                                        Cervisia::LogInfo::NoTagType,
79                                        QLatin1String(", ")));
80 }
81 
82 
truncateLine(const QString & s)83 QString LogListViewItem::truncateLine(const QString &s)
84 {
85     int pos;
86 
87     QString res = s.simplified();
88     if ( (pos = res.indexOf('\n')) != -1 )
89         res = res.left(pos) + "...";
90 
91     return res;
92 }
93 
94 
operator <(const QTreeWidgetItem & other) const95 bool LogListViewItem::operator<(const QTreeWidgetItem &other) const
96 {
97     const LogListViewItem &item = static_cast<const LogListViewItem &>(other);
98 
99     switch ( treeWidget()->sortColumn() )
100     {
101     case Revision: return ::compareRevisions(m_logInfo.m_revision, item.m_logInfo.m_revision) == -1;
102     case Date: return ::compare(m_logInfo.m_dateTime, item.m_logInfo.m_dateTime) == -1;
103     }
104 
105     return QTreeWidgetItem::operator<(other);
106 }
107 
108 
LogListView(KConfig & cfg,QWidget * parent)109 LogListView::LogListView(KConfig& cfg, QWidget *parent)
110     : QTreeWidget(parent)
111     , partConfig(cfg)
112 {
113     setAllColumnsShowFocus(true);
114     header()->setSortIndicatorShown(true);
115     setSelectionMode(QAbstractItemView::NoSelection);
116     setRootIsDecorated(false);
117     setSortingEnabled(true);
118     sortByColumn(LogListViewItem::Revision, Qt::DescendingOrder);
119     setHeaderLabels(QStringList() << i18n("Revision") << i18n("Author") << i18n("Date")
120                                   << i18n("Branch") << i18n("Comment") << i18n("Tags"));
121 
122     Cervisia::ToolTip* toolTip = new Cervisia::ToolTip(viewport());
123 
124     connect(toolTip, SIGNAL(queryToolTip(QPoint,QRect&,QString&)),
125             this, SLOT(slotQueryToolTip(QPoint,QRect&,QString&)));
126 
127     QByteArray state = cfg.group("LogList view").readEntry<QByteArray>("Columns", QByteArray());
128     header()->restoreState(state);
129 }
130 
131 
~LogListView()132 LogListView::~LogListView()
133 {
134     partConfig.group("LogList view").writeEntry("Columns", header()->saveState());
135 }
136 
137 
addRevision(const Cervisia::LogInfo & logInfo)138 void LogListView::addRevision(const Cervisia::LogInfo& logInfo)
139 {
140     (void) new LogListViewItem(this, logInfo);
141 }
142 
143 
setSelectedPair(const QString & selectionA,const QString & selectionB)144 void LogListView::setSelectedPair(const QString &selectionA, const QString &selectionB)
145 {
146     for (int j = 0; j < topLevelItemCount(); j++)
147     {
148         LogListViewItem *i = static_cast<LogListViewItem*>(topLevelItem(j));
149         i->setSelected(selectionA == i->text(LogListViewItem::Revision) ||
150                        selectionB == i->text(LogListViewItem::Revision));
151     }
152 }
153 
mousePressEvent(QMouseEvent * e)154 void LogListView::mousePressEvent(QMouseEvent *e)
155 {
156     // Retrieve selected item
157     const LogListViewItem* selItem
158         = static_cast<LogListViewItem*>(itemAt(e->pos()));
159     if( !selItem )
160         return;
161 
162     // Retrieve revision
163     const QString revision = selItem->text(LogListViewItem::Revision);
164 
165     if ( e->button() == Qt::LeftButton )
166     {
167         // If the control key was pressed, then we change revision B not A
168         if( e->modifiers() & Qt::ControlModifier )
169             emit revisionClicked(revision, true);
170         else
171             emit revisionClicked(revision, false);
172     }
173     else if ( e->button() == Qt::MidButton )
174         emit revisionClicked(revision, true);
175 }
176 
177 
keyPressEvent(QKeyEvent * e)178 void LogListView::keyPressEvent(QKeyEvent *e)
179 {
180     switch (e->key()) {
181     case Qt::Key_A:
182         if (currentItem())
183             emit revisionClicked(currentItem()->text(LogListViewItem::Revision), false);
184         break;
185         break;
186     case Qt::Key_B:
187         if (currentItem())
188             emit revisionClicked(currentItem()->text(LogListViewItem::Revision), true);
189         break;
190     case Qt::Key_Backspace:
191     case Qt::Key_Delete:
192     case Qt::Key_Down:
193     case Qt::Key_Up:
194     case Qt::Key_Home:
195     case Qt::Key_End:
196     case Qt::Key_PageDown:
197     case Qt::Key_PageUp:
198         if (e->modifiers() == Qt::NoModifier)
199              QTreeWidget::keyPressEvent(e);
200         else
201             QApplication::postEvent(this, new QKeyEvent(QEvent::KeyPress, e->key(), Qt::NoModifier, e->text()));
202         break;
203     default:
204         // Ignore Key_Enter, Key_Return
205         e->ignore();
206     }
207 }
208 
209 
slotQueryToolTip(const QPoint & viewportPos,QRect & viewportRect,QString & text)210 void LogListView::slotQueryToolTip(const QPoint& viewportPos,
211                                    QRect&        viewportRect,
212                                    QString&      text)
213 {
214     if (const LogListViewItem* item = static_cast<LogListViewItem*>(itemAt(viewportPos)))
215     {
216         viewportRect = visualRect(indexAt(viewportPos));
217         text = item->m_logInfo.createToolTipText();
218     }
219 }
220 
221 
222 // Local Variables:
223 // c-basic-offset: 4
224 // End:
225