00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <qpainter.h>
00010 #include <qapplication.h>
00011 #include <qheader.h>
00012 #include <qdragobject.h>
00013 #include <qdatetime.h>
00014 #include "common.h"
00015 #include "domain.h"
00016 #include "git.h"
00017 #include "listview.h"
00018
00019 using namespace QGit;
00020
00021 ListView::ListView(Domain* dm, Git* g, QListView* l, FileHistory* f, const QFont& fnt) :
00022 QObject(dm), d(dm), git(g), lv(l), fh(f) {
00023
00024 st = &(d->st);
00025 filterNextContextMenuRequest = currentChangedEmitted = false;
00026 setupListView(fnt);
00027 clear();
00028
00029 lv->setAcceptDrops(git->isMainHistory(fh));
00030 lv->viewport()->setAcceptDrops(git->isMainHistory(fh));
00031 lv->viewport()->installEventFilter(this);
00032
00033 connect(lv, SIGNAL(currentChanged(QListViewItem*)),
00034 this, SLOT(on_currentChanged(QListViewItem*)));
00035
00036 connect(lv, SIGNAL(mouseButtonPressed(int,QListViewItem*,const QPoint&,int)),
00037 this, SLOT(on_mouseButtonPressed(int,QListViewItem*,const QPoint&,int)));
00038
00039 connect(lv, SIGNAL(clicked(QListViewItem*)),
00040 this, SLOT(on_clicked(QListViewItem*)));
00041
00042 connect(lv, SIGNAL(onItem(QListViewItem*)),
00043 this, SLOT(on_onItem(QListViewItem*)));
00044
00045 connect(lv, SIGNAL(contextMenuRequested(QListViewItem*, const QPoint&,int)),
00046 this, SLOT(on_contextMenuRequested(QListViewItem*)));
00047 }
00048
00049 ListView::~ListView() {
00050
00051 git->cancelDataLoading(fh);
00052 }
00053
00054 void ListView::setupListView(const QFont& fnt) {
00055
00056 lv->setItemMargin(0);
00057 lv->setSorting(-1);
00058 lv->setFont(fnt);
00059
00060 int adj = !git->isMainHistory(fh) ? 0 : -1;
00061
00062 lv->setColumnWidthMode(GRAPH_COL, QListView::Manual);
00063 lv->setColumnWidthMode(LOG_COL + adj, QListView::Manual);
00064 lv->setColumnWidthMode(AUTH_COL + adj, QListView::Manual);
00065 lv->setColumnWidthMode(TIME_COL + adj, QListView::Maximum);
00066
00067 lv->setColumnWidth(GRAPH_COL, DEF_GRAPH_COL_WIDTH);
00068 lv->setColumnWidth(LOG_COL + adj, DEF_LOG_COL_WIDTH);
00069 lv->setColumnWidth(AUTH_COL + adj, DEF_AUTH_COL_WIDTH);
00070 lv->setColumnWidth(TIME_COL + adj, DEF_TIME_COL_WIDTH);
00071
00072 lv->header()->setStretchEnabled(false);
00073 lv->header()->setStretchEnabled(true, LOG_COL + adj);
00074 }
00075
00076 void ListView::on_repaintListViews(const QFont& f) {
00077
00078 lv->setFont(f);
00079 lv->ensureItemVisible(lv->currentItem());
00080 }
00081
00082 void ListView::clear() {
00083
00084 git->cancelDataLoading(fh);
00085 lv->clear();
00086 diffTarget = NULL;
00087
00088 int adj = !git->isMainHistory(fh) ? 0 : -1;
00089
00090 if (testFlag(REL_DATE_F)) {
00091 secs = QDateTime::currentDateTime().toTime_t();
00092 lv->setColumnText(TIME_COL + adj, "Last Change");
00093 } else {
00094 secs = 0;
00095 lv->setColumnText(TIME_COL + adj, "Author Date");
00096 }
00097 }
00098
00099 void ListView::updateIdValues() {
00100
00101 if (git->isMainHistory(fh))
00102 return;
00103
00104 uint id = lv->childCount();
00105 QListViewItem* item = lv->firstChild();
00106 while (item) {
00107 item->setText(ANN_ID_COL, QString::number(id--) + " ");
00108 item = item->itemBelow();
00109 }
00110 }
00111
00112 void ListView::getSelectedItems(QStringList& selectedItems) {
00113
00114 selectedItems.clear();
00115 QListViewItem* item = lv->firstChild();
00116 while (item) {
00117 if (item->isSelected())
00118 selectedItems.append(((ListViewItem*)item)->sha());
00119
00120 item = item->itemBelow();
00121 }
00122 }
00123
00124 const QString ListView::getSha(int id) {
00125
00126 if (git->isMainHistory(fh))
00127 return "";
00128
00129
00130 QListViewItem* item = lv->currentItem();
00131 if (item && item->text(ANN_ID_COL).toInt() == id)
00132 return ((ListViewItem*)item)->sha();
00133
00134 item = lv->firstChild();
00135 while (item) {
00136 if (item->text(ANN_ID_COL).toInt() == id)
00137 return ((ListViewItem*)item)->sha();
00138
00139 item = item->itemBelow();
00140 }
00141 return "";
00142 }
00143
00144 ListViewItem* ListView::findItemSha(SCRef sha) const {
00145
00146
00147 if (sha.isEmpty())
00148 return NULL;
00149
00150 QListViewItemIterator it(lv->currentItem() ? lv->currentItem() : lv->firstChild());
00151 QListViewItem *sentinel = NULL;
00152 ListViewItem *item;
00153
00154 for (int pass = 0; pass < 2; pass++) {
00155 while ((item = (ListViewItem*)it.current()) != sentinel) {
00156 if (sha == item->sha())
00157 return item;
00158 ++it;
00159 }
00160 it = QListViewItemIterator(lv->firstChild());
00161 sentinel = lv->currentItem() ? lv->currentItem() : lv->firstChild();
00162 }
00163 return NULL;
00164 }
00165
00166 void ListView::setHighlight(SCRef diffToSha) {
00167
00168 if (diffTarget && diffTarget->sha() == diffToSha)
00169 return;
00170
00171
00172 if (diffTarget) {
00173 diffTarget->setDiffTarget(false);
00174 diffTarget = NULL;
00175 }
00176 if (diffToSha.isEmpty())
00177 return;
00178
00179 diffTarget = findItemSha(diffToSha);
00180 if (diffTarget && (diffTarget->sha() != ZERO_SHA))
00181 diffTarget->setDiffTarget(true);
00182 }
00183
00184 bool ListView::update() {
00185
00186 ListViewItem* item = static_cast<ListViewItem*>(lv->currentItem());
00187
00188 if (item && (item->sha() == st->sha())) {
00189 lv->setSelected(item, st->selectItem());
00190 lv->ensureItemVisible(item);
00191 } else {
00192
00193
00194 lv->clearSelection();
00195
00196 item = findItemSha(st->sha());
00197 if (item) {
00198 lv->setCurrentItem(item);
00199 lv->setSelected(item, st->selectItem());
00200 lv->ensureItemVisible(item);
00201 }
00202 }
00203 if (git->isMainHistory(fh))
00204 setHighlight(st->diffToSha());
00205
00206 return (item != NULL);
00207 }
00208
00209
00210
00211 void ListView::on_newRevsAdded(const FileHistory* f, const QValueVector<QString>& shaVec) {
00212
00213 if (f != fh)
00214 return;
00215
00216 bool evenLine = !(lv->childCount() % 2);
00217
00218 if (lv->childCount() == 0)
00219 lastItem = NULL;
00220
00221 lv->setUpdatesEnabled(false);
00222 for (uint i = lv->childCount(); i < shaVec.count(); i++) {
00223 lastItem = new ListViewItem(lv, lastItem, git, shaVec[i], evenLine, secs, fh);
00224 evenLine = !evenLine;
00225 }
00226 lv->setUpdatesEnabled(true);
00227 }
00228
00229 void ListView::on_currentChanged(QListViewItem* item) {
00230
00231 currentChangedEmitted = true;
00232 SCRef selRev(item ? (static_cast<ListViewItem*>(item))->sha() : "");
00233 if (st->sha() != selRev) {
00234 st->setSha(selRev);
00235 st->setSelectItem(true);
00236 UPDATE_DOMAIN(d);
00237 }
00238 }
00239
00240 void ListView::on_mouseButtonPressed(int b, QListViewItem* item, const QPoint&, int) {
00241
00242 if (item && b == Qt::LeftButton)
00243 d->setReadyToDrag(true);
00244
00245
00246
00247
00248
00249
00250
00251 if (item && !currentChangedEmitted && item == lv->currentItem() && item->isSelected())
00252 on_currentChanged(item);
00253
00254 currentChangedEmitted = false;
00255 }
00256
00257 void ListView::on_clicked(QListViewItem*) {
00258
00259 d->setReadyToDrag(false);
00260 }
00261
00262 void ListView::on_onItem(QListViewItem*) {
00263
00264 if (!d->isReadyToDrag() || !d->setDragging(true))
00265 return;
00266
00267 QStringList selRevs;
00268 getSelectedItems(selRevs);
00269 selRevs.remove(ZERO_SHA);
00270
00271 if (!selRevs.empty()) {
00272 const QString h(d->dragHostName() + '\n');
00273 QString dragRevs = selRevs.join(h).append(h).stripWhiteSpace();
00274 QDragObject* drObj = new QTextDrag(dragRevs, lv);
00275 drObj->dragCopy();
00276 }
00277 d->setDragging(false);
00278 }
00279
00280 void ListView::on_contextMenuRequested(QListViewItem* item) {
00281
00282 if (!item)
00283 return;
00284
00285 if (filterNextContextMenuRequest) {
00286
00287 filterNextContextMenuRequest = false;
00288 return;
00289 }
00290 emit contextMenu(((ListViewItem*)item)->sha(), POPUP_LIST_EV);
00291 }
00292
00293
00294 bool ListView::eventFilter(QObject* obj, QEvent* ev) {
00295
00296
00297
00298
00299 if (obj == lv->viewport() && ev->type() == QEvent::MouseButtonPress) {
00300 QMouseEvent* e = static_cast<QMouseEvent*>(ev);
00301 if (e->button() == Qt::RightButton)
00302 return filterRightButtonPressed(e);
00303 }
00304 if (obj == lv->viewport() && ev->type() == QEvent::Drop) {
00305 QDropEvent* e = static_cast<QDropEvent*>(ev);
00306 return filterDropEvent(e);
00307 }
00308 return QObject::eventFilter(obj, ev);
00309 }
00310
00311 bool ListView::filterRightButtonPressed(QMouseEvent* e) {
00312
00313 ListViewItem* item = static_cast<ListViewItem*>(lv->itemAt(e->pos()));
00314 if (!item)
00315 return false;
00316
00317 if (e->state() == Qt::ControlButton) {
00318
00319 SCRef diffToSha(item->sha());
00320
00321 if (diffToSha != ZERO_SHA && st->sha() != ZERO_SHA) {
00322
00323 if (diffToSha != st->diffToSha())
00324 st->setDiffToSha(diffToSha);
00325 else
00326 st->setDiffToSha("");
00327
00328 filterNextContextMenuRequest = true;
00329 UPDATE_DOMAIN(d);
00330 return true;
00331 }
00332 }
00333
00334 int column = lv->header()->sectionAt(e->pos().x());
00335 if (column == GRAPH_COL) {
00336
00337 filterNextContextMenuRequest = true;
00338 QStringList parents, children;
00339 if (getLaneParentsChilds(item, e->pos().x(), parents, children))
00340 emit lanesContextMenuRequested(parents, children);
00341
00342 return true;
00343 }
00344 return false;
00345 }
00346
00347 bool ListView::getLaneParentsChilds(ListViewItem* item, int x, SList p, SList c) {
00348
00349 uint lane = x / item->laneWidth();
00350 int t = item->getLaneType(lane);
00351 if (t == EMPTY || t == -1)
00352 return false;
00353
00354
00355 p.clear();
00356 QString root;
00357 SCRef sha(item->sha());
00358 if (!isFreeLane(t)) {
00359 p = git->revLookup(sha)->parents();
00360 root = sha;
00361 } else {
00362 SCRef par(git->getLaneParent(sha, lane));
00363 if (par.isEmpty()) {
00364 dbs("ASSERT getLaneParentsChilds: parent not found");
00365 return false;
00366 }
00367 p.append(par);
00368 root = p.first();
00369 }
00370
00371 c = git->getChilds(root);
00372 return true;
00373 }
00374
00375 bool ListView::filterDropEvent(QDropEvent* e) {
00376
00377 QString text;
00378 if (QTextDrag::decode(e, text) && !text.isEmpty()) {
00379
00380 SCList remoteRevs(QStringList::split('\n', text));
00381
00382
00383 SCRef sha(remoteRevs[0].section('@', 0, 0));
00384 SCRef remoteRepo(remoteRevs[0].section('@', 1));
00385
00386 if (sha.length() == 40 && !remoteRepo.isEmpty())
00387 emit droppedRevisions(remoteRevs);
00388 }
00389 return true;
00390 }
00391
00392
00393
00394 ListViewItem::ListViewItem(QListView* p, ListViewItem* a, Git* g, SCRef s,
00395 bool e, unsigned long t, FileHistory* f) : QListViewItem(p, a),
00396 listView_(p), git(g), fh(f), _sha(s), secs(t), isEvenLine(e) {
00397
00398 populated = isDiffTarget = isHighlighted = false;
00399 }
00400
00401 int ListViewItem::getLaneType(uint pos) const {
00402
00403 const Rev* r = git->revLookup(_sha, fh);
00404 return (pos < r->lanes.count() ? r->lanes[pos] : -1);
00405 }
00406
00407 void ListViewItem::setDiffTarget(bool b) {
00408
00409 isDiffTarget = b;
00410 repaint();
00411 }
00412
00413
00414
00415 void ListViewItem::paintGraphLane(QPainter* p, int type, int x1, int x2,
00416 const QColor& col, const QBrush& back) {
00417
00418 int h = height() / 2;
00419 int m = (x1 + x2) / 2;
00420 int r = (x2 - x1) / 3;
00421 int d = 2 * r;
00422
00423 #define P_CENTER m , h
00424 #define P_0 x2, h
00425 #define P_90 m , 0
00426 #define P_180 x1, h
00427 #define P_270 m , 2 * h
00428 #define R_CENTER m - r, h - r, d, d
00429
00430 p->setPen(QPen(col, 2));
00431
00432
00433 switch (type) {
00434 case ACTIVE:
00435 case NOT_ACTIVE:
00436 case MERGE_FORK:
00437 case MERGE_FORK_R:
00438 case MERGE_FORK_L:
00439 case JOIN:
00440 case JOIN_R:
00441 case JOIN_L:
00442 p->drawLine(P_90, P_270);
00443 break;
00444 case HEAD:
00445 case HEAD_R:
00446 case HEAD_L:
00447 case BRANCH:
00448 p->drawLine(P_CENTER, P_270);
00449 break;
00450 case TAIL:
00451 case TAIL_R:
00452 case TAIL_L:
00453 case INITIAL:
00454 case BOUNDARY:
00455 case BOUNDARY_C:
00456 case BOUNDARY_R:
00457 case BOUNDARY_L:
00458 p->drawLine(P_90, P_CENTER);
00459 break;
00460 default:
00461 break;
00462 }
00463
00464
00465 switch (type) {
00466 case MERGE_FORK:
00467 case JOIN:
00468 case HEAD:
00469 case TAIL:
00470 case CROSS:
00471 case CROSS_EMPTY:
00472 case BOUNDARY_C:
00473 p->drawLine(P_180, P_0);
00474 break;
00475 case MERGE_FORK_R:
00476 case JOIN_R:
00477 case HEAD_R:
00478 case TAIL_R:
00479 case BOUNDARY_R:
00480 p->drawLine(P_180, P_CENTER);
00481 break;
00482 case MERGE_FORK_L:
00483 case JOIN_L:
00484 case HEAD_L:
00485 case TAIL_L:
00486 case BOUNDARY_L:
00487 p->drawLine(P_CENTER, P_0);
00488 break;
00489 default:
00490 break;
00491 }
00492
00493
00494 switch (type) {
00495 case ACTIVE:
00496 case INITIAL:
00497 case BRANCH:
00498 p->setPen(Qt::NoPen);
00499 p->setBrush(col);
00500 p->drawEllipse(R_CENTER);
00501 break;
00502 case MERGE_FORK:
00503 case MERGE_FORK_R:
00504 case MERGE_FORK_L:
00505 p->setPen(Qt::NoPen);
00506 p->setBrush(col);
00507 p->drawRect(R_CENTER);
00508 break;
00509 case UNAPPLIED:
00510
00511 p->setPen(Qt::NoPen);
00512 p->setBrush(red);
00513 p->drawRect(m - r, h - 1, d, 2);
00514 break;
00515 case APPLIED:
00516
00517 p->setPen(Qt::NoPen);
00518 p->setBrush(DARK_GREEN);
00519 p->drawRect(m - r, h - 1, d, 2);
00520 p->drawRect(m - 1, h - r, 2, d);
00521 break;
00522 case BOUNDARY:
00523 p->setBrush(back);
00524 p->drawEllipse(R_CENTER);
00525 break;
00526 case BOUNDARY_C:
00527 case BOUNDARY_R:
00528 case BOUNDARY_L:
00529 p->setBrush(back);
00530 p->drawRect(R_CENTER);
00531 break;
00532 default:
00533 break;
00534 }
00535 #undef P_CENTER
00536 #undef P_0
00537 #undef P_90
00538 #undef P_180
00539 #undef P_270
00540 #undef R_CENTER
00541 }
00542
00543 void ListViewItem::paintGraph(const Rev& c, QPainter* p, const QColorGroup& cg, int width) {
00544
00545 static const QColor colors[COLORS_NUM] = { Qt::black, Qt::red, DARK_GREEN,
00546 Qt::blue, Qt::darkGray, BROWN,
00547 Qt::magenta, ORANGE };
00548 QListView* lv = myListView();
00549 if (!lv)
00550 return;
00551
00552 QColorGroup::ColorRole crole = QColorGroup::Base;
00553 if (isSelected() && lv->allColumnsShowFocus())
00554 crole = QColorGroup::Highlight;
00555
00556 QBrush back = cg.brush(crole);
00557 p->fillRect(0, 0, width, height(), back);
00558
00559 const QValueVector<int>& lanes(c.lanes);
00560 uint laneNum = lanes.count();
00561 uint mergeLane = 0;
00562 for (uint i = 0; i < laneNum; i++)
00563 if (isMerge(lanes[i])) {
00564 mergeLane = i;
00565 break;
00566 }
00567
00568 int x1 = 0, x2 = 0;
00569 int lw = laneWidth();
00570 for (uint i = 0; i < laneNum && x1 < width; i++) {
00571
00572 x1 = x2;
00573 x2 += lw;
00574
00575 int ln = lanes[i];
00576 if (ln == EMPTY)
00577 continue;
00578
00579 uint col = ( isHead(ln) || isTail(ln) || isJoin(ln)
00580 || ln == CROSS_EMPTY) ? mergeLane : i;
00581
00582 if (ln == CROSS) {
00583 paintGraphLane(p, NOT_ACTIVE, x1, x2, colors[col % COLORS_NUM], back);
00584 paintGraphLane(p, CROSS, x1, x2, colors[mergeLane % COLORS_NUM], back);
00585 } else
00586 paintGraphLane(p, ln, x1, x2, colors[col % COLORS_NUM], back);
00587 }
00588 }
00589
00590 void ListViewItem::paintCell(QPainter* p, const QColorGroup& cg,
00591 int column, int width, int alignment) {
00592 QColorGroup _cg(cg);
00593 const Rev& c = *git->revLookup(_sha, fh);
00594
00595
00596 if (!populated) {
00597 populated = true;
00598 setupData(c);
00599 }
00600 if (column == GRAPH_COL) {
00601 paintGraph(c, p, _cg, width);
00602 return;
00603 }
00604
00605
00606 int mycolumn = (!git->isMainHistory(fh) ? column : column + 1);
00607
00608
00609 if (isInfoCol(mycolumn))
00610 _cg.setColor(QColorGroup::Base, isEvenLine ? EVEN_LINE_COL : ODD_LINE_COL);
00611
00612
00613 if (mycolumn == LOG_COL) {
00614
00615 paintTagMarks(column);
00616
00617 if (isHighlighted) {
00618 QFont f(p->font());
00619 f.setBold(true);
00620 p->save();
00621 p->setFont(f);
00622 }
00623 if (c.isDiffCache) {
00624 if (changedFiles(ZERO_SHA))
00625 _cg.setColor(QColorGroup::Base, ORANGE);
00626 else
00627 _cg.setColor(QColorGroup::Base, DARK_ORANGE);
00628 }
00629 }
00630
00631 if (isDiffTarget && isInfoCol(mycolumn))
00632 _cg.setColor(QColorGroup::Base, LIGHT_BLUE);
00633
00634 QListViewItem::paintCell(p, _cg, column, width, alignment);
00635
00636 if (isHighlighted && mycolumn == LOG_COL)
00637 p->restore();
00638 }
00639
00640 void ListViewItem::paintTagMarks(int col) {
00641
00642 uint rt = git->checkRef(_sha);
00643
00644 if (!pixmap(col) && rt == 0)
00645 return;
00646
00647 QPixmap* newPm = new QPixmap();
00648
00649 if (rt & Git::BRANCH)
00650 addBranchPixmap(&newPm);
00651
00652 if (rt & Git::RMT_BRANCH)
00653 addRefPixmap(&newPm, git->getRefName(_sha, Git::RMT_BRANCH), LIGHT_ORANGE);
00654
00655 if (rt & Git::TAG)
00656 addRefPixmap(&newPm, git->getRefName(_sha, Git::TAG), Qt::yellow);
00657
00658 if (rt & Git::REF)
00659 addRefPixmap(&newPm, git->getRefName(_sha, Git::REF), PURPLE);
00660
00661 if (!pixmap(col) || (newPm->rect() != pixmap(col)->rect()))
00662 setPixmap(col, *newPm);
00663
00664 delete newPm;
00665 }
00666
00667 void ListViewItem::addBranchPixmap(QPixmap** pp) {
00668
00669 QString curBranch;
00670 SCList refs = git->getRefName(_sha, Git::BRANCH, &curBranch);
00671 FOREACH_SL (it, refs) {
00672 bool isCur = (curBranch == *it);
00673 QColor color(isCur ? Qt::green : DARK_GREEN);
00674 addTextPixmap(pp, *it, color, isCur);
00675 }
00676 }
00677
00678 void ListViewItem::addRefPixmap(QPixmap** pp, SCList refs, const QColor& color) {
00679
00680 FOREACH_SL (it, refs)
00681 addTextPixmap(pp, *it, color, false);
00682 }
00683
00684 void ListViewItem::addTextPixmap(QPixmap** pp, SCRef text, const QColor& color, bool bold) {
00685
00686 QFont fnt(myListView()->font());
00687 if (bold)
00688 fnt.setBold(true);
00689
00690 QFontMetrics fm(fnt);
00691 QPixmap* pm = *pp;
00692 int ofs = pm->isNull() ? 0 : pm->width() + 2;
00693 int spacing = 2;
00694 int pw = fm.boundingRect(text).width() + 2 * (spacing + int(bold));
00695 int ph = fm.height() + 1;
00696
00697 QPixmap* newPm = new QPixmap(ofs + pw, ph);
00698
00699 QPainter p;
00700 p.begin(newPm);
00701 if (!pm->isNull()) {
00702 newPm->fill(isEvenLine ? EVEN_LINE_COL : ODD_LINE_COL);
00703 p.drawPixmap(0, 0, *pm);
00704 }
00705 p.setPen(Qt::black);
00706 p.setBrush(color);
00707 p.setFont(fnt);
00708 p.drawRect(ofs, 0, pw, ph);
00709 p.drawText(ofs + spacing, fm.ascent(), text);
00710 p.end();
00711
00712 delete pm;
00713 *pp = newPm;
00714 }
00715
00716 bool ListViewItem::changedFiles(SCRef c) {
00717
00718 const RevFile* f = git->getFiles(c);
00719 if (f)
00720 for (int i = 0; i < f->count(); i++)
00721 if (!f->statusCmp(i, RevFile::UNKNOWN))
00722 return true;
00723 return false;
00724 }
00725
00726 void ListViewItem::setupData(const Rev& c) {
00727
00728
00729 if (c.lanes.count() == 0)
00730 git->setLane(_sha, fh);
00731
00732
00733 int adj = !git->isMainHistory(fh) ? 0 : -1;
00734 if (_sha != ZERO_SHA) {
00735 if (secs != 0) {
00736 secs -= c.authorDate().toULong();
00737 setText(TIME_COL + adj, timeDiff(secs));
00738 } else
00739 setText(TIME_COL + adj, Git::getLocalDate(c.authorDate()));
00740 }
00741 setText(LOG_COL + adj, c.shortLog());
00742 setText(AUTH_COL + adj, c.author());
00743 }
00744
00745 const QString ListViewItem::timeDiff(unsigned long secs) const {
00746
00747 uint days = secs / (3600 * 24);
00748 uint hours = (secs - days * 3600 * 24) / 3600;
00749 uint min = (secs - days * 3600 * 24 - hours * 3600) / 60;
00750 uint sec = secs - days * 3600 * 24 - hours * 3600 - min * 60;
00751 QString tmp;
00752 if (days > 0)
00753 tmp.append(QString::number(days) + "d ");
00754
00755 if (hours > 0 || !tmp.isEmpty())
00756 tmp.append(QString::number(hours) + "h ");
00757
00758 if (min > 0 || !tmp.isEmpty())
00759 tmp.append(QString::number(min) + "m ");
00760
00761 tmp.append(QString::number(sec) + "s");
00762 return tmp;
00763 }