\chapter{PVS-Steuerkonsole}

Die Steuerkonsole ist das Hauptquartier des \textbf{Pool Video Switch}. Sie wird auf der Dozentmaschine oder
einer geeigneten weiteren Maschine ausgeführt und sie ist für die Steuerung der Clients-Maschine zuständig.
Alleine diese Rolle der Steuerkonsole setzt schon voraus, dass das GUI so benutzerfreundlich aufgebaut werden soll,
dass diese Aufgabe vereinfacht wird.~\\

Wir werden uns in den nächsten Punkten auf den technischen Aufbau der Steuerkonsole fokussieren.
Wir werden als erstes  die Auswahl von Qt zum Aufbau des Server-GUI, dann werden wir die GUI Server-Konsole vorstellen und zum
Schluss werden wir die Beziehung Server-Client unter die Lupe nehmen.

\section{pvsmgr in Qt}
Das Server-GUI wurde in der ersten Version in GTK/Gnome implementiert. Dank der Flexibilität, die von Qt ermöglicht wird, wurde die komplette
Anwendung in Qt umgeschrieben. Qt ist ein User Interface Framework und ermöglicht die Implementierung von Anwendungen, die unter Linux (Unix), Windows, mobile und  eingebettete Systemen ausführbar sind.

\section{GUI Server-Konsole}
Hier sollte die Hauptsteuerung des PVS abgewickelt werden.

\subsection{Architektur}
Es wird u.a. möglich sein, Funktionen auszuführen wie: die Frame der einzelnen Clients ansehen, ein Profil anlegen,
Screenshot aufnehmen, ein (Un)Projektion ausführen, eine Nachricht an Clients verschicken, usw... Die Grundstruktur
des pvsmgr wird in der Abbildung \ref{fig:pvsmgr} illustriert. Das Bild zeigt uns das Hauptfenster (\textit{MainWindow})
der Anwendung und seine unterschiedlichen Komponenten:~\\ ~\\ ~\\  ~\\  ~\\ 
\begin{figure}[h]
	\centering
		\includegraphics[width=0.80\textwidth]{bilder/pvsmgr.jpg}
	\caption{pvsmgr-Architektur}
	\label{fig:pvsmgr}
\end{figure}
\textbf{MainWindow}~\\
Die Klasse MainWindow wird vom QMainWindow abgeleitet; das ist der Parent an der Spitze der Hierachie;
Sie zu zerstören, bedeutet ein automatisches
Schließen der einzelnen Komponente, also der gesammten Anwendung. Alle anderen Komponenten bauen auf ihr auf.
Die Abbildung \ref{fig:mainwindow} zeigt ihr Abhängigkeitsdiagramm.
~\\
Alle andere Komponenten (Klasse) der Anwendung haben die Klasse MainWindow als Parent. Qt verwaltet eine Struktur der
Art \textit{parent-child} Beziehung, so dass wenn ein Parent zerstört wird, werden alle seine Kinder (\textit{child})
automatisch mit zersört; Das ist der sogenannte \textit{Domino-Effekt}.
~\\
\begin{figure}[h]
	\centering
		\includegraphics[width=0.80\textwidth]{bilder/mainwindow.png}
	\caption{Abhängigkeitsdiagram: MainWindow}
	\label{fig:mainwindow}
\end{figure}


\textbf{Menubar}~\\
Diese Klasse enthält eine Liste von \textit{pull-down}-Menu und QMainWindow speichert diese im QMenuBar. Die Klasse
wird also vom QMenuBar abgeleitet. Die gespeicherten Menüs enthalten jeweils die Menu-Items, die nichts anderes als \textit{QAction} sind.
Beim Betätigen einer Aktion (Menü-Item) wird ein korrespondiertes \textit{SIGNAL} gesendet, wir verbinden dann dieses zu einem \textit{SLOTS},
wie hier gezeigt wird \textit{connect(actionCreate-profile, SIGNAL(triggered()), MainWindow, SLOT(createProfile()))}; Also beim Clicken auf das Menü-Item
"File->Profile manager" wird das Signal \textit{triggered()} gesendet, das automatisch das Slot \textit{createProfile()} aufruft. Genau dieses Prinzip
wird auch auf die Aktionen im Toolbar angewandt.

