~ubuntu-branches/debian/sid/kde-baseapps/sid

« back to all changes in this revision

Viewing changes to dolphin/src/views/dolphindetailsview.cpp

  • Committer: Package Import Robot
  • Author(s): Modestas Vainius, Eshat Cakar, Pino Toscano
  • Date: 2012-06-09 22:18:08 UTC
  • mfrom: (4.2.1) (6.1.1 experimental)
  • Revision ID: package-import@ubuntu.com-20120609221808-h1l0ekd5qmb8nefr
Tags: 4:4.8.4-1
* New upstream release.

[ Eshat Cakar ]
* Add watch file.
* Bump kde-sc-dev-latest build dependency to version 4:4.8.4.
* Update installed files.

[ Pino Toscano ]
* Move files of the konqueror documentation from kde-baseapps-data to
  konqueror itself.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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>
40
 
#include <KDirLister>
41
 
#include <KLocale>
42
 
#include <KMenu>
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);
63
 
    Q_ASSERT(dolphinViewController);
64
 
    Q_ASSERT(viewModeController);
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
 
    setFont(m_font);
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
 
    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) {
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(m_font);
461
 
    const int horizontalGap = 2 * (style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1) + 4; // Hardcoded values taken from Qt
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 int count = qMin(rowCount, maxRowCount);
477
 
                for (int row = 0; row < count; ++row) {
478
 
                    const QModelIndex index = model()->index(row, column);
479
 
                    QString text;
480
 
                    if (column == DolphinModel::Size) {
481
 
                        // This is a workaround as KFileItemDelegate::sizeHint() does not
482
 
                        // work in a way that is required for calculating the size.
483
 
                        const QAbstractProxyModel* proxyModel = qobject_cast<const QAbstractProxyModel*>(model());
484
 
                        const KDirModel* dirModel = qobject_cast<const KDirModel*>(proxyModel->sourceModel());
485
 
                        const QModelIndex dirIndex = proxyModel->mapToSource(index);
486
 
                        text = itemSizeString(dirIndex, dirModel->itemForIndex(dirIndex));
487
 
                    } else {
488
 
                        text = model()->data(index).toString();
489
 
                    }
490
 
                    const int width = fontMetrics.width(text) + horizontalGap;
491
 
                    if (width > columnWidth[column]) {
492
 
                        columnWidth[column] = width;
493
 
                    }
494
 
                }
495
 
            }
496
 
 
497
 
            // Assure that the required width is sufficient for the header too
498
 
            const int logicalIndex = headerView->logicalIndex(column);
499
 
            const QString headline = model()->headerData(logicalIndex, Qt::Horizontal).toString();
500
 
            const int headlineWidth = fontMetrics.width(headline) + horizontalGap;
501
 
 
502
 
            columnWidth[column] = qMax(columnWidth[column], headlineWidth);
503
 
        }
504
 
    }
505
 
 
506
 
    // Resize all columns except of the name column
507
 
    int requiredWidth = 0;
508
 
    for (int column = KDirModel::Size; column < DolphinModel::ExtraColumnCount; ++column) {
509
 
        if (!isColumnHidden(column)) {
510
 
            requiredWidth += columnWidth[column];
511
 
            headerView->resizeSection(column, columnWidth[column]);
512
 
        }
513
 
    }
514
 
 
515
 
    // Resize the name column in a way that the whole available width is used
516
 
    columnWidth[KDirModel::Name] = viewport()->width() - requiredWidth;
517
 
 
518
 
    const int minNameWidth = 300;
519
 
    if (columnWidth[KDirModel::Name] < minNameWidth) {
520
 
        columnWidth[KDirModel::Name] = minNameWidth;
521
 
 
522
 
        if ((rowCount > 0) && (rowCount < maxRowCount)) {
523
 
            // Try to decrease the name column width without clipping any text
524
 
            const int nameWidth = sizeHintForColumn(DolphinModel::Name);
525
 
            if (nameWidth + requiredWidth <= viewport()->width()) {
526
 
                columnWidth[KDirModel::Name] = viewport()->width() - requiredWidth;
527
 
            } else if (nameWidth < minNameWidth) {
528
 
                columnWidth[KDirModel::Name] = nameWidth;
529
 
            }
530
 
        }
531
 
    }
