git repos / SagoImageBrowser

blame: src/fsdirmodel.cpp

normal view · raw

14cf904f Poul Sander 2026-06-22 18:18 1
/*
14cf904f Poul Sander 2026-06-22 18:18 2
MIT License
14cf904f Poul Sander 2026-06-22 18:18 3
14cf904f Poul Sander 2026-06-22 18:18 4
Copyright (c) 2026 Poul Sander
14cf904f Poul Sander 2026-06-22 18:18 5
14cf904f Poul Sander 2026-06-22 18:18 6
Permission is hereby granted, free of charge, to any person obtaining a copy
14cf904f Poul Sander 2026-06-22 18:18 7
of this software and associated documentation files (the "Software"), to deal
14cf904f Poul Sander 2026-06-22 18:18 8
in the Software without restriction, including without limitation the rights
14cf904f Poul Sander 2026-06-22 18:18 9
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14cf904f Poul Sander 2026-06-22 18:18 10
copies of the Software, and to permit persons to whom the Software is
14cf904f Poul Sander 2026-06-22 18:18 11
furnished to do so, subject to the following conditions:
14cf904f Poul Sander 2026-06-22 18:18 12
14cf904f Poul Sander 2026-06-22 18:18 13
The above copyright notice and this permission notice shall be included in all
14cf904f Poul Sander 2026-06-22 18:18 14
copies or substantial portions of the Software.
14cf904f Poul Sander 2026-06-22 18:18 15
14cf904f Poul Sander 2026-06-22 18:18 16
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14cf904f Poul Sander 2026-06-22 18:18 17
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14cf904f Poul Sander 2026-06-22 18:18 18
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14cf904f Poul Sander 2026-06-22 18:18 19
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14cf904f Poul Sander 2026-06-22 18:18 20
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
14cf904f Poul Sander 2026-06-22 18:18 21
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
14cf904f Poul Sander 2026-06-22 18:18 22
SOFTWARE.
14cf904f Poul Sander 2026-06-22 18:18 23
14cf904f Poul Sander 2026-06-22 18:18 24
*/
14cf904f Poul Sander 2026-06-22 18:18 25
40efdfde Poul Sander 2026-05-19 21:24 26
#include "fsdirmodel.h"
40efdfde Poul Sander 2026-05-19 21:24 27
40efdfde Poul Sander 2026-05-19 21:24 28
#include <QFileIconProvider>
40efdfde Poul Sander 2026-05-19 21:24 29
40efdfde Poul Sander 2026-05-19 21:24 30
#include <algorithm>
40efdfde Poul Sander 2026-05-19 21:24 31
#include <filesystem>
40efdfde Poul Sander 2026-05-19 21:24 32
#include <vector>
40efdfde Poul Sander 2026-05-19 21:24 33
40efdfde Poul Sander 2026-05-19 21:24 34
namespace fs = std::filesystem;
40efdfde Poul Sander 2026-05-19 21:24 35
40efdfde Poul Sander 2026-05-19 21:24 36
// ---------------------------------------------------------------------------
40efdfde Poul Sander 2026-05-19 21:24 37
// Static helpers
40efdfde Poul Sander 2026-05-19 21:24 38
// ---------------------------------------------------------------------------
40efdfde Poul Sander 2026-05-19 21:24 39
40efdfde Poul Sander 2026-05-19 21:24 40
QList<FsDirModel::Node *> FsDirModel::listSubdirs(Node *parentNode)
40efdfde Poul Sander 2026-05-19 21:24 41
{
40efdfde Poul Sander 2026-05-19 21:24 42
    QList<Node *> result;
40efdfde Poul Sander 2026-05-19 21:24 43
    try {
40efdfde Poul Sander 2026-05-19 21:24 44
        std::vector<std::pair<std::string, std::string>> entries; // {nativePath, filename}
40efdfde Poul Sander 2026-05-19 21:24 45
40efdfde Poul Sander 2026-05-19 21:24 46
        for (const fs::directory_entry &entry :
40efdfde Poul Sander 2026-05-19 21:24 47
             fs::directory_iterator(parentNode->nativePath.toStdString(),
40efdfde Poul Sander 2026-05-19 21:24 48
                                    fs::directory_options::skip_permission_denied))
40efdfde Poul Sander 2026-05-19 21:24 49
        {
40efdfde Poul Sander 2026-05-19 21:24 50
            std::error_code ec;
40efdfde Poul Sander 2026-05-19 21:24 51
            const std::string fname = entry.path().filename().native();
40efdfde Poul Sander 2026-05-19 21:24 52
            if (fname.empty() || fname[0] == '.')
40efdfde Poul Sander 2026-05-19 21:24 53
                continue;
40efdfde Poul Sander 2026-05-19 21:24 54
            if (!entry.is_directory(ec))
40efdfde Poul Sander 2026-05-19 21:24 55
                continue;
40efdfde Poul Sander 2026-05-19 21:24 56
            entries.push_back({entry.path().native(), fname});
40efdfde Poul Sander 2026-05-19 21:24 57
        }
40efdfde Poul Sander 2026-05-19 21:24 58
40efdfde Poul Sander 2026-05-19 21:24 59
        std::sort(entries.begin(), entries.end(),
40efdfde Poul Sander 2026-05-19 21:24 60
                  [](const auto &a, const auto &b) { return a.second < b.second; });
40efdfde Poul Sander 2026-05-19 21:24 61
40efdfde Poul Sander 2026-05-19 21:24 62
        result.reserve(static_cast<qsizetype>(entries.size()));
40efdfde Poul Sander 2026-05-19 21:24 63
        for (const auto &[npath, fname] : entries) {
40efdfde Poul Sander 2026-05-19 21:24 64
            auto *child = new Node;
40efdfde Poul Sander 2026-05-19 21:24 65
            child->nativePath  = QByteArray::fromStdString(npath);
40efdfde Poul Sander 2026-05-19 21:24 66
            child->displayName = QString::fromLocal8Bit(fname.c_str(),
40efdfde Poul Sander 2026-05-19 21:24 67
                                                        static_cast<qsizetype>(fname.size()));
40efdfde Poul Sander 2026-05-19 21:24 68
            child->parent      = parentNode;
40efdfde Poul Sander 2026-05-19 21:24 69
            result.append(child);
40efdfde Poul Sander 2026-05-19 21:24 70
        }
40efdfde Poul Sander 2026-05-19 21:24 71
    } catch (const fs::filesystem_error &) {}
40efdfde Poul Sander 2026-05-19 21:24 72
40efdfde Poul Sander 2026-05-19 21:24 73
    return result;
40efdfde Poul Sander 2026-05-19 21:24 74
}
40efdfde Poul Sander 2026-05-19 21:24 75
40efdfde Poul Sander 2026-05-19 21:24 76
void FsDirModel::destroyChildren(Node *node)
40efdfde Poul Sander 2026-05-19 21:24 77
{
40efdfde Poul Sander 2026-05-19 21:24 78
    for (Node *child : node->children) {
40efdfde Poul Sander 2026-05-19 21:24 79
        destroyChildren(child);
40efdfde Poul Sander 2026-05-19 21:24 80
        delete child;
40efdfde Poul Sander 2026-05-19 21:24 81
    }
40efdfde Poul Sander 2026-05-19 21:24 82
    node->children.clear();
40efdfde Poul Sander 2026-05-19 21:24 83
    node->populated = false;
40efdfde Poul Sander 2026-05-19 21:24 84
}
40efdfde Poul Sander 2026-05-19 21:24 85
40efdfde Poul Sander 2026-05-19 21:24 86
// ---------------------------------------------------------------------------
40efdfde Poul Sander 2026-05-19 21:24 87
// Construction / destruction
40efdfde Poul Sander 2026-05-19 21:24 88
// ---------------------------------------------------------------------------
40efdfde Poul Sander 2026-05-19 21:24 89
40efdfde Poul Sander 2026-05-19 21:24 90
FsDirModel::FsDirModel(QObject *parent)
40efdfde Poul Sander 2026-05-19 21:24 91
    : QAbstractItemModel(parent)
