fix a compiler warning
[qgit4/redivivus.git] / src / filelist.cpp
blobba4895a9c8c353a87b04af96e117d5c8a864f815
1 /*
2 Author: Marco Costalba (C) 2005-2007
4 Copyright: See COPYING file that comes with this distribution
5 */
6 #include <QDrag>
7 #include <QApplication>
8 #include <QMouseEvent>
9 #include "git.h"
10 #include "domain.h"
11 #include "filelist.h"
13 FileList::FileList(QWidget* p) : QListWidget(p), d(NULL), git(NULL), st(NULL) {}
15 void FileList::setup(Domain* dm, Git* g) {
17 d = dm;
18 git = g;
19 st = &(d->st);
21 setFont(QGit::STD_FONT);
23 connect(this, SIGNAL(customContextMenuRequested(const QPoint&)),
24 this, SLOT(on_customContextMenuRequested(const QPoint&)));
26 connect(this, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)),
27 this, SLOT(on_currentItemChanged(QListWidgetItem*, QListWidgetItem*)));
30 void FileList::addItem(const QString& label, const QColor& clr) {
32 QListWidgetItem* item = new QListWidgetItem(label, this);
33 item->setForeground(clr);
36 QString FileList::currentText() {
38 QListWidgetItem* item = currentItem();
39 return (item ? item->data(Qt::DisplayRole).toString() : "");
42 void FileList::on_changeFont(const QFont& f) {
44 setFont(f);
47 void FileList::focusInEvent(QFocusEvent*) {
49 // Workaround a Qt4.2 bug
51 // When an item is clicked and FileList still doesn't have the
52 // focus we could have a double currentItemChanged() signal,
53 // the first with current set to first item, the second with
54 // current correctly set to the clicked one.
55 // Oddly enough overriding this virtual function we remove
56 // the spurious first signal if any.
58 // Unluckily in case the clicked one is the first in list we
59 // have only one event and we could miss an update in that case,
60 // so try to handle that
61 if (!st->isMerge() && row(currentItem()) == 0)
62 on_currentItemChanged(currentItem(), currentItem());
65 void FileList::on_currentItemChanged(QListWidgetItem* current, QListWidgetItem*) {
67 if (!current)
68 return;
70 if (st->isMerge() && row(current) == 0) { // header clicked
72 // In a listbox without current item, as soon as the box
73 // gains focus the first item becomes the current item
74 // and a spurious currentChanged() signal is sent.
75 // In case of a merge the signal arrives here and fakes
76 // the user clicking on the header.
78 // The problem arise when user clicks on a merge header,
79 // then list box gains focus and current item becomes null
80 // because the content of the list is cleared and updated.
82 // If now tab is changed list box loose the focus and,
83 // upon changing back again the tab the signal triggers
84 // because Qt gives back the focus to the listbox.
86 // The workaround here is to give the focus away as soon
87 // as the user clicks on the merge header. Note that a
88 // lb->clearFocus() is not enough, we really need to
89 // reassign the focus to someone else.
90 d->tabPage()->setFocus();
91 st->setAllMergeFiles(!st->allMergeFiles());
93 } else {
94 QString fileName(currentText());
95 git->removeExtraFileInfo(&fileName);
96 // if we are called by updateFileList() fileName is already updated
97 if (st->fileName() == fileName) // avoid loops
98 return;
100 st->setFileName(fileName);
102 st->setSelectItem(true);
103 UPDATE_DOMAIN(d);
106 void FileList::on_customContextMenuRequested(const QPoint&) {
108 int row = currentRow();
109 if (row == -1 || (row == 0 && st->isMerge())) // header clicked
110 return;
112 emit contextMenu(currentText(), QGit::POPUP_FILE_EV);
115 void FileList::mousePressEvent(QMouseEvent* e) {
117 if (currentItem() && e->button() == Qt::LeftButton) {
118 d->setReadyToDrag(true);
119 dragFileName = currentText();
121 QListWidget::mousePressEvent(e);
124 void FileList::mouseReleaseEvent(QMouseEvent* e) {
126 d->setReadyToDrag(false); // in case of just click without moving
127 QListWidget::mouseReleaseEvent(e);
130 void FileList::mouseMoveEvent(QMouseEvent* e) {
132 if (d->isReadyToDrag()) {
134 if (!d->setDragging(true))
135 return;
137 if (dragFileName.isEmpty())
138 dbs("ASSERT in FileList::mouseMoveEvent() empty drag name");
140 QDrag* drag = new QDrag(this);
141 QMimeData* mimeData = new QMimeData;
142 mimeData->setText(dragFileName);
143 drag->setMimeData(mimeData);
144 dragFileName = "";
145 drag->start(); // blocking until drop event
147 d->setDragging(false);
149 QListWidget::mouseMoveEvent(e);
152 void FileList::insertFiles(const RevFile* files) {
154 clear();
155 if (!files)
156 return;
158 if (st->isMerge()) {
159 const QString header((st->allMergeFiles()) ?
160 "Click to view only interesting files" : "Click to view all merge files");
161 addItem(header, Qt::blue);
163 if (files->count() == 0)
164 return;
166 bool isMergeParents = !files->mergeParent.isEmpty();
167 int prevPar = (isMergeParents ? files->mergeParent.first() : 1);
168 setUpdatesEnabled(false);
169 for (int i = 0; i < files->count(); ++i) {
171 if (files->statusCmp(i, RevFile::UNKNOWN))
172 continue;
174 QColor clr = Qt::black;
175 if (isMergeParents && files->mergeParent.at(i) != prevPar) {
176 prevPar = files->mergeParent.at(i);
177 new QListWidgetItem("", this);
178 new QListWidgetItem("", this);
180 QString extSt(files->extendedStatus(i));
181 if (extSt.isEmpty()) {
182 if (files->statusCmp(i, RevFile::NEW))
183 clr = Qt::darkGreen;
184 else if (files->statusCmp(i, RevFile::DELETED))
185 clr = Qt::red;
186 } else {
187 clr = Qt::darkBlue;
188 // in case of rename deleted file is not shown and...
189 if (files->statusCmp(i, RevFile::DELETED))
190 continue;
192 // ...new file is shown with extended info
193 if (files->statusCmp(i, RevFile::NEW)) {
194 addItem(extSt, clr);
195 continue;
198 addItem(git->filePath(*files, i), clr);
200 setUpdatesEnabled(true);
203 void FileList::update(const RevFile* files, bool newFiles) {
205 QPalette pl = QApplication::palette();
206 if (!st->diffToSha().isEmpty())
207 pl.setColor(QPalette::Base, QGit::LIGHT_BLUE);
209 setPalette(pl);
210 if (newFiles)
211 insertFiles(files);
213 QString fileName(currentText());
214 git->removeExtraFileInfo(&fileName); // could be a renamed/copied file
216 if (!fileName.isEmpty() && (fileName == st->fileName())) {
217 currentItem()->setSelected(st->selectItem()); // just a refresh
218 return;
220 clearSelection();
222 if (st->fileName().isEmpty())
223 return;
225 QList<QListWidgetItem*> l = findItems(st->fileName(), Qt::MatchExactly);
226 if (l.isEmpty()) { // could be a renamed/copied file, try harder
228 fileName = st->fileName();
229 git->addExtraFileInfo(&fileName, st->sha(), st->diffToSha(), st->allMergeFiles());
230 l = findItems(fileName, Qt::MatchExactly);
232 if (!l.isEmpty()) {
233 setCurrentItem(l.first());
234 l.first()->setSelected(st->selectItem());