\textbf{Toolbar}~\\
Die Klasse wird vom QToolBatr abgeleitet und enthält eine Liste von Aktionen, die man unmittelbar auf die gesamten
oder die ausgewählten Clients in der ConnectionList anwenden kann. ~\\  ~\\

\textbf{ConnectionList}~\\
Sie enthält die Liste der verbundenen Clients. Sie ist vom QTableView abgeleitet. Die vorhandenen Clients in der Liste können
in unterschiedlichen Bezeichnungen angezeigt werden. Es ist also möglich die Clients unter verschiedenen Sichten anzuzeigen.
Die Clients können mit Name, IP-Adresse oder Username angezeigt werden. Wir entnehmen also, dass das QTableView genauer gesehen
3 Spalten enthält, von denen nur eins davon immer sichtbar wird. Dieses Geschehen lässt sich ganz trivial ausführen.
 Man soll lediglich dafür sorgen, dass wenn eine Spalte angezeigt wird, sollen die 2 anderen ausgeblendet werden.
Das QTableView steht zu diesem Zweck die Methode \textit{setColumnHidden(int column, bool hidden)} zur Verfügung, wobei \textit{column}
 die betroffene Spaltenummer (die erste Spalte hat den Index 0) ist und \textit{hidden} legt dann fest, ob die Spalte
ein-(\textit{true}) oder ausgeblendet(\textit{false}) bleiben soll. Angesichts des angewandten Selection-Model
 (\textit{QItemSelectionModel}) ist es möglich mehrere Clients (\textit{QAbstractItemView::ExtendedSelection}) aufzufassen und
die entsprechenden verfügbaren Aktionen aus dem Tollbar oder der ContexMenu auszuführen.~\\

\textbf{ConnectionWindow}~\\
Die Klasse ist wie der zentrale Widget der Anwendung. Sie ist vom QWidget abgeleitet und enthält die Frame der
jeweiligen verbundenen Clients. Klarerweise hat diese Komponente die MainWindow-Klasse als Parent.~\\

\textbf{ConsoleLog}~\\
Abgeleitet von QTextEdit, hier werden alle Logs angezeigt. Der Log-Bereich ist per Default ausgeblendet.
Man kann ihn aber anzeigen lassen. Man unterscheidet mehrere Arte von Logs: Chat, Error, Normal, Network und Terminal.
~\\

Die richtig konfigurierten Clients werden mit dem pvs-Server verbunden und werden auf der GUI Server-Konsole angezeigt.
 Der Server bietet 2 unterschiedliche Sichten zur Anzeige der verbundenen Clients an.

\subsubsection{Clientliste-Ansicht}
Diese Sicht ist eine Liste, die aus einem \textit{QTableview}-Object abgeleitet wird. Die Client-Liste ist definiert
durch die ConnectionList-Klasse die Abbildung \ref{fig:connectionlist} zeigt uns die Abhängigkeitsdiagramm dieser Klasse.
\begin{figure}[h]
	\centering
		\includegraphics[width=0.80\textwidth]{bilder/ConnectionList.png}
	\caption{Abhängigkeitsdiagramm der ConnectionList-Klasse}
	\label{fig:ConnectionList}
\end{figure}

Die Tabelle enthält 3 Spalten, von denen nur eine angezeigt werden kann. Mit Hilfe passender Tastenkombinationen
können die anderen Spalten angezeigt werden. Die Spalten enthalten jeweils den Name der Clients, seine IP-Adresse und seinen Username. Außerdem
haben wir hier ein Kontextmenü per Überschreibung der Methode \textit{mouseReleaseEvent(QMouseEvent * e)} aus der Mutter-Klasse (QTableView)
zur Verfügung gestellt. Das Kontextmenü ist hier im Grunde ein Popup-Menü, das Menü-Item enthält. Diese Menü-Items sind nichts anderes als Actionen
und sie werden behandelt wie wir es schon oben beschrieben haben. Das Popup-Menü wird angezeigt, wenn die rechte Mause-Taste auf einem Item in
\textit{QTableView} losgelassen wird.\\
Von der jeweiligen Clients in der ConnectionList wollen wir jetzt die entsprechenden VNC-Ansichten vorstellen.

\subsubsection{VNC-Ansicht}

Die zweite Anzeigemöglichkeit, die vom Server angeboten wird ist die Anzeige der VNC-Verbindung zwischen
Client und Server. Genauer gesagt, auf dem pvsmgr kann der Dozent jeder Zeit nachvollziehen, was auf der Client-Maschine
passiert, dies wird vom rfb (Remote Frame Buffer) ermöglicht. Zu dem jeweiligen Client wird vom Manager ein \textit{VNCClientThread()} initialisiert
und in dieser Klasse wird der rfb-Client instanziiert. Die Klasse\textit{VNCClientThread()} wird vom QThread abgeleitet, somit wird eine kontinuierliche
Abfrage des Client rfb gesichert. Als QThread kann man mit der Methode \textit{msleep(int updatefreq)} den Thread für eine bestimmte Zeit
(in Millisekunde) schlafen lassen; dies ermöglicht also den pvsmgr die Abfragefrequenz des Client-rfb zu steuern. Darüberhinaus wird
dem Dozent die Möglichkeit gegeben die Qualität der VNC-Qualität jeder Zeit festzulegen. Da es quasi nicht möglich ist, eine VNC-Qualität bei laufender
Verbindung zu ändern, ist es dann notwendig dem Thread der entsprechenden Client zu terminieren und einen neuen  mit dem gewünschten
Quality zu starten und danach dem Client diesen neuen Thread wieder zuzuordnen.~\\
\begin{figure}[h]
	\centering
		\includegraphics[width=0.80\textwidth]{bilder/connectionframe.png}
	\caption{Abhängigkeitsdiagramm der ConnectionFrame-Klasse}
	\label{fig:Connectionframe}
\end{figure}
Die VNC-Ströme werden in der ConnectionFrame-Klasse verwaltet. Die ConnectionFrame ist vom QGroupBox abgeleitet. Die Abbildung \ref{connectionframe}
das Abhängigkeitsdiagramm der Klasse. Die Klasse wird vom QGroupBox abgeleitet und enthält das Object QLabel, das die eigentlichen VNC-Ströme
anzeigt, denn QLabel ist im Qt eine optimale Unterstützung zum Anzeigen und zum skalieren von Bildern. Jede ConnectionFrame hat ein Kontextmenü und diese
werden genau so wie wir es in der ConnectionList beschrieben haben, verwaltet. \\

Wir fahren mit der Vorstellung der pvsmgr-Struktur fort. Wir wollen uns in den nächsten Punkten der Verbindung zwischen Client und Server
annähen, in dem wir dieser Aushandlung diese Verbindung betrachten. Allerdings werden wir nähere Details darüber in anderen Abschnitten erläutern.

\subsection{Client-Seite}

Wir wollen davon ausgehen, dass im Subnetz, indem sich die Client-Maschine befindet, bereits ein pvsmgr gestartet wurde.
 Die Abwicklung auf dem server werden wir im nächsten Punkt erläutern. Nach dem Start eines Server sendet dieser eine
