add basic chaiscript bindings

This commit is contained in:
Wieczorek Bartosz 2018-08-01 14:22:29 +02:00
parent 1496340495
commit c5b8020c90
16 changed files with 251 additions and 84 deletions

View File

@ -35,6 +35,7 @@ set(Sqlpp11_DIR "${CMAKE_BINARY_DIR}/local/lib/cmake/Sqlpp11")
set(wt_DIR "${CMAKE_BINARY_DIR}/local/lib/cmake/wt")
set(Sqlpp-connector-postgresql_DIR "${CMAKE_BINARY_DIR}/local/lib/cmake/sqlpp-connector-postgresql")
find_program(
CLANG_TIDY_EXE
NAMES "clang-tidy-5.0"

View File

@ -8,4 +8,5 @@ target_link_libraries(eedb
PRIVATE webapp
PRIVATE postgres_connector
PRIVATE dl
PRIVATE chaiscript_bindings
)

View File

@ -10,6 +10,9 @@
#include <Wt/WEnvironment.h>
#include <string_view>
#include <eedb/chai/chai_bindings.hpp>
static auto _createSinks() {
std::vector< spdlog::sink_ptr > sinks;
auto stdout_sink = spdlog::sinks::stdout_sink_mt::instance();
@ -48,9 +51,23 @@ std::unique_ptr< Wt::WApplication > createApplication(const Wt::WEnvironment & e
});
auto factory = std::make_unique< eedb::pg::FactoryImpl >(std::move(connection));
factory->init();
chaiscript::ChaiScript chai;
auto module = std::make_shared< chaiscript::Module >();
eedb::script::chai_bootstrap(*module);
chai.add(module);
chai.add_global(chaiscript::var(static_cast< eedb::Factory * >(factory.get())), "factory");
chai.add(chaiscript::fun([](std::string_view str) { return std::string{str}; }), "toStdString");
try {
chai.eval_file("/home/wieczbar/chai_test.chai");
} catch(chaiscript::exception::eval_error e) {
std::cout << e.pretty_print();
}
return eedb::WebApplicationFactory{}.create(std::move(factory), env);
}

View File

@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.9)
add_subdirectory(eedb)
add_subdirectory(chaiscript_bindings)
add_subdirectory(db)
add_subdirectory(auth)

View File

@ -0,0 +1,24 @@
set(LIB chaiscript_bindings)
#set(chaiscript_DIR "${CMAKE_BINARY_DIR}/local/lib")
find_package(PkgConfig)
set(${PKG_CONFIG_USE_CMAKE_PREFIX_PATH} ON)
# find packages
pkg_check_modules(chaiscript REQUIRED)
# create library
add_library(${LIB} src/chai_bindings.cpp )
# link all
target_include_directories(${LIB}
PUBLIC include
)
target_link_libraries(${LIB}
PUBLIC eedb_api
PRIVATE Boost::system
PRIVATE Boost::filesystem
)

View File

@ -0,0 +1,8 @@
#pragma once
#include <chaiscript/chaiscript.hpp>
namespace eedb::script {
void chai_bootstrap(chaiscript::Module & module);
}

View File

@ -0,0 +1,81 @@
#include <eedb/chai/chai_bindings.hpp>
#include <chaiscript/dispatchkit/bootstrap.hpp>
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
#include <chaiscript/utility/utility.hpp>
#include <eedb/Category.hpp>
#include <eedb/AuthIdentities.hpp>
#include <eedb/AuthInfo.hpp>
#include <eedb/AuthToken.hpp>
#include <eedb/AuthTokens.hpp>
#include <eedb/User.hpp>
#include <eedb/Users.hpp>
#include <eedb/Factory.hpp>
void eedb::script::chai_bootstrap(chaiscript::Module & module) {
using namespace chaiscript;
chaiscript::bootstrap::standard_library::string_type< std::string >("string", module);
/*******************
* CATEGORY
*******************/
module.add(user_type< CategoriesRepository >(), "CategoriesRepository");
module.add(fun(&CategoriesRepository::create), "create");
module.add(fun(&CategoriesRepository::root), "root");
module.add(user_type< exceptions::CategoryAddException >(), "CategoryAddException");
// module.add(constructor< exceptions::CategoryAddException(std::unique_ptr< Category >) >(), "CategoryAddException");
module.add(fun(&exceptions::CategoryAddException::what), "what");
chaiscript::utility::add_class< Category >(module,
"Category",
{},
{//
{fun(&Category::addChild), "addChild"},
{fun(&Category::attachTo), "attachTo"},
{fun(&Category::children), "children"},
{fun(&Category::detach), "detach"},
{fun(&Category::displayName), "displayName"},
{fun(&Category::parent), "parent"}});
module.add(user_type< CategoriesChildren >(), "CategoriesChildren");
bootstrap::standard_library::input_range_type< CategoriesChildren >("CategoriesChildren", module);
/*******************
* USER
*******************/
chaiscript::utility::add_class< User >(module,
"User",
{},
{//
{fun(&User::authIdentities), "authIdentities"},
{fun(&User::authInfo), "authInfo"},
{fun(&User::authTokens), "authTokens"},
{fun(&User::config), "config"}});
chaiscript::utility::add_class< AuthIdentities >(module,
"AuthIdentities",
{},
{//
{fun(&AuthIdentities::removeProvider), "removeProvider"}});
/********************
* FACTORY
********************/
chaiscript::utility::add_class< Factory >(module,
"Factory",
{},
{//
{fun(&Factory::categoriesRepository), "categoriesRepository"}});
// module.add(fun(&Factory::itemsRepository), "itemsRepository");
}

