summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--i18n/server/pvsmgr_ar_JO.ts40
-rw-r--r--i18n/server/pvsmgr_de_DE.ts40
-rw-r--r--i18n/server/pvsmgr_es_MX.ts40
-rw-r--r--i18n/server/pvsmgr_fr_FR.ts40
-rw-r--r--i18n/server/pvsmgr_pl_PL.ts40
-rw-r--r--src/server/connectionframe/connectionframe.cpp9
-rw-r--r--src/server/connectionframe/connectionframe.h2
-rw-r--r--src/server/mainwindow/mainwindow.cpp196
-rw-r--r--src/server/mainwindow/mainwindow.h6
-rw-r--r--src/server/net/client.cpp26
-rw-r--r--src/server/net/client.h3
-rw-r--r--src/shared/networkmessage.cpp6
-rw-r--r--src/shared/networkmessage.h23
13 files changed, 396 insertions, 75 deletions
diff --git a/i18n/server/pvsmgr_ar_JO.ts b/i18n/server/pvsmgr_ar_JO.ts
index 71f8e51..1cb3f91 100644
--- a/i18n/server/pvsmgr_ar_JO.ts
+++ b/i18n/server/pvsmgr_ar_JO.ts
@@ -10,27 +10,53 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/server/mainwindow/mainwindow.cpp" line="335"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="338"/>
<source>Session Name: %1 [click to edit]</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/server/mainwindow/mainwindow.cpp" line="371"/>
- <source>No Projection Source selected</source>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="434"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="462"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="467"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="472"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="499"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="527"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="532"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="537"/>
+ <source>Projection</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/server/mainwindow/mainwindow.cpp" line="371"/>
- <source>You did not select any active client as the connection source.</source>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="435"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="463"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="528"/>
+ <source>No projection source selected.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/server/mainwindow/mainwindow.cpp" line="575"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="468"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="500"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="533"/>
+ <source>No tutor defined, or tutor is offline.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="473"/>
+ <source>Selected projection target is tutor.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="538"/>
+ <source>Selected projection source is tutor.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="747"/>
<source>Projection Error</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/server/mainwindow/mainwindow.cpp" line="576"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="748"/>
<source>Could not send screen contents of %1 to other clients: VNC Startup failed.</source>
<translation type="unfinished"></translation>
</message>
diff --git a/i18n/server/pvsmgr_de_DE.ts b/i18n/server/pvsmgr_de_DE.ts
index abf597e..108af6f 100644
--- a/i18n/server/pvsmgr_de_DE.ts
+++ b/i18n/server/pvsmgr_de_DE.ts
@@ -63,27 +63,53 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/server/mainwindow/mainwindow.cpp" line="335"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="338"/>
<source>Session Name: %1 [click to edit]</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/server/mainwindow/mainwindow.cpp" line="371"/>
- <source>No Projection Source selected</source>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="434"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="462"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="467"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="472"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="499"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="527"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="532"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="537"/>
+ <source>Projection</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/server/mainwindow/mainwindow.cpp" line="371"/>
- <source>You did not select any active client as the connection source.</source>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="435"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="463"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="528"/>
+ <source>No projection source selected.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/server/mainwindow/mainwindow.cpp" line="575"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="468"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="500"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="533"/>
+ <source>No tutor defined, or tutor is offline.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="473"/>
+ <source>Selected projection target is tutor.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="538"/>
+ <source>Selected projection source is tutor.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="747"/>
<source>Projection Error</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/server/mainwindow/mainwindow.cpp" line="576"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="748"/>
<source>Could not send screen contents of %1 to other clients: VNC Startup failed.</source>
<translation type="unfinished"></translation>
</message>
diff --git a/i18n/server/pvsmgr_es_MX.ts b/i18n/server/pvsmgr_es_MX.ts
index ec161f7..ed260d1 100644
--- a/i18n/server/pvsmgr_es_MX.ts
+++ b/i18n/server/pvsmgr_es_MX.ts
@@ -266,27 +266,53 @@ Perform an unprojection or remove remote help to get a target.</source>
<translation type="obsolete">Mostrar el cliente seleccionado en toda la ventana</translation>
</message>
<message>
- <location filename="../../src/server/mainwindow/mainwindow.cpp" line="335"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="338"/>
<source>Session Name: %1 [click to edit]</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/server/mainwindow/mainwindow.cpp" line="371"/>
- <source>No Projection Source selected</source>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="434"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="462"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="467"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="472"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="499"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="527"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="532"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="537"/>
+ <source>Projection</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/server/mainwindow/mainwindow.cpp" line="371"/>
- <source>You did not select any active client as the connection source.</source>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="435"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="463"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="528"/>
+ <source>No projection source selected.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/server/mainwindow/mainwindow.cpp" line="575"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="468"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="500"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="533"/>
+ <source>No tutor defined, or tutor is offline.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="473"/>
+ <source>Selected projection target is tutor.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="538"/>
+ <source>Selected projection source is tutor.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="747"/>
<source>Projection Error</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/server/mainwindow/mainwindow.cpp" line="576"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="748"/>
<source>Could not send screen contents of %1 to other clients: VNC Startup failed.</source>
<translation type="unfinished"></translation>
</message>
diff --git a/i18n/server/pvsmgr_fr_FR.ts b/i18n/server/pvsmgr_fr_FR.ts
index 71f8e51..1cb3f91 100644
--- a/i18n/server/pvsmgr_fr_FR.ts
+++ b/i18n/server/pvsmgr_fr_FR.ts
@@ -10,27 +10,53 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/server/mainwindow/mainwindow.cpp" line="335"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="338"/>
<source>Session Name: %1 [click to edit]</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/server/mainwindow/mainwindow.cpp" line="371"/>
- <source>No Projection Source selected</source>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="434"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="462"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="467"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="472"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="499"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="527"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="532"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="537"/>
+ <source>Projection</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/server/mainwindow/mainwindow.cpp" line="371"/>
- <source>You did not select any active client as the connection source.</source>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="435"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="463"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="528"/>
+ <source>No projection source selected.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/server/mainwindow/mainwindow.cpp" line="575"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="468"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="500"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="533"/>
+ <source>No tutor defined, or tutor is offline.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="473"/>
+ <source>Selected projection target is tutor.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="538"/>
+ <source>Selected projection source is tutor.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="747"/>
<source>Projection Error</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/server/mainwindow/mainwindow.cpp" line="576"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="748"/>
<source>Could not send screen contents of %1 to other clients: VNC Startup failed.</source>
<translation type="unfinished"></translation>
</message>
diff --git a/i18n/server/pvsmgr_pl_PL.ts b/i18n/server/pvsmgr_pl_PL.ts
index 71f8e51..1cb3f91 100644
--- a/i18n/server/pvsmgr_pl_PL.ts
+++ b/i18n/server/pvsmgr_pl_PL.ts
@@ -10,27 +10,53 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/server/mainwindow/mainwindow.cpp" line="335"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="338"/>
<source>Session Name: %1 [click to edit]</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/server/mainwindow/mainwindow.cpp" line="371"/>
- <source>No Projection Source selected</source>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="434"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="462"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="467"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="472"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="499"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="527"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="532"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="537"/>
+ <source>Projection</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/server/mainwindow/mainwindow.cpp" line="371"/>
- <source>You did not select any active client as the connection source.</source>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="435"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="463"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="528"/>
+ <source>No projection source selected.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/server/mainwindow/mainwindow.cpp" line="575"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="468"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="500"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="533"/>
+ <source>No tutor defined, or tutor is offline.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="473"/>
+ <source>Selected projection target is tutor.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="538"/>
+ <source>Selected projection source is tutor.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="747"/>
<source>Projection Error</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/server/mainwindow/mainwindow.cpp" line="576"/>
+ <location filename="../../src/server/mainwindow/mainwindow.cpp" line="748"/>
<source>Could not send screen contents of %1 to other clients: VNC Startup failed.</source>
<translation type="unfinished"></translation>
</message>
diff --git a/src/server/connectionframe/connectionframe.cpp b/src/server/connectionframe/connectionframe.cpp
index 1544c76..6bfce81 100644
--- a/src/server/connectionframe/connectionframe.cpp
+++ b/src/server/connectionframe/connectionframe.cpp
@@ -110,6 +110,7 @@ void ConnectionFrame::assignClient(Client* client)
if (_timerId == 0)
_timerId = startTimer(1000 + qrand() % 150);
this->updateColor();
+ _client->setTutor(_isTutor);
}
void ConnectionFrame::showDefaultThumb()
@@ -213,6 +214,14 @@ void ConnectionFrame::setSelection(bool selected)
this->updateColor();
}
+void ConnectionFrame::setTutor(bool b)
+{
+ if (_isTutor != b && _client != NULL)
+ _client->setTutor(b);
+ _isTutor = b;
+ this->updateColor();
+}
+
void ConnectionFrame::updateColor()
{
if (_client == NULL)
diff --git a/src/server/connectionframe/connectionframe.h b/src/server/connectionframe/connectionframe.h
index 2b78056..ccb32a8 100644
--- a/src/server/connectionframe/connectionframe.h
+++ b/src/server/connectionframe/connectionframe.h
@@ -50,7 +50,7 @@ public:
Client* client() const { return _client; }
inline const bool isTutor() const { return _isTutor; }
- inline void setTutor(bool b) { _isTutor = b; }
+ void setTutor(bool b);
protected:
void mouseDoubleClickEvent(QMouseEvent* event);
diff --git a/src/server/mainwindow/mainwindow.cpp b/src/server/mainwindow/mainwindow.cpp
index bbd6b33..48a1a57 100644
--- a/src/server/mainwindow/mainwindow.cpp
+++ b/src/server/mainwindow/mainwindow.cpp
@@ -61,7 +61,10 @@ MainWindow::MainWindow(QWidget* parent) :
// Close button in tool bar
connect(ui->action_Exit, SIGNAL(triggered()), this, SLOT(onButtonExit()));
- connect(ui->action_BroadcastScreen, SIGNAL(triggered()), this, SLOT(onButtonBroadcast()));
+ connect(ui->action_BroadcastScreen, SIGNAL(triggered()), this, SLOT(onButtonStudentToAll()));
+ connect(ui->action_TutorToAll, SIGNAL(triggered()), this, SLOT(onButtonTutorToAll()));
+ connect(ui->action_StudentToTutor, SIGNAL(triggered()), this, SLOT(onButtonStudentToTutor()));
+ connect(ui->action_TutorToStudent, SIGNAL(triggered()), this, SLOT(onButtonTutorToStudent()));
connect(ui->action_Lock, SIGNAL(toggled(bool)), this, SLOT(onButtonLock(bool)));
// Clicking the session name label shows the edit field for it
connect(_sessionNameLabel, SIGNAL(clicked()), this, SLOT(onSessionNameClick()));
@@ -350,45 +353,192 @@ void MainWindow::onButtonChat()
*/
}
-void MainWindow::onButtonBroadcast()
+void MainWindow::prepareForProjection(Client * const from, Client * const to)
+{
+ // Projection source is never allowed to be an active VNC viewer
+ if (from->isActiveVncClient())
+ from->stopVncClient();
+
+ if (to == NULL)
+ {
+ // One to many
+ from->setProjectionSource(true);
+
+ if (from->isActiveVncServer())
+ {
+ // From is already active, if there is at least one active client, assume it is not
+ // shutting down, so we can directly tell the new client to connect to it
+ for (QList<ConnectionFrame*>::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it)
+ {
+ Client *c = (**it).client();
+ if (c == NULL || c->id() == from->id())
+ continue;
+ if (c->currentProjectionSource() != from->id())
+ continue;
+ // Yep :-)
+ this->onVncServerStateChange(from);
+ return;
+ }
+ }
+ // Could not take shortcut, (re)start VNC server on source
+ from->startVncServer();
+ return;
+ }
+
+ // One to one is desired, figure out what to do with current client
+
+ if (to->isActiveVncClient())
+ to->stopVncClient();
+ to->setDesiredProjectionSource(from->id());
+
+ if (from->isActiveVncServer())
+ {
+ // From is already active, if there is at least one active client, assume it is not
+ // shutting down, so we can directly tell the new client to connect to it
+ for (QList<ConnectionFrame*>::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it)
+ {
+ Client *c = (**it).client();
+ if (c == NULL || c->id() == from->id())
+ continue;
+ if (c->currentProjectionSource() != from->id())
+ continue;
+ // Yep :-)
+ this->onVncServerStateChange(from);
+ return;
+ }
+ }
+ // Could not take shortcut, (re)start VNC server on source
+ from->startVncServer();
+}
+
+void MainWindow::onButtonStudentToAll()
{
const qint64 now = QDateTime::currentMSecsSinceEpoch();
if (now < _buttonBlockTime)
return;
_buttonBlockTime = now + 3000;
- Client *source = NULL; // the desired source (selected frame)
- Client *oldSource = NULL; // if there is a client that is already broadcaster, save it here
+ //
+ Client *from = NULL;
for (QList<ConnectionFrame*>::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it)
{
Client *c = (**it).client();
+ if (c == NULL)
+ continue;
if ((**it).selected())
- source = c;
- if (c != NULL && c->isProjectionSource())
- oldSource = c;
+ from = c;
+ else
+ c->setProjectionSource(false);
}
- if (source == NULL && oldSource == NULL)
- {
- QMessageBox::information(this, tr("No Projection Source selected"), tr("You did not select any active client as the connection source."));
+ if (from == NULL)
+ QMessageBox::critical(this,
+ tr("Projection"),
+ tr("No projection source selected.")
+ );
+ else
+ prepareForProjection(from, NULL);
+}
+
+void MainWindow::onButtonStudentToTutor()
+{
+ const qint64 now = QDateTime::currentMSecsSinceEpoch();
+ if (now < _buttonBlockTime)
return;
+ _buttonBlockTime = now + 3000;
+ //
+ Client *from = NULL;
+ Client *to = NULL;
+ for (QList<ConnectionFrame*>::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it)
+ {
+ Client *c = (**it).client();
+ if (c == NULL)
+ continue;
+ if ((**it).selected())
+ from = c;
+ else if ((**it).isTutor())
+ to = c;
}
- if (oldSource != NULL)
+ if (from == NULL)
+ QMessageBox::critical(this,
+ tr("Projection"),
+ tr("No projection source selected.")
+ );
+ else if (to == NULL)
+ QMessageBox::critical(this,
+ tr("Projection"),
+ tr("No tutor defined, or tutor is offline.")
+ );
+ else if (to == from)
+ QMessageBox::critical(this,
+ tr("Projection"),
+ tr("Selected projection target is tutor.")
+ );
+ else
+ prepareForProjection(from, to);
+}
+
+void MainWindow::onButtonTutorToAll()
+{
+ const qint64 now = QDateTime::currentMSecsSinceEpoch();
+ if (now < _buttonBlockTime)
+ return;
+ _buttonBlockTime = now + 3000;
+ //
+ Client *from = NULL;
+ for (QList<ConnectionFrame*>::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it)
{
- // Is already broadcast source, disable
- oldSource->setProjectionSource(false);
- oldSource->stopVncServer();
- if (source == NULL || source->id() == oldSource->id())
- return;
+ Client *c = (**it).client();
+ if (c == NULL)
+ continue;
+ if ((**it).isTutor())
+ from = c;
+ else
+ c->setProjectionSource(false);
}
- source->setProjectionSource(true);
+ if (from == NULL)
+ QMessageBox::critical(this,
+ tr("Projection"),
+ tr("No tutor defined, or tutor is offline.")
+ );
+ else
+ prepareForProjection(from, NULL);
+}
+
+void MainWindow::onButtonTutorToStudent()
+{
+ const qint64 now = QDateTime::currentMSecsSinceEpoch();
+ if (now < _buttonBlockTime)
+ return;
+ _buttonBlockTime = now + 3000;
+ //
+ Client *from = NULL;
+ Client *to = NULL;
for (QList<ConnectionFrame*>::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it)
{
Client *c = (**it).client();
- if (c == NULL || c->id() == source->id())
+ if (c == NULL)
continue;
- //c->setDesiredProjectionSource(source->id());
- c->setProjectionSource(false);
+ if ((**it).selected())
+ to = c;
+ else if ((**it).isTutor())
+ from = c;
}
- source->startVncServer();
+ if (from == NULL)
+ QMessageBox::critical(this,
+ tr("Projection"),
+ tr("No projection source selected.")
+ );
+ else if (to == NULL)
+ QMessageBox::critical(this,
+ tr("Projection"),
+ tr("No tutor defined, or tutor is offline.")
+ );
+ else if (to == from)
+ QMessageBox::critical(this,
+ tr("Projection"),
+ tr("Selected projection source is tutor.")
+ );
+ else
+ prepareForProjection(from, to);
}
void MainWindow::onButtonLock(bool checked)
@@ -518,11 +668,11 @@ void MainWindow::onClientAuthenticated(Client* client)
// Move to any free tile
placeFrameInFreeSlot(cf);
}
- // Assign client instance
- cf->assignClient(client);
// Make first active client tutor
if (!anyClient && !hasActiveTutor)
cf->setTutor(true);
+ // Assign client instance
+ cf->assignClient(client);
// ################
NetworkMessage msg;
// If clients are currently locked, tell this new client
diff --git a/src/server/mainwindow/mainwindow.h b/src/server/mainwindow/mainwindow.h
index 4f9d142..5905cf5 100644
--- a/src/server/mainwindow/mainwindow.h
+++ b/src/server/mainwindow/mainwindow.h
@@ -38,6 +38,7 @@ private:
ConnectionFrame* createFrame();
bool loadPosition(QSettings& settings, const QString& id, int& x, int& y);
void savePosition(ConnectionFrame *cf);
+ void prepareForProjection(Client * const from, Client * const to);
public:
MainWindow(QWidget *parent = 0);
@@ -57,7 +58,10 @@ protected slots:
void onSessionNameUpdate();
void onButtonSettings();
void onButtonChat();
- void onButtonBroadcast();
+ void onButtonStudentToAll();
+ void onButtonStudentToTutor();
+ void onButtonTutorToAll();
+ void onButtonTutorToStudent();
void onButtonLock(bool checked);
void onButtonExit();
// connection frame
diff --git a/src/server/net/client.cpp b/src/server/net/client.cpp
index ca91e76..e2ea933 100644
--- a/src/server/net/client.cpp
+++ b/src/server/net/client.cpp
@@ -20,7 +20,7 @@ ClientId Client::_clientIdCounter = 0;
Client::Client(QSslSocket* socket) :
_socket(socket), _authed(0), _desiredProjectionSource(0), _isProjectionSource(false),
- _currentProjectionSource(0), _vncPort(0), _activeVncClient(false)
+ _currentProjectionSource(0), _vncPort(0), _activeVncClient(false), _isTutor(false)
{
assert(socket != NULL);
_id = ++_clientIdCounter;
@@ -197,7 +197,8 @@ void Client::handleMsg()
return;
}
- if (_authed == 1) // Not authed yet, only care about login requests
+ // Not authed yet, only care about login requests
+ if (_authed == 1)
{
if (id == _LOGIN)
{
@@ -230,6 +231,7 @@ void Client::handleMsg()
return;
}
+ // Did not pass challenge yet
if (_authed == 0)
{
// Waiting for challenge reply by client
@@ -262,7 +264,7 @@ void Client::startVncServer()
_vncPort = 0;
_toClient.reset();
_toClient.setField(_ID, _VNCSERVER);
- _toClient.setField("ENABLE", QByteArray("1"));
+ _toClient.setField(_ENABLE, __FALSE);
sendMessage(_toClient);
}
@@ -270,10 +272,26 @@ void Client::stopVncServer()
{
_toClient.reset();
_toClient.setField(_ID, _VNCSERVER);
- _toClient.setField("ENABLE", QByteArray("0"));
+ _toClient.setField(_ENABLE, __FALSE);
sendMessage(_toClient);
}
+void Client::stopVncClient()
+{
+ _toClient.reset();
+ _toClient.setField(_ID, _VNCCLIENT);
+ sendMessage(_toClient);
+}
+
+void Client::setTutor(bool enable)
+{
+ _toClient.reset();
+ _toClient.setField(_ID, _TUTOR);
+ _toClient.setField(_ENABLE, _BOOL(enable));
+ sendMessage(_toClient);
+ _isTutor = enable;
+}
+
void Client::disconnect()
{
if (_socket != NULL)
diff --git a/src/server/net/client.h b/src/server/net/client.h
index 8004ebb..c90c884 100644
--- a/src/server/net/client.h
+++ b/src/server/net/client.h
@@ -51,6 +51,7 @@ private:
QString _vncRwPass, _vncRoPass;
int _vncPort;
bool _activeVncClient;
+ bool _isTutor;
void handleMsg();
void disconnect();
@@ -85,6 +86,8 @@ public:
inline void setCurrentProjectionSource(ClientId source) { _currentProjectionSource = source; }
void startVncServer();
void stopVncServer();
+ void stopVncClient();
+ void setTutor(bool enable);
signals:
void authenticating(Client* client, ClientLogin* request);
diff --git a/src/shared/networkmessage.cpp b/src/shared/networkmessage.cpp
index 9a7ba9f..f7972f0 100644
--- a/src/shared/networkmessage.cpp
+++ b/src/shared/networkmessage.cpp
@@ -190,7 +190,7 @@ bool NetworkMessage::parseMessage(char *buffer)
<< ") length > total remaining bytes (" << (_bufferSize - (ptr - buffer)) << ")";
return false;
}
- _fields.insert(QString::fromUtf8(ptr, keyLen), QByteArray(ptr + keyLen, valLen));
+ _fields.insert(QByteArray(ptr, keyLen), QByteArray(ptr + keyLen, valLen));
//qDebug() << "Got " << QString::fromUtf8(ptr, keyLen) << " -> " << QString::fromUtf8(ptr + keyLen, valLen);
ptr += keyLen + valLen;
}
@@ -260,9 +260,9 @@ void NetworkMessage::serializeMessage()
QByteArray buf;
//qDebug() << "Default size: " << buf.capacity();
buf.reserve(_lastBufferSize > 0 ? _lastBufferSize : 200);
- for (QHash<QString, QByteArray>::const_iterator it = _fields.begin(); it != _fields.end(); ++it)
+ for (QHash<QByteArray, QByteArray>::const_iterator it = _fields.begin(); it != _fields.end(); ++it)
{
- const QByteArray &ba = it.key().toUtf8();
+ const QByteArray &ba = it.key();
const QByteArray &val = it.value();
quint16 keyLen = _htons((quint16)ba.size());
quint16 valLen = _htons((quint16)val.size());
diff --git a/src/shared/networkmessage.h b/src/shared/networkmessage.h
index 5a8b2c2..0df51df 100644
--- a/src/shared/networkmessage.h
+++ b/src/shared/networkmessage.h
@@ -13,8 +13,8 @@
class QAbstractSocket;
class QUdpSocket;
-// define qstrings for message ids. this prevents implicit instanciation of the same qstrings over and over again
-#define MSGTYPE(name) static const QString _ ## name ( #name )
+// define QByteArrays for message ids. this prevents implicit instantiation of the same QByteArray over and over again
+#define MSGTYPE(name) static const QByteArray _ ## name ( #name )
MSGTYPE(ID);
MSGTYPE(IMG);
MSGTYPE(LOGIN);
@@ -31,14 +31,21 @@ MSGTYPE(IPLIST);
MSGTYPE(PORT);
MSGTYPE(CERT);
MSGTYPE(CHALLENGE);
+MSGTYPE(ENABLE);
MSGTYPE(ERROR);
+MSGTYPE(TUTOR);
+
+
+static const QByteArray __TRUE("1");
+static const QByteArray __FALSE("0");
+static const inline QByteArray& _BOOL(bool val) { if (val) return __TRUE; return __FALSE; }
class NetworkMessage
{
private:
char *_buffer;
quint32 _bufferSize, _bufferPos, _lastBufferSize;
- QHash<QString, QByteArray> _fields;
+ QHash<QByteArray, QByteArray> _fields;
int _mode; // 0 = none, 1 = reading, 2 = writing, 3 = read complete, 4 = write complete
void allocBuffer();
@@ -56,11 +63,11 @@ public:
void reset() { _fields.clear(); _bufferSize = 0; _mode = 0; }
const bool readComplete() const { return _mode == 3; }
const bool writeComplete() const { return _mode == 4; }
- const bool hasField(const QString& key) const { return _fields.contains(key); }
- const QString getFieldString(const QString& key) const { return QString::fromUtf8(_fields.value(key)); }
- const QByteArray getFieldBytes(const QString& key) const { return _fields.value(key); }
- void setField(const QString& key, const QByteArray& value) { if (_mode == 1 || _mode == 2) qFatal("setField called in bad state."); _fields.insert(key, value); _mode = 0; }
- void setField(const QString& key, const QString& value) { setField(key, value.toUtf8()); }
+ const bool hasField(const QByteArray& key) const { return _fields.contains(key); }
+ const QString getFieldString(const QByteArray& key) const { return QString::fromUtf8(_fields.value(key)); }
+ const QByteArray getFieldBytes(const QByteArray& key) const { return _fields.value(key); }
+ void setField(const QByteArray& key, const QByteArray& value) { if (_mode == 1 || _mode == 2) qFatal("setField called in bad state."); _fields.insert(key, value); _mode = 0; }
+ void setField(const QByteArray& key, const QString& value) { setField(key, value.toUtf8()); }
// Convenience
void buildErrorMessage(const QString& error);
void buildErrorMessage(const char* error);