Logo Search packages:      
Sourcecode: qgit version File versions  Download package

fileview.cpp

/*
      Description: file viewer window

      Author: Marco Costalba (C) 2005-2006

      Copyright: See COPYING file that comes with this distribution

*/
#include <qtextedit.h>
#include <qlistview.h>
#include <qspinbox.h>
#include <qlineedit.h>
#include <qmessagebox.h>
#include <qsettings.h>
#include <qstatusbar.h>
#include <qlabel.h>
#include <qsplitter.h>
#include <qapplication.h>
#include <qcursor.h>
#include <qregexp.h>
#include <qclipboard.h>
#include <qtoolbutton.h>
#include <qtabwidget.h>
#include "mainimpl.h"
#include "git.h"
#include "annotate.h"
#include "listview.h"
#include "filecontent.h"
#include "filebase.h"
#include "fileview.h"

#define MAX_LINE_NUM 5

FileView::FileView(MainImpl* mi, Git* g) : Domain(mi, g) {

      EM_INIT(exDtorCalled, "Closing file viewer");

      fileTab = new TabFile(m());
      m()->tabWdg->addTab(fileTab, "File");
      tabPosition = m()->tabWdg->count() - 1;

      fh = new FileHistory();
      histListView = new ListView(this, git, fileTab->histListView, fh);
      textEditFile = new FileContent(this, git, fileTab->textEditFile);

      // cannot be set directly in the .ui file
      fileTab->spinBoxRevision->setSpecialValueText(" ");

      connect(git, SIGNAL(loadCompleted(const FileHistory*, const QString&)),
              this, SLOT(on_loadCompleted(const FileHistory*, const QString&)));

      connect(git, SIGNAL(newRevsAdded(const FileHistory*, const QValueVector<QString>&)),
      histListView, SLOT(on_newRevsAdded(const FileHistory*, const QValueVector<QString>&)));

      connect(histListView, SIGNAL(contextMenu(const QString&, int)),
              this, SLOT(on_contextMenu(const QString&, int)));

      connect(textEditFile, SIGNAL(annotationAvailable(bool)),
              this, SLOT(on_annotationAvailable(bool)));

      connect(textEditFile, SIGNAL(fileAvailable(bool)),
              this, SLOT(on_fileAvailable(bool)));

      connect(textEditFile, SIGNAL(revIdSelected(int)),
              this, SLOT(on_revIdSelected(int)));

      connect(fileTab->toolButtonCopy, SIGNAL(clicked()),
              this, SLOT(on_toolButtonCopy_clicked()));

      connect(fileTab->toolButtonShowAnnotate, SIGNAL(toggled(bool)),
              this, SLOT(on_toolButtonShowAnnotate_toggled(bool)));

      connect(fileTab->toolButtonFindAnnotate, SIGNAL(toggled(bool)),
              this, SLOT(on_toolButtonFindAnnotate_toggled(bool)));

      connect(fileTab->toolButtonRangeFilter, SIGNAL(toggled(bool)),
              this, SLOT(on_toolButtonRangeFilter_toggled(bool)));

      connect(fileTab->toolButtonPin, SIGNAL(toggled(bool)),
              this, SLOT(on_toolButtonPin_toggled(bool)));

      connect(fileTab->toolButtonHighlightText, SIGNAL(toggled(bool)),
              this, SLOT(on_toolButtonHighlightText_toggled(bool)));

      connect(fileTab->spinBoxRevision, SIGNAL(valueChanged(int)),
              this, SLOT(on_spinBoxRevision_valueChanged(int)));
}

FileView::~FileView() {

      if (!parent())
            return;

      EM_RAISE(exDtorCalled);

      delete textEditFile; // delete now, without waiting base QObject d'tor
      delete histListView; // to do the job for us, we need them out before
      delete fh;           // Domain d'tor is called.
      delete fileTab;

      m()->statusBar()->clear(); // cleanup any pending progress info
      QApplication::restoreOverrideCursor();
}

void FileView::clear(bool complete) {

      if (complete) {
            st.clear();
            m()->tabWdg->changeTab(fileTab, "File");
            fileTab->toolButtonCopy->setEnabled(false);
      }
      histListView->clear();
      textEditFile->clear();

      fileTab->toolButtonHighlightText->setEnabled(false);
      fileTab->toolButtonPin->setEnabled(false);
      fileTab->toolButtonPin->setOn(false); // should not trigger an update
      fileTab->spinBoxRevision->setEnabled(false);
      fileTab->spinBoxRevision->setValue(fileTab->spinBoxRevision->minValue()); // clears the box
}

