📄 qfilesystemmodel.cpp
字号:
/*! \reimp */bool QFileSystemModel::canFetchMore(const QModelIndex &parent) const{ Q_D(const QFileSystemModel); const QFileSystemModelPrivate::QFileSystemNode *indexNode = d->node(parent); return (!indexNode->populatedChildren);}/*! \reimp */void QFileSystemModel::fetchMore(const QModelIndex &parent){ Q_D(QFileSystemModel); if (!d->setRootPath) return; QFileSystemModelPrivate::QFileSystemNode *indexNode = d->node(parent); if (indexNode->populatedChildren) return; indexNode->populatedChildren = true; d->fileInfoGatherer.list(filePath(parent));}/*! \reimp*/int QFileSystemModel::rowCount(const QModelIndex &parent) const{ Q_D(const QFileSystemModel); if (parent.column() > 0) return 0; if (!parent.isValid()) return d->root.visibleChildren.count(); const QFileSystemModelPrivate::QFileSystemNode *parentNode = d->node(parent); return parentNode->visibleChildren.count();}/*! \reimp*/int QFileSystemModel::columnCount(const QModelIndex &parent) const{ return (parent.column() > 0) ? 0 : 4;}QVariant QFileSystemModel::myComputer(int role) const{ Q_D(const QFileSystemModel); switch (role) { case Qt::DisplayRole: return d->myComputer(); case Qt::DecorationRole: return d->fileInfoGatherer.iconProvider()->icon(QFileIconProvider::Computer); } return QVariant();}/*! \reimp*/QVariant QFileSystemModel::data(const QModelIndex &index, int role) const{ Q_D(const QFileSystemModel); if (!index.isValid() || index.model() != this) return QVariant(); switch (role) { case Qt::EditRole: case Qt::DisplayRole: switch (index.column()) { case 0: return d->name(index); case 1: return d->size(index); case 2: return d->type(index); case 3: return d->time(index); default: qWarning("data: invalid display value column %d", index.column()); break; } break; case FilePathRole: return filePath(index); case FileNameRole: return d->name(index); case Qt::DecorationRole: if (index.column() == 0) { QIcon icon = d->icon(index); if (icon.isNull()) { if (d->node(index)->isDir()) icon = d->fileInfoGatherer.iconProvider()->icon(QFileIconProvider::Folder); else icon = d->fileInfoGatherer.iconProvider()->icon(QFileIconProvider::File); } return icon; } break; case Qt::TextAlignmentRole: if (index.column() == 1) return Qt::AlignRight; break; } return QVariant();}/*! \internal*/QString QFileSystemModelPrivate::size(const QModelIndex &index) const{ if (!index.isValid()) return QString(); const QFileSystemNode *n = node(index); if (n->isDir()) {#ifdef Q_OS_MAC return QLatin1String("--");#else return QLatin1String("");#endif // Windows - "" // OS X - "--" // Konqueror - "4 KB" // Nautilus - "9 items" (the number of children) } return size(n->size());}QString QFileSystemModelPrivate::size(qint64 bytes){ // According to the Si standard KB is 1000 bytes, KiB is 1024 // but on windows sizes are calculated by dividing by 1024 so we do what they do. const qint64 kb = 1024; const qint64 mb = 1024 * kb; const qint64 gb = 1024 * mb; const qint64 tb = 1024 * gb; if (bytes >= tb) return QFileSystemModel::tr("%1 TB").arg(QLocale().toString(qreal(bytes) / tb, 'f', 3)); if (bytes >= gb) return QFileSystemModel::tr("%1 GB").arg(QLocale().toString(qreal(bytes) / gb, 'f', 2)); if (bytes >= mb) return QFileSystemModel::tr("%1 MB").arg(QLocale().toString(qreal(bytes) / mb, 'f', 1)); if (bytes >= kb) return QFileSystemModel::tr("%1 KB").arg(QLocale().toString(bytes / kb)); return QFileSystemModel::tr("%1 bytes").arg(QLocale().toString(bytes));}/*! \internal*/QString QFileSystemModelPrivate::time(const QModelIndex &index) const{ if (!index.isValid()) return QString();#ifndef QT_NO_DATESTRING return node(index)->lastModified().toString(Qt::SystemLocaleDate);#else Q_UNUSED(index); return QString();#endif}/* \internal*/QString QFileSystemModelPrivate::type(const QModelIndex &index) const{ if (!index.isValid()) return QString(); return node(index)->type();}/*! \internal*/QString QFileSystemModelPrivate::name(const QModelIndex &index) const{ if (!index.isValid()) return QString(); QFileSystemNode *dirNode = node(index); if (dirNode->isSymLink() && fileInfoGatherer.resolveSymlinks()) { QString fullPath = QDir::fromNativeSeparators(filePath(index)); if (resolvedSymLinks.contains(fullPath)) return resolvedSymLinks[fullPath]; } // ### TODO it would be nice to grab the volume name if dirNode->parent == root return dirNode->fileName;}/*! \internal*/QIcon QFileSystemModelPrivate::icon(const QModelIndex &index) const{ if (!index.isValid()) return QIcon(); return node(index)->icon();}/*! \reimp*/bool QFileSystemModel::setData(const QModelIndex &idx, const QVariant &value, int role){ Q_D(QFileSystemModel); if (!idx.isValid() || idx.column() != 0 || role != Qt::EditRole || (flags(idx) & Qt::ItemIsEditable) == 0) { return false; } QString newName = value.toString(); if (newName == idx.data().toString()) return true; if (newName.isEmpty() || newName.contains(QDir::separator()) || !d->rootDir.rename(idx.data().toString(), newName)) {#ifndef QT_NO_MESSAGEBOX QMessageBox::information(0, QFileSystemModel::tr("Invalid filename"), QFileSystemModel::tr("<b>The name \"%1\" can not be used.</b><p>Try using another name, with fewer characters or no punctuations marks.") .arg(newName), QMessageBox::Ok);#endif // QT_NO_MESSAGEBOX return false; } else { /* *After re-naming something we don't want the selection to change* - can't remove rows and later insert - can't quickly remove and insert - index pointer can't change because treeview doesn't use persistant index's - if this get any more complicated think of changing it to just use layoutChanged */ QFileSystemModelPrivate::QFileSystemNode *indexNode = d->node(idx); QFileSystemModelPrivate::QFileSystemNode *parentNode = indexNode->parent; int oldItemLocation = d->findChild(parentNode, *indexNode); int visibleLocation = parentNode->visibleLocation(oldItemLocation); parentNode->visibleChildren.removeAt(visibleLocation); // keep the old node and just move it around so any model index's that // point to it don't cause segfaults // swap will move the pointers, move will remove and insert. int newItemLocation = d->addNode(parentNode, newName); oldItemLocation = d->findChild(parentNode, *indexNode); parentNode->children.swap(newItemLocation, oldItemLocation); QFileInfo info(d->rootDir, newName); parentNode->children[newItemLocation].fileName = newName; parentNode->children[newItemLocation].parent = parentNode; parentNode->children[newItemLocation].populate(d->fileInfoGatherer.getInfo(info)); parentNode->children.removeAt(oldItemLocation); // remove from the visible children for (int j = 0; j < parentNode->visibleChildren.count(); ++j) if (parentNode->visibleChildren.at(j) > oldItemLocation) --parentNode->visibleChildren[j]; if (oldItemLocation < newItemLocation) --newItemLocation; parentNode->visibleChildren.insert(visibleLocation, newItemLocation); d->delayedSort(); } return true;}/*! \reimp*/QVariant QFileSystemModel::headerData(int section, Qt::Orientation orientation, int role) const{ switch (role) { case Qt::DecorationRole: if (section == 0) { // ### TODO oh man this is ugly and doesn't even work all the way! // it is still 2 pixels off QImage pixmap(16, 1, QImage::Format_Mono); pixmap.fill(0); pixmap.setAlphaChannel(pixmap.createAlphaMask()); return pixmap; } case Qt::TextAlignmentRole: return Qt::AlignLeft; } if (orientation != Qt::Horizontal || role != Qt::DisplayRole) return QAbstractItemModel::headerData(section, orientation, role); QString returnValue; switch (section) { case 0: returnValue = tr("Name"); break; case 1: returnValue = tr("Size"); break; case 2: returnValue =#ifdef Q_OS_MAC tr("Kind", "Match OS X Finder");#else tr("Type", "All other platforms");#endif break; // Windows - Type // OS X - Kind // Konqueror - File Type // Nautilus - Type case 3: returnValue = tr("Date Modified"); break; default: return QVariant(); } return returnValue;}/*! \reimp*/Qt::ItemFlags QFileSystemModel::flags(const QModelIndex &index) const{ Q_D(const QFileSystemModel); Qt::ItemFlags flags = QAbstractItemModel::flags(index); if (!index.isValid()) return flags; QFileSystemModelPrivate::QFileSystemNode *indexNode = d->node(index); if (d->nameFilterDisables && !d->passNameFilters(indexNode)) { flags &= ~Qt::ItemIsEnabled; // ### TODO you shouldn't be able to set this as the current item, task 119433 return flags; } flags |= Qt::ItemIsDragEnabled; if (d->readOnly) return flags; if ((index.column() == 0) && indexNode->permissions() & QFile::WriteUser) { flags |= Qt::ItemIsEditable; if (indexNode->isDir()) flags |= Qt::ItemIsDropEnabled; } return flags;}/*! \internal*/void QFileSystemModelPrivate::_q_performDelayedSort(){ Q_Q(QFileSystemModel); q->sort(sortColumn, sortOrder);}static inline QChar getNextChar(const QString &s, int location){ return (location < s.length()) ? s.at(location) : QChar();}/*! Natural number sort, skips spaces. Examples: 1, 2, 10, 55, 100 01.jpg, 2.jpg, 10.jpg Note on the algorithm: Only as many characters as necessary are looked at and at most they all are looked at once. Slower then QString::compare() (of course) */int QFileSystemModelPrivate::naturalCompare(const QString &s1, const QString &s2, Qt::CaseSensitivity cs){ for (int l1 = 0, l2 = 0; l1 <= s1.count() && l2 <= s2.count(); ++l1, ++l2) { // skip spaces, tabs and 0's QChar c1 = getNextChar(s1, l1); while (c1.isSpace()) c1 = getNextChar(s1, ++l1); QChar c2 = getNextChar(s2, l2); while (c2.isSpace()) c2 = getNextChar(s2, ++l2); if (c1.isDigit() && c2.isDigit()) { while (c1.digitValue() == 0) c1 = getNextChar(s1, ++l1); while (c2.digitValue() == 0) c2 = getNextChar(s2, ++l2); int lookAheadLocation1 = l1; int lookAheadLocation2 = l2; int currentReturnValue = 0; // find the last digit, setting currentReturnValue as we go if it isn't equal for ( QChar lookAhead1 = c1, lookAhead2 = c2; (lookAheadLocation1 <= s1.length() && lookAheadLocation2 <= s2.length()); lookAhead1 = getNextChar(s1, ++lookAheadLocation1), lookAhead2 = getNextChar(s2, ++lookAheadLocation2) ) { bool is1ADigit = !lookAhead1.isNull() && lookAhead1.isDigit(); bool is2ADigit = !lookAhead2.isNull() && lookAhead2.isDigit(); if (!is1ADigit && !is2ADigit) break; if (!is1ADigit) return -1; if (!is2ADigit) return 1; if (currentReturnValue == 0) { if (lookAhead1 < lookAhead2) { currentReturnValue = -1; } else if (lookAhead1 > lookAhead2) { currentReturnValue = 1; } } } if (currentReturnValue != 0) return currentReturnValue; } if (cs == Qt::CaseInsensitive) { if (!c1.isLower()) c1 = c1.toLower(); if (!c2.isLower()) c2 = c2.toLower(); } int r = QString::localeAwareCompare(c1, c2); if (r < 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -