00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <qtextedit.h>
00010 #include <qlistview.h>
00011 #include <qspinbox.h>
00012 #include <qlineedit.h>
00013 #include <qmessagebox.h>
00014 #include <qsettings.h>
00015 #include <qstatusbar.h>
00016 #include <qlabel.h>
00017 #include <qsplitter.h>
00018 #include <qapplication.h>
00019 #include <qcursor.h>
00020 #include <qregexp.h>
00021 #include <qclipboard.h>
00022 #include <qtoolbutton.h>
00023 #include <qtabwidget.h>
00024 #include "mainimpl.h"
00025 #include "git.h"
00026 #include "annotate.h"
00027 #include "listview.h"
00028 #include "filecontent.h"
00029 #include "filebase.h"
00030 #include "fileview.h"
00031
00032 #define MAX_LINE_NUM 5
00033
00034 FileView::FileView(MainImpl* mi, Git* g) : Domain(mi, g) {
00035
00036 fileTab = new TabFile(m());
00037 m()->tabWdg->addTab(fileTab, "File");
00038 tabPosition = m()->tabWdg->count() - 1;
00039
00040 fh = new FileHistory();
00041 histListView = new ListView(this, git, fileTab->histListView, fh, m()->listViewFont);
00042 textEditFile = new FileContent(this, git, fileTab->textEditFile);
00043
00044
00045 fileTab->spinBoxRevision->setSpecialValueText(" ");
00046
00047 clear(true);
00048
00049 connect(git, SIGNAL(loadCompleted(const FileHistory*, const QString&)),
00050 this, SLOT(on_loadCompleted(const FileHistory*, const QString&)));
00051
00052 connect(git, SIGNAL(newRevsAdded(const FileHistory*, const QValueVector<QString>&)),
00053 histListView, SLOT(on_newRevsAdded(const FileHistory*, const QValueVector<QString>&)));
00054
00055 connect(m(), SIGNAL(repaintListViews(const QFont&)),
00056 histListView, SLOT(on_repaintListViews(const QFont&)));
00057
00058 connect(histListView, SIGNAL(contextMenu(const QString&, int)),
00059 this, SLOT(on_contextMenu(const QString&, int)));
00060
00061 connect(textEditFile, SIGNAL(annotationAvailable(bool)),
00062 this, SLOT(on_annotationAvailable(bool)));
00063
00064 connect(textEditFile, SIGNAL(fileAvailable(bool)),
00065 this, SLOT(on_fileAvailable(bool)));
00066
00067 connect(textEditFile, SIGNAL(revIdSelected(int)),
00068 this, SLOT(on_revIdSelected(int)));
00069
00070 connect(fileTab->toolButtonCopy, SIGNAL(clicked()),
00071 this, SLOT(on_toolButtonCopy_clicked()));
00072
00073 connect(fileTab->toolButtonShowAnnotate, SIGNAL(toggled(bool)),
00074 this, SLOT(on_toolButtonShowAnnotate_toggled(bool)));
00075
00076 connect(fileTab->toolButtonFindAnnotate, SIGNAL(toggled(bool)),
00077 this, SLOT(on_toolButtonFindAnnotate_toggled(bool)));
00078
00079 connect(fileTab->toolButtonRangeFilter, SIGNAL(toggled(bool)),
00080 this, SLOT(on_toolButtonRangeFilter_toggled(bool)));
00081
00082 connect(fileTab->toolButtonPin, SIGNAL(toggled(bool)),
00083 this, SLOT(on_toolButtonPin_toggled(bool)));
00084
00085 connect(fileTab->toolButtonHighlightText, SIGNAL(toggled(bool)),
00086 this, SLOT(on_toolButtonHighlightText_toggled(bool)));
00087
00088 connect(fileTab->spinBoxRevision, SIGNAL(valueChanged(int)),
00089 this, SLOT(on_spinBoxRevision_valueChanged(int)));
00090 }
00091
00092 FileView::~FileView() {
00093
00094 if (!parent())
00095 return;
00096
00097 delete textEditFile;
00098 delete histListView;
00099 delete fh;
00100
00101
00102 m()->tabWdg->removePage(fileTab);
00103 delete fileTab;
00104
00105 m()->statusBar()->clear();
00106 QApplication::restoreOverrideCursor();
00107 }
00108
00109 void FileView::clear(bool complete) {
00110
00111 if (complete) {
00112 st.clear();
00113 m()->tabWdg->changeTab(fileTab, "File");
00114 fileTab->toolButtonCopy->setEnabled(false);
00115 }
00116 histListView->clear();
00117 textEditFile->clear();
00118
00119 annotateAvailable = fileAvailable = false;
00120 updateEnabledButtons();
00121
00122 fileTab->toolButtonPin->setEnabled(false);
00123 fileTab->toolButtonPin->setOn(false);
00124 fileTab->spinBoxRevision->setEnabled(false);
00125 fileTab->spinBoxRevision->setValue(fileTab->spinBoxRevision->minValue());
00126 }
00127
00128 bool FileView::goToCurrentAnnotation() {
00129
00130 QListViewItem* item = fileTab->histListView->currentItem();
00131 int id = (item) ? item->text(QGit::ANN_ID_COL).toInt() : 0;
00132 textEditFile->goToAnnotation(id);
00133 return (id != 0);
00134 }
00135
00136 void FileView::updateSpinBoxValue() {
00137
00138 QListViewItem* item = fileTab->histListView->currentItem();
00139 if (!item || !fileTab->spinBoxRevision->isEnabled())
00140 return;
00141
00142 int id = item->text(QGit::ANN_ID_COL).toInt();
00143 fileTab->spinBoxRevision->setValue(id);
00144 }
00145
00146 bool FileView::doUpdate(bool force) {
00147
00148 if (st.fileName().isEmpty())
00149 return false;
00150
00151 if (st.isChanged(StateInfo::FILE_NAME) || force) {
00152
00153 clear(false);
00154 m()->tabWdg->changeTab(fileTab, st.fileName());
00155 fh->clear(st.fileName());
00156 if (git->startFileHistory(fh)) {
00157 QApplication::restoreOverrideCursor();
00158 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
00159 m()->statusBar()->message("Retrieving history of '" +
00160 st.fileName() + "'...");
00161 }
00162 } else if (histListView->update() || st.sha().isEmpty()) {
00163
00164 updateSpinBoxValue();
00165 m()->statusBar()->message(git->getRevInfo(st.sha()));
00166 }
00167 if (!fileTab->toolButtonPin->isOn())
00168 textEditFile->update();
00169
00170 return true;
00171 }
00172
00173
00174
00175 void FileView::updateEnabledButtons() {
00176
00177 QToolButton* copy = fileTab->toolButtonCopy;
00178 QToolButton* showAnnotate = fileTab->toolButtonShowAnnotate;
00179 QToolButton* findAnnotate = fileTab->toolButtonFindAnnotate;
00180 QToolButton* rangeFilter = fileTab->toolButtonRangeFilter;
00181 QToolButton* highlight = fileTab->toolButtonHighlightText;
00182
00183
00184 copy->setEnabled(fileAvailable);
00185 showAnnotate->setEnabled(annotateAvailable);
00186 findAnnotate->setEnabled(annotateAvailable);
00187 rangeFilter->setEnabled(annotateAvailable);
00188 highlight->setEnabled(fileAvailable && git->isTextHighlighter());
00189
00190
00191 if (!showAnnotate->isOn())
00192 findAnnotate->setEnabled(false);
00193
00194 if (highlight->isOn()) {
00195 findAnnotate->setEnabled(false);
00196 rangeFilter->setEnabled(false);
00197 }
00198 if (rangeFilter->isOn())
00199 highlight->setEnabled(false);
00200
00201
00202 if (!annotateAvailable && rangeFilter->isOn())
00203 rangeFilter->toggle();
00204 }
00205
00206 void FileView::on_toolButtonCopy_clicked() {
00207
00208 textEditFile->copySelection();
00209 }
00210
00211 void FileView::on_toolButtonShowAnnotate_toggled(bool b) {
00212
00213 updateEnabledButtons();
00214 textEditFile->setShowAnnotate(b);
00215
00216 if (b && fileTab->toolButtonFindAnnotate->isOn())
00217 goToCurrentAnnotation();
00218 }
00219
00220 void FileView::on_toolButtonFindAnnotate_toggled(bool b) {
00221
00222 updateEnabledButtons();
00223 if (b)
00224 goToCurrentAnnotation();
00225 }
00226
00227 void FileView::on_toolButtonPin_toggled(bool b) {
00228
00229
00230 fileTab->spinBoxRevision->setDisabled(b);
00231
00232 if (!b) {
00233 updateSpinBoxValue();
00234 textEditFile->update(true);
00235 }
00236 }
00237
00238 void FileView::on_toolButtonRangeFilter_toggled(bool b) {
00239
00240 updateEnabledButtons();
00241 if (b) {
00242 if (!textEditFile->annotateAvailable()) {
00243 dbs("ASSERT in on_toolButtonRangeFilter_toggled: annotate not available");
00244 return;
00245 }
00246 if (!fileTab->textEditFile->hasSelectedText()) {
00247 m()->statusBar()->message("Please select some text");
00248 return;
00249 }
00250 }
00251 bool rangeFilterActive = textEditFile->rangeFilter(b);
00252 filterOnRange(rangeFilterActive);
00253 }
00254
00255 void FileView::on_toolButtonHighlightText_toggled(bool b) {
00256
00257 updateEnabledButtons();
00258 textEditFile->setHighlightSource(b);
00259 }
00260
00261 void FileView::on_spinBoxRevision_valueChanged(int id) {
00262
00263 if (id != fileTab->spinBoxRevision->minValue()) {
00264
00265 SCRef selRev(histListView->getSha(id));
00266
00267 if (st.sha() != selRev) {
00268 st.setSha(selRev);
00269 st.setSelectItem(true);
00270 UPDATE();
00271 }
00272 }
00273 }
00274
00275 void FileView::on_loadCompleted(const FileHistory* f, const QString&) {
00276
00277 QApplication::restoreOverrideCursor();
00278
00279 if (f != fh)
00280 return;
00281
00282 histListView->updateIdValues();
00283 int maxId = fileTab->histListView->childCount();
00284 if (maxId == 0) {
00285 m()->statusBar()->clear();
00286 return;
00287 }
00288 fileTab->spinBoxRevision->setMaxValue(maxId);
00289 fileTab->toolButtonPin->setEnabled(true);
00290 fileTab->spinBoxRevision->setEnabled(true);
00291
00292 UPDATE();
00293
00294 updateProgressBar(0);
00295 textEditFile->startAnnotate(fh);
00296 }
00297
00298 void FileView::showAnnotation() {
00299
00300 if ( !fileTab->toolButtonPin->isOn()
00301 && fileTab->toolButtonShowAnnotate->isEnabled()
00302 && fileTab->toolButtonShowAnnotate->isOn()) {
00303
00304 textEditFile->setShowAnnotate(true);
00305
00306 if ( fileTab->toolButtonFindAnnotate->isEnabled()
00307 && fileTab->toolButtonFindAnnotate->isOn())
00308
00309 goToCurrentAnnotation();
00310 }
00311 }
00312
00313 void FileView::on_annotationAvailable(bool b) {
00314
00315 annotateAvailable = b;
00316 updateEnabledButtons();
00317
00318 if (b)
00319 showAnnotation();
00320 }
00321
00322 void FileView::on_fileAvailable(bool b) {
00323
00324 fileAvailable = b;
00325 updateEnabledButtons();
00326
00327 if (b) {
00328
00329 if (fileTab->toolButtonRangeFilter->isOn())
00330 textEditFile->goToRangeStart();
00331
00332 showAnnotation();
00333 }
00334 }
00335
00336 void FileView::on_revIdSelected(int id) {
00337
00338 if (id == 0)
00339 return;
00340
00341 if (fileTab->spinBoxRevision->isEnabled())
00342 fileTab->spinBoxRevision->setValue(id);
00343 else {
00344 QListView* hv = fileTab->histListView;
00345 QString row = QString::number(id);
00346 QListViewItem* item = hv->findItem(row, QGit::ANN_ID_COL, Qt::Contains);
00347 hv->setCurrentItem(item);
00348 }
00349 }
00350
00351
00352
00353 void FileView::customEvent(QCustomEvent* e) {
00354
00355 if (e->type() == (int)QGit::ANN_PRG_EV)
00356 updateProgressBar(((AnnotateProgressEvent*)e)->myData().toInt());
00357 else
00358 Domain::customEvent(e);
00359 }
00360
00361 void FileView::updateProgressBar(int annotatedNum) {
00362
00363 uint tot = fileTab->histListView->childCount();
00364 if (tot == 0)
00365 return;
00366
00367 int cc = (annotatedNum * 100) / tot;
00368 int idx = (annotatedNum * 40) / tot;
00369 QString head("Annotating '" + st.fileName() + "' [");
00370 QString tail("] " + QString::number(cc) + " %");
00371 QString done, toDo;
00372 done.fill('.', idx);
00373 toDo.fill(' ', 40 - idx);
00374 m()->statusBar()->message(head + done + toDo + tail);
00375 }
00376
00377 void FileView::filterOnRange(bool isOn) {
00378
00379
00380 QListView* hv = fileTab->histListView;
00381 QListViewItemIterator it(hv);
00382 bool evenLine = false;
00383 int visibleCnt = 0;
00384 RangeInfo r;
00385 while (it.current()) {
00386 ListViewItem* item = static_cast<ListViewItem*>(it.current());
00387
00388 if (isOn) {
00389 if (!textEditFile->getRange(item->sha(), &r))
00390 continue;
00391
00392 if (r.modified) {
00393 item->setEven(evenLine);
00394 evenLine = !evenLine;
00395 visibleCnt++;
00396 } else
00397 item->setVisible(false);
00398 } else {
00399 item->setEven(evenLine);
00400 evenLine = !evenLine;
00401 if (!item->isVisible())
00402 item->setVisible(true);
00403 }
00404 ++it;
00405 }
00406 QString msg;
00407 if (isOn)
00408 msg = QString("Found %1 matches. Toggle filter "
00409 "button to remove the filter").arg(visibleCnt);
00410 else
00411 hv->ensureItemVisible(hv->currentItem());
00412
00413 m()->statusBar()->message(msg);
00414 }