2 Description: file viewer window
4 Author: Marco Costalba (C) 2005-2007
6 Copyright: See COPYING file that comes with this distribution
10 #include "FileHistory.h"
15 #include "filecontent.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() {
89 delete fileTab
->textEditFile
; // must be deleted before 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()));
102 SCRef
sha(fileTab
->histListView
->shaFromAnnId(id
));
103 SCRef
d(git
->getDesc(sha
, re
, re
, false, model()));
106 return QObject::eventFilter(obj
, e
);
109 void FileView::clear(bool complete
) {
111 Domain::clear(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
);
133 void FileView::updateSpinBoxValue() {
135 SCRef ids
= fileTab
->histListView
->currentText(QGit::ANN_ID_COL
);
137 || !fileTab
->spinBoxRevision
->isEnabled()
138 || fileTab
->spinBoxRevision
->value() == ids
.toInt())
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
))
153 void FileView::filterOnRange(bool isOn
) {
155 int matchedCnt
= fileTab
->histListView
->filterRows(isOn
, false);
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())
170 if (st
.isChanged(StateInfo::FILE_NAME
) || force
) {
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();
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());
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();
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
);
270 updateSpinBoxValue(); // UPDATE() call is filtered in this case
271 fileTab
->textEditFile
->doUpdate(true);
275 void FileView::on_toolButtonRangeFilter_toggled(bool b
) {
277 updateEnabledButtons();
279 if (!fileTab
->textEditFile
->isAnnotateAvailable()) {
280 dbs("ASSERT in on_toolButtonRangeFilter_toggled: annotate not available");
283 if (!fileTab
->textEditFile
->textCursor().hasSelection()) {
284 showStatusBarMessage("Please select some text");
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
305 st
.setSelectItem(true);
311 void FileView::on_loadCompleted(const FileHistory
* f
, const QString
& msg
) {
313 QApplication::restoreOverrideCursor();
318 showStatusBarMessage("");
319 fileTab
->histListView
->showIdValues();
320 int maxId
= model()->rowCount();
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
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();
356 showAnnotation(); // in case annotation got ready after file
359 void FileView::on_fileAvailable(bool b
) {
361 updateEnabledButtons();
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
) {
376 if (fileTab
->spinBoxRevision
->isEnabled())
377 fileTab
->spinBoxRevision
->setValue(id
);
379 ListView
* h
= fileTab
->histListView
;
380 int row
= h
->model()->rowCount() - id
;
381 QModelIndex idx
= h
->model()->index(row
, 0);
382 h
->setCurrentIndex(idx
);