00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "kdirmodel.h"
00021 #include "kdirlister.h"
00022 #include "kfileitem.h"
00023 #include <kdatetime.h>
00024 #include <kicon.h>
00025 #include <klocale.h>
00026 #include <kglobal.h>
00027 #include <kio/copyjob.h>
00028 #include <kio/jobuidelegate.h>
00029 #include <kurl.h>
00030 #include <kdebug.h>
00031 #include <QMimeData>
00032 #include <QFile>
00033 #include <QFileInfo>
00034 #include <QDir>
00035 #include <sys/types.h>
00036 #include <dirent.h>
00037
00038 class KDirModelNode;
00039 class KDirModelDirNode;
00040
00041
00042
00043 class KDirModelNode
00044 {
00045 public:
00046 KDirModelNode( KDirModelDirNode* parent, const KFileItem& item ) :
00047 m_item(item),
00048 m_parent(parent),
00049 m_preview()
00050 {
00051 }
00052
00053
00054
00055 const KFileItem& item() const { return m_item; }
00056 void setItem(const KFileItem& item) { m_item = item; }
00057 KDirModelDirNode* parent() const { return m_parent; }
00058
00059 int rowNumber() const;
00060 QIcon preview() const { return m_preview; }
00061 void addPreview( const QPixmap& pix ) { m_preview.addPixmap(pix); }
00062 void setPreview( const QIcon& icn ) { m_preview = icn; }
00063
00064 private:
00065 KFileItem m_item;
00066 KDirModelDirNode* const m_parent;
00067 QIcon m_preview;
00068 };
00069
00070
00071 class KDirModelDirNode : public KDirModelNode
00072 {
00073 public:
00074 KDirModelDirNode( KDirModelDirNode* parent, const KFileItem& item)
00075 : KDirModelNode( parent, item),
00076 m_childNodes(),
00077 m_childCount(KDirModel::ChildCountUnknown),
00078 m_populated(false)
00079 {}
00080 ~KDirModelDirNode() {
00081 qDeleteAll(m_childNodes);
00082 }
00083 QList<KDirModelNode *> m_childNodes;
00084
00085
00086 int childCount() const { return m_childNodes.isEmpty() ? m_childCount : m_childNodes.count(); }
00087 void setChildCount(int count) { m_childCount = count; }
00088 bool isPopulated() const { return m_populated; }
00089 void setPopulated( bool populated ) { m_populated = populated; }
00090
00091 private:
00092 int m_childCount:31;
00093 bool m_populated:1;
00094 };
00095
00096 int KDirModelNode::rowNumber() const
00097 {
00098 if (!m_parent) return 0;
00099 return m_parent->m_childNodes.indexOf(const_cast<KDirModelNode*>(this));
00100 }
00101
00103
00104 class KDirModelPrivate
00105 {
00106 public:
00107 KDirModelPrivate( KDirModel* model )
00108 : q(model), m_dirLister(0),
00109 m_rootNode(new KDirModelDirNode(0, KFileItem())),
00110 m_dropsAllowed(KDirModel::NoDrops)
00111 {
00112 }
00113 ~KDirModelPrivate() {
00114 delete m_rootNode;
00115 }
00116
00117 void _k_slotNewItems(const KFileItemList&);
00118 void _k_slotDeleteItem(const KFileItem&);
00119 void _k_slotRefreshItems(const QList<QPair<KFileItem, KFileItem> >&);
00120 void _k_slotClear();
00121
00122 void clear() {
00123 delete m_rootNode;
00124 m_rootNode = new KDirModelDirNode(0, KFileItem());
00125 }
00126
00127
00128
00129
00130
00131 QPair<int , KDirModelNode*> nodeForUrl(const KUrl& url, bool returnLastParent = false) const;
00132 KDirModelNode* nodeForIndex(const QModelIndex& index) const;
00133 QModelIndex indexForNode(KDirModelNode* node, int rowNumber = -1 ) const;
00134 bool isDir(KDirModelNode* node) const {
00135 return (node == m_rootNode) || node->item().isDir();
00136 }
00137
00138 KDirModel* q;
00139 KDirLister* m_dirLister;
00140 KDirModelDirNode* m_rootNode;
00141 KDirModel::DropsAllowed m_dropsAllowed;
00142
00143
00144 QMap<KDirModelNode*, KUrl::List> m_urlsBeingFetched;
00145 };
00146
00147
00148
00149
00150
00151 QPair<int , KDirModelNode*> KDirModelPrivate::nodeForUrl(const KUrl& _url, bool returnLastParent) const
00152 {
00153 KUrl url(_url);
00154 url.adjustPath(KUrl::RemoveTrailingSlash);
00155
00156
00157 KUrl nodeUrl = m_dirLister->url();
00158
00159
00160
00161
00162
00163 if (nodeUrl.path().isEmpty())
00164 nodeUrl.setPath("/");
00165
00166 if (url == nodeUrl)
00167 return qMakePair(0, static_cast<KDirModelNode *>(m_rootNode));
00168
00169 const QString pathStr = url.path();
00170 KDirModelDirNode* dirNode = m_rootNode;
00171
00172 if ( !pathStr.startsWith(nodeUrl.path()) ) {
00173 return qMakePair(0, static_cast<KDirModelNode*>(0));
00174 }
00175
00176 for (;;) {
00177 Q_ASSERT( pathStr.startsWith(nodeUrl.path()) );
00178 bool foundChild = false;
00179 QList<KDirModelNode *>::const_iterator it = dirNode->m_childNodes.begin();
00180 const QList<KDirModelNode *>::const_iterator end = dirNode->m_childNodes.end();
00181 int row = 0;
00182 for ( ; it != end ; ++it, ++row ) {
00183 const KUrl u = (*it)->item().url();
00184 if ( u == url ) {
00185
00186 return qMakePair(row, *it);
00187 }
00188
00189 if ( (url.protocol() == u.protocol()) && (pathStr.startsWith(u.path()+'/')) ) {
00190
00191 Q_ASSERT( isDir(*it) );
00192 dirNode = static_cast<KDirModelDirNode *>( *it );
00193 foundChild = true;
00194 break;
00195 }
00196 }
00197 if (!foundChild) {
00198
00199 if (returnLastParent)
00200 return qMakePair(-1 , static_cast<KDirModelNode*>(dirNode));
00201 else
00202 return qMakePair(0, static_cast<KDirModelNode*>(0));
00203 }
00204 nodeUrl = dirNode->item().url();
00205
00206 }
00207
00208
00209 }
00210
00211
00212 QModelIndex KDirModelPrivate::indexForNode(KDirModelNode* node, int rowNumber) const
00213 {
00214 if (node == m_rootNode)
00215 return QModelIndex();
00216
00217 Q_ASSERT(node->parent());
00218 return q->createIndex(rowNumber == -1 ? node->rowNumber() : rowNumber, 0, node);
00219 }
00220
00221
00222 KDirModelNode* KDirModelPrivate::nodeForIndex(const QModelIndex& index) const
00223 {
00224 return index.isValid()
00225 ? static_cast<KDirModelNode*>(index.internalPointer())
00226 : m_rootNode;
00227 }
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245 #ifndef NDEBUG
00246 static QString debugIndex(const QModelIndex& index)
00247 {
00248 QString str;
00249 if (!index.isValid())
00250 str = "[invalid index, i.e. root]";
00251 else {
00252 KDirModelNode* node = static_cast<KDirModelNode*>(index.internalPointer());
00253 str = "[index for " + node->item().url().pathOrUrl();
00254 if (index.column() > 0)
00255 str += ", column " + QString::number(index.column());
00256 str += ']';
00257 }
00258 return str;
00259 }
00260 #endif
00261
00262 KDirModel::KDirModel(QObject* parent)
00263 : QAbstractItemModel(parent),
00264 d(new KDirModelPrivate(this))
00265 {
00266 setDirLister(new KDirLister(this));
00267 }
00268
00269 KDirModel::~KDirModel()
00270 {
00271 delete d;
00272 }
00273
00274 void KDirModel::setDirLister(KDirLister* dirLister)
00275 {
00276 if (d->m_dirLister) {
00277 d->clear();
00278 delete d->m_dirLister;
00279 }
00280 d->m_dirLister = dirLister;
00281 d->m_dirLister->setParent(this);
00282 connect( d->m_dirLister, SIGNAL(newItems(KFileItemList)),
00283 this, SLOT(_k_slotNewItems(KFileItemList)) );
00284 connect( d->m_dirLister, SIGNAL(deleteItem(KFileItem)),
00285 this, SLOT(_k_slotDeleteItem(KFileItem)) );
00286 connect( d->m_dirLister, SIGNAL(refreshItems(QList<QPair<KFileItem, KFileItem> >)),
00287 this, SLOT(_k_slotRefreshItems(QList<QPair<KFileItem, KFileItem> >)) );
00288 connect( d->m_dirLister, SIGNAL(clear()),
00289 this, SLOT(_k_slotClear()) );
00290 }
00291
00292 KDirLister* KDirModel::dirLister() const
00293 {
00294 return d->m_dirLister;
00295 }
00296
00297 void KDirModelPrivate::_k_slotNewItems(const KFileItemList& items)
00298 {
00299
00300
00301
00302 KUrl dir( items.first().url().upUrl() );
00303 dir.adjustPath(KUrl::RemoveTrailingSlash);
00304
00305
00306
00307 const QPair<int, KDirModelNode*> result = nodeForUrl(dir);
00308 Q_ASSERT(result.second);
00309 Q_ASSERT(isDir(result.second));
00310 KDirModelDirNode* dirNode = static_cast<KDirModelDirNode *>(result.second);
00311
00312 const QModelIndex index = indexForNode(dirNode, result.first);
00313 const int newItemsCount = items.count();
00314 const int newRowCount = dirNode->m_childNodes.count() + newItemsCount;
00315 #ifndef NDEBUG // debugIndex only defined in debug mode
00316 kDebug(7008) << items.count() << "in" << dir
00317 << "index=" << debugIndex(index) << "newRowCount=" << newRowCount;
00318 #endif
00319 q->beginInsertRows( index, newRowCount - newItemsCount, newRowCount - 1 );
00320
00321 const KUrl::List urlsBeingFetched = m_urlsBeingFetched.value(dirNode);
00322
00323
00324 QList<QModelIndex> emitExpandFor;
00325
00326 KFileItemList::const_iterator it = items.begin();
00327 KFileItemList::const_iterator end = items.end();
00328 for ( ; it != end ; ++it ) {
00329 const bool isDir = it->isDir();
00330 KDirModelNode* node = isDir
00331 ? new KDirModelDirNode( dirNode, *it )
00332 : new KDirModelNode( dirNode, *it );
00333 dirNode->m_childNodes.append(node);
00334
00335 if (isDir && !urlsBeingFetched.isEmpty()) {
00336 const KUrl dirUrl = it->url();
00337 foreach(const KUrl& urlFetched, urlsBeingFetched) {
00338 if (dirUrl.isParentOf(urlFetched)) {
00339
00340 const QModelIndex parentIndex = indexForNode(node, dirNode->m_childNodes.count()-1);
00341 Q_ASSERT(parentIndex.isValid());
00342 emitExpandFor.append(parentIndex);
00343 if (dirUrl != urlFetched) {
00344 q->fetchMore(parentIndex);
00345 m_urlsBeingFetched[node].append(urlFetched);
00346 }
00347 }
00348 }
00349 }
00350 }
00351
00352 m_urlsBeingFetched.remove(dirNode);
00353
00354 q->endInsertRows();
00355
00356
00357
00358 Q_FOREACH(const QModelIndex& idx, emitExpandFor) {
00359 emit q->expand(idx);
00360 }
00361 }
00362
00363 void KDirModelPrivate::_k_slotDeleteItem(const KFileItem& item)
00364 {
00365
00366
00367
00368 Q_ASSERT(!item.isNull());
00369 const QPair<int, KDirModelNode*> result = nodeForUrl(item.url());
00370 const int rowNumber = result.first;
00371 KDirModelNode* node = result.second;
00372 if (!node)
00373 return;
00374
00375 KDirModelDirNode* dirNode = node->parent();
00376 if (!dirNode)
00377 return;
00378
00379 QModelIndex parentIndex = indexForNode(dirNode);
00380 q->beginRemoveRows( parentIndex, rowNumber, rowNumber );
00381 dirNode->m_childNodes.removeAt(rowNumber);
00382 q->endRemoveRows();
00383 }
00384
00385 void KDirModelPrivate::_k_slotRefreshItems(const QList<QPair<KFileItem, KFileItem> >& items)
00386 {
00387 QModelIndex topLeft, bottomRight;
00388
00389
00390
00391 for ( QList<QPair<KFileItem, KFileItem> >::const_iterator fit = items.begin(), fend = items.end() ; fit != fend ; ++fit ) {
00392 const QModelIndex index = q->indexForUrl( fit->first.url() );
00393 nodeForIndex(index)->setItem(fit->second);
00394 if (!topLeft.isValid() || index.row() < topLeft.row()) {
00395 topLeft = index;
00396 }
00397 if (!bottomRight.isValid() || index.row() > bottomRight.row()) {
00398 bottomRight = index;
00399 }
00400 }
00401 #ifndef NDEBUG // debugIndex only defined in debug mode
00402 kDebug(7008) << "slotRefreshItems: dataChanged(" << debugIndex(topLeft) << " - " << debugIndex(bottomRight);
00403 #endif
00404 bottomRight = bottomRight.sibling(bottomRight.row(), q->columnCount(QModelIndex())-1);
00405 emit q->dataChanged(topLeft, bottomRight);
00406 }
00407
00408 void KDirModelPrivate::_k_slotClear()
00409 {
00410 const int numRows = m_rootNode->m_childNodes.count();
00411 q->beginRemoveRows( QModelIndex(), 0, numRows );
00412 q->endRemoveRows();
00413
00414
00415 clear();
00416
00417 }
00418
00419 void KDirModel::itemChanged( const QModelIndex& index )
00420 {
00421 emit dataChanged(index, index);
00422 }
00423
00424 int KDirModel::columnCount( const QModelIndex & ) const
00425 {
00426 return ColumnCount;
00427 }
00428
00429 QVariant KDirModel::data( const QModelIndex & index, int role ) const
00430 {
00431 if (index.isValid()) {
00432 KDirModelNode* node = static_cast<KDirModelNode*>(index.internalPointer());
00433 const KFileItem& item( node->item() );
00434 switch (role) {
00435 case Qt::DisplayRole:
00436 switch (index.column()) {
00437 case Name:
00438 return item.text();
00439 case Size:
00440
00441
00442
00443 return KGlobal::locale()->formatNumber(item.size(), 0);
00444 case ModifiedTime: {
00445 KDateTime dt = item.time(KFileItem::ModificationTime);
00446 return KGlobal::locale()->formatDateTime(dt);
00447 }
00448 case Permissions:
00449 return item.permissionsString();
00450 case Owner:
00451 return item.user();
00452 case Group:
00453 return item.group();
00454 case Type:
00455 return item.mimeComment();
00456 }
00457 break;
00458 case Qt::EditRole:
00459 switch (index.column()) {
00460 case Name:
00461 return item.text();
00462 }
00463 break;
00464 case Qt::DecorationRole:
00465 if (index.column() == Name) {
00466 if (!node->preview().isNull()) {
00467
00468 return node->preview();
00469 }
00470 Q_ASSERT(!item.isNull());
00471
00472 return KIcon(item.iconName(), 0, item.overlays());
00473 }
00474 break;
00475 case Qt::TextAlignmentRole:
00476 if (index.column() == Size) {
00477
00478 const Qt::Alignment alignment = Qt::AlignRight | Qt::AlignVCenter;
00479 return int(alignment);
00480 }
00481 break;
00482 case FileItemRole:
00483 return QVariant::fromValue(item);
00484 case ChildCountRole:
00485 if (!item.isDir())
00486 return ChildCountUnknown;
00487 else {
00488 KDirModelDirNode* dirNode = static_cast<KDirModelDirNode *>(node);
00489 int count = dirNode->childCount();
00490 if (count == ChildCountUnknown && item.isReadable()) {
00491 const QString path = item.localPath();
00492 if (!path.isEmpty()) {
00493 #if 0 // slow
00494 QDir dir(path);
00495 count = dir.entryList(QDir::AllEntries|QDir::NoDotAndDotDot|QDir::System).count();
00496 #else
00497 DIR* dir = ::opendir(QFile::encodeName(path));
00498 if (dir) {
00499 count = 0;
00500 struct dirent *dirEntry = 0;
00501 while ((dirEntry = ::readdir(dir))) {
00502 if (dirEntry->d_name[0] == '.') {
00503 if (dirEntry->d_name[1] == '\0')
00504 continue;
00505 if (dirEntry->d_name[1] == '.' && dirEntry->d_name[2] == '\0')
00506 continue;
00507 }
00508 ++count;
00509 }
00510 ::closedir(dir);
00511 }
00512 #endif
00513
00514 dirNode->setChildCount(count);
00515 }
00516 }
00517 return count;
00518 }
00519 }
00520 }
00521 return QVariant();
00522 }
00523
00524 void KDirModel::sort( int column, Qt::SortOrder order )
00525 {
00526
00527 return QAbstractItemModel::sort(column, order);
00528 }
00529
00530 bool KDirModel::setData( const QModelIndex & index, const QVariant & value, int role )
00531 {
00532 switch (role) {
00533 case Qt::EditRole:
00534 if (index.column() == Name && value.type() == QVariant::String) {
00535 Q_ASSERT(index.isValid());
00536 KDirModelNode* node = static_cast<KDirModelNode*>(index.internalPointer());
00537 const KFileItem& item = node->item();
00538 const QString newName = value.toString();
00539 if (newName.isEmpty() || newName == item.text())
00540 return true;
00541 KUrl newurl(item.url());
00542 newurl.setPath(newurl.directory(KUrl::AppendTrailingSlash) + newName);
00543 KIO::Job * job = KIO::moveAs(item.url(), newurl, newurl.isLocalFile() ? KIO::HideProgressInfo : KIO::DefaultFlags);
00544 job->ui()->setAutoErrorHandlingEnabled(true);
00545
00546 return true;
00547 }
00548 break;
00549 case Qt::DecorationRole:
00550 if (index.column() == Name) {
00551 Q_ASSERT(index.isValid());
00552
00553 KDirModelNode* node = static_cast<KDirModelNode*>(index.internalPointer());
00554
00555 Q_ASSERT(node);
00556 if (value.type() == QVariant::Icon) {
00557 const QIcon icon(qvariant_cast<QIcon>(value));
00558 Q_ASSERT(!icon.isNull());
00559 node->setPreview(icon);
00560 } else if (value.type() == QVariant::Pixmap) {
00561 node->addPreview(qvariant_cast<QPixmap>(value));
00562 }
00563 emit dataChanged(index, index);
00564 return true;
00565 }
00566 break;
00567 default:
00568 break;
00569 }
00570 return false;
00571 }
00572
00573 int KDirModel::rowCount( const QModelIndex & parent ) const
00574 {
00575 KDirModelDirNode* parentNode = static_cast<KDirModelDirNode *>(d->nodeForIndex(parent));
00576 Q_ASSERT(parentNode);
00577 const int count = parentNode->m_childNodes.count();
00578
00579 return count;
00580 }
00581
00582
00583 QModelIndex KDirModel::parent( const QModelIndex & index ) const
00584 {
00585 if (!index.isValid())
00586 return QModelIndex();
00587 KDirModelNode* childNode = static_cast<KDirModelNode*>(index.internalPointer());
00588 Q_ASSERT(childNode);
00589 KDirModelNode* parentNode = childNode->parent();
00590 Q_ASSERT(parentNode);
00591 return d->indexForNode(parentNode);
00592 }
00593
00594 QStringList KDirModel::mimeTypes( ) const
00595 {
00596 return QStringList() << QLatin1String("text/uri-list")
00597 << QLatin1String( "application/x-kde-cutselection" )
00598 << QLatin1String( "text/plain" )
00599 << QLatin1String( "application/x-kde-urilist" );
00600 }
00601
00602 QMimeData * KDirModel::mimeData( const QModelIndexList & indexes ) const
00603 {
00604 KUrl::List urls;
00605 foreach ( const QModelIndex &index, indexes ) {
00606 urls << d->nodeForIndex( index )->item().url();
00607 }
00608 QMimeData *data = new QMimeData();
00609 urls.populateMimeData( data );
00610 return data;
00611 }
00612
00613
00614 KFileItem KDirModel::itemForIndex( const QModelIndex& index ) const
00615 {
00616 if (!index.isValid()) {
00617 return d->m_dirLister->rootItem();
00618 } else {
00619 return static_cast<KDirModelNode*>(index.internalPointer())->item();
00620 }
00621 }
00622
00623 QModelIndex KDirModel::indexForItem( const KFileItem* item ) const
00624 {
00625
00626
00627 return indexForUrl(item->url());
00628 }
00629
00630 QModelIndex KDirModel::indexForItem( const KFileItem& item ) const
00631 {
00632
00633
00634 return indexForUrl(item.url());
00635 }
00636
00637
00638 QModelIndex KDirModel::indexForUrl(const KUrl& url) const
00639 {
00640 const QPair<int, KDirModelNode*> result = d->nodeForUrl(url);
00641 if (!result.second) {
00642 kDebug(7007) << url << "not found";
00643 return QModelIndex();
00644 }
00645 return d->indexForNode(result.second, result.first);
00646 }
00647
00648 QModelIndex KDirModel::index( int row, int column, const QModelIndex & parent ) const
00649 {
00650 KDirModelNode* parentNode = d->nodeForIndex(parent);
00651 Q_ASSERT(parentNode);
00652 Q_ASSERT(d->isDir(parentNode));
00653 KDirModelNode* childNode = static_cast<KDirModelDirNode *>(parentNode)->m_childNodes.value(row);
00654 if (childNode)
00655 return createIndex(row, column, childNode);
00656 else
00657 return QModelIndex();
00658 }
00659
00660 QVariant KDirModel::headerData( int section, Qt::Orientation orientation, int role ) const
00661 {
00662 Q_UNUSED(orientation);
00663 switch (role) {
00664 case Qt::DisplayRole:
00665 switch (section) {
00666 case Name:
00667 return i18nc("@title:column","Name");
00668 case Size:
00669 return i18nc("@title:column","Size");
00670 case ModifiedTime:
00671 return i18nc("@title:column","Date");
00672 case Permissions:
00673 return i18nc("@title:column","Permissions");
00674 case Owner:
00675 return i18nc("@title:column","Owner");
00676 case Group:
00677 return i18nc("@title:column","Group");
00678 case Type:
00679 return i18nc("@title:column","Type");
00680 }
00681 }
00682 return QVariant();
00683 }
00684
00685 bool KDirModel::hasChildren( const QModelIndex & parent ) const
00686 {
00687 if (!parent.isValid())
00688 return true;
00689
00690 const KFileItem& parentItem = static_cast<KDirModelNode*>(parent.internalPointer())->item();
00691 Q_ASSERT(!parentItem.isNull());
00692 return parentItem.isDir();
00693 }
00694
00695 Qt::ItemFlags KDirModel::flags( const QModelIndex & index ) const
00696 {
00697 Qt::ItemFlags f = Qt::ItemIsEnabled;
00698 if (index.column() == Name) {
00699 f |= Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled;
00700 }
00701
00702
00703 if (d->m_dropsAllowed != NoDrops) {
00704 if(!index.isValid()) {
00705 if (d->m_dropsAllowed & DropOnDirectory) {
00706 f |= Qt::ItemIsDropEnabled;
00707 }
00708 } else {
00709 KFileItem item = itemForIndex(index);
00710 if (item.isNull()) {
00711 kWarning(7007) << "Invalid item returned for index";
00712 } else if (item.isDir()) {
00713 if (d->m_dropsAllowed & DropOnDirectory) {
00714 f |= Qt::ItemIsDropEnabled;
00715 }
00716 } else {
00717 if (d->m_dropsAllowed & DropOnAnyFile)
00718 f |= Qt::ItemIsDropEnabled;
00719 else if (d->m_dropsAllowed & DropOnLocalExecutable) {
00720 if (item.isLocalFile()) {
00721
00722 if (item.mimeTypePtr()->is("application/x-desktop"))
00723 f |= Qt::ItemIsDropEnabled;
00724
00725 else if ( QFileInfo( item.localPath() ).isExecutable() )
00726 f |= Qt::ItemIsDropEnabled;
00727 }
00728 }
00729 }
00730 }
00731 }
00732
00733 return f;
00734 }
00735
00736 bool KDirModel::canFetchMore( const QModelIndex & parent ) const
00737 {
00738 if (!parent.isValid())
00739 return false;
00740
00741
00742
00743
00744
00745
00746 KDirModelNode* node = static_cast<KDirModelNode*>(parent.internalPointer());
00747 const KFileItem& item = node->item();
00748 return item.isDir() && !static_cast<KDirModelDirNode *>(node)->isPopulated()
00749 && static_cast<KDirModelDirNode *>(node)->m_childNodes.isEmpty();
00750 }
00751
00752 void KDirModel::fetchMore( const QModelIndex & parent )
00753 {
00754 if (!parent.isValid())
00755 return;
00756
00757 KDirModelNode* parentNode = static_cast<KDirModelNode*>(parent.internalPointer());
00758
00759 KFileItem parentItem = parentNode->item();
00760 Q_ASSERT(!parentItem.isNull());
00761 Q_ASSERT(parentItem.isDir());
00762 KDirModelDirNode* dirNode = static_cast<KDirModelDirNode *>(parentNode);
00763 if( dirNode->isPopulated() )
00764 return;
00765 dirNode->setPopulated( true );
00766
00767 const KUrl parentUrl = parentItem.url();
00768 d->m_dirLister->openUrl(parentUrl, KDirLister::Keep);
00769 }
00770
00771 bool KDirModel::dropMimeData( const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent )
00772 {
00773
00774
00775 Q_UNUSED(data);
00776 Q_UNUSED(action);
00777 Q_UNUSED(row);
00778 Q_UNUSED(column);
00779 Q_UNUSED(parent);
00780 return false;
00781 }
00782
00783 void KDirModel::setDropsAllowed(DropsAllowed dropsAllowed)
00784 {
00785 d->m_dropsAllowed = dropsAllowed;
00786 }
00787
00788 void KDirModel::expandToUrl(const KUrl& url)
00789 {
00790 const QPair<int, KDirModelNode*> result = d->nodeForUrl(url, true );
00791
00792 if (!result.second)
00793 return;
00794 if (!(result.second->item().isNull()) && result.second->item().url() == url) {
00795
00796 kDebug(7008) << "have it already item=" <<url ;
00797 return;
00798 }
00799
00800 d->m_urlsBeingFetched[result.second].append(url);
00801
00802 if (result.second == d->m_rootNode) {
00803 kDebug(7008) << "Remembering to emit expand after listing the root url";
00804
00805 return;
00806 }
00807
00808 kDebug(7008) << "Remembering to emit expand after listing" << result.second->item().url();
00809
00810
00811 const QModelIndex parentIndex = d->indexForNode(result.second, result.first);
00812 Q_ASSERT(parentIndex.isValid());
00813 fetchMore(parentIndex);
00814 }
00815
00816 bool KDirModel::insertRows(int , int, const QModelIndex&)
00817 {
00818 return false;
00819 }
00820
00821 bool KDirModel::insertColumns(int, int, const QModelIndex&)
00822 {
00823 return false;
00824 }
00825
00826 bool KDirModel::removeRows(int, int, const QModelIndex&)
00827 {
00828 return false;
00829 }
00830
00831 bool KDirModel::removeColumns(int, int, const QModelIndex&)
00832 {
00833 return false;
00834 }
00835
00836 #include "kdirmodel.moc"