(C++) Wt example 4: broadcasting using WtBroadcastServer
January 11, 2018 · View on GitHub
(C++) Wt example 4: broadcasting using WtBroadcastServer
Wt example 4: broadcasting using WtBroadcastServera is an article about a simple Wt example in which is shown how multiple clients can respond to the same data source and be notified when needed.
This example shows how to use two classes to do most of the work for you. For a complete view of all delegated tasks, Wt example 3: broadcasting gives a complete view of all bookkeeping necessary.
The code shown is simplified from the tool TestBroadcastServer (version 1.0).
This example has the following players:
- WtBroadcastServer: a server singleton class that notifies its WtBroadcastServerClients every 100 milliseconds
- WtMainDialog: a derived class of WtBroadcastServerClients that has contents editable and viewable to all web page visitos
The program does the following:
- WtMainDialog displays one Wt::WLineEdit that acts as one shared edit box for all visitors
Below, the WtMainDialog and its communication to the WtBroadcastServer is discussed in detail, starting at its header file.
The WtBroadcastServer header file
struct WtMainDialog : public Wt::WContainerWidget, WtBroadcastServerClient { WtMainDialog(); private: ///The user interface struct Ui { Ui() : m_edit(0) {} Wt::WLineEdit * m_edit; } ui; ///The user changes the text in the Wt::WLineEdit void OnEditChanged(); ///The server updates the page void UpdatePage(); };
This header file has the following elements:
- WtMainDialog is a Wt::WContainerWidget, because it inherits from Wt::WContainerWidget. Wt::WContainerWidget is used as a base class to let WtMainDialog be a dialog
- WtMainDialog is a WtBroadcastServerClient, because it also inherits from WtBroadcastServerClient. WtBroadcastServerClient is used as a base class to let WtMainDialog be a client to the WtBroadcastServer. This imposes a rule on WtMainDialog: it must define an UpdatePage method, which will be called every 100 milliseconds
- WtMainDialog uses a nested struct called 'Ui', short for 'User Interface', which contains the only visible control: the Wt::WLineEdit called m_edit. In this example, one could also easily put m_edit as a direct member of WtMainDialog. For reasons of following the same approach as Qt, this is done in this (and in many more) examples
- WtMainDialog has a method called 'OnEditChanged', which will be called when the Wt::WLineEdit is changed by one of its possibly many users
- WtMainDialog has a method called 'UpdatePage', which will be called when the Wt::WLineEdit is changed by one of its possibly many users. Because WtMainDialog is a WtBroadcastServerClient, it must define this abstract method, otherwise the compiler will indicate this
The WtBroadcastServer implementation file
WtMainDialog::WtMainDialog() { ui.m_edit = new Wt::WLineEdit(this); ui.m_edit->keyWentUp().connect(this,&WtMainDialog::OnEditChanged); } //--------------------------------------------------------------------------- void WtMainDialog::OnEditChanged() { WtBroadcastServer::GetInstance()->SetData( std::string(ui.m_edit->text().toUTF8())); } //--------------------------------------------------------------------------- void WtMainDialog::UpdatePage() { std::string text; try { text = boost::any_cast<std::string>(WtBroadcastServer::GetInstance()->GetData()); } catch (boost::bad_any_cast&) { text = "TestBroadcastServer"; } ui.m_edit->setText(text.c_str()); }
WtMainDialog has only three methods:
- WtMainDialog::WtMainDialog: the WtMainDialog constructor: in it, the ui.m_edit is constructed and its keyWentUp signal is connected to WtMainDialog::OnEditChanged: when the user releases a key when ui.m_edit is in focus, WtMainDialog::OnEditChanged is called
- WtMainDialog::OnEditChanged: sets the data of the server to the freshly edited text in the Wt::WLineEdit. WtBroadcastServer holds only one piece of data, in the form of boost::any. In this case, the data is of type std::string, but it can be any (no pun intended) much more complex data type
- WtMainDialog::UpdatePage: this method is called every 100 milliseconds and gets the data of the server and puts it in the Wt::WLineEdit. The use of boost::any_cast is needed, because WtBroadcastServer holds only one piece of data, in the form of boost::any. It can be true, however, that WtBroadcastServer has no data yet. In such a case, boost::any_cast throws boost::bad_any_cast and the content content of the Wt::WLineEdit is set to the name of the application
Conclusion
Compared to the previous example, that is Wt example 3: broadcasting, this example is shorter and, in my humble opinion, better focussed: all bookkeeping is done by WtBroadcastServer and WtBroadcastServerClient.