Logo Search packages:      
Sourcecode: qgit version File versions

filelist.cpp

/*
      Author: Marco Costalba (C) 2005-2006

      Copyright: See COPYING file that comes with this distribution
*/
#include <qlistview.h>
#include <qlistbox.h>
#include <qapplication.h>
#include <qpainter.h>
#include <qdragobject.h>
#include "mainimpl.h"
#include "git.h"
#include "domain.h"
#include "filelist.h"

ListBoxFileItem::ListBoxFileItem(QListBox* lb, SCRef t, const QColor& c) :
                                 QListBoxText(lb, t), myColor(c) {}

void ListBoxFileItem::paint(QPainter* p) {

      if (myColor != Qt::black) {
            p->save();
            p->setPen(myColor);
            QListBoxText::paint(p);
            p->restore();
      } else
            QListBoxText::paint(p);
}

ListBoxFiles::ListBoxFiles(Domain* dm, Git* g, QListBox* l) :
                           QObject(dm), d(dm), git(g), lb(l) {
      st = &(d->st);

      connect(lb, SIGNAL(currentChanged(QListBoxItem*)),
              this, SLOT(on_currentChanged(QListBoxItem*)));

      connect(lb, SIGNAL(contextMenuRequested(QListBoxItem*, const QPoint&)),
              this, SLOT(on_contextMenuRequested(QListBoxItem*)));

      connect(lb, SIGNAL(mouseButtonPressed(int, QListBoxItem*, const QPoint&)),
              this, SLOT(on_mouseButtonPressed(int, QListBoxItem*, const QPoint&)));

      connect(lb, SIGNAL(onItem(QListBoxItem*)),
              this,SLOT(on_onItem(QListBoxItem*)));

      connect(lb, SIGNAL(onViewport()),
              this,SLOT(on_onViewport()));

      connect(lb, SIGNAL(clicked(QListBoxItem*)),
              this,SLOT(on_clicked(QListBoxItem*)));
}

void ListBoxFiles::clear() {

      lb->clear();
}

void ListBoxFiles::update(const RevFile* files, bool newFiles) {

      if (st->diffToSha().isEmpty())
            lb->unsetPalette();
      else if (lb->paletteBackgroundColor() != QGit::LIGHT_BLUE)
            lb->setPaletteBackgroundColor(QGit::LIGHT_BLUE);

      if (newFiles)
            insertFiles(files);

      QString fileName(lb->currentText());
      git->removeExtraFileInfo(&fileName); // could be a renamed/copied file

      if (fileName && (fileName == st->fileName())) {
            lb->setSelected(lb->currentItem(), st->selectItem()); // just a refresh
            return;
      }
      lb->clearSelection();

      if (st->fileName().isEmpty())
            return;

      QListBoxItem* c = lb->findItem(st->fileName(), Qt::ExactMatch);
      if (c == NULL) { // could be a renamed/copied file, try harder

            fileName = st->fileName();
            git->addExtraFileInfo(&fileName, st->sha(), st->diffToSha(), st->allMergeFiles());
            c = lb->findItem(fileName, Qt::ExactMatch);
      }
      lb->setSelected(c, st->selectItem()); // calls current changed
}

void ListBoxFiles::insertFiles(const RevFile* files) {

      lb->clear();

      if (!files)
            return;

      if (st->isMerge()) {
            QString header((st->allMergeFiles()) ?
                            "Click to view only interesting files" :
                            "Click to view all merge files");
            new ListBoxFileItem(lb, header, Qt::blue);
      }
      if (files->names.empty())
            return;

      int prevPar = files->mergeParent[0];
      for (uint i = 0; i < files->names.count(); ++i) {

            QChar status(files->getStatus(i));
            if (status == QGit::UNKNOWN)
                  continue;

            QColor clr = Qt::black;
            if (files->mergeParent[i] != prevPar) {
                  prevPar = files->mergeParent[i];
                  new ListBoxFileItem(lb, "", clr);
                  new ListBoxFileItem(lb, "", clr);
            }
            QString extSt(files->getExtendedStatus(i));
            if (extSt.isEmpty()) {
                  if (status == QGit::MODIFIED)
                        ; // common case
                  else if (status == QGit::NEW)
                        clr = Qt::darkGreen;
                  else if (status == QGit::DELETED)
                        clr = Qt::red;
            } else {
                  clr = Qt::darkBlue;
                  // in case of rename deleted file is not shown and...
                  if (status == QGit::DELETED)
                        continue;

                  // ...new file is shown with extended info
                  if (status == QGit::NEW) {
                        new ListBoxFileItem(lb, extSt, clr);
                        continue;
                  }
            }
            new ListBoxFileItem(lb, git->filePath(*files, i), clr);
      }
}

void ListBoxFiles::on_currentChanged(QListBoxItem* item) {

      if (item) {
            if (st->isMerge() && item == lb->firstItem()) { // header clicked

                  // In a listbox without current item, as soon as the box
                  // gains focus the first item becomes the current item
                  // and a spurious currentChanged() signal is sent.
                  // In case of a merge the signal arrives here and fakes
                  // the user clicking on the header.
                  //
                  // The problem arise when user clicks on a merge header,
                  // then list box gains focus and current item becomes null
                  // because the content of the list is cleared and updated.
                  //
                  // If now tab is changed list box loose the focus and,
                  // upon changing back again the tab the signal triggers
                  // because Qt gives back the focus to the listbox.
                  //
                  // The workaround here is to give the focus away as soon
                  // as the user clicks on the merge header. Note that a
                  // lb->clearFocus() is not enough, we really need to
                  // reassign the focus to someone else.
                  d->tab()->setFocus();

                  st->setAllMergeFiles(!st->allMergeFiles());
                  st->setSelectItem(true);
                  UPDATE_DOMAIN(d);
                  return;
            }
            QString fileName(item->text());
            git->removeExtraFileInfo(&fileName);
            // if we are called by updateFileList() fileName is already updated
            if (st->fileName() != fileName) { // avoid loops
                  st->setFileName(fileName);
                  st->setSelectItem(true);
                  UPDATE_DOMAIN(d);
            }
      }
}

void ListBoxFiles::on_contextMenuRequested(QListBoxItem* item) {

      if (!item)
            return;

      int idx = lb->index(item);
      if (idx == 0 && st->isMerge()) // header clicked
            return;

      emit contextMenu(item->text(), QGit::POPUP_FILE_EV);
}

void ListBoxFiles::on_mouseButtonPressed(int b, QListBoxItem* item, const QPoint&) {

      if (item && b == Qt::LeftButton) {
            d->setReadyToDrag(true);
            dragFileName = item->text();
      }
}

void ListBoxFiles::on_clicked(QListBoxItem*) {

      d->setReadyToDrag(false); // in case of just click without moving
}

void ListBoxFiles::on_onItem(QListBoxItem*) { mouseMoved(); }
void ListBoxFiles::on_onViewport() { mouseMoved(); }

void ListBoxFiles::mouseMoved() {

      if (d->isReadyToDrag()) {

            if (!d->setDragging(true))
                  return;

            if (dragFileName.isEmpty())
                  dbs("ASSERT in ListBoxFiles::on_onItem: empty drag name");

            QDragObject* drObj = new QTextDrag(dragFileName, lb);
            dragFileName = "";

            drObj->dragCopy(); // do NOT delete drObj. Blocking until drop event

            d->setDragging(false);
      }
}

Generated by  Doxygen 1.6.0   Back to index