]> cloud.milkyroute.net Git - dolphin.git/blob - src/dolphindetailsview.cpp
Some port
[dolphin.git] / src / dolphindetailsview.cpp
1 /***************************************************************************
2 * Copyright (C) 2006 by Peter Penz *
3 * peter.penz@gmx.at *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20
21 #include "dolphindetailsview.h"
22
23 #include <qpainter.h>
24 #include <qobject.h>
25 #include <q3header.h>
26 #include <qclipboard.h>
27 #include <qpainter.h>
28 //Added by qt3to4:
29 #include <Q3ValueList>
30 #include <QPixmap>
31 #include <QDragMoveEvent>
32 #include <QDropEvent>
33 #include <QResizeEvent>
34 #include <QMouseEvent>
35 #include <QEvent>
36 #include <QPaintEvent>
37 #include <QStyleOptionFocusRect>
38 #include <klocale.h>
39 #include <kglobalsettings.h>
40 #include <kicontheme.h>
41 #include <qscrollbar.h>
42 #include <qcursor.h>
43 #include <qstyle.h>
44 #include <assert.h>
45
46 #include "dolphinview.h"
47 #include "viewproperties.h"
48 #include "dolphin.h"
49 #include "kiconeffect.h"
50 #include "dolphinsettings.h"
51 #include "dolphinstatusbar.h"
52 #include "detailsmodesettings.h"
53
54 DolphinDetailsView::DolphinDetailsView(DolphinView* parent) :
55 KFileDetailView(parent),
56 m_dolphinView(parent),
57 m_resizeTimer(0),
58 m_scrollTimer(0),
59 m_rubber(0)
60 {
61 m_resizeTimer = new QTimer(this);
62 connect(m_resizeTimer, SIGNAL(timeout()),
63 this, SLOT(updateColumnsWidth()));
64
65 setAcceptDrops(true);
66 setSelectionMode(KFile::Extended);
67 setHScrollBarMode(Q3ScrollView::AlwaysOff);
68
69 setColumnAlignment(SizeColumn, Qt::AlignRight);
70 for (int i = DateColumn; i <= GroupColumn; ++i) {
71 setColumnAlignment(i, Qt::AlignHCenter);
72 }
73
74 Dolphin& dolphin = Dolphin::mainWin();
75
76 connect(this, SIGNAL(onItem(Q3ListViewItem*)),
77 this, SLOT(slotOnItem(Q3ListViewItem*)));
78 connect(this, SIGNAL(onViewport()),
79 this, SLOT(slotOnViewport()));
80 connect(this, SIGNAL(contextMenuRequested(Q3ListViewItem*, const QPoint&, int)),
81 this, SLOT(slotContextMenuRequested(Q3ListViewItem*, const QPoint&, int)));
82 connect(this, SIGNAL(selectionChanged()),
83 &dolphin, SLOT(slotSelectionChanged()));
84 connect(&dolphin, SIGNAL(activeViewChanged()),
85 this, SLOT(slotActivationUpdate()));
86 connect(this, SIGNAL(itemRenamed(Q3ListViewItem*, const QString&, int)),
87 this, SLOT(slotItemRenamed(Q3ListViewItem*, const QString&, int)));
88 connect(this, SIGNAL(dropped(QDropEvent*, const KUrl::List&, const KUrl&)),
89 parent, SLOT(slotURLListDropped(QDropEvent*, const KUrl::List&, const KUrl&)));
90
91 QClipboard* clipboard = QApplication::clipboard();
92 connect(clipboard, SIGNAL(dataChanged()),
93 this, SLOT(slotUpdateDisabledItems()));
94
95 Q3Header* viewHeader = header();
96 viewHeader->setResizeEnabled(false);
97 viewHeader->setMovingEnabled(false);
98 connect(viewHeader, SIGNAL(clicked(int)),
99 this, SLOT(slotHeaderClicked(int)));
100
101 setMouseTracking(true);
102 setDefaultRenameAction(Q3ListView::Accept);
103
104 refreshSettings();
105 }
106
107 DolphinDetailsView::~DolphinDetailsView()
108 {
109 delete m_rubber;
110 m_rubber = 0;
111 }
112
113 void DolphinDetailsView::beginItemUpdates()
114 {
115 }
116
117 void DolphinDetailsView::endItemUpdates()
118 {
119 updateDisabledItems();
120
121 // Restore the current item. Use the information stored in the history if
122 // available. Otherwise use the first item as current item.
123
124 const KFileListViewItem* item = static_cast<const KFileListViewItem*>(firstChild());
125 if (item != 0) {
126 setCurrentItem(item->fileInfo());
127 }
128
129 int index = 0;
130 const Q3ValueList<URLNavigator::HistoryElem> history = m_dolphinView->urlHistory(index);
131 if (!history.isEmpty()) {
132 KFileView* fileView = static_cast<KFileView*>(this);
133 fileView->setCurrentItem(history[index].currentFileName());
134 setContentsPos(history[index].contentsX(), history[index].contentsY());
135 }
136
137 updateColumnsWidth();
138 }
139
140 void DolphinDetailsView::insertItem(KFileItem* fileItem)
141 {
142 KFileView::insertItem(fileItem);
143
144 DolphinListViewItem* item = new DolphinListViewItem(static_cast<Q3ListView*>(this), fileItem);
145
146 QDir::SortFlags spec = KFileView::sorting();
147 if (spec & QDir::Time) {
148 item->setKey(sortingKey(fileItem->time(KIO::UDS_MODIFICATION_TIME),
149 fileItem->isDir(),
150 spec));
151 }
152 else if (spec & QDir::Size) {
153 item->setKey(sortingKey(fileItem->size(), fileItem->isDir(), spec));
154 }
155 else {
156 item->setKey(sortingKey(fileItem->text(), fileItem->isDir(), spec));
157 }
158
159 fileItem->setExtraData(this, item);
160 }
161
162 bool DolphinDetailsView::isOnFilename(const Q3ListViewItem* item, const QPoint& pos) const
163 {
164 const QPoint absPos(mapToGlobal(QPoint(0, 0)));
165 return (pos.x() - absPos.x()) <= filenameWidth(item);
166 }
167
168 void DolphinDetailsView::refreshSettings()
169 {
170 const DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
171 assert(settings != 0);
172
173 if (!settings->showGroup()) {
174 removeColumn(GroupColumn);
175 }
176 if (!settings->showOwner()) {
177 removeColumn(OwnerColumn);
178 }
179 if (!settings->showPermissions()) {
180 removeColumn(PermissionsColumn);
181 }
182 if (!settings->showDate()) {
183 removeColumn(DateColumn);
184 }
185
186 QFont adjustedFont(font());
187 adjustedFont.setFamily(settings->fontFamily());
188 adjustedFont.setPointSize(settings->fontSize());
189 setFont(adjustedFont);
190
191 updateView(true);
192 }
193
194 void DolphinDetailsView::zoomIn()
195 {
196 if (isZoomInPossible()) {
197 DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
198 switch (settings->iconSize()) {
199 case K3Icon::SizeSmall: settings->setIconSize(K3Icon::SizeMedium); break;
200 case K3Icon::SizeMedium: settings->setIconSize(K3Icon::SizeLarge); break;
201 default: assert(false); break;
202 }
203 ItemEffectsManager::zoomIn();
204 }
205 }
206
207 void DolphinDetailsView::zoomOut()
208 {
209 if (isZoomOutPossible()) {
210 DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
211 switch (settings->iconSize()) {
212 case K3Icon::SizeLarge: settings->setIconSize(K3Icon::SizeMedium); break;
213 case K3Icon::SizeMedium: settings->setIconSize(K3Icon::SizeSmall); break;
214 default: assert(false); break;
215 }
216 ItemEffectsManager::zoomOut();
217 }
218 }
219
220 bool DolphinDetailsView::isZoomInPossible() const
221 {
222 DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
223 return settings->iconSize() < K3Icon::SizeLarge;
224 }
225
226 bool DolphinDetailsView::isZoomOutPossible() const
227 {
228 DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
229 return settings->iconSize() > K3Icon::SizeSmall;
230 }
231
232 void DolphinDetailsView::resizeContents(int width, int height)
233 {
234 KFileDetailView::resizeContents(width, height);
235
236 // When loading several 1000 items a punch of resize events
237 // drops in. As updating the column width is a quite expensive
238 // operation, this operation will be postponed until there is
239 // no resize event for at least 50 milliseconds.
240 m_resizeTimer->stop();
241 m_resizeTimer->start(50, true);
242 }
243
244 void DolphinDetailsView::slotOnItem(Q3ListViewItem* item)
245 {
246 if (isOnFilename(item, QCursor::pos())) {
247 activateItem(item);
248 KFileItem* fileItem = static_cast<KFileListViewItem*>(item)->fileInfo();
249 m_dolphinView->requestItemInfo(fileItem->url());
250 }
251 else {
252 resetActivatedItem();
253 }
254 }
255
256 void DolphinDetailsView::slotOnViewport()
257 {
258 resetActivatedItem();
259 m_dolphinView->requestItemInfo(KUrl());
260 }
261
262 void DolphinDetailsView::setContextPixmap(void* context,
263 const QPixmap& pixmap)
264 {
265 reinterpret_cast<KFileListViewItem*>(context)->setPixmap(0, pixmap);
266 }
267
268 const QPixmap* DolphinDetailsView::contextPixmap(void* context)
269 {
270 return reinterpret_cast<KFileListViewItem*>(context)->pixmap(0);
271 }
272
273 void* DolphinDetailsView::firstContext()
274 {
275 return reinterpret_cast<void*>(firstChild());
276 }
277
278 void* DolphinDetailsView::nextContext(void* context)
279 {
280 KFileListViewItem* listViewItem = reinterpret_cast<KFileListViewItem*>(context);
281 return reinterpret_cast<void*>(listViewItem->nextSibling());
282 }
283
284 KFileItem* DolphinDetailsView::contextFileInfo(void* context)
285 {
286 return reinterpret_cast<KFileListViewItem*>(context)->fileInfo();
287 }
288
289
290 void DolphinDetailsView::contentsDragMoveEvent(QDragMoveEvent* event)
291 {
292 KFileDetailView::contentsDragMoveEvent(event);
293
294 // If a dragging is done above a directory, show the icon as 'active' for
295 // a visual feedback
296 KFileListViewItem* item = static_cast<KFileListViewItem*>(itemAt(event->pos()));
297
298 bool showActive = false;
299 if (item != 0) {
300 const KFileItem* fileInfo = item->fileInfo();
301 showActive = (fileInfo != 0) && fileInfo->isDir();
302 }
303
304 if (showActive) {
305 slotOnItem(item);
306 }
307 else {
308 slotOnViewport();
309 }
310 }
311
312 void DolphinDetailsView::resizeEvent(QResizeEvent* event)
313 {
314 KFileDetailView::resizeEvent(event);
315
316 // When loading several 1000 items a punch of resize events
317 // drops in. As updating the column width is a quite expensive
318 // operation, this operation will be postponed until there is
319 // no resize event for at least 50 milliseconds.
320 m_resizeTimer->stop();
321 m_resizeTimer->start(50, true);
322 }
323
324 bool DolphinDetailsView::acceptDrag(QDropEvent* event) const
325 {
326 KUrl::List uriList = KUrl::List::fromMimeData( event->mimeData() );
327 bool accept = !uriList.isEmpty() &&
328 (event->action() == QDropEvent::Copy ||
329 event->action() == QDropEvent::Move ||
330 event->action() == QDropEvent::Link);
331 if (accept) {
332 if (static_cast<const QWidget*>(event->source()) == this) {
333 KFileListViewItem* item = static_cast<KFileListViewItem*>(itemAt(event->pos()));
334 accept = (item != 0);
335 if (accept) {
336 KFileItem* fileItem = item->fileInfo();
337 accept = fileItem->isDir();
338 }
339 }
340 }
341
342 return accept;
343 }
344
345 void DolphinDetailsView::contentsDropEvent(QDropEvent* event)
346 {
347 // KFileDetailView::contentsDropEvent does not care whether the mouse
348 // cursor is above a filename or not, the destination URL is always
349 // the URL of the item. This is fixed here in a way that the destination
350 // URL is only the URL of the item if the cursor is above the filename.
351 const QPoint pos(QCursor::pos());
352 const QPoint viewportPos(viewport()->mapToGlobal(QPoint(0, 0)));
353 Q3ListViewItem* item = itemAt(QPoint(pos.x() - viewportPos.x(), pos.y() - viewportPos.y()));
354 if ((item == 0) || ((item != 0) && isOnFilename(item, pos))) {
355 // dropping is done on the viewport or directly above a filename
356 KFileDetailView::contentsDropEvent(event);
357 return;
358 }
359
360 // Dropping is done above an item, but the mouse cursor is not above the file name.
361 // In this case the signals of the base implementation will be blocked and send
362 // in a corrected manner afterwards.
363 assert(item != 0);
364 const bool block = signalsBlocked();
365 blockSignals(true);
366 KFileDetailView::contentsDropEvent(event);
367 blockSignals(block);
368
369 if (!acceptDrag(event)) {
370 return;
371 }
372
373 emit dropped(event, 0);
374 KUrl::List urls = KUrl::List::fromMimeData( event->mimeData() );
375 if (!urls.isEmpty()) {
376 emit dropped(event, urls, KUrl());
377 sig->dropURLs(0, event, urls);
378 }
379 }
380
381 void DolphinDetailsView::contentsMousePressEvent(QMouseEvent* event)
382 {
383 if (m_rubber != 0) {
384 drawRubber();
385 delete m_rubber;
386 m_rubber = 0;
387 }
388
389 // Swallow the base implementation of the mouse press event
390 // if the mouse cursor is not above the filename. This prevents
391 // that the item gets selected and simulates an equal usability
392 // like in the icon view.
393 const QPoint pos(QCursor::pos());
394 const QPoint viewportPos(viewport()->mapToGlobal(QPoint(0, 0)));
395 Q3ListViewItem* item = itemAt(QPoint(pos.x() - viewportPos.x(), pos.y() - viewportPos.y()));
396 if ((item != 0) && isOnFilename(item, pos)) {
397 KFileDetailView::contentsMousePressEvent(event);
398 }
399 else if (event->button() == Qt::LeftButton) {
400 const Qt::KeyboardModifiers keyboardState = QApplication::keyboardModifiers();
401 const bool isSelectionActive = (keyboardState & Qt::ShiftModifier) ||
402 (keyboardState & Qt::ControlModifier);
403 if (!isSelectionActive) {
404 clearSelection();
405 }
406
407 assert(m_rubber == 0);
408 m_rubber = new QRect(event->x(), event->y(), 0, 0);
409 }
410
411 resetActivatedItem();
412 emit signalRequestActivation();
413
414 m_dolphinView->statusBar()->clear();
415 }
416
417 void DolphinDetailsView::contentsMouseMoveEvent(QMouseEvent* event)
418 {
419 if (m_rubber != 0) {
420 slotAutoScroll();
421 return;
422 }
423
424 KFileDetailView::contentsMouseMoveEvent(event);
425
426 const QPoint& pos = event->globalPos();
427 const QPoint viewportPos = viewport()->mapToGlobal(QPoint(0, 0));
428 Q3ListViewItem* item = itemAt(QPoint(pos.x() - viewportPos.x(), pos.y() - viewportPos.y()));
429 if ((item != 0) && isOnFilename(item, pos)) {
430 activateItem(item);
431 }
432 else {
433 resetActivatedItem();
434 }
435 }
436
437 void DolphinDetailsView::contentsMouseReleaseEvent(QMouseEvent* event)
438 {
439 if (m_rubber != 0) {
440 drawRubber();
441 delete m_rubber;
442 m_rubber = 0;
443 }
444
445 if (m_scrollTimer != 0) {
446 disconnect(m_scrollTimer, SIGNAL(timeout()),
447 this, SLOT(slotAutoScroll()));
448 m_scrollTimer->stop();
449 delete m_scrollTimer;
450 m_scrollTimer = 0;
451 }
452
453 KFileDetailView::contentsMouseReleaseEvent(event);
454 }
455
456 void DolphinDetailsView::paintEmptyArea(QPainter* painter, const QRect& rect)
457 {
458 if (m_dolphinView->isActive()) {
459 KFileDetailView::paintEmptyArea(painter, rect);
460 }
461 else {
462 const QBrush brush(colorGroup().background());
463 painter->fillRect(rect, brush);
464 }
465 }
466
467 void DolphinDetailsView::drawRubber()
468 {
469 // Parts of the following code have been taken
470 // from the class KonqBaseListViewWidget located in
471 // konqueror/listview/konq_listviewwidget.h of Konqueror.
472 // (Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
473 // 2001, 2002, 2004 Michael Brade <brade@kde.org>)
474 if (m_rubber == 0) {
475 return;
476 }
477
478 QPainter p;
479 p.begin(viewport());
480 //p.setRasterOp(NotROP);
481 p.setPen(QPen(Qt::color0, 1));
482 p.setBrush(Qt::NoBrush);
483
484 QPoint point(m_rubber->x(), m_rubber->y());
485 point = contentsToViewport(point);
486 QStyleOptionFocusRect option;
487 option.initFrom(this);
488 option.rect = QRect(point.x(), point.y(), m_rubber->width(), m_rubber->height());
489 style()->drawPrimitive(QStyle::PE_FrameFocusRect, &option, &p);
490 p.end();
491 }
492
493 void DolphinDetailsView::viewportPaintEvent(QPaintEvent* paintEvent)
494 {
495 drawRubber();
496 KFileDetailView::viewportPaintEvent(paintEvent);
497 drawRubber();
498 }
499
500 void DolphinDetailsView::leaveEvent(QEvent* event)
501 {
502 KFileDetailView::leaveEvent(event);
503 slotOnViewport();
504 }
505
506 void DolphinDetailsView::slotActivationUpdate()
507 {
508 update();
509
510 // TODO: there must be a simpler way to say
511 // "update all children"
512 const QList<QObject*> list = children();
513 if (list.isEmpty()) {
514 return;
515 }
516
517 QListIterator<QObject*> it(list);
518 QObject* object = 0;
519 while (it.hasNext()) {
520 object = it.next();
521 if (object->inherits("QWidget")) {
522 QWidget* widget = static_cast<QWidget*>(object);
523 widget->update();
524 }
525 }
526 }
527
528 void DolphinDetailsView::slotContextMenuRequested(Q3ListViewItem* item,
529 const QPoint& pos,
530 int /* col */)
531 {
532 KFileItem* fileInfo = 0;
533 if ((item != 0) && isOnFilename(item, pos)) {
534 fileInfo = static_cast<KFileListViewItem*>(item)->fileInfo();
535 }
536 m_dolphinView->openContextMenu(fileInfo, pos);
537
538 }
539
540 void DolphinDetailsView::slotUpdateDisabledItems()
541 {
542 updateDisabledItems();
543 }
544
545 void DolphinDetailsView::slotAutoScroll()
546 {
547 // Parts of the following code have been taken
548 // from the class KonqBaseListViewWidget located in
549 // konqueror/listview/konq_listviewwidget.h of Konqueror.
550 // (Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
551 // 2001, 2002, 2004 Michael Brade <brade@kde.org>)
552
553 const QPoint pos(viewport()->mapFromGlobal(QCursor::pos()));
554 const QPoint vc(viewportToContents(pos));
555
556 if (vc == m_rubber->bottomRight()) {
557 return;
558 }
559
560 drawRubber();
561
562 m_rubber->setBottomRight(vc);
563
564 Q3ListViewItem* item = itemAt(QPoint(0,0));
565
566 const bool block = signalsBlocked();
567 blockSignals(true);
568
569 const QRect rubber(m_rubber->normalize());
570 const int bottom = contentsY() + visibleHeight() - 1;
571
572 // select all items which intersect with the rubber, deselect all others
573 bool bottomReached = false;
574 while ((item != 0) && !bottomReached) {
575 QRect rect(itemRect(item));
576 rect.setWidth(filenameWidth(item));
577 rect = QRect(viewportToContents(rect.topLeft()),
578 viewportToContents(rect.bottomRight()));
579 if (rect.isValid() && (rect.top() <= bottom)) {
580 const KFileItem* fileItem = static_cast<KFileListViewItem*>(item)->fileInfo();
581 setSelected(fileItem, rect.intersects(rubber));
582 item = item->itemBelow();
583 }
584 else {
585 bottomReached = true;
586 }
587 }
588
589 blockSignals(block);
590 emit selectionChanged();
591
592 drawRubber();
593
594 // scroll the viewport if the top or bottom margin is reached
595 const int scrollMargin = 40;
596 ensureVisible(vc.x(), vc.y(), scrollMargin, scrollMargin);
597 const bool scroll = !QRect(scrollMargin,
598 scrollMargin,
599 viewport()->width() - 2 * scrollMargin,
600 viewport()->height() - 2 * scrollMargin).contains(pos);
601 if (scroll) {
602 if (m_scrollTimer == 0) {
603 m_scrollTimer = new QTimer( this );
604 connect(m_scrollTimer, SIGNAL(timeout()),
605 this, SLOT(slotAutoScroll()));
606 m_scrollTimer->start(100, false);
607 }
608 }
609 else if (m_scrollTimer != 0) {
610 disconnect(m_scrollTimer, SIGNAL(timeout()),
611 this, SLOT(slotAutoScroll()));
612 m_scrollTimer->stop();
613 delete m_scrollTimer;
614 m_scrollTimer = 0;
615 }
616 }
617
618 void DolphinDetailsView::updateColumnsWidth()
619 {
620 const int columnCount = columns();
621 int requiredWidth = 0;
622 for (int i = 1; i < columnCount; ++i) {
623 // When a directory contains no items, a minimum width for
624 // the column must be available, so that the header is readable.
625 // TODO: use header data instead of the hardcoded 64 value...
626 int columnWidth = 64;
627 QFontMetrics fontMetrics(font());
628 for (Q3ListViewItem* item = firstChild(); item != 0; item = item->nextSibling()) {
629 const int width = item->width(fontMetrics, this, i);
630 if (width > columnWidth) {
631 columnWidth = width;
632 }
633 }
634 columnWidth += 16; // add custom margin
635 setColumnWidth(i, columnWidth);
636 requiredWidth += columnWidth;
637 }
638
639 // resize the first column in a way that the
640 // whole available width is used
641 int firstColumnWidth = visibleWidth() - requiredWidth;
642 if (firstColumnWidth < 128) {
643 firstColumnWidth = 128;
644 }
645 setColumnWidth(0, firstColumnWidth);
646 }
647
648 void DolphinDetailsView::slotItemRenamed(Q3ListViewItem* item,
649 const QString& name,
650 int /* column */)
651 {
652 KFileItem* fileInfo = static_cast<KFileListViewItem*>(item)->fileInfo();
653 m_dolphinView->rename(KUrl(fileInfo->url()), name);
654 }
655
656 void DolphinDetailsView::slotHeaderClicked(int /* section */)
657 {
658 // The sorting has already been changed in QListView if this slot is
659 // invoked, but Dolphin was not informed about this (no signal is available
660 // which indicates a change of the sorting). This is bypassed by changing
661 // the sorting and sort order to a temporary other value and readjust it again.
662 const int column = sortColumn();
663 if (column <= DateColumn) {
664 DolphinView::Sorting sorting = DolphinView::SortByName;
665 switch (column) {
666 case SizeColumn: sorting = DolphinView::SortBySize; break;
667 case DateColumn: sorting = DolphinView::SortByDate; break;
668 case NameColumn:
669 default: break;
670 }
671
672 const Qt::SortOrder currSortOrder = sortOrder();
673
674 // temporary adjust the sorting and sort order to different values...
675 const DolphinView::Sorting tempSorting = (sorting == DolphinView::SortByName) ?
676 DolphinView::SortBySize :
677 DolphinView::SortByName;
678 m_dolphinView->setSorting(tempSorting);
679 const Qt::SortOrder tempSortOrder = (currSortOrder == Qt::Ascending) ?
680 Qt::Descending : Qt::Ascending;
681 m_dolphinView->setSortOrder(tempSortOrder);
682
683 // ... so that setting them again results in storing the new setting.
684 m_dolphinView->setSorting(sorting);
685 m_dolphinView->setSortOrder(currSortOrder);
686 }
687 }
688
689 DolphinDetailsView::DolphinListViewItem::DolphinListViewItem(Q3ListView* parent,
690 KFileItem* fileItem) :
691 KFileListViewItem(parent, fileItem)
692 {
693 const int iconSize = DolphinSettings::instance().detailsModeSettings()->iconSize();
694 KFileItem* info = fileInfo();
695 setPixmap(DolphinDetailsView::NameColumn, info->pixmap(iconSize));
696
697 // The base class KFileListViewItem represents the column 'Size' only as byte values.
698 // Adjust those values in a way that a mapping to GBytes, MBytes, KBytes and Bytes
699 // is done. As the file size for directories is useless (only the size of the directory i-node
700 // is given), it is removed completely.
701 if (fileItem->isDir()) {
702 setText(SizeColumn, " - ");
703 }
704 else {
705 QString sizeText(KIO::convertSize(fileItem->size()));
706 sizeText.append(" ");
707 setText(SizeColumn, sizeText);
708 }
709
710 // Dolphin allows to remove specific columns, but the base class KFileListViewItem
711 // is not aware about this (or at least the class KFileDetailView does not react on
712 // QListView::remove()). Therefore the columns are rearranged here.
713 const DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
714 assert(settings != 0);
715
716 int column_idx = DateColumn; // the columns for 'name' and 'size' cannot get removed
717 for (int i = DolphinDetailsView::DateColumn; i <= DolphinDetailsView::GroupColumn; ++i) {
718 if (column_idx < i) {
719 setText(column_idx, text(i));
720 }
721
722 bool inc = false;
723 switch (i) {
724 case DateColumn: inc = settings->showDate(); break;
725 case PermissionsColumn: inc = settings->showPermissions(); break;
726 case OwnerColumn: inc = settings->showOwner(); break;
727 case GroupColumn: inc = settings->showGroup(); break;
728 default: break;
729 }
730
731 if (inc) {
732 ++column_idx;
733 }
734 }
735 }
736
737 DolphinDetailsView::DolphinListViewItem::~DolphinListViewItem()
738 {
739 }
740
741 void DolphinDetailsView::DolphinListViewItem::paintCell(QPainter* painter,
742 const QColorGroup& colorGroup,
743 int column,
744 int cellWidth,
745 int alignment)
746 {
747 const Q3ListView* view = listView();
748 const bool isActive = view->parent() == Dolphin::mainWin().activeView();
749 if (isSelected()) {
750 // Per default the selection is drawn above the whole width of the item. As a consistent
751 // behavior with the icon view is wanted, only the the column containing the file name
752 // should be shown as selected.
753 QColorGroup defaultColorGroup(colorGroup);
754 const QColor highlightColor(isActive ? backgroundColor(column) : view->colorGroup().background());
755 defaultColorGroup.setColor(QColorGroup::Highlight , highlightColor);
756 defaultColorGroup.setColor(QColorGroup::HighlightedText, colorGroup.color(QColorGroup::Text));
757 KFileListViewItem::paintCell(painter, defaultColorGroup, column, cellWidth, alignment);
758
759 if (column == 0) {
760 // draw the selection only on the first column
761 Q3ListView* parent = listView();
762 const int itemWidth = width(parent->fontMetrics(), parent, 0);
763 if (isActive) {
764 KFileListViewItem::paintCell(painter, colorGroup, column, itemWidth, alignment);
765 }
766 else {
767 Q3ListViewItem::paintCell(painter, colorGroup, column, itemWidth, alignment);
768 }
769 }
770 }
771 else {
772 if (isActive) {
773 KFileListViewItem::paintCell(painter, colorGroup, column, cellWidth, alignment);
774 }
775 else {
776 Q3ListViewItem::paintCell(painter, colorGroup, column, cellWidth, alignment);
777 }
778 }
779
780 if (column < listView()->columns() - 1) {
781 // draw a separator between columns
782 painter->setPen(KGlobalSettings::buttonBackground());
783 painter->drawLine(cellWidth - 1, 0, cellWidth - 1, height() - 1);
784 }
785 }
786
787 void DolphinDetailsView::DolphinListViewItem::paintFocus(QPainter* painter,
788 const QColorGroup& colorGroup,
789 const QRect& rect)
790 {
791 // draw the focus consistently with the selection (see implementation notes
792 // in DolphinListViewItem::paintCell)
793 Q3ListView* parent = listView();
794 int visibleWidth = width(parent->fontMetrics(), parent, 0);
795 const int colWidth = parent->columnWidth(0);
796 if (visibleWidth > colWidth) {
797 visibleWidth = colWidth;
798 }
799
800 QRect focusRect(rect);
801 focusRect.setWidth(visibleWidth);
802
803 KFileListViewItem::paintFocus(painter, colorGroup, focusRect);
804 }
805
806 int DolphinDetailsView::filenameWidth(const Q3ListViewItem* item) const
807 {
808 assert(item != 0);
809
810 int visibleWidth = item->width(fontMetrics(), this, 0);
811 const int colWidth = columnWidth(0);
812 if (visibleWidth > colWidth) {
813 visibleWidth = colWidth;
814 }
815
816 return visibleWidth;
817 }
818 #include "dolphindetailsview.moc"