532
 
 
533
 
    headerView->resizeSection(KDirModel::Name, columnWidth[KDirModel::Name]);
534
 
}
535
 
 
536
 
void DolphinDetailsView::saveColumnPositions()
537
 
{
538
 
    QList<int> columnPositions;
539
 
    for (int i = DolphinModel::Name; i < DolphinModel::ExtraColumnCount; ++i) {
540
 
        columnPositions.append(header()->visualIndex(i));
541
 
    }
542
 
 
543
 
    DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
544
 
    settings->setColumnPositions(columnPositions);
545
 
}
546
 
 
547
 
void DolphinDetailsView::slotHeaderSectionResized(int logicalIndex, int oldSize, int newSize)
548
 
{
549
 
    Q_UNUSED(logicalIndex);
550
 
    Q_UNUSED(oldSize);
551
 
    Q_UNUSED(newSize);
552
 
    // If the user changes the size of the headers, the autoresize feature should be
553
 
    // turned off. As there is no dedicated interface to find out whether the header
554
 
    // section has been resized by the user or by a resize event, another approach is used.
555
 
    // Attention: Take care when changing the if-condition to verify that there is no
556
 
    // regression in combination with bug 178630 (see fix in comment #8).
557
 
    if ((QApplication::mouseButtons() & Qt::LeftButton) && header()->underMouse()) {
558
 
        disableAutoResizing();
559
 
    }
560
 
 
561
 
    adjustMaximumSizeForEditing(currentIndex());
562
 
}
563
 
 
564
 
void DolphinDetailsView::slotActivationChanged(bool active)
565
 
{
566
 
    setAlternatingRowColors(active);
567
 
}
568
 
 
569
 
void DolphinDetailsView::disableAutoResizing()
570
 
{
571
 
    m_autoResize = false;
572
 
}
573
 
 
574
 
void DolphinDetailsView::requestActivation()
575
 
{
576
 
    m_dolphinViewController->requestActivation();
577
 
}
578
 
 
579
 
void DolphinDetailsView::slotGlobalSettingsChanged(int category)
580
 
{
581
 
    Q_UNUSED(category);
582
 
 
583
 
    const DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
584
 
    Q_ASSERT(settings);
585
 
    if (settings->useSystemFont()) {
586
 
        m_font = KGlobalSettings::generalFont();
587
 
    }
588
 
    // Disconnect then reconnect, since the settings have been changed, the connection requirements may have also.
589
 
    disconnect(this, SIGNAL(clicked(QModelIndex)), m_dolphinViewController, SLOT(triggerItem(QModelIndex)));
590
 
    disconnect(this, SIGNAL(doubleClicked(QModelIndex)), m_dolphinViewController, SLOT(triggerItem(QModelIndex)));
591
 
    if (KGlobalSettings::singleClick()) {
592
 
        connect(this, SIGNAL(clicked(QModelIndex)), m_dolphinViewController, SLOT(triggerItem(QModelIndex)));
593
 
    } else {
594
 
        connect(this, SIGNAL(doubleClicked(QModelIndex)), m_dolphinViewController, SLOT(triggerItem(QModelIndex)));
595
 
    }
596
 
}
597
 
 
598
 
 
599
 
void DolphinDetailsView::setFoldersExpandable(bool expandable)
600
 
{
601
 
    if (!expandable) {
602
 
        // Collapse all expanded folders, as QTreeView::setItemsExpandable(false)
603
 
        // does not do this task
604
 
        const int rowCount = model()->rowCount();
605
 
        for (int row = 0; row < rowCount; ++row) {
606
 
            setExpanded(model()->index(row, 0), false);
607
 
        }
608
 
    }
609
 
    DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
610
 
    settings->setExpandableFolders(expandable);
611
 
    setRootIsDecorated(expandable);
612
 
    setItemsExpandable(expandable);
613
 
 
614
 
    // The width of the space which is available for editing has changed
615
 
    // because of the (dis)appearance of the expanding toggles
616
 
    adjustMaximumSizeForEditing(currentIndex());
617
 
}
618
 
 
619
 
