xybrid/xybrid/ui/directorynode.cpp

103 lines
3.1 KiB
C++

#include "directorynode.h"
using Xybrid::UI::DirectoryNode;
#include <algorithm>
#include <functional>
#include <QStringBuilder>
#include <QCollator>
#include <QHash>
DirectoryNode::DirectoryNode(DirectoryNode* parent, QString name, QVariant data) {
this->parent = parent;
this->name = name;
this->data = data;
if (parent) {
index = parent->children.size();
parent->children.push_back(this);
}
}
DirectoryNode::~DirectoryNode() {
qDeleteAll(children);
}
void DirectoryNode::clear() {
qDeleteAll(children);
children.clear();
}
void DirectoryNode::sortChildren() {
QCollator col;
col.setNumericMode(true);
std::sort(children.begin(), children.end(), [&col](auto a, auto b) {
if (a->isDirectory() != b->isDirectory()) return a->isDirectory();
return col.compare(a->name, b->name) < 0;
});
for (int i = 0; i < children.size(); i++) children[i]->index = i;
}
void DirectoryNode::sortTree() {
sortChildren();
for (auto c : qAsConst(children)) c->sortTree();
}
DirectoryNode* DirectoryNode::subdir(QString name) {
if (name.isEmpty()) return this;
QString first = name.section('/', 0, 0, QString::SectionSkipEmpty);
QString rest = name.section('/', 1, -1, QString::SectionSkipEmpty);
DirectoryNode* sd = nullptr;
for (auto c : qAsConst(children)) if (c->isDirectory() && c->name == first) { sd = c; break; }
if (!sd) sd = new DirectoryNode(this, first);
return sd->subdir(rest);
}
DirectoryNode* DirectoryNode::placeData(QString name, QVariant data) {
QString dir = name.section('/', 0, -2, QString::SectionSkipEmpty);
QString file = name.section('/', -1, -1, QString::SectionSkipEmpty);
return new DirectoryNode(subdir(dir), file, data);
}
QString DirectoryNode::path() const {
if (!parent || parent->name.isEmpty()) return name;
if (name.isEmpty()) return parent->path(); // nameless nodes don't add an extra /
return parent->path() % "/" % name;
}
DirectoryNode* DirectoryNode::findPath(QString path) {
if (path.isEmpty()) return this;
QString first = path.section('/', 0, 0, QString::SectionSkipEmpty);
QString rest = path.section('/', 1, -1, QString::SectionSkipEmpty);
DirectoryNode* sd = nullptr;
for (auto c : qAsConst(children)) if (c->name == first) { sd = c; break; }
if (!sd) return nullptr;
return sd->findPath(rest);
}
DirectoryNode* DirectoryNode::findData(const QVariant& d) {
if (data == d) return this;
for (auto c : qAsConst(children)) {
if (auto cd = c->findData(d); cd) return cd;
}
return nullptr;
}
bool DirectoryNode::isChildOf(Xybrid::UI::DirectoryNode* dn) const {
auto c = this;
forever {
if (!c) return false;
if (c == dn) return true;
c = c->parent;
}
}
void DirectoryNode::treeExec(const std::function<void(Xybrid::UI::DirectoryNode*)>& f) {
for (auto c : qAsConst(children)) c->treeExec(f);
f(this);
}
/*void DirectoryNode::placeData(const QVector<std::pair<QString, QVariant>>& data) {
QHash<QString, DirectoryNode*> dirs; // lookup table for directories
dirs[""] = this;
}*/