bool FileView::goToCurrentAnnotation() {

      QListViewItem* item = fileTab->histListView->currentItem();
      int id = (item) ? item->text(QGit::ANN_ID_COL).toInt() : 0;
      textEditFile->goToAnnotation(id);
      return (id != 0);
}

void FileView::updateSpinBoxValue() {

      QListViewItem* item = fileTab->histListView->currentItem();
      if (!item || !fileTab->spinBoxRevision->isEnabled())
            return;

      int id = item->text(QGit::ANN_ID_COL).toInt();
      fileTab->spinBoxRevision->setValue(id); // triggers on_spinBoxRevision_valueChanged()
}

bool FileView::doUpdate() {

      if (st.fileName().isEmpty())
            return false;

      try {
            EM_REGISTER(exDtorCalled);

            if (st.fileName(true) != st.fileName(false)) {

                  clear(false);

                  m()->tabWdg->changeTab(fileTab, st.fileName());

                  QApplication::restoreOverrideCursor();
                  QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));

                  m()->statusBar()->message("Retrieving history of '" +
                                            st.fileName() + "'...");
                  fh->reset(st.fileName());
                  git->startFileHistory(fh);

            } else {
                  bool found = histListView->update();
                  if (found) {
                        updateSpinBoxValue();
                        m()->statusBar()->message(git->getRevInfo(st.sha(), fh));
                  }
            }
            if (!fileTab->toolButtonPin->isOn())
                  textEditFile->update();

            EM_REMOVE(exDtorCalled);

            return true; // always accept new state

      } catch (int i) {
            EM_REMOVE(exDtorCalled);

            if (EM_MATCH(i, exDtorCalled, "updating file viewer")) {
                  EM_CHECK_PENDING;
                  return false;
            }
            const QString info("Exception \'" + EM_DESC(i) + "\' "
                               "not handled in file viewer...re-throw");
            dbp("%1", info);
            throw i;
      }
}

// ************************************ SLOTS ********************************

void FileView::on_toolButtonCopy_clicked() {

      textEditFile->copySelection();
}

void FileView::on_toolButtonShowAnnotate_toggled(bool b) {

      fileTab->toolButtonFindAnnotate->setEnabled(b);
      textEditFile->setShowAnnotate(b);

      if (b && fileTab->toolButtonFindAnnotate->isOn())
            goToCurrentAnnotation();
}

void FileView::on_toolButtonFindAnnotate_toggled(bool b) {

      if (b)
            goToCurrentAnnotation();
}

void FileView::on_toolButtonPin_toggled(bool b) {
// button is enabled and togglable only if st.sha() is found

      fileTab->spinBoxRevision->setDisabled(b);

      if (!b) {
            updateSpinBoxValue();
            textEditFile->update(true);
      }
}

void FileView::on_toolButtonRangeFilter_toggled(bool b) {

      fileTab->toolButtonHighlightText->setEnabled(!b);
      if (b) {
            if (!textEditFile->annotateAvailable()) {
                  dbs("ASSERT in on_toolButtonRangeFilter_toggled: annotate not available");
                  return;
            }
            if (!fileTab->textEditFile->hasSelectedText()) {
                  m()->statusBar()->message("Please select some text to activate range filter");
                  return;
            }
      }
      bool rangeFilterActive = textEditFile->rangeFilter(b);
      filterOnRange(rangeFilterActive);
}

void FileView::on_toolButtonHighlightText_toggled(bool b) {

      fileTab->toolButtonRangeFilter->setEnabled(!b);
      textEditFile->setHighlightSource(b);
}

void FileView::on_spinBoxRevision_valueChanged(int id) {

      if (id != fileTab->spinBoxRevision->minValue()) {

            SCRef selRev(histListView->getSha(id));

            if (st.sha() != selRev) { // to avoid looping
                  st.setSha(selRev);
                  st.setSelectItem(true);
                  UPDATE();
            }
      }
}

