initial player stuff

This commit is contained in:
Blue 2018-08-05 00:52:16 +03:00 committed by Gitea
parent 4b60ece582
commit 00f26c431e
38 changed files with 1107 additions and 93 deletions

View File

@ -23,6 +23,7 @@ set(SOURCES
) )
add_executable(corax ${HEADERS} ${SOURCES}) add_executable(corax ${HEADERS} ${SOURCES})
add_subdirectory(models)
target_link_libraries(corax Qt5::Core) target_link_libraries(corax Qt5::Core)
target_link_libraries(corax Qt5::Network) target_link_libraries(corax Qt5::Network)
@ -31,10 +32,10 @@ target_link_libraries(corax wSocket)
target_link_libraries(corax wDispatcher) target_link_libraries(corax wDispatcher)
target_link_libraries(corax utils) target_link_libraries(corax utils)
target_link_libraries(corax wModel) target_link_libraries(corax wModel)
target_link_libraries(corax wController)
target_link_libraries(corax wServerUtils)
target_link_libraries(corax wDatabase) target_link_libraries(corax wDatabase)
target_link_libraries(corax tag) target_link_libraries(corax tag)
target_link_libraries(corax tools) target_link_libraries(corax tools)
target_link_libraries(corax coraxModels)
target_link_libraries(corax wServerUtils)
install(TARGETS corax RUNTIME DESTINATION bin) install(TARGETS corax RUNTIME DESTINATION bin)

View File