Broadcast-Nachricht, die von allen verfügbaren Client erhalten wird. Erhält ein Client diese Nachricht, dann weiß er,
dass ein Server gerade am laufen ist. Anschließend fügt der Client diesen Server in seiner Server-Liste hinzu.
Wird es eine von einen anderen Server gesendetete Broadcast-Nachricht empfangen, wird ebenfalls den entsprechenden
Server in die Server-Liste des Client hinzugenommen.
Der Client verfügt also über eine Liste von potentiellen Server, mit denen er eine PVS-Verbindung aufbauen kann, die dann schließlich
eine VNC-Verbindung wird und erst dann kann die Remote Frame Buffer initialisiert werden. Verläuft diese Initiliasierung erfolgreich, wird bei dem Server
der VNC-Frame angezeigt.
Aus seiner Server-Liste kann der Client freiwillig den Server auswählen, mit dem er sich verbinden möchte. Allerdings
erfolgt die eigentliche Verbindung zwischen Server und Client erst, nachdem der Client das vom Dozent gesetzte Passwort
richtig eingegeben hat. Beim Start des Server wird vom System ein zufälliges Passwort generiert und der Dozent soll dieses den Client
im Raum bekanntgegeben, so dass ein anderer Client, der im Nebenraum steht und auch die Server-Broadcast-Nachricht erhalten hat,
keine M{\"0}glichkeit hat, mit diesem Server eine Verbindung aufbauen zu können.
%Die genaue Spezifikation der Abwicklung der Verbindung zwischen und Client  und Server kann in ServAppTech und in Service-Discovery entnommen werden.
Also nun hat ein Client das richtige Passwort eingeben und die Verbindung mit dem Server konnte erfolgreich aufgebaut werden. An dieser Stelle wollen
wir noch betonen, dass der Dozent selbst entscheiden kann, ob ein Passwort zum Verbindungsaufbau mit dem PVS-Server vom Client aus eingegeben werden
soll oder nicht. Dafür wird eine Checkbox  auf dem pvsmgr-GUI eingebaut, die beim Ankreuzen per SIGNAL-SLOT die Funktion
\textit{PVSConnectionManager::getManager()->setNeedPassword(bool needed)} aufruft, wobei mit \textit{needed=TRUE} wird ein Passwort benötigt. \\
Nun wollen wir erläutern wie der Server mit einer bestehenden Verbindung umgeht.~\\

\subsection{Server-Seite}

Wir hatten schon erwähnt, dass der Server 2 Ansichtsmöglichkeiten zur Annzeige eines verbundenen Client verfügt.
Nachdem ein Client mit dem Server eine Verbindung erfolgreich aufgebaut hat, wird fast zeitgleich erstmal der Client
links in der Connection-Liste angezeigt und dann wird eine VNC-Verbindung zwischen Client und Server so aufgebaut, dass auf der rechten
Seite (\textit{Connectionwindow}) das Client-Frame angezeigt werden kann. Jeder Frame wird so beschriftet,
dass es jeder Zeit möglich wird, aus einem Client in der Liste (links) den entsprechenden Frame (recht) anzuordnen.\\

Somit hat der Server einen besseren {\"U}berblick über die gesamten vorhandenen Verbindungen. Der Server kann also jegliche verfügbare
 Aktion ausführen. Der Betreiber (der Dozent) des pvsmgr verfügt über eine zweite Maschine, die an einen Beamer angeschlossen
wird und auf dieser Maschine läuft ein PVS-Client. Dieser Client wird als \textit{Superclient} bezeichnet und verfügt dementsprechend gegenüber anderen Clients über einen Sonderstatus. Z.B: bei einer LockAll-Aktion wird er nicht gesperrt und dabei muss geachtet werden, dass ein auf dem Superclient projektierter Client auch nicht gesperrt wird.

\section{Verbindungsverwaltung und Projektion}

Meldet sich ein Client an der PVS-Steuerkonsole an, wird der Bildschirminhalt des Clients zur Thumbnail Darstellung angefordert. Hierzu sendet der Client seine Verbindungsdaten, d.h. Passwort, RW Passwort und Port, an die Steuerkonsole (s.h. Liste der PVS Messages \ref{pvs-msg-liste}). Die Verbindungsdaten werden in der Klasse \texttt{pvsConnectionManager} in einer Liste \texttt{std::list<PVSClient*> \_listClients} von PVSClient Objekten verwaltet. Ein solches Clientobjekt enthält unter anderem Port, Passwort, RW Passwort sowie Flags, ob eine VNC Verbindung erlaubt ist, ob ein VNC Passwort vorhanden ist, und ob der Client gerade projeziert wird (siehe hierzu auch \texttt{/core/pvsClient.h}). Der pvsConnectionManager wird in allen Klassen verwendet, welche auf die Verbindungsdaten der Clients zugreifen müssen, daher ist er als Singleton implementiert und auf die entsprechende Instanz kann über \texttt{PVSConnectionManager::getManager()} zugegriffen werden.

\subsection{Projektion}
\label{pvs-console-projection}
Um zu gewährleisten, dass bei einer Projektion ein als Quelle ausgewählter Client nicht als Ziel einer Projektion gewählt werden kann, werden in der Klasse \texttt{ConnectionList}
eine Liste \texttt{QList<QString> targetList} mit den Projektionszielen und eine Map \texttt{QMap<QString, QList<QString> > sourceMap} mit der Quelle und der zugehörigen Liste von Zielen geführt. Wird ein Client als Projektionsquelle ausgewählt, wird zunächst überprüft, ob dieser Client schon in der Liste der Projektionsziele vorhanden ist. Ist er nicht vorhanden, wird ein Auswahldialog \texttt{projectionDialog} mit allen verfügbaren Projektionszielen angezeigt (ProjectionDialog erhält die entsprechende Liste durch\\ \texttt{MainWindow::getWindow()->getConnectionList()->getTargetToDisplay(source)}). Projektionsziele können hierbei alle angemeldeten Clients sein, die nicht Ziel oder Quelle einer anderen Projektion sind. Die Auswahl der Ziele im \texttt{projectionDialog} erfolgt durch Checkboxen. Die hierdurch gewählten Clients werden zurück an die den \texttt{projectionDialog} aufrufende Klasse übergeben. Nachdem Quelle und Ziel ausgewählt wurden, wird die Funktion \texttt{projectStations}, welche zunächst prüft, ob auf dem Quell-Client überhaupt ein VNC Server läuft, in der Klasse \texttt{ConnectionWindow} mit dem Quell-Client als Parameter aufgerufen. Ist ein VNC Server gestartet, so werden die Verbindungsdaten des Quell-Clients, die über die get-Methoden des entsprechenden PVSClient Objekts ausgelesen werden, an alle Ziel-Clients als durch Leerzeichen separierte Liste gesendet. Auf Clientseite werden diese Verbindungsdaten dann in ein Array transformiert und an den \texttt{clientVNCViewer} übergeben (via DBus).
Soll ein Client als Ziel zu einer existierenden Projektion hinzugefügt werden, wird der entsprechende Quellclient und alle neuen bzw. zusätzlichen Projektionsziele gewählt. Die Zielclients werden dann einfach der in der \texttt{sourceMap} gespeicherten Liste der Quelle sowie der \texttt{targetList} hinzugefügt.
\subsubsection{Qualitätsoptionen}
\label{pvs-console-quality}
Zusätzlich zu den Verbindungsdaten werden Qualitätsoptionen zu der gesendeten Nachricht hinzugefügt. Die Qualitätsoption ist ein Integerwert 0,1 oder 2 wobei 0 der besten Qualität, 2 der schlechtesten Qualität entspricht. Dieser Wert wird an den Zielclient einer Projektion gesendet, welcher die Qualitätseinstellungen des VNC-Viewers entsprechend anpasst. Aktuell wird die Qualität immer auf 0 gesetzt, da noch die Einstellungsmöglichkeiten in der GUI fehlen.
\subsection{Remote Help}

Remote Help funktioniert analog zur Projektion, jedoch ist hier zu gewährleisten, dass jeweils nur ein Quellclient und ein Zielclient ausgewählt werden, da es nicht sinnvoll ist, Tastatur und Maus eines Clients von mehreren anderen Clients aus zu steuern. Anstelle des Passworts wird das RW-Passwort des Clients verwendet. Die Möglichkeit, die Maus und die Tastatur eines Clients zu steuern, ist mit dem verwendeten VNC-Server schon gegeben, für die Steuerkonsole ändert sich hier nichts, lediglich der VNC Viewer muss die Tastatureingaben und die Mausbewegung an den VNC Server weitergeben (siehe hierzu auch \ref{pvsclient-remotehelp} Tastatur und Maussteuerung).