void DolphinDetailsView::slotExpanded(const QModelIndex& index)
620
 
{
621
 
    KFileItem item = m_dolphinViewController->itemForIndex(index);
622
 
    if (!item.isNull()) {
623
 
        m_expandedUrls.insert(item.url());
624
 
    }
625
 
}
626
 
 
627
 
void DolphinDetailsView::slotCollapsed(const QModelIndex& index)
628
 
{
629
 
    KFileItem item = m_dolphinViewController->itemForIndex(index);
630
 
    if (!item.isNull()) {
631
 
        m_expandedUrls.remove(item.url());
632
 
    }
633
 
}
634
 
 
635
 
void DolphinDetailsView::removeExpandedIndexes(const QModelIndex& parent, int start, int end)
636
 
{
637
 
    if (m_expandedUrls.isEmpty()) {
638
 
        return;
639
 
    }
640
 
 
641
 
    for (int row = start; row <= end; row++) {
642
 
        const QModelIndex index = model()->index(row, 0, parent);
643
 
        if (isExpanded(index)) {
644
 
            slotCollapsed(index);
645
 
            removeExpandedIndexes(index, 0, model()->rowCount(index) - 1);
646
 
        }
647
 
    }
648
 
}
649
 
 
650
 
void DolphinDetailsView::updateDecorationSize(bool showPreview)
651
 
{
652
 
    DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
653
 
    const int iconSize = showPreview ? settings->previewSize() : settings->iconSize();
654
 
    setIconSize(QSize(iconSize, iconSize));
655
 
    m_decorationSize = QSize(iconSize, iconSize);
656
 
 
657
 
    if (m_extensionsFactory) {
658
 
        // The old maximumSize used by KFileItemDelegate is not valid any more after the icon size change.
659
 
        // It must be discarded before doItemsLayout() is called (see bug 234600).
660
 
        m_extensionsFactory->fileItemDelegate()->setMaximumSize(QSize());
661
 
    }
662
 
 
663
 
    doItemsLayout();
664
 
 
665
 
    // Calculate the new maximumSize for KFileItemDelegate after the icon size change.
666
 
    QModelIndex current = currentIndex();
667
 
    if (current.isValid()) {
668
 
        adjustMaximumSizeForEditing(current);
669
 
    }
670
 
}
671
 
 
672
 
KFileItemDelegate::Information DolphinDetailsView::infoForColumn(int columnIndex) const
673
 
{
674
 
    return AdditionalInfoAccessor::instance().keyForColumn(columnIndex);
675
 
}
676
 
 
677
 
void DolphinDetailsView::adjustMaximumSizeForEditing(const QModelIndex& index)
678
 
{
679
 
    // Make sure that the full width of the "Name" column is available for "Rename Inline".
680
 
    // Before we do that, we have to check if m_extensionsFactory has been initialised because
681
 
    // it is possible that we end up here before the constructor is finished (see bug 257035)
682
 
    if (m_extensionsFactory) {
683
 
        m_extensionsFactory->fileItemDelegate()->setMaximumSize(QTreeView::visualRect(index).size());
684
 
    }
685
 
}
686
 
 
687
 
QString DolphinDetailsView::itemSizeString(const QModelIndex& index, const KFileItem& item) const
688
 
{
689
 
    // The following code has been copied from KFileItemDelegate::Private::itemSize()
690
 
    // Copyright (c) 2006-2007, 2008 Fredrik Höglund <fredrik@kde.org>
691
 
    // Ideally this should be handled by KFileItemDelegate::sizeHint().
692
 
    if (item.isFile()) {
693
 
        return KGlobal::locale()->formatByteSize(item.size());
694
 
    }
695
 
 
696
 
    // Return the number of items in the directory
697
 
    const QVariant value = index.data(KDirModel::ChildCountRole);
698
 
    const int count = value.type() == QVariant::Int ? value.toInt() : KDirModel::ChildCountUnknown;
699
 
 
700
 
    if (count == KDirModel::ChildCountUnknown) {
701
 
        return QString();
702
 
    }
703
 
 
704
 
    return i18ncp("Items in a folder", "1 item", "%1 items", count);
705
 
}
706
 
 
707
 
#include "dolphindetailsview.moc"