@ -90,11 +90,11 @@ void Corax::start()
server->listen(8080); server->listen(8080);
cout << "Registering models..." << endl; cout << "Registering models..." << endl;
attributes->registerModel(dispatcher, server); attributes->getRegistered(connector);
commands->registerModel(dispatcher, server); commands->getRegistered(connector);
for (; beg != end; ++beg) { for (; beg != end; ++beg) {
beg->second->registerModel(dispatcher, server); beg->second->getRegistered(connector);
} }
cout << "Opening caches..." << endl; cout << "Opening caches..." << endl;
@ -115,11 +115,11 @@ void Corax::stop()
std::map<W::String, ResourceCache*>::iterator end = caches.end(); std::map<W::String, ResourceCache*>::iterator end = caches.end();
cout << "Stopping corax..." << endl; cout << "Stopping corax..." << endl;
commands->unregisterModel(); commands->getUnregistered();
attributes->unregisterModel(); attributes->getUnregistered();
for (; beg != end; ++beg) { for (; beg != end; ++beg) {
beg->second->unregisterModel(); beg->second->getUnregistered();
} }
server->stop(); server->stop();
@ -169,10 +169,10 @@ void Corax::h_parseDirectory(const W::Event& ev)
if (itr != parsers.end()) { if (itr != parsers.end()) {
cout << "directory " << path.toString() << " is already being parsed" << endl; cout << "directory " << path.toString() << " is already being parsed" << endl;
} else { } else {
const W::Socket& socket = connector->getNodeSocket(W::String(u"Perturabo")); const W::Socket* socket = connector->getNodeSocket(W::String(u"Perturabo"));
ResourceCache* music = caches.at(W::String(u"music")); ResourceCache* music = caches.at(W::String(u"music"));
ResourceCache* images = caches.at(W::String(u"images")); ResourceCache* images = caches.at(W::String(u"images"));
Parser* parser = new Parser(&socket, dispatcher, music, images); Parser* parser = new Parser(socket, dispatcher, music, images);
parsers.insert(std::make_pair(path, parser)); parsers.insert(std::make_pair(path, parser));
connect(parser, SIGNAL(serviceMessage(const QString&)), SLOT(onModelServiceMessage(const QString&))); connect(parser, SIGNAL(serviceMessage(const QString&)), SLOT(onModelServiceMessage(const QString&)));

View File

@ -0,0 +1,21 @@
cmake_minimum_required(VERSION 2.8.12)
project(coraxModels)
find_package(Qt5Core REQUIRED)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(HEADERS
player.h
proxysong.h
)
set(SOURCES
player.cpp
proxysong.cpp
)
add_library(coraxModels STATIC ${HEADERS} ${SOURCES})
target_link_libraries(coraxModels wModel)

121
corax/models/player.cpp Normal file
View File

@ -0,0 +1,121 @@
#include "player.h"
M::Player::Player(const W::Address& address, QObject* parent):
M::Model(address, parent),
controls(),
views(),
playPauseBtn(new M::Button(address + W::Address{u"play"})),
_queueView(new M::List(address + W::Address{u"queueView"})),
_queue(),
current(0)
{
W::Handler* get = W::Handler::create(address + W::Address({u"get"}), this, &M::Player::_h_get);
W::Handler* hqueue = W::Handler::create(address + W::Address({u"queue"}), this, &M::Player::_h_queue);
addHandler(get);
addHandler(hqueue);
playPauseBtn->setLabel(W::String(u"play"));
playPauseBtn->setEnabled(false);
connect(playPauseBtn, SIGNAL(activated()), this, SLOT(onPlayPauseBtn()));
addModel(playPauseBtn);
addModel(_queueView);
controls.insert(std::make_pair(playPause, playPauseBtn->getAddress()));
views.insert(std::make_pair(queue, _queueView->getAddress()));
}
M::Player::~Player()
{
}
void M::Player::set(const W::Object& value)
{
throw 14; //what do you expect here? not implemented, and not sure it ever would be
}
void M::Player::set(W::Object* value)
{
set(*value);
}
M::Model::ModelType M::Player::getType() const
{
return M::Model::player;
}
void M::Player::h_subscribe(const W::Event& ev)
{
M::Model::h_subscribe(ev);
h_get(ev);
}
void M::Player::h_get(const W::Event& ev)
{
W::Vector* ctrls = new W::Vector();
ItemMap::const_iterator citr = controls.begin();
ItemMap::const_iterator cend = controls.end();
for (; citr != cend; ++citr) {
W::Vocabulary* cvc = new W::Vocabulary();
cvc->insert(u"type", new W::Uint64(cend->first));
cvc->insert(u"address", cend->second);
ctrls->push(cvc);
}
W::Vector* vws = new W::Vector();
ItemMap::const_iterator vitr = views.begin();
ItemMap::const_iterator vend = views.end();
for (; vitr != vend; ++vitr) {
W::Vocabulary* vvc = new W::Vocabulary();
vvc->insert(u"type", new W::Uint64(vend->first));
vvc->insert(u"address", vend->second);
vws->push(vvc);
}
W::Vocabulary* res = new W::Vocabulary();
res->insert(u"controls", ctrls);
res->insert(u"views", vws);
response(res, W::Address({u"get"}), ev);
}
void M::Player::onPlayPauseBtn()
{
}
void M::Player::h_queue(const W::Event& ev)
{
const W::Vocabulary& data = static_cast<const W::Vocabulary&>(ev.getData());
const W::Uint64& id = static_cast<const W::Uint64&>(data.at(u"id"));
ProxySong* song = new ProxySong(id, address + W::Address{u"currentPlayback"});
addModel(song);
if (current == 0) {
current = song;
views.insert(std::make_pair(currentPlayback, song->getAddress()));
W::Vocabulary* avc = new W::Vocabulary();
avc->insert(u"type", new W::Uint64(currentPlayback));
avc->insert(u"address", song->getAddress());
W::Vector* add = new W::Vector();
add->push(avc);
W::Vocabulary* res = new W::Vocabulary();
res->insert(u"add", add);
res->insert(u"remove", new W::Vector());
broadcast(res, W::Address{u"viewsChange"});
} else {
_queue.push_back(song);
_queueView->push(song->getAddress());
}
}

60
corax/models/player.h Normal file
View File

@ -0,0 +1,60 @@
#ifndef PLAYER_H
#define PLAYER_H
#include <map>
#include <deque>
#include <wModel/model.h>
#include <wModel/button.h>
#include <wModel/modelstring.h>
#include <wModel/list.h>
#include <wType/vocabulary.h>
#include <wType/vector.h>
#include <wType/address.h>
#include "proxysong.h"
/**
* @todo write docs
*/
namespace M {
class Player : public M::Model {
Q_OBJECT
public:
Player(const W::Address& address, QObject* parent = 0);
~Player();
void set(const W::Object & value) override;
void set(W::Object * value) override;
M::Model::ModelType getType() const override;
enum ItemType {
playPause,
currentPlayback,
queue
};
protected:
void h_subscribe(const W::Event & ev) override;
handler(get);
handler(queue);
private:
typedef std::map<ItemType, const W::Address&> ItemMap;
typedef std::deque<ProxySong*> Queue;
ItemMap controls;
ItemMap views;
M::Button* playPauseBtn;
M::List* _queueView;
Queue _queue;
ProxySong* current;
private slots:
void onPlayPauseBtn();
};
}
#endif // PLAYER_H

135
corax/models/proxysong.cpp Normal file
View File

@ -0,0 +1,135 @@
#include "proxysong.h"
ProxySong::ProxySong(const W::Uint64& p_id, const W::Address& p_address, QObject* parent):
M::Vocabulary(p_address, parent),
songCtrl(new C::Vocabulary(W::Address{u"songs", W::String(p_id.toString())})),
albumCtrl(0),
artistCtrl(0),
fileId(0),
_ready(false)
{
addController(songCtrl, W::String(u"Perturabo"));
connect(songCtrl, SIGNAL(newElement(const W::String&, const W::Object&)), SLOT(onSongNewElement(const W::String&, const W::Object&)));
connect(songCtrl, SIGNAL(removeElement(const W::String&)), SLOT(onSongRemoveElement(const W::String&)));
insert(W::String(u"id"), p_id);
insert(W::String(u"artist"), new W::String(u"undefined"));
insert(W::String(u"album"), new W::String(u"undefined"));
insert(W::String(u"name"), new W::String(u"undefined"));
insert(W::String(u"image"), new W::Uint64(0));
}
bool ProxySong::isReady() const
{
return _ready;
}
ProxySong::~ProxySong()
{
}
void ProxySong::onSongNewElement(const W::String& key, const W::Object& element)
{
if (key == u"name") {
insert(key, element);
} else if (key == u"audio") {
if (_ready) {
_ready = false;
emit notReady();
}
fileId = static_cast<const W::Uint64&>(element);
_ready = true;
emit ready();
} else if (key == u"artist") {
if (artistCtrl != 0) {
removeController(artistCtrl);
disconnect(artistCtrl, SIGNAL(newElement(const W::String&, const W::Object&)), this, SLOT(onArtistNewElement(const W::String&, const W::Object&)));
disconnect(artistCtrl, SIGNAL(removeElement(const W::String&)), this, SLOT(onAtristRemoveElement(const W::String&)));
artistCtrl->deleteLater();
}
const W::Uint64& aid = static_cast<const W::Uint64&>(element);
artistCtrl = new C::Vocabulary(W::Address{u"artists", W::String(aid.toString())});
addController(artistCtrl, W::String(u"Perturabo"));
connect(artistCtrl, SIGNAL(newElement(const W::String&, const W::Object&)), SLOT(onArtistNewElement(const W::String&, const W::Object&)));
connect(artistCtrl, SIGNAL(removeElement(const W::String&)), SLOT(onAtristRemoveElement(const W::String&)));
} else if (key == u"album") {
if (albumCtrl != 0) {
removeController(albumCtrl);
disconnect(albumCtrl, SIGNAL(newElement(const W::String&, const W::Object&)), this, SLOT(onAlbumNewElement(const W::String&, const W::Object&)));
disconnect(albumCtrl, SIGNAL(removeElement(const W::String&)), this, SLOT(onAlbumRemoveElement(const W::String&)));
albumCtrl->deleteLater();
}
const W::Uint64& aid = static_cast<const W::Uint64&>(element);
albumCtrl = new C::Vocabulary(W::Address{u"albums", W::String(aid.toString())});
addController(albumCtrl, W::String(u"Perturabo"));
connect(albumCtrl, SIGNAL(newElement(const W::String&, const W::Object&)), SLOT(onAlbumNewElement(const W::String&, const W::Object&)));
connect(albumCtrl, SIGNAL(removeElement(const W::String&)), SLOT(onAlbumRemoveElement(const W::String&)));
}
}
void ProxySong::onSongRemoveElement(const W::String& key)
{
if (key == u"name") {
insert(key, new W::String(u"undefined"));
} else if (key == u"audio") {
if (_ready) {
_ready = false;
fileId = W::Uint64(0);
emit notReady();
}
} else if (key == u"artist") {
if (artistCtrl != 0) {
removeController(artistCtrl);
disconnect(artistCtrl, SIGNAL(newElement(const W::String&, const W::Object&)), this, SLOT(onArtistNewElement(const W::String&, const W::Object&)));
disconnect(artistCtrl, SIGNAL(removeElement(const W::String&)), this, SLOT(onAtristRemoveElement(const W::String&)));
artistCtrl->deleteLater();
artistCtrl = 0;
}
} else if (key == u"album") {
if (albumCtrl != 0) {
removeController(albumCtrl);
disconnect(albumCtrl, SIGNAL(newElement(const W::String&, const W::Object&)), this, SLOT(onAlbumNewElement(const W::String&, const W::Object&)));
disconnect(albumCtrl, SIGNAL(removeElement(const W::String&)), this, SLOT(onAlbumRemoveElement(const W::String&)));
albumCtrl->deleteLater();
albumCtrl = 0;
}
}
}
void ProxySong::onAlbumNewElement(const W::String& key, const W::Object& element)
{
if (key == u"name") {
insert(W::String(u"album"), element);
} else if (key == u"image") {
insert(key, element);
}
}
void ProxySong::onAlbumRemoveElement(const W::String& key)
{
if (key == u"name") {
insert(W::String(u"album"), new W::String(u"undefined"));
} else if (key == u"image") {
insert(key, new W::Uint64(0));
}
}
void ProxySong::onArtistNewElement(const W::String& key, const W::Object& element)
{
if (key == u"name") {
insert(W::String(u"artist"), element);
}
}
void ProxySong::onArtistRemoveElement(const W::String& key)
{
if (key == u"name") {
insert(W::String(u"artist"), new W::String(u"undefined"));
}
}
const W::Uint64 & ProxySong::getFileId() const
{
return fileId;
}

47
corax/models/proxysong.h Normal file
View File

@ -0,0 +1,47 @@
#ifndef PROXYSONG_H
#define PROXYSONG_H
/**
* @todo write docs
*/
#include <wType/uint64.h>
#include <wType/address.h>
#include <wModel/vocabulary.h>
#include <wController/vocabulary.h>
class ProxySong : public M::Vocabulary {
Q_OBJECT
public:
ProxySong(const W::Uint64& p_id, const W::Address& p_address, QObject* parent = 0);
~ProxySong();
const W::Uint64& getFileId() const;
bool isReady() const;
signals:
void ready();
void notReady();
private:
C::Vocabulary* songCtrl;
C::Vocabulary* albumCtrl;
C::Vocabulary* artistCtrl;
W::Uint64 fileId;
bool _ready;
private slots:
void onSongNewElement(const W::String& key, const W::Object& element);
void onSongRemoveElement(const W::String& key);
void onAlbumNewElement(const W::String& key, const W::Object& element);
void onAlbumRemoveElement(const W::String& key);
void onArtistNewElement(const W::String& key, const W::Object& element);
void onArtistRemoveElement(const W::String& key);
};
#endif // PROXYSONG_H

View File

@ -276,3 +276,8 @@ bool C::Controller::isSubscribed()
{ {
return subscribed; return subscribed;
} }
const W::Address & C::Controller::getAddress() const
{
return address;
}

View File

@ -40,6 +40,7 @@ namespace C {
void subscribe(); void subscribe();
void unsubscribe(); void unsubscribe();
bool isSubscribed(); bool isSubscribed();
const W::Address& getAddress() const;
void removeHandler(W::Handler* handler); void removeHandler(W::Handler* handler);
void removeController(C::Controller* ctrl); void removeController(C::Controller* ctrl);

View File

@ -215,7 +215,7 @@ void ResourceCache::h_subscribeMember(const W::Event& ev)
M::File* modelRecord = M::File::create(readFile(*record), address + lastHops >> 1); M::File* modelRecord = M::File::create(readFile(*record), address + lastHops >> 1);
delete record; delete record;
addModel(modelRecord); addModel(modelRecord);
passToHandler(ev); passToLocalHandler(ev);
} catch (int err) { } catch (int err) {
if (err == 3) { if (err == 3) {
emit serviceMessage(QString("An attempt to create and subscribe record model in resourcecache, but it is not found. Event: ") + ev.toString().c_str()); emit serviceMessage(QString("An attempt to create and subscribe record model in resourcecache, but it is not found. Event: ") + ev.toString().c_str());

View File

@ -14,6 +14,7 @@ set(HEADERS
attributes.h attributes.h
icatalogue.h icatalogue.h
catalogue.h catalogue.h
button.h
file/file.h file/file.h
) )
@ -25,12 +26,13 @@ set(SOURCES
attributes.cpp attributes.cpp
icatalogue.cpp icatalogue.cpp
catalogue.cpp catalogue.cpp
button.cpp
file/file.cpp file/file.cpp
) )
add_library(wModel STATIC ${HEADERS} ${SOURCES}) add_library(wModel STATIC ${HEADERS} ${SOURCES})
target_link_libraries(wModel Qt5::Core) target_link_libraries(wModel Qt5::Core)
target_link_libraries(wModel wSocket) target_link_libraries(wModel wServerUtils)
target_link_libraries(wModel wDispatcher)
target_link_libraries(wModel wType) target_link_libraries(wModel wType)
target_link_libraries(wModel wController)

113
lib/wModel/button.cpp Normal file
View File

@ -0,0 +1,113 @@
#include "button.h"
M::Button::Button(const W::Address& address, QObject* parent):
M::Model(address, parent),
enabled(true),
hasImage(false),
hasLabel(false),
imageName(0),
label(0)
{
W::Handler* get = W::Handler::create(address + W::Address({u"get"}), this, &M::Button::_h_get);
W::Handler* activate = W::Handler::create(address + W::Address({u"activate"}), this, &M::Button::_h_activate);
addHandler(get);
addHandler(activate);
}
M::Button::~Button()
{
if (hasImage) {
delete imageName;
}
}
void M::Button::setImage(const W::String& p_image)
{
if (hasImage) {
if (*imageName != p_image) {
imageName = static_cast<W::String*>(p_image.copy());
W::Vocabulary* vc = new W::Vocabulary();
vc->insert(u"image", p_image);
broadcast(vc, W::Address{u"changeImage"});
}
} else {
imageName = static_cast<W::String*>(p_image.copy());
hasImage = true;
W::Vocabulary* vc = new W::Vocabulary();
vc->insert(u"image", p_image);
broadcast(vc, W::Address{u"setImage"});
}
hasImage = true;
}
void M::Button::setEnabled(bool p_enabled)
{
if (enabled != p_enabled) {
enabled = p_enabled;
W::Vocabulary* vc = new W::Vocabulary();
vc->insert(u"enable", new W::Boolean(enabled));
broadcast(vc, W::Address{u"setEnabled"});
}
}
void M::Button::setLabel(const W::String& p_label)
{
if (hasLabel) {
label->set(p_label);
} else {
label = new M::String(p_label, address + W::Address{u"label"});
addModel(label);
W::Vocabulary* vc = new W::Vocabulary();
vc->insert(u"hasLabel", new W::Boolean(true));
vc->insert(u"label", label->getAddress());
broadcast(vc, W::Address{u"setLabel"});
hasLabel = true;
}
}
void M::Button::h_subscribe(const W::Event& ev)
{
M::Model::h_subscribe(ev);
h_get(ev);
}
void M::Button::h_get(const W::Event& ev)
{
W::Vocabulary* vc = new W::Vocabulary();
vc->insert(u"hasImage", new W::Boolean(hasImage));
if (hasImage) {
vc->insert(u"image", imageName->copy());
}
vc->insert(u"hasLabel", new W::Boolean(hasLabel));
if (hasLabel) {
vc->insert(u"label", label->getAddress());
}
vc->insert(u"enabled", new W::Boolean(enabled));
response(vc, W::Address({u"get"}), ev);
}
void M::Button::h_activate(const W::Event& ev)
{
if (enabled) {
emit activated();
}
}
M::Model::ModelType M::Button::getType() const
{
return M::Model::button;
}
void M::Button::set(const W::Object& value)
{
throw 14; //what do you expect here? not implemented, and not sure it ever would be
}
void M::Button::set(W::Object* value)
{
set(*value);
}

52
lib/wModel/button.h Normal file
View File

@ -0,0 +1,52 @@
#ifndef BUTTON_H
#define BUTTON_H
#include <wModel/model.h>
#include <wModel/modelstring.h>
#include <wDispatcher/handler.h>
#include <wType/address.h>
#include <wType/event.h>
#include <wType/vocabulary.h>
#include <wType/boolean.h>
/**
* @todo write docs
*/
namespace M {
class Button : public Model {
Q_OBJECT
public:
Button(const W::Address& address, QObject* parent = 0);
~Button();
void setImage(const W::String& p_image);
void setLabel(const W::String& p_label);
void setEnabled(bool p_enabled);
M::Model::ModelType getType() const override;
void set(const W::Object & value) override;
void set(W::Object * value) override;
signals:
void activated() const;
protected:
void h_subscribe(const W::Event & ev) override;
handler(get);
handler(activate);
protected:
bool enabled;
bool hasImage;
bool hasLabel;
W::String* imageName;
M::String* label;
};
}
#endif // BUTTON_H

View File

@ -5,12 +5,12 @@ M::Model::Model(const W::Address p_address, QObject* parent):
address(p_address), address(p_address),
registered(false), registered(false),
subscribers(new Map()), subscribers(new Map()),
dispatcher(0), connector(0),
server(0),
subscribersCount(0), subscribersCount(0),
handlers(new HList()), handlers(new HList()),
properties(new W::Vector()), properties(new W::Vector()),
models(new MList()) models(new MList()),
controllers(new Controllers())
{ {
W::Handler* subscribe = W::Handler::create(address + W::Address({u"subscribe"}), this, &M::Model::_h_subscribe); W::Handler* subscribe = W::Handler::create(address + W::Address({u"subscribe"}), this, &M::Model::_h_subscribe);
W::Handler* unsubscribe = W::Handler::create(address + W::Address({u"unsubscribe"}), this, &M::Model::_h_unsubscribe); W::Handler* unsubscribe = W::Handler::create(address + W::Address({u"unsubscribe"}), this, &M::Model::_h_unsubscribe);
@ -21,7 +21,7 @@ M::Model::Model(const W::Address p_address, QObject* parent):
M::Model::~Model() M::Model::~Model()
{ {
if (registered) { if (registered) {
unregisterModel(); getUnregistered();
} }
MList::iterator itr = models->begin(); MList::iterator itr = models->begin();
@ -38,10 +38,18 @@ M::Model::~Model()
delete *hItr; delete *hItr;
} }
Controllers::iterator cItr = controllers->begin();
Controllers::iterator cEnd = controllers->end();
for (; cItr != cEnd; ++cItr) {
delete cItr->first;
}
delete subscribers; delete subscribers;
delete properties; delete properties;
delete handlers; delete handlers;
delete models; delete models;
delete controllers;
} }
void M::Model::addModel(M::Model* model) void M::Model::addModel(M::Model* model)
@ -49,7 +57,7 @@ void M::Model::addModel(M::Model* model)
models->push_back(model); models->push_back(model);
connect(model, SIGNAL(serviceMessage(const QString&)), SIGNAL(serviceMessage(const QString&))); connect(model, SIGNAL(serviceMessage(const QString&)), SIGNAL(serviceMessage(const QString&)));
if (registered) { if (registered) {
model->registerModel(dispatcher, server); model->getRegistered(connector);
} }
} }
@ -57,7 +65,7 @@ void M::Model::addHandler(W::Handler* handler)
{ {
handlers->push_back(handler); handlers->push_back(handler);
if (registered) { if (registered) {
dispatcher->registerHandler(handler); connector->registerHandler(handler);
} }
} }
@ -83,21 +91,20 @@ W::Address M::Model::getAddress() const
} }
void M::Model::registerModel(W::Dispatcher* dp, W::Server* srv) void M::Model::getRegistered(U::Connector* cn)
{ {
if (registered) { if (registered) {
emit serviceMessage(QString("Model ") + address.toString().c_str() + " is already registered"); emit serviceMessage(QString("Model ") + address.toString().c_str() + " is already registered");
throw 1; throw 1;
} else { } else {
dispatcher = dp; connector = cn;
server = srv;
MList::iterator itr = models->begin(); MList::iterator itr = models->begin();
MList::iterator end = models->end(); MList::iterator end = models->end();
for (; itr != end; ++itr) { for (; itr != end; ++itr) {
M::Model* model = *itr; M::Model* model = *itr;
model->registerModel(dispatcher, server); model->getRegistered(connector);
} }
HList::iterator hItr = handlers->begin(); HList::iterator hItr = handlers->begin();
@ -105,14 +112,21 @@ void M::Model::registerModel(W::Dispatcher* dp, W::Server* srv)
for (; hItr != hEnd; ++hItr) { for (; hItr != hEnd; ++hItr) {
W::Handler* handler = *hItr; W::Handler* handler = *hItr;
dispatcher->registerHandler(handler); connector->registerHandler(handler);
}
Controllers::iterator cItr = controllers->begin();
Controllers::iterator cEnd = controllers->end();
for (; cItr != cEnd; ++cItr) {
connector->registerController(cItr->first, cItr->second);
} }
registered = true; registered = true;
} }
} }
void M::Model::unregisterModel() void M::Model::getUnregistered()
{ {
if (!registered) { if (!registered) {
emit serviceMessage(QString("Model ") + address.toString().c_str() + " is not registered"); emit serviceMessage(QString("Model ") + address.toString().c_str() + " is not registered");
@ -123,7 +137,7 @@ void M::Model::unregisterModel()
for (; itr != end; ++itr) { for (; itr != end; ++itr) {
Model* model = *itr; Model* model = *itr;
model->unregisterModel(); model->getUnregistered();
} }
HList::iterator hItr = handlers->begin(); HList::iterator hItr = handlers->begin();
@ -131,21 +145,27 @@ void M::Model::unregisterModel()
for (; hItr != hEnd; ++hItr) { for (; hItr != hEnd; ++hItr) {
W::Handler* handler = *hItr; W::Handler* handler = *hItr;
dispatcher->unregisterHandler(handler); connector->unregisterHandler(handler);
} }
Map::iterator sItr = subscribers->begin(); Map::iterator sItr = subscribers->begin();
Map::iterator sEnd = subscribers->end(); Map::iterator sEnd = subscribers->end();
for (; sItr != sEnd; ++sItr) { for (; sItr != sEnd; ++sItr) {
const W::Socket& socket = server->getConnection(sItr->first); const W::Socket* socket = connector->getConnection(sItr->first);
disconnect(&socket, SIGNAL(disconnected()), this, SLOT(onSocketDisconnected())); disconnect(socket, SIGNAL(disconnected()), this, SLOT(onSocketDisconnected()));
} }
subscribers->clear(); subscribers->clear();
subscribersCount = 0; subscribersCount = 0;
dispatcher = 0; Controllers::iterator cItr = controllers->begin();
server = 0; Controllers::iterator cEnd = controllers->end();
for (; cItr != cEnd; ++cItr) {
connector->unregisterController(cItr->first, cItr->second);
}
connector = 0;
registered = false; registered = false;
} }
@ -162,7 +182,6 @@ void M::Model::h_subscribe(const W::Event& ev)
params = static_cast<const W::Vocabulary&>(vc.at(u"params")); params = static_cast<const W::Vocabulary&>(vc.at(u"params"));
} }
Map::iterator sItr = subscribers->find(id); Map::iterator sItr = subscribers->find(id);
if (sItr == subscribers->end()) { if (sItr == subscribers->end()) {
@ -171,8 +190,8 @@ void M::Model::h_subscribe(const W::Event& ev)
emit serviceMessage(QString("Model ") + address.toString().c_str() + ": something completely wrong happened"); emit serviceMessage(QString("Model ") + address.toString().c_str() + ": something completely wrong happened");
throw 3; throw 3;
} }
const W::Socket& socket = server->getConnection(id); const W::Socket* socket = connector->getConnection(id);
connect(&socket, SIGNAL(disconnected()), this, SLOT(onSocketDisconnected())); connect(socket, SIGNAL(disconnected()), this, SLOT(onSocketDisconnected()));
sItr = pair.first; sItr = pair.first;
} }
SMap::const_iterator oItr = sItr->second.find(source); SMap::const_iterator oItr = sItr->second.find(source);
@ -238,8 +257,8 @@ void M::Model::h_unsubscribe(const W::Event& ev)
smap.erase(sItr); smap.erase(sItr);
if (smap.size() == 0) { if (smap.size() == 0) {
const W::Socket& socket = server->getConnection(itr->first); const W::Socket* socket = connector->getConnection(itr->first);
disconnect(&socket, SIGNAL(disconnected()), this, SLOT(onSocketDisconnected())); disconnect(socket, SIGNAL(disconnected()), this, SLOT(onSocketDisconnected()));
subscribers->erase(itr); subscribers->erase(itr);
} }
--subscribersCount; --subscribersCount;
@ -256,7 +275,7 @@ void M::Model::send(W::Vocabulary* vc, const W::Address& destination, uint64_t c
} }
W::Event ev(destination, vc); W::Event ev(destination, vc);
ev.setSenderId(connectionId); ev.setSenderId(connectionId);
server->getConnection(connectionId).send(ev); connector->getConnection(connectionId)->send(ev);
} }
void M::Model::response(W::Vocabulary* vc, const W::Address& handlerAddress, const W::Event& src) void M::Model::response(W::Vocabulary* vc, const W::Address& handlerAddress, const W::Event& src)
@ -272,7 +291,7 @@ void M::Model::response(W::Vocabulary* vc, const W::Address& handlerAddress, con
W::Event ev(source + handlerAddress, vc); W::Event ev(source + handlerAddress, vc);
ev.setSenderId(id); ev.setSenderId(id);
server->getConnection(id).send(ev); connector->getConnection(id)->send(ev);
} }
void M::Model::fakeResponse(W::Vocabulary* vc, const W::Address& handlerAddress, const W::Address& sourceAddress, const W::Event& src) void M::Model::fakeResponse(W::Vocabulary* vc, const W::Address& handlerAddress, const W::Address& sourceAddress, const W::Event& src)
@ -288,7 +307,7 @@ void M::Model::fakeResponse(W::Vocabulary* vc, const W::Address& handlerAddress,
W::Event ev(source + handlerAddress, vc); W::Event ev(source + handlerAddress, vc);
ev.setSenderId(id); ev.setSenderId(id);
server->getConnection(id).send(ev); connector->getConnection(id)->send(ev);
} }
void M::Model::broadcast(W::Vocabulary* vc, const W::Address& handlerAddress) void M::Model::broadcast(W::Vocabulary* vc, const W::Address& handlerAddress)
@ -307,7 +326,7 @@ void M::Model::broadcast(W::Vocabulary* vc, const W::Address& handlerAddress)
for (;oItr != oEnd; ++oItr) { for (;oItr != oEnd; ++oItr) {
W::Event ev(oItr->first + handlerAddress, vc->copy()); W::Event ev(oItr->first + handlerAddress, vc->copy());
ev.setSenderId(itr->first); ev.setSenderId(itr->first);
server->getConnection(itr->first).send(ev); connector->getConnection(itr->first)->send(ev);
} }
} }
delete vc; delete vc;
@ -317,23 +336,54 @@ void M::Model::removeHandler(W::Handler* handler)
{ {
handlers->erase(handler); handlers->erase(handler);
if (registered) { if (registered) {
dispatcher->unregisterHandler(handler); connector->unregisterHandler(handler);
} }
} }
void M::Model::removeModel(M::Model* model) void M::Model::removeModel(M::Model* model)
{ {
models->erase(model); models->erase(model);
disconnect(model, SIGNAL(serviceMessage(const QString&)), this, SIGNAL(serviceMessage(const QString&)));
if (registered) { if (registered) {
model->unregisterModel(); model->getUnregistered();
} }
} }
void M::Model::passToHandler(const W::Event& event) const void M::Model::passToLocalHandler(const W::Event& event) const
{ {
if (registered) { if (registered) {
dispatcher->pass(event); connector->passThroughDispatcher(event);
} else { } else {
emit serviceMessage(QString("An attempt to pass event to dispatcher from unregistered model\nModel address ") + address.toString().c_str()); emit serviceMessage(QString("An attempt to pass event to dispatcher from unregistered model\nModel address ") + address.toString().c_str());
} }
} }
void M::Model::addController(C::Controller* ctrl, const W::String& nodeName)
{
Controllers::const_iterator itr = controllers->find(ctrl);
if (itr != controllers->end()) {
emit serviceMessage(QString("An attempt to add controller ") + ctrl->getAddress().toString().c_str() + QString(" for the second time in model ") + address.toString().c_str());
throw 9;
}
controllers->insert(std::make_pair(ctrl, nodeName));
connect(ctrl, SIGNAL(serviceMessage(const QString&)), SIGNAL(serviceMessage(const QString&)));
if (registered) {
connector->registerController(ctrl, nodeName);;
}
}
void M::Model::removeController(C::Controller* ctrl)
{
Controllers::const_iterator itr = controllers->find(ctrl);
if (itr == controllers->end()) {
emit serviceMessage(QString("An attempt to remove absent controller ") + ctrl->getAddress().toString().c_str() + QString(" from the model ") + address.toString().c_str());
throw 10;
}
disconnect(ctrl, SIGNAL(serviceMessage(const QString&)), this, SIGNAL(serviceMessage(const QString&)));
if (registered) {
connector->unregisterController(itr->first, itr->second);
}
controllers->erase(itr);
}

