source: trunk/src/gui/dialogs/qsidebar.cpp@ 460

Last change on this file since 460 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 14.7 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qsidebar_p.h"
43#include "qfilesystemmodel.h"
44
45#ifndef QT_NO_FILEDIALOG
46
47#include <qaction.h>
48#include <qurl.h>
49#include <qmenu.h>
50#include <qmimedata.h>
51#include <qevent.h>
52#include <qdebug.h>
53#include <qfileiconprovider.h>
54#include <qfiledialog.h>
55
56QT_BEGIN_NAMESPACE
57
58/*!
59 QUrlModel lets you have indexes from a QFileSystemModel to a list. When QFileSystemModel
60 changes them QUrlModel will automatically update.
61
62 Example usage: File dialog sidebar and combo box
63 */
64QUrlModel::QUrlModel(QObject *parent) : QStandardItemModel(parent), showFullPath(false), fileSystemModel(0)
65{
66}
67
68/*!
69 \reimp
70*/
71QStringList QUrlModel::mimeTypes() const
72{
73 return QStringList(QLatin1String("text/uri-list"));
74}
75
76/*!
77 \reimp
78*/
79Qt::ItemFlags QUrlModel::flags(const QModelIndex &index) const
80{
81 Qt::ItemFlags flags = QStandardItemModel::flags(index);
82 if (index.isValid()) {
83 flags &= ~Qt::ItemIsEditable;
84 // ### some future version could support "moving" urls onto a folder
85 flags &= ~Qt::ItemIsDropEnabled;
86 }
87
88 if (index.data(Qt::DecorationRole).isNull())
89 flags &= ~Qt::ItemIsEnabled;
90
91 if (invalidUrls.contains(index.data(UrlRole).toUrl()))
92 flags &= ~Qt::ItemIsEnabled;
93
94 return flags;
95}
96
97/*!
98 \reimp
99*/
100QMimeData *QUrlModel::mimeData(const QModelIndexList &indexes) const
101{
102 QList<QUrl> list;
103 for (int i = 0; i < indexes.count(); ++i) {
104 if (indexes.at(i).column() == 0)
105 list.append(indexes.at(i).data(UrlRole).toUrl());
106 }
107 QMimeData *data = new QMimeData();
108 data->setUrls(list);
109 return data;
110}
111
112#ifndef QT_NO_DRAGANDDROP
113
114/*!
115 Decide based upon the data if it should be accepted or not
116
117 We only accept dirs and not files
118*/
119bool QUrlModel::canDrop(QDragEnterEvent *event)
120{
121 if (!event->mimeData()->formats().contains(mimeTypes().first()))
122 return false;
123
124 const QList<QUrl> list = event->mimeData()->urls();
125 for (int i = 0; i < list.count(); ++i) {
126 QModelIndex idx = fileSystemModel->index(list.at(0).toLocalFile());
127 if (!fileSystemModel->isDir(idx))
128 return false;
129 }
130 return true;
131}
132
133/*!
134 \reimp
135*/
136bool QUrlModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
137 int row, int column, const QModelIndex &parent)
138{
139 if (!data->formats().contains(mimeTypes().first()))
140 return false;
141 Q_UNUSED(action);
142 Q_UNUSED(column);
143 Q_UNUSED(parent);
144 addUrls(data->urls(), row);
145 return true;
146}
147
148#endif // QT_NO_DRAGANDDROP
149
150/*!
151 \reimp
152
153 If the role is the UrlRole then handle otherwise just pass to QStandardItemModel
154*/
155bool QUrlModel::setData(const QModelIndex &index, const QVariant &value, int role)
156{
157 if (value.type() == QVariant::Url) {
158 QUrl url = value.toUrl();
159 QModelIndex dirIndex = fileSystemModel->index(url.toLocalFile());
160 //On windows the popup display the "C:\", convert to nativeSeparators
161 if (showFullPath)
162 QStandardItemModel::setData(index, QDir::toNativeSeparators(fileSystemModel->data(dirIndex, QFileSystemModel::FilePathRole).toString()));
163 else {
164 QStandardItemModel::setData(index, QDir::toNativeSeparators(fileSystemModel->data(dirIndex, QFileSystemModel::FilePathRole).toString()), Qt::ToolTipRole);
165 QStandardItemModel::setData(index, fileSystemModel->data(dirIndex).toString());
166 }
167 QStandardItemModel::setData(index, fileSystemModel->data(dirIndex, Qt::DecorationRole),
168 Qt::DecorationRole);
169 QStandardItemModel::setData(index, url, UrlRole);
170 return true;
171 }
172 return QStandardItemModel::setData(index, value, role);
173}
174
175void QUrlModel::setUrl(const QModelIndex &index, const QUrl &url, const QModelIndex &dirIndex)
176{
177 setData(index, url, UrlRole);
178 if (url.path().isEmpty()) {
179 setData(index, fileSystemModel->myComputer());
180 setData(index, fileSystemModel->myComputer(Qt::DecorationRole), Qt::DecorationRole);
181 } else {
182 QString newName;
183 if (showFullPath) {
184 //On windows the popup display the "C:\", convert to nativeSeparators
185 newName = QDir::toNativeSeparators(dirIndex.data(QFileSystemModel::FilePathRole).toString());
186 } else {
187 newName = dirIndex.data().toString();
188 }
189
190 QIcon newIcon = qvariant_cast<QIcon>(dirIndex.data(Qt::DecorationRole));
191 if (!dirIndex.isValid()) {
192 newIcon = fileSystemModel->iconProvider()->icon(QFileIconProvider::Folder);
193 newName = QFileInfo(url.toLocalFile()).fileName();
194 if (!invalidUrls.contains(url))
195 invalidUrls.append(url);
196 }
197
198 // Make sure that we have at least 32x32 images
199 const QSize size = newIcon.actualSize(QSize(32,32));
200 if (size.width() < 32) {
201 QPixmap smallPixmap = newIcon.pixmap(QSize(32, 32));
202 newIcon.addPixmap(smallPixmap.scaledToWidth(32, Qt::SmoothTransformation));
203 }
204
205 if (index.data().toString() != newName)
206 setData(index, newName);
207 QIcon oldIcon = qvariant_cast<QIcon>(index.data(Qt::DecorationRole));
208 if (oldIcon.cacheKey() != newIcon.cacheKey())
209 setData(index, newIcon, Qt::DecorationRole);
210 }
211}
212
213void QUrlModel::setUrls(const QList<QUrl> &list)
214{
215 removeRows(0, rowCount());
216 invalidUrls.clear();
217 watching.clear();
218 addUrls(list, 0);
219}
220
221/*!
222 Add urls \a list into the list at \a row. If move then movie
223 existing ones to row.
224
225 \sa dropMimeData()
226*/
227void QUrlModel::addUrls(const QList<QUrl> &list, int row, bool move)
228{
229 if (row == -1)
230 row = rowCount();
231 row = qMin(row, rowCount());
232 for (int i = list.count() - 1; i >= 0; --i) {
233 QUrl url = list.at(i);
234 if (!url.isValid() || url.scheme() != QLatin1String("file"))
235 continue;
236 for (int j = 0; move && j < rowCount(); ++j) {
237 if (index(j, 0).data(UrlRole) == url) {
238 removeRow(j);
239 if (j <= row)
240 row--;
241 break;
242 }
243 }
244 row = qMax(row, 0);
245 QModelIndex idx = fileSystemModel->index(url.toLocalFile());
246 if (!fileSystemModel->isDir(idx))
247 continue;
248 insertRows(row, 1);
249 setUrl(index(row, 0), url, idx);
250 watching.append(QPair<QModelIndex, QString>(idx, url.toLocalFile()));
251 }
252}
253
254/*!
255 Return the complete list of urls in a QList.
256*/
257QList<QUrl> QUrlModel::urls() const
258{
259 QList<QUrl> list;
260 for (int i = 0; i < rowCount(); ++i)
261 list.append(data(index(i, 0), UrlRole).toUrl());
262 return list;
263}
264
265/*!
266 QFileSystemModel to get index's from, clears existing rows
267*/
268void QUrlModel::setFileSystemModel(QFileSystemModel *model)
269{
270 if (model == fileSystemModel)
271 return;
272 if (fileSystemModel != 0) {
273 disconnect(model, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
274 this, SLOT(dataChanged(const QModelIndex &, const QModelIndex &)));
275 disconnect(model, SIGNAL(layoutChanged()),
276 this, SLOT(layoutChanged()));