Skip to content

Commit

Permalink
libgui|Widgets: Basic implementation of DirectoryTreeData
Browse files Browse the repository at this point in the history
  • Loading branch information
skyjake committed Sep 1, 2019
1 parent 9a3a54b commit e0d1f1b
Show file tree
Hide file tree
Showing 8 changed files with 194 additions and 12 deletions.
11 changes: 6 additions & 5 deletions doomsday/libs/core/include/de/filesys/folder.h
Expand Up @@ -75,7 +75,7 @@ class DE_PUBLIC Folder : public File
PopulateAsync = 0x4, ///< Do not block until complete.
PopulateAsyncFullTree = PopulateAsync | PopulateFullTree,

PopulateCalledRecursively = 0x1000, // internal use
DisableNotification = 0x1000, // internal use
};
using PopulationBehaviors = Flags;

Expand Down Expand Up @@ -127,10 +127,11 @@ class DE_PUBLIC Folder : public File
List<Folder *> subfolders() const;

/**
* Empties the contents of the folder: all contained file instances are
* deleted. Attached feeds are not notified, which means the source data
* they translate into the folder remains untouched. This is called
* automatically when the Folder instance is deleted.
* Unpopulates the folder, i.e., deletes all contained File objects.
* The attached feeds are not notified, which means the source data they translate
* remains untouched.
*
* Called automatically when the Folder instance is deleted.
*/
void clear();

Expand Down
6 changes: 3 additions & 3 deletions doomsday/libs/core/src/filesys/folder.cpp
Expand Up @@ -202,7 +202,7 @@ void Folder::clear()
// Destroy all the file objects.
for (Contents::iterator i = d->contents.begin(); i != d->contents.end(); ++i)
{
i->second->setParent(0);
i->second->setParent(nullptr);
delete i->second;
}
d->contents.clear();
Expand Down Expand Up @@ -302,7 +302,7 @@ void Folder::populate(PopulationBehaviors behavior)
// Call populate on subfolders.
for (Folder *folder : d->subfolders())
{
folder->populate(behavior | PopulateCalledRecursively);
folder->populate(behavior | DisableNotification);
}
}

Expand All @@ -327,7 +327,7 @@ void Folder::populate(PopulationBehaviors behavior)

// Each population gets an individual notification since they're done synchronously.
// However, only notify once a full hierarchy of populations has finished.
if (!(behavior & PopulateCalledRecursively))
if (!(behavior & DisableNotification))
{
internal::populationNotifier.notify();
}
Expand Down
2 changes: 2 additions & 0 deletions doomsday/libs/gui/include/de/DirectoryTreeData
@@ -0,0 +1,2 @@
#include "gui/directorytreedata.h"

64 changes: 64 additions & 0 deletions doomsday/libs/gui/include/de/gui/directorytreedata.h
@@ -0,0 +1,64 @@
/** @file directorytreedata.h Native filesystem directory tree.
*
* @authors Copyright (c) 2019 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* @par License
* LGPL: http://www.gnu.org/licenses/lgpl.html
*
* <small>This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or (at your
* option) any later version. This program is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details. You should have received a copy of
* the GNU Lesser General Public License along with this program; if not, see:
* http://www.gnu.org/licenses</small>
*/

#pragma once

#include "../ui/Item"
#include "../ui/TreeData"
#include <de/File>

namespace de {

class LIBGUI_PUBLIC DirectoryTreeData : public ui::TreeData
{
public:
/**
* Item in the directory tree data model (i.e., file or subdirectory).
*/
class LIBGUI_PUBLIC DirectoryItem : public ui::Item
{
public:
DirectoryItem(const String &name, const File::Status &status, const Path &directory)
: ui::Item(DefaultSemantics, name)
, _status(status)
, _directory(directory)
{
setLabel(name);
}

String name() const { return label(); }
File::Status status() const { return _status; }
Path path() const { return _directory / name(); }

private:
File::Status _status;
const Path & _directory;
};

public:
DirectoryTreeData();

// Implements ui::TreeData.
bool contains(const Path &path) const override;
const ui::Data &items(const Path &path) const override;

private:
DE_PRIVATE(d)
};

} // namespace de
42 changes: 42 additions & 0 deletions doomsday/libs/gui/include/de/gui/treedata.h
@@ -0,0 +1,42 @@
/** @file treedata.h Data model for a tree of lists.
*
* @authors Copyright (c) 2019 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* @par License
* LGPL: http://www.gnu.org/licenses/lgpl.html
*
* <small>This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or (at your
* option) any later version. This program is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details. You should have received a copy of
* the GNU Lesser General Public License along with this program; if not, see:
* http://www.gnu.org/licenses</small>
*/

#pragma once

#include "../ui/Data"
#include <de/Path>

namespace de {
namespace ui {

/**
* Data model representing a tree of lists.
*
* @ingroup uidata
*/
class LIBGUI_PUBLIC TreeData
{
public:
virtual ~TreeData() = default;

virtual bool contains(const Path &path) const = 0;
virtual const Data &items(const Path &path) const = 0;
};

} // namespace ui
} // namespace de
2 changes: 2 additions & 0 deletions doomsday/libs/gui/include/de/ui/TreeData
@@ -0,0 +1,2 @@
#include "../gui/treedata.h"

5 changes: 1 addition & 4 deletions doomsday/libs/gui/include/de/widgets/browserwidget.h
Expand Up @@ -16,8 +16,7 @@
* http://www.gnu.org/licenses</small>
*/

#ifndef LIBAPPFW_BROWSERWIDGET_H
#define LIBAPPFW_BROWSERWIDGET_H
#pragma once

#include <de/GuiWidget>

Expand All @@ -38,5 +37,3 @@ class LIBGUI_PUBLIC BrowserWidget : public GuiWidget
};

} // namespace de

#endif // LIBAPPFW_BROWSERWIDGET_H
74 changes: 74 additions & 0 deletions doomsday/libs/gui/src/directorytreedata.cpp
@@ -0,0 +1,74 @@
/** @file directorytreedata.cpp Native filesystem directory tree.
*
* @authors Copyright (c) 2019 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* @par License
* LGPL: http://www.gnu.org/licenses/lgpl.html
*
* <small>This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or (at your
* option) any later version. This program is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details. You should have received a copy of
* the GNU Lesser General Public License along with this program; if not, see:
* http://www.gnu.org/licenses</small>
*/

#include "de/DirectoryTreeData"
#include "de/ui/ListData"

#include <de/DirectoryFeed>
#include <de/Folder>

namespace de {

DE_PIMPL(DirectoryTreeData)
{
NativePath dir;
ui::ListDataT<DirectoryItem> items;

Impl(Public *i) : Base(i)
{}

void populate(const NativePath &path)
{
// Get rid of the previous contents.
items.clear();

// Populate a folder with the directory contents.
dir = path;
Folder folder(path.fileName());
folder.attach(new DirectoryFeed(dir));
folder.populate(Folder::PopulateOnlyThisFolder | Folder::DisableNotification);

// Create corresponding data items.
for (const auto &entry : folder.contents())
{
items << new DirectoryItem(entry.first, entry.second->status(), dir);
}

items.sort();
}
};

DirectoryTreeData::DirectoryTreeData()
: d(new Impl(this))
{}

bool DirectoryTreeData::contains(const Path &path) const
{
return NativePath(path).isDirectory();
}

const ui::Data &DirectoryTreeData::items(const Path &path) const
{
if (NativePath(path) != d->dir)
{
d->populate(path);
}
return d->items;
}

} // namespace de

0 comments on commit e0d1f1b

Please sign in to comment.