View File

@ -13,10 +13,10 @@
#include <wType/event.h> #include <wType/event.h>
#include <wType/string.h> #include <wType/string.h>
#include <wSocket/socket.h> #include <wSocket/socket.h>
#include <wSocket/server.h>
#include <wDispatcher/dispatcher.h>
#include <wDispatcher/handler.h> #include <wDispatcher/handler.h>
#include <wContainer/order.h> #include <wContainer/order.h>
#include <wServerUtils/connector.h>
#include <wController/controller.h>
namespace M { namespace M {
@ -29,10 +29,15 @@ namespace M {
list, list,
vocabulary, vocabulary,
catalogue, catalogue,
image,
button,
model,
attributes = 50, attributes = 50,
file, file,
resourceCache resourceCache,
player = 107
}; };
Model(const W::Address p_address, QObject* parent = 0); Model(const W::Address p_address, QObject* parent = 0);
@ -46,13 +51,15 @@ namespace M {
void addModel(M::Model* model); void addModel(M::Model* model);
void addHandler(W::Handler* handler); void addHandler(W::Handler* handler);
void addProperty(const W::String& value, const W::String& name); void addProperty(const W::String& value, const W::String& name);
void addController(C::Controller* ctrl, const W::String& nodeName);
W::Address getAddress() const; W::Address getAddress() const;
void registerModel(W::Dispatcher* dp, W::Server* srv); void getRegistered(U::Connector* connector);
void unregisterModel(); void getUnregistered();
void removeHandler(W::Handler* handler); void removeHandler(W::Handler* handler);
void removeModel(M::Model* model); void removeModel(M::Model* model);
void passToHandler(const W::Event& event) const; void removeController(C::Controller* ctrl);
void passToLocalHandler(const W::Event& event) const;
signals: signals:
void serviceMessage(const QString& msg) const; void serviceMessage(const QString& msg) const;
@ -76,13 +83,14 @@ namespace M {
private: private:
typedef W::Order<W::Handler*> HList; typedef W::Order<W::Handler*> HList;
typedef W::Order<M::Model*> MList; typedef W::Order<M::Model*> MList;
typedef std::map<C::Controller*, W::String> Controllers;
W::Dispatcher* dispatcher; U::Connector* connector;
W::Server* server;
uint64_t subscribersCount; uint64_t subscribersCount;
HList* handlers; HList* handlers;
W::Vector* properties; W::Vector* properties;
MList* models; MList* models;
Controllers* controllers;
private slots: private slots:
void onSocketDisconnected(); void onSocketDisconnected();

View File

@ -12,8 +12,7 @@
namespace M { namespace M {
class ICatalogue; class ICatalogue;
class Vocabulary : public M::Model class Vocabulary : public M::Model {
{
friend class ICatalogue; friend class ICatalogue;
public: public:
Vocabulary(const W::Address p_address, QObject* parent = 0); Vocabulary(const W::Address p_address, QObject* parent = 0);

View File

@ -1,4 +1,5 @@
#include "connector.h" #include "connector.h"
#include "commands.h"
U::Connector::Connector(W::Dispatcher* dp, W::Server* srv, U::Commands* cmds, QObject* parent): U::Connector::Connector(W::Dispatcher* dp, W::Server* srv, U::Commands* cmds, QObject* parent):
QObject(parent), QObject(parent),
@ -6,7 +7,8 @@ U::Connector::Connector(W::Dispatcher* dp, W::Server* srv, U::Commands* cmds, QO
server(srv), server(srv),
commands(cmds), commands(cmds),
nodes(), nodes(),
ignoredNodes() ignoredNodes(),
controllers()
{ {
connect(server, SIGNAL(newConnection(const W::Socket&)), SLOT(onNewConnection(const W::Socket&))); connect(server, SIGNAL(newConnection(const W::Socket&)), SLOT(onNewConnection(const W::Socket&)));
connect(server, SIGNAL(closedConnection(const W::Socket&)), SLOT(onClosedConnection(const W::Socket&))); connect(server, SIGNAL(closedConnection(const W::Socket&)), SLOT(onClosedConnection(const W::Socket&)));
@ -30,6 +32,17 @@ U::Connector::~Connector()
for (; itr != end; ++itr) { for (; itr != end; ++itr) {
commands->removeCommand(dc + itr->first); commands->removeCommand(dc + itr->first);
} }
std::multimap<W::String, C::Controller*>::const_iterator cbeg = controllers.begin();
std::multimap<W::String, C::Controller*>::const_iterator cend = controllers.end();
for (; cbeg != cend; ++cbeg) {
C::Controller* ctrl = cbeg->second;
if (ctrl->isSubscribed()) {
ctrl->unsubscribe();
ctrl->unregisterController();
}
}
} }
void U::Connector::addIgnoredNode(const W::String& name) void U::Connector::addIgnoredNode(const W::String& name)
@ -43,7 +56,7 @@ void U::Connector::sendTo(const W::String& name, const W::Event& event)
if (itr != nodes.end()) { if (itr != nodes.end()) {
throw new NodeAccessError(name); throw new NodeAccessError(name);
} else { } else {
server->getConnection(itr->second).send(event); server->getConnection(itr->second)->send(event);
} }
} }
@ -69,6 +82,14 @@ void U::Connector::onNewConnection(const W::Socket& socket)
emit serviceMessage(QString("New connection, id: ") + socket.getId().toString().c_str()); emit serviceMessage(QString("New connection, id: ") + socket.getId().toString().c_str());
connect(&socket, SIGNAL(message(const W::Event&)), dispatcher, SLOT(pass(const W::Event&))); connect(&socket, SIGNAL(message(const W::Event&)), dispatcher, SLOT(pass(const W::Event&)));
std::multimap<W::String, C::Controller*>::const_iterator beg = controllers.lower_bound(name);
std::multimap<W::String, C::Controller*>::const_iterator end = controllers.upper_bound(name);
for (; beg != end; ++beg) {
beg->second->registerController(dispatcher, &socket);
beg->second->subscribe();
}
emit nodeConnected(name); emit nodeConnected(name);
} }
} else { } else {
@ -90,6 +111,14 @@ void U::Connector::onClosedConnection(const W::Socket& socket)
if (ign == ignoredNodes.end()) { if (ign == ignoredNodes.end()) {
Map::const_iterator itr = nodes.find(name); Map::const_iterator itr = nodes.find(name);
if (itr != nodes.end()) { if (itr != nodes.end()) {
std::multimap<W::String, C::Controller*>::const_iterator beg = controllers.lower_bound(name);
std::multimap<W::String, C::Controller*>::const_iterator end = controllers.upper_bound(name);
for (; beg != end; ++beg) {
beg->second->unsubscribe();
beg->second->unregisterController();
}
emit nodeDisconnected(name); emit nodeDisconnected(name);
commands->removeCommand(W::String(u"disconnect") + name); commands->removeCommand(W::String(u"disconnect") + name);
nodes.erase(itr); nodes.erase(itr);
@ -114,7 +143,7 @@ void U::Connector::h_disconnect(const W::Event& ev)
server->closeConnection(itr->second); server->closeConnection(itr->second);
} }
const W::Socket& U::Connector::getNodeSocket(const W::String& name) const W::Socket* U::Connector::getNodeSocket(const W::String& name)
{ {
Map::const_iterator itr = nodes.find(name); Map::const_iterator itr = nodes.find(name);
if (itr == nodes.end()) { if (itr == nodes.end()) {
@ -122,3 +151,62 @@ const W::Socket& U::Connector::getNodeSocket(const W::String& name)
} }
return server->getConnection(itr->second); return server->getConnection(itr->second);
} }
void U::Connector::registerHandler(W::Handler* handler)
{
dispatcher->registerHandler(handler);
}
void U::Connector::unregisterHandler(W::Handler* handler)
{
dispatcher->unregisterHandler(handler);
}
const W::Socket * U::Connector::getConnection(uint64_t p_id) const
{
return server->getConnection(p_id);
}
void U::Connector::passThroughDispatcher(const W::Event& ev) const
{
dispatcher->pass(ev);
}
void U::Connector::registerController(C::Controller* ctrl, const W::String& node)
{
std::set<W::String>::const_iterator iitr = ignoredNodes.find(node);
if (iitr != ignoredNodes.end()) {
throw 3; //this means you're trying to receive something from one of ignored nodes, which never going to be handled in connector, most probably it's a mistake
}
controllers.insert(std::make_pair(node, ctrl));
Map::const_iterator itr = nodes.find(node);
if (itr != nodes.end()) {
ctrl->registerController(dispatcher, server->getConnection(itr->second));
ctrl->subscribe(); //let's say I always need them subscribed, for now at least
}
}
void U::Connector::unregisterController(C::Controller* ctrl, const W::String& node)
{
bool found = false;
std::multimap<W::String, C::Controller*>::const_iterator beg = controllers.lower_bound(node);
std::multimap<W::String, C::Controller*>::const_iterator end = controllers.upper_bound(node);
for (; beg != end; ++beg) {
if (beg->second == ctrl) {
found = true; //TODO make a proper way to store 'em
break;
}
}
if (!found) {
throw 4;
}
if (ctrl->isSubscribed()) {
ctrl->unsubscribe();
ctrl->unregisterController();
}
controllers.erase(beg);
}

View File

@ -1,11 +1,14 @@
#ifndef CONNECTOR_H #ifndef CONNECTOR_H
#define CONNECTOR_H #define CONNECTOR_H
#include <utils/defines.h>
#include <QtCore/QObject> #include <QtCore/QObject>
#include <map> #include <map>
#include <set> #include <set>
#include <wDispatcher/dispatcher.h> #include <wDispatcher/dispatcher.h>
#include <wDispatcher/handler.h>
#include <wSocket/socket.h> #include <wSocket/socket.h>
#include <wSocket/server.h> #include <wSocket/server.h>
@ -16,9 +19,11 @@
#include <utils/exception.h> #include <utils/exception.h>
#include "commands.h" #include <wController/controller.h>
namespace U { namespace U {
class Commands;
class Connector : public QObject class Connector : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -29,7 +34,13 @@ namespace U {
void addIgnoredNode(const W::String& name); void addIgnoredNode(const W::String& name);
void sendTo(const W::String& name, const W::Event& event); void sendTo(const W::String& name, const W::Event& event);
const W::Socket& getNodeSocket(const W::String& name); const W::Socket* getNodeSocket(const W::String& name);
void registerHandler(W::Handler* handler);
void unregisterHandler(W::Handler* handler);
const W::Socket* getConnection(uint64_t p_id) const;
void passThroughDispatcher(const W::Event& ev) const;
void registerController(C::Controller* ctrl, const W::String& node);
void unregisterController(C::Controller* ctrl, const W::String& node);
signals: signals:
void serviceMessage(const QString& msg); void serviceMessage(const QString& msg);
@ -42,6 +53,7 @@ namespace U {
U::Commands* commands; U::Commands* commands;
Map nodes; Map nodes;
std::set<W::String> ignoredNodes; std::set<W::String> ignoredNodes;
std::multimap<W::String, C::Controller*> controllers;
protected: protected:
handler(connect); handler(connect);

View File

@ -44,14 +44,14 @@ void W::Server::stop()
} }
} }
const W::Socket& W::Server::getConnection(uint64_t p_id) const const W::Socket* W::Server::getConnection(uint64_t p_id) const
{ {
std::map<uint64_t, Socket*>::const_iterator itr = connections.find(p_id); std::map<uint64_t, Socket*>::const_iterator itr = connections.find(p_id);
if (itr == connections.end()) { if (itr == connections.end()) {
throw new SocketAccessError(); throw new SocketAccessError();
} }
return *(itr->second); return itr->second;
} }
uint64_t W::Server::getConnectionsCount() const uint64_t W::Server::getConnectionsCount() const

View File

@ -27,7 +27,7 @@ namespace W
void listen(uint16_t port); void listen(uint16_t port);
void stop(); void stop();
const Socket& getConnection(uint64_t p_id) const; const Socket* getConnection(uint64_t p_id) const;
uint64_t getConnectionsCount() const; uint64_t getConnectionsCount() const;
void closeConnection(uint64_t p_id); void closeConnection(uint64_t p_id);
void openConnection(const String& addr, const Uint64& port); void openConnection(const String& addr, const Uint64& port);

View File

@ -102,5 +102,7 @@ W::Object::StdStr W::Object::getTypeName(W::Object::objectType type)
case blob: case blob:
return "Blob"; return "Blob";
} }
throw 5;
} }

View File

@ -0,0 +1,69 @@
"use strict";
var Controller = require("./controller");
var String = require("./string");
var Vocabulary = require("../wType/vocabulary");
var Button = Controller.inherit({
"className": "Button",
"constructor": function(addr) {
Controller.fn.constructor.call(this, addr);
this.enabled = false;
this.hasLabel = false;
this.addHandler("get");
this.addHandler("setLabel");
this.addHandler("setImage");
this.addHandler("setEnabled");
this.addHandler("changeImage");
},
"destructor": function() {
Controller.fn.destructor.call(this);
},
"activate": function() {
if (this.enabled) {
this.send(new Vocabulary, "activate");
}
},
"_h_changeImage": function(ev) {
},
"_h_get": function(ev) {
this._h_setLabel(ev);
this._h_setImage(ev);
this._h_setEnabled(ev);
},
"_h_setEnabled": function(ev) {
var data = ev.getData();
var enabled = data.at("enabled").valueOf();
if (this.enabled !== enabled) {
this.enabled = enabled;
this.trigger("setEnabled", this.enabled);
}
},
"_h_setLabel": function(ev) {
var data = ev.getData();
var hasLabel = data.at("hasLabel").valueOf();
if (hasLabel !== this.hasLabel) {
this.hasLabel = hasLabel;
if (hasLabel) {
this.label = new String(data.at("label").clone());
this.addController(this.label);
this.trigger("setLabel", true, this.label);
} else {
this.trigger("setLabel", false);
this.removeController(this.label);
this.label.destructor();
}
}
},
"_h_setImage": function(ev) {
}
});
module.exports = Button;

View File

@ -328,8 +328,10 @@ Controller.ModelType = {
String: 0, String: 0,
List: 1, List: 1,
Vocabulary: 2, Vocabulary: 2,
Image: 3, Catalogue: 3,
Controller: 4, Image: 4,
Button: 5,
Controller: 6,
Attributes: 50, Attributes: 50,
@ -339,15 +341,18 @@ Controller.ModelType = {
PageStorage: 103, PageStorage: 103,
PanesList: 104, PanesList: 104,
Theme: 105, Theme: 105,
ThemeStorage: 106 ThemeStorage: 106,
Player: 107
}; };
Controller.ReversedModelType = { Controller.ReversedModelType = {
"0": "String", "0": "String",
"1": "List", "1": "List",
"2": "Vocabulary", "2": "Vocabulary",
"3": "Image", "3": "Catalogue",
"4": "Controller", "4": "Image",
"5": "Button",
"6": "Controller",
"50": "Attributes", "50": "Attributes",
@ -357,7 +362,8 @@ Controller.ReversedModelType = {
"103": "PageStorage", "103": "PageStorage",
"104": "PanesList", "104": "PanesList",
"105": "Theme", "105": "Theme",
"106": "ThemeStorage" "106": "ThemeStorage",
"107": "Player"
}; };
Controller.ModelTypesPaths = { Controller.ModelTypesPaths = {
@ -372,7 +378,10 @@ Controller.ModelTypesPaths = {
PanesList: "./panesList", //resolve as dependency PanesList: "./panesList", //resolve as dependency
Theme: "./theme", //resolve as dependency Theme: "./theme", //resolve as dependency
ThemeStorage: "./themeStorage", //resolve as dependency ThemeStorage: "./themeStorage", //resolve as dependency
Image: "./image" //resolve as dependency Image: "./image", //resolve as dependency
Button: "./button", //resolve as dependency
Catalogue: "./catalogue", //resolve as dependency
Player: "./player" //resolve as dependency
}; };
Controller.constructors = { Controller.constructors = {

View File

@ -10,16 +10,12 @@ var Link = Controller.inherit({
"constructor": function(addr) { "constructor": function(addr) {
Controller.fn.constructor.call(this, addr); Controller.fn.constructor.call(this, addr);
var hop = new Address(["label"]);
this.targetAddress = new Address([]); this.targetAddress = new Address([]);
this.label = new String(addr['+'](hop)); this.label = new String(addr['+'](hop));
this.addController(this.label); this.addController(this.label);
this.addHandler("get"); this.addHandler("get");
hop.destructor();
}, },
"destructor": function() { "destructor": function() {
this.targetAddress.destructor(); this.targetAddress.destructor();
@ -35,4 +31,6 @@ var Link = Controller.inherit({
} }
}); });
var hop = new Address(["label"]);
module.exports = Link; module.exports = Link;

View File

@ -13,5 +13,6 @@ configure_file(themeStorage.js themeStorage.js)
configure_file(vocabulary.js vocabulary.js) configure_file(vocabulary.js vocabulary.js)
configure_file(attributes.js attributes.js) configure_file(attributes.js attributes.js)
configure_file(image.js image.js) configure_file(image.js image.js)
configure_file(button.js button.js)
add_subdirectory(proxy) add_subdirectory(proxy)

90
libjs/wModel/button.js Normal file
View File

@ -0,0 +1,90 @@
"use strict";
var Model = require("./model");
var ModelString = require("./string");
var Vocabulary = require("../wType/vocabulary");
var Boolean = require("../wType/boolean");
var Address = require("../wType/address");
var String = require("../wType/string");
var Button = Model.inherit({
"className": "Button",
"constructor": function(address) {
Model.fn.constructor.call(this, address);
this._enabled = true;
this._hasImage = false;
this._hasLabel =false;
this._imageName = undefined;
this._label = undefined;
this.addHandler("get");
this.addHandler("activate");
},
"setImage": function(name) {
if (this._hasImage) {
if (this._imageName !== name) {
this._image = name;
var vc = new Vocabulary();
vc.insert("image", new String(this._imageName));
this.broadcast(vc, "changeImage");
}
} else {
this._image = name;
this._hasImage = true;
var vc = new Vocabulary();
vc.insert("image", new String(this._imageName));
this.broadcast(vc, "setImage");
}
},
"setEnabled": function(enabled) {
if (enabled !== this._enabled) {
this._enabled = enabled;
var vc = new Vocabulary();
vc.insert("enabled", new Boolean(this._enabled));
this.broadcast(vc, "setEnabled");
}
},
"setLabel": function(text) {
if (this._hasLabel) {
this._label.set(text);
} else {
this._label = new ModelString(this._address["+"](labelHop), text);
this.addModel(this._label);
var vc = new Vocabulary();
vc.insert("hasLabel", new Boolean(true));
vc.insert("label", this._label.getAddress());
this.broadcast(vc, "setLabel");
this._hasLabel = true;
}
},
"_h_subscribe": function(ev) {
Model.fn._h_subscribe.call(this, ev);
this._h_get(ev);
},
"_h_get": function(ev) {
var vc = new Vocabulary();
vc.insert("hasImage", new Boolean(this._hasImage));
if (this._hasImage) {
vc.insert("image", new String(this._imageName));
}
vc.insert("hasLabel", new Boolean(this._hasLabel));
if (this._hasLabel) {
vc.insert("label", this._label.getAddress());
}
vc.insert("enabled", new Boolean(this._enabled));
this.response(vc, "get", ev);
},
"_h_activate": function() {
if (this._enabled) {
this.trigger("activated");
}
}
});
var labelHop = new Address(["label"]);
module.exports = Button;

View File

@ -299,8 +299,10 @@ Model.ModelType = {
String: 0, String: 0,
List: 1, List: 1,
Vocabulary: 2, Vocabulary: 2,
Image: 3, //Catalogue: 3,
Model: 4, Image: 4,
Button: 5,
Model: 6,
Attributes: 50, Attributes: 50,
@ -310,7 +312,8 @@ Model.ModelType = {
PageStorage: 103, PageStorage: 103,
PanesList: 104, PanesList: 104,
Theme: 105, Theme: 105,
ThemeStorage: 106 ThemeStorage: 106,
Player: 107
}; };
module.exports = Model; module.exports = Model;

View File

@ -45,3 +45,7 @@ div.dragging .draggable {
cursor: -moz-grabbing; cursor: -moz-grabbing;
cursor: grabbing; cursor: grabbing;
} }
.disabled {
opacity: 0.7;
}

View File

@ -17,3 +17,4 @@ add_jslib(wController/localModel.js lib/wController/localModel ${LORGAR_DIR} bro
add_jslib(wController/imagePane.js lib/wController/imagePane ${LORGAR_DIR} browser) add_jslib(wController/imagePane.js lib/wController/imagePane ${LORGAR_DIR} browser)
add_jslib(wController/file/file.js lib/wController/file/file ${LORGAR_DIR} browser) add_jslib(wController/file/file.js lib/wController/file/file ${LORGAR_DIR} browser)
add_jslib(wController/image.js lib/wController/image ${LORGAR_DIR} browser) add_jslib(wController/image.js lib/wController/image ${LORGAR_DIR} browser)
add_jslib(wController/button.js lib/wController/button ${LORGAR_DIR} browser)

View File

@ -36,8 +36,8 @@
} }
} }
Controller.initialize(["String", "List", "Vocabulary", "Page", "PanesList", "Link", "Image"], waiter.check.bind(waiter, "controllers")); Controller.initialize(["String", "List", "Vocabulary", "Page", "PanesList", "Link", "Image", "Button"], waiter.check.bind(waiter, "controllers"));
View.initialize(["Label", "Page", "PanesList", "Nav", "Image"], waiter.check.bind(waiter, "views")); View.initialize(["Label", "Page", "PanesList", "Nav", "Image", "Button"], waiter.check.bind(waiter, "views"));
var test = new Test(); var test = new Test();
test.run(); test.run();

View File

@ -11,5 +11,6 @@ configure_file(mainLayout.js mainLayout.js)
configure_file(page.js page.js) configure_file(page.js page.js)
configure_file(pane.js pane.js) configure_file(pane.js pane.js)
configure_file(image.js image.js) configure_file(image.js image.js)
configure_file(button.js button.js)
add_subdirectory(helpers) add_subdirectory(helpers)

95
lorgar/views/button.js Normal file
View File

@ -0,0 +1,95 @@
"use strict";
(function() {
var moduleName = "views/button";
var deps = [];
deps.push("views/layout");
deps.push("views/label");
define(moduleName, deps, function() {
var Layout = require("views/layout");
var Label = require("views/label");
var Button = Layout.inherit({
"className": "Button",
"constructor": function(controller, options) {
var base = {
padding: 5
};
W.extend(base, options)
Layout.fn.constructor.call(this, controller, base);
this.addClass("hoverable");
this._enabled = true;
this._hasLabel = false;
this._e.addEventListener("click", this._onClick.bind(this), false);
controller.on("setEnabled", this._onSetEnabled, this);
controller.on("setLabel", this._onSetLabel, this);
},
"destructor": function() {
this._f.off("setEnabled", this._onSetEnabled, this);
this._f.off("setLabel", this._onSetLabel, this);
Layout.fn.destructor.call(this);
},
"append": function(child, aligment, index) {
this._updateLimits();
Layout.fn.append.call(this, child, aligment, index);
},
"_onChildChangeLimits": function(child) {
this._updateLimits();
Layout.fn._onChildChangeLimits.call(this, child);
},
"_onClick": function() {
if (this._enabled) {
this._f.activate();
}
},
"_onSetEnabled": function(enabled) {
if (this._enabled !== enabled) {
this._enabled = enabled;
if (this._enabled) {
this.addClass("hoverable");
this.removeClass("disabled");
} else {
this.removeClass("hoverable");
this.addClass("disabled");
}
}
},
"_onSetLabel": function(hasLabel, label) {
if (this._hasLabel !== hasLabel) {
this._hasLabel = hasLabel;
if (this._hasLabel) {
this._label = new Label(label);
this.append(this._label, Layout.Aligment.CenterCenter);
} else {
this._label.destructor();
delete this._label();
}
}
},
"_updateLimits": function() {
var minWidth = this._o.padding * 2;
var maxWidth = this._o.padding * 2;
var minHeight = this._o.padding * 2;
var maxHeight = this._o.padding * 2;
if (this._hasLabel) {
minWidth += this._label._o.minWidth;
minHeight += this._label._o.minHeight;
maxWidth += this._label._o.maxWidth;
maxHeight += this._label._o.maxHeight;
}
this._setLimits(minWidth, minHeight, maxWidth, maxHeight);
}
});
return Button;
})
})();

View File

@ -76,8 +76,12 @@
} }
} }
if (this._w !== undefined && this._h !== undefined) { if (this._w !== undefined && this._h !== undefined) {
child.setSize(this._w, this._h); child.setSize(this._w, this._h);
index = index || this._c.length - 1;
var c = this._c[index];
this._positionElement(c);
} }
}, },
"clear": function() { "clear": function() {

View File

@ -191,9 +191,12 @@
} }
if (needToTell) { if (needToTell) {
this.trigger("changeLimits", this); this.trigger("changeLimits", this);
if (this._w !== undefined && this._h !== undefined) {
this.setSize(this._w, this._h);
}
} }
return needToTell && this._events.changeLimits && this._events.changeLimits.length; //to see if someone actually going to listen that event return needToTell && this._events.changeLimits && this._events.changeLimits.length; //to see if someone actually going to listen that event, if not - return result
}, },
"setMaxSize": function(w, h) { "setMaxSize": function(w, h) {
this._o.maxWidth = w; this._o.maxWidth = w;
@ -284,22 +287,27 @@
View.ViewType = { View.ViewType = {
Label: 0, Label: 0,
Image: 3, Image: 4,
View: 4, Button: 5,
View: 6,
Page: 102, Page: 102,
PanesList: 104 PanesList: 104,
Player: 107
}; };
View.ReversedViewType = { View.ReversedViewType = {
"0": "Label", "0": "Label",
"3": "Image", "4": "Image",
"4": "View", "5": "Button",
"6": "View",
"101": "Nav", "101": "Nav",
"102": "Page", "102": "Page",
"104": "PanesList" "104": "PanesList",
"107": "Player"
}; };
View.ViewTypesPaths = { View.ViewTypesPaths = {
@ -307,7 +315,9 @@
Nav: "views/nav", Nav: "views/nav",
Page: "views/page", Page: "views/page",
PanesList: "views/panesList", PanesList: "views/panesList",
Image: "views/image" Image: "views/image",
Button: "views/button",
Player: "views/player"
}; };
View.constructors = { View.constructors = {

View File

@ -13,5 +13,6 @@ add_jslib(wModel/themeStorage.js lib/wModel/themeStorage ${MAGNUS_DIR} node)
add_jslib(wModel/vocabulary.js lib/wModel/vocabulary ${MAGNUS_DIR} node) add_jslib(wModel/vocabulary.js lib/wModel/vocabulary ${MAGNUS_DIR} node)
add_jslib(wModel/attributes.js lib/wModel/attributes ${MAGNUS_DIR} node) add_jslib(wModel/attributes.js lib/wModel/attributes ${MAGNUS_DIR} node)
add_jslib(wModel/image.js lib/wModel/image ${MAGNUS_DIR} node) add_jslib(wModel/image.js lib/wModel/image ${MAGNUS_DIR} node)
add_jslib(wModel/button.js lib/wModel/button ${MAGNUS_DIR} node)
add_subdirectory(proxy) add_subdirectory(proxy)

View File

@ -2,6 +2,7 @@
var Page = require("../lib/wModel/page"); var Page = require("../lib/wModel/page");
var String = require("../lib/wModel/string"); var String = require("../lib/wModel/string");
var Button = require("../lib/wModel/button");
var Address = require("../lib/wType/address"); var Address = require("../lib/wType/address");
@ -13,6 +14,16 @@ var TestPage = Page.inherit({
var header = new String(this._address["+"](new Address(["message"])), "This is a test page"); var header = new String(this._address["+"](new Address(["message"])), "This is a test page");
header.addProperty("fontFamily", "casualFont"); header.addProperty("fontFamily", "casualFont");
this.addItem(header, 0, 0, 1, 1, Page.Aligment.CenterTop); this.addItem(header, 0, 0, 1, 1, Page.Aligment.CenterTop);
this._button = new Button(this._address["+"](new Address(["testButton"])));
this._button.setLabel("Push me");
this._button.on("activated", this._onActivate, this);
this.addItem(this._button, 1, 0, 1, 1, Page.Aligment.CenterTop);
},
"_onActivate": function() {
this.trigger("serviceMessage", "Button works!");
this._button.setEnabled(false);
setTimeout(this._button.setEnabled.bind(this._button, true), 3000);
} }
}); });

