]> cloud.milkyroute.net Git - dolphin.git/blob - src/views/dolphindetailsview.cpp
d434a4b3d2ec1f0d35b6a629fe11cfdff017c3a9
[dolphin.git] / src / views / dolphindetailsview.cpp
1 /***************************************************************************
2 * Copyright (C) 2006 by Peter Penz (peter.penz@gmx.at) *
3 * Copyright (C) 2008 by Simon St. James (kdedevel@etotheipiplusone.com) *
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 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
19 ***************************************************************************/
20
21 #include "dolphindetailsview.h"
22
23 #include "additionalinfoaccessor.h"
24 #include "dolphinmodel.h"
25 #include "dolphinviewcontroller.h"
26 #include "dolphinfileitemdelegate.h"
27 #include "settings/dolphinsettings.h"
28 #include "dolphinsortfilterproxymodel.h"
29 #include "dolphinviewautoscroller.h"
30 #include "draganddrophelper.h"
31 #include "viewextensionsfactory.h"
32 #include "viewmodecontroller.h"
33 #include "viewproperties.h"
34 #include "zoomlevelinfo.h"
35
36 #include "dolphin_detailsmodesettings.h"
37 #include "dolphin_generalsettings.h"
38
39 #include <kdirmodel.h>
40 #include <kdirlister.h>
41 #include <klocale.h>
42 #include <kmenu.h>
43
44 #include <QApplication>
45 #include <QHeaderView>
46 #include <QScrollBar>
47
48 DolphinDetailsView::DolphinDetailsView(QWidget* parent,
49 DolphinViewController* dolphinViewController,
50 const ViewModeController* viewModeController,
51 DolphinSortFilterProxyModel* proxyModel) :
52 DolphinTreeView(parent),
53 m_autoResize(true),
54 m_dolphinViewController(dolphinViewController),
55 m_extensionsFactory(0),
56 m_expandableFoldersAction(0),
57 m_expandedUrls(),
58 m_font(),
59 m_decorationSize()
60 {
61 const DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
62 Q_ASSERT(settings != 0);
63 Q_ASSERT(dolphinViewController != 0);
64 Q_ASSERT(viewModeController != 0);
65
66 setLayoutDirection(Qt::LeftToRight);
67 setAcceptDrops(true);
68 setSortingEnabled(true);
69 setSelectionBehavior(SelectItems);
70 setDragDropMode(QAbstractItemView::DragDrop);
71 setDropIndicatorShown(false);
72 setAlternatingRowColors(true);
73 setRootIsDecorated(settings->expandableFolders());
74 setItemsExpandable(settings->expandableFolders());
75 setEditTriggers(QAbstractItemView::NoEditTriggers);
76 setModel(proxyModel);
77
78 setMouseTracking(true);
79
80 const ViewProperties props(viewModeController->url());
81 setSortIndicatorSection(props.sorting());
82 setSortIndicatorOrder(props.sortOrder());
83
84 QHeaderView* headerView = header();
85 connect(headerView, SIGNAL(sectionClicked(int)),
86 this, SLOT(synchronizeSortingState(int)));
87 headerView->setContextMenuPolicy(Qt::CustomContextMenu);
88 connect(headerView, SIGNAL(customContextMenuRequested(const QPoint&)),
89 this, SLOT(configureSettings(const QPoint&)));
90 connect(headerView, SIGNAL(sectionResized(int, int, int)),
91 this, SLOT(slotHeaderSectionResized(int, int, int)));
92 connect(headerView, SIGNAL(sectionHandleDoubleClicked(int)),
93 this, SLOT(disableAutoResizing()));
94
95 connect(parent, SIGNAL(sortingChanged(DolphinView::Sorting)),
96 this, SLOT(setSortIndicatorSection(DolphinView::Sorting)));
97 connect(parent, SIGNAL(sortOrderChanged(Qt::SortOrder)),
98 this, SLOT(setSortIndicatorOrder(Qt::SortOrder)));
99
100 connect(this, SIGNAL(clicked(const QModelIndex&)),
101 dolphinViewController, SLOT(requestTab(const QModelIndex&)));
102 if (KGlobalSettings::singleClick()) {
103 connect(this, SIGNAL(clicked(const QModelIndex&)),
104 dolphinViewController, SLOT(triggerItem(const QModelIndex&)));
105 } else {
106 connect(this, SIGNAL(doubleClicked(const QModelIndex&)),
107 dolphinViewController, SLOT(triggerItem(const QModelIndex&)));
108 }
109
110 connect(this, SIGNAL(entered(const QModelIndex&)),
111 this, SLOT(slotEntered(const QModelIndex&)));
112 connect(this, SIGNAL(viewportEntered()),
113 dolphinViewController, SLOT(emitViewportEntered()));
114 connect(viewModeController, SIGNAL(zoomLevelChanged(int)),
115 this, SLOT(setZoomLevel(int)));
116 connect(dolphinViewController->view(), SIGNAL(additionalInfoChanged()),
117 this, SLOT(updateColumnVisibility()));
118 connect(viewModeController, SIGNAL(activationChanged(bool)),
119 this, SLOT(slotActivationChanged(bool)));
120
121 if (settings->useSystemFont()) {
122 m_font = KGlobalSettings::generalFont();
123 } else {
124 m_font = QFont(settings->fontFamily(),
125 qRound(settings->fontSize()),
126 settings->fontWeight(),
127 settings->italicFont());
128 m_font.setPointSizeF(settings->fontSize());
129 }
130
131 setVerticalScrollMode(QTreeView::ScrollPerPixel);
132 setHorizontalScrollMode(QTreeView::ScrollPerPixel);
133
134 const DolphinView* view = dolphinViewController->view();
135 connect(view, SIGNAL(showPreviewChanged()),
136 this, SLOT(slotShowPreviewChanged()));
137
138
139 viewport()->installEventFilter(this);
140
141 connect(KGlobalSettings::self(), SIGNAL(settingsChanged(int)),
142 this, SLOT(slotGlobalSettingsChanged(int)));
143
144 m_expandableFoldersAction = new QAction(i18nc("@option:check", "Expandable Folders"), this);
145 m_expandableFoldersAction->setCheckable(true);
146 connect(m_expandableFoldersAction, SIGNAL(toggled(bool)),
147 this, SLOT(setFoldersExpandable(bool)));
148
149 connect(this, SIGNAL(expanded(const QModelIndex&)), this, SLOT(slotExpanded(const QModelIndex&)));
150 connect(this, SIGNAL(collapsed(const QModelIndex&)), this, SLOT(slotCollapsed(const QModelIndex&)));
151
152 updateDecorationSize(view->showPreview());
153
154 m_extensionsFactory = new ViewExtensionsFactory(this, dolphinViewController, viewModeController);
155 m_extensionsFactory->fileItemDelegate()->setMinimizedNameColumn(true);
156
157 KDirLister *dirLister = qobject_cast<KDirModel*>(proxyModel->sourceModel())->dirLister();
158 connect(dirLister, SIGNAL(newItems(KFileItemList)), this, SLOT(resizeColumns()));
159 }
160
161 DolphinDetailsView::~DolphinDetailsView()
162 {
163 }
164
165 QSet<KUrl> DolphinDetailsView::expandedUrls() const
166 {
167 return m_expandedUrls;
168 }
169
170 bool DolphinDetailsView::event(QEvent* event)
171 {
172 if (event->type() == QEvent::Polish) {
173 header()->setResizeMode(QHeaderView::Interactive);
174 updateColumnVisibility();
175 }
176
177 return DolphinTreeView::event(event);
178 }
179
180 QStyleOptionViewItem DolphinDetailsView::viewOptions() const
181 {
182 QStyleOptionViewItem viewOptions = DolphinTreeView::viewOptions();
183 viewOptions.font = m_font;
184 viewOptions.fontMetrics = QFontMetrics(m_font);
185 viewOptions.showDecorationSelected = true;
186 viewOptions.decorationSize = m_decorationSize;
187 return viewOptions;
188 }
189
190 void DolphinDetailsView::contextMenuEvent(QContextMenuEvent* event)
191 {
192 DolphinTreeView::contextMenuEvent(event);
193
194 DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
195 m_expandableFoldersAction->setChecked(settings->expandableFolders());
196 m_dolphinViewController->triggerContextMenuRequest(event->pos(),
197 QList<QAction*>() << m_expandableFoldersAction);
198 }
199
200 void DolphinDetailsView::mousePressEvent(QMouseEvent* event)
201 {
202 m_dolphinViewController->requestActivation();
203
204 DolphinTreeView::mousePressEvent(event);
205
206 const QModelIndex index = indexAt(event->pos());
207 if (!index.isValid() || (index.column() != DolphinModel::Name)) {
208 // The mouse press is done somewhere outside the filename column
209 if (QApplication::mouseButtons() & Qt::MidButton) {
210 m_dolphinViewController->replaceUrlByClipboard();
211 }
212 }
213 }
214
215 void DolphinDetailsView::startDrag(Qt::DropActions supportedActions)
216 {
217 DragAndDropHelper::instance().startDrag(this, supportedActions, m_dolphinViewController);
218 DolphinTreeView::startDrag(supportedActions);
219 }
220
221 void DolphinDetailsView::dragEnterEvent(QDragEnterEvent* event)
222 {
223 event->acceptProposedAction();
224 DolphinTreeView::dragEnterEvent(event);
225 }
226
227 void DolphinDetailsView::dragMoveEvent(QDragMoveEvent* event)
228 {
229 DolphinTreeView::dragMoveEvent(event);
230 event->acceptProposedAction();
231 }
232
233 void DolphinDetailsView::dropEvent(QDropEvent* event)
234 {
235 const QModelIndex index = indexAt(event->pos());
236 KFileItem item;
237 if (index.isValid() && (index.column() == DolphinModel::Name)) {
238 item = m_dolphinViewController->itemForIndex(index);
239 }
240 m_dolphinViewController->indicateDroppedUrls(item, event);
241 DolphinTreeView::dropEvent(event);
242 }
243
244 void DolphinDetailsView::keyPressEvent(QKeyEvent* event)
245 {
246 DolphinTreeView::keyPressEvent(event);
247 m_dolphinViewController->handleKeyPressEvent(event);
248 }
249
250 void DolphinDetailsView::resizeEvent(QResizeEvent* event)
251 {
252 DolphinTreeView::resizeEvent(event);
253 if (m_autoResize) {
254 resizeColumns();
255 }
256 }
257
258 void DolphinDetailsView::wheelEvent(QWheelEvent* event)
259 {
260 const int step = m_decorationSize.height();
261 verticalScrollBar()->setSingleStep(step);
262 DolphinTreeView::wheelEvent(event);
263 }
264
265 void DolphinDetailsView::currentChanged(const QModelIndex& current, const QModelIndex& previous)
266 {
267 m_extensionsFactory->handleCurrentIndexChange(current, previous);
268 DolphinTreeView::currentChanged(current, previous);
269
270 // If folders are expanded, the width which is available for editing may have changed
271 // because it depends on the level of the current item in the folder hierarchy.
272 adjustMaximumSizeForEditing(current);
273 }
274
275 bool DolphinDetailsView::eventFilter(QObject* watched, QEvent* event)
276 {
277 if ((watched == viewport()) && (event->type() == QEvent::Leave)) {
278 // If the mouse is above an item and moved very fast outside the widget,
279 // no viewportEntered() signal might be emitted although the mouse has been moved
280 // above the viewport.
281 m_dolphinViewController->emitViewportEntered();
282 }
283
284 return DolphinTreeView::eventFilter(watched, event);
285 }
286
287 QRect DolphinDetailsView::visualRect(const QModelIndex& index) const
288 {
289 QRect rect = DolphinTreeView::visualRect(index);
290 const KFileItem item = m_dolphinViewController->itemForIndex(index);
291 if (!item.isNull()) {
292 const int width = DolphinFileItemDelegate::nameColumnWidth(item.text(), viewOptions());
293
294 if (width < rect.width()) {
295 rect.setWidth(width);
296 }
297 }
298
299 return rect;
300 }
301
302 bool DolphinDetailsView::acceptsDrop(const QModelIndex& index) const
303 {
304 if (index.isValid() && (index.column() == DolphinModel::Name)) {
305 // Accept drops above directories
306 const KFileItem item = m_dolphinViewController->itemForIndex(index);
307 return !item.isNull() && item.isDir();
308 }
309
310 return false;
311 }
312
313 void DolphinDetailsView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
314 {
315 removeExpandedIndexes(parent, start, end);
316 DolphinTreeView::rowsAboutToBeRemoved(parent, start, end);
317 }
318
319 void DolphinDetailsView::setSortIndicatorSection(DolphinView::Sorting sorting)
320 {
321 header()->setSortIndicator(sorting, header()->sortIndicatorOrder());
322 }
323
324 void DolphinDetailsView::setSortIndicatorOrder(Qt::SortOrder sortOrder)
325 {
326 header()->setSortIndicator(header()->sortIndicatorSection(), sortOrder);
327 }
328
329 void DolphinDetailsView::synchronizeSortingState(int column)
330 {
331 // The sorting has already been changed in QTreeView if this slot is
332 // invoked, but Dolphin is not informed about this.
333 DolphinView::Sorting sorting = DolphinSortFilterProxyModel::sortingForColumn(column);
334 const Qt::SortOrder sortOrder = header()->sortIndicatorOrder();
335 m_dolphinViewController->indicateSortingChange(sorting);
336 m_dolphinViewController->indicateSortOrderChange(sortOrder);
337 }
338
339 void DolphinDetailsView::slotEntered(const QModelIndex& index)
340 {
341 if (index.column() == DolphinModel::Name) {
342 m_dolphinViewController->emitItemEntered(index);
343 } else {
344 m_dolphinViewController->emitViewportEntered();
345 }
346 }
347
348 void DolphinDetailsView::setZoomLevel(int level)
349 {
350 const int size = ZoomLevelInfo::iconSizeForZoomLevel(level);
351 DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
352
353 const bool showPreview = m_dolphinViewController->view()->showPreview();
354 if (showPreview) {
355 settings->setPreviewSize(size);
356 } else {
357 settings->setIconSize(size);
358 }
359
360 updateDecorationSize(showPreview);
361 }
362
363 void DolphinDetailsView::slotShowPreviewChanged()
364 {
365 const DolphinView* view = m_dolphinViewController->view();
366 updateDecorationSize(view->showPreview());
367 }
368
369 void DolphinDetailsView::configureSettings(const QPoint& pos)
370 {
371 KMenu popup(this);
372 popup.addTitle(i18nc("@title:menu", "Columns"));
373
374 // Add checkbox items for each column
375 QHeaderView* headerView = header();
376 const int columns = model()->columnCount();
377 for (int i = 0; i < columns; ++i) {
378 const int logicalIndex = headerView->logicalIndex(i);
379 const QString text = model()->headerData(logicalIndex, Qt::Horizontal).toString();
380 if (!text.isEmpty()) {
381 QAction* action = popup.addAction(text);
382 action->setCheckable(true);
383 action->setChecked(!headerView->isSectionHidden(logicalIndex));
384 action->setData(logicalIndex);
385 action->setEnabled(logicalIndex != DolphinModel::Name);
386 }
387 }
388 popup.addSeparator();
389
390 QAction* activatedAction = popup.exec(header()->mapToGlobal(pos));
391 if (activatedAction != 0) {
392 const bool show = activatedAction->isChecked();
393 const int columnIndex = activatedAction->data().toInt();
394
395 KFileItemDelegate::InformationList list = m_dolphinViewController->view()->additionalInfo();
396 const KFileItemDelegate::Information info = infoForColumn(columnIndex);
397 if (show) {
398 Q_ASSERT(!list.contains(info));
399 list.append(info);
400 } else {
401 Q_ASSERT(list.contains(info));
402 const int index = list.indexOf(info);
403 list.removeAt(index);
404 }
405
406 m_dolphinViewController->indicateAdditionalInfoChange(list);
407 setColumnHidden(columnIndex, !show);
408 resizeColumns();
409 }
410 }
411
412 void DolphinDetailsView::updateColumnVisibility()
413 {
414 QHeaderView* headerView = header();
415 disconnect(headerView, SIGNAL(sectionMoved(int, int, int)),
416 this, SLOT(saveColumnPositions()));
417
418 const DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
419 const QList<int> columnPositions = settings->columnPositions();
420
421 const KFileItemDelegate::InformationList list = m_dolphinViewController->view()->additionalInfo();
422 for (int i = DolphinModel::Name; i < DolphinModel::ExtraColumnCount; ++i) {
423 const KFileItemDelegate::Information info = infoForColumn(i);
424 const bool hide = !list.contains(info) && (i != DolphinModel::Name);
425 if (isColumnHidden(i) != hide) {
426 setColumnHidden(i, hide);
427 }
428
429 // If the list columnPositions has been written by an older Dolphin version,
430 // its length might be smaller than DolphinModel::ExtraColumnCount. Therefore,
431 // we have to check if item number i exists before accessing it.
432 if (i < columnPositions.length()) {
433 const int position = columnPositions[i];
434
435 // The position might be outside the correct range if the list columnPositions
436 // has been written by a newer Dolphin version with more columns.
437 if (position < DolphinModel::ExtraColumnCount) {
438 const int from = headerView->visualIndex(i);
439 headerView->moveSection(from, position);
440 }
441 }
442 }
443
444 resizeColumns();
445
446 connect(headerView, SIGNAL(sectionMoved(int, int, int)),
447 this, SLOT(saveColumnPositions()));
448 }
449
450 void DolphinDetailsView::resizeColumns()
451 {
452 // Using the resize mode QHeaderView::ResizeToContents is too slow (it takes
453 // around 3 seconds for each (!) resize operation when having > 10000 items).
454 // This gets a problem especially when opening large directories, where several
455 // resize operations are received for showing the currently available items during
456 // loading (the application hangs around 20 seconds when loading > 10000 items).
457
458 QHeaderView* headerView = header();
459 const int rowCount = model()->rowCount();
460 QFontMetrics fontMetrics(viewport()->font());
461
462 // Define the maximum number of rows, where an exact (but expensive) calculation
463 // of the widths is done.
464 const int maxRowCount = 200;
465
466 // Calculate the required with for each column and store it in columnWidth[]
467 int columnWidth[DolphinModel::ExtraColumnCount];
468
469 for (int column = 0; column < DolphinModel::ExtraColumnCount; ++column) {
470 columnWidth[column] = 0;
471 if (!isColumnHidden(column)) {
472 // Calculate the required width for the current column and consider only
473 // up to maxRowCount columns for performance reasons
474 if (rowCount > 0) {
475 const QAbstractProxyModel* proxyModel = qobject_cast<const QAbstractProxyModel*>(model());
476 const KDirModel* dirModel = qobject_cast<const KDirModel*>(proxyModel->sourceModel());
477
478 const int count = qMin(rowCount, maxRowCount);
479 const QStyleOptionViewItem option = viewOptions();
480 for (int row = 0; row < count; ++row) {
481 const QModelIndex index = dirModel->index(row, column);
482 const int width = itemDelegate()->sizeHint(option, index).width();
483 if (width > columnWidth[column]) {
484 columnWidth[column] = width;
485 }
486 }
487 }
488
489 // Assure that the required width is sufficient for the header too
490 const int logicalIndex = headerView->logicalIndex(column);
491 const QString headline = model()->headerData(logicalIndex, Qt::Horizontal).toString();
492 // TODO: check Qt-sources which left/right-gap is used for the headlines
493 const int headlineWidth = fontMetrics.width(headline) + 20;
494
495 columnWidth[column] = qMax(columnWidth[column], headlineWidth);
496 }
497 }
498
499 // Resize all columns except of the name column
500 int requiredWidth = 0;
501 for (int column = KDirModel::Size; column < DolphinModel::ExtraColumnCount; ++column) {
502 if (!isColumnHidden(column)) {
503 requiredWidth += columnWidth[column];
504 headerView->resizeSection(column, columnWidth[column]);
505 }
506 }
507
508 // Resize the name column in a way that the whole available width is used
509 columnWidth[KDirModel::Name] = viewport()->width() - requiredWidth;
510
511 const int minNameWidth = 300;
512 if (columnWidth[KDirModel::Name] < minNameWidth) {
513 columnWidth[KDirModel::Name] = minNameWidth;
514
515 if ((rowCount > 0) && (rowCount < maxRowCount)) {
516 // Try to decrease the name column width without clipping any text
517 const int nameWidth = sizeHintForColumn(DolphinModel::Name);
518 if (nameWidth + requiredWidth <= viewport()->width()) {
519 columnWidth[KDirModel::Name] = viewport()->width() - requiredWidth;
520 } else if (nameWidth < minNameWidth) {
521 columnWidth[KDirModel::Name] = nameWidth;
522 }
523 }
524 }
525
526 headerView->resizeSection(KDirModel::Name, columnWidth[KDirModel::Name]);
527 }
528
529 void DolphinDetailsView::saveColumnPositions()
530 {
531 QList<int> columnPositions;
532 for (int i = DolphinModel::Name; i < DolphinModel::ExtraColumnCount; ++i) {
533 columnPositions.append(header()->visualIndex(i));
534 }
535
536 DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
537 settings->setColumnPositions(columnPositions);
538 }
539
540 void DolphinDetailsView::slotHeaderSectionResized(int logicalIndex, int oldSize, int newSize)
541 {
542 Q_UNUSED(logicalIndex);
543 Q_UNUSED(oldSize);
544 Q_UNUSED(newSize);
545 // If the user changes the size of the headers, the autoresize feature should be
546 // turned off. As there is no dedicated interface to find out whether the header
547 // section has been resized by the user or by a resize event, another approach is used.
548 // Attention: Take care when changing the if-condition to verify that there is no
549 // regression in combination with bug 178630 (see fix in comment #8).
550 if ((QApplication::mouseButtons() & Qt::LeftButton) && header()->underMouse()) {
551 disableAutoResizing();
552 }
553
554 adjustMaximumSizeForEditing(currentIndex());
555 }
556
557 void DolphinDetailsView::slotActivationChanged(bool active)
558 {
559 setAlternatingRowColors(active);
560 }
561
562 void DolphinDetailsView::disableAutoResizing()
563 {
564 m_autoResize = false;
565 }
566
567 void DolphinDetailsView::requestActivation()
568 {
569 m_dolphinViewController->requestActivation();
570 }
571
572 void DolphinDetailsView::slotGlobalSettingsChanged(int category)
573 {
574 Q_UNUSED(category);
575
576 const DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
577 Q_ASSERT(settings != 0);
578 if (settings->useSystemFont()) {
579 m_font = KGlobalSettings::generalFont();
580 }
581 // Disconnect then reconnect, since the settings have been changed, the connection requirements may have also.
582 disconnect(this, SIGNAL(clicked(QModelIndex)), m_dolphinViewController, SLOT(triggerItem(QModelIndex)));
583 disconnect(this, SIGNAL(doubleClicked(QModelIndex)), m_dolphinViewController, SLOT(triggerItem(QModelIndex)));
584 if (KGlobalSettings::singleClick()) {
585 connect(this, SIGNAL(clicked(QModelIndex)), m_dolphinViewController, SLOT(triggerItem(QModelIndex)));
586 } else {
587 connect(this, SIGNAL(doubleClicked(QModelIndex)), m_dolphinViewController, SLOT(triggerItem(QModelIndex)));
588 }
589 }
590
591
592 void DolphinDetailsView::setFoldersExpandable(bool expandable)
593 {
594 if (!expandable) {
595 // Collapse all expanded folders, as QTreeView::setItemsExpandable(false)
596 // does not do this task
597 const int rowCount = model()->rowCount();
598 for (int row = 0; row < rowCount; ++row) {
599 setExpanded(model()->index(row, 0), false);
600 }
601 }
602 DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
603 settings->setExpandableFolders(expandable);
604 setRootIsDecorated(expandable);
605 setItemsExpandable(expandable);
606
607 // The width of the space which is available for editing has changed
608 // because of the (dis)appearance of the expanding toggles
609 adjustMaximumSizeForEditing(currentIndex());
610 }
611
612 void DolphinDetailsView::slotExpanded(const QModelIndex& index)
613 {
614 KFileItem item = m_dolphinViewController->itemForIndex(index);
615 if (!item.isNull()) {
616 m_expandedUrls.insert(item.url());
617 }
618 }
619
620 void DolphinDetailsView::slotCollapsed(const QModelIndex& index)
621 {
622 KFileItem item = m_dolphinViewController->itemForIndex(index);
623 if (!item.isNull()) {
624 m_expandedUrls.remove(item.url());
625 }
626 }
627
628 void DolphinDetailsView::removeExpandedIndexes(const QModelIndex& parent, int start, int end)
629 {
630 if (m_expandedUrls.isEmpty()) {
631 return;
632 }
633
634 for (int row = start; row <= end; row++) {
635 const QModelIndex index = model()->index(row, 0, parent);
636 if (isExpanded(index)) {
637 slotCollapsed(index);
638 removeExpandedIndexes(index, 0, model()->rowCount(index) - 1);
639 }
640 }
641 }
642
643 void DolphinDetailsView::updateDecorationSize(bool showPreview)
644 {
645 DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
646 const int iconSize = showPreview ? settings->previewSize() : settings->iconSize();
647 setIconSize(QSize(iconSize, iconSize));
648 m_decorationSize = QSize(iconSize, iconSize);
649
650 if (m_extensionsFactory) {
651 // The old maximumSize used by KFileItemDelegate is not valid any more after the icon size change.
652 // It must be discarded before doItemsLayout() is called (see bug 234600).
653 m_extensionsFactory->fileItemDelegate()->setMaximumSize(QSize());
654 }
655
656 doItemsLayout();
657
658 // Calculate the new maximumSize for KFileItemDelegate after the icon size change.
659 QModelIndex current = currentIndex();
660 if (current.isValid()) {
661 adjustMaximumSizeForEditing(current);
662 }
663 }
664
665 KFileItemDelegate::Information DolphinDetailsView::infoForColumn(int columnIndex) const
666 {
667 return AdditionalInfoAccessor::instance().keyForColumn(columnIndex);
668 }
669
670 void DolphinDetailsView::adjustMaximumSizeForEditing(const QModelIndex& index)
671 {
672 // Make sure that the full width of the "Name" column is available for "Rename Inline".
673 // Before we do that, we have to check if m_extensionsFactory has been initialised because
674 // it is possible that we end up here before the constructor is finished (see bug 257035)
675 if (m_extensionsFactory) {
676 m_extensionsFactory->fileItemDelegate()->setMaximumSize(QTreeView::visualRect(index).size());
677 }
678 }
679
680 #include "dolphindetailsview.moc"