1/*
2 This file is part of the KDE project
3
4 Copyright (C) 2007 Tobias Koenig <tokoe@kde.org>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21
22#include "kfiletreeview.h"
23
24#include <QtCore/QDir>
25#include <QtGui/QContextMenuEvent>
26#include <QtGui/QMenu>
27
28#include <kdirlister.h>
29#include <kdirmodel.h>
30#include <kdirsortfilterproxymodel.h>
31#include <kfileitemdelegate.h>
32#include <klocale.h>
33#include <ktoggleaction.h>
34#include <kurl.h>
35
36class KFileTreeView::Private
37{
38 public:
39 Private(KFileTreeView *parent)
40 : q(parent)
41 {
42 }
43
44 KUrl urlForProxyIndex(const QModelIndex &index) const;
45
46 void _k_activated(const QModelIndex&);
47 void _k_currentChanged(const QModelIndex&, const QModelIndex&);
48 void _k_expanded(const QModelIndex&);
49
50 KFileTreeView *q;
51 KDirModel *mSourceModel;
52 KDirSortFilterProxyModel *mProxyModel;
53};
54
55KUrl KFileTreeView::Private::urlForProxyIndex(const QModelIndex &index) const
56{
57 const KFileItem item = mSourceModel->itemForIndex(mProxyModel->mapToSource(index));
58
59 return !item.isNull() ? item.url() : KUrl();
60}
61
62void KFileTreeView::Private::_k_activated(const QModelIndex &index)
63{
64 const KUrl url = urlForProxyIndex(index);
65 if (url.isValid())
66 emit q->activated(url);
67}
68
69void KFileTreeView::Private::_k_currentChanged(const QModelIndex &currentIndex, const QModelIndex&)
70{
71 const KUrl url = urlForProxyIndex(currentIndex);
72 if (url.isValid())
73 emit q->currentChanged(url);
74}
75
76void KFileTreeView::Private::_k_expanded(const QModelIndex &baseIndex)
77{
78 QModelIndex index = mProxyModel->mapFromSource(baseIndex);
79
80 q->selectionModel()->clearSelection();
81 q->selectionModel()->setCurrentIndex(index, QItemSelectionModel::SelectCurrent);
82 q->scrollTo(index);
83}
84
85KFileTreeView::KFileTreeView(QWidget *parent)
86 : QTreeView(parent), d(new Private(this))
87{
88 d->mSourceModel = new KDirModel(this);
89 d->mProxyModel = new KDirSortFilterProxyModel(this);
90 d->mProxyModel->setSourceModel(d->mSourceModel);
91
92 setModel(d->mProxyModel);
93 setItemDelegate(new KFileItemDelegate(this));
94 setLayoutDirection(Qt::LeftToRight);
95
96 d->mSourceModel->dirLister()->openUrl(KUrl(QDir::root().absolutePath()), KDirLister::Keep);
97
98 connect(this, SIGNAL(activated(QModelIndex)),
99 this, SLOT(_k_activated(QModelIndex)));
100 connect(selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
101 this, SLOT(_k_currentChanged(QModelIndex,QModelIndex)));
102
103 connect(d->mSourceModel, SIGNAL(expand(QModelIndex)),
104 this, SLOT(_k_expanded(QModelIndex)));
105}
106
107KFileTreeView::~KFileTreeView()
108{
109 delete d;
110}
111
112KUrl KFileTreeView::currentUrl() const
113{
114 return d->urlForProxyIndex(currentIndex());
115}
116
117KUrl KFileTreeView::selectedUrl() const
118{
119 if (!selectionModel()->hasSelection())
120 return KUrl();
121
122 const QItemSelection selection = selectionModel()->selection();
123 const QModelIndex firstIndex = selection.indexes().first();
124
125 return d->urlForProxyIndex(firstIndex);
126}
127
128KUrl::List KFileTreeView::selectedUrls() const
129{
130 KUrl::List urls;
131
132 if (!selectionModel()->hasSelection())
133 return urls;
134
135 const QModelIndexList indexes = selectionModel()->selection().indexes();
136 foreach (const QModelIndex &index, indexes) {
137 const KUrl url = d->urlForProxyIndex(index);
138 if (url.isValid())
139 urls.append(url);
140 }
141
142 return urls;
143}
144
145KUrl KFileTreeView::rootUrl() const
146{
147 return d->mSourceModel->dirLister()->url();
148}
149
150void KFileTreeView::setDirOnlyMode(bool enabled)
151{
152 d->mSourceModel->dirLister()->setDirOnlyMode(enabled);
153 d->mSourceModel->dirLister()->openUrl(d->mSourceModel->dirLister()->url());
154}
155
156void KFileTreeView::setShowHiddenFiles(bool enabled)
157{
158 KUrl url = currentUrl();
159 d->mSourceModel->dirLister()->setShowingDotFiles(enabled);
160 d->mSourceModel->dirLister()->openUrl(d->mSourceModel->dirLister()->url());
161 setCurrentUrl(url);
162}
163
164void KFileTreeView::setCurrentUrl(const KUrl &url)
165{
166 QModelIndex baseIndex = d->mSourceModel->indexForUrl(url);
167
168 if (!baseIndex.isValid()) {
169 d->mSourceModel->expandToUrl(url);
170 return;
171 }
172
173 QModelIndex proxyIndex = d->mProxyModel->mapFromSource(baseIndex);
174 selectionModel()->clearSelection();
175 selectionModel()->setCurrentIndex(proxyIndex, QItemSelectionModel::SelectCurrent);
176 scrollTo(proxyIndex);
177}
178
179void KFileTreeView::setRootUrl(const KUrl &url)
180{
181 d->mSourceModel->dirLister()->openUrl(url);
182}
183
184void KFileTreeView::contextMenuEvent(QContextMenuEvent *event)
185{
186 QMenu menu;
187 KToggleAction *showHiddenAction = new KToggleAction(i18n("Show Hidden Folders"), &menu);
188 showHiddenAction->setChecked(d->mSourceModel->dirLister()->showingDotFiles());
189 connect(showHiddenAction, SIGNAL(toggled(bool)), this, SLOT(setShowHiddenFiles(bool)));
190
191 menu.addAction(showHiddenAction);
192 menu.exec(event->globalPos());
193}
194
195bool KFileTreeView::showHiddenFiles() const
196{
197 return d->mSourceModel->dirLister()->showingDotFiles();
198}
199
200QSize KFileTreeView::sizeHint() const
201{
202 // This size makes KDirSelectDialog pop up just under 800x600 by default :-)
203 return QSize(680, 500);
204}
205
206#include "kfiletreeview.moc"
207