filetree.cpp Example File
xmlpatterns/filetree/filetree.cpp
#include <QtCore/QUrl>
#include <QtCore/QVariant>
#include <QtXmlPatterns/QXmlNamePool>
#include "filetree.h"
FileTree::FileTree(const QXmlNamePool& pool) : QSimpleXmlNodeModel(pool)
, m_filterAllowAll(QDir::AllEntries
| QDir::AllDirs
| QDir::NoDotAndDotDot
| QDir::Hidden)
, m_sortFlags(QDir::Name)
{
QXmlNamePool np = namePool();
m_names.resize(7);
m_names[File] = QXmlName(np, QLatin1String("file"));
m_names[Directory] = QXmlName(np, QLatin1String("directory"));
m_names[AttributeFileName] = QXmlName(np, QLatin1String("fileName"));
m_names[AttributeFilePath] = QXmlName(np, QLatin1String("filePath"));
m_names[AttributeSize] = QXmlName(np, QLatin1String("size"));
m_names[AttributeMIMEType] = QXmlName(np, QLatin1String("mimeType"));
m_names[AttributeSuffix] = QXmlName(np, QLatin1String("suffix"));
}
QXmlNodeModelIndex FileTree::nodeFor(const QString& dirName) const
{
QFileInfo dirInfo(QDir::cleanPath(dirName));
Q_ASSERT(dirInfo.exists());
return toNodeIndex(dirInfo);
}
const QFileInfo&
FileTree::toFileInfo(const QXmlNodeModelIndex &nodeIndex) const
{
return m_fileInfos.at(nodeIndex.data());
}
QXmlNodeModelIndex
FileTree::toNodeIndex(const QFileInfo &fileInfo, Type attributeName) const
{
const int indexOf = m_fileInfos.indexOf(fileInfo);
if (indexOf == -1) {
m_fileInfos.append(fileInfo);
return createIndex(m_fileInfos.count()-1, attributeName);
}
else
return createIndex(indexOf, attributeName);
}
QXmlNodeModelIndex FileTree::toNodeIndex(const QFileInfo &fileInfo) const
{
return toNodeIndex(fileInfo, fileInfo.isDir() ? Directory : File);
}
QXmlNodeModelIndex FileTree::nextSibling(const QXmlNodeModelIndex &nodeIndex,
const QFileInfo &fileInfo,
qint8 offset) const
{
Q_ASSERT(offset == -1 || offset == 1);
const QXmlNodeModelIndex parent(nextFromSimpleAxis(Parent, nodeIndex));
if (parent.isNull())
return QXmlNodeModelIndex();
const QFileInfo parentFI(toFileInfo(parent));
Q_ASSERT(Type(parent.additionalData()) == Directory);
const QFileInfoList
siblings(QDir(parentFI.absoluteFilePath()).entryInfoList(QStringList(), m_filterAllowAll, m_sortFlags));
Q_ASSERT_X(!siblings.isEmpty(),
Q_FUNC_INFO,
"This would be a contradiction, there's at least one.");
const int indexOfMe = siblings.indexOf(fileInfo);
Q_ASSERT_X(indexOfMe != -1, Q_FUNC_INFO, "We're there, somewhere.");
const int siblingIndex = indexOfMe + offset;
if (siblingIndex < 0 || siblingIndex > siblings.count() - 1)
return QXmlNodeModelIndex();
else
return toNodeIndex(siblings.at(siblingIndex));
}
QXmlNodeModelIndex
FileTree::nextFromSimpleAxis(QSimpleXmlNodeModel::SimpleAxis axis,
const QXmlNodeModelIndex &nodeIndex) const
{
const QFileInfo fi(toFileInfo(nodeIndex));
const Type type = Type(nodeIndex.additionalData());
if (type != File && type != Directory) {
Q_ASSERT_X(axis == Parent,
Q_FUNC_INFO,
"QSimpleXmlNodeModel guarantees that it only "
"asks for Parent for attributes.");
return toNodeIndex(fi, Directory);
}
switch(axis) {
case Parent:
return toNodeIndex(QFileInfo(fi.path()), Directory);
case FirstChild:
{
if (type == File) {
return QXmlNodeModelIndex();
}
else {
Q_ASSERT(type == Directory);
Q_ASSERT_X(fi.isDir(),
Q_FUNC_INFO,
"If we're a directory, we really should be one!");
const QDir dir(fi.absoluteFilePath());
Q_ASSERT(dir.exists());
const QFileInfoList children(dir.entryInfoList(QStringList(), m_filterAllowAll, m_sortFlags));
if (children.isEmpty())
return QXmlNodeModelIndex();
const QFileInfo firstChild(children.first());
return toNodeIndex(firstChild);
}
}
case PreviousSibling:
return nextSibling(nodeIndex, fi, -1);
case NextSibling:
return nextSibling(nodeIndex, fi, 1);
}
Q_ASSERT_X(false, Q_FUNC_INFO, "This line should never be reached.");
return QXmlNodeModelIndex();
}
QUrl FileTree::documentUri(const QXmlNodeModelIndex &node) const
{
Q_UNUSED(node);
return QUrl("file:
}
QXmlNodeModelIndex::NodeKind
FileTree::kind(const QXmlNodeModelIndex &node) const
{
switch(Type(node.additionalData())) {
case Directory:
case File:
return QXmlNodeModelIndex::Element;
default:
return QXmlNodeModelIndex::Attribute;
}
}
QXmlNodeModelIndex::DocumentOrder
FileTree::compareOrder(const QXmlNodeModelIndex&,
const QXmlNodeModelIndex&) const
{
return QXmlNodeModelIndex::Precedes;
}
QXmlName FileTree::name(const QXmlNodeModelIndex &node) const
{
return m_names.at(node.additionalData());
}
QXmlNodeModelIndex FileTree::root(const QXmlNodeModelIndex &node) const
{
Q_UNUSED(node);
return toNodeIndex(QFileInfo(QLatin1String("/")));
}
QVariant FileTree::typedValue(const QXmlNodeModelIndex &node) const
{
const QFileInfo &fi = toFileInfo(node);
switch(Type(node.additionalData())) {
case Directory:
case File:
return QString();
case AttributeFileName:
return fi.fileName();
case AttributeFilePath:
return fi.filePath();
case AttributeSize:
return fi.size();
case AttributeMIMEType:
{
return QLatin1String("application/octet-stream");
}
case AttributeSuffix:
return fi.suffix();
}
Q_ASSERT_X(false, Q_FUNC_INFO, "This line should never be reached.");
return QString();
}
QVector<QXmlNodeModelIndex>
FileTree::attributes(const QXmlNodeModelIndex &element) const
{
QVector<QXmlNodeModelIndex> result;
const QFileInfo &forElement = toFileInfo(element);
result.append(toNodeIndex(forElement, AttributeFilePath));
result.append(toNodeIndex(forElement, AttributeFileName));
if (Type(element.additionalData() == File)) {
result.append(toNodeIndex(forElement, AttributeSize));
result.append(toNodeIndex(forElement, AttributeSuffix));
result.append(toNodeIndex(forElement, AttributeMIMEType));
}
else {
Q_ASSERT(element.additionalData() == Directory);
}
return result;
}