Skip to content

Instantly share code, notes, and snippets.

@RockinRoel
Created May 20, 2020 12:25
Show Gist options
  • Save RockinRoel/27ec5be4a785888c465a5121e3216a58 to your computer and use it in GitHub Desktop.
Save RockinRoel/27ec5be4a785888c465a5121e3216a58 to your computer and use it in GitHub Desktop.
#include <Wt/WAbstractItemModel.h>
#include <Wt/WApplication.h>
#include <Wt/WContainerWidget.h>
#include <Wt/WModelIndex.h>
#include <Wt/WStandardItem.h>
#include <Wt/WStandardItemModel.h>
#include <Wt/WTreeView.h>
#include <algorithm>
#include <iterator>
#include <memory>
namespace ModelIterators {
class ColumnIterator final {
public:
using difference_type = int;
using value_type = Wt::WModelIndex;
using reference = const value_type &;
using pointer = const value_type *;
using iterator_category = std::forward_iterator_tag;
// past the end iterator
ColumnIterator();
// column iterator starting from index
ColumnIterator(const Wt::WModelIndex &index);
// copy ctor
ColumnIterator(const ColumnIterator &other);
// copy assignment
ColumnIterator& operator=(const ColumnIterator &other);
// move ctor deleted
ColumnIterator(ColumnIterator &&) = delete;
// move assignment deleted
ColumnIterator& operator=(ColumnIterator &&) = delete;
// equality
bool operator==(const ColumnIterator &other) const;
// inequality
bool operator!=(const ColumnIterator &other) const;
// deref
const Wt::WModelIndex &operator*() const;
// arrow
const Wt::WModelIndex *operator->() const;
// preincrement
ColumnIterator& operator++();
// postincrement
ColumnIterator operator++(int);
private:
Wt::WModelIndex index_;
};
void swap(ColumnIterator &it1, ColumnIterator &it2);
ColumnIterator::ColumnIterator()
{ }
ColumnIterator::ColumnIterator(const Wt::WModelIndex &index)
: index_(index)
{ }
ColumnIterator::ColumnIterator(const ColumnIterator &other)
: index_(other.index_)
{ }
ColumnIterator& ColumnIterator::operator=(const ColumnIterator &other)
{
index_ = other.index_;
return *this;
}
bool ColumnIterator::operator==(const ColumnIterator &other) const
{
return index_ == other.index_;
}
bool ColumnIterator::operator!=(const ColumnIterator &other) const
{
return index_ != other.index_;
}
const Wt::WModelIndex &ColumnIterator::operator*() const
{
return index_;
}
const Wt::WModelIndex *ColumnIterator::operator->() const
{
return &index_;
}
ColumnIterator& ColumnIterator::operator++()
{
if (!index_.isValid())
return *this;
const Wt::WAbstractItemModel * const model = index_.model();
// first: child?
const Wt::WModelIndex child = index_.child(0, index_.column());
if (child.isValid()) {
index_ = child;
return *this;
}
// then: sibling?
const Wt::WModelIndex sibling = model->index(index_.row() + 1, index_.column(), index_.parent());
if (sibling.isValid()) {
index_ = sibling;
return *this;
}
// finally: (great*)uncle?
for (Wt::WModelIndex ancestor = index_.parent();
ancestor.isValid();
ancestor = ancestor.parent()) {
const Wt::WModelIndex uncle = model->index(ancestor.row() + 1, ancestor.column(), ancestor.parent());
if (uncle.isValid()) {
index_ = uncle;
return *this;
}
}
// if everything fails: past the end iterator
index_ = Wt::WModelIndex();
return *this;
}
ColumnIterator ColumnIterator::operator++(int)
{
ColumnIterator old = *this;
++*this;
return old;
}
void swap(ColumnIterator &it1, ColumnIterator &it2)
{
ColumnIterator tmp = it1;
it1 = it2;
it2 = tmp;
}
}
void fillModel(Wt::WStandardItem *item,
int &index,
int count,
int maxDepth,
int currentDepth = 0)
{
if (currentDepth == maxDepth) {
return;
}
for (int r = 0; r < count; ++r) {
auto subItem = std::make_unique<Wt::WStandardItem>(Wt::utf8("{1}").arg(index));
++index;
fillModel(subItem.get(), index, count, maxDepth, currentDepth + 1);
item->appendRow(std::move(subItem));
}
}
int main(int argc, char *argv[])
{
return Wt::WRun(argc, argv, [](const Wt::WEnvironment &env) {
auto app = std::make_unique<Wt::WApplication>(env);
auto root = app->root();
auto model = std::make_shared<Wt::WStandardItemModel>();
int index = 0;
fillModel(model->invisibleRootItem(), index, 10, 3);
auto tv = root->addNew<Wt::WTreeView>();
tv->setModel(model);
tv->resize(500, 500);
std::for_each(ModelIterators::ColumnIterator(model->index(0, 0)),
ModelIterators::ColumnIterator(),
[](const Wt::WModelIndex &index) {
std::cout << "R: " << index.row() << ", C: " << index.column() << ", V: " << Wt::asString(index.data()).toUTF8() << '\n';
});
return app;
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment