FileTree


Qt documentation Contained in the Qt distribution.

Index


Code Index:


Qt documentation Contained in the Qt distribution.
package FileTree;

use strict;
use warnings;
use QtCore4;
use QtGui4;
use QtXmlPatterns4;
use QtCore4::isa qw( Qt::SimpleXmlNodeModel );
use List::MoreUtils qw ( first_index );

use constant {
    File => 1,
    Directory => 2,
    AttributeFileName => 3,
    AttributeFilePath => 4,
    AttributeSize => 5,
    AttributeMIMEType => 6,
    AttributeSuffix => 7,
};

    #! [2]
    #mutable Qt::Vector<Qt::FileInfo>  m_fileInfos;
    #Qt::Dir::Filters         m_filterAllowAll;
    #Qt::Dir::SortFlags       m_sortFlags;
    #Qt::Vector<Qt::XmlName>           m_names;
sub m_fileInfos() {
    return this->{m_fileInfos};
}

sub m_filterAllowAll() {
    return this->{m_filterAllowAll};
}

sub m_sortFlags() {
    return this->{m_sortFlags};
}

sub m_names() {
    return this->{m_names};
}

# [2]
sub NEW {
    my ($class, $pool) = @_;
    $class->SUPER::NEW($pool);
    this->{m_fileInfos} = [];
    this->{m_filterAllowAll} = (Qt::Dir::AllEntries() |
                     Qt::Dir::AllDirs() |
                     Qt::Dir::NoDotAndDotDot() |
                     Qt::Dir::Hidden()),
    this->{m_sortFlags} = Qt::Dir::Name();
    my $np = namePool();
    this->{m_names} = {
        File              , Qt::XmlName($np, 'file'),
        Directory         , Qt::XmlName($np, 'directory'),
        AttributeFileName , Qt::XmlName($np, 'fileName'),
        AttributeFilePath , Qt::XmlName($np, 'filePath'),
        AttributeSize     , Qt::XmlName($np, 'size'),
        AttributeMIMEType , Qt::XmlName($np, 'mimeType'),
        AttributeSuffix   , Qt::XmlName($np, 'suffix'),
    };
}
# [2]

sub nodeFor
{
    my ($dirName) = @_;
    my $dirInfo = Qt::FileInfo(Qt::Dir::cleanPath($dirName));
    die "Directory $dirName does not exist." unless $dirInfo->exists();
    return toNodeIndex($dirInfo);
}

# [6]
sub toFileInfo
{
    my ($nodeIndex) = @_;
    return m_fileInfos->[$nodeIndex->data()];
}
# [6]

# [1]
sub toNodeIndex
{
    my ($fileInfo, $attributeName) = @_;
    if ( !defined $attributeName ) {
        return toNodeIndex($fileInfo, $fileInfo->isDir() ? Directory : File);
    }
    my $indexOf = first_index { $_ == $fileInfo } @{m_fileInfos()};

    if ($indexOf == -1) {
        push @{m_fileInfos()}, $fileInfo;
        return createIndex( scalar @{m_fileInfos()}-1, $attributeName);
    }
    else {
        return createIndex($indexOf, $attributeName);
    }
}
# [1]

# [5]
sub nextSibling
{
    my ($nodeIndex, $fileInfo, $offset) = @_;
    die "Offset must be -1 or 1" unless ($offset == -1 || $offset == 1);

    # Get the context node's parent.
    my $parent = Qt::XmlNodeModelIndex(nextFromSimpleAxis(Qt::AbstractXmlNodeModel::Parent(), $nodeIndex));

    if ($parent->isNull()) {
        return Qt::XmlNodeModelIndex();
    }

    # Get the parent's child list.
    my $parentFI = Qt::FileInfo(toFileInfo($parent));
    die "Parent's type must be 'Directory" unless $parent->additionalData() == Directory;
    my $siblings = Qt::Dir($parentFI->absoluteFilePath())->entryInfoList([],
                                                                         m_filterAllowAll,
                                                                         m_sortFlags);
    print STDERR 'Can\'t happen! We started at a child.' if (!defined $siblings || scalar @{$siblings} < 0);

    # Find the index of the child where we started.
    my $indexOfMe = first_index { $_ == $fileInfo } @{$siblings};

    # Apply the offset.
    my $siblingIndex = $indexOfMe + $offset;
    if ($siblingIndex < 0 || $siblingIndex > scalar @{$siblings} - 1) {
        return Qt::XmlNodeModelIndex();
    }
    else {
        return toNodeIndex($siblings->[$siblingIndex]);
    }
}
# [5]