View File

@ -25,7 +25,7 @@ target_link_libraries(perturabo wSocket)
target_link_libraries(perturabo wDispatcher) target_link_libraries(perturabo wDispatcher)
target_link_libraries(perturabo utils) target_link_libraries(perturabo utils)
target_link_libraries(perturabo wModel) target_link_libraries(perturabo wModel)
target_link_libraries(perturabo wServerUtils)
target_link_libraries(perturabo wDatabase) target_link_libraries(perturabo wDatabase)
target_link_libraries(perturabo wServerUtils)
install(TARGETS perturabo RUNTIME DESTINATION bin) install(TARGETS perturabo RUNTIME DESTINATION bin)

View File

@ -86,11 +86,11 @@ void Perturabo::start()
server->listen(8082); server->listen(8082);
cout << "Registering models..." << endl; cout << "Registering models..." << endl;
attributes->registerModel(dispatcher, server); attributes->getRegistered(connector);
commands->registerModel(dispatcher, server); commands->getRegistered(connector);
for (; beg != end; ++beg) { for (; beg != end; ++beg) {
beg->second->registerModel(dispatcher, server); beg->second->getRegistered(connector);
} }
cout << "Opening and indexing databases..." << endl; cout << "Opening and indexing databases..." << endl;
@ -115,11 +115,11 @@ void Perturabo::stop()
commands->enableCommand(W::String(u"clearDatabase"), false); commands->enableCommand(W::String(u"clearDatabase"), false);
for (; beg != end; ++beg) { for (; beg != end; ++beg) {
beg->second->unregisterModel(); beg->second->getUnregistered();
} }
commands->unregisterModel(); commands->getUnregistered();
attributes->unregisterModel(); attributes->getUnregistered();
server->stop(); server->stop();
} }