Version 2.6
[qgit4/redivivus.git] / src / fileview.cpp
blob561419a8de6ff0794b66ea464c1a547d6aa94a66
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 "FileHistory.h"
11 #include "mainimpl.h"
12 #include "git.h"
13 #include "annotate.h"
14 #include "listview.h"
15 #include "filecontent.h"
16 #include "fileview.h"
18 #define MAX_LINE_NUM 5
20 FileView::FileView(MainImpl* mi, Git* g) : Domain(mi, g, false) {
22 fileTab = new Ui_TabFile();
23 fileTab->setupUi(container);
24 fileTab->histListView->setup(this, git);
25 fileTab->textEditFile->setup(this, git, fileTab->listWidgetAnn);
27 // an empty string turn off the special-value text display
28 fileTab->spinBoxRevision->setSpecialValueText(" ");
30 // Add GNU source-highlight version to tooltip, or add a message that it's not installed.
31 QToolButton* highlight = fileTab->toolButtonHighlightText;
32 highlight->setToolTip(highlight->toolTip().arg(git->textHighlighterVersion()));
34 clear(true); // init some stuff
36 fileTab->listWidgetAnn->installEventFilter(this);
38 connect(git, SIGNAL(loadCompleted(const FileHistory*, const QString&)),
39 this, SLOT(on_loadCompleted(const FileHistory*, const QString&)));
41 connect(m(), SIGNAL(changeFont(const QFont&)),
42 fileTab->histListView, SLOT(on_changeFont(const QFont&)));
44 connect(fileTab->histListView, SIGNAL(contextMenu(const QString&, int)),
45 this, SLOT(on_contextMenu(const QString&, int)));
47 connect(fileTab->textEditFile, SIGNAL(annotationAvailable(bool)),
48 this, SLOT(on_annotationAvailable(bool)));
50 connect(fileTab->textEditFile, SIGNAL(fileAvailable(bool)),
51 this, SLOT(on_fileAvailable(bool)));
53 connect(fileTab->textEditFile, SIGNAL(revIdSelected(int)),
54 this, SLOT(on_revIdSelected(int)));
56 connect(fileTab->toolButtonCopy, SIGNAL(clicked()),
57 this, SLOT(on_toolButtonCopy_clicked()));
59 connect(fileTab->toolButtonShowAnnotate, SIGNAL(toggled(bool)),
60 this, SLOT(on_toolButtonShowAnnotate_toggled(bool)));
62 connect(fileTab->toolButtonFindAnnotate, SIGNAL(toggled(bool)),
63 this, SLOT(on_toolButtonFindAnnotate_toggled(bool)));
65 connect(fileTab->toolButtonGoNext, SIGNAL(clicked()),
66 this, SLOT(on_toolButtonGoNext_clicked()));
68 connect(fileTab->toolButtonGoPrev, SIGNAL(clicked()),
69 this, SLOT(on_toolButtonGoPrev_clicked()));
71 connect(fileTab->toolButtonRangeFilter, SIGNAL(toggled(bool)),
72 this, SLOT(on_toolButtonRangeFilter_toggled(bool)));
74 connect(fileTab->toolButtonPin, SIGNAL(toggled(bool)),
75 this, SLOT(on_toolButtonPin_toggled(bool)));
77 connect(fileTab->toolButtonHighlightText, SIGNAL(toggled(bool)),
78 this, SLOT(on_toolButtonHighlightText_toggled(bool)));
80 connect(fileTab->spinBoxRevision, SIGNAL(valueChanged(int)),
81 this, SLOT(on_spinBoxRevision_valueChanged(int)));
84 FileView::~FileView() {
86 if (!parent())
87 return;
89 delete fileTab->textEditFile; // must be deleted before fileTab
90 delete fileTab;
91 showStatusBarMessage(""); // cleanup any pending progress info
92 QApplication::restoreOverrideCursor();
95 bool FileView::eventFilter(QObject* obj, QEvent* e) {
97 QListWidget* lw = fileTab->listWidgetAnn;
98 if (e->type() == QEvent::ToolTip && obj == lw) {
99 QHelpEvent* h = static_cast<QHelpEvent*>(e);
100 int id = fileTab->textEditFile->itemAnnId(lw->itemAt(h->pos()));
101 QRegExp re;
102 SCRef sha(fileTab->histListView->shaFromAnnId(id));
103 SCRef d(git->getDesc(sha, re, re, false, model()));
104 lw->setToolTip(d);
106 return QObject::eventFilter(obj, e);
109 void FileView::clear(bool complete) {
111 Domain::clear(complete);
113 if (complete) {
114 setTabCaption("File");
115 fileTab->toolButtonCopy->setEnabled(false);
117 fileTab->textEditFile->clearAll(); // emits file/ann available signals
119 fileTab->toolButtonPin->setEnabled(false);
120 fileTab->toolButtonPin->setChecked(false); // TODO signals pressed() and clicked() are not emitted
121 fileTab->spinBoxRevision->setEnabled(false);
122 fileTab->spinBoxRevision->setValue(fileTab->spinBoxRevision->minimum()); // clears the box
125 bool FileView::goToCurrentAnnotation(int direction) {
127 SCRef ids = fileTab->histListView->currentText(QGit::ANN_ID_COL);
128 int id = (!ids.isEmpty() ? ids.toInt() : 0);
129 fileTab->textEditFile->goToAnnotation(id, direction);
130 return (id != 0);
133 void FileView::updateSpinBoxValue() {
135 SCRef ids = fileTab->histListView->currentText(QGit::ANN_ID_COL);
136 if ( ids.isEmpty()
137 || !fileTab->spinBoxRevision->isEnabled()
138 || fileTab->spinBoxRevision->value() == ids.toInt())
139 return;
141 fileTab->spinBoxRevision->setValue(ids.toInt()); // emit QSpinBox::valueChanged()
144 bool FileView::isMatch(SCRef sha) {
146 static RangeInfo r; // fast path here, avoid allocation on each call
147 if (!fileTab->textEditFile->getRange(sha, &r))
148 return false;
150 return r.modified;
153 void FileView::filterOnRange(bool isOn) {
155 int matchedCnt = fileTab->histListView->filterRows(isOn, false);
156 QString msg;
157 if (isOn)
158 msg = QString("Found %1 matches. Toggle filter "
159 "button to remove the filter").arg(matchedCnt);
161 showStatusBarMessage(msg);
162 QApplication::postEvent(this, new MessageEvent(msg)); // deferred message, after update
165 bool FileView::doUpdate(bool force) {
167 if (st.fileName().isEmpty())
168 return false;
170 if (st.isChanged(StateInfo::FILE_NAME) || force) {
172 clear(false);
173 setTabCaption(st.fileName());
175 if (git->startFileHistory(st.sha(), st.fileName(), model())) {
176 QApplication::restoreOverrideCursor();
177 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
178 showStatusBarMessage("Retrieving history of '" +
179 st.fileName() + "'...");
181 } else if (fileTab->histListView->update() || st.sha().isEmpty()) {
183 updateSpinBoxValue();
184 showStatusBarMessage(git->getRevInfo(st.sha()));
186 if (!fileTab->toolButtonPin->isChecked())
187 fileTab->textEditFile->doUpdate();
189 return true; // always accept new state
192 // ************************************ SLOTS ********************************
194 void FileView::updateEnabledButtons() {
196 QToolButton* copy = fileTab->toolButtonCopy;
197 QToolButton* showAnnotate = fileTab->toolButtonShowAnnotate;
198 QToolButton* findAnnotate = fileTab->toolButtonFindAnnotate;
199 QToolButton* goPrev = fileTab->toolButtonGoPrev;
200 QToolButton* goNext = fileTab->toolButtonGoNext;
201 QToolButton* rangeFilter = fileTab->toolButtonRangeFilter;
202 QToolButton* highlight = fileTab->toolButtonHighlightText;
204 bool fileAvailable = fileTab->textEditFile->isFileAvailable();
205 bool annotateAvailable = fileTab->textEditFile->isAnnotateAvailable();
207 // first enable
208 copy->setEnabled(fileAvailable);
209 showAnnotate->setEnabled(annotateAvailable);
210 findAnnotate->setEnabled(annotateAvailable);
211 goPrev->setEnabled(annotateAvailable);
212 goNext->setEnabled(annotateAvailable);
213 rangeFilter->setEnabled(annotateAvailable);
214 highlight->setEnabled(fileAvailable && git->isTextHighlighter());
216 // then disable
217 if (!showAnnotate->isChecked()) {
218 findAnnotate->setEnabled(false);
219 goPrev->setEnabled(false);
220 goNext->setEnabled(false);
222 if (highlight->isChecked())
223 rangeFilter->setEnabled(false);
225 if (rangeFilter->isChecked())
226 highlight->setEnabled(false);
228 // special case: reset range filter when changing file
229 if (!annotateAvailable && rangeFilter->isChecked())
230 rangeFilter->toggle();
233 void FileView::on_toolButtonCopy_clicked() {
235 fileTab->textEditFile->copySelection();
238 void FileView::on_toolButtonShowAnnotate_toggled(bool b) {
240 updateEnabledButtons();
241 fileTab->textEditFile->setShowAnnotate(b);
243 if (b && fileTab->toolButtonFindAnnotate->isChecked())
244 goToCurrentAnnotation();
247 void FileView::on_toolButtonFindAnnotate_toggled(bool b) {
249 updateEnabledButtons();
250 if (b)
251 goToCurrentAnnotation();
254 void FileView::on_toolButtonGoNext_clicked() {
256 goToCurrentAnnotation(1);
259 void FileView::on_toolButtonGoPrev_clicked() {
261 goToCurrentAnnotation(-1);
264 void FileView::on_toolButtonPin_toggled(bool b) {
265 // button is enabled and togglable only if st.sha() is found
267 fileTab->spinBoxRevision->setDisabled(b);
269 if (!b) {
270 updateSpinBoxValue(); // UPDATE() call is filtered in this case
271 fileTab->textEditFile->doUpdate(true);
275 void FileView::on_toolButtonRangeFilter_toggled(bool b) {
277 updateEnabledButtons();
278 if (b) {
279 if (!fileTab->textEditFile->isAnnotateAvailable()) {
280 dbs("ASSERT in on_toolButtonRangeFilter_toggled: annotate not available");
281 return;
283 if (!fileTab->textEditFile->textCursor().hasSelection()) {
284 showStatusBarMessage("Please select some text");
285 return;
288 bool rangeFilterActive = fileTab->textEditFile->rangeFilter(b);
289 filterOnRange(rangeFilterActive);
292 void FileView::on_toolButtonHighlightText_toggled(bool b) {
294 updateEnabledButtons();
295 fileTab->textEditFile->setHighlightSource(b);
298 void FileView::on_spinBoxRevision_valueChanged(int id) {
300 if (id != fileTab->spinBoxRevision->minimum()) {
302 SCRef selRev(fileTab->histListView->shaFromAnnId(id));
303 if (st.sha() != selRev) { // to avoid looping
304 st.setSha(selRev);
305 st.setSelectItem(true);
306 UPDATE();
311 void FileView::on_loadCompleted(const FileHistory* f, const QString& msg) {
313 QApplication::restoreOverrideCursor();
315 if (f != model())
316 return;
318 showStatusBarMessage("");
319 fileTab->histListView->showIdValues();
320 int maxId = model()->rowCount();
321 if (maxId == 0)
322 return;
324 fileTab->spinBoxRevision->setMaximum(maxId);
325 fileTab->toolButtonPin->setEnabled(true);
326 fileTab->spinBoxRevision->setEnabled(true);
328 // update histListView now to avoid to miss
329 // following status bar messages
330 doUpdate(false);
332 QString histTime = msg.section(" ms", 0, 0).section(" ", -1);
333 if (fileTab->textEditFile->startAnnotate(model(), histTime))
334 showStatusBarMessage("Annotating revisions of '" + st.fileName() + "'...");
337 void FileView::showAnnotation() {
339 if ( !fileTab->toolButtonPin->isChecked()
340 && fileTab->toolButtonShowAnnotate->isEnabled()
341 && fileTab->toolButtonShowAnnotate->isChecked()) {
343 fileTab->textEditFile->setShowAnnotate(true);
345 if ( fileTab->toolButtonFindAnnotate->isEnabled()
346 && fileTab->toolButtonFindAnnotate->isChecked())
348 goToCurrentAnnotation();
352 void FileView::on_annotationAvailable(bool b) {
354 updateEnabledButtons();
355 if (b)
356 showAnnotation(); // in case annotation got ready after file
359 void FileView::on_fileAvailable(bool b) {
361 updateEnabledButtons();
362 if (b) {
363 // code range is independent from annotation
364 if (fileTab->toolButtonRangeFilter->isChecked())
365 fileTab->textEditFile->goToRangeStart();
367 showAnnotation(); // in case file got ready after annotation
371 void FileView::on_revIdSelected(int id) {
373 if (id == 0)
374 return;
376 if (fileTab->spinBoxRevision->isEnabled())
377 fileTab->spinBoxRevision->setValue(id);
378 else {
379 ListView* h = fileTab->histListView;
380 int row = h->model()->rowCount() - id;
381 QModelIndex idx = h->model()->index(row, 0);
382 h->setCurrentIndex(idx);