• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KIO

  • kio
  • kio
kdirmodel.cpp
Go to the documentation of this file.
1/* This file is part of the KDE project
2 Copyright (C) 2006 David Faure <faure@kde.org>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
18*/
19
20#include "kdirmodel.h"
21#include "kdirlister.h"
22#include "kfileitem.h"
23#include <kdatetime.h>
24#include <kicon.h>
25#include <klocale.h>
26#include <kglobal.h>
27#include <kio/copyjob.h>
28#include <kio/fileundomanager.h>
29#include <kio/jobuidelegate.h>
30#include <kio/joburlcache_p.h>
31#include <kurl.h>
32#include <kdebug.h>
33#include <QMimeData>
34#include <QFile>
35#include <QFileInfo>
36#include <QDir>
37#include <sys/types.h>
38#include <dirent.h>
39
40#ifdef Q_WS_WIN
41#include <windows.h>
42#endif
43
44class KDirModelNode;
45class KDirModelDirNode;
46
47static KUrl cleanupUrl(const KUrl& url) {
48 KUrl u = url;
49 u.cleanPath(); // remove double slashes in the path, simplify "foo/." to "foo/", etc.
50 u.adjustPath(KUrl::RemoveTrailingSlash); // KDirLister does this too, so we remove the slash before comparing with the root node url.
51 u.setQuery(QString());
52 u.setRef(QString());
53 return u;
54}
55
56// We create our own tree behind the scenes to have fast lookup from an item to its parent,
57// and also to get the children of an item fast.
58class KDirModelNode
59{
60public:
61 KDirModelNode( KDirModelDirNode* parent, const KFileItem& item ) :
62 m_item(item),
63 m_parent(parent),
64 m_preview()
65 {
66 }
67 // m_item is KFileItem() for the root item
68 const KFileItem& item() const { return m_item; }
69 void setItem(const KFileItem& item) { m_item = item; }
70 KDirModelDirNode* parent() const { return m_parent; }
71 // linear search
72 int rowNumber() const; // O(n)
73 QIcon preview() const { return m_preview; }
74 void setPreview( const QPixmap& pix ) { m_preview = QIcon(); m_preview.addPixmap(pix); }
75 void setPreview( const QIcon& icn ) { m_preview = icn; }
76
77private:
78 KFileItem m_item;
79 KDirModelDirNode* const m_parent;
80 QIcon m_preview;
81};
82
83// Specialization for directory nodes
84class KDirModelDirNode : public KDirModelNode
85{
86public:
87 KDirModelDirNode( KDirModelDirNode* parent, const KFileItem& item)
88 : KDirModelNode( parent, item),
89 m_childNodes(),
90 m_childCount(KDirModel::ChildCountUnknown),
91 m_populated(false)
92 {}
93 ~KDirModelDirNode() {
94 qDeleteAll(m_childNodes);
95 }
96 QList<KDirModelNode *> m_childNodes; // owns the nodes
97
98 // If we listed the directory, the child count is known. Otherwise it can be set via setChildCount.
99 int childCount() const { return m_childNodes.isEmpty() ? m_childCount : m_childNodes.count(); }
100 void setChildCount(int count) { m_childCount = count; }
101 bool isPopulated() const { return m_populated; }
102 void setPopulated( bool populated ) { m_populated = populated; }
103 bool isSlow() const { return item().isSlow(); }
104
105 // For removing all child urls from the global hash.
106 void collectAllChildUrls(KUrl::List &urls) const {
107 Q_FOREACH(KDirModelNode* node, m_childNodes) {
108 const KFileItem& item = node->item();
109 urls.append(cleanupUrl(item.url()));
110 if (item.isDir())
111 static_cast<KDirModelDirNode*>(node)->collectAllChildUrls(urls);
112 }
113 }
114
115private:
116 int m_childCount:31;
117 bool m_populated:1;
118};
119
120int KDirModelNode::rowNumber() const
121{
122 if (!m_parent) return 0;
123 return m_parent->m_childNodes.indexOf(const_cast<KDirModelNode*>(this));
124}
125
127
128class KDirModelPrivate
129{
130public:
131 KDirModelPrivate( KDirModel* model )
132 : q(model), m_dirLister(0),
133 m_rootNode(new KDirModelDirNode(0, KFileItem())),
134 m_dropsAllowed(KDirModel::NoDrops), m_jobTransfersVisible(false)
135 {
136 }
137 ~KDirModelPrivate() {
138 delete m_rootNode;
139 }
140
141 void _k_slotNewItems(const KUrl& directoryUrl, const KFileItemList&);
142 void _k_slotDeleteItems(const KFileItemList&);
143 void _k_slotRefreshItems(const QList<QPair<KFileItem, KFileItem> >&);
144 void _k_slotClear();
145 void _k_slotRedirection(const KUrl& oldUrl, const KUrl& newUrl);
146 void _k_slotJobUrlsChanged(const QStringList& urlList);
147
148 void clear() {
149 delete m_rootNode;
150 m_rootNode = new KDirModelDirNode(0, KFileItem());
151 }
152 // Emit expand for each parent and then return the
153 // last known parent if there is no node for this url
154 KDirModelNode* expandAllParentsUntil(const KUrl& url) const;
155
156 // Return the node for a given url, using the hash.
157 KDirModelNode* nodeForUrl(const KUrl& url) const;
158 KDirModelNode* nodeForIndex(const QModelIndex& index) const;
159 QModelIndex indexForNode(KDirModelNode* node, int rowNumber = -1 /*unknown*/) const;
160 bool isDir(KDirModelNode* node) const {
161 return (node == m_rootNode) || node->item().isDir();
162 }
163 KUrl urlForNode(KDirModelNode* node) const {
171 KUrl url(node == m_rootNode ? m_dirLister->url() : node->item().url());
172 if (url.hasQuery() || url.hasRef()) { // avoid detach if not necessary.
173 url.setQuery(QString());
174 url.setRef(QString()); // kill ref (#171117)
175 }
176 return url;
177 }
178 void removeFromNodeHash(KDirModelNode* node, const KUrl& url);
179#ifndef NDEBUG
180 void dump();
181#endif
182
183 KDirModel* q;
184 KDirLister* m_dirLister;
185 KDirModelDirNode* m_rootNode;
186 KDirModel::DropsAllowed m_dropsAllowed;
187 bool m_jobTransfersVisible;
188 // key = current known parent node (always a KDirModelDirNode but KDirModelNode is more convenient),
189 // value = final url[s] being fetched
190 QMap<KDirModelNode*, KUrl::List> m_urlsBeingFetched;
191 QHash<KUrl, KDirModelNode *> m_nodeHash; // global node hash: url -> node
192 QStringList m_allCurrentDestUrls; //list of all dest urls that have jobs on them (e.g. copy, download)
193};
194
195KDirModelNode* KDirModelPrivate::nodeForUrl(const KUrl& _url) const // O(1), well, O(length of url as a string)
196{
197 KUrl url = cleanupUrl(_url);
198 if (url == urlForNode(m_rootNode))
199 return m_rootNode;
200 return m_nodeHash.value(url);
201}
202
203void KDirModelPrivate::removeFromNodeHash(KDirModelNode* node, const KUrl& url)
204{
205 if (node->item().isDir()) {
206 KUrl::List urls;
207 static_cast<KDirModelDirNode *>(node)->collectAllChildUrls(urls);
208 Q_FOREACH(const KUrl& u, urls) {
209 m_nodeHash.remove(u);
210 }
211 }
212 m_nodeHash.remove(cleanupUrl(url));
213}
214
215KDirModelNode* KDirModelPrivate::expandAllParentsUntil(const KUrl& _url) const // O(depth)
216{
217 KUrl url = cleanupUrl(_url);
218
219 //kDebug(7008) << url;
220 KUrl nodeUrl = urlForNode(m_rootNode);
221 if (url == nodeUrl)
222 return m_rootNode;
223
224 // Protocol mismatch? Don't even start comparing paths then. #171721
225 if (url.protocol() != nodeUrl.protocol())
226 return 0;
227
228 const QString pathStr = url.path(); // no trailing slash
229 KDirModelDirNode* dirNode = m_rootNode;
230
231 if (!pathStr.startsWith(nodeUrl.path())) {
232 return 0;
233 }
234
235 for (;;) {
236 const QString nodePath = nodeUrl.path(KUrl::AddTrailingSlash);
237 if(!pathStr.startsWith(nodePath)) {
238 kError(7008) << "The kioslave for" << url.protocol() << "violates the hierarchy structure:"
239 << "I arrived at node" << nodePath << ", but" << pathStr << "does not start with that path.";
240 return 0;
241 }
242
243 // E.g. pathStr is /a/b/c and nodePath is /a/. We want to find the node with url /a/b
244 const int nextSlash = pathStr.indexOf('/', nodePath.length());
245 const QString newPath = pathStr.left(nextSlash); // works even if nextSlash==-1
246 nodeUrl.setPath(newPath);
247 nodeUrl.adjustPath(KUrl::RemoveTrailingSlash); // #172508
248 KDirModelNode* node = nodeForUrl(nodeUrl);
249 if (!node) {
250 //kDebug(7008) << "child equal or starting with" << url << "not found";
251 // return last parent found:
252 return dirNode;
253 }
254
255 emit q->expand(indexForNode(node));
256
257 //kDebug(7008) << " nodeUrl=" << nodeUrl;
258 if (nodeUrl == url) {
259 //kDebug(7008) << "Found node" << node << "for" << url;
260 return node;
261 }
262 //kDebug(7008) << "going into" << node->item().url();
263 Q_ASSERT(isDir(node));
264 dirNode = static_cast<KDirModelDirNode *>(node);
265 }
266 // NOTREACHED
267 //return 0;
268}
269
270#ifndef NDEBUG
271void KDirModelPrivate::dump()
272{
273 kDebug() << "Dumping contents of KDirModel" << q << "dirLister url:" << m_dirLister->url();
274 QHashIterator<KUrl, KDirModelNode *> it(m_nodeHash);
275 while (it.hasNext()) {
276 it.next();
277 kDebug() << it.key() << it.value();
278 }
279}
280#endif
281
282// node -> index. If rowNumber is set (or node is root): O(1). Otherwise: O(n).
283QModelIndex KDirModelPrivate::indexForNode(KDirModelNode* node, int rowNumber) const
284{
285 if (node == m_rootNode)
286 return QModelIndex();
287
288 Q_ASSERT(node->parent());
289 return q->createIndex(rowNumber == -1 ? node->rowNumber() : rowNumber, 0, node);
290}
291
292// index -> node. O(1)
293KDirModelNode* KDirModelPrivate::nodeForIndex(const QModelIndex& index) const
294{
295 return index.isValid()
296 ? static_cast<KDirModelNode*>(index.internalPointer())
297 : m_rootNode;
298}
299
300/*
301 * This model wraps the data held by KDirLister.
302 *
303 * The internal pointer of the QModelIndex for a given file is the node for that file in our own tree.
304 * E.g. index(2,0) returns a QModelIndex with row=2 internalPointer=<KDirModelNode for the 3rd child of the root>
305 *
306 * Invalid parent index means root of the tree, m_rootNode
307 */
308
309#ifndef NDEBUG
310static QString debugIndex(const QModelIndex& index)
311{
312 QString str;
313 if (!index.isValid())
314 str = "[invalid index, i.e. root]";
315 else {
316 KDirModelNode* node = static_cast<KDirModelNode*>(index.internalPointer());
317 str = "[index for " + node->item().url().pathOrUrl();
318 if (index.column() > 0)
319 str += ", column " + QString::number(index.column());
320 str += ']';
321 }
322 return str;
323}
324#endif
325
326KDirModel::KDirModel(QObject* parent)
327 : QAbstractItemModel(parent),
328 d(new KDirModelPrivate(this))
329{
330 setDirLister(new KDirLister(this));
331}
332
333KDirModel::~KDirModel()
334{
335 delete d;
336}
337
338void KDirModel::setDirLister(KDirLister* dirLister)
339{
340 if (d->m_dirLister) {
341 d->clear();
342 delete d->m_dirLister;
343 }
344 d->m_dirLister = dirLister;
345 d->m_dirLister->setParent(this);
346 connect( d->m_dirLister, SIGNAL(itemsAdded(KUrl,KFileItemList)),
347 this, SLOT(_k_slotNewItems(KUrl,KFileItemList)) );
348 connect( d->m_dirLister, SIGNAL(itemsDeleted(KFileItemList)),
349 this, SLOT(_k_slotDeleteItems(KFileItemList)) );
350 connect( d->m_dirLister, SIGNAL(refreshItems(QList<QPair<KFileItem,KFileItem> >)),
351 this, SLOT(_k_slotRefreshItems(QList<QPair<KFileItem,KFileItem> >)) );
352 connect( d->m_dirLister, SIGNAL(clear()),
353 this, SLOT(_k_slotClear()) );
354 connect(d->m_dirLister, SIGNAL(redirection(KUrl,KUrl)),
355 this, SLOT(_k_slotRedirection(KUrl,KUrl)));
356}
357
358KDirLister* KDirModel::dirLister() const
359{
360 return d->m_dirLister;
361}
362
363void KDirModelPrivate::_k_slotNewItems(const KUrl& directoryUrl, const KFileItemList& items)
364{
365 //kDebug(7008) << "directoryUrl=" << directoryUrl;
366
367 KDirModelNode* result = nodeForUrl(directoryUrl); // O(depth)
368 // If the directory containing the items wasn't found, then we have a big problem.
369 // Are you calling KDirLister::openUrl(url,true,false)? Please use expandToUrl() instead.
370 if (!result) {
371 kError(7008) << "Items emitted in directory" << directoryUrl
372 << "but that directory isn't in KDirModel!"
373 << "Root directory:" << urlForNode(m_rootNode);
374 Q_FOREACH(const KFileItem& item, items) {
375 kDebug() << "Item:" << item.url();
376 }
377#ifndef NDEBUG
378 dump();
379#endif
380 Q_ASSERT(result);
381 }
382 Q_ASSERT(isDir(result));
383 KDirModelDirNode* dirNode = static_cast<KDirModelDirNode *>(result);
384
385 const QModelIndex index = indexForNode(dirNode); // O(n)
386 const int newItemsCount = items.count();
387 const int newRowCount = dirNode->m_childNodes.count() + newItemsCount;
388#if 0
389#ifndef NDEBUG // debugIndex only defined in debug mode
390 kDebug(7008) << items.count() << "in" << directoryUrl
391 << "index=" << debugIndex(index) << "newRowCount=" << newRowCount;
392#endif
393#endif
394
395 q->beginInsertRows( index, newRowCount - newItemsCount, newRowCount - 1 ); // parent, first, last
396
397 const KUrl::List urlsBeingFetched = m_urlsBeingFetched.value(dirNode);
398 //kDebug(7008) << "urlsBeingFetched for dir" << dirNode << directoryUrl << ":" << urlsBeingFetched;
399
400 QList<QModelIndex> emitExpandFor;
401
402 KFileItemList::const_iterator it = items.begin();
403 KFileItemList::const_iterator end = items.end();
404 for ( ; it != end ; ++it ) {
405 const bool isDir = it->isDir();
406 KDirModelNode* node = isDir
407 ? new KDirModelDirNode( dirNode, *it )
408 : new KDirModelNode( dirNode, *it );
409#ifndef NDEBUG
410 // Test code for possible duplication of items in the childnodes list,
411 // not sure if/how it ever happened.
412 //if (dirNode->m_childNodes.count() &&
413 // dirNode->m_childNodes.last()->item().name() == (*it).name())
414 // kFatal() << "Already having" << (*it).name() << "in" << directoryUrl
415 // << "url=" << dirNode->m_childNodes.last()->item().url();
416#endif
417 dirNode->m_childNodes.append(node);
418 const KUrl url = it->url();
419 m_nodeHash.insert(cleanupUrl(url), node);
420 //kDebug(7008) << url;
421
422 if (!urlsBeingFetched.isEmpty()) {
423 const KUrl dirUrl = url;
424 foreach(const KUrl& urlFetched, urlsBeingFetched) {
425 if (dirUrl.isParentOf(urlFetched)) {
426 kDebug(7008) << "Listing found" << dirUrl << "which is a parent of fetched url" << urlFetched;
427 const QModelIndex parentIndex = indexForNode(node, dirNode->m_childNodes.count()-1);
428 Q_ASSERT(parentIndex.isValid());
429 emitExpandFor.append(parentIndex);
430 if (isDir && dirUrl != urlFetched) {
431 q->fetchMore(parentIndex);
432 m_urlsBeingFetched[node].append(urlFetched);
433 }
434 }
435 }
436 }
437 }
438
439 m_urlsBeingFetched.remove(dirNode);
440
441 q->endInsertRows();
442
443 // Emit expand signal after rowsInserted signal has been emitted,
444 // so that any proxy model will have updated its mapping already
445 Q_FOREACH(const QModelIndex& idx, emitExpandFor) {
446 emit q->expand(idx);
447 }
448}
449
450void KDirModelPrivate::_k_slotDeleteItems(const KFileItemList& items)
451{
452 //kDebug(7008) << items.count();
453
454 // I assume all items are from the same directory.
455 // From KDirLister's code, this should be the case, except maybe emitChanges?
456 const KFileItem item = items.first();
457 Q_ASSERT(!item.isNull());
458 KUrl url = item.url();
459 KDirModelNode* node = nodeForUrl(url); // O(depth)
460 if (!node) {
461 kWarning(7008) << "No node found for item that was just removed:" << url;
462 return;
463 }
464
465 KDirModelDirNode* dirNode = node->parent();
466 if (!dirNode)
467 return;
468
469 QModelIndex parentIndex = indexForNode(dirNode); // O(n)
470
471 // Short path for deleting a single item
472 if (items.count() == 1) {
473 const int r = node->rowNumber();
474 q->beginRemoveRows(parentIndex, r, r);
475 removeFromNodeHash(node, url);
476 delete dirNode->m_childNodes.takeAt(r);
477 q->endRemoveRows();
478 return;
479 }
480
481 // We need to make lists of consecutive row numbers, for the beginRemoveRows call.
482 // Let's use a bit array where each bit represents a given child node.
483 const int childCount = dirNode->m_childNodes.count();
484 QBitArray rowNumbers(childCount, false);
485 Q_FOREACH(const KFileItem& item, items) {
486 if (!node) { // don't lookup the first item twice
487 url = item.url();
488 node = nodeForUrl(url);
489 if (!node) {
490 kWarning(7008) << "No node found for item that was just removed:" << url;
491 continue;
492 }
493 if (!node->parent()) {
494 // The root node has been deleted, but it was not first in the list 'items'.
495 // see https://bugs.kde.org/show_bug.cgi?id=196695
496 return;
497 }
498 }
499 rowNumbers.setBit(node->rowNumber(), 1); // O(n)
500 removeFromNodeHash(node, url);
501 node = 0;
502 }
503
504 int start = -1;
505 int end = -1;
506 bool lastVal = false;
507 // Start from the end, otherwise all the row numbers are offset while we go
508 for (int i = childCount - 1; i >= 0; --i) {
509 const bool val = rowNumbers.testBit(i);
510 if (!lastVal && val) {
511 end = i;
512 //kDebug(7008) << "end=" << end;
513 }
514 if ((lastVal && !val) || (i == 0 && val)) {
515 start = val ? i : i + 1;
516 //kDebug(7008) << "beginRemoveRows" << start << end;
517 q->beginRemoveRows(parentIndex, start, end);
518 for (int r = end; r >= start; --r) { // reverse because takeAt changes indexes ;)
519 //kDebug(7008) << "Removing from m_childNodes at" << r;
520 delete dirNode->m_childNodes.takeAt(r);
521 }
522 q->endRemoveRows();
523 }
524 lastVal = val;
525 }
526}
527
528void KDirModelPrivate::_k_slotRefreshItems(const QList<QPair<KFileItem, KFileItem> >& items)
529{
530 QModelIndex topLeft, bottomRight;
531
532 // Solution 1: we could emit dataChanged for one row (if items.size()==1) or all rows
533 // Solution 2: more fine-grained, actually figure out the beginning and end rows.
534 for ( QList<QPair<KFileItem, KFileItem> >::const_iterator fit = items.begin(), fend = items.end() ; fit != fend ; ++fit ) {
535 Q_ASSERT(!fit->first.isNull());
536 Q_ASSERT(!fit->second.isNull());
537 const KUrl oldUrl = fit->first.url();
538 const KUrl newUrl = fit->second.url();
539 KDirModelNode* node = nodeForUrl(oldUrl); // O(n); maybe we could look up to the parent only once
540 //kDebug(7008) << "in model for" << m_dirLister->url() << ":" << oldUrl << "->" << newUrl << "node=" << node;
541 if (!node) // not found [can happen when renaming a dir, redirection was emitted already]
542 continue;
543 if (node != m_rootNode) { // we never set an item in the rootnode, we use m_dirLister->rootItem instead.
544 bool hasNewNode = false;
545 // A file became directory (well, it was overwritten)
546 if (fit->first.isDir() != fit->second.isDir()) {
547 //kDebug(7008) << "DIR/FILE STATUS CHANGE";
548 const int r = node->rowNumber();
549 removeFromNodeHash(node, oldUrl);
550 KDirModelDirNode* dirNode = node->parent();
551 delete dirNode->m_childNodes.takeAt(r); // i.e. "delete node"
552 node = fit->second.isDir() ? new KDirModelDirNode(dirNode, fit->second)
553 : new KDirModelNode(dirNode, fit->second);
554 dirNode->m_childNodes.insert(r, node); // same position!
555 hasNewNode = true;
556 } else {
557 node->setItem(fit->second);
558 }
559
560 if (oldUrl != newUrl || hasNewNode) {
561 // What if a renamed dir had children? -> kdirlister takes care of emitting for each item
562 //kDebug(7008) << "Renaming" << oldUrl << "to" << newUrl << "in node hash";
563 m_nodeHash.remove(cleanupUrl(oldUrl));
564 m_nodeHash.insert(cleanupUrl(newUrl), node);
565 }
566 // Mimetype changed -> forget cached icon (e.g. from "cut", #164185 comment #13)
567 if (fit->first.mimeTypePtr()->name() != fit->second.mimeTypePtr()->name()) {
568 node->setPreview(QIcon());
569 }
570
571 const QModelIndex index = indexForNode(node);
572 if (!topLeft.isValid() || index.row() < topLeft.row()) {
573 topLeft = index;
574 }
575 if (!bottomRight.isValid() || index.row() > bottomRight.row()) {
576 bottomRight = index;
577 }
578 }
579 }
580#ifndef NDEBUG // debugIndex only defined in debug mode
581 kDebug(7008) << "dataChanged(" << debugIndex(topLeft) << " - " << debugIndex(bottomRight);
582#endif
583 bottomRight = bottomRight.sibling(bottomRight.row(), q->columnCount(QModelIndex())-1);
584 emit q->dataChanged(topLeft, bottomRight);
585}
586
587// Called when a kioslave redirects (e.g. smb:/Workgroup -> smb://workgroup)
588// and when renaming a directory.
589void KDirModelPrivate::_k_slotRedirection(const KUrl& oldUrl, const KUrl& newUrl)
590{
591 KDirModelNode* node = nodeForUrl(oldUrl);
592 if (!node)
593 return;
594 m_nodeHash.remove(cleanupUrl(oldUrl));
595 m_nodeHash.insert(cleanupUrl(newUrl), node);
596
597 // Ensure the node's URL is updated. In case of a listjob redirection
598 // we won't get a refreshItem, and in case of renaming a directory
599 // we'll get it too late (so the hash won't find the old url anymore).
600 KFileItem item = node->item();
601 if (!item.isNull()) { // null if root item, #180156
602 item.setUrl(newUrl);
603 node->setItem(item);
604 }
605
606 // The items inside the renamed directory have been handled before,
607 // KDirLister took care of emitting refreshItem for each of them.
608}
609
610void KDirModelPrivate::_k_slotClear()
611{
612 const int numRows = m_rootNode->m_childNodes.count();
613 if (numRows > 0) {
614 q->beginRemoveRows( QModelIndex(), 0, numRows - 1 );
615 q->endRemoveRows();
616 }
617
618 m_nodeHash.clear();
619 //emit layoutAboutToBeChanged();
620 clear();
621 //emit layoutChanged();
622}
623
624void KDirModelPrivate::_k_slotJobUrlsChanged(const QStringList& urlList)
625{
626 m_allCurrentDestUrls = urlList;
627}
628
629void KDirModel::itemChanged( const QModelIndex& index )
630{
631 // This method is really a itemMimeTypeChanged(), it's mostly called by KMimeTypeResolver.
632 // When the mimetype is determined, clear the old "preview" (could be
633 // mimetype dependent like when cutting files, #164185)
634 KDirModelNode* node = d->nodeForIndex(index);
635 if (node)
636 node->setPreview(QIcon());
637
638#ifndef NDEBUG // debugIndex only defined in debug mode
639 //kDebug(7008) << "dataChanged(" << debugIndex(index);
640#endif
641 emit dataChanged(index, index);
642}
643
644int KDirModel::columnCount( const QModelIndex & ) const
645{
646 return ColumnCount;
647}
648
649QVariant KDirModel::data( const QModelIndex & index, int role ) const
650{
651 if (index.isValid()) {
652 KDirModelNode* node = static_cast<KDirModelNode*>(index.internalPointer());
653 const KFileItem& item( node->item() );
654 switch (role) {
655 case Qt::DisplayRole:
656 switch (index.column()) {
657 case Name:
658 return item.text();
659 case Size:
660 //
661 //return KIO::convertSize(item->size());
662 // Default to "file size in bytes" like in kde3's filedialog
663 return KGlobal::locale()->formatNumber(item.size(), 0);
664 case ModifiedTime: {
665 KDateTime dt = item.time(KFileItem::ModificationTime);
666 return KGlobal::locale()->formatDateTime(dt);
667 }
668 case Permissions:
669 return item.permissionsString();
670 case Owner:
671 return item.user();
672 case Group:
673 return item.group();
674 case Type:
675 return item.mimeComment();
676 }
677 break;
678 case Qt::EditRole:
679 switch (index.column()) {
680 case Name:
681 return item.text();
682 }
683 break;
684 case Qt::DecorationRole:
685 if (index.column() == Name) {
686 if (!node->preview().isNull()) {
687 //kDebug(7008) << item->url() << " preview found";
688 return node->preview();
689 }
690 Q_ASSERT(!item.isNull());
691 //kDebug(7008) << item->url() << " overlays=" << item->overlays();
692 return KIcon(item.iconName(), 0, item.overlays());
693 }
694 break;
695 case Qt::TextAlignmentRole:
696 if (index.column() == Size) {
697 // use a right alignment for L2R and R2L languages
698 const Qt::Alignment alignment = Qt::AlignRight | Qt::AlignVCenter;
699 return int(alignment);
700 }
701 break;
702 case Qt::ToolTipRole:
703 return item.text();
704 case FileItemRole:
705 return QVariant::fromValue(item);
706 case ChildCountRole:
707 if (!item.isDir())
708 return ChildCountUnknown;
709 else {
710 KDirModelDirNode* dirNode = static_cast<KDirModelDirNode *>(node);
711 int count = dirNode->childCount();
712 if (count == ChildCountUnknown && item.isReadable() && !dirNode->isSlow()) {
713 const QString path = item.localPath();
714 if (!path.isEmpty()) {
715// slow
716// QDir dir(path);
717// count = dir.entryList(QDir::AllEntries|QDir::NoDotAndDotDot|QDir::System).count();
718#ifdef Q_WS_WIN
719 QString s = path + QLatin1String( "\\*.*" );
720 s.replace('/', '\\');
721 count = 0;
722 WIN32_FIND_DATA findData;
723 HANDLE hFile = FindFirstFile( (LPWSTR)s.utf16(), &findData );
724 if( hFile != INVALID_HANDLE_VALUE ) {
725 do {
726 if (!( findData.cFileName[0] == '.' &&
727 findData.cFileName[1] == '\0' ) &&
728 !( findData.cFileName[0] == '.' &&
729 findData.cFileName[1] == '.' &&
730 findData.cFileName[2] == '\0' ) )
731 ++count;
732 } while( FindNextFile( hFile, &findData ) != 0 );
733 FindClose( hFile );
734 }
735#else
736 DIR* dir = ::opendir(QFile::encodeName(path));
737 if (dir) {
738 count = 0;
739 struct dirent *dirEntry = 0;
740 while ((dirEntry = ::readdir(dir))) {
741 if (dirEntry->d_name[0] == '.') {
742 if (dirEntry->d_name[1] == '\0') // skip "."
743 continue;
744 if (dirEntry->d_name[1] == '.' && dirEntry->d_name[2] == '\0') // skip ".."
745 continue;
746 }
747 ++count;
748 }
749 ::closedir(dir);
750 }
751#endif
752 //kDebug(7008) << "child count for " << path << ":" << count;
753 dirNode->setChildCount(count);
754 }
755 }
756 return count;
757 }
758 case HasJobRole:
759 if (d->m_jobTransfersVisible && d->m_allCurrentDestUrls.isEmpty() == false) {
760 KDirModelNode* node = d->nodeForIndex(index);
761 const QString url = node->item().url().url();
762 //return whether or not there are job dest urls visible in the view, so the delegate knows which ones to paint.
763 return QVariant(d->m_allCurrentDestUrls.contains(url));
764 }
765 }
766 }
767 return QVariant();
768}
769
770void KDirModel::sort( int column, Qt::SortOrder order )
771{
772 // Not implemented - we should probably use QSortFilterProxyModel instead.
773 return QAbstractItemModel::sort(column, order);
774}
775
776bool KDirModel::setData( const QModelIndex & index, const QVariant & value, int role )
777{
778 switch (role) {
779 case Qt::EditRole:
780 if (index.column() == Name && value.type() == QVariant::String) {
781 Q_ASSERT(index.isValid());
782 KDirModelNode* node = static_cast<KDirModelNode*>(index.internalPointer());
783 const KFileItem& item = node->item();
784 const QString newName = value.toString();
785 if (newName.isEmpty() || newName == item.text() || (newName == QLatin1String(".")) || (newName == QLatin1String("..")))
786 return true;
787 KUrl newurl(item.url());
788 newurl.setPath(newurl.directory(KUrl::AppendTrailingSlash) + KIO::encodeFileName(newName));
789 KIO::Job * job = KIO::moveAs(item.url(), newurl, newurl.isLocalFile() ? KIO::HideProgressInfo : KIO::DefaultFlags);
790 job->ui()->setAutoErrorHandlingEnabled(true);
791 // undo handling
792 KIO::FileUndoManager::self()->recordJob( KIO::FileUndoManager::Rename, item.url(), newurl, job );
793 return true;
794 }
795 break;
796 case Qt::DecorationRole:
797 if (index.column() == Name) {
798 Q_ASSERT(index.isValid());
799 // Set new pixmap - e.g. preview
800 KDirModelNode* node = static_cast<KDirModelNode*>(index.internalPointer());
801 //kDebug(7008) << "setting icon for " << node->item()->url();
802 Q_ASSERT(node);
803 if (value.type() == QVariant::Icon) {
804 const QIcon icon(qvariant_cast<QIcon>(value));
805 node->setPreview(icon);
806 } else if (value.type() == QVariant::Pixmap) {
807 node->setPreview(qvariant_cast<QPixmap>(value));
808 }
809 emit dataChanged(index, index);
810 return true;
811 }
812 break;
813 default:
814 break;
815 }
816 return false;
817}
818
819int KDirModel::rowCount( const QModelIndex & parent ) const
820{
821 KDirModelNode* node = d->nodeForIndex(parent);
822 if (!node || !d->isDir(node)) // #176555
823 return 0;
824
825 KDirModelDirNode* parentNode = static_cast<KDirModelDirNode *>(node);
826 Q_ASSERT(parentNode);
827 const int count = parentNode->m_childNodes.count();
828#if 0
829 QStringList filenames;
830 for (int i = 0; i < count; ++i) {
831 filenames << d->urlForNode(parentNode->m_childNodes.at(i)).fileName();
832 }
833 kDebug(7008) << "rowCount for " << d->urlForNode(parentNode) << ": " << count << filenames;
834#endif
835 return count;
836}
837
838// sibling() calls parent() and isn't virtual! So parent() should be fast...
839QModelIndex KDirModel::parent( const QModelIndex & index ) const
840{
841 if (!index.isValid())
842 return QModelIndex();
843 KDirModelNode* childNode = static_cast<KDirModelNode*>(index.internalPointer());
844 Q_ASSERT(childNode);
845 KDirModelNode* parentNode = childNode->parent();
846 Q_ASSERT(parentNode);
847 return d->indexForNode(parentNode); // O(n)
848}
849
850static bool lessThan(const KUrl &left, const KUrl &right)
851{
852 return left.url().compare(right.url()) < 0;
853}
854
855void KDirModel::requestSequenceIcon(const QModelIndex& index, int sequenceIndex)
856{
857 emit needSequenceIcon(index, sequenceIndex);
858}
859
860void KDirModel::setJobTransfersVisible(bool value)
861{
862 if(value) {
863 d->m_jobTransfersVisible = true;
864 connect(&JobUrlCache::instance(), SIGNAL(jobUrlsChanged(QStringList)), this, SLOT(_k_slotJobUrlsChanged(QStringList)), Qt::UniqueConnection);
865
866 JobUrlCache::instance().requestJobUrlsChanged();
867 } else {
868 disconnect(this, SLOT(_k_slotJobUrlsChanged(QStringList)));
869 }
870
871}
872
873bool KDirModel::jobTransfersVisible() const
874{
875 return d->m_jobTransfersVisible;
876}
877
878KUrl::List KDirModel::simplifiedUrlList(const KUrl::List &urls)
879{
880 if (!urls.count()) {
881 return urls;
882 }
883
884 KUrl::List ret(urls);
885 qSort(ret.begin(), ret.end(), lessThan);
886
887 KUrl::List::iterator it = ret.begin();
888 KUrl url = *it;
889 ++it;
890 while (it != ret.end()) {
891 if (url.isParentOf(*it)) {
892 it = ret.erase(it);
893 } else {
894 url = *it;
895 ++it;
896 }
897 }
898
899 return ret;
900}
901
902QStringList KDirModel::mimeTypes( ) const
903{
904 return KUrl::List::mimeDataTypes();
905}
906
907QMimeData * KDirModel::mimeData( const QModelIndexList & indexes ) const
908{
909 KUrl::List urls, mostLocalUrls;
910 bool canUseMostLocalUrls = true;
911 foreach (const QModelIndex &index, indexes) {
912 const KFileItem& item = d->nodeForIndex(index)->item();
913 urls << item.url();
914 bool isLocal;
915 mostLocalUrls << item.mostLocalUrl(isLocal);
916 if (!isLocal)
917 canUseMostLocalUrls = false;
918 }
919 QMimeData *data = new QMimeData();
920 const bool different = canUseMostLocalUrls && (mostLocalUrls != urls);
921 urls = simplifiedUrlList(urls);
922 if (different) {
923 mostLocalUrls = simplifiedUrlList(mostLocalUrls);
924 urls.populateMimeData(mostLocalUrls, data);
925 } else {
926 urls.populateMimeData(data);
927 }
928
929 // for compatibility reasons (when dropping or pasting into kde3 applications)
930 QString application_x_qiconlist;
931 const int items = urls.count();
932 for (int i = 0; i < items; i++) {
933 const int offset = i*16;
934 QString tmp("%1$@@$%2$@@$32$@@$32$@@$%3$@@$%4$@@$32$@@$16$@@$no data$@@$");
935 application_x_qiconlist += tmp.arg(offset).arg(offset).arg(offset).arg(offset+40);
936 }
937 data->setData("application/x-qiconlist", application_x_qiconlist.toLatin1());
938
939 return data;
940}
941
942// Public API; not much point in calling it internally
943KFileItem KDirModel::itemForIndex( const QModelIndex& index ) const
944{
945 if (!index.isValid()) {
946 return d->m_dirLister->rootItem();
947 } else {
948 return static_cast<KDirModelNode*>(index.internalPointer())->item();
949 }
950}
951
952#ifndef KDE_NO_DEPRECATED
953QModelIndex KDirModel::indexForItem( const KFileItem* item ) const
954{
955 // Note that we can only use the URL here, not the pointer.
956 // KFileItems can be copied.
957 return indexForUrl(item->url()); // O(n)
958}
959#endif
960
961QModelIndex KDirModel::indexForItem( const KFileItem& item ) const
962{
963 // Note that we can only use the URL here, not the pointer.
964 // KFileItems can be copied.
965 return indexForUrl(item.url()); // O(n)
966}
967
968// url -> index. O(n)
969QModelIndex KDirModel::indexForUrl(const KUrl& url) const
970{
971 KDirModelNode* node = d->nodeForUrl(url); // O(depth)
972 if (!node) {
973 kDebug(7007) << url << "not found";
974 return QModelIndex();
975 }
976 return d->indexForNode(node); // O(n)
977}
978
979QModelIndex KDirModel::index( int row, int column, const QModelIndex & parent ) const
980{
981 KDirModelNode* parentNode = d->nodeForIndex(parent); // O(1)
982 Q_ASSERT(parentNode);
983 Q_ASSERT(d->isDir(parentNode));
984 KDirModelNode* childNode = static_cast<KDirModelDirNode *>(parentNode)->m_childNodes.value(row); // O(1)
985 if (childNode)
986 return createIndex(row, column, childNode);
987 else
988 return QModelIndex();
989}
990
991QVariant KDirModel::headerData( int section, Qt::Orientation orientation, int role ) const
992{
993 if (orientation == Qt::Horizontal) {
994 switch (role) {
995 case Qt::DisplayRole:
996 switch (section) {
997 case Name:
998 return i18nc("@title:column","Name");
999 case Size:
1000 return i18nc("@title:column","Size");
1001 case ModifiedTime:
1002 return i18nc("@title:column","Date");
1003 case Permissions:
1004 return i18nc("@title:column","Permissions");
1005 case Owner:
1006 return i18nc("@title:column","Owner");
1007 case Group:
1008 return i18nc("@title:column","Group");
1009 case Type:
1010 return i18nc("@title:column","Type");
1011 }
1012 }
1013 }
1014 return QVariant();
1015}
1016
1017bool KDirModel::hasChildren( const QModelIndex & parent ) const
1018{
1019 if (!parent.isValid())
1020 return true;
1021
1022 const KFileItem& parentItem = static_cast<KDirModelNode*>(parent.internalPointer())->item();
1023 Q_ASSERT(!parentItem.isNull());
1024 return parentItem.isDir();
1025}
1026
1027Qt::ItemFlags KDirModel::flags( const QModelIndex & index ) const
1028{
1029 Qt::ItemFlags f = Qt::ItemIsEnabled;
1030 if (index.column() == Name) {
1031 f |= Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled;
1032 }
1033
1034 // Allow dropping onto this item?
1035 if (d->m_dropsAllowed != NoDrops) {
1036 if(!index.isValid()) {
1037 if (d->m_dropsAllowed & DropOnDirectory) {
1038 f |= Qt::ItemIsDropEnabled;
1039 }
1040 } else {
1041 KFileItem item = itemForIndex(index);
1042 if (item.isNull()) {
1043 kWarning(7007) << "Invalid item returned for index";
1044 } else if (item.isDir()) {
1045 if (d->m_dropsAllowed & DropOnDirectory) {
1046 f |= Qt::ItemIsDropEnabled;
1047 }
1048 } else { // regular file item
1049 if (d->m_dropsAllowed & DropOnAnyFile)
1050 f |= Qt::ItemIsDropEnabled;
1051 else if (d->m_dropsAllowed & DropOnLocalExecutable) {
1052 if (!item.localPath().isEmpty()) {
1053 // Desktop file?
1054 if (item.mimeTypePtr()->is("application/x-desktop"))
1055 f |= Qt::ItemIsDropEnabled;
1056 // Executable, shell script ... ?
1057 else if ( QFileInfo( item.localPath() ).isExecutable() )
1058 f |= Qt::ItemIsDropEnabled;
1059 }
1060 }
1061 }
1062 }
1063 }
1064
1065 return f;
1066}
1067
1068bool KDirModel::canFetchMore( const QModelIndex & parent ) const
1069{
1070 if (!parent.isValid())
1071 return false;
1072
1073 // We now have a bool KDirModelNode::m_populated,
1074 // to avoid calling fetchMore more than once on empty dirs.
1075 // But this wastes memory, and how often does someone open and re-open an empty dir in a treeview?
1076 // Maybe we can ask KDirLister "have you listed <url> already"? (to discuss with M. Brade)
1077
1078 KDirModelNode* node = static_cast<KDirModelNode*>(parent.internalPointer());
1079 const KFileItem& item = node->item();
1080 return item.isDir() && !static_cast<KDirModelDirNode *>(node)->isPopulated()
1081 && static_cast<KDirModelDirNode *>(node)->m_childNodes.isEmpty();
1082}
1083
1084void KDirModel::fetchMore( const QModelIndex & parent )
1085{
1086 if (!parent.isValid())
1087 return;
1088
1089 KDirModelNode* parentNode = static_cast<KDirModelNode*>(parent.internalPointer());
1090
1091 KFileItem parentItem = parentNode->item();
1092 Q_ASSERT(!parentItem.isNull());
1093 Q_ASSERT(parentItem.isDir());
1094 KDirModelDirNode* dirNode = static_cast<KDirModelDirNode *>(parentNode);
1095 if( dirNode->isPopulated() )
1096 return;
1097 dirNode->setPopulated( true );
1098
1099 const KUrl parentUrl = parentItem.url();
1100 d->m_dirLister->openUrl(parentUrl, KDirLister::Keep);
1101}
1102
1103bool KDirModel::dropMimeData( const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent )
1104{
1105 // Not sure we want to implement any drop handling at this level,
1106 // but for sure the default QAbstractItemModel implementation makes no sense for a dir model.
1107 Q_UNUSED(data);
1108 Q_UNUSED(action);
1109 Q_UNUSED(row);
1110 Q_UNUSED(column);
1111 Q_UNUSED(parent);
1112 return false;
1113}
1114
1115void KDirModel::setDropsAllowed(DropsAllowed dropsAllowed)
1116{
1117 d->m_dropsAllowed = dropsAllowed;
1118}
1119
1120void KDirModel::expandToUrl(const KUrl& url)
1121{
1122 // emit expand for each parent and return last parent
1123 KDirModelNode* result = d->expandAllParentsUntil(url); // O(depth)
1124 //kDebug(7008) << url << result;
1125
1126 if (!result) // doesn't seem related to our base url?
1127 return;
1128 if (!(result->item().isNull()) && result->item().url() == url) {
1129 // We have it already, nothing to do
1130 kDebug(7008) << "have it already item=" <<url /*result->item()*/;
1131 return;
1132 }
1133
1134 d->m_urlsBeingFetched[result].append(url);
1135
1136 if (result == d->m_rootNode) {
1137 kDebug(7008) << "Remembering to emit expand after listing the root url";
1138 // the root is fetched by default, so it must be currently being fetched
1139 return;
1140 }
1141
1142 kDebug(7008) << "Remembering to emit expand after listing" << result->item().url();
1143
1144 // start a new fetch to look for the next level down the URL
1145 const QModelIndex parentIndex = d->indexForNode(result); // O(n)
1146 Q_ASSERT(parentIndex.isValid());
1147 fetchMore(parentIndex);
1148}
1149
1150bool KDirModel::insertRows(int , int, const QModelIndex&)
1151{
1152 return false;
1153}
1154
1155bool KDirModel::insertColumns(int, int, const QModelIndex&)
1156{
1157 return false;
1158}
1159
1160bool KDirModel::removeRows(int, int, const QModelIndex&)
1161{
1162 return false;
1163}
1164
1165bool KDirModel::removeColumns(int, int, const QModelIndex&)
1166{
1167 return false;
1168}
1169
1170#include "kdirmodel.moc"
JobUrlCache::requestJobUrlsChanged
void requestJobUrlsChanged()
Definition: joburlcache.cpp:62
JobUrlCache::instance
static JobUrlCache & instance()
Definition: joburlcache.cpp:34
KDateTime
KDirLister
Helper class for the kiojob used to list and update a directory.
Definition: kdirlister.h:58
KDirLister::Keep
@ Keep
Previous directories aren't forgotten (they are still watched by kdirwatch and their items are kept f...
Definition: kdirlister.h:76
KDirModel
A model for a KIO-based directory tree.
Definition: kdirmodel.h:49
KDirModel::itemChanged
void itemChanged(const QModelIndex &index)
Notify the model that the item at this index has changed.
Definition: kdirmodel.cpp:629
KDirModel::indexForUrl
QModelIndex indexForUrl(const KUrl &url) const
Return the index for a given url.
Definition: kdirmodel.cpp:969
KDirModel::DropOnDirectory
@ DropOnDirectory
allow drops on any directory
Definition: kdirmodel.h:144
KDirModel::NoDrops
@ NoDrops
Definition: kdirmodel.h:143
KDirModel::DropOnAnyFile
@ DropOnAnyFile
allow drops on any file
Definition: kdirmodel.h:145
KDirModel::DropOnLocalExecutable
@ DropOnLocalExecutable
allow drops on local executables, shell scripts and desktop files. Can be used with DropOnDirectory.
Definition: kdirmodel.h:146
KDirModel::sort
virtual void sort(int column, Qt::SortOrder order=Qt::AscendingOrder)
Reimplemented from QAbstractItemModel. Not implemented.
Definition: kdirmodel.cpp:770
KDirModel::fetchMore
virtual void fetchMore(const QModelIndex &parent)
Reimplemented from QAbstractItemModel. Lists the subdirectory.
Definition: kdirmodel.cpp:1084
KDirModel::ChildCountUnknown
@ ChildCountUnknown
Definition: kdirmodel.h:132
KDirModel::mimeTypes
virtual QStringList mimeTypes() const
Reimplemented from QAbstractItemModel.
Definition: kdirmodel.cpp:902
KDirModel::setJobTransfersVisible
void setJobTransfersVisible(bool value)
Enable/Disable the displaying of an animated overlay that is shown for any destination urls (in the v...
Definition: kdirmodel.cpp:860
KDirModel::index
virtual QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const
Reimplemented from QAbstractItemModel. O(1)
Definition: kdirmodel.cpp:979
KDirModel::FileItemRole
@ FileItemRole
returns the KFileItem for a given index
Definition: kdirmodel.h:137
KDirModel::ChildCountRole
@ ChildCountRole
returns the number of items in a directory, or ChildCountUnknown
Definition: kdirmodel.h:138
KDirModel::HasJobRole
@ HasJobRole
returns whether or not there is a job on an item (file/directory)
Definition: kdirmodel.h:139
KDirModel::flags
virtual Qt::ItemFlags flags(const QModelIndex &index) const
Reimplemented from QAbstractItemModel.
Definition: kdirmodel.cpp:1027
KDirModel::KDirModel
KDirModel(QObject *parent=0)
Definition: kdirmodel.cpp:326
KDirModel::setData
virtual bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole)
Reimplemented from QAbstractItemModel.
Definition: kdirmodel.cpp:776
KDirModel::expandToUrl
void expandToUrl(const KUrl &url)
Lists subdirectories using fetchMore() as needed until the given url exists in the model.
Definition: kdirmodel.cpp:1120
KDirModel::needSequenceIcon
void needSequenceIcon(const QModelIndex &index, int sequenceIndex)
Emitted when another icon sequence index is requested.
KDirModel::columnCount
virtual int columnCount(const QModelIndex &parent=QModelIndex()) const
Reimplemented from QAbstractItemModel. Returns ColumnCount.
Definition: kdirmodel.cpp:644
KDirModel::dirLister
KDirLister * dirLister() const
Return the directory lister used by this model.
Definition: kdirmodel.cpp:358
KDirModel::hasChildren
virtual bool hasChildren(const QModelIndex &parent=QModelIndex()) const
Reimplemented from QAbstractItemModel. Returns true for directories.
Definition: kdirmodel.cpp:1017
KDirModel::jobTransfersVisible
bool jobTransfersVisible() const
Returns whether or not displaying job transfers has been enabled.
Definition: kdirmodel.cpp:873
KDirModel::setDirLister
void setDirLister(KDirLister *dirLister)
Set the directory lister to use by this model, instead of the default KDirLister created internally.
Definition: kdirmodel.cpp:338
KDirModel::setDropsAllowed
void setDropsAllowed(DropsAllowed dropsAllowed)
Set whether dropping onto items should be allowed, and for which kind of item Drops are disabled by d...
Definition: kdirmodel.cpp:1115
KDirModel::simplifiedUrlList
static KUrl::List simplifiedUrlList(const KUrl::List &urls)
Remove urls from the list if an ancestor is present on the list.
Definition: kdirmodel.cpp:878
KDirModel::itemForIndex
KFileItem itemForIndex(const QModelIndex &index) const
Return the fileitem for a given index.
Definition: kdirmodel.cpp:943
KDirModel::indexForItem
QModelIndex indexForItem(const KFileItem *) const
Return the index for a given kfileitem.
Definition: kdirmodel.cpp:953
KDirModel::parent
virtual QModelIndex parent(const QModelIndex &index) const
Reimplemented from QAbstractItemModel.
Definition: kdirmodel.cpp:839
KDirModel::canFetchMore
virtual bool canFetchMore(const QModelIndex &parent) const
Reimplemented from QAbstractItemModel. Returns true for empty directories.
Definition: kdirmodel.cpp:1068
KDirModel::headerData
virtual QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const
Reimplemented from QAbstractItemModel. Returns the column titles.
Definition: kdirmodel.cpp:991
KDirModel::Size
@ Size
Definition: kdirmodel.h:121
KDirModel::ColumnCount
@ ColumnCount
Definition: kdirmodel.h:127
KDirModel::ModifiedTime
@ ModifiedTime
Definition: kdirmodel.h:122
KDirModel::Permissions
@ Permissions
Definition: kdirmodel.h:123
KDirModel::Owner
@ Owner
Definition: kdirmodel.h:124
KDirModel::Name
@ Name
Definition: kdirmodel.h:120
KDirModel::Group
@ Group
Definition: kdirmodel.h:125
KDirModel::data
virtual QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const
Reimplemented from QAbstractItemModel.
Definition: kdirmodel.cpp:649
KDirModel::~KDirModel
~KDirModel()
Definition: kdirmodel.cpp:333
KDirModel::mimeData
virtual QMimeData * mimeData(const QModelIndexList &indexes) const
Reimplemented from QAbstractItemModel.
Definition: kdirmodel.cpp:907
KDirModel::rowCount
virtual int rowCount(const QModelIndex &parent=QModelIndex()) const
Reimplemented from QAbstractItemModel.
Definition: kdirmodel.cpp:819
KDirModel::requestSequenceIcon
void requestSequenceIcon(const QModelIndex &index, int sequenceIndex)
This emits the needSequenceIcon signal, requesting another sequence icon.
Definition: kdirmodel.cpp:855
KDirModel::dropMimeData
virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
Reimplemented from QAbstractItemModel. Not implemented yet.
Definition: kdirmodel.cpp:1103
KFileItemList
List of KFileItems, which adds a few helper methods to QList<KFileItem>.
Definition: kfileitem.h:675
KFileItem
A KFileItem is a generic class to handle a file, local or remote.
Definition: kfileitem.h:46
KFileItem::iconName
QString iconName() const
Returns the full path name to the icon that represents this mime type.
Definition: kfileitem.cpp:879
KFileItem::time
KDateTime time(FileTimes which) const
Requests the modification, access or creation time, depending on which.
Definition: kfileitem.cpp:655
KFileItem::setUrl
void setUrl(const KUrl &url)
Sets the item's URL.
Definition: kfileitem.cpp:543
KFileItem::mostLocalUrl
KUrl mostLocalUrl(bool &local) const
Tries to give a local URL for this file item if possible.
Definition: kfileitem.cpp:1470
KFileItem::user
QString user() const
Returns the owner of the file.
Definition: kfileitem.cpp:681
KFileItem::size
KIO::filesize_t size() const
Returns the size of the file, if known.
Definition: kfileitem.cpp:610
KFileItem::mimeTypePtr
KMimeType::Ptr mimeTypePtr() const
Returns the currently known mimetype of the file item.
Definition: kfileitem.cpp:1649
KFileItem::ModificationTime
@ ModificationTime
Definition: kfileitem.h:58
KFileItem::isReadable
bool isReadable() const
Checks whether the file or directory is readable.
Definition: kfileitem.cpp:1069
KFileItem::group
QString group() const
Returns the group of the file.
Definition: kfileitem.cpp:712
KFileItem::localPath
QString localPath() const
Returns the local path if isLocalFile() == true or the KIO item has a UDS_LOCAL_PATH atom.
Definition: kfileitem.cpp:602
KFileItem::isDir
bool isDir() const
Returns true if this item represents a directory.
Definition: kfileitem.cpp:1141
KFileItem::isNull
bool isNull() const
Return true if default-constructed.
Definition: kfileitem.cpp:1714
KFileItem::url
KUrl url() const
Returns the url of the file.
Definition: kfileitem.cpp:1543
KFileItem::text
QString text() const
Returns the text of the file item.
Definition: kfileitem.cpp:1583
KFileItem::permissionsString
QString permissionsString() const
Returns the access permissions for the file as a string.
Definition: kfileitem.cpp:1403
KFileItem::mimeComment
QString mimeComment() const
Returns the user-readable string representing the type of this file, like "OpenDocument Text File".
Definition: kfileitem.cpp:823
KFileItem::overlays
QStringList overlays() const
Returns the overlays (bitfield of KIconLoader::*Overlay flags) that are used for this item's pixmap.
Definition: kfileitem.cpp:952
KIO::FileUndoManager::self
static FileUndoManager * self()
Definition: fileundomanager.cpp:208
KIO::FileUndoManager::recordJob
void recordJob(CommandType op, const KUrl::List &src, const KUrl &dst, KIO::Job *job)
Record this job while it's happening and add a command for it so that the user can undo it.
Definition: fileundomanager.cpp:247
KIO::FileUndoManager::Rename
@ Rename
Definition: fileundomanager.h:135
KIO::Job
The base class for all jobs.
Definition: jobclasses.h:94
KIO::Job::ui
JobUiDelegate * ui() const
Retrieves the UI delegate of this job.
Definition: job.cpp:90
KIcon
KJobUiDelegate::setAutoErrorHandlingEnabled
void setAutoErrorHandlingEnabled(bool enable)
KLocale::formatNumber
QString formatNumber(const QString &numStr, bool round=true, int precision=-1) const
KLocale::formatDateTime
QString formatDateTime(const KDateTime &dateTime, DateFormat format=ShortDate, DateTimeFormatOptions options=0) const
KUrl::List
KUrl::List::mimeDataTypes
static QStringList mimeDataTypes()
KUrl::List::populateMimeData
void populateMimeData(const KUrl::List &mostLocalUrls, QMimeData *mimeData, const KUrl::MetaDataMap &metaData=MetaDataMap(), MimeDataFlags flags=DefaultMimeDataFlags) const
KUrl
KUrl::cleanPath
void cleanPath(const CleanPathOption &options=SimplifyDirSeparators)
KUrl::AppendTrailingSlash
AppendTrailingSlash
KUrl::RemoveTrailingSlash
RemoveTrailingSlash
KUrl::AddTrailingSlash
AddTrailingSlash
KUrl::adjustPath
void adjustPath(AdjustPathOption trailing)
KUrl::url
QString url(AdjustPathOption trailing=LeaveTrailingSlash) const
KUrl::path
QString path(AdjustPathOption trailing=LeaveTrailingSlash) const
KUrl::directory
QString directory(const DirectoryOptions &options=IgnoreTrailingSlash) const
KUrl::isLocalFile
bool isLocalFile() const
KUrl::setPath
void setPath(const QString &path)
KUrl::setQuery
void setQuery(const QString &query)
KUrl::setRef
void setRef(const QString &fragment)
KUrl::isParentOf
bool isParentOf(const KUrl &u) const
KUrl::protocol
QString protocol() const
QAbstractItemModel
QHash
QList
QMap
QObject
QPair
copyjob.h
f
static quint32 f(DES_KEY *key, quint32 r, char *subkey)
Definition: des.cpp:378
fileundomanager.h
kDebug
#define kDebug
kWarning
#define kWarning
jobuidelegate.h
joburlcache_p.h
lessThan
bool lessThan(const QString &left, const QString &right)
kdatetime.h
kdebug.h
kdirlister.h
lessThan
static bool lessThan(const KUrl &left, const KUrl &right)
Definition: kdirmodel.cpp:850
debugIndex
static QString debugIndex(const QModelIndex &index)
Definition: kdirmodel.cpp:310
cleanupUrl
static KUrl cleanupUrl(const KUrl &url)
Definition: kdirmodel.cpp:47
kdirmodel.h
kfileitem.h
kglobal.h
kicon.h
klocale.h
i18nc
QString i18nc(const char *ctxt, const char *text)
kurl.h
Type
Type
KGlobal::locale
KLocale * locale()
KIO::moveAs
CopyJob * moveAs(const KUrl &src, const KUrl &dest, JobFlags flags=DefaultFlags)
Moves a file or directory src to the given destination dest.
Definition: copyjob.cpp:2196
KIO::encodeFileName
QString encodeFileName(const QString &str)
Encodes (from the text displayed to the real filename) This translates '/' into a "unicode fraction s...
Definition: global.cpp:146
KIO::DefaultFlags
@ DefaultFlags
Show the progress info GUI, no Resume and no Overwrite.
Definition: jobclasses.h:46
KIO::HideProgressInfo
@ HideProgressInfo
Hide progress information dialog, i.e.
Definition: jobclasses.h:51
clear
KAction * clear(const QObject *recvr, const char *slot, QObject *parent)
end
const KShortcut & end()
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KIO

Skip menu "KIO"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal