Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qsidebar.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qsidebar_p.h"
5
6#include <qaction.h>
7#include <qurl.h>
8#if QT_CONFIG(menu)
9#include <qmenu.h>
10#endif
11#include <qmimedata.h>
12#include <qevent.h>
13#include <qdebug.h>
14#include <qfilesystemmodel.h>
16#include <qfiledialog.h>
17
19
20using namespace Qt::StringLiterals;
21
22void QSideBarDelegate::initStyleOption(QStyleOptionViewItem *option,
23 const QModelIndex &index) const
24{
27 if (value.isValid()) {
28 //If the bookmark/entry is not enabled then we paint it in gray
29 if (!qvariant_cast<bool>(value))
30 option->state &= ~QStyle::State_Enabled;
31 }
32}
33
43{
44}
45
50{
51 return QStringList("text/uri-list"_L1);
52}
53
57Qt::ItemFlags QUrlModel::flags(const QModelIndex &index) const
58{
59 Qt::ItemFlags flags = QStandardItemModel::flags(index);
60 if (index.isValid()) {
61 flags &= ~Qt::ItemIsEditable;
62 // ### some future version could support "moving" urls onto a folder
63 flags &= ~Qt::ItemIsDropEnabled;
64 }
65
66 if (index.data(Qt::DecorationRole).isNull())
67 flags &= ~Qt::ItemIsEnabled;
68
69 return flags;
70}
71
76{
78 for (const auto &index : indexes) {
79 if (index.column() == 0)
80 list.append(index.data(UrlRole).toUrl());
81 }
82 QMimeData *data = new QMimeData();
83 data->setUrls(list);
84 return data;
85}
86
87#if QT_CONFIG(draganddrop)
88
94bool QUrlModel::canDrop(QDragEnterEvent *event)
95{
96 if (!event->mimeData()->formats().contains(mimeTypes().constFirst()))
97 return false;
98
99 const QList<QUrl> list = event->mimeData()->urls();
100 for (const auto &url : list) {
101 const QModelIndex idx = fileSystemModel->index(url.toLocalFile());
102 if (!fileSystemModel->isDir(idx))
103 return false;
104 }
105 return true;
106}
107
112 int row, int column, const QModelIndex &parent)
113{
114 if (!data->formats().contains(mimeTypes().constFirst()))
115 return false;
116 Q_UNUSED(action);
119 addUrls(data->urls(), row);
120 return true;
121}
122
123#endif // QT_CONFIG(draganddrop)
124
130bool QUrlModel::setData(const QModelIndex &index, const QVariant &value, int role)
131{
132 if (value.userType() == QMetaType::QUrl) {
133 QUrl url = value.toUrl();
134 QModelIndex dirIndex = fileSystemModel->index(url.toLocalFile());
135 //On windows the popup display the "C:\", convert to nativeSeparators
136 if (showFullPath)
138 else {
140 QStandardItemModel::setData(index, fileSystemModel->data(dirIndex).toString());
141 }
142 QStandardItemModel::setData(index, fileSystemModel->data(dirIndex, Qt::DecorationRole),
145 return true;
146 }
148}
149
150void QUrlModel::setUrl(const QModelIndex &index, const QUrl &url, const QModelIndex &dirIndex)
151{
153 if (url.path().isEmpty()) {
154 setData(index, fileSystemModel->myComputer());
156 } else {
157 QString newName;
158 if (showFullPath) {
159 //On windows the popup display the "C:\", convert to nativeSeparators
161 } else {
162 newName = dirIndex.data().toString();
163 }
164
165 QIcon newIcon = qvariant_cast<QIcon>(dirIndex.data(Qt::DecorationRole));
166 if (!dirIndex.isValid()) {
167 const QAbstractFileIconProvider *provider = fileSystemModel->iconProvider();
168 if (provider)
169 newIcon = provider->icon(QAbstractFileIconProvider::Folder);
170 newName = QFileInfo(url.toLocalFile()).fileName();
171 if (!invalidUrls.contains(url))
172 invalidUrls.append(url);
173 //The bookmark is invalid then we set to false the EnabledRole
174 setData(index, false, EnabledRole);
175 } else {
176 //The bookmark is valid then we set to true the EnabledRole
177 setData(index, true, EnabledRole);
178 }
179
180 // Make sure that we have at least 32x32 images
181 const QSize size = newIcon.actualSize(QSize(32,32));
182 if (size.width() < 32) {
183 QPixmap smallPixmap = newIcon.pixmap(QSize(32, 32));
184 newIcon.addPixmap(smallPixmap.scaledToWidth(32, Qt::SmoothTransformation));
185 }
186
187 if (index.data().toString() != newName)
188 setData(index, newName);
189 QIcon oldIcon = qvariant_cast<QIcon>(index.data(Qt::DecorationRole));
190 if (oldIcon.cacheKey() != newIcon.cacheKey())
192 }
193}
194
196{
197 removeRows(0, rowCount());
198 invalidUrls.clear();
199 watching.clear();
200 addUrls(list, 0);
201}
202
209void QUrlModel::addUrls(const QList<QUrl> &list, int row, bool move)
210{
211 if (row == -1)
212 row = rowCount();
213 row = qMin(row, rowCount());
214 const auto rend = list.crend();
215 for (auto it = list.crbegin(); it != rend; ++it) {
216 QUrl url = *it;
217 if (!url.isValid() || url.scheme() != "file"_L1)
218 continue;
219 //this makes sure the url is clean
220 const QString cleanUrl = QDir::cleanPath(url.toLocalFile());
221 if (!cleanUrl.isEmpty())
222 url = QUrl::fromLocalFile(cleanUrl);
223
224 for (int j = 0; move && j < rowCount(); ++j) {
225 QString local = index(j, 0).data(UrlRole).toUrl().toLocalFile();
226#if defined(Q_OS_WIN)
228#else
230#endif
231 if (!cleanUrl.compare(local, cs)) {
232 removeRow(j);
233 if (j <= row)
234 row--;
235 break;
236 }
237 }
238 row = qMax(row, 0);
239 QModelIndex idx = fileSystemModel->index(cleanUrl);
240 if (!fileSystemModel->isDir(idx))
241 continue;
242 insertRows(row, 1);
243 setUrl(index(row, 0), url, idx);
244 watching.append({idx, cleanUrl});
245 }
246}
247
252{
254 const int numRows = rowCount();
255 list.reserve(numRows);
256 for (int i = 0; i < numRows; ++i)
257 list.append(data(index(i, 0), UrlRole).toUrl());
258 return list;
259}
260
265{
266 if (model == fileSystemModel)
267 return;
268 if (fileSystemModel != nullptr) {
270 this, SLOT(dataChanged(QModelIndex,QModelIndex)));
271 disconnect(model, SIGNAL(layoutChanged()),
272 this, SLOT(layoutChanged()));
274 this, SLOT(layoutChanged()));
275 }
276 fileSystemModel = model;
277 if (fileSystemModel != nullptr) {
279 this, SLOT(dataChanged(QModelIndex,QModelIndex)));
280 connect(model, SIGNAL(layoutChanged()),
281 this, SLOT(layoutChanged()));
283 this, SLOT(layoutChanged()));
284 }
285 clear();
286 insertColumns(0, 1);
287}
288
289/*
290 If one of the index's we are watching has changed update our internal data
291*/
292void QUrlModel::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
293{
294 QModelIndex parent = topLeft.parent();
295 for (int i = 0; i < watching.size(); ++i) {
296 QModelIndex index = watching.at(i).index;
297 if (index.model() && topLeft.model()) {
298 Q_ASSERT(index.model() == topLeft.model());
299 }
300 if ( index.row() >= topLeft.row()
301 && index.row() <= bottomRight.row()
302 && index.column() >= topLeft.column()
303 && index.column() <= bottomRight.column()
304 && index.parent() == parent) {
305 changed(watching.at(i).path);
306 }
307 }
308}
309
313void QUrlModel::layoutChanged()
314{
316 paths.reserve(watching.size());
317 for (const WatchItem &item : std::as_const(watching))
319 watching.clear();
320 for (const auto &path : paths) {
321 QModelIndex newIndex = fileSystemModel->index(path);
322 watching.append({newIndex, path});
323 if (newIndex.isValid())
324 changed(path);
325 }
326}
327
333void QUrlModel::changed(const QString &path)
334{
335 for (int i = 0; i < rowCount(); ++i) {
336 QModelIndex idx = index(i, 0);
337 if (idx.data(UrlRole).toUrl().toLocalFile() == path) {
338 setData(idx, idx.data(UrlRole).toUrl());
339 }
340 }
341}
342
344{
345}
346
348{
350 urlModel = new QUrlModel(this);
351 urlModel->setFileSystemModel(model);
352 setModel(urlModel);
354
356 this, SLOT(clicked(QModelIndex)));
357#if QT_CONFIG(draganddrop)
358 setDragDropMode(QAbstractItemView::DragDrop);
359#endif
360 setContextMenuPolicy(Qt::CustomContextMenu);
361 connect(this, SIGNAL(customContextMenuRequested(QPoint)),
362 this, SLOT(showContextMenu(QPoint)));
363 urlModel->setUrls(newUrls);
364 setCurrentIndex(this->model()->index(0,0));
365}
366
368{
369}
370
371#if QT_CONFIG(draganddrop)
372void QSidebar::dragEnterEvent(QDragEnterEvent *event)
373{
374 if (urlModel->canDrop(event))
375 QListView::dragEnterEvent(event);
376}
377#endif // QT_CONFIG(draganddrop)
378
380{
381 if (model())
382 return QListView::sizeHintForIndex(model()->index(0, 0)) + QSize(2 * frameWidth(), 2 * frameWidth());
383 return QListView::sizeHint();
384}
385
387{
389 this, SLOT(clicked(QModelIndex)));
390
392 for (int i = 0; i < model()->rowCount(); ++i) {
393 if (model()->index(i, 0).data(QUrlModel::UrlRole).toUrl() == url) {
395 break;
396 }
397 }
398
400 this, SLOT(clicked(QModelIndex)));
401}
402
403#if QT_CONFIG(menu)
409void QSidebar::showContextMenu(const QPoint &position)
410{
411 QList<QAction *> actions;
412 if (indexAt(position).isValid()) {
413 QAction *action = new QAction(QFileDialog::tr("Remove"), this);
414 if (indexAt(position).data(QUrlModel::UrlRole).toUrl().path().isEmpty())
415 action->setEnabled(false);
416 connect(action, SIGNAL(triggered()), this, SLOT(removeEntry()));
417 actions.append(action);
418 }
419 if (actions.size() > 0)
420 QMenu::exec(actions, mapToGlobal(position));
421}
422#endif // QT_CONFIG(menu)
423
429void QSidebar::removeEntry()
430{
432 // Create a list of QPersistentModelIndex as the removeRow() calls below could
433 // invalidate the indexes in "idxs"
434 const QList<QPersistentModelIndex> persIndexes(idxs.cbegin(), idxs.cend());
435 for (const QPersistentModelIndex &persistent : persIndexes) {
436 if (!persistent.data(QUrlModel::UrlRole).toUrl().path().isEmpty())
437 model()->removeRow(persistent.row());
438 }
439}
440
446void QSidebar::clicked(const QModelIndex &index)
447{
450 selectUrl(url);
451}
452
458{
459 QAbstractScrollArea::focusInEvent(event);
460 viewport()->update();
461}
462
467{
468 if (event->type() == QEvent::KeyRelease) {
469 QKeyEvent *ke = static_cast<QKeyEvent *>(event);
470 if (ke->key() == Qt::Key_Delete) {
471 removeEntry();
472 return true;
473 }
474 }
475 return QListView::event(event);
476}
477
479
480#include "moc_qsidebar_p.cpp"
virtual QIcon icon(IconType) const
Returns an icon set for the given type, using the current icon theme.
virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
Handles the data supplied by a drag and drop operation that ended with the given action.
virtual Q_INVOKABLE int rowCount(const QModelIndex &parent=QModelIndex()) const =0
Returns the number of rows under the given parent.
virtual Q_INVOKABLE QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const =0
Returns the index of the item in the model specified by the given row, column and parent index.
void rowsRemoved(const QModelIndex &parent, int first, int last, QPrivateSignal)
This signal is emitted after rows have been removed from the model.
QAbstractItemModel * model() const
Returns the model that this view is presenting.
void setCurrentIndex(const QModelIndex &index)
Sets the current item to be the item at index.
void setItemDelegate(QAbstractItemDelegate *delegate)
Sets the item delegate for this view and its model to delegate.
virtual void setModel(QAbstractItemModel *model)
Sets the model for the view to present.
virtual void currentChanged(const QModelIndex &current, const QModelIndex &previous)
This slot is called when a new item becomes the current item.
QSize sizeHintForIndex(const QModelIndex &index) const
Returns the size hint for the item with the specified index or an invalid size for invalid indexes.
QItemSelectionModel * selectionModel() const
Returns the current selection model.
The QAction class provides an abstraction for user commands that can be added to different user inter...
Definition qaction.h:30
void setEnabled(bool)
Definition qaction.cpp:927
static QString cleanPath(const QString &path)
Returns path with directory separators normalized (that is, platform-native separators converted to "...
Definition qdir.cpp:2395
static QString toNativeSeparators(const QString &pathName)
Definition qdir.cpp:929
\inmodule QtCore
Definition qcoreevent.h:45
@ KeyRelease
Definition qcoreevent.h:65
\inmodule QtCore \reentrant
Definition qfileinfo.h:22
QString fileName() const
Returns the name of the file, excluding the path.
The QFileSystemModel class provides a data model for the local filesystem.
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
\reimp
QVariant myComputer(int role=Qt::DisplayRole) const
Returns the data stored under the given role for the item "My Computer".
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
\reimp
QAbstractFileIconProvider * iconProvider() const
Returns the file icon provider for this directory model.
bool isDir(const QModelIndex &index) const
Returns true if the model item index represents a directory; otherwise returns false.
The QFocusEvent class contains event parameters for widget focus events.
Definition qevent.h:469
The QIcon class provides scalable icons in different modes and states.
Definition qicon.h:20
void addPixmap(const QPixmap &pixmap, Mode mode=Normal, State state=Off)
Adds pixmap to the icon, as a specialization for mode and state.
Definition qicon.cpp:1014
qint64 cacheKey() const
Returns a number that identifies the contents of this QIcon object.
Definition qicon.cpp:773
QSize actualSize(const QSize &size, Mode mode=Normal, State state=Off) const
Returns the actual size of the icon for the requested size, mode, and state.
Definition qicon.cpp:880
QPixmap pixmap(const QSize &size, Mode mode=Normal, State state=Off) const
Returns a pixmap with the requested size, mode, and state, generating one if necessary.
Definition qicon.cpp:788
QModelIndexList selectedIndexes
virtual void select(const QModelIndex &index, QItemSelectionModel::SelectionFlags command)
Selects the model item index using the specified command, and emits selectionChanged().
virtual void clear()
Clears the selection model.
The QKeyEvent class describes a key event.
Definition qevent.h:423
int key() const
Returns the code of the key that was pressed or released.
Definition qevent.h:433
The QListView class provides a list or icon view onto a model.
Definition qlistview.h:17
bool event(QEvent *e) override
\reimp
void setUniformItemSizes(bool enable)
QModelIndex indexAt(const QPoint &p) const override
\reimp
qsizetype size() const noexcept
Definition qlist.h:386
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
const_reverse_iterator crbegin() const noexcept
Definition qlist.h:621
void reserve(qsizetype size)
Definition qlist.h:746
const_iterator cend() const noexcept
Definition qlist.h:614
void append(parameter_type t)
Definition qlist.h:441
const_iterator cbegin() const noexcept
Definition qlist.h:613
void clear()
Definition qlist.h:417
const_reverse_iterator crend() const noexcept
Definition qlist.h:622
QAction * exec()
Executes this menu synchronously.
Definition qmenu.cpp:2586
\inmodule QtCore
Definition qmimedata.h:16
\inmodule QtCore
QVariant data(int role=Qt::DisplayRole) const
Returns the data for the given role for the item referred to by the index.
constexpr int row() const noexcept
Returns the row this model index refers to.
QModelIndex parent() const
Returns the parent of the model index, or QModelIndex() if it has no parent.
constexpr const QAbstractItemModel * model() const noexcept
Returns a pointer to the model containing the item that this index refers to.
constexpr int column() const noexcept
Returns the column this model index refers to.
constexpr bool isValid() const noexcept
Returns {true} if this model index is valid; otherwise returns {false}.
\inmodule QtCore
Definition qobject.h:90
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
Returns a copy of the pixmap that is transformed using the given transformation transform and transfo...
Definition qpixmap.h:27
QPixmap scaledToWidth(int w, Qt::TransformationMode mode=Qt::FastTransformation) const
Returns a scaled copy of the image.
Definition qpixmap.cpp:1038
\inmodule QtCore\reentrant
Definition qpoint.h:23
void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const override
Initialize option with the values using the index index.
Definition qsidebar.cpp:22
void focusInEvent(QFocusEvent *event) override
\reimp Don't automatically select something
Definition qsidebar.cpp:457
QSize sizeHint() const override
Definition qsidebar.cpp:379
void goToUrl(const QUrl &url)
void setModelAndUrls(QFileSystemModel *model, const QList< QUrl > &newUrls)
Definition qsidebar.cpp:347
void selectUrl(const QUrl &url)
Definition qsidebar.cpp:386
bool event(QEvent *e) override
\reimp
Definition qsidebar.cpp:466
QSidebar(QWidget *parent=nullptr)
Definition qsidebar.cpp:343
\inmodule QtCore
Definition qsize.h:25
The QStandardItemModel class provides a generic model for storing custom data.
void clear()
Removes all items (including header items) from the model and sets the number of rows and columns to ...
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:311
bool insertRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
\reimp
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
\reimp
bool insertColumns(int column, int count, const QModelIndex &parent=QModelIndex()) override
\reimp
Qt::ItemFlags flags(const QModelIndex &index) const override
\reimp
int rowCount(const QModelIndex &parent=QModelIndex()) const override
\reimp
bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
\reimp
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
int compare(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.cpp:6498
The QStyle class is an abstract base class that encapsulates the look and feel of a GUI.
Definition qstyle.h:29
virtual void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const
Initialize option with the values using the index index.
void setUrls(const QList< QUrl > &list)
Definition qsidebar.cpp:195
void addUrls(const QList< QUrl > &urls, int row=-1, bool move=true)
Add urls list into the list at row.
Definition qsidebar.cpp:209
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
\reimp
Definition qsidebar.cpp:130
QMimeData * mimeData(const QModelIndexList &indexes) const override
\reimp
Definition qsidebar.cpp:75
bool showFullPath
Definition qsidebar_p.h:64
QStringList mimeTypes() const override
\reimp
Definition qsidebar.cpp:49
QList< QUrl > urls() const
Return the complete list of urls in a QList.
Definition qsidebar.cpp:251
void setFileSystemModel(QFileSystemModel *model)
QFileSystemModel to get index's from, clears existing rows.
Definition qsidebar.cpp:264
Qt::ItemFlags flags(const QModelIndex &index) const override
\reimp
Definition qsidebar.cpp:57
QUrlModel(QObject *parent=nullptr)
Definition qsidebar.cpp:42
\inmodule QtCore
Definition qurl.h:94
static QUrl fromLocalFile(const QString &localfile)
Returns a QUrl representation of localFile, interpreted as a local file.
Definition qurl.cpp:3354
bool isValid() const
Returns true if the URL is non-empty and valid; otherwise returns false.
Definition qurl.cpp:1874
QString scheme() const
Returns the scheme of the URL.
Definition qurl.cpp:1983
QString toLocalFile() const
Returns the path of this URL formatted as a local file path.
Definition qurl.cpp:3411
QString path(ComponentFormattingOptions options=FullyDecoded) const
Returns the path of the URL.
Definition qurl.cpp:2465
\inmodule QtCore
Definition qvariant.h:64
void * data()
Returns a pointer to the contained object as a generic void* that can be written to.
QString toString() const
Returns the variant as a QString if the variant has a userType() including, but not limited to:
QUrl toUrl() const
Returns the variant as a QUrl if the variant has userType() \l QMetaType::QUrl; otherwise returns an ...
The QWidget class is the base class of all user interface objects.
Definition qwidget.h:99
list append(new Employee("Blackpool", "Stephen"))
QSet< QString >::iterator it
Combined button and popup list for selecting options.
@ SmoothTransformation
@ DecorationRole
@ ToolTipRole
@ Key_Delete
Definition qnamespace.h:665
CaseSensitivity
@ CaseInsensitive
@ CaseSensitive
DropAction
@ CustomContextMenu
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
#define SLOT(a)
Definition qobjectdefs.h:51
#define SIGNAL(a)
Definition qobjectdefs.h:52
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLsizei const GLuint * paths
GLbitfield flags
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLenum GLsizei void GLsizei void * column
struct _cl_event * event
GLsizei const GLchar *const * path
GLenum GLenum GLsizei void * row
GLuint GLenum option
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define emit
#define Q_UNUSED(x)
QSqlQueryModel * model
[16]
QList< int > list
[14]
QUrl url("example.com")
[constructor-url-reference]
connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::QueuedConnection)
QObject::connect nullptr
myObject disconnect()
[26]
QGraphicsItem * item
view viewport() -> scroll(dx, dy, deviceRect)
flay removeRow(2)
bool contains(const AT &t) const noexcept
Definition qlist.h:44
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent