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