# [4]
sub nextFromSimpleAxis
{
    my ($axis, $nodeIndex) = @_;
    my $fi = Qt::FileInfo(toFileInfo($nodeIndex));
    my $type = $nodeIndex->additionalData();

    if ($type != File && $type != Directory) {
        print STDERR 'An attribute only has a parent!' if $axis == Qt::AbstractXmlNodeModel::Parent();
        return toNodeIndex($fi, Directory);
    }

    if ( $axis == Qt::AbstractXmlNodeModel::Parent() ) {
        return toNodeIndex(Qt::FileInfo($fi->path()), Directory);
    }
    elsif ( $axis == Qt::AbstractXmlNodeModel::FirstChild() ) {
        if ($type == File) { # A file has no children.
            return Qt::XmlNodeModelIndex();
        }
        else {
            die "Type must be Directory" unless ($type == Directory);
            print STDERR 'It isn\'t really a directory!' unless $fi->isDir();
            my $dir = Qt::Dir($fi->absoluteFilePath());
            die "Directory doesn't exist." unless $dir->exists();

            my $children = $dir->entryInfoList([],
                                               m_filterAllowAll,
                                               m_sortFlags);
            if (defined $children && scalar @{$children} <= 0) {
                return Qt::XmlNodeModelIndex();
            }
            my $firstChild = Qt::FileInfo($children->[0]);
            return toNodeIndex($firstChild);
        }
    }
    elsif ( $axis == Qt::AbstractXmlNodeModel::PreviousSibling() ) {
        return nextSibling($nodeIndex, $fi, -1);
    }
    elsif ( $axis == Qt::AbstractXmlNodeModel::NextSibling() ) {
        return nextSibling($nodeIndex, $fi, 1);
    }

    print STDERR 'Don\'t ever get here!';
    return Qt::XmlNodeModelIndex();
}
# [4]

sub documentUri
{
    return Qt::Url('file:#/');
}

sub kind
{
    my ($node) = @_;
    if ( $node->additionalData() == Directory || $node->additionalData() == File ) {
        return Qt::XmlNodeModelIndex::Element();
    }
    else {
        return Qt::XmlNodeModelIndex::Attribute();
    }
}

sub compareOrder
{
    return Qt::XmlNodeModelIndex::Precedes();
}

# [3]
sub name
{
    my ($node) = @_;
    return Qt::XmlName(m_names->{$node->additionalData()});
}
# [3]

sub root
{
    return toNodeIndex(Qt::FileInfo('/'));
}

sub typedValue
{
    my ($node) = @_;
    my $fi = toFileInfo($node);

    if ( $node->additionalData() == Directory ) {
        # deliberate fall through.
    }
    elsif ( $node->additionalData() == File ) {
        Qt::Variant(Qt::String());
    }
    elsif ( $node->additionalData() == AttributeFileName ) {
        return Qt::Variant(Qt::String($fi->fileName()));
    }
    elsif ( $node->additionalData() == AttributeFilePath ) {
        return Qt::Variant(Qt::String($fi->filePath()));
    }
    elsif ( $node->additionalData() == AttributeSize ) {
        return Qt::Variant(Qt::String($fi->size()));
    }
    elsif ( $node->additionalData() == AttributeMIMEType ) {
        # We don't have any MIME detection code currently, so return
        # the most generic one. */
        return Qt::Variant(Qt::String('application/octet-stream'));
    }
    elsif ( $node->additionalData() == AttributeSuffix ) {
        return Qt::Variant(Qt::String($fi->suffix()));
    }

    print STDERR 'This line should never be reached.';
    return Qt::Variant(Qt::String());
}

sub attributes
{
    my ($element) = @_;
    my @result;

    # Both elements has this attribute.
    my $forElement = toFileInfo($element);
    push @result, toNodeIndex($forElement, AttributeFilePath);
    push @result, toNodeIndex($forElement, AttributeFileName);

    if ($element->additionalData() == File) {
        push @result, toNodeIndex($forElement, AttributeSize);
        push @result, toNodeIndex($forElement, AttributeSuffix);
        #push @result, toNodeIndex(forElement, AttributeMIMEType));
    }
    else {
        die "Type must be a directory"
            unless $element->additionalData() == Directory;
    }

    return \@result;
}

1;