filelist.cpp

Go to the documentation of this file.
00001 /*
00002         Author: Marco Costalba (C) 2005-2006
00003 
00004         Copyright: See COPYING file that comes with this distribution
00005 */
00006 #include <qlistview.h>
00007 #include <qlistbox.h>
00008 #include <qapplication.h>
00009 #include <qpainter.h>
00010 #include <qdragobject.h>
00011 #include "mainimpl.h"
00012 #include "git.h"
00013 #include "domain.h"
00014 #include "filelist.h"
00015 
00016 ListBoxFileItem::ListBoxFileItem(QListBox* lb, SCRef t, const QColor& c) :
00017                                  QListBoxText(lb, t), myColor(c) {}
00018 
00019 void ListBoxFileItem::paint(QPainter* p) {
00020 
00021         if (myColor != Qt::black) {
00022                 p->save();
00023                 p->setPen(myColor);
00024                 QListBoxText::paint(p);
00025                 p->restore();
00026         } else
00027                 QListBoxText::paint(p);
00028 }
00029 
00030 ListBoxFiles::ListBoxFiles(Domain* dm, Git* g, QListBox* l) :
00031                            QObject(dm), d(dm), git(g), lb(l) {
00032         st = &(d->st);
00033 
00034         connect(lb, SIGNAL(currentChanged(QListBoxItem*)),
00035                 this, SLOT(on_currentChanged(QListBoxItem*)));
00036 
00037         connect(lb, SIGNAL(contextMenuRequested(QListBoxItem*, const QPoint&)),
00038                 this, SLOT(on_contextMenuRequested(QListBoxItem*)));
00039 
00040         connect(lb, SIGNAL(mouseButtonPressed(int, QListBoxItem*, const QPoint&)),
00041                 this, SLOT(on_mouseButtonPressed(int, QListBoxItem*, const QPoint&)));
00042 
00043         connect(lb, SIGNAL(onItem(QListBoxItem*)),
00044                 this,SLOT(on_onItem(QListBoxItem*)));
00045 
00046         connect(lb, SIGNAL(onViewport()),
00047                 this,SLOT(on_onViewport()));
00048 
00049         connect(lb, SIGNAL(clicked(QListBoxItem*)),
00050                 this,SLOT(on_clicked(QListBoxItem*)));
00051 }
00052 
00053 void ListBoxFiles::clear() {
00054 
00055         lb->clear();
00056 }
00057 
00058 void ListBoxFiles::update(const RevFile* files, bool newFiles) {
00059 
00060         if (st->diffToSha().isEmpty())
00061                 lb->unsetPalette();
00062         else if (lb->paletteBackgroundColor() != QGit::LIGHT_BLUE)
00063                 lb->setPaletteBackgroundColor(QGit::LIGHT_BLUE);
00064 
00065         if (newFiles)
00066                 insertFiles(files); // currentItem is NULL after this call
00067 
00068         QString fileName(lb->currentText());
00069         git->removeExtraFileInfo(&fileName); // could be a renamed/copied file
00070 
00071         if (!fileName.isEmpty() && (fileName == st->fileName())) {
00072                 lb->setSelected(lb->currentItem(), st->selectItem()); // just a refresh
00073                 return;
00074         }
00075         lb->clearSelection();
00076 
00077         if (st->fileName().isEmpty())
00078                 return;
00079 
00080         QListBoxItem* c = lb->findItem(st->fileName(), Qt::ExactMatch);
00081         if (c == NULL) { // could be a renamed/copied file, try harder
00082 
00083                 fileName = st->fileName();
00084                 git->addExtraFileInfo(&fileName, st->sha(), st->diffToSha(), st->allMergeFiles());
00085                 c = lb->findItem(fileName, Qt::ExactMatch);
00086         }
00087         lb->setSelected(c, st->selectItem()); // calls current changed
00088 }
00089 
00090 void ListBoxFiles::insertFiles(const RevFile* files) {
00091 
00092         lb->clear();
00093 
00094         if (!files)
00095                 return;
00096 
00097         if (st->isMerge()) {
00098                 QString header((st->allMergeFiles()) ?
00099                                 "Click to view only interesting files" :
00100                                 "Click to view all merge files");
00101                 new ListBoxFileItem(lb, header, Qt::blue);
00102         }
00103         if (files->names.empty())
00104                 return;
00105 
00106         bool isMergeParents = !files->mergeParent.isEmpty();
00107         int prevPar = (isMergeParents ? files->mergeParent.first() : 1);
00108         for (int i = 0; i < files->count(); ++i) {
00109 
00110                 if (files->statusCmp(i, RevFile::UNKNOWN))
00111                         continue;
00112 
00113                 QColor clr = Qt::black;
00114                 if (isMergeParents && files->mergeParent[i] != prevPar) {
00115                         prevPar = files->mergeParent[i];
00116                         new ListBoxFileItem(lb, "", clr);
00117                         new ListBoxFileItem(lb, "", clr);
00118                 }
00119                 QString extSt(files->extendedStatus(i));
00120                 if (extSt.isEmpty()) {
00121                         if (files->statusCmp(i, RevFile::MODIFIED))
00122                                 ; // common case
00123                         else if (files->statusCmp(i, RevFile::NEW))
00124                                 clr = Qt::darkGreen;
00125                         else if (files->statusCmp(i, RevFile::DELETED))
00126                                 clr = Qt::red;
00127                 } else {
00128                         clr = Qt::darkBlue;
00129                         // in case of rename deleted file is not shown and...
00130                         if (files->statusCmp(i, RevFile::DELETED))
00131                                 continue;
00132 
00133                         // ...new file is shown with extended info
00134                         if (files->statusCmp(i, RevFile::NEW)) {
00135                                 new ListBoxFileItem(lb, extSt, clr);
00136                                 continue;
00137                         }
00138                 }
00139                 new ListBoxFileItem(lb, git->filePath(*files, i), clr);
00140         }
00141 }
00142 
00143 void ListBoxFiles::on_currentChanged(QListBoxItem* item) {
00144 
00145         if (item) {
00146                 if (st->isMerge() && item == lb->firstItem()) { // header clicked
00147 
00148                         // In a listbox without current item, as soon as the box
00149                         // gains focus the first item becomes the current item
00150                         // and a spurious currentChanged() signal is sent.
00151                         // In case of a merge the signal arrives here and fakes
00152                         // the user clicking on the header.
00153                         //
00154                         // The problem arise when user clicks on a merge header,
00155                         // then list box gains focus and current item becomes null
00156                         // because the content of the list is cleared and updated.
00157                         //
00158                         // If now tab is changed list box loose the focus and,
00159                         // upon changing back again the tab the signal triggers
00160                         // because Qt gives back the focus to the listbox.
00161                         //
00162                         // The workaround here is to give the focus away as soon
00163                         // as the user clicks on the merge header. Note that a
00164                         // lb->clearFocus() is not enough, we really need to
00165                         // reassign the focus to someone else.
00166                         d->tab()->setFocus();
00167 
00168                         st->setAllMergeFiles(!st->allMergeFiles());
00169                         st->setSelectItem(true);
00170                         UPDATE_DOMAIN(d);
00171                         return;
00172                 }
00173                 QString fileName(item->text());
00174                 git->removeExtraFileInfo(&fileName);
00175                 // if we are called by updateFileList() fileName is already updated
00176                 if (st->fileName() != fileName) { // avoid loops
00177                         st->setFileName(fileName);
00178                         st->setSelectItem(true);
00179                         UPDATE_DOMAIN(d);
00180                 }
00181         }
00182 }
00183 
00184 void ListBoxFiles::on_contextMenuRequested(QListBoxItem* item) {
00185 
00186         if (!item)
00187                 return;
00188 
00189         int idx = lb->index(item);
00190         if (idx == 0 && st->isMerge()) // header clicked
00191                 return;
00192 
00193         emit contextMenu(item->text(), QGit::POPUP_FILE_EV);
00194 }
00195 
00196 void ListBoxFiles::on_mouseButtonPressed(int b, QListBoxItem* item, const QPoint&) {
00197 
00198         if (item && b == Qt::LeftButton) {
00199                 d->setReadyToDrag(true);
00200                 dragFileName = item->text();
00201         }
00202 }
00203 
00204 void ListBoxFiles::on_clicked(QListBoxItem*) {
00205 
00206         d->setReadyToDrag(false); // in case of just click without moving
00207 }
00208 
00209 void ListBoxFiles::on_onItem(QListBoxItem*) { mouseMoved(); }
00210 void ListBoxFiles::on_onViewport() { mouseMoved(); }
00211 
00212 void ListBoxFiles::mouseMoved() {
00213 
00214         if (d->isReadyToDrag()) {
00215 
00216                 if (!d->setDragging(true))
00217                         return;
00218 
00219                 if (dragFileName.isEmpty())
00220                         dbs("ASSERT in ListBoxFiles::on_onItem: empty drag name");
00221 
00222                 QDragObject* drObj = new QTextDrag(dragFileName, lb);
00223                 dragFileName = "";
00224 
00225                 drObj->dragCopy(); // do NOT delete drObj. Blocking until drop event
00226 
00227                 d->setDragging(false);
00228         }
00229 }

Generated on Fri Dec 7 21:57:37 2007 for QGit by  doxygen 1.5.3