From 1f6493e319016f8c375b62f2109ee57f5cea828d Mon Sep 17 00:00:00 2001 From: Christian Klinger Date: Tue, 27 Sep 2016 15:38:39 +0200 Subject: Implemented 'majority vote' to determine the toolbar options. clients in exam-mode are also displayed differently. --- src/client/clientapp/clientapp.cpp | 3 +- src/client/net/serverconnection.cpp | 17 +++++- src/server/connectionframe/connectionframe.cpp | 31 ++++++++-- src/server/connectionframe/connectionframe.h | 1 + src/server/mainwindow/mainwindow.cpp | 84 ++++++++++++++++++++------ src/server/mainwindow/mainwindow.h | 3 + src/server/net/client.cpp | 20 +++--- src/server/net/client.h | 5 ++ src/shared/networkmessage.h | 1 + 9 files changed, 130 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/client/clientapp/clientapp.cpp b/src/client/clientapp/clientapp.cpp index 3d2dba1..f177d44 100644 --- a/src/client/clientapp/clientapp.cpp +++ b/src/client/clientapp/clientapp.cpp @@ -1,6 +1,6 @@ #include "clientapp.h" -ClientApp::ClientApp(int& argc, char** argv) : QApplication(argc, argv), _connectionMode(ConnectionMode::None) { +ClientApp::ClientApp(int& argc, char** argv) : QApplication(argc, argv), _connectionMode(ConnectionMode::None), _examMode(false) { /* some values */ setOrganizationName("openslx"); setOrganizationDomain("openslx.org"); @@ -32,6 +32,7 @@ ClientApp::ClientApp(int& argc, char** argv) : QApplication(argc, argv), _connec void ClientApp::parseParameters() { for (QString a : arguments()) { if (a == "--exam-mode") { + qDebug() << "setting exam-mode to true"; _examMode = true; } else if (a == "--auto") { _connectionMode = ConnectionMode::Auto; diff --git a/src/client/net/serverconnection.cpp b/src/client/net/serverconnection.cpp index 3ff16bf..418e13c 100644 --- a/src/client/net/serverconnection.cpp +++ b/src/client/net/serverconnection.cpp @@ -153,6 +153,9 @@ void ServerConnection::handleMsg() _toServer.setField(_ID, _LOGIN); _toServer.setField("HOST", QHostInfo::localHostName()); _toServer.setField("NAME", QString(user)); + qDebug() << "logging into manager, exam mode is " << clientApp->isExamMode(); + _toServer.setField(_EXAMMODE, clientApp->isExamMode() ? __TRUE : __FALSE); + /* TODO: (Question) Why is this here not using sendMessage() ? */ qDebug("Sending login request!"); if (_toServer.writeMessage(_socket)) { @@ -182,7 +185,11 @@ void ServerConnection::handleMsg() if (id == _THUMB) { if (clientApp->isExamMode()) { - qDebug() << "denied request for screenshot (exam mode)"; + /* but we still have to send a message, to reset the timeout timer of the server */ + QByteArray emptyArray; + _toServer.setField(_ID, _THUMB); + _toServer.setField(_IMG, emptyArray); + sendMessage(_toServer); return; } int x = _fromServer.getFieldString(_X).toInt(); @@ -240,6 +247,10 @@ void ServerConnection::handleMsg() } // message VNCSERVER - start local vncserver else if (id == _VNCSERVER) { + if (clientApp->isExamMode()) { + qDebug() << "denied request for vnc server (exam mode)"; + return; + } const bool enable = (_fromServer.getFieldString("ENABLE").toInt() != 0); if (enable) { @@ -253,6 +264,10 @@ void ServerConnection::handleMsg() } else if (id == _VNCCLIENT) { + if (clientApp->isExamMode()) { + qDebug() << "denied request for vnc projection (exam mode)"; + return; + } const QString host(_fromServer.getFieldString("HOST")); const int port = _fromServer.getFieldString("PORT").toInt(); if (host.isEmpty() || port <= 0) diff --git a/src/server/connectionframe/connectionframe.cpp b/src/server/connectionframe/connectionframe.cpp index e962e39..3278e04 100644 --- a/src/server/connectionframe/connectionframe.cpp +++ b/src/server/connectionframe/connectionframe.cpp @@ -37,6 +37,14 @@ static QString style_selectedTutor( "QLabel{ background-color: #FFF; border-radius: 2px; color: black;} \ QGroupBox { background-color: #99ff99; margin: 0px; border-radius: 4px; border: 4px solid #6C8CF0;}" ); +static QString style_exam ( + "QLabel{ background-color: #919191; color: black; } \ + QGroupBox { background-color: #d35400; margin: 1px; border-radius: 4px}" +); +static QString style_exam_selected ( + "QLabel{ background-color: #919191; color: black; } \ + QGroupBox { background-color: #cc743a; margin: 1px; border-radius: 4px}" +); static QString style_disconnected( "QLabel{ background-color: #919191; color: black; } \ QGroupBox { background-color: #7F7F7F; margin: 1px; border-radius: 4px}" @@ -82,6 +90,10 @@ ConnectionFrame::ConnectionFrame(QWidget *parent, int width, int height) : _lblHostName = new QLabel("PC", this); _lblHostName->setAlignment(Qt::AlignHCenter); + _lblExamMode = new QLabel(tr("EXAM-MODE"), this); + _lblExamMode->setAlignment(Qt::AlignHCenter); + _lblExamMode->setVisible(false); + _icoCam = addIcon(cam); _icoEye = addIcon(eye); _icoLock = addIcon(lock); @@ -93,6 +105,8 @@ ConnectionFrame::ConnectionFrame(QWidget *parent, int width, int height) : _mainLayout->addLayout(_iconLayout); _mainLayout->addStretch(); + _mainLayout->addWidget(_lblExamMode); + _mainLayout->addStretch(); _mainLayout->addWidget(_lblUserName); _mainLayout->addWidget(_lblHostName); this->setLayout(_mainLayout); @@ -270,7 +284,7 @@ void ConnectionFrame::mouseDoubleClickEvent(QMouseEvent* event) void ConnectionFrame::paintEvent(QPaintEvent *event) { QGroupBox::paintEvent(event); - if (_remoteScreen.isNull() || Global::isExam()) { + if (_remoteScreen.isNull()) { return; } @@ -344,6 +358,8 @@ void ConnectionFrame::updateAppearance() _icoEye->setVisible(_client->isActiveVncClient()); _icoLock->setVisible(_client->isLocked()); + + _lblExamMode->setVisible(_client->isExamMode()); // Normal client, no special stuff active if (_isSelected && _isTutor){ @@ -352,13 +368,18 @@ void ConnectionFrame::updateAppearance() else if (_isTutor){ this->setStyleSheet(style_tutor); } - else if (_isSelected){ + else if (_client->isExamMode()) { + if (_isSelected) { + this->setStyleSheet(style_exam_selected); + } else { + this->setStyleSheet(style_exam); + } + } + else if (_isSelected) { this->setStyleSheet(style_selectedStudent); - } - else{ + else { this->setStyleSheet(style_student); - } } diff --git a/src/server/connectionframe/connectionframe.h b/src/server/connectionframe/connectionframe.h index d5551cb..9ac71c0 100644 --- a/src/server/connectionframe/connectionframe.h +++ b/src/server/connectionframe/connectionframe.h @@ -20,6 +20,7 @@ private: QBoxLayout *_iconLayout; QLabel *_lblUserName; QLabel *_lblHostName; + QLabel *_lblExamMode; QLabel *_icoCam, *_icoEye, *_icoLock; QList _icons; diff --git a/src/server/mainwindow/mainwindow.cpp b/src/server/mainwindow/mainwindow.cpp index ae83dfb..ff34911 100644 --- a/src/server/mainwindow/mainwindow.cpp +++ b/src/server/mainwindow/mainwindow.cpp @@ -102,6 +102,15 @@ MainWindow::MainWindow(QWidget* parent) : ui->action_Exit->setStatusTip(tr("Exit")); ui->action_Lock->setStatusTip(tr("Lock or Unlock all Clients")); + /* the label */ + _examModeLabel = new QLabel("Klausur-\nModus"); + _examModeLabel->setObjectName("examModeLabel"); + _examModeLabel->setAlignment(Qt::AlignCenter); + _examModeLabel->setFixedHeight(400); + ui->toolBar->insertWidget(ui->action_TutorToStudent, _examModeLabel); + + Global::setExam(false); + updateExamMode(); // Close button in tool bar connect(ui->action_Exit, SIGNAL(triggered()), this, SLOT(onButtonExit())); @@ -117,26 +126,11 @@ MainWindow::MainWindow(QWidget* parent) : connect(ui->actionReload_Room_Configuration, SIGNAL(triggered()), this, SLOT(onButtonReloadRoomConfig())); connect(ui->action_DeleteClient, SIGNAL(triggered()), this, SLOT(onDeleteClient())); - /* In exam-mode: disable most features */ - QSharedPointer conf = Global::getSettings(); - if (conf->contains("examMode")) { - Global::setExam(conf->value("examMode").toBool()); - } - - if (Global::isExam()) { - qDebug() << "Exam-Mode!"; - ui->action_TutorToAll->setVisible(false); - ui->action_StudentToTutor->setVisible(false); - ui->action_StudentToTutorExclusive->setVisible(false); - ui->action_TutorToStudent->setVisible(false); - ui->action_StopProjection->setVisible(false); - - QLabel* examModeLabel = new QLabel("Klausur-\nModus"); - examModeLabel->setObjectName("examModeLabel"); - examModeLabel->setAlignment(Qt::AlignCenter); - examModeLabel->setFixedHeight(400); - ui->toolBar->insertWidget(ui->action_TutorToStudent, examModeLabel); - } + // /* In exam-mode: disable most features */ + // QSharedPointer conf = Global::getSettings(); + // if (conf->contains("examMode")) { + // Global::setExam(conf->value("examMode").toBool()); + // } /* disable context-sensitive buttons by default */ @@ -186,6 +180,48 @@ MainWindow::MainWindow(QWidget* parent) : tryToUseRoomTemplate(); } +/** this function determines if the number of clients in exam mode comprise +* more than 50%. In that case the whole manager switches to exam mode, +* disabling many features in the toolbar **/ +void MainWindow::updateExamMode() { + /* TODO */ + int numerator = 0; + int denominator = 0; + + + for (QList::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it) { + Client* c = (*it)->client(); + if (c != NULL) { + bool b = c->isExamMode(); + numerator += b ? 1 : 0; + denominator++; + } + + } + qDebug() << "updateExamMode(), ratio: " << numerator << "/" << denominator; + + /* TODO: Find clients */ + // static const QMap rooms = getRooms(); + // for (auto k : rooms.keys()) { + // Room* r = rooms.value(k); + // numerator += r->examMode; + // denominator++; + // } + Global::setExam(numerator * 2 >= denominator && denominator > 0); + bool e = Global::isExam(); + qDebug() << "isExam is " << e; + ui->action_TutorToAll->setVisible(!e); + ui->action_StudentToTutor->setVisible(!e); + ui->action_StudentToTutorExclusive->setVisible(!e); + ui->action_TutorToStudent->setVisible(!e); + ui->action_StopProjection->setVisible(!e); + _examModeLabel->setVisible(e); + _examModeLabel->setFixedHeight(e ? 400 : 0); + + + +} + MainWindow::~MainWindow() { _sessionNameLabel->deleteLater(); @@ -1184,6 +1220,9 @@ void MainWindow::onClientConnected(Client* client) void MainWindow::onClientAuthenticating(Client* client, ClientLogin* request) { disconnect(client, SIGNAL(authenticating(Client*, ClientLogin*)), this, SLOT(onClientAuthenticating(Client*, ClientLogin*))); + /* copy examMode */ + client->setExamMode(request->examMode); + if (!request->accept) // Another receiver of that signal already rejected the client, so nothing to do return; bool inuse; @@ -1251,6 +1290,7 @@ void MainWindow::onClientAuthenticated(Client* client) } } + bool isTutor = false; if (!hasActiveTutor) { @@ -1271,6 +1311,7 @@ void MainWindow::onClientAuthenticated(Client* client) existing->setTutor(isTutor); existing->assignClient(client); tellClientCurrentSituation(client); + updateExamMode(); return; } @@ -1307,6 +1348,7 @@ void MainWindow::onClientAuthenticated(Client* client) resizeEvent(NULL); // This is where all the positioning should be tellClientCurrentSituation(client); + updateExamMode(); } @@ -1448,9 +1490,11 @@ void MainWindow::onDeleteClient() { frame->deleteLater(); _clientFrames.removeOne(frame); lockContextButtons(); + updateExamMode(); return; } else { frame->move(frame->getPreviousPosition()); + updateExamMode(); return; } } diff --git a/src/server/mainwindow/mainwindow.h b/src/server/mainwindow/mainwindow.h index b3b6f13..3de0e1c 100644 --- a/src/server/mainwindow/mainwindow.h +++ b/src/server/mainwindow/mainwindow.h @@ -42,6 +42,7 @@ private: int _tilesX; int _tilesY; QImage* _backgroundImage = NULL; + QLabel* _examModeLabel = NULL; /* virtual columns to preserve the aspect ratio of the loaded room */ @@ -130,5 +131,7 @@ protected slots: void onClientAuthenticated(Client* client); void onVncServerStateChange(Client* client); void onVncClientStateChange(Client* client); + + void updateExamMode(); }; #endif diff --git a/src/server/net/client.cpp b/src/server/net/client.cpp index 5086ea1..84c45a9 100644 --- a/src/server/net/client.cpp +++ b/src/server/net/client.cpp @@ -150,7 +150,6 @@ void Client::handleMsg() qDebug("Received message with empty ID field. ignored."); return; } - //qDebug() << "Received message " << id; if (_authed == 2) { @@ -159,13 +158,16 @@ void Client::handleMsg() { QPixmap pixmap; const QByteArray& rawImage = _fromClient.getFieldBytes("IMG"); - if (!pixmap.loadFromData(rawImage)) - { - qDebug("Could not decode thumbnail image from client."); - return; + /* size 0 means the client is in exam-mode and therefore doesn't send any thumbnail */ + if (rawImage.size() > 0) { + if (!pixmap.loadFromData(rawImage)) + { + qDebug("Could not decode thumbnail image from client."); + return; + } + _rawRemoteScreen = QByteArray(rawImage); + emit thumbUpdated(this, pixmap, rawImage); } - _rawRemoteScreen = QByteArray(rawImage); - emit thumbUpdated(this, pixmap, rawImage); } else if (id == _VNCSERVER) { @@ -225,8 +227,10 @@ void Client::handleMsg() request.accept = true; request.host = _fromClient.getFieldString("HOST"); request.name = _fromClient.getFieldString("NAME"); + request.examMode = _fromClient.getFieldString(_EXAMMODE) == __TRUE; request.ip = _socket->peerAddress().toString(); - qDebug() << "Login request by " << request.name; + + qDebug() << "Login request by " << request.name << (request.examMode ? "(in exam mode)" : ""); // emit event, see if request is accepted emit authenticating(this, &request); if (!request.accept) diff --git a/src/server/net/client.h b/src/server/net/client.h index d2097ad..872d0e1 100644 --- a/src/server/net/client.h +++ b/src/server/net/client.h @@ -18,6 +18,7 @@ struct ClientLogin QString name; QString host; QString ip; + bool examMode; }; @@ -40,10 +41,12 @@ public: inline const bool isLocked() const { return _locked; } inline const int desiredProjectionSource(){ return _desiredSource; } inline const int projectionSource() const { return _projectionSource; } + inline const int isExamMode() const { return _isExamMode; } // Setters inline void setTutor(bool enable){ _isTutor = enable; } inline void setDesiredProjectionSource(int id){_desiredSource = id;} + inline void setExamMode(bool mode) { _isExamMode = mode; } //Send message stuff void startVncServer(); @@ -71,8 +74,10 @@ private: int _projectionSource; // The source the client was or is connected to (depends on _isActiveVncClient) bool _isActiveVncClient; // VNCclient state. indicating that the client is displaying a remote screen via VNC bool _isTutor; // Flag indicating that the client has been set as a tutor + bool _isExamMode; QByteArray _rawRemoteScreen; + static int _clientIdCounter; bool isManagerMachine(); diff --git a/src/shared/networkmessage.h b/src/shared/networkmessage.h index 2e8c1c5..ddc810a 100644 --- a/src/shared/networkmessage.h +++ b/src/shared/networkmessage.h @@ -38,6 +38,7 @@ MSGTYPE(CHALLENGE); MSGTYPE(ENABLE); MSGTYPE(ERROR); MSGTYPE(TUTOR); +MSGTYPE(EXAMMODE); static const QByteArray __TRUE("1"); -- cgit v1.2.3-55-g7522