View File

@ -52,7 +52,7 @@ class CategoryImpl : public impl::PgCategory {
Category * parent() const override;
Category * addChild(std::unique_ptr< Category > category) noexcept(false) override;
Category * addChild(std::unique_ptr< Category > && category) noexcept(false) override;
CategoriesChildren children() const override;

View File

@ -36,7 +36,7 @@ class CategoryMock : public impl::PgCategory {
MOCK_CONST_METHOD0(path, std::string_view());
MOCK_CONST_METHOD0(parent, Category *());
MOCK_METHOD1(doAddChild, Category *( Category * ) );
Category * addChild(std::unique_ptr< Category > c) {
Category * addChild(std::unique_ptr< Category > &&c) {
return doAddChild(c.get());
}
MOCK_CONST_METHOD0(children, CategoriesChildren());

View File

@ -177,7 +177,7 @@ struct CategoryImpl::CategoryImplPrivate {
return _parent;
}
auto displayName() const {
const auto & displayName() const {
return _name;
}
@ -217,7 +217,7 @@ Category * CategoryImpl::parent() const {
return _priv->parent();
}
Category * CategoryImpl::addChild(std::unique_ptr< Category > category) noexcept(false) {
Category * CategoryImpl::addChild(std::unique_ptr< Category > && category) noexcept(false) {
return _priv->addChild(std::move(category));
}

View File

@ -4,6 +4,7 @@
#include <eedb/AuthInfoConst.hpp>
#include <eedb/pg/CategoriesRepository.hpp>
#include <eedb/pg/Category.hpp>
#include <eedb/pg/ItemsRepository.hpp>
#include <eedb/pg/Session.hpp>
#include <eedb/pg/Stats.hpp>
@ -66,6 +67,44 @@ void FactoryImpl::init() {
(*_connection)(insert_into(t_category).set(set_rootCategoryValues()));
}
details::session_set_user_id((*_connection), _global_root_uid);
// CategoriesRepositoryImpl repo{(*_connection)};
// auto rootId = dynamic_cast< CategoryImpl * >(repo.root().get())->id();
// try{
// auto cat1 = (*_connection)(sqlpp::postgresql::insert_into(t_category)
// .set(t_category.owner = app_root_id(),
// t_category.status = 0,
// t_category.parent_id = rootId,
// t_category.name = "cat123",
// t_category.description = "cat123")
// .returning(t_category.id))
// .front()
// .id;
// auto cat2 = (*_connection)(sqlpp::postgresql::insert_into(t_category)
// .set(t_category.owner = app_root_id(),
// t_category.status = 0,
// t_category.parent_id = rootId,
// t_category.name = "cat2123",
// t_category.description = "cat2123")
// .returning(t_category.id))
// .front()
// .id;
// auto cat3 = (*_connection)(sqlpp::postgresql::insert_into(t_category)
// .set(t_category.owner = app_root_id(),
// t_category.status = 0,
// t_category.parent_id = cat2,
// t_category.name = "cat3123",
// t_category.description = "cat3123")
// .returning(t_category.id))
// .front()
// .id;
// } catch (const sqlpp::postgresql::failure &f){
// std::cout << f.what() << '\n';
// }
}
std::unique_ptr< Users > FactoryImpl::usersRepository() const {

View File

@ -29,7 +29,7 @@ class CategoriesRepository {
};
namespace details {
using CategoryPtrIterator = IteratorTypeErasure::any_iterator< Category *, std::forward_iterator_tag, Category * >;
using CategoryPtrIterator = IteratorTypeErasure::any_iterator< Category *, std::bidirectional_iterator_tag, Category * >;
using CategoryPtrIteratorRange = boost::iterator_range< CategoryPtrIterator >;
} // namespace details
@ -90,7 +90,7 @@ class Category {
* @throws CategoryAddException()
* @return pointer to newely added category
*/
virtual Category * addChild(std::unique_ptr< Category > category) = 0;
virtual Category * addChild(std::unique_ptr< Category > && category) = 0;
/**
* @brief children

View File

@ -2,7 +2,11 @@
#include <widget/CategoryThree.hpp>
#include <vector>
#include <map>
namespace Wt {
class WTreeNode;
}
namespace eedb {
@ -20,8 +24,12 @@ class DefaultCategoriesTree final : public CategoriesTree {
void registerOnCategoryChanged(std::function< void(const Category *) >) override;
private:
std::unique_ptr< CategoriesRepository > _categories;
void handleTreeNodeSelect() ;
std::unique_ptr< Category > _root;
std::map< Wt::WTreeNode *, const Category * > _categories;
Wt::Signal< const Category * > _categorySelected;
std::function< void(Wt::WTreeNode *) > registerForUpdate;
};
} // namespace eedb

View File

@ -12,7 +12,7 @@ class CategoryMock : public Category {
MOCK_CONST_METHOD0(displayName, string_view());
MOCK_CONST_METHOD0(parent, Category *());
MOCK_METHOD1(doAddChild, Category *( Category * ) );
Category * addChild(std::unique_ptr< Category > c) {
Category * addChild(std::unique_ptr< Category > && c) {
return doAddChild(c.get());
}
MOCK_CONST_METHOD0(children, CategoriesChildren());

View File

@ -8,8 +8,7 @@
namespace eedb {
DefaultCategoriesTree::DefaultCategoriesTree(std::unique_ptr< CategoriesRepository > categories)
: _categories{std::move(categories)}, _root{_categories->root()} {
DefaultCategoriesTree::DefaultCategoriesTree(std::unique_ptr< CategoriesRepository > categories) : _root{categories->root()} {
using namespace Wt;
setObjectName(widget_name());
@ -22,58 +21,53 @@ DefaultCategoriesTree::DefaultCategoriesTree(std::unique_ptr< CategoriesReposito
treeRoot()->setChildCountPolicy(Wt::ChildCountPolicy::Disabled);
treeRoot()->setLoadPolicy(ContentLoading::NextLevel);
treeRoot()->selected().connect([root = _root.get()](bool e) {
for(const auto child : root->children()) {
auto name = std::string{child->displayName()};
/// TODO load image into WTreeNode
auto node = cpp14::make_unique< WTreeNode >(name);
node->selected().connect( [name](bool selected){
if(selected){
std::cout << "selected category: " << name;
}
} );
itemSelectionChanged().connect(this, &DefaultCategoriesTree::handleTreeNodeSelect);
auto saveCategory = [=](auto node, const auto child) {
if(_categories.find(node) == _categories.end()) {
assert(node);
assert(child);
_categories[node] = child;
}
});
};
// treeRoot()->addChildNode(cpp14::make_unique< WTreeNode >("Table"))->selected().connect([](bool selected) {
// if(selected)
// std::cout << "selected Table\n";
// });
auto populate = [=](WTreeNode * parent, const Category * child) {
auto node = parent->addChildNode(cpp14::make_unique< WTreeNode >(std::string{child->displayName()}));
saveCategory(node, child);
return node;
};
// treeRoot()->addChildNode(cpp14::make_unique< WTreeNode >("Cupboard"))->selected().connect([](bool selected) {
// if(selected)
// std::cout << "selected Cupboard\n";
// });
registerForUpdate = [=](WTreeNode * node) {
node->selected().connect([&, n=node](bool selected) {
if(selected) {
for(const auto child : _categories[n]->children()) {
populate(n, child);
registerForUpdate(n);
}
}
});
};
// auto subtree = cpp14::make_unique< WTreeNode >("Chair");
// auto subtree_ = treeRoot()->addChildNode(std::move(subtree));
// treeRoot()->addChildNode(cpp14::make_unique< WTreeNode >("Coach"));
// treeRoot()->expand();
// subtree_->addChildNode(cpp14::make_unique< WTreeNode >("Doc"));
// subtree_->addChildNode(cpp14::make_unique< WTreeNode >("Grumpy"));
// subtree_->addChildNode(cpp14::make_unique< WTreeNode >("Happy"));
// subtree_->addChildNode(cpp14::make_unique< WTreeNode >("Sneezy"));
// subtree_->addChildNode(cpp14::make_unique< WTreeNode >("Dopey"));
// subtree_->addChildNode(cpp14::make_unique< WTreeNode >("Bashful"));
// subtree_->addChildNode(cpp14::make_unique< WTreeNode >("Sleepy"));
// Wt::WTreeNode node{""};
// auto root_category = categories->root();
// node.selected().connect([ this, category = root_category.get() ](auto selected) {
// if(selected)
// this->_categorySelected(category);
// });
// node.expanded()
// auto children = root_category->children();
// for(const auto & category : *children) {
// }
for(const auto child : _root->children()) {
/// TODO load image into WTreeNode
auto node = populate(treeRoot(), child);
registerForUpdate(node);
}
}
void DefaultCategoriesTree::registerOnCategoryChanged(std::function< void(const Category *) >) {}
void DefaultCategoriesTree::registerOnCategoryChanged(std::function< void(const Category *) > cb) {
_categorySelected.connect(cb);
}
void DefaultCategoriesTree::handleTreeNodeSelect() {
auto allSelected = selectedNodes();
if(allSelected.size() == 1) {
const auto selected = *allSelected.begin();
const auto category = _categories.find(selected)->second;
_categorySelected.emit(category);
}
}
} // namespace eedb

View File

@ -20,6 +20,7 @@
#include <widget/NavigationBar.hpp>
#include <eedb/Session.hpp>
#include <eedb/Category.hpp>
namespace eedb {
@ -27,37 +28,28 @@ eedb::DefaultHomePage::DefaultHomePage(Session & session,
std::unique_ptr< NavigationBar > navigationBar,
std::unique_ptr< CategoriesTree > tree)
: _session(session) {
auto stackedWidget = std::make_unique< Wt::WStackedWidget >();
// navigationBar->registerLogoutAction([=]() { this->_session.login().logout(); });
stackedWidget->addWidget(std::move(navigationBar));
// _navigationBar->attachTo(stackedWidget.get());
navigationBar->registerLogoutAction([=]() { this->_session.logout(); });
auto vbox = std::make_unique< Wt::WVBoxLayout >();
vbox->setPreferredImplementation(Wt::LayoutImplementation::JavaScript);
{
auto hbox = std::make_unique< Wt::WHBoxLayout >();
hbox->setPreferredImplementation(Wt::LayoutImplementation::JavaScript);
{
// auto tree = make_tree();
// tree->clicked().connect([](Wt::WModelIndex, Wt::WMouseEvent) { Wt::log("notice") << "Item selection changed"; });
// /// TODO #7 collumn size based on the actual size of text
// tree->setColumnWidth(0, 100.0);
hbox->addWidget(std::move(tree), 1);
}
{
auto contents = std::make_unique< Wt::WStackedWidget >();
contents->setId("contents");
hbox->addWidget(std::move(contents), 2);
}
hbox->setResizable(0, true);
auto stackedWidget = vbox->addWidget(std::make_unique< Wt::WStackedWidget >(), 0);
stackedWidget->addWidget(std::move(navigationBar));
vbox->addWidget(std::move(stackedWidget), 0);
vbox->addLayout(std::move(hbox), 20);
}
auto hbox = vbox->addLayout(std::make_unique< Wt::WHBoxLayout >(), 20);
hbox->setPreferredImplementation(Wt::LayoutImplementation::JavaScript);
auto catTree = hbox->addWidget(std::move(tree), 1);
/// TODO #7 collumn size based on the actual size of text
// tree->setColumnWidth(0, 100.0);
auto contents = hbox->addWidget(std::make_unique< Wt::WStackedWidget >(), 2);
auto text = contents->addWidget(std::make_unique< Wt::WText >("some text"));
catTree->registerOnCategoryChanged([text](const Category * cat) { text->setText(std::string{cat->displayName()}); });
hbox->setResizable(0, true);
this->setLayout(std::move(vbox));
}