void FileView::on_loadCompleted(const FileHistory* f, const QString&) {

      QApplication::restoreOverrideCursor();

      if (f != fh)
            return;

      histListView->updateIdValues();
      int maxId = fileTab->histListView->childCount();
      if (maxId == 0) {
            m()->statusBar()->clear();
            return;
      }
      fileTab->spinBoxRevision->setMaxValue(maxId);
      fileTab->toolButtonPin->setEnabled(true);
      fileTab->spinBoxRevision->setEnabled(true);

      UPDATE();

      updateProgressBar(0);
      textEditFile->startAnnotate(fh);
}

void FileView::showAnnotation() {

      if (  !fileTab->toolButtonPin->isOn()
          && fileTab->toolButtonShowAnnotate->isEnabled()
          && fileTab->toolButtonShowAnnotate->isOn()) {

            textEditFile->setShowAnnotate(true);

            if (   fileTab->toolButtonFindAnnotate->isEnabled()
                && fileTab->toolButtonFindAnnotate->isOn())

                  goToCurrentAnnotation();
      }
}

void FileView::on_annotationAvailable(bool b) {

      fileTab->toolButtonRangeFilter->setEnabled(b && !fileTab->toolButtonHighlightText->isOn());

      if (!b && fileTab->toolButtonRangeFilter->isOn())
            fileTab->toolButtonRangeFilter->toggle();

      fileTab->toolButtonShowAnnotate->setEnabled(b);
      fileTab->toolButtonFindAnnotate->setEnabled(b && fileTab->toolButtonShowAnnotate->isOn());

      if (b)
            showAnnotation(); // in case annotation got ready after file
}

void FileView::on_fileAvailable(bool b) {

      if (b) {
            fileTab->toolButtonCopy->setEnabled(b);
            fileTab->toolButtonHighlightText->setEnabled(!fileTab->toolButtonRangeFilter->isOn()
                                                         && git->isTextHighlighter());
            // code range is indipendent from annotation
            if (fileTab->toolButtonRangeFilter->isOn())
                  textEditFile->goToRangeStart();

            showAnnotation(); // in case file got ready after annotation
      } else
            ; // avoid flickering disabling only temporary
}

void FileView::on_revIdSelected(int id) {

      if (id != 0 && fileTab->spinBoxRevision->isEnabled())
            fileTab->spinBoxRevision->setValue(id);
}

// ******************************* data events ****************************

void FileView::customEvent(QCustomEvent* e) {

      if (e->type() == (int)QGit::ANN_PRG_EV)
            updateProgressBar(((AnnotateProgressEvent*)e)->data().toInt());
      else
            Domain::customEvent(e);
}

void FileView::updateProgressBar(int annotatedNum) {

      uint tot = fileTab->histListView->childCount();
      if (tot == 0)
            return;

      int cc = (annotatedNum * 100) / tot;
      int idx = (annotatedNum * 40) / tot;
      QString head("Annotating '" + st.fileName() + "' [");
      QString tail("] " + QString::number(cc) + " %");
      QString done, toDo;
      done.fill('.', idx);
      toDo.fill(' ', 40 - idx);
      m()->statusBar()->message(head + done + toDo + tail);
}

void FileView::filterOnRange(bool isOn) {
// TODO integrate with mainimpl function

      QListViewItemIterator it(fileTab->histListView);
      bool evenLine = false;
      int visibleCnt = 0;
      RangeInfo r;
      while (it.current()) {
            ListViewItem* item = static_cast<ListViewItem*>(it.current());

            if (isOn) {
                  if (!textEditFile->getRange(item->text(QGit::COMMIT_COL), &r))
                        continue;

                  if (r.modified) {
                        item->setEven(evenLine);
                        evenLine = !evenLine;
                        visibleCnt++;
                  } else
                        item->setVisible(false);
            } else {
                  item->setEven(evenLine);
                  evenLine = !evenLine;
                  if (!item->isVisible())
                        item->setVisible(true);
            }
            ++it;
      }
      if (isOn) {
            QString tmp(QString("Found %1 matches. Toggle filter "
                                "button to remove the filter").arg(visibleCnt));
            m()->statusBar()->message(tmp);
      } else {
            fileTab->histListView->ensureItemVisible(fileTab->histListView->currentItem());
            m()->statusBar()->clear();
      }
}

Generated by  Doxygen 1.6.0   Back to index