40efdfde Poul Sander 2026-05-19 21:24 92
{
40efdfde Poul Sander 2026-05-19 21:24 93
    m_virtualRoot.populated = true; // virtual root is always "populated"
40efdfde Poul Sander 2026-05-19 21:24 94
40efdfde Poul Sander 2026-05-19 21:24 95
    QFileIconProvider iconProvider;
40efdfde Poul Sander 2026-05-19 21:24 96
    m_folderIcon = iconProvider.icon(QFileIconProvider::Folder);
40efdfde Poul Sander 2026-05-19 21:24 97
}
40efdfde Poul Sander 2026-05-19 21:24 98
40efdfde Poul Sander 2026-05-19 21:24 99
FsDirModel::~FsDirModel()
40efdfde Poul Sander 2026-05-19 21:24 100
{
40efdfde Poul Sander 2026-05-19 21:24 101
    destroyChildren(&m_virtualRoot);
40efdfde Poul Sander 2026-05-19 21:24 102
}
40efdfde Poul Sander 2026-05-19 21:24 103
40efdfde Poul Sander 2026-05-19 21:24 104
// ---------------------------------------------------------------------------
40efdfde Poul Sander 2026-05-19 21:24 105
// Public API
40efdfde Poul Sander 2026-05-19 21:24 106
// ---------------------------------------------------------------------------
40efdfde Poul Sander 2026-05-19 21:24 107
40efdfde Poul Sander 2026-05-19 21:24 108
void FsDirModel::setRootPath(const QString &path)
40efdfde Poul Sander 2026-05-19 21:24 109
{
40efdfde Poul Sander 2026-05-19 21:24 110
    setRootPath(QFile::encodeName(path));
40efdfde Poul Sander 2026-05-19 21:24 111
}
40efdfde Poul Sander 2026-05-19 21:24 112
40efdfde Poul Sander 2026-05-19 21:24 113
void FsDirModel::setRootPath(const QByteArray &nativePath)
40efdfde Poul Sander 2026-05-19 21:24 114
{
40efdfde Poul Sander 2026-05-19 21:24 115
    beginResetModel();
40efdfde Poul Sander 2026-05-19 21:24 116
    destroyChildren(&m_virtualRoot);
40efdfde Poul Sander 2026-05-19 21:24 117
40efdfde Poul Sander 2026-05-19 21:24 118
    if (!nativePath.isEmpty()) {
40efdfde Poul Sander 2026-05-19 21:24 119
        auto *node = new Node;
40efdfde Poul Sander 2026-05-19 21:24 120
        node->nativePath  = nativePath;
40efdfde Poul Sander 2026-05-19 21:24 121
        // Display name = last path component (empty for "/", use "/" in that case)
40efdfde Poul Sander 2026-05-19 21:24 122
        std::string fname = fs::path(nativePath.toStdString()).filename().native();
40efdfde Poul Sander 2026-05-19 21:24 123
        node->displayName = fname.empty()
40efdfde Poul Sander 2026-05-19 21:24 124
            ? QFile::decodeName(nativePath)
40efdfde Poul Sander 2026-05-19 21:24 125
            : QString::fromLocal8Bit(fname.c_str(), static_cast<qsizetype>(fname.size()));
40efdfde Poul Sander 2026-05-19 21:24 126
        node->parent      = &m_virtualRoot;
40efdfde Poul Sander 2026-05-19 21:24 127
        m_virtualRoot.children.append(node);
40efdfde Poul Sander 2026-05-19 21:24 128
    }
40efdfde Poul Sander 2026-05-19 21:24 129
40efdfde Poul Sander 2026-05-19 21:24 130
    endResetModel();
40efdfde Poul Sander 2026-05-19 21:24 131
}
40efdfde Poul Sander 2026-05-19 21:24 132
40efdfde Poul Sander 2026-05-19 21:24 133
QModelIndex FsDirModel::rootIndex() const
40efdfde Poul Sander 2026-05-19 21:24 134
{
40efdfde Poul Sander 2026-05-19 21:24 135
    if (m_virtualRoot.children.isEmpty())
40efdfde Poul Sander 2026-05-19 21:24 136
        return {};
40efdfde Poul Sander 2026-05-19 21:24 137
    return createIndex(0, 0, m_virtualRoot.children.first());
40efdfde Poul Sander 2026-05-19 21:24 138
}
40efdfde Poul Sander 2026-05-19 21:24 139
40efdfde Poul Sander 2026-05-19 21:24 140
QByteArray FsDirModel::filePath(const QModelIndex &index) const
40efdfde Poul Sander 2026-05-19 21:24 141
{
40efdfde Poul Sander 2026-05-19 21:24 142
    if (!index.isValid())
40efdfde Poul Sander 2026-05-19 21:24 143
        return {};
40efdfde Poul Sander 2026-05-19 21:24 144
    return nodeForIndex(index)->nativePath;
40efdfde Poul Sander 2026-05-19 21:24 145
}
40efdfde Poul Sander 2026-05-19 21:24 146
40efdfde Poul Sander 2026-05-19 21:24 147
QModelIndex FsDirModel::indexForPath(const QByteArray &nativePath)
40efdfde Poul Sander 2026-05-19 21:24 148
{
40efdfde Poul Sander 2026-05-19 21:24 149
    if (nativePath.isEmpty() || m_virtualRoot.children.isEmpty())
40efdfde Poul Sander 2026-05-19 21:24 150
        return {};
40efdfde Poul Sander 2026-05-19 21:24 151
40efdfde Poul Sander 2026-05-19 21:24 152
    const fs::path target(nativePath.toStdString());
40efdfde Poul Sander 2026-05-19 21:24 153
    const fs::path root(m_virtualRoot.children.first()->nativePath.toStdString());
40efdfde Poul Sander 2026-05-19 21:24 154
40efdfde Poul Sander 2026-05-19 21:24 155
    // Collect the ancestry chain from root down to target
40efdfde Poul Sander 2026-05-19 21:24 156
    std::vector<fs::path> chain;
40efdfde Poul Sander 2026-05-19 21:24 157
    fs::path cur = target;
40efdfde Poul Sander 2026-05-19 21:24 158
    while (cur != root) {
40efdfde Poul Sander 2026-05-19 21:24 159
        chain.push_back(cur);
40efdfde Poul Sander 2026-05-19 21:24 160
        fs::path up = cur.parent_path();
40efdfde Poul Sander 2026-05-19 21:24 161
        if (up == cur)
40efdfde Poul Sander 2026-05-19 21:24 162
            return {}; // reached filesystem root without finding model root
40efdfde Poul Sander 2026-05-19 21:24 163
        cur = up;
40efdfde Poul Sander 2026-05-19 21:24 164
    }
40efdfde Poul Sander 2026-05-19 21:24 165
    // chain is [target, …, root_child]; reverse so we walk root→target
40efdfde Poul Sander 2026-05-19 21:24 166
    std::reverse(chain.begin(), chain.end());
40efdfde Poul Sander 2026-05-19 21:24 167
40efdfde Poul Sander 2026-05-19 21:24 168
    // Start at the root path node
40efdfde Poul Sander 2026-05-19 21:24 169
    Node *node = m_virtualRoot.children.first();
40efdfde Poul Sander 2026-05-19 21:24 170
    QModelIndex idx = createIndex(0, 0, node);
40efdfde Poul Sander 2026-05-19 21:24 171
40efdfde Poul Sander 2026-05-19 21:24 172
    for (const fs::path &step : chain) {
40efdfde Poul Sander 2026-05-19 21:24 173
        // Ensure this node's children are loaded
40efdfde Poul Sander 2026-05-19 21:24 174
        if (!node->populated) {
40efdfde Poul Sander 2026-05-19 21:24 175
            QList<Node *> children = listSubdirs(node);
40efdfde Poul Sander 2026-05-19 21:24 176
            if (!children.isEmpty()) {
40efdfde Poul Sander 2026-05-19 21:24 177
                beginInsertRows(idx, 0, children.size() - 1);
40efdfde Poul Sander 2026-05-19 21:24 178
                node->children = children;
40efdfde Poul Sander 2026-05-19 21:24 179
                node->populated = true;
40efdfde Poul Sander 2026-05-19 21:24 180
                endInsertRows();
40efdfde Poul Sander 2026-05-19 21:24 181
            } else {
40efdfde Poul Sander 2026-05-19 21:24 182
                node->populated = true;
40efdfde Poul Sander 2026-05-19 21:24 183
            }
40efdfde Poul Sander 2026-05-19 21:24 184
        }
40efdfde Poul Sander 2026-05-19 21:24 185
40efdfde Poul Sander 2026-05-19 21:24 186
        // Find the child whose nativePath matches step
40efdfde Poul Sander 2026-05-19 21:24 187
        const std::string stepStr = step.native();
40efdfde Poul Sander 2026-05-19 21:24 188
        bool found = false;
40efdfde Poul Sander 2026-05-19 21:24 189
        for (int i = 0; i < node->children.size(); ++i) {
40efdfde Poul Sander 2026-05-19 21:24 190
            if (node->children[i]->nativePath.toStdString() == stepStr) {
40efdfde Poul Sander 2026-05-19 21:24 191
                node = node->children[i];
40efdfde Poul Sander 2026-05-19 21:24 192
                idx  = createIndex(i, 0, node);
40efdfde Poul Sander 2026-05-19 21:24 193
                found = true;
40efdfde Poul Sander 2026-05-19 21:24 194
                break;
40efdfde Poul Sander 2026-05-19 21:24 195
            }
40efdfde Poul Sander 2026-05-19 21:24 196
        }
40efdfde Poul Sander 2026-05-19 21:24 197
        if (!found)
40efdfde Poul Sander 2026-05-19 21:24 198
            return {};
40efdfde Poul Sander 2026-05-19 21:24 199
    }
40efdfde Poul Sander 2026-05-19 21:24 200
40efdfde Poul Sander 2026-05-19 21:24 201
    return idx;
40efdfde Poul Sander 2026-05-19 21:24 202
}
40efdfde Poul Sander 2026-05-19 21:24 203
40efdfde Poul Sander 2026-05-19 21:24 204
// ---------------------------------------------------------------------------
40efdfde Poul Sander 2026-05-19 21:24 205
// QAbstractItemModel interface
40efdfde Poul Sander 2026-05-19 21:24 206
// ---------------------------------------------------------------------------
40efdfde Poul Sander 2026-05-19 21:24 207
40efdfde Poul Sander 2026-05-19 21:24 208
FsDirModel::Node *FsDirModel::nodeForIndex(const QModelIndex &index) const
40efdfde Poul Sander 2026-05-19 21:24 209
{
40efdfde Poul Sander 2026-05-19 21:24 210
    if (!index.isValid())
40efdfde Poul Sander 2026-05-19 21:24 211
        return const_cast<Node *>(&m_virtualRoot);
40efdfde Poul Sander 2026-05-19 21:24 212
    return static_cast<Node *>(index.internalPointer());
40efdfde Poul Sander 2026-05-19 21:24 213
}
40efdfde Poul Sander 2026-05-19 21:24 214
40efdfde Poul Sander 2026-05-19 21:24 215
QModelIndex FsDirModel::indexForNode(Node *node) const
40efdfde Poul Sander 2026-05-19 21:24 216
{
40efdfde Poul Sander 2026-05-19 21:24 217
    if (!node || node == &m_virtualRoot)
40efdfde Poul Sander 2026-05-19 21:24 218
        return {};
40efdfde Poul Sander 2026-05-19 21:24 219
    Node *parentNode = node->parent;
40efdfde Poul Sander 2026-05-19 21:24 220
    int row = parentNode->children.indexOf(node);
40efdfde Poul Sander 2026-05-19 21:24 221
    if (row < 0)
40efdfde Poul Sander 2026-05-19 21:24 222
        return {};
40efdfde Poul Sander 2026-05-19 21:24 223
    return createIndex(row, 0, node);
40efdfde Poul Sander 2026-05-19 21:24 224
}
40efdfde Poul Sander 2026-05-19 21:24 225
40efdfde Poul Sander 2026-05-19 21:24 226
QModelIndex FsDirModel::index(int row, int column, const QModelIndex &parent) const
40efdfde Poul Sander 2026-05-19 21:24 227
{
40efdfde Poul Sander 2026-05-19 21:24 228
    if (column != 0)
40efdfde Poul Sander 2026-05-19 21:24 229
        return {};
40efdfde Poul Sander 2026-05-19 21:24 230
40efdfde Poul Sander 2026-05-19 21:24 231
    Node *parentNode = nodeForIndex(parent);
40efdfde Poul Sander 2026-05-19 21:24 232
    if (row < 0 || row >= parentNode->children.size())
40efdfde Poul Sander 2026-05-19 21:24 233
        return {};
40efdfde Poul Sander 2026-05-19 21:24 234
40efdfde Poul Sander 2026-05-19 21:24 235
    return createIndex(row, 0, parentNode->children[row]);
40efdfde Poul Sander 2026-05-19 21:24 236
}
40efdfde Poul Sander 2026-05-19 21:24 237
40efdfde Poul Sander 2026-05-19 21:24 238
QModelIndex FsDirModel::parent(const QModelIndex &index) const
40efdfde Poul Sander 2026-05-19 21:24 239
{
40efdfde Poul Sander 2026-05-19 21:24 240
    if (!index.isValid())
40efdfde Poul Sander 2026-05-19 21:24 241
        return {};
40efdfde Poul Sander 2026-05-19 21:24 242
40efdfde Poul Sander 2026-05-19 21:24 243
    Node *node       = static_cast<Node *>(index.internalPointer());
40efdfde Poul Sander 2026-05-19 21:24 244
    Node *parentNode = node->parent;
40efdfde Poul Sander 2026-05-19 21:24 245
40efdfde Poul Sander 2026-05-19 21:24 246
    if (!parentNode || parentNode == &m_virtualRoot)
40efdfde Poul Sander 2026-05-19 21:24 247
        return {};
40efdfde Poul Sander 2026-05-19 21:24 248
40efdfde Poul Sander 2026-05-19 21:24 249
    return indexForNode(parentNode);
40efdfde Poul Sander 2026-05-19 21:24 250
}
40efdfde Poul Sander 2026-05-19 21:24 251
40efdfde Poul Sander 2026-05-19 21:24 252
int FsDirModel::rowCount(const QModelIndex &parent) const
40efdfde Poul Sander 2026-05-19 21:24 253
{
40efdfde Poul Sander 2026-05-19 21:24 254
    return nodeForIndex(parent)->children.size();
40efdfde Poul Sander 2026-05-19 21:24 255
}
40efdfde Poul Sander 2026-05-19 21:24 256
40efdfde Poul Sander 2026-05-19 21:24 257
int FsDirModel::columnCount(const QModelIndex &) const
40efdfde Poul Sander 2026-05-19 21:24 258
{
40efdfde Poul Sander 2026-05-19 21:24 259
    return 1;
40efdfde Poul Sander 2026-05-19 21:24 260
}
40efdfde Poul Sander 2026-05-19 21:24 261
40efdfde Poul Sander 2026-05-19 21:24 262
QVariant FsDirModel::data(const QModelIndex &index, int role) const
40efdfde Poul Sander 2026-05-19 21:24 263
{
40efdfde Poul Sander 2026-05-19 21:24 264
    if (!index.isValid())
40efdfde Poul Sander 2026-05-19 21:24 265
        return {};
40efdfde Poul Sander 2026-05-19 21:24 266
40efdfde Poul Sander 2026-05-19 21:24 267
    const Node *node = static_cast<const Node *>(index.internalPointer());
40efdfde Poul Sander 2026-05-19 21:24 268
40efdfde Poul Sander 2026-05-19 21:24 269
    switch (role) {
40efdfde Poul Sander 2026-05-19 21:24 270
    case Qt::DisplayRole:
40efdfde Poul Sander 2026-05-19 21:24 271
        return node->displayName;
40efdfde Poul Sander 2026-05-19 21:24 272
    case Qt::DecorationRole:
40efdfde Poul Sander 2026-05-19 21:24 273
        return m_folderIcon;
40efdfde Poul Sander 2026-05-19 21:24 274
    default:
40efdfde Poul Sander 2026-05-19 21:24 275
        return {};
40efdfde Poul Sander 2026-05-19 21:24 276
    }
40efdfde Poul Sander 2026-05-19 21:24 277
}
40efdfde Poul Sander 2026-05-19 21:24 278
40efdfde Poul Sander 2026-05-19 21:24 279
bool FsDirModel::hasChildren(const QModelIndex &parent) const
40efdfde Poul Sander 2026-05-19 21:24 280
{
40efdfde Poul Sander 2026-05-19 21:24 281
    const Node *node = nodeForIndex(parent);
40efdfde Poul Sander 2026-05-19 21:24 282
    if (!node->populated)
40efdfde Poul Sander 2026-05-19 21:24 283
        return true; // optimistic: show expand arrow until we actually look
40efdfde Poul Sander 2026-05-19 21:24 284
    return !node->children.isEmpty();
40efdfde Poul Sander 2026-05-19 21:24 285
}
40efdfde Poul Sander 2026-05-19 21:24 286
40efdfde Poul Sander 2026-05-19 21:24 287
bool FsDirModel::canFetchMore(const QModelIndex &parent) const
40efdfde Poul Sander 2026-05-19 21:24 288
{
40efdfde Poul Sander 2026-05-19 21:24 289
    return !nodeForIndex(parent)->populated;
40efdfde Poul Sander 2026-05-19 21:24 290
}
40efdfde Poul Sander 2026-05-19 21:24 291
40efdfde Poul Sander 2026-05-19 21:24 292
void FsDirModel::fetchMore(const QModelIndex &parent)
40efdfde Poul Sander 2026-05-19 21:24 293
{
40efdfde Poul Sander 2026-05-19 21:24 294
    Node *node = nodeForIndex(parent);
40efdfde Poul Sander 2026-05-19 21:24 295
    if (node->populated)
40efdfde Poul Sander 2026-05-19 21:24 296
        return;
40efdfde Poul Sander 2026-05-19 21:24 297
40efdfde Poul Sander 2026-05-19 21:24 298
    QList<Node *> children = listSubdirs(node);
40efdfde Poul Sander 2026-05-19 21:24 299
    node->populated = true;
40efdfde Poul Sander 2026-05-19 21:24 300
40efdfde Poul Sander 2026-05-19 21:24 301
    if (children.isEmpty())
40efdfde Poul Sander 2026-05-19 21:24 302
        return;
40efdfde Poul Sander 2026-05-19 21:24 303
40efdfde Poul Sander 2026-05-19 21:24 304
    beginInsertRows(parent, 0, children.size() - 1);
40efdfde Poul Sander 2026-05-19 21:24 305
    node->children = children;
40efdfde Poul Sander 2026-05-19 21:24 306
    endInsertRows();
40efdfde Poul Sander 2026-05-19 21:24 307
}
1970-01-01 00:00 308