Add "GNU source-highlight not installed" to Source highlight button tooltip, if not...
[qgit4.git] / src / fileview.cpp
blobbeafce80c9a33719407c342564b2231ee6a4a5ec
1 /*
2 Description: file viewer window
4 Author: Marco Costalba (C) 2005-2007
6 Copyright: See COPYING file that comes with this distribution
8 */
9 #include <QHelpEvent>
10 #include "mainimpl.h"
11 #include "git.h"
12 #include "annotate.h"
13 #include "listview.h"
14 #include "filecontent.h"
15 #include "fileview.h"
17 #define MAX_LINE_NUM 5
19 FileView::FileView(MainImpl* mi, Git* g) : Domain(mi, g, false) {
21 fileTab = new Ui_TabFile();
22 fileTab->setupUi(container);
23 fileTab->histListView->setup(this, git);
24 fileTab->textEditFile->setup(this, git, fileTab->listWidgetAnn);
26 // an empty string turn off the special-value text display
27 fileTab->spinBoxRevision->setSpecialValueText(" ");
29 // Add GNU source-highlight version to tooltip, or add a message that it's not installed.
30 QToolButton* highlight = fileTab->toolButtonHighlightText;
31 highlight->setToolTip(highlight->toolTip().arg(git->textHighlighterVersion()));
33 clear(true); // init some stuff
35 fileTab->listWidgetAnn->installEventFilter(this);
37 connect(git, SIGNAL(loadCompleted(const FileHistory*, const QString&)),
38 this, SLOT(on_loadCompleted(const FileHistory*, const QString&)));
40 connect(m(), SIGNAL(changeFont(const QFont&)),
41 fileTab->histListView, SLOT(on_changeFont(const QFont&)));
43 connect(fileTab->histListView, SIGNAL(contextMenu(const QString&, int)),
44 this, SLOT(on_contextMenu(const QString&, int)));
46 connect(fileTab->textEditFile, SIGNAL(annotationAvailable(bool)),
47 this, SLOT(on_annotationAvailable(bool)));
49 connect(fileTab->textEditFile, SIGNAL(fileAvailable(bool)),
50 this, SLOT(on_fileAvailable(bool)));
52 connect(fileTab->textEditFile, SIGNAL(revIdSelected(int)),
53 this, SLOT(on_revIdSelected(int)));
55 connect(fileTab->toolButtonCopy, SIGNAL(clicked()),
56 this, SLOT(on_toolButtonCopy_clicked()));
58 connect(fileTab->toolButtonShowAnnotate, SIGNAL(toggled(bool)),
59 this, SLOT(on_toolButtonShowAnnotate_toggled(bool)));
61 connect(fileTab->toolButtonFindAnnotate, SIGNAL(toggled(bool)),
62 this, SLOT(on_toolButtonFindAnnotate_toggled(bool)));
64 connect(fileTab->toolButtonGoNext, SIGNAL(clicked()),
65 this, SLOT(on_toolButtonGoNext_clicked()));
67 connect(fileTab->toolButtonGoPrev, SIGNAL(clicked()),
68 this, SLOT(on_toolButtonGoPrev_clicked()));
70 connect(fileTab->toolButtonRangeFilter, SIGNAL(toggled(bool)),
71 this, SLOT(on_toolButtonRangeFilter_toggled(bool)));
73 connect(fileTab->toolButtonPin, SIGNAL(toggled(bool)),
74 this, SLOT(on_toolButtonPin_toggled(bool)));
76 connect(fileTab->toolButtonHighlightText, SIGNAL(toggled(bool)),
77 this, SLOT(on_toolButtonHighlightText_toggled(bool)));
79 connect(fileTab->spinBoxRevision, SIGNAL(valueChanged(int)),
80 this, SLOT(on_spinBoxRevision_valueChanged(int)));
83 FileView::~FileView() {
85 if (!parent())
86 return;
88 delete fileTab->textEditFile; // must be deleted before fileTab
89 delete fileTab;
90 showStatusBarMessage(""); // cleanup any pending progress info
91 QApplication::restoreOverrideCursor();
94 bool FileView::eventFilter(QObject* obj, QEvent* e) {
96 QListWidget* lw = fileTab->listWidgetAnn;
97 if (e->type() == QEvent::ToolTip && obj == lw) {
98 QHelpEvent* h = static_cast<QHelpEvent*>(e);
99 int id = fileTab->textEditFile->itemAnnId(lw->itemAt(h->pos()));
100 QRegExp re;
101 SCRef sha(fileTab->histListView->shaFromAnnId(id));
102 SCRef d(git->getDesc(sha, re, re, false, model()));
103 lw->setToolTip(d);
105 return QObject::eventFilter(obj, e);
108 void FileView::clear(bool complete) {
110 Domain::clear(complete);
112 if (complete) {
113 setTabCaption("File");
114 fileTab->toolButtonCopy->setEnabled(false);
116 fileTab->textEditFile->clearAll(); // emits file/ann available signals
118 fileTab->toolButtonPin->setEnabled(false);
119 fileTab->toolButtonPin->setChecked(false); // TODO signals pressed() and clicked() are not emitted
120 fileTab->spinBoxRevision->setEnabled(false);
121 fileTab->spinBoxRevision->setValue(fileTab->spinBoxRevision->minimum()); // clears the box
124 bool FileView::goToCurrentAnnotation(int direction) {
126 SCRef ids = fileTab->histListView->currentText(QGit::ANN_ID_COL);
127 int id = (!ids.isEmpty() ? ids.toInt() : 0);
128 fileTab->textEditFile->goToAnnotation(id, direction);
129 return (id != 0);
132 void FileView::updateSpinBoxValue() {
134 SCRef ids = fileTab->histListView->currentText(QGit::ANN_ID_COL);
135 if ( ids.isEmpty()
136 || !fileTab->spinBoxRevision->isEnabled()
137 || fileTab->spinBoxRevision->value() == ids.toInt())
138 return;
140 fileTab->spinBoxRevision->setValue(ids.toInt()); // emit QSpinBox::valueChanged()
143 bool FileView::isMatch(SCRef sha) {
145 static RangeInfo r; // fast path here, avoid allocation on each call
146 if (!fileTab->textEditFile->getRange(sha, &r))
147 return false;
149 return r.modified;
152 void FileView::filterOnRange(bool isOn) {
154 int matchedCnt = fileTab->histListView->filterRows(isOn, false);
155 QString msg;
156 if (isOn)
157 msg = QString("Found %1 matches. Toggle filter "
158 "button to remove the filter").arg(matchedCnt);
160 showStatusBarMessage(msg);
161 QApplication::postEvent(this, new MessageEvent(msg)); // deferred message, after update
164 bool FileView::doUpdate(bool force) {
166 if (st.fileName().isEmpty())
167 return false;
169 if (st.isChanged(StateInfo::FILE_NAME) || force) {
171 clear(false);
172 setTabCaption(st.fileName());
174 if (git->startFileHistory(st.sha(), st.fileName(), model())) {
175 QApplication::restoreOverrideCursor();
176 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
177 showStatusBarMessage("Retrieving history of '" +
178 st.fileName() + "'...");
180 } else if (fileTab->histListView->update() || st.sha().isEmpty()) {
182 updateSpinBoxValue();
183 showStatusBarMessage(git->getRevInfo(st.sha()));
185 if (!fileTab->toolButtonPin->isChecked())
186 fileTab->textEditFile->doUpdate();
188 return true; // always accept new state
191 // ************************************ SLOTS ********************************
193 void FileView::updateEnabledButtons() {
195 QToolButton* copy = fileTab->toolButtonCopy;
196 QToolButton* showAnnotate = fileTab->toolButtonShowAnnotate;
197 QToolButton* findAnnotate = fileTab->toolButtonFindAnnotate;
198 QToolButton* goPrev = fileTab->toolButtonGoPrev;
199 QToolButton* goNext = fileTab->toolButtonGoNext;
200 QToolButton* rangeFilter = fileTab->toolButtonRangeFilter;
201 QToolButton* highlight = fileTab->toolButtonHighlightText;
203 bool fileAvailable = fileTab->textEditFile->isFileAvailable();
204 bool annotateAvailable = fileTab->textEditFile->isAnnotateAvailable();
206 // first enable
207 copy->setEnabled(fileAvailable);
208 showAnnotate->setEnabled(annotateAvailable);
209 findAnnotate->setEnabled(annotateAvailable);
210 goPrev->setEnabled(annotateAvailable);
211 goNext->setEnabled(annotateAvailable);
212 rangeFilter->setEnabled(annotateAvailable);
213 highlight->setEnabled(fileAvailable && git->isTextHighlighter());
215 // then disable
216 if (!showAnnotate->isChecked()) {
217 findAnnotate->setEnabled(false);
218 goPrev->setEnabled(false);
219 goNext->setEnabled(false);
221 if (highlight->isChecked())
222 rangeFilter->setEnabled(false);
224 if (rangeFilter->isChecked())
225 highlight->setEnabled(false);
227 // special case: reset range filter when changing file
228 if (!annotateAvailable && rangeFilter->isChecked())
229 rangeFilter->toggle();
232 void FileView::on_toolButtonCopy_clicked() {
234 fileTab->textEditFile->copySelection();
237 void FileView::on_toolButtonShowAnnotate_toggled(bool b) {
239 updateEnabledButtons();
240 fileTab->textEditFile->setShowAnnotate(b);
242 if (b && fileTab->toolButtonFindAnnotate->isChecked())
243 goToCurrentAnnotation();
246 void FileView::on_toolButtonFindAnnotate_toggled(bool b) {
248 updateEnabledButtons();
249 if (b)
250 goToCurrentAnnotation();
253 void FileView::on_toolButtonGoNext_clicked() {
255 goToCurrentAnnotation(1);
258 void FileView::on_toolButtonGoPrev_clicked() {
260 goToCurrentAnnotation(-1);
263 void FileView::on_toolButtonPin_toggled(bool b) {
264 // button is enabled and togglable only if st.sha() is found
266 fileTab->spinBoxRevision->setDisabled(b);
268 if (!b) {
269 updateSpinBoxValue(); // UPDATE() call is filtered in this case
270 fileTab->textEditFile->doUpdate(true);
274 void FileView::on_toolButtonRangeFilter_toggled(bool b) {
276 updateEnabledButtons();
277 if (b) {
278 if (!fileTab->textEditFile->isAnnotateAvailable()) {
279 dbs("ASSERT in on_toolButtonRangeFilter_toggled: annotate not available");
280 return;
282 if (!fileTab->textEditFile->textCursor().hasSelection()) {
283 showStatusBarMessage("Please select some text");
284 return;
287 bool rangeFilterActive = fileTab->textEditFile->rangeFilter(b);
288 filterOnRange(rangeFilterActive);
291 void FileView::on_toolButtonHighlightText_toggled(bool b) {
293 updateEnabledButtons();
294 fileTab->textEditFile->setHighlightSource(b);
297 void FileView::on_spinBoxRevision_valueChanged(int id) {
299 if (id != fileTab->spinBoxRevision->minimum()) {
301 SCRef selRev(fileTab->histListView->shaFromAnnId(id));
302 if (st.sha() != selRev) { // to avoid looping
303 st.setSha(selRev);
304 st.setSelectItem(true);
305 UPDATE();
310 void FileView::on_loadCompleted(const FileHistory* f, const QString& msg) {
312 QApplication::restoreOverrideCursor();
314 if (f != model())
315 return;
317 showStatusBarMessage("");
318 fileTab->histListView->showIdValues();
319 int maxId = model()->rowCount();
320 if (maxId == 0)
321 return;
323 fileTab->spinBoxRevision->setMaximum(maxId);
324 fileTab->toolButtonPin->setEnabled(true);
325 fileTab->spinBoxRevision->setEnabled(true);
327 // update histListView now to avoid to miss
328 // following status bar messages
329 doUpdate(false);
331 QString histTime = msg.section(" ms", 0, 0).section(" ", -1);
332 if (fileTab->textEditFile->startAnnotate(model(), histTime))
333 showStatusBarMessage("Annotating revisions of '" + st.fileName() + "'...");
336 void FileView::showAnnotation() {
338 if ( !fileTab->toolButtonPin->isChecked()
339 && fileTab->toolButtonShowAnnotate->isEnabled()
340 && fileTab->toolButtonShowAnnotate->isChecked()) {
342 fileTab->textEditFile->setShowAnnotate(true);
344 if ( fileTab->toolButtonFindAnnotate->isEnabled()
345 && fileTab->toolButtonFindAnnotate->isChecked())
347 goToCurrentAnnotation();
351 void FileView::on_annotationAvailable(bool b) {
353 updateEnabledButtons();
354 if (b)
355 showAnnotation(); // in case annotation got ready after file
358 void FileView::on_fileAvailable(bool b) {
360 updateEnabledButtons();
361 if (b) {
362 // code range is independent from annotation
363 if (fileTab->toolButtonRangeFilter->isChecked())
364 fileTab->textEditFile->goToRangeStart();
366 showAnnotation(); // in case file got ready after annotation
370 void FileView::on_revIdSelected(int id) {
372 if (id == 0)
373 return;
375 if (fileTab->spinBoxRevision->isEnabled())
376 fileTab->spinBoxRevision->setValue(id);
377 else {
378 ListView* h = fileTab->histListView;
379 int row = h->model()->rowCount() - id;
380 QModelIndex idx = h->model()->index(row, 0);
381 h->setCurrentIndex(idx);