103 lines
3.1 KiB
C++
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;
|
|
}*/
|