WIP Merging basic player to master #6
@ -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)
|
||||||
|
@ -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&)));
|
||||||
|
21
corax/models/CMakeLists.txt
Normal file
21
corax/models/CMakeLists.txt
Normal 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
121
corax/models/player.cpp
Normal 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
60
corax/models/player.h
Normal 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
135
corax/models/proxysong.cpp
Normal 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
47
corax/models/proxysong.h
Normal 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
|
@ -276,3 +276,8 @@ bool C::Controller::isSubscribed()
|
|||||||
{
|
{
|
||||||
return subscribed;
|
return subscribed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const W::Address & C::Controller::getAddress() const
|
||||||
|
{
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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());
|
||||||
|
@ -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
113
lib/wModel/button.cpp
Normal 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
52
lib/wModel/button.h
Normal 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
|
@ -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();
|
||||||
@ -37,11 +37,19 @@ M::Model::~Model()
|
|||||||
for (; hItr != hEnd; ++hItr) {
|
for (; hItr != hEnd; ++hItr) {
|
||||||
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -102,5 +102,7 @@ W::Object::StdStr W::Object::getTypeName(W::Object::objectType type)
|
|||||||
case blob:
|
case blob:
|
||||||
return "Blob";
|
return "Blob";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
69
libjs/wController/button.js
Normal file
69
libjs/wController/button.js
Normal 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;
|
@ -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 = {
|
||||||
|
@ -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;
|
||||||
|
@ -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
90
libjs/wModel/button.js
Normal 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;
|
@ -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;
|
||||||
|
@ -45,3 +45,7 @@ div.dragging .draggable {
|
|||||||
cursor: -moz-grabbing;
|
cursor: -moz-grabbing;
|
||||||
cursor: grabbing;
|
cursor: grabbing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.disabled {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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();
|
||||||
|
@ -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
95
lorgar/views/button.js
Normal 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;
|
||||||
|
})
|
||||||
|
})();
|
||||||
|
|
@ -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() {
|
||||||
|
@ -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 = {
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user