summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSebastian2010-05-12 19:42:27 +0200
committerSebastian2010-05-12 19:42:27 +0200
commitce3329047d378a14006ce74ec273ac59e3375303 (patch)
tree782430f270b4c7aca1b35d5b7813518e3797c555 /src
downloadpvs-ce3329047d378a14006ce74ec273ac59e3375303.tar.gz
pvs-ce3329047d378a14006ce74ec273ac59e3375303.tar.xz
pvs-ce3329047d378a14006ce74ec273ac59e3375303.zip
initial import of latest svn version
Diffstat (limited to 'src')
-rw-r--r--src/core/pvsChatClient.cpp151
-rw-r--r--src/core/pvsChatClient.h71
-rw-r--r--src/core/pvsChatMsg.cpp108
-rw-r--r--src/core/pvsChatMsg.h48
-rw-r--r--src/core/pvsClient.cpp301
-rw-r--r--src/core/pvsClient.h129
-rw-r--r--src/core/pvsConnectionManager.cpp483
-rw-r--r--src/core/pvsConnectionManager.h118
-rw-r--r--src/core/pvsServer.cpp22
-rw-r--r--src/core/pvsServer.h24
-rw-r--r--src/core/vncConnection.cpp261
-rw-r--r--src/core/vncConnection.h99
-rw-r--r--src/gui/aboutDialog.cpp58
-rw-r--r--src/gui/aboutDialog.h30
-rw-r--r--src/gui/clientChatDialog.cpp298
-rw-r--r--src/gui/clientChatDialog.h63
-rw-r--r--src/gui/clientConfigDialog.cpp105
-rw-r--r--src/gui/clientConfigDialog.h44
-rw-r--r--src/gui/clientFileReceiveDialog.cpp181
-rw-r--r--src/gui/clientFileReceiveDialog.h47
-rw-r--r--src/gui/clientFileSendDialog.cpp248
-rw-r--r--src/gui/clientFileSendDialog.h76
-rw-r--r--src/gui/clientInfoDialog.cpp60
-rw-r--r--src/gui/clientInfoDialog.h32
-rw-r--r--src/gui/clientVNCViewer.cpp273
-rw-r--r--src/gui/clientVNCViewer.h67
-rw-r--r--src/gui/connectionDialog.cpp216
-rw-r--r--src/gui/connectionDialog.h123
-rw-r--r--src/gui/connectionFrame.cpp557
-rw-r--r--src/gui/connectionFrame.h199
-rw-r--r--src/gui/connectionList.cpp603
-rw-r--r--src/gui/connectionList.h134
-rw-r--r--src/gui/connectionWindow.cpp763
-rw-r--r--src/gui/connectionWindow.h125
-rw-r--r--src/gui/dialog.cpp74
-rw-r--r--src/gui/dialog.h33
-rw-r--r--src/gui/frame.cpp332
-rw-r--r--src/gui/frame.h90
-rw-r--r--src/gui/mainWindow.cpp1205
-rw-r--r--src/gui/mainWindow.h200
-rw-r--r--src/gui/profileDialog.cpp179
-rw-r--r--src/gui/profileDialog.h46
-rw-r--r--src/gui/projectionDialog.cpp140
-rw-r--r--src/gui/projectionDialog.h46
-rw-r--r--src/gui/serverChatDialog.cpp281
-rw-r--r--src/gui/serverChatDialog.h67
-rw-r--r--src/gui/serverFileTransfert.cpp265
-rw-r--r--src/gui/serverFileTransfert.h52
-rw-r--r--src/gui/ui/aboutDialog.ui251
-rw-r--r--src/gui/ui/clientChatDialog.ui121
-rw-r--r--src/gui/ui/clientConfigDialog.ui280
-rw-r--r--src/gui/ui/clientFileReceiveDialog.ui134
-rw-r--r--src/gui/ui/clientFileSendDialog.ui134
-rw-r--r--src/gui/ui/clientInfoDialog.ui60
-rw-r--r--src/gui/ui/clientNicklistDialog.ui110
-rw-r--r--src/gui/ui/clientToolbar.ui214
-rw-r--r--src/gui/ui/dialog.ui66
-rw-r--r--src/gui/ui/mainwindow.ui540
-rw-r--r--src/gui/ui/mainwindowtouch.ui645
-rw-r--r--src/gui/ui/profileDialog.ui179
-rw-r--r--src/gui/ui/projectionDialog.ui98
-rw-r--r--src/gui/ui/serverChatDialog.ui121
-rw-r--r--src/gui/ui/startdialog.ui195
-rw-r--r--src/gui/ui/touchgui.ui322
-rw-r--r--src/net/SslServer.cpp130
-rw-r--r--src/net/SslServer.h50
-rw-r--r--src/net/pvsClientConnection.cpp178
-rw-r--r--src/net/pvsClientConnection.h67
-rw-r--r--src/net/pvsDiscoveredServer.cpp152
-rw-r--r--src/net/pvsDiscoveredServer.h63
-rw-r--r--src/net/pvsListenServer.cpp308
-rw-r--r--src/net/pvsListenServer.h106
-rw-r--r--src/net/pvsLocalhostCommunicator.cpp104
-rw-r--r--src/net/pvsLocalhostCommunicator.h51
-rw-r--r--src/net/pvsMsg.cpp207
-rw-r--r--src/net/pvsMsg.h73
-rw-r--r--src/net/pvsServerConnection.cpp243
-rw-r--r--src/net/pvsServerConnection.h99
-rw-r--r--src/net/pvsServiceBroadcast.cpp51
-rw-r--r--src/net/pvsServiceBroadcast.h46
-rw-r--r--src/net/pvsServiceDiscovery.cpp181
-rw-r--r--src/net/pvsServiceDiscovery.h57
-rw-r--r--src/pvs.cpp629
-rw-r--r--src/pvs.h146
-rw-r--r--src/pvsDaemon.cpp362
-rw-r--r--src/pvsgui.cpp444
-rw-r--r--src/pvsgui.h103
-rw-r--r--src/pvsmgr.cpp55
-rw-r--r--src/pvsmgrtouch.cpp55
-rw-r--r--src/setup.h13
-rw-r--r--src/util/CertManager.cpp87
-rw-r--r--src/util/CertManager.h30
-rw-r--r--src/util/TextFile.cpp39
-rw-r--r--src/util/TextFile.h26
-rw-r--r--src/util/clientGUIUtils.cpp144
-rw-r--r--src/util/clientGUIUtils.h39
-rw-r--r--src/util/consoleLogger.cpp355
-rw-r--r--src/util/consoleLogger.h273
-rw-r--r--src/util/dispatcher.h210
-rw-r--r--src/util/pvsSettingsManager.cpp185
-rw-r--r--src/util/pvsSettingsManager.h50
-rw-r--r--src/util/serviceDiscoveryUtil.cpp65
-rw-r--r--src/util/serviceDiscoveryUtil.h19
-rw-r--r--src/util/timeUtil.cpp42
-rw-r--r--src/util/timeUtil.h34
-rw-r--r--src/util/util.cpp416
-rw-r--r--src/util/util.h59
-rw-r--r--src/util/vncClientThread.cpp249
-rw-r--r--src/util/vncClientThread.h114
-rw-r--r--src/version.h2
110 files changed, 19008 insertions, 0 deletions
diff --git a/src/core/pvsChatClient.cpp b/src/core/pvsChatClient.cpp
new file mode 100644
index 0000000..6717e34
--- /dev/null
+++ b/src/core/pvsChatClient.cpp
@@ -0,0 +1,151 @@
+/*
+# Copyright (c) 2009,2010 - OpenSLX Project, Computer Center University of
+# Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+# -----------------------------------------------------------------------------
+# pvsChatClient.cpp
+# - Methods of the chat service.
+# -----------------------------------------------------------------------------
+*/
+
+#include "pvsChatClient.h"
+
+using namespace std;
+
+// Constructor
+PVSChatClient::PVSChatClient()
+{
+ _chatServerConnection = NULL;
+ _source = getFullUsername();
+ _registered = true;
+}
+
+PVSChatClient::~PVSChatClient()
+{
+
+}
+
+// Get Chat login name.
+QString PVSChatClient::getSource()
+{
+ return _source;
+}
+
+// Set (from server) assigned username.
+void PVSChatClient::setSource(QString name)
+{
+ _source = name;
+ _registered = true;
+}
+
+bool PVSChatClient::isRegistered()
+{
+ return _registered;
+}
+
+// Set PVSServerConnection
+void PVSChatClient::setServerConnection(PVSServerConnection* sc)
+{
+ if (sc)
+ {
+ _chatServerConnection = sc;
+ _chatServerConnection->addChatHandler("*", this, &PVSChatClient::receive);
+ }
+}
+
+// Send a message to Server.
+void PVSChatClient::send(QString tar, QString msg)
+{
+ // Append username to msg.
+ QString username = _source;
+ username.append(":");
+ msg = username.append(msg) ;
+
+ // Create a Msg.
+ PVSMsg myMsg(PVSMESSAGE, tar, msg, 0);
+
+ // Send the message.
+ if (_chatServerConnection)
+ _chatServerConnection->sendMessage(myMsg);
+ else
+ ConsoleLog writeError("[CHAT] Chat get no server connection"); // no ServerConnection
+
+}
+
+// Handle messages from server.
+void PVSChatClient::receive(PVSMsg recv)
+{
+ PVSChatMsg chatMsg(recv);
+
+ if(chatMsg.isCommand()) // command message for update of the client list.
+ {
+ _chatCommandDispatcher.fire(chatMsg);
+ }
+ else // conversation message.
+ {
+ if(chatMsg.getMsg().size())
+ _chatMessageDispatcher.fire(chatMsg);
+ }
+}
+
+// Return the current list of logged Clients.
+QStringList PVSChatClient::getClients()
+{
+ return _clients;
+}
+
+// Return the ip of the username.
+QString PVSChatClient::getIPFromUsername(QString username)
+{
+ if(_clientsData.contains(username))
+ {
+ return _clientsData.value(username);
+ }
+ else
+ {
+ ConsoleLog writeError("[CHAT] Wanted key was not found in clients hash table.");
+ return QString("ip not found");
+ }
+}
+
+// Add the name and ip of a new client.
+void PVSChatClient::addClient(QString name, QString ip)
+{
+ if(!_clients.contains(name))
+ {
+ _clients.append(name);
+ _clientsData[name] = ip;
+ }
+ else
+ {
+ ConsoleLog writeError("[CHAT] The new client wasn't added, because exists allready.");
+ }
+}
+
+// Remove the name and ip of a removed client.
+void PVSChatClient::removeClient(QString name)
+{
+ if(_clients.contains(name))
+ {
+ _clients.removeOne(name);
+ _clientsData.remove(name);
+ }
+ else
+ {
+ ConsoleLog writeError("[CHAT] The new client can not be removed, because doesn't exist.");
+ }
+}
+
+// Delete all infomation about client.
+void PVSChatClient::clearClients()
+{
+ _clients.clear();
+ _clientsData.clear();
+}
diff --git a/src/core/pvsChatClient.h b/src/core/pvsChatClient.h
new file mode 100644
index 0000000..2cb5d9f
--- /dev/null
+++ b/src/core/pvsChatClient.h
@@ -0,0 +1,71 @@
+/*
+# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+*/
+
+// pvsChatClient.h
+
+#ifndef PVSCHATCLIENT_H_
+#define PVSCHATCLIENT_H_
+
+#include <iostream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sstream>
+#include <fstream>
+#include <QStringList>
+#include <QHash>
+#include "src/net/pvsMsg.h"
+#include "src/core/pvsChatMsg.h"
+#include "src/net/pvsServerConnection.h"
+#include "src/util/consoleLogger.h"
+#include "src/util/util.h"
+
+class PVS; // forward declaration.
+
+class PVSChatClient
+{
+
+public:
+
+ PVSChatClient();
+ ~PVSChatClient();
+ void setServerConnection(PVSServerConnection* sc);
+ void setSource(QString name);
+ QString getSource();
+ QStringList getClients();
+ QString getIPFromUsername(QString username);
+ void addClient(QString name, QString ip);
+ void removeClient(QString name);
+ void clearClients();
+ void send(QString tar, QString msg);
+ void receive(PVSMsg recv);
+ bool isRegistered();
+ EventDispatcher<PVSChatMsg>& getChatMsgHandler()
+ {
+ return _chatMessageDispatcher;
+ };
+ EventDispatcher<PVSChatMsg>& getChatCommandHandler()
+ {
+ return _chatCommandDispatcher;
+ };
+
+private:
+
+ QString _source;
+ bool _registered;
+ QStringList _clients;
+ QHash<QString, QString> _clientsData;
+ PVSServerConnection *_chatServerConnection;
+ EventDispatcher<PVSChatMsg> _chatMessageDispatcher;
+ EventDispatcher<PVSChatMsg> _chatCommandDispatcher;
+};
+#endif
diff --git a/src/core/pvsChatMsg.cpp b/src/core/pvsChatMsg.cpp
new file mode 100644
index 0000000..7a2d755
--- /dev/null
+++ b/src/core/pvsChatMsg.cpp
@@ -0,0 +1,108 @@
+/*
+# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+*/
+
+// pvsChatMsg.cpp
+
+#include "src/core/pvsChatMsg.h"
+#include <QStringList>
+
+PVSChatMsg::PVSChatMsg(PVSMsg pvsMsg)
+{
+ QStringList l = pvsMsg.getMessage().split(":");
+
+ if(l[0] == "")
+ {
+ _command = pvsMsg.getIdent();
+ _nickFrom = "unseted";
+ _nickTo = "unseted";
+ _msg = "unseted";
+
+ if(l[2] == "local")
+ {
+ _username = l[1];
+ _ip = pvsMsg.getRemoteIp();
+ }
+ else
+ {
+ _username = l[1];
+ _ip = l[2];
+ }
+ }
+ else
+ {
+ _nickFrom = l[0];
+ _msg = pvsMsg.getMessage().remove(0, l[0].size()+1);
+ _nickTo = pvsMsg.getIdent();
+ _command = "unseted";
+ _username = "unseted";
+ _ip = "unseted";
+ }
+}
+
+PVSChatMsg::~PVSChatMsg(){};
+
+void PVSChatMsg::setNickFrom(QString nick)
+{
+ _nickFrom = nick;
+}
+
+void PVSChatMsg::setNickTo(QString nick)
+{
+ _nickTo = nick;
+}
+
+void PVSChatMsg::setMsg(QString msg)
+{
+ _msg = msg;
+}
+
+QString PVSChatMsg::getNickFrom()
+{
+ return _nickFrom;
+}
+
+QString PVSChatMsg::getNickTo()
+{
+ return _nickTo;
+}
+
+QString PVSChatMsg::getMsg()
+{
+ return _msg;
+}
+
+QString PVSChatMsg::getCommand()
+{
+ return _command;
+}
+
+QString PVSChatMsg::getUsername()
+{
+ return _username;
+}
+
+QString PVSChatMsg::getIp()
+{
+ return _ip;
+}
+
+bool PVSChatMsg::isCommand()
+{
+ if(_command == "unseted")
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
diff --git a/src/core/pvsChatMsg.h b/src/core/pvsChatMsg.h
new file mode 100644
index 0000000..0a9793e
--- /dev/null
+++ b/src/core/pvsChatMsg.h
@@ -0,0 +1,48 @@
+/*
+# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+*/
+
+// pvsChatMsg.h
+
+#include "src/net/pvsMsg.h"
+
+#ifndef PVSCHATMSG_H_
+#define PVSCHATMSG_H_
+
+class PVSChatMsg
+{
+public:
+
+ PVSChatMsg(PVSMsg pvsMsg);
+ ~PVSChatMsg();
+
+ void setNickFrom(QString nick);
+ void setNickTo(QString nick);
+ void setMsg(QString msg);
+ QString getNickFrom();
+ QString getNickTo();
+ QString getMsg();
+ QString getCommand();
+ QString getUsername();
+ QString getIp();
+ bool isCommand();
+
+
+private:
+ QString _msg;
+ QString _nickFrom;
+ QString _nickTo;
+ QString _command;
+ QString _username;
+ QString _ip;
+};
+
+#endif /* PVSCHATMSG_H_ */
diff --git a/src/core/pvsClient.cpp b/src/core/pvsClient.cpp
new file mode 100644
index 0000000..0d08b1d
--- /dev/null
+++ b/src/core/pvsClient.cpp
@@ -0,0 +1,301 @@
+/*
+# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+# -----------------------------------------------------------------------------
+# src/core/pvsConnection.cpp
+# - ...
+# -----------------------------------------------------------------------------
+*/
+
+#include "pvsClient.h"
+#include "pvsServer.h"
+#include "pvsConnectionManager.h"
+#include "src/util/consoleLogger.h"
+#include "src/core/vncConnection.h"
+#include "src/gui/mainWindow.h"
+
+#define CONST_PASS ""
+
+PVSClient::PVSClient(PVSClientConnection *newClient)
+{
+ newClient->setParent(this); // so the object will be deleted when this object dies
+ _pvsClientConnection = newClient;
+ _vncConnection = NULL;
+ _vncRwPasswordReceived = _vncPasswordReceived = _vncAllowed = false;
+ _vncInitMutex = false;
+ _hostString = newClient->getAddress();
+ _hostName = _hostString; // for now
+ //_gotFrame = false;
+ _vncPort = -1;
+ _vncProject = false;
+ _connectionFrame = NULL;
+ _loginName = "unseted";
+}
+
+PVSClient::~PVSClient()
+{
+ if (_vncConnection)
+ {
+ disconnect(_vncConnection, SIGNAL(finished()), this, SLOT(vncFinished()));
+ _vncConnection->clear();
+ delete _vncConnection;
+ _vncConnection = NULL;
+ }
+}
+
+/* TODO: Call this method from an extra thread.
+ * Imo there should be one thread (probably in ConnectionManager) that does this job.
+ * Also, this function should just receive the data etc, but the actual drawing has to happen
+ * in the Qt main thread (the thread the window belongs to)
+ * Right now with GTK it would, but pay attention when switching to Qt
+ * */
+
+void PVSClient::tick()
+{
+ if (_vncInitMutex) return;
+ if (_vncPasswordReceived && _vncAllowed && _vncRequested && _vncConnection == NULL)
+ {
+ vncProbe();
+ }
+}
+
+QString PVSClient::getIp()
+{
+ return _hostString;
+}
+
+QString PVSClient::getDesktopName()
+{
+ if (_vncConnection)
+ {
+ return _vncConnection->getDesktopName();
+ }
+
+ return _hostName;
+}
+
+QString PVSClient::getUserName()
+{
+ return _userName;
+}
+
+QString PVSClient::getLoginName()
+{
+ return _loginName;
+}
+
+//Returns Port
+int PVSClient::getPort(){
+ return _vncPort;
+}
+
+
+bool PVSClient::getVNCAllowed()
+{
+ return _vncAllowed;
+}
+
+void PVSClient::requestVNCConnect()
+{
+ _vncRequested = true;
+ _pvsClientConnection->push_back_send(PVSMsg(PVSCOMMAND, "VNCREQUEST", "YES"));
+}
+
+void PVSClient::setVncPassword(QString password)
+{
+ _vncPassword = password;
+ _vncPasswordReceived = true;
+}
+
+void PVSClient::setVncRwPassword(QString password)
+{
+ _vncRwPassword = password;
+ _vncRwPasswordReceived = true;
+}
+
+QString PVSClient::getPassword()
+{
+ return _vncPassword;
+}
+
+QString PVSClient::getRWPassword()
+{
+ return _vncRwPassword;
+}
+
+void PVSClient::setProject(bool value)
+{
+ _vncProject = value;
+
+}
+
+void PVSClient::setVncPort(int newPort)
+{
+ if (newPort < 1)
+ {
+ ConsoleLog writeNetwork("Client sent invalid vnc-port.");
+ return;
+ }
+ _vncPort = newPort;
+ ConsoleLog writeNetwork(QString("Received new vnc-port: ").append(int2String(newPort)));
+}
+void PVSClient::setAllowed(bool allow)
+{
+ _vncAllowed = allow;
+
+ if (allow)
+ {
+ ConsoleLog writeLine(QString("VNCConnection was granted by the Client."));
+ _vncRequested = true;
+ }
+ else
+ {
+ ConsoleLog writeLine(QString("VNCConnection was denied by the Client."));
+ _vncPort = 0;
+ _vncPasswordReceived = false;
+ }
+
+ if(_vncProject){
+ if(allow){
+ MainWindow::getConnectionWindow()->projectStations(_hostString);
+ }
+ else{
+ _vncProject = false;
+ }
+ }
+}
+
+void PVSClient::shutDownVNC()
+{
+ if (_vncConnection)
+ {
+ disconnect(_vncConnection, SIGNAL(finished()), this, SLOT(vncFinished()));
+ _vncConnection->clear();
+ delete _vncConnection;
+ _vncConnection = NULL;
+ }
+}
+
+void PVSClient::shutDownClient()
+{
+ if (_pvsClientConnection)
+ {
+ _pvsClientConnection->closeConnection();
+ }
+}
+
+void PVSClient::onClientDisconnected()
+{
+ _pvsClientConnection = NULL;
+
+}
+
+bool PVSClient::getLocked()
+{
+ // TODO: Implement!
+ // Previously "_pvsClientConnection->isLocked()" war returned,
+ // but that method always returned "false" and was removed now.
+ // It really didn't make any sense to put that there anyways, it has
+ // to be taken care of in this class.
+ return false;
+}
+
+
+bool PVSClient::sendMessage(PVSMsgType type, QString ident, QString message)
+{
+ if (_pvsClientConnection)
+ {
+ _pvsClientConnection->push_back_send(PVSMsg(type, (char*)ident.toUtf8().data(), message));
+ return true;
+ }
+ return false;
+}
+
+bool PVSClient::sendMessage(PVSMsg message)
+{
+ if (_pvsClientConnection)
+ {
+ _pvsClientConnection->push_back_send(message);
+ return true;
+ }
+ return false;
+}
+
+void PVSClient::vncProbe()
+{
+ _vncInitMutex = true;
+ if (_vncPasswordReceived && _vncAllowed && _vncRequested)
+ {
+#ifndef local_test
+ QString portString;
+ if (_vncPort > 0)
+ {
+ portString = int2String(_vncPort);
+ }
+ else
+ {
+ portString = int2String(5900); //std port
+ ConsoleLog writeError("WARNING: Using default vnc-port 5900");
+ }
+#else
+ QString portString;
+ portString = int2String(5900);
+#endif
+
+ if (_hostString.length() > 0)
+ {
+ char ** args = new char*[1];
+ QString fullstring(_hostString);
+ fullstring.append(":");
+ fullstring.append(portString);
+ args[0] = new char[fullstring.length()+1];
+ std::cout << "[pvsC]connecting to: " << fullstring.toStdString() << std::endl;
+ ConsoleLog writeNetwork(QString("connecting to: ").append(fullstring));
+ //strcpy(args[0], host);
+ strcpy(args[0], fullstring.toUtf8().data());
+ VNCConnectInfo tmpInfo(1, args, _vncPassword);
+
+ VNCConnection* newConnection = new VNCConnection(tmpInfo.getPassword());
+ if (newConnection)
+ {
+ if (newConnection->initClient(&tmpInfo))
+ {
+ _vncProject = false;
+ if (_vncConnection) _vncConnection->setDead();
+ _vncConnection = newConnection;
+ connect(_vncConnection, SIGNAL(finished()), this, SLOT(vncFinished()));
+ //TODO: comment beachten !!!!!
+ //vncAllowed = false; // to make sure we recheck if the allowance wasnt revoked in the meantime to prevent
+ // another connection
+ ConsoleLog writeLine(QString("VNC connection attempt succeeded."));
+ MainWindow::getWindow()->getConnectionWindow()->onVNCAdd(this);
+ }
+ else
+ {
+ delete newConnection;
+ // TODO: post on the log console
+ ConsoleLog writeError(QString("VNC connection attempt failed."));
+ _vncRequested = false; // otherwise loop of death
+ }
+ }
+ }
+ }
+ _vncInitMutex = false;
+}
+
+void PVSClient::vncFinished()
+{
+ disconnect(_vncConnection, SIGNAL(finished()), this, SLOT(vncFinished()));
+ delete _vncConnection;
+ _vncConnection = NULL;
+ _vncPort = 0;
+ _vncPasswordReceived = false;
+}
+
diff --git a/src/core/pvsClient.h b/src/core/pvsClient.h
new file mode 100644
index 0000000..180995a
--- /dev/null
+++ b/src/core/pvsClient.h
@@ -0,0 +1,129 @@
+/**
+ * PVSConnection
+ *
+ * the representation of a connection from a PVSClient to the PVSServer
+ * it holds a pointer the PVSClientConnection we got from a PVS(Listen)Server
+ * and (if present) a pointer to a VNCConnection to the same host as the PVSClientConnection
+ */
+
+
+
+
+#ifndef _PVSCONNECTION_H_
+#define _PVSCONNECTION_H_
+#include "vncConnection.h"
+#include "src/net/pvsClientConnection.h"
+#include "src/gui/frame.h"
+#include <QtCore/QThread>
+
+class PVSServer;
+class VNCConnection;
+class PVSClient;
+class ConnectionFrame;
+class Frame;
+
+class PVSClient : public QObject
+{
+ Q_OBJECT
+ friend class PVSServer;
+ friend class VNCConnection;
+
+public:
+ // C'Tor and D'Tor
+ PVSClient(PVSClientConnection *newClient);
+ ~PVSClient();
+
+ // heartbeat
+ void tick();
+
+
+ //general stuff
+ char* getHost();
+ QString getIp();
+ QString getDesktopName();
+ QString getUserName();
+ QString getLoginName();
+ bool getVNCAllowed();
+ int getPort();
+ void setUsername(QString name)
+ {
+ _userName = name;
+ };
+ void setLoginName(QString ln)
+ {
+ _loginName = ln;
+ };
+
+ // methods for/from vnConnection
+ void requestVNCConnect();
+ void setVncPassword(QString password);
+ void setVncRwPassword(QString password);
+
+ QString getPassword();
+ QString getRWPassword();
+
+ void setProject(bool value);
+ void setAllowed(bool allow);
+ void setVncPort(int newPort);
+ void shutDownVNC();
+ void shutDownClient();
+ /*bool gotFrame(){return _gotFrame;};
+ void setFrame(bool gotFrame){_gotFrame = gotFrame;};*/
+ ConnectionFrame* getConnectionFrame()
+ {
+ return _connectionFrame;
+ };
+ void setConnectionFrame(ConnectionFrame* nFrame)
+ {
+ _connectionFrame = nFrame;
+ };
+ void setFrame(Frame *f)
+ {
+ _vncFrame = f;
+ };
+ Frame* getFrame()
+ {
+ return _vncFrame;
+ };
+ VNCConnection* getVNCConnection()
+ {
+ return _vncConnection;
+ };
+ PVSClientConnection* getPVSClientConnection()
+ {
+ return _pvsClientConnection;
+ };
+
+ // methods for/from PVSClientConnection
+ void onClientDisconnected();
+ bool getLocked();
+ bool sendMessage(PVSMsgType type, QString ident, QString message);
+ bool sendMessage(PVSMsg message);
+
+ void setClientindex(int ind) { _clientIndex = ind; }
+ int getClientindex() { return _clientIndex; }
+ int getConnectionId() { return _pvsClientConnection->getID(); }
+
+private Q_SLOTS:
+ void vncFinished();
+
+private:
+
+ void vncProbe();
+ Frame* _vncFrame;
+ VNCConnection* _vncConnection;
+ PVSClientConnection *_pvsClientConnection;
+ ConnectionFrame* _connectionFrame;
+ int _vncPort;
+ bool _gotFrame;
+ QString _hostString;
+ QString _hostName;
+ QString _userName;
+ QString _loginName;
+ QString _vncPassword;
+ QString _vncRwPassword;
+ int _clientIndex;
+ bool _vncAllowed, _vncRequested, _vncPasswordReceived, _vncRwPasswordReceived, _vncInitMutex, _vncProject;
+};
+
+#endif
diff --git a/src/core/pvsConnectionManager.cpp b/src/core/pvsConnectionManager.cpp
new file mode 100644
index 0000000..8a35ca9
--- /dev/null
+++ b/src/core/pvsConnectionManager.cpp
@@ -0,0 +1,483 @@
+/*
+# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+# -----------------------------------------------------------------------------
+# src/core/pvsConnectionManager.cpp
+# -----------------------------------------------------------------------------
+*/
+
+#include "pvsConnectionManager.h"
+#include "src/gui/mainWindow.h"
+#include <QApplication>
+#include "src/setup.h"
+#include "src/util/CertManager.h"
+#include "src/util/serviceDiscoveryUtil.h"
+
+PVSConnectionManager* PVSConnectionManager::singleCM;
+
+
+PVSConnectionManager* PVSConnectionManager::getManager()
+{
+ if (!singleCM)
+ singleCM = new PVSConnectionManager();
+ return singleCM;
+}
+
+PVSConnectionManager::PVSConnectionManager()
+{
+ _busy = false;
+ _needPassword = false;
+ loadCommands();
+ ConsoleLog writeLine(QString("Connection Manager created."));
+ ConsoleLog writeChat("Log for chat is now running");
+
+ if (!(_pvsServer.startListen(SERVER_PORT_INT)))
+ ConsoleLog writeError(QString("Server listening failed!"));
+ setUpdateRate(500);
+ _sdBroadcaster.setFingerprint(
+ CertManager::getCertificate("manager").digest(QCryptographicHash::Sha1)
+ );
+ _timerId = startTimer(1000);
+}
+
+PVSConnectionManager::~PVSConnectionManager()
+{
+ killTimer(_timerId);
+}
+
+void PVSConnectionManager::setUpdateRate(int newRate)
+{
+ // TODO: Iterate over list of clients and set the updateRate on each vncConnection
+ // Object. The timer does not influence the update rate of the thumbs, thus the code
+ // here was removed.
+}
+
+void PVSConnectionManager::timerEvent(QTimerEvent *event)
+{
+ update();
+}
+
+void PVSConnectionManager::onClientNew(PVSClientConnection* newConnection)
+{
+ PVSClient* tmp = getClientFromConnection(newConnection);
+ if (tmp == NULL)
+ {
+ PVSClient* newCon = new PVSClient(newConnection);
+ _listClients.push_back(newCon);
+ sendEventToClients(QString("addedConnection"), newConnection, "");
+ }
+ else
+ {
+ // already got that one... strange, eh?
+ }
+}
+
+void PVSConnectionManager::onClientRemove(PVSClientConnection* removedConnection)
+{
+ PVSClient* tmp = getClientFromConnection(removedConnection);
+ if (tmp == NULL) return;
+ MainWindow::getWindow()->removeConnection(tmp);
+ removeConnection(tmp);
+ if(tmp->getUserName().length() > 0)
+ {
+ ConsoleLog writeChat(tmp->getUserName()+" has left the chat.");
+ sendEventToClients("removedClient", removedConnection , tmp->getUserName()+":"+tmp->getIp());
+ }
+}
+
+// Inform all chat clients about a new event.
+void PVSConnectionManager::sendEventToClients(QString event, PVSClientConnection* connection, QString clientName)
+{
+ if(event.compare("addedConnection") == 0)
+ {
+ // send the client list to new Connection.
+ for (std::list<PVSClient*>::iterator it = _listClients.begin(); it != _listClients.end(); it++)
+ {
+ QString name = (**it).getUserName();
+ QString ip = (**it).getIp();
+ if (name.length() == 0) continue;
+ connection->push_back_send(PVSMsg(PVSMESSAGE, "clientToAdd", ":" + name + ":" + ip, 0));
+ }
+ }
+ if(event.compare("addedClient") == 0)
+ {
+ // send name to everybody to all connected clients.
+ _pvsServer.sendToAll(PVSMsg(PVSMESSAGE, "clientToAdd", ":" + clientName, 0));
+ connection->push_back_send(PVSMsg(PVSMESSAGE, "assignedName", ":" + clientName, 0));
+ connection->push_back_send(PVSMsg(PVSMESSAGE, "clientToAdd", ":PVSMGR:local", 0));
+ }
+ if(event.compare("removedClient") == 0)
+ {
+ // send name of removed client to connected clients.
+ _pvsServer.sendToAll(PVSMsg(PVSMESSAGE, "clientToRemove", ":"+ clientName, 0));
+ }
+}
+
+PVSClient* PVSConnectionManager::getClientFromConnection(PVSClientConnection* client)
+{
+ if (!_listClients.empty())
+ {
+
+ for (std::list<PVSClient*>::iterator it = _listClients.begin(); it != _listClients.end(); it++)
+ {
+ if ((*it)->getPVSClientConnection())
+ {
+ if ((*it)->getPVSClientConnection() == client)
+ {
+ return (*it);
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+PVSClient* PVSConnectionManager::getClientFromConnectionId(int id)
+{
+ if (_listClients.empty()) return NULL;
+ for (std::list<PVSClient*>::iterator it = _listClients.begin(); it != _listClients.end(); it++)
+ {
+ if ((*it)->getConnectionId() == id) return (*it);
+ }
+ return NULL;
+}
+
+PVSClient* PVSConnectionManager::getClientFromVNCConnection(VNCConnection* client)
+{
+ if (!_listClients.empty())
+ {
+
+ for (std::list<PVSClient*>::iterator it = _listClients.begin(); it != _listClients.end(); it++)
+ {
+ if ((*it)->getVNCConnection())
+ {
+ if ((*it)->getVNCConnection() == client)
+ {
+ return (*it);
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+PVSClient* PVSConnectionManager::getClientFromIp(QString ip)
+{
+ if (!_listClients.empty())
+ {
+ for (std::list<PVSClient*>::iterator it = _listClients.begin(); it != _listClients.end(); it++)
+ {
+ // ok, probably this could be handled better inside the PVSConnection itself
+ // but makeshift for now
+ if ((*it)->getPVSClientConnection())
+ {
+ if ((*it)->getIp() == ip)
+ {
+ return (*it);
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+void PVSConnectionManager::onCommand(PVSMsg command)
+{
+ QString message = command.getMessage();
+ QString ident = command.getIdent();
+ if (ident.compare("VNCSRVRESULT") == 0)
+ {
+ int e = string2Int(message);
+ QString id = int2String(command.getSndID());
+ switch (e)
+ {
+ case 0:
+ ConsoleLog writeLine("[Client: " + id + ", VNCSRV] Server should be running");
+ break;
+ case 1:
+ ConsoleLog writeError("[Client: " + id + ", VNCSRV] Server returned general error");
+ break;
+ case 2:
+ ConsoleLog writeError("[Client: " + id + ", VNCSRV] ~/.pvs/vncpasswd not found");
+ break;
+ case 3:
+ ConsoleLog writeError("[Client: " + id + ", VNCSRV] VNC-Script not found");
+ break;
+ case 127:
+ ConsoleLog writeError("[Client: " + id + ", VNCSRV] command not found (vnc-server installed?)");
+ break;
+ default:
+ ConsoleLog writeError("[Client: " + id + ", VNCSRV] unknown error");
+ break;
+ }
+ }
+}
+void PVSConnectionManager::onChat(PVSMsg chatMsg)
+{
+
+ QString nick_to = chatMsg.getIdent();
+ int sndID = chatMsg.getSndID();
+ PVSClientConnection* clientConnection = NULL;
+ PVSClient* client;
+ QStringList l = chatMsg.getMessage().split(":");
+ QString nick_from = l[0];
+ QString msg = chatMsg.getMessage().remove(0, l[0].size()+1);
+
+ if (nick_to == "@all") // public message.
+ {
+ _pvsServer.sendToAll(chatMsg);
+ MainWindow::getWindow()->receiveChatMsg(nick_from, nick_to, msg);// get Msg on PVSMgr's Chat-GUI.
+ ConsoleLog writeChat(nick_from +" wrote '"+msg+"' in @all-Channel.");
+ }
+ else // private message.
+ {
+ if(nick_from == "PVSMGR") //Msg from Server
+ {
+ MainWindow::getWindow()->receiveChatMsg(nick_from, nick_to, msg); // get Msg on PVSMgr's Chat-GUI.
+ ConsoleLog writeChat(nick_from+" wrote '" + msg + "' to " + nick_to); // write the event to the chat log.
+ }
+ else
+ {
+ clientConnection = _pvsServer.getConnectionFromId(sndID); // become your own message.
+ if (clientConnection)
+ {
+ clientConnection->push_back_send(chatMsg);
+ }
+ else
+ {
+ ConsoleLog writeError("Got Chat Message from unknown ID");
+ }
+ }
+ if(nick_to == "PVSMGR") //Msg to Server
+ {
+ MainWindow::getWindow()->receiveChatMsg(nick_from, nick_to, msg); // get Msg on PVSMgr's Chat-GUI.
+ ConsoleLog writeChat(nick_from+" wrote '" + msg + "' to " + nick_to);// write the event to the chat log.
+ }
+ else
+ {
+ client = getClientFromUsername(nick_to); // private receiver become the message.
+ if (client)
+ {
+ client->sendMessage(chatMsg);
+ ConsoleLog writeChat(nick_from+" wrote '" + msg + "' to " + nick_to);// write the event to the chat log.
+ }
+ else
+ {
+ ConsoleLog writeError("[CHAT] There is no client with username: " + nick_to);
+ }
+ }
+
+ }
+}
+
+PVSClient* PVSConnectionManager::getClientFromUsername(QString name)
+{
+ if (!(_listClients.empty()))
+ {
+ // Check for ping timeout
+ for (std::list<PVSClient*>::iterator it = _listClients.begin(); it!= _listClients.end(); it++)
+ {
+ PVSClient *client = *it;
+ if (client)
+ if (client->getUserName() == name)
+ return client;
+ }
+ }
+ return NULL;
+}
+
+void PVSConnectionManager::onLoginPassword(PVSMsg command)
+{
+ if (!_needPassword) return; // No password required
+ if (_password == command.getMessage()) return; // No password set
+ PVSClient* tmp = getClientFromConnectionId(command.getSndID());
+ tmp->sendMessage(
+ PVSMsg(PVSLOGIN, "FAILED", "Wrong password.")
+ );
+ tmp->shutDownClient();
+}
+
+// Set usernamen and loginname a client.
+void PVSConnectionManager::onLoginUsername(PVSMsg command)
+{
+ QStringList l = command.getMessage().split(",");
+ PVSClient* tmp = getClientFromConnectionId(command.getSndID());
+ if (tmp->getUserName().length() > 0) return;
+ ConsoleLog writeError("(PVSConnectionManager::onUsername) was fired.");
+ if(l[0] == "PVSMGR")
+ {
+ l[0] = "fake_PVSMGR";
+ }
+ int counter = 0;
+ QString uname = l[0];
+ while (getClientFromUsername(uname) != NULL)
+ {
+ uname = l[0].append(QString::number(counter++, 16));
+ }
+ if (tmp)
+ {
+ tmp->setUsername(uname);
+ tmp->setLoginName(l[1]);
+ MainWindow::getWindow()->addConnection(tmp);
+ ConsoleLog writeChat(tmp->getUserName()+" has joined the chat.");
+ sendEventToClients(QString("addedClient"), tmp->getPVSClientConnection(), tmp->getUserName() +":"+ tmp->getIp());
+ }
+ else
+ ConsoleLog writeError("(PVSConnectionManager::onUsername) Couldnt find connection to user-id");
+}
+
+void PVSConnectionManager::onVncPassword(PVSMsg command)
+{
+ PVSClient* tmp = getClientFromConnectionId(command.getSndID());
+
+ if (tmp)
+ {
+ tmp->setVncPassword(command.getMessage());
+ return;
+ }
+ else
+ ConsoleLog writeError("couldnt find matching connection to id!");
+}
+
+void PVSConnectionManager::onVncRwPassword(PVSMsg command)
+{
+ PVSClient* tmp = getClientFromConnectionId(command.getSndID());
+
+ if (tmp)
+ {
+ tmp->setVncRwPassword(command.getMessage());
+ return;
+ }
+ else
+ ConsoleLog writeError("couldnt find matching connection to id!");
+}
+
+void PVSConnectionManager::onVncAllow(PVSMsg command)
+{
+ PVSClient* tmp = getClientFromConnectionId(command.getSndID());
+
+ if (tmp)
+ {
+ if (command.getMessage().compare("YES") == 0)
+ {
+ tmp->setAllowed(true);
+ return;
+ }
+ tmp->setAllowed(false);
+ }
+}
+
+void PVSConnectionManager::onVncPort(PVSMsg command)
+{
+ PVSClient* tmp = getClientFromConnectionId(command.getSndID());
+ if (tmp)
+ {
+ int port = string2Int(command.getMessage());
+ if (port > 0)
+ tmp->setVncPort(port);
+ }
+
+}
+
+void PVSConnectionManager::onVncProjection(PVSMsg command)
+{
+ if (command.getMessage().compare(QString("YES")) == 0)
+ ConsoleLog writeLine("Client is watching.(connected via vnc)");
+ if (command.getMessage().compare(QString("NO")) == 0)
+ ConsoleLog writeLine("Client failed to connect via vnc.");
+}
+
+void PVSConnectionManager::removeConnection(PVSClient* newConnection)
+{
+ if (newConnection != NULL)
+ {
+ for (std::list<PVSClient*>::iterator it = _listClients.begin(); it != _listClients.end(); it++)
+ {
+ if (newConnection == (*it))
+ {
+ // remove it from the list to keep this method from causing trouble when being called more than
+ // once in the process
+ _listClients.remove(newConnection);
+
+ // it is important to tell the GUI that the vnc is gone (or ... will be)
+ // before we really shut it down, since the removal procedure of the
+ // frames shouldnt be messed with from here.
+ MainWindow::getWindow()->onConnectionRemoved(newConnection); // to kill vncConnection
+
+ // now that the gui nows about it and does no longer call the vnc-stuff
+ newConnection->shutDownVNC();
+ // and its gone...
+
+ // clean up on the connection
+ newConnection->shutDownClient(); // just to be sure
+ newConnection->onClientDisconnected();
+
+
+ newConnection->deleteLater();
+ return;
+ }
+ }
+ }
+ else
+ {
+ // well, not our problem obviously
+ }
+}
+
+bool PVSConnectionManager::update()
+{
+ if (_busy) return true; // already ongoing, so scrap that.
+
+ _busy = true; // lock method
+
+ if (!_listClients.empty())
+ {
+ // now update the rest and check if they are alive
+ // otherwise mark dead connections
+ for (std::list<PVSClient*>::iterator it = _listClients.begin(); it != _listClients.end(); it++)
+ {
+ PVSClient* current = (*it);
+ current->tick();
+ }
+ }
+
+ //QApplication::processEvents(QEventLoop::AllEvents, 5);
+
+ _busy = false; // we're done, so unlock
+ return true;
+}
+
+void PVSConnectionManager::loadCommands()
+{
+ _pvsServer.addLoginHandler("USERNAME", this, &PVSConnectionManager::onLoginUsername);
+ _pvsServer.addLoginHandler("PASSWORD", this, &PVSConnectionManager::onLoginPassword);
+ _pvsServer.addCommandHandler("*", this, &PVSConnectionManager::onCommand);
+ _pvsServer.addCommandHandler("VNC", this, &PVSConnectionManager::onVncAllow);
+ _pvsServer.addCommandHandler("PORT", this, &PVSConnectionManager::onVncPort);
+ _pvsServer.addCommandHandler("PASSWORD", this, &PVSConnectionManager::onVncPassword);
+ _pvsServer.addCommandHandler("RWPASSWORD", this, &PVSConnectionManager::onVncRwPassword);
+ _pvsServer.addCommandHandler("PROJECTING", this, &PVSConnectionManager::onVncProjection);
+ _pvsServer.addChatHandler("*", this, &PVSConnectionManager::onChat);
+}
+
+QString PVSConnectionManager::setNeedPassword(bool enabled)
+{
+ _needPassword = enabled;
+ if (enabled && _password.isEmpty())
+ {
+ _password = QString::number(getRandom(1000, 9999), 10);
+ }
+ return _password;
+}
+
+QString PVSConnectionManager::getSessionName()
+{
+ return sha1ToReadable(CertManager::getCertificate("manager").digest(QCryptographicHash::Sha1));
+}
diff --git a/src/core/pvsConnectionManager.h b/src/core/pvsConnectionManager.h
new file mode 100644
index 0000000..5f5fcca
--- /dev/null
+++ b/src/core/pvsConnectionManager.h
@@ -0,0 +1,118 @@
+/**
+ * The PVSConnection Manager is the heart and core of the PVS. He creates, updates, delivers and deletes the connections.
+ *
+ */
+
+
+
+// TODO:
+// make it look good ;-)
+
+
+
+#include <QtGui>
+#include <iostream>
+#include <fstream>
+#include <list>
+#include <src/core/pvsClient.h>
+#include <src/gui/mainWindow.h>
+#include <src/core/pvsServer.h>
+#ifndef _PVSCONNECTIONMANAGER_H_
+#define _PVSCONNECTIONMANAGER_H_
+#ifndef RFBCLIENT_H
+extern "C"
+{
+#include <rfb/rfbclient.h>
+}
+#endif
+
+#define PROFILE
+#include <src/util/timeUtil.h>
+#include <src/util/consoleLogger.h>
+#include "src/net/pvsServiceBroadcast.h"
+
+
+
+class PVSConnectionManager; //forward declaration
+class PVSClient;
+class PVSListenSever;
+class MainWindow;
+
+class PVSConnectionManager : public QObject
+{
+public:
+ // singleton getter
+ static PVSConnectionManager* getManager();
+
+ ~PVSConnectionManager();
+
+ // PVSServer control/get/set methods
+ PVSServer* getServer()
+ {
+ return &_pvsServer;
+ };
+
+ // VNCConnection related static method
+ //static void onFBUpdate(rfbClient* client, int x, int y, int w, int h);
+
+
+ // gui update frequency
+ void setUpdateRate(int newRate);
+
+
+ // PVSConnection control/get/set methods
+ std::list<PVSClient*> getConnections()
+ {
+ return _listClients;
+ };
+ void onClientNew(PVSClientConnection* newConnection); // called by the server when a new client connects
+ void onClientRemove(PVSClientConnection* removedConnection); // called by the server when a new client disconnects (on its own)
+ PVSClient* getClientFromConnection(PVSClientConnection* client);
+ PVSClient* getClientFromConnectionId(int id);
+ PVSClient* getClientFromVNCConnection(VNCConnection* client);
+ PVSClient* getClientFromIp(QString ip); // returns connection with hostname 'host'
+ PVSClient* getClientFromUsername(QString name); // returns connection with username 'name'
+ // these methods are called by the PVSServer which forwards the command/etc handling to the CM
+ void onCommand(PVSMsg command);
+ void onChat(PVSMsg chatMsg);
+ void onVncPassword(PVSMsg command);
+ void onVncRwPassword(PVSMsg command);
+ void onLoginUsername(PVSMsg command);
+ void onLoginPassword(PVSMsg command);
+ void onVncAllow(PVSMsg command);
+ void onVncPort(PVSMsg command);
+ void onVncProjection(PVSMsg command);
+
+ void sendEventToClients(QString event, PVSClientConnection* newConnection, QString newClientName); // informs every connected clients about a new client or a removed client.
+
+ void removeConnection(PVSClient* removedConnection); // removes and deletes the connection !DOES NOT DISCONNECT DIRECTLY!
+ PVSClient* getNewConnection(VNCConnectInfo* newConInfo); // returns a new connection object based on the VNCConnectInfo or NULL
+
+ bool isBusy() { return _busy; }
+
+ QString setNeedPassword(bool enabled);
+ QString getSessionName();
+
+protected:
+ void timerEvent(QTimerEvent *event);
+
+private:
+ // C'Tor
+ PVSConnectionManager(); // private due to singleton pattern
+ // internal control methods
+ bool update(); // does the update and cleaning routines and makes sure the framebuffers in the connection objects are up to date
+ void loadCommands();
+
+ // Member
+ std::list<PVSClient*> _listClients; // list of all verified clients
+ PVSServer _pvsServer; // the server that handles the pvsConnections
+ static PVSConnectionManager* singleCM; // the CM itself
+ bool _busy; // to keep timed calls from starting another update before the old one is thru.
+ PVSServiceBroadcast _sdBroadcaster; ///< Service discovery handling
+
+ QString _password; ///< Password required to connect (can be empty)
+ bool _needPassword;
+ int _timerId;
+};
+
+#endif
diff --git a/src/core/pvsServer.cpp b/src/core/pvsServer.cpp
new file mode 100644
index 0000000..916ad89
--- /dev/null
+++ b/src/core/pvsServer.cpp
@@ -0,0 +1,22 @@
+#include "pvsConnectionManager.h"
+#undef Q_FOREACH
+#include "pvsServer.h"
+
+
+PVSServer::PVSServer(int port)
+ :PVSListenServer(port,0)
+{
+}
+
+
+void PVSServer::onClientConnected(PVSClientConnection* connected)
+{
+ PVSListenServer::onClientConnected(connected);
+ PVSConnectionManager::getManager()->onClientNew(connected);
+}
+void PVSServer::onClientDisconnected(PVSClientConnection* disconnected)
+{
+ PVSConnectionManager::getManager()->onClientRemove(disconnected);
+ PVSListenServer::onClientDisconnected(disconnected);
+}
+
diff --git a/src/core/pvsServer.h b/src/core/pvsServer.h
new file mode 100644
index 0000000..acd9c61
--- /dev/null
+++ b/src/core/pvsServer.h
@@ -0,0 +1,24 @@
+/**
+ * A derivate of PVSListenServer and used by the PVSConnectionManager to handle incoming connections
+ * which then return pointers to their PVSClientConnections to the manager to handle
+ * in and outgoing messsages/commands
+ *
+ */
+
+
+
+#include <src/net/pvsListenServer.h>
+
+#ifndef _PVSSERVER_H_
+#define _PVSSERVER_H_
+
+class PVSServer : public PVSListenServer
+{
+public:
+ PVSServer(int port = 0);
+private:
+ virtual void onClientConnected(PVSClientConnection* connected);
+ virtual void onClientDisconnected(PVSClientConnection* disconnected);
+};
+
+#endif
diff --git a/src/core/vncConnection.cpp b/src/core/vncConnection.cpp
new file mode 100644
index 0000000..1864e77
--- /dev/null
+++ b/src/core/vncConnection.cpp
@@ -0,0 +1,261 @@
+/*
+# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+# -----------------------------------------------------------------------------
+# src/core/vncConnection.cpp
+# -----------------------------------------------------------------------------
+*/
+
+
+#include "vncConnection.h"
+#include <iostream>
+#include <src/core/pvsConnectionManager.h>
+#include <src/core/pvsClient.h>
+#include <src/gui/connectionFrame.h>
+
+
+//***********************************************************************************//
+// VNCConnection //
+//***********************************************************************************//
+
+
+
+VNCConnection::VNCConnection(QString newPass)
+{
+ thread = NULL;
+ pwSet = false;
+ if (newPass != "")
+ {
+ password = newPass;
+ pwSet = true;
+ }
+ else
+ password = "";
+ first = true;
+ view_only = true;
+ locked = false;
+ myFrame = NULL;
+}
+
+VNCConnection::~VNCConnection()
+{
+ setDead();
+}
+
+bool VNCConnection::initClient(VNCConnectInfo* newConInfo)
+{
+ int argc = newConInfo->getCount();
+ char** argv = newConInfo->getArguments();
+
+ if (argc > 0)
+ {
+
+ stringHost = QString(argv[0]);
+
+ /*QString cropHost = colonSplitter(stringHost, true);
+ QString cropPort = colonSplitter(stringHost, false);*/
+ _host = colonSplitter(stringHost, true);
+ _port = colonSplitter(stringHost, false);
+ /*if (!(cropHost.size()))
+ cropHost = stringHost;
+ if (!(cropPort.size()))
+ _port = 5900;
+ password = newConInfo->getPassword();
+ _host = cropHost;
+ thread = new VNCClientThread(_host, 5900, password , 0, 500);*/
+ if (!(_host.size()))
+ _host = stringHost;
+ if (!(_port.size()))
+ _port = QString("5900");
+ thread = new VNCClientThread(_host, string2Int(_port), newConInfo->getPassword(), 0, 500);
+ connect(thread, SIGNAL(finished()), this, SIGNAL(finished()));
+
+ return true;
+ }
+
+ rfbClientLog("init failed\n");
+ emit finished();
+ return false;
+}
+
+/*
+ * disconnect and terminate the current connection and set a new one.
+ */
+void VNCConnection::reInitClientWithQuality(int quality)
+{
+ disconnect(thread, SIGNAL(finished()), this, SIGNAL(finished()));
+ thread->terminate = true;
+ thread = new VNCClientThread(_host, string2Int(_port), password , quality, 500);
+ connect(thread, SIGNAL(finished()), this, SIGNAL(finished()));
+}
+
+bool VNCConnection::isOK()
+{
+ return thread != NULL && thread->isRunning();
+}
+
+bool VNCConnection::viewOnly()
+{
+ return view_only;
+}
+
+void VNCConnection::setDead()
+{
+ if (thread != NULL)
+ {
+ disconnect(thread, SIGNAL(finished()), this, SIGNAL(finished()));
+ if (thread->isRunning())
+ {
+ thread->terminate = true;
+ thread->wait(2000);
+ }
+ delete thread;
+ thread = NULL;
+ }
+}
+
+void VNCConnection::clear()
+{
+ setDead();
+
+ if (myFrame)
+ {
+ myFrame = NULL;
+ }
+}
+
+void VNCConnection::setFrame(ConnectionFrame* newFrame)
+{
+ if (newFrame)
+ {
+ if (myFrame)
+ {
+ // TODO: Tell it that we left?
+ }
+ myFrame = newFrame;
+ if (thread != NULL) myFrame->setToolTip(thread->getDesktopName());
+ myFrame->setRatio(ratio);
+ myFrame->setOversized(overSized);
+ }
+}
+
+ConnectionFrame* VNCConnection::getFrame()
+{
+ return myFrame;
+}
+
+char* VNCConnection::getPassword(rfbClient* myClient)
+{
+ // better off somewhere else?
+
+ QString tmpPassword;
+ QString serverHost(myClient->serverHost);
+ QString cropHost = colonSplitter(serverHost, true);
+ if (!(cropHost.size()))
+ cropHost = serverHost;
+ if (PVSClient* selfConnection = PVSConnectionManager::getManager()->getClientFromIp(cropHost)) // no candidate means false call anyway
+ {
+ tmpPassword = selfConnection->getPassword();
+ }
+ else
+ {
+ tmpPassword = "";
+ ConsoleLog writeError("Couldn't find a matching connection to retrieve a password from!");
+ }
+ if (tmpPassword.length() > 8) // shorten if pw is too long
+ {
+ std::cout << "VNCConnection::getPassword() given password too long, cutting it down to 8 chars!" << std::endl;
+ tmpPassword = tmpPassword.mid(0,8);
+ }
+
+
+ char* pw = new char[9];
+ strcpy(pw, tmpPassword.toUtf8().data());
+ return pw;
+}
+
+QString VNCConnection::getPassword()
+{
+ return password;
+}
+
+bool VNCConnection::getPWSet()
+{
+ return pwSet;
+}
+
+QString VNCConnection::getDesktopName()
+{
+ if (_desktopName.isNull() && thread != NULL && thread->isRunning()) _desktopName = thread->getDesktopName();
+ return _desktopName;
+}
+
+VNCClientThread* VNCConnection::getVNCClientThread()
+{
+ if (thread)
+ return thread;
+ return NULL;
+}
+
+
+
+//***********************************************************************************//
+// VNCConnectInfo //
+//***********************************************************************************//
+
+
+
+VNCConnectInfo::VNCConnectInfo()
+{
+ count = 0;
+ arguments = NULL;
+ password = "";
+ passwordSupplied = false;
+}
+
+VNCConnectInfo::VNCConnectInfo(int newCount, char** newArgs, QString pass)
+{
+ if (pass == "")
+ setArguments(newCount, newArgs);
+ else
+ setArguments(newCount, newArgs, pass);
+}
+
+VNCConnectInfo::~VNCConnectInfo()
+{
+ if (arguments)
+ delete[] arguments;
+}
+
+void VNCConnectInfo::setArguments(int newCount, char** newArgs, QString pass)
+{
+ count = newCount;
+ arguments = newArgs;
+ if (pass != "")
+ {
+ password = pass;
+ passwordSupplied = true;
+ }
+}
+
+int VNCConnectInfo::getCount()
+{
+ return count;
+}
+
+char** VNCConnectInfo::getArguments()
+{
+ return arguments;
+}
+
+QString VNCConnectInfo::getPassword()
+{
+ return password;
+}
diff --git a/src/core/vncConnection.h b/src/core/vncConnection.h
new file mode 100644
index 0000000..6893135
--- /dev/null
+++ b/src/core/vncConnection.h
@@ -0,0 +1,99 @@
+/**
+ *
+ * VNCConnection
+ *
+ * The VNCConnection and the VNCConnectInfo are the Classes containing the information about the vnc-connections.
+ * While the VNCConnectInfo just holds the information about the token and password / parameters given on
+ * create time of a new connection, the connection itself contains the C-Object from the vnc library and is
+ * maintained by the PVSConnectionManger.
+ */
+
+
+#ifndef _VNCCONNECTION_H_
+#define _VNCCONNECTION_H_
+extern "C"
+{
+#include <rfb/rfbclient.h>
+}
+
+#include <QtGui>
+#include "../util/vncClientThread.h"
+#include <src/gui/connectionFrame.h>
+#include <iostream>
+#include <QtCore/QObject>
+
+#define PROFILE
+#include <src/util/timeUtil.h>
+
+
+class VNCConnection; // forward declaration
+class ConnectionFrame;
+class PVSConnectionManager;
+class VNCConnectInfo
+{
+ //Q_OBJECT
+public:
+ VNCConnectInfo(); //Constructor
+ VNCConnectInfo(int newCount, char** newArgs, QString pass = ""); // Constructor with instant information feed
+ ~VNCConnectInfo();
+ void setArguments(int newCount, char** newArgs, QString pass = ""); // (re)feed of information
+ int getCount(); // returns count
+ bool pwSet()
+ {
+ return passwordSupplied;
+ }; // returns wether a password was set or not
+ char ** getArguments(); // returns pointer to an array of char arrays holding the given arguments
+ QString getPassword(); // returns (if given) the password
+
+private:
+ char** arguments;
+ bool passwordSupplied;
+ QString password;
+ int count;
+};
+
+class VNCConnection : public QObject
+{
+ Q_OBJECT
+public:
+ VNCConnection(QString newPass = ""); // Constructor
+ ~VNCConnection();
+ bool initClient(VNCConnectInfo* newConInfo); // initiates the connection based on the information given with the VNCConnectInfo object
+ void reInitClientWithQuality(int quality);
+ bool isOK(); // returns true if not dead, false otherwise
+ bool viewOnly();
+ void setDead(); // marks the connection for removal
+ void clear(); // does internal cleanup
+ void setFrame(ConnectionFrame* newFrame); // sets the given frame as its own
+ ConnectionFrame* getFrame(); // if present, returns the frame
+ static char* getPassword(rfbClient* client); // is called if a rfbclient-object asks for a password and starts the upward chain to ask for a password
+ QString getPassword(); // bad overload, since it returns the stored password (if any was given)
+ QString getHost()
+ {
+ return _host;
+ }
+ bool getPWSet(); // returns true if a password was given, false otherwise
+ //Glib::RefPtr<Gdk::Pixbuf> getBuffer();
+ bool getBusy() { return busy; }
+ QString getDesktopName();
+ VNCClientThread* getVNCClientThread();
+
+Q_SIGNALS:
+ void finished();
+
+private:
+ VNCClientThread *thread;
+ ConnectionFrame* myFrame;
+ QImage img;
+ QString password, stringHost, _host, _port;
+ bool pwSet;
+ bool first;
+ bool view_only;
+ bool overSized;
+ float ratio;
+ bool busy;
+ bool locked;
+ QString _desktopName;
+};
+
+#endif
diff --git a/src/gui/aboutDialog.cpp b/src/gui/aboutDialog.cpp
new file mode 100644
index 0000000..a52f70b
--- /dev/null
+++ b/src/gui/aboutDialog.cpp
@@ -0,0 +1,58 @@
+/*
+ # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of
+ # Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # -----------------------------------------------------------------------------
+ # aboutDialog.cpp
+ # - shows about dialog
+ # -----------------------------------------------------------------------------
+ */
+
+#include "aboutDialog.h"
+#include "src/version.h"
+
+AboutDialog::AboutDialog(QWidget *parent) :
+ QDialog(parent)
+{
+ setupUi(this);
+
+ // set version
+ QString version = tr("Version: ") + (VERSION_STRING);
+ label_version->setText(version);
+
+ // read authors and write to textEdit
+ QString authors = "";
+ QFile f1(":/AUTHORS");
+ if (f1.open(QIODevice::ReadOnly | QIODevice::Text))
+ {
+ QTextStream in(&f1);
+ authors = in.readAll();
+ f1.close();
+ }
+ plainTextEdit_authors->insertPlainText(authors);
+ plainTextEdit_authors->moveCursor(QTextCursor::Start);
+
+ // read translation and write to textEdit
+ QString translation = "";
+ QFile f2(":/TRANSLATION");
+ if (f2.open(QIODevice::ReadOnly | QIODevice::Text))
+ {
+ QTextStream in(&f2);
+ translation = in.readAll();
+ f2.close();
+ }
+ plainTextEdit_translation->insertPlainText(translation);
+ plainTextEdit_translation->moveCursor(QTextCursor::Start);
+
+}
+
+AboutDialog::~AboutDialog()
+{
+}
diff --git a/src/gui/aboutDialog.h b/src/gui/aboutDialog.h
new file mode 100644
index 0000000..5f0489a
--- /dev/null
+++ b/src/gui/aboutDialog.h
@@ -0,0 +1,30 @@
+/*
+ # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of
+ # Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ */
+
+#ifndef ABOUTDIALOG_H_
+#define ABOUTDIALOG_H_
+
+#include <QtGui>
+#include "ui_aboutDialog.h"
+
+class AboutDialog: public QDialog, private Ui::AboutDialogClass
+{
+Q_OBJECT
+
+public:
+ AboutDialog(QWidget *parent = 0);
+ ~AboutDialog();
+
+};
+
+#endif /* ABOUTDIALOG_H_ */
diff --git a/src/gui/clientChatDialog.cpp b/src/gui/clientChatDialog.cpp
new file mode 100644
index 0000000..7c32790
--- /dev/null
+++ b/src/gui/clientChatDialog.cpp
@@ -0,0 +1,298 @@
+/*
+ # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of
+ # Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # -----------------------------------------------------------------------------
+ # clientChatDialog.cpp
+ # - graphical chat interface
+ # -----------------------------------------------------------------------------
+ */
+
+#include "clientChatDialog.h"
+
+ClientChatDialog::ClientChatDialog(QWidget *parent) :
+ QDialog(parent)
+{
+ _trayIcon = NULL;
+ _nickname = "";
+
+ setupUi(this);
+ setAcceptDrops(true);
+ connect(pushButton, SIGNAL(clicked()), this, SLOT(send()));
+
+ // connect to D-Bus and get interface
+ QDBusConnection dbus = QDBusConnection::sessionBus();
+ dbus.registerObject("/chat", this);
+ dbus.registerService("org.openslx.pvsgui");
+ _ifaceDBus = new OrgOpenslxPvsInterface("org.openslx.pvs", "/", dbus, this);
+ connect(_ifaceDBus, SIGNAL(chat_receive(QString, QString, QString)), this,
+ SLOT(receive(QString, QString, QString)));
+
+ // add first tab for public messages
+ tabWidget->clear();
+ QTextEdit *t = new QTextEdit();
+ t->setReadOnly(true);
+ tabWidget->addTab(t, "@all");
+ _hash = new QHash<QString, QTextEdit*> ();
+ _hash->insert(tabWidget->tabText(0), t);
+
+ // already connected?
+ QDBusPendingReply<QString> reply = _ifaceDBus->isConnected();
+ reply.waitForFinished();
+ if (reply.isValid() && reply.value() != "")
+ {
+ // get available nicknames if already connected
+ QDBusPendingReply<QStringList> reply1 = _ifaceDBus->chat_getNicknames();
+ reply1.waitForFinished();
+ QStringList nicknames = reply1.value();
+ if (reply1.isValid() && !nicknames.isEmpty())
+ listWidget->addItems(nicknames);
+
+ connected();
+ }
+ else
+ disconnected();
+
+ // setup menu
+ _menu = new QMenu();
+ _sendFileAction = new QAction(tr("&Send File..."), this);
+ _menu->addAction(_sendFileAction);
+
+ connect(listWidget, SIGNAL(doubleClicked(QModelIndex)), this,
+ SLOT(addTab(QModelIndex)));
+ connect(tabWidget, SIGNAL(tabCloseRequested(int)), this,
+ SLOT(removeTab(int)));
+ connect(tabWidget, SIGNAL(currentChanged(int)), this, SLOT(removeIcon(int)));
+ connect(listWidget, SIGNAL(customContextMenuRequested(QPoint)), this,
+ SLOT(showMenu(QPoint)));
+ connect(_sendFileAction, SIGNAL(triggered()), this,
+ SLOT(sendFile()));
+
+ connect(_ifaceDBus, SIGNAL(chat_client_add(QString)), this,
+ SLOT(addClient(QString)));
+ connect(_ifaceDBus, SIGNAL(chat_client_remove(QString)), this,
+ SLOT(removeClient(QString)));
+ connect(_ifaceDBus, SIGNAL(disconnected()), listWidget,
+ SLOT(clear()));
+ connect(_ifaceDBus, SIGNAL(connected(QString)), this,
+ SLOT(connected()));
+ connect(_ifaceDBus, SIGNAL(disconnected()), this,
+ SLOT(disconnected()));
+
+ lineEdit->setFocus();
+}
+
+ClientChatDialog::~ClientChatDialog()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Public
+
+void ClientChatDialog::setTrayIcon(QSystemTrayIcon *trayIcon)
+{
+ _trayIcon = trayIcon;
+ // FIXME: messageClicked() is always emitted, not only on chat msg
+ //connect(_trayIcon, SIGNAL(messageClicked()), this, SLOT(open()));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Protected
+
+void ClientChatDialog::dragEnterEvent(QDragEnterEvent *event)
+{
+ if (event->mimeData()->hasUrls())
+ event->accept();
+}
+
+void ClientChatDialog::dropEvent(QDropEvent *event)
+{
+ event->accept();
+ sendFile(event->mimeData()->urls().first().toLocalFile());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Private
+
+void ClientChatDialog::send()
+{
+ QString msg = lineEdit->text();
+ if (msg != "")
+ {
+ QString nick_to = tabWidget->tabText(tabWidget->currentIndex());
+ _ifaceDBus->chat_send(nick_to, _nickname, msg);
+ lineEdit->clear();
+ lineEdit->setFocus();
+
+ qDebug("[%s] S %s -> %s : %s", metaObject()->className(),
+ qPrintable(_nickname), qPrintable(nick_to), qPrintable(msg));
+ }
+}
+
+void ClientChatDialog::receive(QString nick_from, QString nick_to, QString msg)
+{
+ qDebug("[%s] R %s <- %s : %s", metaObject()->className(),
+ qPrintable(nick_to), qPrintable(nick_from), qPrintable(msg));
+
+ if (nick_to == tabWidget->tabText(0) || nick_from == _nickname)
+ printMsg(nick_from, msg, getTab(nick_to)); // public message or own msg
+ else
+ printMsg(nick_from, msg, getTab(nick_from)); // private message
+}
+
+void ClientChatDialog::addTab(QModelIndex i)
+{
+ QString text = i.data().toString();
+ if (_hash->contains(text))
+ tabWidget->setCurrentWidget(_hash->value(text));
+ else
+ {
+ QTextEdit *t = new QTextEdit();
+ t->setReadOnly(true);
+ tabWidget->setCurrentIndex(tabWidget->addTab(t, text));
+ _hash->insert(text, t);
+ }
+ lineEdit->setFocus();
+}
+
+void ClientChatDialog::removeTab(int i)
+{
+ if (i != 0)
+ {
+ _hash->remove(tabWidget->tabText(i));
+ tabWidget->removeTab(i);
+ lineEdit->setFocus();
+ }
+}
+
+void ClientChatDialog::addClient(QString nick)
+{
+ listWidget->addItem(nick);
+ printEvent("-> " + nick + tr(" has joined the chat."));
+}
+
+void ClientChatDialog::removeClient(QString nick)
+{
+ delete listWidget->findItems(nick, Qt::MatchExactly).first();
+ printEvent("<- " + nick + tr(" has left the chat."));
+}
+
+void ClientChatDialog::removeIcon(int i)
+{
+ tabWidget->setTabIcon(i, QIcon());
+}
+
+void ClientChatDialog::showMenu(QPoint p)
+{
+ _menu->popup(listWidget->mapToGlobal(p));
+}
+
+void ClientChatDialog::sendFile()
+{
+ ClientFileSendDialog *d = new ClientFileSendDialog(this);
+ d->open(listWidget->currentItem()->text());
+}
+
+void ClientChatDialog::sendFile(QString filename)
+{
+ if (tabWidget->currentIndex() == 0 || filename == "")
+ return;
+
+ // ask user
+ QString nick = tabWidget->tabText(tabWidget->currentIndex());
+ QMessageBox::StandardButton result = QMessageBox::question(0,
+ tr("PVS File Transfer"),
+ tr("Send file '") + filename + tr("' to ") + nick + "?",
+ QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
+
+ if (result != QMessageBox::Ok)
+ return;
+
+ ClientFileSendDialog *d = new ClientFileSendDialog(this);
+ d->open(nick, filename);
+}
+
+void ClientChatDialog::connected()
+{
+ // get current users name from backend
+ QDBusPendingReply<QString> reply = _ifaceDBus->chat_getNickname();
+ reply.waitForFinished();
+ if (reply.isValid())
+ {
+ _nickname = reply.value();
+ pushButton->setEnabled(true);
+ printEvent("!!! " + tr("Connected."));
+ }
+
+ qDebug("[%s] Nickname: '%s'", metaObject()->className(),
+ qPrintable(_nickname));
+}
+
+void ClientChatDialog::disconnected()
+{
+ pushButton->setEnabled(false);
+ printEvent("!!! " + tr("Disconnected."));
+}
+
+QTextEdit* ClientChatDialog::getTab(QString text)
+{
+ if (!_hash->contains(text))
+ {
+ QTextEdit *t = new QTextEdit();
+ t->setReadOnly(true);
+ tabWidget->addTab(t, text);
+ _hash->insert(text, t);
+ }
+ lineEdit->setFocus();
+ return _hash->value(text);
+}
+
+void ClientChatDialog::printMsg(QString nick_from, QString msg, QTextEdit *t)
+{
+ // move cursor at the end
+ t->moveCursor(QTextCursor::End);
+
+ // print time
+ t->setTextColor(QColor(0, 100, 0));
+ t->append("[" + QTime::currentTime().toString("hh:mm") + "] ");
+
+ // print nickname
+ t->setTextColor(QColor(0, 0, 255));
+ t->insertPlainText("<" + nick_from + "> ");
+
+ // print message
+ t->setTextColor(QColor(0, 0, 0));
+ t->insertPlainText(msg);
+
+ // show icon if not current tab
+ if (tabWidget->currentIndex() != tabWidget->indexOf(t))
+ tabWidget->setTabIcon(tabWidget->indexOf(t), QIcon(":chat_msg16.svg"));
+
+ // show balloon message if supported and chat-dialog is not visible
+ if (!isVisible() && _trayIcon && QSystemTrayIcon::supportsMessages())
+ _trayIcon->showMessage(tr("Message from <") + nick_from + ">", msg,
+ QSystemTrayIcon::Information, 20000);
+}
+
+void ClientChatDialog::printEvent(QString msg)
+{
+ QTextEdit *t = _hash->value(tabWidget->tabText(0));
+
+ // move cursor at the end
+ t->moveCursor(QTextCursor::End);
+
+ t->setTextColor(QColor(150, 150, 150));
+
+ // print time
+ t->append("[" + QTime::currentTime().toString("hh:mm") + "] ");
+
+ // print message
+ t->insertPlainText(msg);
+}
diff --git a/src/gui/clientChatDialog.h b/src/gui/clientChatDialog.h
new file mode 100644
index 0000000..42bbb75
--- /dev/null
+++ b/src/gui/clientChatDialog.h
@@ -0,0 +1,63 @@
+/*
+ # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of
+ # Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ */
+
+#ifndef CLIENTCHATDIALOG_H_
+#define CLIENTCHATDIALOG_H_
+
+#include <QtGui>
+#include "pvsinterface.h"
+#include "clientFileSendDialog.h"
+#include "ui_clientChatDialog.h"
+
+class ClientChatDialog: public QDialog, private Ui::ClientChatDialogClass
+{
+Q_OBJECT
+
+public:
+ ClientChatDialog(QWidget *parent = 0);
+ ~ClientChatDialog();
+ void setTrayIcon(QSystemTrayIcon *trayIcon);
+
+private Q_SLOTS:
+ void send();
+ void receive(QString nick_from, QString nick_to, QString msg);
+ void addTab(QModelIndex i);
+ void removeTab(int i);
+ void addClient(QString nick);
+ void removeClient(QString nick);
+ void showMenu(QPoint p);
+ void removeIcon(int i);
+ void sendFile();
+ void sendFile(QString filename);
+ void connected();
+ void disconnected();
+
+protected:
+ void dragEnterEvent(QDragEnterEvent *event);
+ void dropEvent(QDropEvent *event);
+
+private:
+ QTextEdit* getTab(QString text);
+ void printMsg(QString nick_from, QString msg, QTextEdit *t);
+ void printEvent(QString msg);
+
+ OrgOpenslxPvsInterface *_ifaceDBus;
+ QHash<QString, QTextEdit*> *_hash;
+ QSystemTrayIcon *_trayIcon;
+ QString _nickname;
+ QMenu *_menu;
+ QAction *_sendFileAction;
+
+};
+
+#endif /* CLIENTCHATDIALOG_H_ */
diff --git a/src/gui/clientConfigDialog.cpp b/src/gui/clientConfigDialog.cpp
new file mode 100644
index 0000000..76b4f5e
--- /dev/null
+++ b/src/gui/clientConfigDialog.cpp
@@ -0,0 +1,105 @@
+/*
+ # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of
+ # Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # -----------------------------------------------------------------------------
+ # clientConfigDialog.cpp
+ # - graphical interface
+ # - all configuration used by pvs/pvsgui is done here
+ # -----------------------------------------------------------------------------
+ */
+
+#include "clientConfigDialog.h"
+
+ClientConfigDialog::ClientConfigDialog(QWidget *parent) :
+ QDialog(parent)
+{
+ setupUi(this);
+ connect(this, SIGNAL(accepted()), this, SLOT(writeSettings()));
+ connect(radioButtonOtherRO, SIGNAL(clicked()), this,
+ SLOT(checkPermissions()));
+
+}
+
+ClientConfigDialog::~ClientConfigDialog()
+{
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Public
+
+void ClientConfigDialog::open()
+{
+ readSettings();
+ setVisible(true);
+}
+
+void ClientConfigDialog::readSettings()
+{
+ if (_settings.value("Display/location").isNull())
+ comboBox->setCurrentIndex(1);
+ else
+ comboBox->setCurrentIndex(_settings.value("Display/location").toInt());
+
+ if (_settings.value("Permissions/vnc_lecturer").toString() == "rw")
+ radioButtonLecturerRW->setChecked(true);
+ else if (_settings.value("Permissions/vnc_lecturer").toString() == "ro")
+ radioButtonLecturerRO->setChecked(true);
+ else
+ radioButtonLecturerNO->setChecked(true);
+ if (_settings.value("Permissions/vnc_other").toString() == "rw")
+ radioButtonOtherRW->setChecked(true);
+ else if (_settings.value("Permissions/vnc_other").toString() == "ro")
+ radioButtonOtherRO->setChecked(true);
+ else
+ radioButtonOtherNO->setChecked(true);
+ checkBoxAllowChat->setChecked(
+ _settings.value("Permissions/allow_chat").toBool());
+ checkBoxAllowFiletransfer->setChecked(_settings.value(
+ "Permissions/allow_filetransfer").toBool());
+
+ qDebug("[%s] Setting read from: '%s'", metaObject()->className(),
+ qPrintable(_settings.fileName()));
+}
+
+void ClientConfigDialog::writeSettings()
+{
+ _settings.setValue("Display/location", comboBox->currentIndex());
+ if (radioButtonLecturerRW->isChecked())
+ _settings.setValue("Permissions/vnc_lecturer", "rw");
+ else if (radioButtonLecturerRO->isChecked())
+ _settings.setValue("Permissions/vnc_lecturer", "ro");
+ else
+ _settings.setValue("Permissions/vnc_lecturer", "no");
+ if (radioButtonOtherRW->isChecked())
+ _settings.setValue("Permissions/vnc_other", "rw");
+ else if (radioButtonOtherRO->isChecked())
+ _settings.setValue("Permissions/vnc_other", "ro");
+ else
+ _settings.setValue("Permissions/vnc_other", "no");
+ _settings.setValue("Permissions/allow_chat", checkBoxAllowChat->isChecked());
+ _settings.setValue("Permissions/allow_filetransfer",
+ checkBoxAllowFiletransfer->isChecked());
+ _settings.sync();
+ emit configChanged();
+
+ qDebug("[%s] Settings written to: '%s'.", metaObject()->className(),
+ qPrintable(_settings.fileName()));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Private
+
+void ClientConfigDialog::checkPermissions()
+{
+ if (radioButtonLecturerNO->isChecked() && radioButtonOtherRO->isChecked())
+ radioButtonLecturerRO->setChecked(true);
+}
diff --git a/src/gui/clientConfigDialog.h b/src/gui/clientConfigDialog.h
new file mode 100644
index 0000000..706bd8a
--- /dev/null
+++ b/src/gui/clientConfigDialog.h
@@ -0,0 +1,44 @@
+/*
+ # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of
+ # Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ */
+
+#ifndef CLIENTCONFIGDIALOG_H_
+#define CLIENTCONFIGDIALOG_H_
+
+#include <QtGui>
+#include "ui_clientConfigDialog.h"
+
+class ClientConfigDialog: public QDialog, private Ui::ClientConfigDialogClass
+{
+Q_OBJECT
+
+public:
+ ClientConfigDialog(QWidget *parent = 0);
+ ~ClientConfigDialog();
+
+public Q_SLOTS:
+ void open();
+ void readSettings();
+ void writeSettings();
+
+Q_SIGNALS:
+ void configChanged();
+
+private Q_SLOTS:
+ void checkPermissions();
+
+private:
+ QSettings _settings;
+
+};
+
+#endif /* CLIENTCONFIGDIALOG_H_ */
diff --git a/src/gui/clientFileReceiveDialog.cpp b/src/gui/clientFileReceiveDialog.cpp
new file mode 100644
index 0000000..669ca81
--- /dev/null
+++ b/src/gui/clientFileReceiveDialog.cpp
@@ -0,0 +1,181 @@
+/*
+ # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of
+ # Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # -----------------------------------------------------------------------------
+ # clientFileReceiveDialog.cpp
+ # - filechooser and progress dialog
+ # -----------------------------------------------------------------------------
+ */
+
+#include "clientFileReceiveDialog.h"
+
+ClientFileReceiveDialog::ClientFileReceiveDialog(QTcpSocket *socket, QWidget *parent) :
+ QDialog(parent)
+{
+ setupUi(this);
+
+ _file = NULL;
+ _bytesToRead = 0;
+ _socket = socket;
+
+ connect(_socket, SIGNAL(readyRead()), this, SLOT(receiveHeader()));
+ connect(_socket, SIGNAL(disconnected()), this, SLOT(close()));
+ connect(_socket, SIGNAL(error(QAbstractSocket::SocketError)),
+ this, SLOT(error(QAbstractSocket::SocketError)));
+
+ qDebug("[%s] New Connection: %s", metaObject()->className(),
+ qPrintable(_socket->peerAddress().toString()));
+
+ connect(this, SIGNAL(finished(int)), this, SLOT(deleteLater()));
+}
+
+ClientFileReceiveDialog::~ClientFileReceiveDialog()
+{
+ _socket->deleteLater();
+ qDebug("[%s] Deleted!", metaObject()->className());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Private
+
+void ClientFileReceiveDialog::receiveHeader()
+{
+ // parse header
+ QString header = QString::fromUtf8(_socket->readLine());
+ QStringList args = header.split(";");
+ QString nick = args[0];
+ QString filename = args[1];
+ _bytesToRead = args[2].toLongLong();
+ div = 1 + _bytesToRead / 1000000000; // bc. progressBar supports only int
+
+ qDebug("[%s] Received header.", metaObject()->className());
+
+ // ask user
+ QMessageBox::StandardButton result = QMessageBox::question(0,
+ tr("PVS File Transfer"),tr("User '") + nick +
+ tr("' would like to send you a file: ") + filename +
+ " (" + formatSize(_bytesToRead) + ").",
+ QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
+
+ if (result != QMessageBox::Ok)
+ {
+ sendAck(false);
+ return;
+ }
+
+ // open file
+ QString saveAs = QFileDialog::getSaveFileName(this, tr("Open File"),
+ QDir::homePath() + QDir::separator() + filename, "");
+ if (saveAs == "")
+ {
+ sendAck(false);
+ return;
+ }
+ _file = new QFile(saveAs);
+ _file->open(QIODevice::WriteOnly);
+
+ // gui
+ filenameLabel->setText(saveAs);
+ progressBar->setValue(0);
+ progressBar->setMaximum(_bytesToRead/div);
+ labelNick->setText(nick);
+ labelB->setText(formatSize(_bytesToRead));
+ connect(cancelButton, SIGNAL(clicked()), this, SLOT(close()));
+
+ sendAck(true);
+ show();
+}
+
+void ClientFileReceiveDialog::sendAck(bool b)
+{
+ disconnect(_socket, SIGNAL(readyRead()), this, SLOT(receiveHeader()));
+
+ if (b)
+ {
+ QString ack = QString("ok\n");
+ _socket->write(ack.toUtf8());
+ qDebug("[%s] Sending ack...", metaObject()->className());
+ connect(_socket, SIGNAL(readyRead()), this, SLOT(receiveFile()));
+ }
+ else
+ {
+ QString ack = QString("no\n");
+ _socket->write(ack.toUtf8());
+ qDebug("[%s] Sending nack!!!", metaObject()->className());
+ close();
+ }
+}
+
+void ClientFileReceiveDialog::receiveFile()
+{
+ qint64 bytesRead = _file->write(_socket->readAll());
+ _bytesToRead -= bytesRead;
+ progressBar->setValue(progressBar->value() + bytesRead/div);
+ labelA->setText(formatSize(progressBar->value()*div));
+}
+
+void ClientFileReceiveDialog::close()
+{
+ if (_file && _file->isOpen())
+ {
+ _file->flush();
+ _file->close();
+ qDebug("[%s] File closed.", metaObject()->className());
+ }
+
+ if (_socket && _socket->isOpen())
+ {
+ disconnect(_socket, SIGNAL(readyRead()), this, SLOT(receiveHeader()));
+ disconnect(_socket, SIGNAL(readyRead()), this, SLOT(receiveFile()));
+ disconnect(_socket, SIGNAL(disconnected()), this, SLOT(close()));
+ disconnect(_socket, SIGNAL(error(QAbstractSocket::SocketError)),
+ this, SLOT(error(QAbstractSocket::SocketError)));
+ _socket->disconnectFromHost();
+ qDebug("[%s] Connection closed.", metaObject()->className());
+ }
+
+ disconnect(cancelButton, SIGNAL(clicked()), this, SLOT(close()));
+
+ if (_bytesToRead == 0)
+ {
+ accept();
+ QMessageBox::information(0, tr("PVS - File Transfer"),
+ tr("File Transfer complete."));
+ }
+ else
+ {
+ reject();
+ QMessageBox::warning(0, tr("PVS - File Transfer"),
+ tr("File Transfer canceled!"));
+ }
+}
+
+void ClientFileReceiveDialog::error(QAbstractSocket::SocketError error)
+{
+ if (error == QAbstractSocket::RemoteHostClosedError)
+ qDebug("[%s] Socket closed by remote host.", metaObject()->className());
+ else
+ qDebug("[%s] Socket error: %i", metaObject()->className(), error);
+
+ close();
+}
+
+QString ClientFileReceiveDialog::formatSize(qint64 size)
+{
+ if (size >= 1000000000) // GB
+ return QString("%1GB").arg((qreal)size / 1000000000, 0, 'f',1);
+ else if (size >= 1000000) // MB
+ return QString("%1MB").arg((qreal)size / 1000000, 0, 'f',1);
+ else if (size >= 1000) // KB
+ return QString("%1KB").arg((qreal)size / 1000, 0, 'f',1);
+ else // B
+ return QString("%1B").arg((qreal)size, 0, 'f',1);
+}
diff --git a/src/gui/clientFileReceiveDialog.h b/src/gui/clientFileReceiveDialog.h
new file mode 100644
index 0000000..c13d7b7
--- /dev/null
+++ b/src/gui/clientFileReceiveDialog.h
@@ -0,0 +1,47 @@
+/*
+ # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of
+ # Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ */
+
+#ifndef CLIENTFILERECEIVEDIALOG_H_
+#define CLIENTFILERECEIVEDIALOG_H_
+
+#include <QtGui>
+#include <QtNetwork>
+#include "ui_clientFileReceiveDialog.h"
+
+class ClientFileReceiveDialog: public QDialog,
+ private Ui::ClientFileReceiveDialogClass
+{
+Q_OBJECT
+
+public:
+ ClientFileReceiveDialog(QTcpSocket *socket, QWidget *parent = 0);
+ ~ClientFileReceiveDialog();
+
+private Q_SLOTS:
+ void receiveHeader();
+ void receiveFile();
+ void close();
+ void error(QAbstractSocket::SocketError error);
+
+private:
+ void sendAck(bool b);
+ QString formatSize(qint64 size);
+
+ QTcpSocket *_socket;
+ QFile *_file;
+ qint64 _bytesToRead;
+ int div;
+
+};
+
+#endif /* CLIENTFILERECEIVEDIALOG_H_ */
diff --git a/src/gui/clientFileSendDialog.cpp b/src/gui/clientFileSendDialog.cpp
new file mode 100644
index 0000000..ccb44b3
--- /dev/null
+++ b/src/gui/clientFileSendDialog.cpp
@@ -0,0 +1,248 @@
+/*
+ # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of
+ # Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # -----------------------------------------------------------------------------
+ # clientFileSendDialog.cpp
+ # - filechooser and progress dialog
+ # -----------------------------------------------------------------------------
+ */
+
+#include "clientFileSendDialog.h"
+
+ClientFileSendDialog::ClientFileSendDialog(QWidget *parent) :
+ QDialog(parent)
+{
+ setupUi(this);
+
+ _file = NULL;
+ _socket = NULL;
+ _clientNicklistDialog = new ClientNicklistDialog(this);
+
+ // connect to D-Bus and get interface
+ QDBusConnection dbus = QDBusConnection::sessionBus();
+ dbus.registerObject("/filesend", this);
+ dbus.registerService("org.openslx.pvsgui");
+ _ifaceDBus = new OrgOpenslxPvsInterface("org.openslx.pvs", "/", dbus, this);
+
+ // get current users name from backend
+ QDBusPendingReply<QString> reply = _ifaceDBus->chat_getNickname();
+ reply.waitForFinished();
+ if (reply.isValid())
+ _nickname = reply.value();
+ else
+ _nickname = "unknown";
+
+ connect(this, SIGNAL(finished(int)), this, SLOT(deleteLater()));
+}
+
+ClientFileSendDialog::~ClientFileSendDialog()
+{
+ qDebug("[%s] Deleted!", metaObject()->className());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Public
+
+void ClientFileSendDialog::open()
+{
+ // get nick of remote user
+ int result = _clientNicklistDialog->exec();
+ if (result == 0) // User canceled
+ {
+ reject();
+ return;
+ }
+ open(_clientNicklistDialog->getNick());
+}
+
+void ClientFileSendDialog::open(QString nick)
+{
+ QString filename = QFileDialog::getOpenFileName(this, tr("Open File"),
+ QDir::homePath(), "");
+ if (filename == "")
+ {
+ reject();
+ return;
+ }
+ open(nick, filename);
+}
+
+void ClientFileSendDialog::open(QString nick, QString filename)
+{
+ // open file
+ _file = new QFile(filename);
+ _file->open(QIODevice::ReadOnly);
+ _bytesToWrite = _file->size();
+ div = 1 + _bytesToWrite / 1000000000; // bc. progressBar supports only int
+
+ // get host from backend
+ QString host = "";
+ QDBusPendingReply<QString> reply = _ifaceDBus->getIpByNick(nick);
+ reply.waitForFinished();
+ if (reply.isValid())
+ host = reply.value();
+ else // DBus Error, hostname
+ qDebug("[%s] D-Bus ERROR, no hostname available!", metaObject()->className());
+
+ // gui
+ filenameLabel->setText(filename);
+ progressBar->setValue(0);
+ progressBar->setMaximum(_bytesToWrite/div);
+ labelNick->setText(nick);
+ labelB->setText(formatSize(_bytesToWrite));
+ connect(cancelButton, SIGNAL(clicked()), this, SLOT(close()));
+
+ // open socket
+ _socket = new QTcpSocket();
+ _socket->connectToHost(host, 29481);
+ qDebug("[%s] Remote host: %s", metaObject()->className(), qPrintable(host));
+
+ connect(_socket, SIGNAL(connected()), this, SLOT(sendHeader()));
+ connect(_socket, SIGNAL(disconnected()), this, SLOT(close()));
+ connect(_socket, SIGNAL(error(QAbstractSocket::SocketError)),
+ this, SLOT(error(QAbstractSocket::SocketError)));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Private
+
+void ClientFileSendDialog::sendHeader()
+{
+ QFileInfo info(_file->fileName());
+ QString size = QString::number(_bytesToWrite);
+ QString header = _nickname + ";" + info.fileName() + ";" + size + "\n";
+ _socket->write(header.toLocal8Bit());
+ connect(_socket, SIGNAL(readyRead()), this, SLOT(receiveAck()));
+ qDebug("[%s] Sending header...", metaObject()->className());
+}
+
+void ClientFileSendDialog::receiveAck()
+{
+ QString ack = QString::fromUtf8(_socket->readLine());
+ if (ack != "ok\n")
+ {
+ qDebug("[%s] Received nack!", metaObject()->className());
+ close();
+ return;
+ }
+ qDebug("[%s] Received ack.", metaObject()->className());
+
+ disconnect(_socket, SIGNAL(readyRead()), this, SLOT(receiveAck()));
+ connect(_socket, SIGNAL(bytesWritten(qint64)), this, SLOT(sendFile()));
+ show();
+ qDebug("[%s] Sending file...", metaObject()->className());
+ sendFile();
+}
+
+void ClientFileSendDialog::sendFile()
+{
+ if (_bytesToWrite == 0)
+ {
+ qDebug("[%s] Transfer completed.", metaObject()->className());
+ close(); // finished
+ }
+ else
+ {
+ qint64 bytesWritten = _socket->write(_file->read(1024)); // data left
+ _bytesToWrite -= bytesWritten;
+ progressBar->setValue(progressBar->value() + bytesWritten/div);
+ labelA->setText(formatSize(progressBar->value()*div));
+ }
+}
+
+void ClientFileSendDialog::close()
+{
+ if (_file && _file->isOpen())
+ {
+ _file->close();
+ qDebug("[%s] File closed.", metaObject()->className());
+ }
+
+ if (_socket && _socket->isOpen())
+ {
+ disconnect(_socket, SIGNAL(readyRead()), this, SLOT(receiveAck()));
+ disconnect(_socket, SIGNAL(bytesWritten(qint64)), this, SLOT(sendFile()));
+ disconnect(_socket, SIGNAL(disconnected()), this, SLOT(close()));
+ disconnect(_socket, SIGNAL(connected()), this, SLOT(sendHeader()));
+ disconnect(_socket, SIGNAL(error(QAbstractSocket::SocketError)),
+ this, SLOT(error(QAbstractSocket::SocketError)));
+ _socket->disconnectFromHost();
+ qDebug("[%s] Connection closed.", metaObject()->className());
+ }
+
+ disconnect(cancelButton, SIGNAL(clicked()), this, SLOT(close()));
+
+ if (_bytesToWrite == 0)
+ {
+ accept();
+ QMessageBox::information(0, tr("PVS - File Transfer"),
+ tr("File Transfer complete."));
+ }
+ else
+ {
+ reject();
+ QMessageBox::warning(0, tr("PVS - File Transfer"),
+ tr("File Transfer canceled!"));
+ }
+}
+
+void ClientFileSendDialog::error(QAbstractSocket::SocketError error)
+{
+ qDebug("[%s] Socket error: %i", metaObject()->className(), error);
+ close();
+}
+
+QString ClientFileSendDialog::formatSize(qint64 size)
+{
+ if (size >= 1000000000) // GB
+ return QString("%1GB").arg((qreal)size / 1000000000, 0, 'f',1);
+ else if (size >= 1000000) // MB
+ return QString("%1MB").arg((qreal)size / 1000000, 0, 'f',1);
+ else if (size >= 1000) // KB
+ return QString("%1KB").arg((qreal)size / 1000, 0, 'f',1);
+ else // B
+ return QString("%1B").arg((qreal)size, 0, 'f',1);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+ClientNicklistDialog::ClientNicklistDialog(QWidget *parent) :
+ QDialog(parent)
+{
+ setupUi(this);
+
+ // connect to D-Bus and get interface
+ QDBusConnection dbus = QDBusConnection::sessionBus();
+ dbus.registerObject("/nicklist", this);
+ dbus.registerService("org.openslx.pvsgui");
+ _ifaceDBus = new OrgOpenslxPvsInterface("org.openslx.pvs", "/", dbus, this);
+
+ // get available nicknames
+ QDBusPendingReply<QStringList> reply = _ifaceDBus->chat_getNicknames();
+ reply.waitForFinished();
+ QStringList nicknames = reply.value();
+ if (!reply.isValid() || nicknames.isEmpty()) // DBus Error, nicknames
+ qDebug("[%s] D-Bus ERROR, no nicknames available!", metaObject()->className());
+
+ listWidget->addItems(nicknames);
+ listWidget->setCurrentRow(0);
+}
+
+ClientNicklistDialog::~ClientNicklistDialog()
+{
+
+}
+
+QString ClientNicklistDialog::getNick()
+{
+ return listWidget->currentItem()->text();
+}
diff --git a/src/gui/clientFileSendDialog.h b/src/gui/clientFileSendDialog.h
new file mode 100644
index 0000000..d8afc3a
--- /dev/null
+++ b/src/gui/clientFileSendDialog.h
@@ -0,0 +1,76 @@
+/*
+ # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of
+ # Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ */
+
+#ifndef CLIENTFILESENDDIALOG_H_
+#define CLIENTFILESENDDIALOG_H_
+
+#include <QtGui>
+#include <QtNetwork>
+#include "pvsinterface.h"
+#include "ui_clientFileSendDialog.h"
+#include "ui_clientNicklistDialog.h"
+
+class ClientNicklistDialog: public QDialog,
+ private Ui::ClientNicklistDialogClass
+{
+Q_OBJECT
+
+public:
+ ClientNicklistDialog(QWidget *parent = 0);
+ ~ClientNicklistDialog();
+
+ QString getNick();
+
+private:
+ OrgOpenslxPvsInterface *_ifaceDBus;
+
+};
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+class ClientFileSendDialog: public QDialog,
+ private Ui::ClientFileSendDialogClass
+{
+Q_OBJECT
+
+public:
+ ClientFileSendDialog(QWidget *parent = 0);
+ ~ClientFileSendDialog();
+
+ void open();
+ void open(QString nick);
+ void open(QString nick, QString filename);
+
+private Q_SLOTS:
+ void sendHeader();
+ void receiveAck();
+ void sendFile();
+ void close();
+ void error(QAbstractSocket::SocketError error);
+
+private:
+ QString formatSize(qint64 size);
+
+ QTcpSocket *_socket;
+ QFile *_file;
+ qint64 _bytesToWrite;
+ int div;
+
+ ClientNicklistDialog *_clientNicklistDialog;
+ OrgOpenslxPvsInterface *_ifaceDBus;
+ QString _nickname;
+
+};
+
+#endif /* CLIENTFILESENDDIALOG_H_ */
diff --git a/src/gui/clientInfoDialog.cpp b/src/gui/clientInfoDialog.cpp
new file mode 100644
index 0000000..02a6fd8
--- /dev/null
+++ b/src/gui/clientInfoDialog.cpp
@@ -0,0 +1,60 @@
+/*
+ # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of
+ # Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # -----------------------------------------------------------------------------
+ # clientInfoDialog.cpp
+ # - shows big info dialog (connected host and passwd)
+ # -----------------------------------------------------------------------------
+ */
+
+#include "clientInfoDialog.h"
+
+ClientInfoDialog::ClientInfoDialog(QWidget *parent) :
+ QDialog(parent)
+{
+ setupUi(this);
+}
+
+ClientInfoDialog::~ClientInfoDialog()
+{
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Public
+
+void ClientInfoDialog::setHost(QString host)
+{
+ hostLabel->setText("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" "
+ "\"http://www.w3.org/TR/REC-html40/strict.dtd\"><html>"
+ "<head><meta name=\"qrichtext\" content=\"1\" />"
+ "<style type=\"text/css\">p, li { white-space: pre-wrap; }</style>"
+ "</head><body style=\" font-family:'DejaVu Sans'; font-size:9pt; "
+ "font-weight:400; font-style:normal;\"><p style=\" margin-top:0px; "
+ "margin-bottom:0px; margin-left:0px; margin-right:0px; "
+ "-qt-block-indent:0; text-indent:0px;\"><span style=\" "
+ "font-size:72pt; font-weight:600; color:#0000ff;\">"
+ + host + "</span></p></body></html>");
+}
+
+void ClientInfoDialog::setPasswd(QString passwd)
+{
+ passwdLabel->setText("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" "
+ "\"http://www.w3.org/TR/REC-html40/strict.dtd\"><html>"
+ "<head><meta name=\"qrichtext\" content=\"1\" />"
+ "<style type=\"text/css\">p, li { white-space: pre-wrap; }</style>"
+ "</head><body style=\" font-family:'DejaVu Sans'; font-size:9pt; "
+ "font-weight:400; font-style:normal;\"><p style=\" margin-top:0px; "
+ "margin-bottom:0px; margin-left:0px; margin-right:0px; "
+ "-qt-block-indent:0; text-indent:0px;\"><span style=\" "
+ "font-size:48pt; font-weight:600; color:#ff0000;\">"
+ + passwd + "</span></p></body></html>");
+}
diff --git a/src/gui/clientInfoDialog.h b/src/gui/clientInfoDialog.h
new file mode 100644
index 0000000..770b5b7
--- /dev/null
+++ b/src/gui/clientInfoDialog.h
@@ -0,0 +1,32 @@
+/*
+ # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of
+ # Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ */
+
+#ifndef CLIENTINFODIALOG_H_
+#define CLIENTINFODIALOG_H_
+
+#include <QtGui>
+#include "ui_clientInfoDialog.h"
+
+class ClientInfoDialog: public QDialog, private Ui::InfoDialogClass
+{
+Q_OBJECT
+
+public:
+ ClientInfoDialog(QWidget *parent = 0);
+ ~ClientInfoDialog();
+
+ void setHost(QString host);
+ void setPasswd(QString passwd);
+};
+
+#endif /* CLIENTINFODIALOG_H_ */
diff --git a/src/gui/clientVNCViewer.cpp b/src/gui/clientVNCViewer.cpp
new file mode 100644
index 0000000..d6a218b
--- /dev/null
+++ b/src/gui/clientVNCViewer.cpp
@@ -0,0 +1,273 @@
+/*
+ # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of
+ # Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # -----------------------------------------------------------------------------
+ # clientVNCViewer.cpp
+ # - connetct to vnc server and show remote screen (window/full)
+ # -----------------------------------------------------------------------------
+ */
+
+#include "clientVNCViewer.h"
+
+ClientVNCViewer::ClientVNCViewer(QWidget *parent) :
+ QDialog(parent), _thread(0), _viewOnly(true), _buttonMask(0)
+{
+ // connect to D-Bus and get interface
+ QDBusConnection dbus = QDBusConnection::sessionBus();
+ dbus.registerObject("/vnc", this);
+ dbus.registerService("org.openslx.pvsgui");
+ _ifaceDBus = new OrgOpenslxPvsInterface("org.openslx.pvs", "/", dbus, this);
+ connect(_ifaceDBus, SIGNAL(project(QString, int, QString, bool, bool, int)),
+ this, SLOT(open(QString, int, QString, bool, bool, int)));
+ connect(_ifaceDBus, SIGNAL(unproject()), this, SLOT(close()));
+}
+
+ClientVNCViewer::~ClientVNCViewer()
+{
+ close();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Public
+
+void ClientVNCViewer::open(QString host, int port, QString passwd, bool fs,
+ bool mode, int quality)
+{
+ // start thread for vnc-updates
+ _thread = new VNCClientThread(host, port, passwd, quality);
+ _thread->start();
+ //_rfbclient = _thread->getRfbClient();
+ //installEventFilter(this);
+ setMouseTracking(true); // get mouse events even when there is no mousebutton pressed
+ setFocusPolicy(Qt::WheelFocus); //needed?!?
+
+ setAttribute(Qt::WA_OpaquePaintEvent);
+
+ // smooth transformation?
+ if (mode)
+ _mode = Qt::SmoothTransformation;
+ else
+ _mode = Qt::FastTransformation;
+
+ // fullscreen?
+ if (fs)
+ {
+ setWindowFlags(Qt::WindowStaysOnTopHint);
+ showFullScreen();
+ activateWindow();
+ raise();
+ }
+ else
+ showNormal();
+
+ connect(this, SIGNAL(rejected()), this, SLOT(close()));
+ connect(_thread, SIGNAL(imageUpdated(int,int,int,int)), this,
+ SLOT(updateImage(int,int,int,int)), Qt::BlockingQueuedConnection);
+}
+
+void ClientVNCViewer::close()
+{
+ setVisible(false);
+ if (_thread)
+ {
+ disconnect(_thread, SIGNAL(imageUpdated(int,int,int,int)), this,
+ SLOT(updateImage(int,int,int,int)));
+
+ _thread->terminate = true;
+ _thread->wait(1000);
+ delete _thread;
+ _thread = NULL;
+ }
+ disconnect(this, SIGNAL(rejected()), this, SLOT(close()));
+}
+
+void ClientVNCViewer::updateImage(int x, int y, int w, int h)
+{
+ if (_thread->getSize() != size()) // scaling needed?
+ {
+ // grow the update rectangle to avoid artifacts
+ x -= 1;
+ y -= 1;
+ w += 2;
+ h += 2;
+
+ _img = _thread->getImage().copy(x, y, w, h);
+
+ qreal sx = qreal(width()) / qreal(_thread->getSize().width());
+ qreal sy = qreal(height()) / qreal(_thread->getSize().height());
+
+ x = qRound(qreal(x) * sx);
+ y = qRound(qreal(y) * sy);
+ w = qRound(qreal(w) * sx);
+ h = qRound(qreal(h) * sy);
+ }
+ else
+ {
+ _img = _thread->getImage().copy(x, y, w, h);
+ }
+
+ repaint(x, y, w, h);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Protected
+
+void ClientVNCViewer::paintEvent(QPaintEvent *event)
+{
+ if (_img.isNull())
+ return;
+
+ QPainter painter(this);
+ QRect r = event->rect();
+
+ if (r == rect())
+ _img = _thread->getImage(); // redraw complete image (e.g. on resize)
+
+ if (_thread->getSize() == size())
+ {
+ painter.drawImage(r.topLeft(), _img); // don't scale
+ }
+ else
+ {
+ QImage i = _img.scaled(r.size(), Qt::IgnoreAspectRatio, _mode);
+ painter.drawImage(r.topLeft(), i);
+ }
+ event->accept();
+}
+//returns true if event was processed
+/*bool ClientVNCViewer::event(QEvent *event)
+{
+ switch (event->type()) {
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+
+ keyEventHandler(static_cast<QKeyEvent*>(event));
+ return true;
+ break;
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseMove:
+ mouseEventHandler(static_cast<QMouseEvent*>(event));
+ return true;
+ break;
+ case QEvent::Wheel:
+ wheelEventHandler(static_cast<QWheelEvent*>(event));
+ return true;
+ break;
+ default:
+ return false;
+ }
+}*/
+
+//handles mouseevents
+void ClientVNCViewer::mouseEventHandler(QMouseEvent *e)
+{
+ if (e->type() != QEvent::MouseMove) {
+ if ((e->type() == QEvent::MouseButtonPress) ||
+ (e->type() == QEvent::MouseButtonDblClick)) {
+ if (e->button() & Qt::LeftButton)
+ _buttonMask |= 0x01;
+ if (e->button() & Qt::MidButton)
+ _buttonMask |= 0x02;
+ if (e->button() & Qt::RightButton)
+ _buttonMask |= 0x04;
+ } else if (e->type() == QEvent::MouseButtonRelease) {
+ if (e->button() & Qt::LeftButton)
+ _buttonMask &= 0xfe;
+ if (e->button() & Qt::MidButton)
+ _buttonMask &= 0xfd;
+ if (e->button() & Qt::RightButton)
+ _buttonMask &= 0xfb;
+ }
+ }
+ qreal sx = qreal(width()) / qreal(_thread->getSize().width());
+ qreal sy = qreal(height()) / qreal(_thread->getSize().height());
+ _thread->mouseEvent(qRound(e->x() / sx), qRound(e->y() / sy), _buttonMask);
+}
+
+//handles mousewheel
+void ClientVNCViewer::wheelEventHandler(QWheelEvent *event)
+{
+ int eb = 0;
+ if (event->delta() < 0)
+ eb |= 0x10;
+ else
+ eb |= 0x8;
+
+ qreal sx = qreal(width()) / qreal(_thread->getSize().width());
+ qreal sy = qreal(height()) / qreal(_thread->getSize().height());
+ const int x = qRound(event->x() / sx);
+ const int y = qRound(event->y() / sy);
+
+ _thread->mouseEvent(x, y, eb | _buttonMask);
+ _thread->mouseEvent(x, y, _buttonMask);
+}
+
+//Handles keypress
+void ClientVNCViewer::keyEventHandler(QKeyEvent *e)
+{
+ rfbKeySym k = e->nativeVirtualKey();
+
+ // do not handle Key_Backtab separately because the Shift-modifier
+ // is already enabled
+ if (e->key() == Qt::Key_Backtab) {
+ k = XK_Tab;
+ }
+
+ const bool pressed = (e->type() == QEvent::KeyPress);
+
+ // handle modifiers
+ if (k == XK_Shift_L || k == XK_Control_L || k == XK_Meta_L || k == XK_Alt_L) {
+ if (pressed) {
+ _modkeys[k] = true;
+ } else if (_modkeys.contains(k)) {
+ _modkeys.remove(k);
+ } else {
+ unpressModifiers();
+ }
+ }
+
+ if (k) {
+ _thread->keyEvent(k, pressed);
+ }
+}
+
+//removes modifier keys which have been pressed
+void ClientVNCViewer::unpressModifiers()
+{
+ const QList<unsigned int> keys = _modkeys.keys();
+ QList<unsigned int>::const_iterator it = keys.constBegin();
+ while (it != keys.end()) {
+ _thread->keyEvent(*it, false);
+ it++;
+ }
+ _modkeys.clear();
+}
+
+//(QT Function) Filters events, if _viewOnly is set, true is returned and the event is ignored
+//TODO use this function when implementing viewonly switch
+bool ClientVNCViewer::eventFilter(QObject *obj, QEvent *event)
+{
+ if (_viewOnly) {
+ if (event->type() == QEvent::KeyPress ||
+ event->type() == QEvent::KeyRelease ||
+ event->type() == QEvent::MouseButtonDblClick ||
+ event->type() == QEvent::MouseButtonPress ||
+ event->type() == QEvent::MouseButtonRelease ||
+ event->type() == QEvent::Wheel ||
+ event->type() == QEvent::MouseMove)
+ return true;
+ }
+
+ return false;
+ //return RemoteView::eventFilter(obj, event);
+}
diff --git a/src/gui/clientVNCViewer.h b/src/gui/clientVNCViewer.h
new file mode 100644
index 0000000..6ff9c33
--- /dev/null
+++ b/src/gui/clientVNCViewer.h
@@ -0,0 +1,67 @@
+/*
+ # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of
+ # Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ */
+
+#ifndef CLIENTVNCVIEWER_H_
+#define CLIENTVNCVIEWER_H_
+
+#include <QtGui>
+#include <QMouseEvent>
+#include "pvsinterface.h"
+#include "../util/vncClientThread.h"
+
+// Definition of key modifier mask constants
+#define KMOD_Alt_R 0x01
+#define KMOD_Alt_L 0x02
+#define KMOD_Meta_L 0x04
+#define KMOD_Control_L 0x08
+#define KMOD_Shift_L 0x10
+
+class ClientVNCViewer: public QDialog
+{
+Q_OBJECT
+
+public:
+ ClientVNCViewer(QWidget *parent = 0);
+ virtual ~ClientVNCViewer();
+
+public Q_SLOTS:
+ void open(QString host, int port, QString passwd, bool fullscreen = false,
+ bool smoothTransformation = false, int quality = 0);
+ void close();
+ void updateImage(int x, int y, int w, int h);
+
+protected:
+ void paintEvent(QPaintEvent *event);
+ //bool event(QEvent *event);
+ //bool eventFilter(QObject *obj, QEvent *event);
+
+private:
+ VNCClientThread *_thread;
+ //rfbClient *_rfbclient;
+ QImage _img;
+ bool _viewOnly;
+ int _buttonMask;
+ QMap<unsigned int, bool> _modkeys;
+ bool eventFilter(QObject *obj, QEvent *event);
+ void keyEventHandler(QKeyEvent *e);
+ void unpressModifiers();
+ void wheelEventHandler(QWheelEvent *event);
+ void mouseEventHandler(QMouseEvent *event);
+
+
+ Qt::TransformationMode _mode;
+
+ OrgOpenslxPvsInterface *_ifaceDBus;
+};
+
+#endif /* CLIENTVNCVIEWER_H_ */
diff --git a/src/gui/connectionDialog.cpp b/src/gui/connectionDialog.cpp
new file mode 100644
index 0000000..8c5b743
--- /dev/null
+++ b/src/gui/connectionDialog.cpp
@@ -0,0 +1,216 @@
+#include "connectionDialog.h"
+
+ConnectionDialog::ConnectionDialog(MainWindow* newParent, const Glib::ustring& title)
+ : buttonOK("OK"),
+ buttonCancel("Cancel")
+
+{
+ set_default_size(300, 100);
+ if (newParent)
+ myParent = newParent;
+ else
+ ; // handle errors
+
+ set_title(title);
+ buttonOK.signal_clicked().connect(sigc::mem_fun(*this, &ConnectionDialog::on_button_ok_click));
+ buttonCancel.signal_clicked().connect(sigc::mem_fun(*this, &ConnectionDialog::on_button_cancel_click));
+
+
+ windowBox.pack_start(contentBox, Gtk::PACK_SHRINK);
+ windowBox.pack_start(buttonBox, Gtk::PACK_SHRINK);
+ buttonBox.pack_end(buttonOK, Gtk::PACK_SHRINK);
+ buttonBox.pack_end(buttonCancel, Gtk::PACK_SHRINK);
+
+
+ add(windowBox);
+ show_all_children();
+}
+
+ConnectionDialog::~ConnectionDialog()
+{}
+
+void ConnectionDialog::on_button_ok_click()
+{
+ hide();
+}
+
+void ConnectionDialog::on_button_cancel_click()
+{
+ hide();
+}
+
+
+
+PasswordDialog::PasswordDialog(MainWindow* newParent, const Glib::ustring& title, QString* newTargetPW)
+ : ConnectionDialog(newParent, title),
+ frameIP(*newTargetPW),
+ targetPW(newTargetPW)
+
+{
+ *newTargetPW = "";
+ entryPW.signal_activate().connect(sigc::mem_fun(*this, &PasswordDialog::on_enter_password));
+
+ frameIP.add(entryPW);
+ contentBox.add(frameIP);
+
+ show_all_children();
+
+}
+
+PasswordDialog::~PasswordDialog()
+{}
+
+void PasswordDialog::on_button_ok_click()
+{
+ if (password != "") // there was a password set by pressing enter in the pw-entry
+ {
+ *targetPW = password;
+ ConnectionDialog::on_button_ok_click();
+ }
+ else // it was just typed or not supplied
+ {
+ *targetPW = entryPW.get_text();
+ if (*targetPW != "")
+ ConnectionDialog::on_button_ok_click();
+
+ }
+
+}
+
+void PasswordDialog::on_button_cancel_click()
+{
+ *targetPW = "";
+ ConnectionDialog::on_button_cancel_click();
+}
+
+void PasswordDialog::on_enter_password()
+{
+ password = entryPW.get_text();
+ if (password != "")
+ on_button_ok_click();
+}
+
+NewConDialog::NewConDialog(MainWindow* newParent, const Glib::ustring& title)
+ : ConnectionDialog(newParent, title),
+ frameIP("Host"),
+ framePW("Password"),
+ buttonFromFile("From File")
+{
+ entryIP.signal_activate().connect(sigc::mem_fun(*this, &NewConDialog::on_enter_IP));
+ entryPW.signal_activate().connect(sigc::mem_fun(*this, &NewConDialog::on_enter_password));
+ buttonFromFile.signal_clicked().connect(sigc::mem_fun(*this, &NewConDialog::on_button_fromFile_click));
+
+ frameIP.add(entryIP);
+ framePW.add(entryPW);
+ contentBox.add(frameIP);
+ contentBox.add(framePW);
+ contentBox.add(buttonFromFile);
+ show_all_children();
+}
+
+NewConDialog::~NewConDialog()
+{}
+
+void NewConDialog::on_enter_password()
+{
+ if (entryIP.get_text() != "") // if the IP/hostname was already supplied, we proceed without putting the focus
+ // back on the IP field.
+ // we also proceed if theres no password given, because theres either no password
+ // needed or the password dialog will take care of that later on
+ on_button_ok_click();
+ else
+ entryIP.grab_focus();
+}
+
+void NewConDialog::on_enter_IP()
+{
+ if (entryIP.get_text() != "")
+ {
+ if (entryPW.get_text() == "") // if no password was supplied we put the focus on the password
+ entryPW.grab_focus();
+ else
+ on_button_ok_click();
+ }
+ else
+ return;
+}
+
+
+void NewConDialog::on_button_ok_click()
+{
+ connection_IP = entryIP.get_text();
+ if (connection_IP != "") // we only proceed if the IP/hostname field isnt empty
+ {
+ connection_password = entryPW.get_text();
+ QString infoLine;
+ infoLine = connection_IP;
+ if (connection_password.length() > 0) // if the password was supplied, we assemble the string
+ // with the necessary information
+ {
+ infoLine.append(" ");
+ infoLine.append(connection_password);
+ }
+
+ // VNCConnectInfo* newCon = getConInfo(infoLine);
+
+// myParent->addConnection(newCon);
+
+ ConnectionDialog::on_button_ok_click();
+ }
+}
+
+void NewConDialog::on_button_fromFile_click()
+{
+// myParent->readClientsFromFile();
+ ConnectionDialog::on_button_ok_click();
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+MessageDialog::MessageDialog(MainWindow* newParent, const Glib::ustring& title, QString* newMessage)
+ : ConnectionDialog(newParent, title),
+ frameMsg("Message")
+{
+ message = newMessage;
+ entryMsg.signal_activate().connect(sigc::mem_fun(*this, &MessageDialog::on_enter_message));
+
+ frameMsg.add(entryMsg);
+
+ contentBox.add(frameMsg);
+
+ show_all_children();
+}
+
+MessageDialog::~MessageDialog()
+{}
+
+void MessageDialog::on_enter_message()
+{
+ if (entryMsg.get_text() != "")
+ {
+ on_button_ok_click();
+ }
+}
+
+
+void MessageDialog::on_button_ok_click()
+{
+ if (entryMsg.get_text().empty())
+ return;
+
+ *message = entryMsg.get_text();
+
+ ConnectionDialog::on_button_ok_click();
+}
diff --git a/src/gui/connectionDialog.h b/src/gui/connectionDialog.h
new file mode 100644
index 0000000..8f268d4
--- /dev/null
+++ b/src/gui/connectionDialog.h
@@ -0,0 +1,123 @@
+#ifndef _CONNECTIONDIALOG_H_
+#define _CONNECTIONDIALOG_H_
+#include <src/gui/mainWindow.h>
+//#include <src/core/pvsCore.h>
+//#include <src/util/pvsUtil.h>
+
+
+class MainWindow;
+
+/** ConnectionDialog
+ * Abstract base class for dialogs
+ */
+
+class ConnectionDialog : public Gtk::Window
+{
+
+public:
+ ConnectionDialog(MainWindow* newParent, const Glib::ustring& title);
+ ~ConnectionDialog();
+
+protected:
+
+ virtual void on_button_ok_click(); // callback for ok button
+ virtual void on_button_cancel_click(); // callback for cancel button
+
+ Gtk::VBox contentBox; // box containing the individual content of the dialogs
+ Gtk::HBox buttonBox; // box containing the shared buttons (ok & cancel) of the dialogs
+ Gtk::VBox windowBox; // box containing content and button boxes
+ Gtk::Button buttonOK; // the ok button
+ Gtk::Button buttonCancel; // the cancel button
+ MainWindow* myParent; // pointer to the parenting window
+
+};
+
+
+/** PasswordDialog
+ * dialog with the sole purpose to ask for a password (if requested)
+ */
+
+
+class PasswordDialog : public ConnectionDialog
+{
+
+public:
+
+ PasswordDialog(MainWindow* newParent, const Glib::ustring& title, QString* newTargetPW); // the PasswordDialog constructor takes a pointer to a string for the sole
+ // reason that it is not connected to the connection that asks for a password and therefore cannot tell the user to which
+ // connection it belongs. So the connection puts the hostname in the string which the pointer is pointing to for the password
+ // dialog to read out and show to the user. The string is then overwritten with the password the user entered and then used
+ // inside the connection to feed the password request.
+ ~PasswordDialog();
+
+protected:
+
+ void on_enter_password();
+ void on_button_ok_click();
+ void on_button_cancel_click();
+
+ Gtk::Frame frameIP;
+ Gtk::Entry entryPW;
+
+private:
+ QString password, *targetPW;
+};
+
+/** NewConDialog
+ * dialog to open up a new connection to a vnc server
+ * offers the options
+ * * to enter a password to not come up
+ * with a password dialog later
+ * * to read prefab connections from a file
+ */
+
+
+class NewConDialog : public ConnectionDialog
+{
+
+public:
+ NewConDialog(MainWindow* newParent, const Glib::ustring& title);
+ ~NewConDialog();
+
+protected:
+
+ void on_enter_password(); // callback when enter was hit in the password text field.
+ void on_enter_IP(); // callback when enter was hit in the IP/Host text field
+
+ void on_button_ok_click(); // ok button callback
+ void on_button_fromFile_click();// read-from-file button callback
+
+ Gtk::Frame frameIP; // just a frame around the IP text field
+ Gtk::Frame framePW; // the same for the pw field
+ Gtk::Button buttonFromFile; // button to read out a file
+ Gtk::Entry entryIP; // text field for the IP/Hostname
+ Gtk::Entry entryPW; // text field for the password (optional)
+
+private:
+ QString connection_password;
+ QString connection_IP;
+};
+
+class MessageDialog : public ConnectionDialog
+{
+
+public:
+ MessageDialog(MainWindow* newParent, const Glib::ustring& title, QString* newMessage);
+ ~MessageDialog();
+
+protected:
+
+ void on_enter_message(); // callback when enter was hit in the text field.
+
+ void on_button_ok_click(); // ok button callback
+ void on_button_fromFile_click();// read-from-file button callback
+
+ Gtk::Frame frameMsg; // just a frame around the text
+ Gtk::Entry entryMsg; // text field for the message
+
+private:
+ QString * message;
+};
+
+
+#endif
diff --git a/src/gui/connectionFrame.cpp b/src/gui/connectionFrame.cpp
new file mode 100644
index 0000000..e889991
--- /dev/null
+++ b/src/gui/connectionFrame.cpp
@@ -0,0 +1,557 @@
+/*
+# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+# -----------------------------------------------------------------------------
+# src/gui/connectionFrame.cpp
+# -----------------------------------------------------------------------------
+*/
+
+
+#include <src/gui/connectionFrame.h>
+#include <src/gui/dialog.h>
+#include <src/gui/mainWindow.h>
+#include <iostream>
+extern "C"
+{
+#include <rfb/rfbclient.h>
+}
+#include <src/core/pvsConnectionManager.h>
+
+
+ConnectionFrame::ConnectionFrame(QWidget *parent) :
+ QGroupBox(parent)
+{
+
+ //defines the ui-stuff
+
+ _gL = new QGridLayout(this);
+ _gL->setSpacing(6);
+ _gL->setMargin(1);
+
+ _split = new QSplitter(this);
+ _split->setOrientation(Qt::Vertical);
+
+ _frame = new Frame("", _split);
+ _frame->setConFrame(this);
+ _split->addWidget(_frame);
+
+ _conFrameTaskbar = new QWidget(_split);
+ _conFrameTaskbar->setMaximumHeight(30);
+
+ _gLayout = new QGridLayout(_conFrameTaskbar);
+ _gLayout->setMargin(0);
+ _gLayout->setSpacing(0);
+
+ _hLayoutInCfTaskbar = new QHBoxLayout();
+
+ _username = new QLabel(_conFrameTaskbar);
+ _username->setStyleSheet(QString::fromUtf8("background-color: rgb(150, 150, 168);"));
+ _username->setAlignment(Qt::AlignLeft);
+
+ _hLayoutInCfTaskbar->addWidget(_username);
+
+ _dozentContaimner = new QLabel(_conFrameTaskbar);
+ _dozentContaimner->setStyleSheet(QString::fromUtf8("background-color: rgb(150, 150, 168);"));
+ _dozentContaimner->setAlignment(Qt::AlignRight);
+ _dozentContaimner->setMaximumSize(QSize(20, 20));
+ _dozentContaimner->setScaledContents(true);
+
+ _hLayoutInCfTaskbar->addWidget(_dozentContaimner);
+
+ _dozentContaimner->setDisabled(true);
+
+ _status = new QLabel(_conFrameTaskbar);
+ _status->setStyleSheet(QString::fromUtf8("background-color: rgb(150, 150, 168);"));
+ _status->setAlignment(Qt::AlignRight);
+ _status->setMaximumSize(QSize(22, 21));
+
+ _hLayoutInCfTaskbar->addWidget(_status);
+
+ _gLayout->addLayout(_hLayoutInCfTaskbar, 0, 0, 1, 1);
+ _split->addWidget(_conFrameTaskbar);
+
+ _gL->addWidget(_split, 0, 0, 1, 1);
+
+ this->setLayout(_gL);
+
+ setInitSize(190,168);
+
+ initFrame();
+
+ nat_height = 0;
+ nat_width = 0;
+ _ratio = 100;
+ overSized = false;
+ _fullscreen = false;
+ _closeup = false;
+ active = false;
+ _isOnProjekt = false;
+ isClientOnline = true;
+
+ //slots and signals
+
+ DelDummy = new QAction(tr("&Remove dummy..."),this);
+ connect(DelDummy, SIGNAL(triggered()), this, SLOT(delDummy()));
+ lockClient = new QAction(tr("&Lock Client(s)"),this);
+ connect(lockClient, SIGNAL(triggered()), this, SLOT(on_lock()));
+ uLockClient = new QAction(tr("&Unlock Client(s)"),this);
+ connect(uLockClient, SIGNAL(triggered()), this, SLOT(on_unlock()));
+ /*invertlockClient = new QAction(tr("&Invertlock Client(s)"),this);
+ connect(invertlockClient, SIGNAL(triggered()), this, SLOT(on_lock_invert()));
+ LockAllClient = new QAction(tr("&Lock all Client(s)"),this);
+ connect(LockAllClient, SIGNAL(triggered()), this, SLOT(on_lock_all()));
+ uLockAllClient = new QAction(tr("&Unlock all Client(s)"),this);
+ connect(uLockAllClient, SIGNAL(triggered()), this, SLOT(on_unlock_all()));*/
+ msgLockClient = new QAction(tr("&MsgLock Client(s)"),this);
+ connect(msgLockClient, SIGNAL(triggered()), this, SLOT(on_lock_with_message()));
+ msgLockAllClient = new QAction(tr("&MsgLock all Client(s)"),this);
+ connect(msgLockAllClient, SIGNAL(triggered()), this, SLOT(on_lock_all_with_message()));
+ msgClient = new QAction(tr("&Message Client(s)"),this);
+ connect(msgClient, SIGNAL(triggered()), this, SLOT(on_message()));
+ project = new QAction(tr("&Projection"),this);
+ connect(project, SIGNAL(triggered()), this, SLOT(on_projection()));
+ uproject = new QAction(tr("&Unprojection"),this);
+ connect(uproject, SIGNAL(triggered()), this, SLOT(on_unprojection()));
+ /*rHelp = new QAction(tr("&Remote Help"),this);
+ connect(rHelp, SIGNAL(triggered()), this, SLOT(on_remoteHelp()));*/
+
+ //connect(_frame, SIGNAL(clicked()), this, SLOT(on_click()));
+
+ //menu entries
+
+ menu = new QMenu(this);
+ menu->addAction(DelDummy);
+ menu->addSeparator();
+ menu->addAction(lockClient);
+ menu->addAction(uLockClient);
+ /*menu->addAction(invertlockClient);
+ menu->addAction(LockAllClient);
+ menu->addAction(uLockAllClient);*/
+ menu->addAction(msgLockClient);
+ menu->addAction(msgLockAllClient);
+ menu->addAction(msgClient);
+ menu->addAction(project);
+ menu->addAction(uproject);
+ //menu->addAction(rHelp);
+
+ this->show();
+}
+
+ConnectionFrame::~ConnectionFrame()
+{
+
+}
+
+QString ConnectionFrame::getTitle() // get frame title
+{
+ return title();
+}
+
+void ConnectionFrame::setTheTitle(QString title) // set frame title
+{
+ if (title.isNull()) return;
+ setTitle(title);
+}
+
+QString ConnectionFrame::getTaskbarTitle() // get taskbar title
+{
+ if (!_username->text().isNull())
+ return _username->text();
+ else
+ return _myConnection->getIp();
+}
+
+void ConnectionFrame::setTaskbarTitle(QString title) // set taskbar title
+{
+ _username->setText(title);
+ _frame->ip = title;
+}
+
+void ConnectionFrame::setInitSize(int w, int h)
+{
+ resize(w, h);
+ _frame->resize(w, h);
+ _conFrameTaskbar->resize(w, h);
+ prev_height = h;
+ prev_width = w;
+ init_w = w;
+ init_h = h;
+}
+
+void ConnectionFrame::Resize(int w, int h)
+{
+ resize(w, h);
+ _frame->resize(w, h);
+}
+
+void ConnectionFrame::initFrame()
+{
+ _clientStatus = QPixmap(":/offline");
+ _clientDozent = QPixmap(":/dozent2");
+ _dozentContaimner->setPixmap(_clientDozent.scaled(3*_dozentContaimner->size()/4,
+ Qt::KeepAspectRatio, Qt::SmoothTransformation));
+}
+
+
+void ConnectionFrame::setConnection(PVSClient* newConnection)
+{
+ if (newConnection)
+ {
+ _myConnection = newConnection;
+ _myConnection->setConnectionFrame(this);
+ const QString userName = QString(
+ _myConnection->getUserName().toUtf8().data());
+ if (_myConnection->getVNCConnection() && _myConnection->getVNCConnection()->getVNCClientThread())
+ {
+ _myConnection->getVNCConnection()->setFrame(this);
+ _frame->setVNCThreadConnection(_myConnection->getVNCConnection()->getVNCClientThread());
+ setActive(true);
+ setToolTip(userName);
+ setTitle(userName);
+ }
+ else
+ {
+ setToolTip(userName);
+ setTitle(userName);
+ }
+ }
+
+}
+
+/*
+ * We set a new VNCConnection to the pvsmgr with a new quality.
+ * To do this, that is very easy. At this point we have already a ruuning
+ * Connection between the server an the client. This connection is controlled in a thread.
+ * So we disconnect all Qt-Signals on this thread and we terminate the thread.
+ * After do this we have to set a new thread(VNCClientThread) and connect the signals again.
+ *
+ * When you want to read about this, please check the developper's book.
+ */
+void ConnectionFrame::resetConnectionWithQuality(int quality)
+{
+ if (getFrame())
+ {
+ _myConnection->getVNCConnection()->reInitClientWithQuality(quality);
+ getFrame()->stopVNCThreadConnection();
+ getFrame()->setVNCThreadConnection(_myConnection->getVNCConnection()->getVNCClientThread());
+ getFrame()->update();
+ }
+}
+
+void ConnectionFrame::delDummy()
+{
+ MainWindow::getConnectionWindow()->removeFromList(this);
+}
+
+void ConnectionFrame::on_projection()
+{
+ MainWindow::getConnectionList()->on_projection();
+}
+
+void ConnectionFrame::on_unprojection()
+{
+ MainWindow::getConnectionList()->on_unprojection();
+}
+
+void ConnectionFrame::on_lock()
+{
+ if (_myConnection->getVNCConnection())
+ MainWindow::getConnectionWindow()->lockStation(_myConnection);
+}
+
+void ConnectionFrame::on_unlock()
+{
+ if (_myConnection->getVNCConnection())
+ MainWindow::getConnectionWindow()->unlockStation(_myConnection);
+}
+
+void ConnectionFrame::on_message()
+{
+ Dialog msgD;
+ QString myString = NULL;
+ int result = msgD.exec();
+
+ if (result == 1)
+ {
+ myString = MainWindow::getWindow()->getMsgDialog();
+ if(!myString.isEmpty())
+ MainWindow::getConnectionWindow()->messageStations("BROADCAST",myString);
+ }
+}
+
+void ConnectionFrame::on_lock_with_message()
+{
+ Dialog msgD;
+ QString myString = NULL;
+ int result = msgD.exec();
+
+ if(result == 1)
+ {
+ myString = MainWindow::getWindow()->getMsgDialog();
+ if(!myString.isEmpty())
+ {
+ MainWindow::getConnectionWindow()->lockStationsWithMessage(myString);
+ }
+ }
+}
+
+void ConnectionFrame::on_lock_all_with_message()
+{
+ QString myString = NULL;
+ Dialog msgD;
+ int result = msgD.exec();
+
+ if(result == 1)
+ {
+ myString = MainWindow::getWindow()->getMsgDialog();
+ if(!myString.isEmpty())
+ {
+ MainWindow::getConnectionWindow()->lockAllStationsWithMessage(myString);
+ }
+ }
+}
+
+void ConnectionFrame::on_lock_all()
+{
+ MainWindow::getConnectionWindow()->lockAllStations();
+}
+
+void ConnectionFrame::on_unlock_all()
+{
+ MainWindow::getConnectionWindow()->unlockAllStations();
+}
+
+void ConnectionFrame::on_lock_invert()
+{
+ //MainWindow::getConnectionWindow()->lockInvertStations();
+}
+
+void ConnectionFrame::on_remoteHelp()
+{
+
+}
+
+void ConnectionFrame::setIgnoreRatio(bool ignore)
+{
+ ignore_ratio = ignore;
+}
+
+void ConnectionFrame::setFullscreen(bool fs)
+{
+ _fullscreen = fs;
+ setIgnoreRatio(!fs);
+}
+
+void ConnectionFrame::setCloseup(bool cu)
+{
+ _closeup = cu;
+ setIgnoreRatio(false);
+}
+
+void ConnectionFrame::setInteractive(bool doit)
+{
+ viewOnly = !doit;
+}
+
+void ConnectionFrame::setActive(bool activate)
+{
+ active = activate;
+}
+
+void ConnectionFrame::setDummy(bool dummy)
+{
+ _dummy = dummy;
+ if (_dummy)
+ {
+ _clientStatus = QPixmap(0, 0); //ein leeres Pixmap erstellen
+ _clientStatus.fill(Qt::white); // benöigt bevor man drin zeichen
+ _clientStatus = QPixmap(":/offline");
+ _status->setMaximumSize(QSize(30, 30));
+ _status->setPixmap(_clientStatus.scaled(29,27,
+ Qt::KeepAspectRatio, Qt::SmoothTransformation));
+ //_status->setPixmap(clientStatus.scaled(3*_status->size()/4,
+ // Qt::KeepAspectRatio, Qt::SmoothTransformation));
+ //setConnection(NULL);
+ }
+ else
+ {
+ _clientStatus = QPixmap(0, 0); //ein leeres Pixmap erstellen
+ _clientStatus.fill(Qt::white); // benöigt bevor man drin zeichen
+ _clientStatus = QPixmap(":/online");
+ _status->setMaximumSize(QSize(30, 30));
+ _status->setPixmap(_clientStatus.scaled(29,27,
+ Qt::KeepAspectRatio, Qt::SmoothTransformation));
+ //_status->setPixmap(clientStatus.scaled(3*_status->size()/4,
+ // Qt::KeepAspectRatio, Qt::SmoothTransformation));
+ }
+ // }
+}
+
+void ConnectionFrame::setFrameRate(int newRate)
+{
+ //newRate = 5000;
+}
+
+void ConnectionFrame::mouseReleaseEvent ( QMouseEvent * e )
+{
+ if (e->button() == Qt::LeftButton)
+ {
+ QPoint relPoint = mapToParent(e->pos());
+ QRect r = MainWindow::getConnectionWindow()->frameGeometry();
+ /*
+ * We don't want to move the client in a position where we can't catch it again!
+ */
+ if (relPoint.x() > r.width() || relPoint.y() > r.height() ||
+ relPoint.x() < 0 || relPoint.y() < 0)
+ move(_previousPoint);
+ QApplication::setOverrideCursor(QCursor(Qt::OpenHandCursor));
+ }
+}
+
+void ConnectionFrame::enterEvent ( QEvent * event )
+{
+ update();
+ QApplication::setOverrideCursor(QCursor(Qt::OpenHandCursor));
+ if (!_dummy)
+ _frame->setToolButtonListVisible(true);
+}
+
+void ConnectionFrame::leaveEvent ( QEvent * event )
+{
+ QApplication::setOverrideCursor(QCursor(Qt::ArrowCursor));
+ if (!_dummy)
+ _frame->setToolButtonListVisible(false);
+}
+
+void ConnectionFrame::mousePressEvent(QMouseEvent *event)
+{
+ if (event->button() == Qt::RightButton)
+ {
+ if (!_dummy)
+ {
+ DelDummy->setDisabled(true);
+ menu->exec(QCursor::pos());
+ }
+ else
+ {
+ foreach (QAction* a, menu->actions())
+ a->setDisabled(true);
+ DelDummy->setDisabled(false);
+ menu->exec(QCursor::pos());
+ }
+ }
+ else
+ {
+ _clickPoint = event->pos();
+ _previousPoint = pos();
+ QApplication::setOverrideCursor(QCursor(Qt::ClosedHandCursor));
+ }
+ /*
+ * On click, the window have to be on the top-level.
+ */
+ activateWindow();
+ raise();
+ update();
+}
+
+void ConnectionFrame::mouseMoveEvent(QMouseEvent *event)
+{
+ QApplication::setOverrideCursor(QCursor(Qt::ClosedHandCursor));
+ move(mapToParent(event->pos()-_clickPoint));
+}
+
+void ConnectionFrame::paintCloseUp(int w, int h)
+{
+
+
+ if (!_frame->image().isNull())
+ {
+ /*this->setFixedWidth(w);
+ _conFrameTaskbar->setMaximumWidth(w);
+ resize(w, h);*/
+ resizeComponent(w, h);
+ setMaximumSize(w,h);
+ resize(w, h);
+ }
+ else
+ {
+ std::cout << "pixel is NULL" << std::endl;
+ }
+
+}
+
+void ConnectionFrame::resizeComponent(int w, int h)
+{
+ int th = (h*_conFrameTaskbar->width())/w;
+ int uh = (h*_username->width())/w;
+ _conFrameTaskbar->setMaximumSize(w, th);
+ _conFrameTaskbar->resize(w, th);
+ _username->setMaximumSize(w, uh);
+ _username->resize(w,uh);
+}
+
+void ConnectionFrame::setSource()
+{
+ _clientStatus = QPixmap(0, 0); //ein leeres Pixmap erstellen
+ _clientStatus.fill(Qt::white); // benöigt bevor man drin zeichen
+ _clientStatus = QPixmap(":/source");
+ _status->setMaximumSize(QSize(62, 30));
+ _status->setPixmap(_clientStatus.scaled(61,29,
+ Qt::KeepAspectRatio, Qt::SmoothTransformation));
+ _isOnProjekt = true;
+}
+
+void ConnectionFrame::setTarget()
+{
+ _clientStatus = QPixmap(0, 0); //ein leeres Pixmap erstellen
+ _clientStatus.fill(Qt::white); // benöigt bevor man drin zeichen
+ _clientStatus = QPixmap(":/target");
+ _status->setMaximumSize(QSize(62, 30));
+ _status->setPixmap(_clientStatus.scaled(61,29,
+ Qt::KeepAspectRatio, Qt::SmoothTransformation));
+}
+
+void ConnectionFrame::setUnproject()
+{
+ _clientStatus = QPixmap(0, 0); //ein leeres Pixmap erstellen
+ _clientStatus.fill(Qt::white); // benöigt bevor man drin zeichen
+ _clientStatus = QPixmap(":/online");
+ _status->setMaximumSize(QSize(30, 30));
+ _status->setPixmap(_clientStatus.scaled(29,27,
+ Qt::KeepAspectRatio, Qt::SmoothTransformation));
+ _isOnProjekt = false;
+}
+
+void ConnectionFrame::setDozent(bool isDozent)
+{
+ if (isDozent)
+ _dozentContaimner->setDisabled(false);
+ else
+ _dozentContaimner->setDisabled(true);
+}
+
+void ConnectionFrame::on_click()
+{
+ //std::cout << "HALLO! WAS?" << std::endl;
+}
+
+const QPixmap* ConnectionFrame::getFramePixmap()
+{
+ if (_frame == NULL) return NULL;
+ return _frame->pixmap();
+}
+
+Frame* ConnectionFrame::getFrame()
+{
+ if(_myConnection && _myConnection->getVNCConnection()) return _frame;
+ return NULL;
+};
+
+//Frame* ConnectionFrame::_frame = NULL;
diff --git a/src/gui/connectionFrame.h b/src/gui/connectionFrame.h
new file mode 100644
index 0000000..a199102
--- /dev/null
+++ b/src/gui/connectionFrame.h
@@ -0,0 +1,199 @@
+#ifndef _CONNECTIONFRAME_H_
+#define _CONNECTIONFRAME_H_
+#include <QtGui>
+#include <fstream>
+#include <iostream>
+#include <QImage>
+#include <QPixmap>
+#include <QLabel>
+#include <src/core/pvsClient.h>
+#include <src/gui/frame.h>
+//#include <src/gui/mainWindow.h>
+#include <src/gui/dialog.h>
+extern "C"
+{
+#include <rfb/rfbclient.h>
+}
+
+#define PROFILE
+#include <src/util/timeUtil.h>
+
+/**
+ * Container for the drawable area that shows the corresponding servers desktop
+ *
+ */
+
+class PVSClient;
+class VNCConnection;
+class ConnectionWindow;
+class Frame;
+class Dialog;
+class MainWindow;
+
+class ConnectionFrame : public QGroupBox
+{
+
+ Q_OBJECT
+
+public:
+ ConnectionFrame(QWidget* parent=0); // on width and height being zero, defaults values are used
+ virtual ~ConnectionFrame();
+
+ QString getTitle();
+ void setTheTitle(QString title);
+ QString getTaskbarTitle();
+ void setTaskbarTitle(QString title);
+ void setInitSize(int w, int h);
+ void Resize(int w, int h);
+ void initFrame();
+
+ int getPrevWidth(){return prev_width;};
+ void setPrevWidth(int w){prev_width = w;}
+ int getPrevHeight(){return prev_height;};
+ void setPrevHeight(int h){prev_height = h;}
+
+ void setConnection(PVSClient* newConnection);
+ void resetConnectionWithQuality(int quality);
+ PVSClient* getConnection()
+ {
+ return _myConnection;
+ }
+ ;
+ //bool drawFrame(); // call to ask for a redraw of the frames content
+ void setIgnoreRatio(bool ignore); // sets wether it should force square on the content or not
+ void setFullscreen(bool fs); // toggles wether this frame is requested to shown fullscreen or not
+ bool getFullscreen()
+ {
+ return _fullscreen;
+ }
+ ; // returns wether the frame is fullscreen (or requested to be) or not
+ void setCloseup(bool cu); // toggles wether this frame is requested to shown fullscreen or not
+ bool getCloseup()
+ {
+ return _closeup;
+ }
+ ; // returns wether the frame is fullscreen (or requested to be) or not
+
+ void setInteractive(bool doit);
+ float getRatio()
+ {
+ return _ratio;
+ }
+ ; // returns the native ratio of the source buffer (h/w)
+ void setRatio(int newRatio)
+ {
+ _ratio = newRatio;
+ }
+ ;
+ bool getOversized()
+ {
+ return overSized;
+ }
+ ; // returns wether the frame is reasonably wider than other frames (e.g. dual screen displays)
+ void setOversized(bool over)
+ {
+ overSized = over;
+ }
+ ;
+ void setActive(bool activate);
+ bool getActive()
+ {
+ return active;
+ }
+ ;
+ void setDummy(bool dummy);
+ bool isDummy()
+ {
+ return _dummy;
+ }
+ ;
+ bool isOnProjekt()
+ {
+ return _isOnProjekt;
+ }
+ ;
+ void setFrameRate(int newRate);
+ bool isClientOnline;
+ void paintCloseUp(int w, int h);
+ void resizeComponent(int w, int h);
+ void setSource();
+ void setTarget();
+ void setUnproject();
+ void setDozent(bool isDozent);
+ const QPixmap* getFramePixmap();
+ Frame* getFrame();
+ int init_w, init_h;
+
+public Q_SLOTS:
+ virtual void delDummy();
+ virtual void on_projection();
+ virtual void on_unprojection();
+ virtual void on_lock();
+ virtual void on_unlock();
+ virtual void on_message();
+ virtual void on_lock_with_message();
+ virtual void on_lock_all_with_message();
+ virtual void on_lock_all();
+ virtual void on_unlock_all();
+ virtual void on_lock_invert();
+ virtual void on_remoteHelp();
+ virtual void on_click();
+
+protected:
+ //virtual void paintEvent(QPaintEvent *event);
+ void mouseReleaseEvent ( QMouseEvent * e );
+ virtual void enterEvent ( QEvent * event );
+ virtual void leaveEvent ( QEvent * event );
+ void mousePressEvent(QMouseEvent *event);
+ void mouseMoveEvent(QMouseEvent *event);
+ //void mouseReleaseEvent ( QMouseEvent * event );
+
+private:
+
+ Frame *_frame;
+ //clickableLabel *frame;
+ QSplitter *_split;
+ QGridLayout* _gL;
+ QLabel* _username;
+ QLabel* _status;
+ QLabel* _dozentContaimner;
+ QWidget* _conFrameTaskbar;
+ QGridLayout* _gLayout;
+ QHBoxLayout* _hLayoutInCfTaskbar;
+
+ PVSClient* _myConnection;
+ QPixmap _clientPix;
+ QPixmap _clientStatus;
+ QPixmap _clientDozent;
+ int nat_height, nat_width; // native height and width of the source buffer
+ int cu_height, cu_width;
+ int prev_height, prev_width;
+ // uint8_t prev_buttonMask; /* bits 0-7 are buttons 1-8, 0=up, 1=down */
+ int _ratio;
+ bool _dummy;
+ bool ignore_ratio, overSized, first;
+ bool _fullscreen, _closeup, _isOnProjekt;
+
+ bool viewOnly, active;
+ rfbClient* myClient;
+
+ QMenu *menu;
+ QAction *DelDummy;
+ QAction *lockClient ;
+ QAction *uLockClient ;
+ /*QAction *invertlockClient ;
+ QAction *LockAllClient ;
+ QAction *uLockAllClient ;*/
+ QAction *msgLockAllClient ;
+ QAction *msgClient ;
+ QAction *msgLockClient ;
+ QAction *project ;
+ QAction *uproject ;
+ //QAction *rHelp ;
+
+
+ QPoint _clickPoint;
+ QPoint _previousPoint;
+};
+
+#endif
diff --git a/src/gui/connectionList.cpp b/src/gui/connectionList.cpp
new file mode 100644
index 0000000..2f9829e
--- /dev/null
+++ b/src/gui/connectionList.cpp
@@ -0,0 +1,603 @@
+/*
+# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+# -----------------------------------------------------------------------------
+# src/gui/connectionList.cpp
+# -----------------------------------------------------------------------------
+*/
+
+#include <QtGui>
+#include <iostream>
+#include "connectionList.h"
+#include <src/gui/dialog.h>
+//#include <src/gui/projectionDialog.h>
+//#include "mainWindow.h"
+#define COL_FULLNAME 0
+#define COL_IP 1
+#define COL_USERNAME 2
+
+ConnectionList::ConnectionList(QWidget *parent):
+ QTableView(parent)
+{
+ /*Das Modelfestlegen, wo die Clientname angezeigt werden.*/
+ model = new QStandardItemModel(0,3,this); //Leere Tabelle mit einer Spalte erstellen
+ model->setHeaderData(0, Qt::Horizontal, tr("Name")); //Spalte name definieren
+ model->setHeaderData(1, Qt::Horizontal, tr("IP")); //IP-column will be hide
+ model->setHeaderData(2, Qt::Horizontal, tr("Username"));
+ setModel(model);
+ this->setColumnHidden(1, true);
+ this->setColumnHidden(2, true);
+
+ QItemSelectionModel *selectionModel = new QItemSelectionModel(model);
+ setSelectionModel(selectionModel);
+ QHeaderView *headerView = horizontalHeader();
+ headerView->setStretchLastSection(true);
+ /*Das popup einstellen*/
+ preparePopup();
+
+ _useUserName = true;
+
+ setEditTriggers(QAbstractItemView::NoEditTriggers); //Die Einträge in der Tabelle werden nicht editierbar.
+ setSelectionMode(QAbstractItemView::ExtendedSelection); //Damit mehere Einträge selektierbar werden.
+
+ resizeColumnToContents(0);
+ clientindex = 0;
+ isOnProjection = false; //No projection on progress now!
+ projSourceName = ""; //The projection source name is empty.
+}
+
+ConnectionList::~ConnectionList()
+{
+}
+
+void ConnectionList::preparePopup()
+{
+
+ /*Aktion definieren*/
+ /* a1 = new QAction(tr("&Remove Clients (debug)"),model);
+ connect(a1, SIGNAL(triggered()), this, SLOT(on_removeClient()));
+ a2 = new QAction(tr("&Request VNC-Window"),model);
+ connect(a2, SIGNAL(triggered()), this, SLOT(on_vnc_add()));
+ a3 = new QAction(tr("&Remove VNC-Window"),model);
+ connect(a3, SIGNAL(triggered()), this, SLOT(on_vnc_remove()));*/
+ _lockClient = new QAction(tr("&Lock Client(s)"),model);
+ connect(_lockClient, SIGNAL(triggered()), this, SLOT(on_lock()));
+ _uLockClient = new QAction(tr("&Unlock Client(s)"),model);
+ connect(_uLockClient, SIGNAL(triggered()), this, SLOT(on_unlock()));
+ /* invertlockClient = new QAction(tr("&Invertlock Client(s)"),model);
+ connect(invertlockClient, SIGNAL(triggered()), this, SLOT(on_lock_invert()));
+ LockAllClient = new QAction(tr("&Lock all Client(s)"),model);
+ connect(LockAllClient, SIGNAL(triggered()), this, SLOT(on_lock_all()));
+ uLockAllClient = new QAction(tr("&Unlock all Client(s)"),model);
+ connect(uLockAllClient, SIGNAL(triggered()), this, SLOT(on_unlock_all()));*/
+ _msgLockClient = new QAction(tr("&MsgLock Client(s)"),model);
+ connect(_msgLockClient, SIGNAL(triggered()), this, SLOT(on_lock_with_message()));
+ _msgLockAllClient = new QAction(tr("&MsgLock all Client(s)"),model);
+ connect(_msgLockAllClient, SIGNAL(triggered()), this, SLOT(on_lock_all_with_message()));
+ _msgClient = new QAction(tr("&Message Client(s)"),model);
+ connect(_msgClient, SIGNAL(triggered()), this, SLOT(on_message()));
+ //msgClient = createToolbarButton(tr("&Message Client(s)"), SLOT(on_message()));
+ _project = new QAction(tr("&Projection"),model);
+ connect(_project, SIGNAL(triggered()), this, SLOT(on_projection()));
+ _uproject = new QAction(tr("&Unprojection"),model);
+ connect(_uproject, SIGNAL(triggered()), this, SLOT(on_unprojection()));
+ /* rHelp = new QAction(tr("&Remote Help"),model);
+ connect(rHelp, SIGNAL(triggered()), this, SLOT(on_remoteHelp()));*/
+
+ /*Menü definieren*/
+ _popupMenu = new QMenu(this);
+
+ /*Aktionen in Menü aufnehmen*/
+ /* menu->addAction(a1);
+ menu->addAction(a2);
+ menu->addAction(a3);*/
+ _popupMenu->addAction(_lockClient);
+ _popupMenu->addAction(_uLockClient);
+ /* menu->addAction(invertlockClient);
+ menu->addAction(LockAllClient);
+ menu->addAction(uLockAllClient);*/
+ _popupMenu->addAction(_msgLockClient);
+ _popupMenu->addAction(_msgLockAllClient);
+ _popupMenu->addAction(_msgClient);
+ _popupMenu->addAction(_project);
+ _popupMenu->addAction(_uproject);
+ // menu->addAction(rHelp);
+
+}
+
+QAction* ConnectionList::createToolbarButton(const QString &name, const char *slot)
+{
+ QAction *action = new QAction(name, model);
+ connect(action, SIGNAL(triggered()), this, slot);
+ _popupMenu->addAction(action);
+
+ return action;
+}
+
+void ConnectionList::mouseReleaseEvent(QMouseEvent * e )
+{
+ // setCurrentIndex ( currentIndex () );
+ if (e->button() == Qt::RightButton)
+ {
+ if (model->rowCount(QModelIndex()) > 0)
+ foreach (QAction *a, _popupMenu->actions())
+ {
+ a->setDisabled(false);
+ }
+ else
+ foreach (QAction *a, _popupMenu->actions())
+ {
+ a->setDisabled(true);
+ }
+ _popupMenu->exec(QCursor::pos());
+ }
+}
+
+void ConnectionList::onAddClient(PVSClient* newConnection)
+{
+ if (newConnection)
+ {
+ //clientindex = model->rowCount(QModelIndex())+1;
+ model->insertRow(clientindex, QModelIndex());
+ //QString uname = newConnection->getPVSClientConnection()->getNameUser();
+ QString uname = newConnection->getLoginName();
+ if (_useUserName)
+ {
+ QString username = newConnection->getUserName();
+ QString ip = newConnection->getIp();
+ model->setData(model->index(clientindex, COL_FULLNAME, QModelIndex()),username);
+ model->setData(model->index(clientindex, COL_IP, QModelIndex()),ip);
+ model->setData(model->index(clientindex, COL_USERNAME, QModelIndex()),uname);
+ newConnection->getConnectionFrame()->setTaskbarTitle(ip);
+ addClientToList(username);
+ }
+ else
+ {
+ QString desktopname = QString(newConnection->getDesktopName().toUtf8().data());
+ QString ip = newConnection->getIp();
+ model->setData(model->index(clientindex, COL_FULLNAME, QModelIndex()),desktopname);
+ model->setData(model->index(clientindex, COL_IP, QModelIndex()),ip);
+ model->setData(model->index(clientindex, COL_USERNAME, QModelIndex()),uname);
+ }
+ setCurrentIndex(model->index(clientindex, 0));
+ on_vnc_add(); // triggert the automatic vnc request!
+ setCurrentIndex(model->index(-1, 0));
+ newConnection->setClientindex(clientindex);
+ clientindex++;
+ }
+}
+
+void ConnectionList::onRemoveClient(PVSClient* newCon)
+{
+ if (newCon && model->rowCount(QModelIndex()) > 0)
+ {
+ QString host = newCon->getIp();
+ for (int i=0; i<model->rowCount(QModelIndex()); i++)
+ {
+ if (model->index(i, 1, QModelIndex()).data(Qt::DisplayRole).toString()
+ .compare(host) == 0)
+ {
+ removeClientToList(model->index(i, 1, QModelIndex()).data(Qt::DisplayRole).toString());
+ model->removeRow(i, QModelIndex());
+ clientindex--;
+ break;
+ }
+ }
+ /*
+ * We have to check, if this disconnected client is involved in a projection process.
+ * If true, we have to unproject it, this will unproject the others clients that becomme
+ * the projection.
+ */
+ if (targetList.contains(host) || sourceList.contains(host))
+ unproject(host);
+
+
+ }
+}
+
+void ConnectionList::addClientToList(QString clientname)
+{
+ if (!_clientNames.contains(clientname))
+ _clientNames.append(clientname);
+}
+
+void ConnectionList::removeClientToList(QString clientname)
+{
+ if (_clientNames.contains(clientname))
+ {
+ _clientNames.removeOne(clientname);
+ }
+}
+
+void ConnectionList::onUpdateClient(PVSClient* newConnection)
+{
+
+ if (model->rowCount(QModelIndex()) > 0)
+ {
+ for (int i=0; i<model->rowCount(QModelIndex()); i++)
+ {
+ if (model->index(i, 1, QModelIndex()).data(Qt::DisplayRole).toString()
+ .compare(newConnection->getIp()) == 0)
+ {
+ if (_useUserName)
+ {
+ newConnection->getConnectionFrame()->setTheTitle(newConnection->getUserName());
+ model->setData(model->index(i, COL_FULLNAME, QModelIndex()),newConnection->getUserName());
+ }
+ else
+ {
+ newConnection->getConnectionFrame()->setTheTitle(newConnection->getDesktopName());
+ model->setData(model->index(i, COL_FULLNAME, QModelIndex()),newConnection->getDesktopName());
+ }
+ break;
+ }
+ }
+ }
+ else
+ {
+ // something went awfully wrong!
+ }
+}
+
+bool ConnectionList::useUserName()
+{
+ return _useUserName;
+}
+
+bool ConnectionList::useUserName(bool use)
+{
+
+ if (use != _useUserName)
+ {
+ _useUserName = use;
+ }
+ return useUserName();
+}
+
+void ConnectionList::on_vnc_add()
+{
+ MainWindow::getConnectionWindow()->addVNC();
+}
+
+void ConnectionList::on_vnc_remove()
+{
+ MainWindow::getConnectionWindow()->removeVNC();
+}
+
+void ConnectionList::unproject(QString source)
+{
+ if (sourceList.contains(source))
+ {
+ QList<QString> target;
+ if (sourceMap.contains(source))
+ {
+ QString item;
+ foreach (item, sourceMap.value(source))
+ {
+ MainWindow::getConnectionWindow()->unprojectStations(item); //Nur target must be unproject
+ targetList.removeOne(item);
+ }
+ sourceMap.take(source);
+ }
+ MainWindow::getConnectionWindow()->unprojectStations(source); //the source schould be too unprojected.
+ sourceList.removeOne(source);
+ }
+ else
+ {
+ MainWindow::getConnectionWindow()->unprojectStations(source); //unproject a target
+ targetList.removeOne(source);
+ }
+ /*if (targetList.size() == 1)
+ targetList.clear();*/
+}
+
+void ConnectionList::on_projection()
+{
+ if(model->rowCount(QModelIndex())>1)
+ {
+ std::list<QString>* cuList = getSelectedClients();
+
+ if (targetList.size() == (model->rowCount(QModelIndex())-1))
+ {
+ QString message = QString(tr("No Target is available for a projection!\nPerform an unprojection to get a target."));
+ QMessageBox::information(this, "PVS", message);
+ }
+ else if(cuList->size() == 1)
+ {
+ QString source = cuList->front();
+ if (targetList.contains(source))
+ {
+ QString message = QString(tr("This source is already in a projection process involved.\n You can perform a unprojection on it to get it free."));
+ QMessageBox::information(this, "PVS", message);
+ }
+ else
+ {
+ ProjectionDialog projDialog;
+ int result = projDialog.exec();
+
+ if(result == 1)
+ {
+ if(projectList.size()>0)
+ {
+ QList<QString> list;
+ QString item;
+ foreach(item, projectList)
+ {
+ list.append(item);
+ }
+ sourceMap.insert(projSourceName, list);
+ if (!sourceList.contains(source))
+ sourceList.append(source);
+ MainWindow::getConnectionWindow()->projectStations(projSourceName);
+ }
+ else
+ ConsoleLog writeError( "Strange...the selected target aren't be transmitted to the MainWindow.");
+ }
+ else
+ ; // :(
+ }
+ }
+ else if(cuList->size() > 1)
+ {
+ QString message = QString(tr("To perform a projection you have to select only one source in a list with more than one index!"));
+ QMessageBox::information(this, "PVS", message);
+ }
+ }
+ else
+ {
+ QString message = QString(tr("To perform a projection you have to select only one source in a list with more than one index!"));
+ QMessageBox::information(this, "PVS", message);
+ }
+}
+
+void ConnectionList::on_unprojection()
+{
+ if(model->rowCount(QModelIndex())>1)
+ {
+ std::list<QString>* cuList = getSelectedClients();
+ if(cuList->size() == 1)
+ {
+ QString source = cuList->front();
+ unproject(source);
+ }
+ else
+ {
+ QString message = QString(tr("An unprojection is only possible on a selected source that is involved in a projection process, in a list with more than one index!"));
+ QMessageBox::information(this, "PVS", message);
+ }
+ }
+ else
+ {
+ QString message = QString(tr("An unprojection is only possible on a selected source that is involved in a projection process, in a list with more than one index!"));
+ QMessageBox::information(this, "PVS", message);
+ }
+}
+
+void ConnectionList::on_remoteHelp()
+{
+ if(model->rowCount(QModelIndex())>1)
+ {
+ std::list<QString>* cuList = getSelectedClients();
+
+ if (targetList.size() == (model->rowCount(QModelIndex())-1))
+ {
+ QString message = QString(tr("No Target is available for remote Help!\nPerform an unprojection or remove remote help to get a target."));
+ QMessageBox::information(this, "PVS", message);
+ }
+ else if(cuList->size() == 1)
+ {
+ QString source = cuList->front();
+ if (targetList.contains(source))
+ {
+ QString message = QString(tr("This source is already in a projection or remote Help process involved.\n You can perform a unprojection or remove remote Help on it to get it free."));
+ QMessageBox::information(this, "PVS", message);
+ }
+ else
+ {
+ ProjectionDialog projDialog;
+ int result = projDialog.exec();
+
+ if(result == 1)
+ {
+ if(projectList.size() > 0 && projectList.size() < 2)
+ {
+ QList<QString> list;
+ QString item;
+ foreach(item, projectList)
+ {
+ list.append(item);
+ }
+ sourceMap.insert(projSourceName, list);
+ MainWindow::getConnectionWindow()->remoteHelp(projSourceName);
+ }
+ else
+ ConsoleLog writeError( "Strange...the selected targets aren't be transmitted to the MainWindow.");
+ }
+ else
+ ; // :(
+ }
+ }
+ }
+ else
+ {
+ QString message = QString(tr("To perform a projection you have to select only one source in a list with more than one index!"));
+ QMessageBox::information(this, "PVS", message);
+ }
+}
+
+void ConnectionList::on_lock()
+{
+ MainWindow::getConnectionWindow()->lockStations();
+}
+
+void ConnectionList::on_unlock()
+{
+ MainWindow::getConnectionWindow()->unlockStations();
+}
+
+void ConnectionList::on_message()
+{
+ Dialog msgD;
+ QString myString = NULL;
+ int result = msgD.exec();
+
+ if (result == 1)
+ {
+ myString = MainWindow::getWindow()->getMsgDialog();
+ if(!myString.isEmpty())
+ MainWindow::getConnectionWindow()->messageStations("BROADCAST",myString);
+ }
+
+}
+
+void ConnectionList::on_lock_with_message()
+{
+ Dialog msgD;
+ QString myString = NULL;
+ int result = msgD.exec();
+
+ if(result == 1)
+ {
+ myString = MainWindow::getWindow()->getMsgDialog();
+ if(!myString.isEmpty())
+ {
+ MainWindow::getConnectionWindow()->lockStationsWithMessage(myString);
+ }
+ }
+}
+
+void ConnectionList::on_lock_all_with_message()
+{
+ QString myString = NULL;
+ Dialog msgD;
+ int result = msgD.exec();
+
+ if(result == 1)
+ {
+ myString = MainWindow::getWindow()->getMsgDialog();
+ if(!myString.isEmpty())
+ {
+ MainWindow::getConnectionWindow()->lockAllStationsWithMessage(myString);
+ }
+ }
+}
+
+
+void ConnectionList::on_lock_all()
+{
+ MainWindow::getConnectionWindow()->lockAllStations();
+}
+void ConnectionList::on_unlock_all()
+{
+ MainWindow::getConnectionWindow()->unlockAllStations();
+}
+
+void ConnectionList::on_unproject_all()
+{
+ MainWindow::getConnectionWindow()->unprojectAllStations();
+}
+
+
+void ConnectionList::on_lock_invert()
+{
+ MainWindow::getConnectionWindow()->lockInvertStations();
+}
+
+
+void ConnectionList::on_removeClient()
+{
+ QTableView *temp = static_cast<QTableView*>(this);
+ QItemSelectionModel *selectionModel = temp->selectionModel();
+
+ QModelIndexList indexes = selectionModel->selectedRows();
+ removeClient(indexes);
+}
+
+void ConnectionList::removeClient(QModelIndexList indexes)
+{
+
+ QModelIndex index;
+
+ foreach(index, indexes)
+ {
+ int row = currentIndex().row();
+ QString current = model->index(row, 0).data(Qt::DisplayRole).toString();
+ removeClientToList(current);
+ model->removeRow(row, QModelIndex());
+ }
+}
+
+std::list<QString>* ConnectionList::getSelectedClients(bool isClickOnWindow)
+{
+
+ std::list<QString>* currentList = new std::list<QString>;
+
+
+ QTableView *temp = static_cast<QTableView*>(this);
+ QItemSelectionModel *selectionModel = temp->selectionModel();
+ QModelIndexList indexes = selectionModel->selectedIndexes();
+ QModelIndex index;
+ if (indexes.size() > 0)
+ {
+ foreach (index, indexes)
+ {
+ QString current = model->index(index.row(), 1).data(Qt::DisplayRole).toString();
+ currentList->push_back(current);
+ }
+ }
+
+ return currentList;
+}
+
+void ConnectionList::setProjectProporties(QString source)
+{
+ projSourceName = source; // The source for this projection
+ sourceList.append(source); // The list for all source in pvsmgr
+}
+
+QList<QString> ConnectionList::getTargetToDisplay(QString source)
+{
+ displayList.clear();
+ projectList.clear();
+
+ for (int i=0; i<model->rowCount(QModelIndex()); i++)
+ {
+ QString item = model->index(i, 1, QModelIndex()).data(Qt::DisplayRole).toString();
+ if (item.compare(source) != 0 && !targetList.contains(item) && !sourceList.contains(item))
+ {
+ displayList.append(item);
+ }
+ }
+
+ return displayList;
+
+}
+
+void ConnectionList::addTargetToProjectList(QString name)
+{
+ if (!targetList.contains(name))
+ {
+ projectList.append(name);
+ targetList .append(name);
+ }
+}
+
+QList<QString> ConnectionList::getTargetForTheProject(QString source)
+{
+ QList<QString> target;
+ if(sourceMap.contains(source)){
+ target = sourceMap.value(source);
+ }
+ return target;
+}
+
+
+
+bool ConnectionList::isOnProjection = false;
diff --git a/src/gui/connectionList.h b/src/gui/connectionList.h
new file mode 100644
index 0000000..50d8924
--- /dev/null
+++ b/src/gui/connectionList.h
@@ -0,0 +1,134 @@
+#ifndef _CONNECTIONLIST_H_
+#define _CONNECTIONLIST_H_
+
+#include <QtGui>
+#include <src/core/pvsClient.h>
+#include <QTableView>
+#include <QObject>
+#include <QMap>
+#include <QItemSelection>
+#include <src/gui/mainWindow.h>
+#include <src/gui/dialog.h>
+#include <src/gui/projectionDialog.h>
+
+class PVSClient;
+
+//class QAbstractItemView;
+
+
+/**
+ * The Sidebar showing the connected servers
+ * also used to determine to which connection
+ * contextual actions should be applied
+ */
+
+class QVBoxLayout;
+class QSortFilterProxyModel;
+class QAbstractItemModel;
+class QAbstractItemView;
+class QItemSelectionModel;
+class MainWindow;
+class Dialog;
+class ProjectionDialog;
+//class ConnectionList;
+
+class ConnectionList: public QTableView
+{
+ Q_OBJECT
+
+public:
+ ConnectionList(QWidget *parent=0);
+ ~ ConnectionList();
+
+ void onAddClient(PVSClient* newConnection); // called if a new connection is added
+ void onUpdateClient(PVSClient* newConnection); // update the username*/
+ void addClientToList(QString clientname);
+ void onRemoveClient(PVSClient* newCon);
+ void removeClientToList(QString clientname);
+ QList<QString> getClientist()
+ {
+ return _clientNames;
+ };
+ // void updateAllClients();
+ bool useUserName();
+ bool useUserName(bool use);
+ QList<QString> projectList;
+ QList<QString> targetList;
+ QList<QString> displayList;
+ QList<QString> sourceList;
+ QMap<QString, QList<QString> > sourceMap;
+ QString projSourceName;
+ std::list<QString>* getSelectedClients(bool isClickOnWindow=false); // returns the currently selected clients
+ //void setTargetToDisplay(QString source); // return the list for the projection
+ void setProjectProporties(QString source);
+ QList<QString> getTargetToDisplay(QString source);
+ void addTargetToProjectList(QString name);
+ QList<QString> getTargetForTheProject(QString source);
+ QList<QString>getTargetToProject()
+ {
+ return projectList;
+ }
+ // void removeFromList(PVSConnection* newConnection); // called if a connection is removed
+ // void setMultipleSelection(bool on);
+
+ QAbstractItemModel *model;
+
+private:
+ QItemSelectionModel *_selectionModel;
+ QList<QString> _clientNames;
+
+ int clientindex; //Index of clientname in the list.
+
+ static bool isOnProjection;
+
+ QMenu *_popupMenu; // in der PopupMenu
+ /*Die Aktionen in der PopupMenu*/
+ /* QAction *a1 ;
+ QAction *a2 ;
+ QAction *a3 ;*/
+ QAction *_lockClient ;
+ QAction *_uLockClient ;
+ /*QAction *invertlockClient ;
+ QAction *LockAllClient ;
+ QAction *uLockAllClient ;*/
+ QAction *_msgLockClient ;
+ QAction *_msgLockAllClient ;
+ QAction *_msgClient ;
+ QAction *_project ;
+ QAction *_uproject ;
+ // QAction *rHelp ;
+
+ void preparePopup();
+ void unproject(QString source);
+ QAction* createToolbarButton(const QString &name, const char *slot);
+
+public slots:
+ //Signal handlers:
+
+ virtual void on_projection();
+ virtual void on_unprojection();
+ virtual void on_lock();
+ virtual void on_unlock();
+ virtual void on_message();
+ virtual void on_lock_with_message();
+ virtual void on_lock_all_with_message();
+ virtual void on_lock_all();
+ virtual void on_unlock_all();
+ virtual void on_unproject_all();
+ virtual void on_lock_invert();
+ virtual void on_remoteHelp();
+ void on_vnc_add();
+ void on_vnc_remove();
+ void on_removeClient();
+ void removeClient(QModelIndexList indexes);
+ /*virtual void on_menu_file_remove_connection();*/
+
+signals:
+ void selectionChanged (const QItemSelection &selected);
+
+protected:
+ bool _useUserName;
+ virtual void mouseReleaseEvent (QMouseEvent * e );
+};
+
+#endif
diff --git a/src/gui/connectionWindow.cpp b/src/gui/connectionWindow.cpp
new file mode 100644
index 0000000..cf51051
--- /dev/null
+++ b/src/gui/connectionWindow.cpp
@@ -0,0 +1,763 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # -----------------------------------------------------------------------------
+ # src/gui/connectionWindow.cpp
+ # -----------------------------------------------------------------------------
+ */
+
+#include "connectionWindow.h"
+#include <src/core/pvsConnectionManager.h>
+#include <src/gui/mainWindow.h>
+
+ConnectionWindow::ConnectionWindow(QWidget *parent) :
+ QWidget(parent) {
+
+ //initialize the position for the frame in the clientView
+ posX = 4;
+ posY = 4;
+
+ _closeupFrame = NULL;
+ hasDozent = false; // at the begin we don't have a dozent machine
+
+ QPalette newPalette = palette();
+ newPalette.setColor(QPalette::Window, Qt::white);
+ setPalette(newPalette);
+
+ newDummy = new QAction(tr("&Add a dummy..."), this); // set a dummy
+ connect(newDummy, SIGNAL(triggered()), this, SLOT(addDummy()));
+
+ menu = new QMenu(this);
+ menu->addAction(newDummy);
+
+ setAcceptDrops(true); //drag&drop should be enabled
+}
+
+ConnectionWindow::~ConnectionWindow() {
+ //
+}
+
+void ConnectionWindow::addFrame(ConnectionFrame *cF) {
+ bool found = false;
+ foreach (ConnectionFrame* cFr, AllFrameOnWindow)
+ {
+ if (QString::compare(cF->getTaskbarTitle(), cFr->getTaskbarTitle(), Qt::CaseInsensitive) == 0)
+ {
+ QPoint cuP = currentPosition(cFr);
+ cF->move(cuP);
+ AllFrameOnWindow.append(cF);
+ AllFrameOnWindow.removeOne(cFr); //we don't need this dummy any more
+ cFr->deleteLater();
+ found = true;
+ return;
+ }
+ }
+
+ /* If the Frame don't belong to the profile
+ * we have to move it at the default position for now.
+ * The user can move this later to his favorite position.
+ */
+ if (!found)
+ {
+ foreach (clientLocation cur, ClientLocationList)
+ {
+ if (QString::compare(cF->getTaskbarTitle(), cur.first, Qt::CaseInsensitive) == 0)
+ {
+ cF->move(cur.second);
+ found = true;
+ return;
+ }
+ }
+ }
+
+ if (!found)
+ cF->move(10, 10);
+}
+
+void ConnectionWindow::addFrameBySettings(QString client, QPoint pos) {
+ clientLocation cur(client, pos);
+ ClientLocationList.append(cur);
+}
+
+void ConnectionWindow::showFrameFromSettings() {
+ foreach (clientLocation cur, ClientLocationList)
+ {
+ ConnectionFrame* dummy = new ConnectionFrame(
+ MainWindow::getConnectionWindow());
+ AllFrameOnWindow.append(dummy);
+ dummy->setTheTitle("[No name]");
+ dummy->setTaskbarTitle(cur.first);
+ dummy->setDummy(true);
+ dummy->move(cur.second);
+ }
+}
+
+void ConnectionWindow::addDummy() { //function to add a dummy
+ ConnectionFrame* dummy = new ConnectionFrame(
+ MainWindow::getConnectionWindow());
+ dummy->setTheTitle("[No name]");
+ dummy->setTaskbarTitle("[0.0.0.0]");
+ QPoint p = QPoint(10, 10);//the default move position, when created a dummy screen
+ AllFrameOnWindow.append(dummy);
+ clientLocation cur("[No name]", p);
+ ClientLocationList.append(cur);
+ dummy->setDummy(true);
+ dummy->move(p);
+ dummy->setStyleSheet(QString::fromUtf8(
+ "background-color: rgb(150, 150, 168);"));
+}
+
+void ConnectionWindow::mousePressEvent(QMouseEvent *event) { //catch the mouse press event
+ if (event->button() == Qt::RightButton)
+ menu->exec(QCursor::pos());
+}
+
+QPoint ConnectionWindow::currentPosition(ConnectionFrame* cF) {
+ QPoint pos = QPoint(10, 10);
+ clientLocation cur;
+ foreach (cur, ClientLocationList)
+ {
+ if (QString::compare(cF->getTaskbarTitle(), cur.first, Qt::CaseInsensitive) == 0)
+ return cur.second;
+ }
+ return pos;
+}
+
+int ConnectionWindow::itemAt(ConnectionFrame* cf)
+{
+ for (int i = AllFrameOnWindow.size() - 1; i >= 0; --i)
+ {
+ ConnectionFrame* item = AllFrameOnWindow.at(i);
+ if (cf->pos().x() == item->pos().x() && cf->pos().y() == item->pos().y())
+ return i;
+ }
+ return -1;
+}
+
+void ConnectionWindow::removeFromList(ConnectionFrame* cF) {
+ //dummyList.removeOne(cF);
+ if(AllFrameOnWindow.contains(cF))
+ AllFrameOnWindow.removeOne(cF);
+ cF->deleteLater();
+}
+
+void ConnectionWindow::onChangeConnections() {
+
+ //clear the view
+ if (!frameList.empty()) {
+ ConnectionFrame* tmpIt;
+ foreach (tmpIt, frameList)
+ {
+ if (tmpIt != currentSingleFrame)
+ tmpIt->setActive(false);
+ tmpIt->hide();
+ }
+ }
+
+}
+
+bool ConnectionWindow::projectStations(QString sname) {
+ QString password, hostname;
+ int port, quality;
+ ConsoleLog writeLine(QString("Projecting from: ").append(sname));
+ //TODO add method parameter for this
+ quality = 0;
+
+ QList<QString> projectList =
+ MainWindow::getConnectionList()->getTargetForTheProject(sname);
+
+ if (!projectList.isEmpty()) {
+ PVSClient* tmpSrcConnection =
+ PVSConnectionManager::getManager()->getClientFromIp(sname);
+ if (tmpSrcConnection) {
+ if (!tmpSrcConnection->getVNCAllowed()) {
+ ConsoleLog writeError(QString("VNC is not allowed on Projection Source: ").append(sname));
+ ConsoleLog writeError(QString("Trying to start VNC-Server on Client: ").append(sname));
+ tmpSrcConnection->setProject(true);
+ return false;
+ }
+ password = tmpSrcConnection->getPassword();
+ port = tmpSrcConnection->getPort();
+ hostname = sname;
+ tmpSrcConnection->getConnectionFrame()->setSource();
+ ConsoleLog writeError (QString("port: ").append(int2String(port)));
+ ConsoleLog writeError (QString("passwort: ").append(password));
+ ConsoleLog writeError (QString("pr-sourcename: ").append(sname));
+
+ }
+ else
+ {
+ return false;
+ }
+
+ ConsoleLog writeError (QString("port as int: ").append(port));
+ ConsoleLog writeError (QString("port as String: ").append(int2String(port)));
+
+ QString item;
+ foreach (item, projectList)
+ {
+ PVSClient* tmpConnection = PVSConnectionManager::getManager()->getClientFromIp(item);
+ if (tmpConnection)
+ {
+ ConsoleLog writeError (QString("sending vnc data to: ").append(tmpConnection->getIp()));
+ tmpConnection->sendMessage(PVSCOMMAND,"PROJECT", hostname + " " + int2String(port) + " " + password + " " + int2String(quality));
+ tmpConnection->getConnectionFrame()->setTarget();
+ }
+ else
+ {
+ // scream in agony
+ }
+ }
+ }
+ return true;
+}
+
+bool ConnectionWindow::remoteHelp(QString sname) {
+
+ //TODO Finish this...
+ QString password, hostname;
+ int port;
+
+ PVSClient* tmpSrcConnection =
+ PVSConnectionManager::getManager()->getClientFromIp(sname);
+ QList<QString> projectList =
+ MainWindow::getConnectionList()->getTargetForTheProject(sname);
+ if (tmpSrcConnection) {
+ if (!tmpSrcConnection->getVNCAllowed()) {
+ tmpSrcConnection->requestVNCConnect();
+ tmpSrcConnection->setProject(true);
+ return false;
+ }
+ password = tmpSrcConnection->getRWPassword();
+ port = tmpSrcConnection->getPort();
+ hostname = sname;
+ tmpSrcConnection->getConnectionFrame()->setSource();
+ } else {
+ return false;
+ }
+
+ QString item;
+ foreach (item, projectList)
+ {
+ PVSClient
+ * tmpConnection =
+ PVSConnectionManager::getManager()->getClientFromIp(item);
+ if (tmpConnection) {
+ ConsoleLog writeError(QString("sending vnc data to: ").append(
+ tmpConnection->getIp()));
+ tmpConnection->sendMessage(PVSCOMMAND, "PROJECT", hostname
+ + " " + int2String(port) + " " + password);
+ tmpConnection->getConnectionFrame()->setTarget();
+ } else {
+ // scream in agony
+ }
+ }
+ return true;
+
+}
+
+
+
+bool ConnectionWindow::lockStations() {
+ if (std::list<QString>* lockList = MainWindow::getConnectionList()->getSelectedClients()) {
+ if (!lockList->empty()) {
+ for (std::list<QString>::iterator tmpIt = lockList->begin(); tmpIt
+ != lockList->end(); tmpIt++) {
+ PVSClient
+ * tmpConnection =
+ PVSConnectionManager::getManager()->getClientFromIp(
+ (*tmpIt).toUtf8().data());
+ if (tmpConnection->getConnectionFrame()->getFrame())
+ {
+ // we don't want to lock the dozent machine
+ if (tmpConnection && !tmpConnection->getConnectionFrame()->getFrame()->isDozent()
+ && !tmpConnection->getConnectionFrame()->isOnProjekt())
+ lockStation(tmpConnection);
+ else {
+ // scream in agony
+ }
+ }
+ }
+ }
+ delete lockList;
+ }
+ return true;
+}
+
+void ConnectionWindow::lockStation(PVSClient* pvsCon) {
+ if (pvsCon->getVNCConnection())
+ {
+ pvsCon->getConnectionFrame()->getFrame()->setLockStatus(true);
+ // we call the update to force Qt to paint the lockicon on the frame
+ pvsCon->getConnectionFrame()->getFrame()->update();
+ pvsCon->sendMessage(PVSCOMMAND, "LOCKSTATION", "");
+ }
+}
+
+bool ConnectionWindow::unlockStations() {
+ if (std::list<QString>* unlockList = MainWindow::getConnectionList()->getSelectedClients()) {
+ if (!unlockList->empty()) {
+ for (std::list<QString>::iterator tmpIt = unlockList->begin(); tmpIt
+ != unlockList->end(); tmpIt++) {
+ PVSClient
+ * tmpConnection =
+ PVSConnectionManager::getManager()->getClientFromIp(
+ (*tmpIt).toUtf8().data());
+ if (tmpConnection && tmpConnection->getConnectionFrame()->getFrame() &&
+ tmpConnection->getVNCConnection()) {
+ tmpConnection->getConnectionFrame()->getFrame()->setLockStatus(false);
+ tmpConnection->getConnectionFrame()->getFrame()->update(); // we call the update to force Qt to paint the lock on the frame
+ tmpConnection->sendMessage(PVSCOMMAND, "UNLOCKSTATION", "");
+ } else {
+ // scream in agony
+ }
+ }
+ }
+ delete unlockList;
+ }
+ return true;
+}
+
+void ConnectionWindow::unlockStation(PVSClient* pvsCon) {
+ if (pvsCon->getVNCConnection())
+ {
+ pvsCon->getConnectionFrame()->getFrame()->setLockStatus(false);
+ // we call the update to force Qt to paint the lockicon on the frame
+ pvsCon->getConnectionFrame()->getFrame()->update();
+ pvsCon->sendMessage(PVSCOMMAND, "UNLOCKSTATION", "");
+ }
+}
+
+bool ConnectionWindow::lockAllStations()
+{
+ if (!hasDozent)
+ {
+ QString message = QString(tr("You have to set a Superclient-machine before performing this action."));
+ QMessageBox::information(this, "PVS", message);
+ return false;
+ }
+ std::list<PVSClient*> listAll =
+ PVSConnectionManager::getManager()->getConnections();
+ for (std::list<PVSClient*>::iterator it = listAll.begin(); it
+ != listAll.end(); it++)
+ {
+ if (*it == NULL || (*it)->getConnectionFrame() == NULL) continue;
+ // we don't want to lock the superclient machine
+ if ((*it)->getConnectionFrame()->getFrame() &&
+ !(*it)->getConnectionFrame()->getFrame()->isDozent() &&
+ (*it)->getVNCConnection())
+ (*it)->sendMessage(PVSCOMMAND, "LOCKSTATION", "");
+ else if (!(*it)->getConnectionFrame()->getFrame())
+ ConsoleLog writeError(QString("The Frame connection from client: ").
+ append((*it)->getConnectionFrame()->getTaskbarTitle()).
+ append(QString(" is corrupted. Reconned the client it again.")));
+ }
+ return true;
+}
+
+bool ConnectionWindow::unlockAllStations() {
+ std::list<PVSClient*> listAll =
+ PVSConnectionManager::getManager()->getConnections();
+ for (std::list<PVSClient*>::iterator it = listAll.begin(); it
+ != listAll.end(); it++)
+ {
+ if ((*it)->getVNCConnection())
+ {
+ (*it)->getConnectionFrame()->getFrame()->setLockStatus(false);
+ (*it)->getConnectionFrame()->getFrame()->update(); // we call the update to force Qt to repaint the frame
+ (*it)->sendMessage(PVSCOMMAND, "UNLOCKSTATION", "");
+ }
+ // otherwise this will get scattered all over the place
+ }
+ return true;
+}
+
+bool ConnectionWindow::unprojectStations(QString sname) {
+ PVSClient* tmpConnection =
+ PVSConnectionManager::getManager()->getClientFromIp(sname);
+ if (tmpConnection && tmpConnection->getVNCConnection()) {
+ tmpConnection->sendMessage(PVSCOMMAND, "UNPROJECT", "");
+ tmpConnection->getConnectionFrame()->setUnproject();
+ } else {
+ // scream in agony
+ }
+
+ return true;
+}
+
+bool ConnectionWindow::unprojectAllStations() {
+ std::list<PVSClient*> listAll =
+ PVSConnectionManager::getManager()->getConnections();
+ for (std::list<PVSClient*>::iterator it = listAll.begin(); it
+ != listAll.end(); it++)
+ {
+ if ((*it)->getVNCConnection())
+ {
+ (*it)->sendMessage(PVSCOMMAND, "UNPROJECT", "");
+ (*it)->getConnectionFrame()->setUnproject();
+ }
+ }
+ return true;
+}
+
+bool ConnectionWindow::lockInvertStations() {
+ // ok, this method is highly imperformant i guess
+ // we're going thru all existing connections, and if they dont equal one of the selected (another loop)
+ // we lock them...
+ if (std::list<QString>* lockList = MainWindow::getConnectionList()->getSelectedClients()) {
+ std::list<PVSClient*> listAll =
+ PVSConnectionManager::getManager()->getConnections();
+ bool skip = false;
+ for (std::list<PVSClient*>::iterator it = listAll.begin(); it
+ != listAll.end(); it++) {
+ if (!lockList->empty()) {
+ for (std::list<QString>::iterator tmpIt = lockList->begin(); tmpIt
+ != lockList->end(); tmpIt++) {
+ PVSClient
+ * tmpConnection =
+ PVSConnectionManager::getManager()->getClientFromIp(
+ (*tmpIt).toUtf8().data());
+ if (tmpConnection == (*it)) {
+ skip = true;
+ break;
+ }
+ }
+ }
+ if (!skip)
+ (*it)->sendMessage(PVSCOMMAND, "LOCKSTATION", "");//TODO define some standard to grab this from...
+ // otherwise this will get scattered all over the place
+ }
+ delete lockList;
+ }
+ return true;
+}
+
+void ConnectionWindow::lockInvertStation(PVSClient* pvsCon) {
+ pvsCon->sendMessage(PVSCOMMAND, "LOCKSTATION", "");
+}
+
+bool ConnectionWindow::messageStations(QString ident, QString message) {
+ if (std::list<QString>* messageList = MainWindow::getConnectionList()->getSelectedClients()) {
+ if (!messageList->empty()) {
+ for (std::list<QString>::iterator tmpIt = messageList->begin(); tmpIt
+ != messageList->end(); tmpIt++) {
+ PVSClient
+ * tmpConnection =
+ PVSConnectionManager::getManager()->getClientFromIp(
+ (*tmpIt).toUtf8().data());
+ // we don't want to lock the dozent machine
+ if (tmpConnection && tmpConnection->getConnectionFrame()->getFrame() &&
+ !tmpConnection->getConnectionFrame()->getFrame()->isDozent())
+ {
+ messageStation(ident, message, tmpConnection);
+ } else {
+ // scream in agony
+ }
+ }
+ }
+ delete messageList;
+ }
+ return true;
+}
+
+void ConnectionWindow::messageStation(QString ident, QString message,
+ PVSClient* pvsCon) {
+ pvsCon->sendMessage(PVSMESSAGE, ident, message);
+}
+
+bool ConnectionWindow::lockStationsWithMessage(QString message)
+{
+ if (!hasDozent)
+ {
+ QString message = QString(tr("You have to set a Superclient-machine before performing this action."));
+ QMessageBox::information(this, "PVS", message);
+ return false;
+ }
+ if (std::list<QString>* messageList = MainWindow::getConnectionList()->getSelectedClients()) {
+ if (!messageList->empty()) {
+ for (std::list<QString>::iterator tmpIt = messageList->begin(); tmpIt
+ != messageList->end(); tmpIt++) {
+ PVSClient
+ * tmpConnection =
+ PVSConnectionManager::getManager()->getClientFromIp(
+ (*tmpIt).toUtf8().data());
+ // we don't want to lock the dozent machine
+ if (tmpConnection && !tmpConnection->getConnectionFrame()->getFrame()->isDozent())
+ {
+ lockStationsWithMessage(message, tmpConnection);
+
+ } else {
+ // scream in agony
+ }
+ }
+ }
+ delete messageList;
+ }
+ return true;
+}
+
+void ConnectionWindow::lockStationsWithMessage(QString message,
+ PVSClient* pvsCon)
+{
+ pvsCon->sendMessage(PVSCOMMAND, "LOCKSTATION", message);
+}
+
+bool ConnectionWindow::lockAllStationsWithMessage(QString message) {
+
+ if (!hasDozent)
+ {
+ QString message = QString(tr("You have to set a Superclient-machine before performing this action."));
+ QMessageBox::information(this, "PVS", message);
+ return false;
+ }
+ std::list<PVSClient*> listAll =
+ PVSConnectionManager::getManager()->getConnections();
+ for (std::list<PVSClient*>::iterator it = listAll.begin(); it
+ != listAll.end(); it++)
+ {
+ if ((*it) && !(*it)->getConnectionFrame()->getFrame()->isDozent()) // we don't want to lock the dozent machine
+ (*it)->sendMessage(PVSCOMMAND, "LOCKSTATION", message);
+ }
+ return true;
+}
+
+void ConnectionWindow::addConnection(PVSClient* newCon) {
+ if (newCon) {
+ // QList<QString> ClientList= MainWindow::getConnectionList()->getClientist();
+
+ //Check if this client already in the list, before we add it.
+ //We don't want to have two clients with the same names.
+ //We comments it for test.
+ /*if (!ClientList.contains(newCon->getHostString()))
+ {*/
+ onVNCAdd(newCon);
+ MainWindow::getConnectionList()->onAddClient(newCon);
+ /*
+ * We check if the pvsmgr run a lockAll on the already connected
+ * clients. If yes, we lock the new conencted client too.
+ */
+ if (MainWindow::getWindow()->isLockAllStatus() && newCon->getConnectionFrame()->getFrame())
+ {
+ newCon->getConnectionFrame()->getFrame()->setLockStatus(true);
+ // we call the update to force Qt to paint the lockicon on the frame
+ newCon->getConnectionFrame()->getFrame()->update();
+ lockStation(newCon);
+ }
+ //}
+ }
+}
+
+void ConnectionWindow::removeConnection(PVSClient* newCon) {
+ if (newCon == NULL) return;
+ ConnectionFrame* frame = newCon->getConnectionFrame();
+ if (frame != NULL)
+ {
+ removeFromList(frame);
+ //frame->deleteLater();
+ }
+ MainWindow::getConnectionList()->onRemoveClient(newCon);
+}
+
+void ConnectionWindow::onView() {
+ if (std::list<QString>* selectedClient = MainWindow::getConnectionList()->getSelectedClients()) {
+ if (!selectedClient->empty()) {
+ if (selectedClient->size() == 1)
+ ;//TODO
+
+ }
+ }
+}
+
+void ConnectionWindow::updateConnection(PVSClient* newCon) {
+ if (newCon) {
+ MainWindow::getConnectionList()->onUpdateClient(newCon);
+ }
+}
+
+void ConnectionWindow::addVNC() {
+ if (std::list<QString>* vncAddList = MainWindow::getConnectionList()->getSelectedClients()) {
+ if (!vncAddList->empty()) {
+ for (std::list<QString>::iterator tmpIt = vncAddList->begin(); tmpIt
+ != vncAddList->end(); tmpIt++) {
+ PVSClient
+ * tmpConnection =
+ PVSConnectionManager::getManager()->getClientFromIp(
+ (*tmpIt).toUtf8().data());
+ if (tmpConnection) {
+ tmpConnection->requestVNCConnect();
+ } else {
+ // scream in agony
+ }
+ }
+ }
+ }
+}
+
+void ConnectionWindow::onVNCAdd(PVSClient* newCon) {
+
+ if (!newCon->getConnectionFrame()) {
+ ConnectionFrame* newFrame = newConFrame(newCon);
+ newFrame->setConnection(newCon);
+ newFrame->setTaskbarTitle(newFrame->getTaskbarTitle());
+ newFrame->setDummy(false);
+ newFrame->setFrameRate(500);
+ addFrame(newFrame);
+ if (!frameList.contains(newFrame))
+ frameList.append(newFrame);
+ if (!AllFrameOnWindow.contains(newFrame))
+ AllFrameOnWindow.append(newFrame);
+ newFrame->show();
+ } else
+ // now we have already a pvsconnection, we should set the existing vncconnection to it
+ newCon->getConnectionFrame()->setConnection(newCon);
+ // addFrame(newFrame);
+}
+
+void ConnectionWindow::removeVNC() {
+ std::list<QString>* vncRemoveList =
+ MainWindow::getConnectionList()->getSelectedClients();
+
+ // if(!vncRemoveList->empty())
+ // {
+ for (std::list<QString>::iterator tmpIt = vncRemoveList->begin(); tmpIt
+ != vncRemoveList->end(); tmpIt++) {
+ PVSClient* tmpConnection =
+ PVSConnectionManager::getManager()->getClientFromIp(
+ (*tmpIt).toUtf8().data());
+ if (tmpConnection) {
+ if (tmpConnection->getVNCConnection()) {
+ ConnectionFrame* tmpFrame =
+ tmpConnection->getVNCConnection()->getFrame();
+ if (tmpFrame) {
+ frameList.removeOne(tmpFrame);
+ onChangeConnections();
+ tmpFrame->setConnection(NULL);
+ tmpFrame->initFrame();
+ //delete tmpFrame;
+ }
+ tmpConnection->shutDownVNC();
+ }
+ } else {
+ // scream in agony
+ }
+ }
+ //
+ // }
+}
+
+void ConnectionWindow::onRemoveConnection() {
+ if (std::list<QString>* removeList = MainWindow::getConnectionList()->getSelectedClients()) {
+ if (!removeList->empty()) {
+ for (std::list<QString>::iterator tmpIt = removeList->begin(); tmpIt
+ != removeList->end(); tmpIt++) {
+ PVSClient
+ * tmpConnection =
+ PVSConnectionManager::getManager()->getClientFromIp(
+ (*tmpIt).toUtf8().data());
+ if (tmpConnection) {
+ // removal should start from the CM, so hes linking back to the ConnectionWindow::onConnectionRemoved() method
+ // to finish the removal procedure here
+ PVSConnectionManager::getManager()->removeConnection(
+ tmpConnection);
+ } else {
+ // scream in agony
+ }
+ }
+ // onChangeConnections();
+ }
+ delete removeList;
+ return;
+ }
+}
+
+void ConnectionWindow::onConnectionRemoved(PVSClient* newConnection) {
+
+
+ if (newConnection->getVNCConnection())
+
+ // check for associated frames!
+ if (newConnection->getVNCConnection()) {
+ ConnectionFrame* tmpFrame =
+ newConnection->getVNCConnection()->getFrame();
+ // now handle the case that the client disconnects while we are in fullscreen mode
+ // the vncconnection would be cut nevertheless, so this:
+ if (tmpFrame) {
+ frameList.removeOne(tmpFrame);
+ // now handle the case that the client disconnects while we are in fullscreen mode
+ // the vncconnection would be cut nevertheless, so this:
+ if (tmpFrame == currentSingleFrame) {
+ currentSingleFrame = NULL;
+ }
+
+ // no longer needed
+ delete tmpFrame;
+ newConnection->getVNCConnection()->setFrame(NULL);
+ }
+ }
+}
+
+void ConnectionWindow::setSize(int width, int height, bool forceSquare) {
+ if (height >= 100 && width >= 100) {
+ MainWindow::getWindow()->setPrevWidth(width);
+ MainWindow::getWindow()->setPrevHeight(height);
+ }
+
+ ignoreRatio = forceSquare;
+
+ if (!frameList.empty()) {
+ ConnectionFrame* item;
+ foreach (item, frameList)
+ {
+ item->setIgnoreRatio(ignoreRatio);
+ }
+ }
+}
+
+void ConnectionWindow::getCloseupSize(int &width, int &height) {
+ if (!onCloseup) {
+ width = height = 0;
+ return;
+ }
+
+ width = 150;
+ height = 150;
+}
+
+bool ConnectionWindow::getShowDummies() {
+ return _showDummies;
+}
+
+void ConnectionWindow::setShowDummies(bool show) {
+
+}
+
+ConnectionFrame* ConnectionWindow::newConFrame(PVSClient* newConnection) {
+ if (newConnection->getConnectionFrame()) {
+ return NULL;
+ }
+ ConnectionFrame* temp = new ConnectionFrame(
+ MainWindow::getConnectionWindow());
+ if (!temp) {
+ return NULL;
+ }
+ return temp;
+}
+
+void ConnectionWindow::setCloseupFrame(ConnectionFrame* cFrame) {
+ _closeupFrame = cFrame;
+}
+
+ConnectionFrame* ConnectionWindow::getCloseupFrame() {
+ if (_closeupFrame)
+ return _closeupFrame;
+
+ return NULL;
+}
+
diff --git a/src/gui/connectionWindow.h b/src/gui/connectionWindow.h
new file mode 100644
index 0000000..81b5033
--- /dev/null
+++ b/src/gui/connectionWindow.h
@@ -0,0 +1,125 @@
+#ifndef _CONNECTIONWINDOW_H_
+#define _CONNECTIONWINDOW_H_
+
+#include <QtGui>
+#include <src/gui/connectionFrame.h>
+#include <src/gui/connectionList.h>
+#include <src/gui/mainWindow.h>
+#include <list>
+#include <iostream>
+#include <math.h>
+#include <QSettings>
+#define FRAME_DELAY 1000 // to comply with the standard value in the gui
+
+
+typedef std::pair<QString, QPoint> clientLocation;
+typedef QList<clientLocation> clientLocationList;
+
+class ConnectionList;
+class PVSClient;
+class PVSConnectionManager;
+class MainWindow;
+class ConnectionFrame;
+class QDragEnterEvent;
+class QDropEvent;
+
+
+class ConnectionWindow : public QWidget
+{
+ Q_OBJECT
+public:
+ enum FILLORDER
+ {
+ ROW,
+ COLUMN,
+ SQUARE,
+ };
+
+ enum VIEWSTYLE
+ {
+ FULLSCREEN,
+ TABLE,
+ };
+
+
+
+ ConnectionWindow(QWidget *parent=0);
+ ~ConnectionWindow();
+ void addFrame(ConnectionFrame *conFrame);
+ void addFrameBySettings(QString client, QPoint pos);
+ void showFrameFromSettings();
+ void onChangeConnections(); // if connections are added or removed, this method makes sure the window changes accordingly
+ void addConnection(PVSClient* newCon); // handle newly connected clients (forward to con-list)
+ void removeConnection(PVSClient* newCon); // Remove client on disconnect
+ void onView();
+ void updateConnection(PVSClient* newCon); // update stuff like username etc on a present connection
+ void addVNC();
+ void onVNCAdd(PVSClient* newCon);
+ void removeVNC();
+ void onRemoveConnection(); // tells the PVSConnectionManager to remove the connections that are marked in the sidebar
+ void onConnectionRemoved(PVSClient* newConnection); // does some cleanup and tells the gui elements that this connection is removed
+ void setSize(int width, int height, bool forceSquare); // tell the frames to use this size settings
+ void getCloseupSize(int &width, int &height);
+ bool getShowDummies();
+ void setShowDummies(bool show);
+ QList<ConnectionFrame*> dummyList;
+ QList<ConnectionFrame*> AllFrameOnWindow;
+ QList<ConnectionFrame*> getAllFrameOnWindow()
+ {
+ return AllFrameOnWindow;
+ }
+ void removeFromList(ConnectionFrame* cF);
+
+ bool remoteHelp(QString sname);
+ bool projectStations(QString sname);
+ bool unprojectStations(QString sname);
+ bool lockStations();
+ void lockStation(PVSClient* pvsCon);
+ bool unlockStations();
+ void unlockStation(PVSClient* pvsCon);
+ bool lockAllStations();
+ bool unlockAllStations();
+ bool unprojectAllStations();
+ bool lockInvertStations();
+ void lockInvertStation(PVSClient* pvsCon);
+ bool messageStations(QString ident, QString message);
+ void messageStation(QString ident, QString message, PVSClient* pvsCon);
+ bool lockStationsWithMessage(QString message);
+ void lockStationsWithMessage(QString message, PVSClient* pvsCon);
+ bool lockAllStationsWithMessage(QString message);
+
+ void setCloseupFrame(ConnectionFrame* cFrame);
+ int itemAt(ConnectionFrame* cf);
+ ConnectionFrame* getCloseupFrame();
+ QList<ConnectionFrame*> getFrameList(){ return frameList; };
+ clientLocationList ClientLocationList;
+ bool hasDozent; //if a Dozent machine is available this will be set to true else false
+ //Frame position in the window
+ int posX;
+ int posY;
+
+public Q_SLOTS:
+ void addDummy();
+
+
+protected:
+ QList<ConnectionFrame*> frameList; // list of all connected frames
+ void mousePressEvent(QMouseEvent *event);
+
+private:
+ ConnectionFrame* newConFrame(PVSClient* newConnection); // returns a new frame for the given connection
+ ConnectionFrame* currentSingleFrame; // pointer to the frame thats currently in FullScreen
+ ConnectionFrame* _closeupFrame;
+ QPoint currentPosition (ConnectionFrame* cF);
+ QMenu *menu;
+ QAction *newDummy;
+ bool ignoreRatio; // wether the native ratio should be ignored or not
+ bool onFullscreen; // wether on fullscreen or not
+ bool onCloseup; // wether on closeup or not
+ int defaultWidth, defaultHeight; // obvious
+ unsigned int frameRate; // also obvious*/
+ bool _showDummies;
+
+};
+
+#endif
diff --git a/src/gui/dialog.cpp b/src/gui/dialog.cpp
new file mode 100644
index 0000000..3c9b7a2
--- /dev/null
+++ b/src/gui/dialog.cpp
@@ -0,0 +1,74 @@
+/*
+# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+# -----------------------------------------------------------------------------
+# dialog.cpp
+ Dialog to get message to send to client
+# -----------------------------------------------------------------------------
+*/
+
+#include "dialog.h"
+#include "ui_dialog.h"
+#include <src/gui/mainWindow.h>
+
+Dialog::Dialog(QWidget *parent) :
+ QDialog(parent),
+ dui(new Ui::MsgDialog)
+{
+ dui->setupUi(this);
+
+ dui->send->setDisabled(true);
+
+ setWindowTitle(tr("Enter the Text for the client(s)"));
+
+ connect( dui->send, SIGNAL( clicked()), this, SLOT( send()));
+ connect( dui->cancel, SIGNAL( clicked()), this, SLOT( NotSend()));
+ connect(dui->message, SIGNAL(textChanged()), this, SLOT(textchange()));
+}
+
+Dialog::~Dialog()
+{
+ delete dui;
+}
+
+void Dialog::send()
+{
+ QString mesge = dui->message->toPlainText();
+ MainWindow::getWindow()->setMsgDialog(mesge);
+ dui->message->clear();
+ emit accept();
+}
+
+void Dialog::NotSend()
+{
+ dui->message->clear();
+ emit reject();
+}
+
+void Dialog::textchange()
+{
+ QString message = dui->message->toPlainText();
+ if(message.length()>0)
+ dui->send->setDisabled(false);
+ else
+ dui->send->setDisabled(true);
+}
+
+void Dialog::changeEvent(QEvent *e)
+{
+ QDialog::changeEvent(e);
+ switch (e->type()) {
+ case QEvent::LanguageChange:
+ dui->retranslateUi(this);
+ break;
+ default:
+ break;
+ }
+}
diff --git a/src/gui/dialog.h b/src/gui/dialog.h
new file mode 100644
index 0000000..689cbb4
--- /dev/null
+++ b/src/gui/dialog.h
@@ -0,0 +1,33 @@
+#ifndef DIALOG_H
+#define DIALOG_H
+
+#include <QDialog>
+#include <QtGui>
+//#include <src/gui/mainWindow.h>
+
+
+namespace Ui {
+ class MsgDialog;
+}
+
+class MainWindow;
+
+class Dialog : public QDialog {
+ Q_OBJECT
+public:
+ Dialog(QWidget *parent = 0);
+ ~Dialog();
+
+protected:
+ void changeEvent(QEvent *e);
+
+private:
+ Ui::MsgDialog *dui;
+
+private slots:
+ void send();
+ void NotSend();
+ void textchange();
+};
+
+#endif // DIALOG_H
diff --git a/src/gui/frame.cpp b/src/gui/frame.cpp
new file mode 100644
index 0000000..cb79643
--- /dev/null
+++ b/src/gui/frame.cpp
@@ -0,0 +1,332 @@
+/*
+# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+# -----------------------------------------------------------------------------
+# src/gui/frame.cpp
+# This is the drawingarea, it will be set to the suitable ConnectionFrame.
+# Each instance of this class has is own VNCThread, this way is more simple
+# to show, update and scale the image from the suitable client. Only the point
+# on the image that need to be drawed or scaled will be processed. Thus the CPU
+# performance will not be affected. The pvsmgr can manage in this way a lot of clients.
+# -----------------------------------------------------------------------------
+*/
+
+#include "frame.h"
+#include <src/gui/mainWindow.h>
+#include <iostream>
+#include <QPixmap>
+
+Frame::Frame(const QString & text, QWidget * parent) :
+ QLabel(parent), _clientVNCThread(0)
+{
+ _clientVNCThread = NULL;
+
+ X = 0;
+ Y = 0;
+ setBackgroundRole(QPalette::Base);
+
+ setStyleSheet(QString::fromUtf8("QLabel{border-radius:10px;\n"
+ "background-color: rgb(150,150,150);}"));
+
+ setAlignment(Qt::AlignCenter);
+
+ setAutoFillBackground(true);
+ setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
+
+ _isLocked = false;
+ _dozent = false;
+ _uy = _ux = 0;
+
+ //QIcon icon;
+ //icon.addFile(QString::fromUtf8(), QSize(), QIcon::Normal, QIcon::Off);
+ button_closeUp = createToolButton(tr("View"), QIcon(":/restore"),SLOT(closeUp()));
+ button_foto = createToolButton(tr("Foto"), QIcon(":/photos"),SLOT(foto()));
+ button_lock = createToolButton(tr("Lock this client"), QIcon(":/lock"),SLOT(setLock()));
+ //button_unlock = createToolButton(tr("Unlock this client"), QIcon(":/lock"),SLOT(setLock()));
+ button_dozent = createToolButton(tr("Set as Superclient"), QIcon(":/dozent2"),SLOT(setDozent()));
+
+ connect(this, SIGNAL(clicked()), this, SLOT(slotClicked()));
+ ip = "";
+ setToolButtonListVisible(false);
+}
+
+Frame::~Frame()
+{
+ if (_clientVNCThread)
+ {
+ disconnect(_clientVNCThread, SIGNAL(imageUpdated(int,int,int,int)), this,
+ SLOT(updateImage(int,int,int,int)));
+ disconnect(_clientVNCThread, SIGNAL(finished()), this,
+ SLOT(iamDown()));
+ if (_clientVNCThread->isRunning())
+ {
+ _clientVNCThread->terminate = true;
+ _clientVNCThread->wait(_clientVNCThread->getUpdatefreq()+2000);
+ }
+ }
+}
+
+
+void Frame::setVNCThreadConnection(VNCClientThread * vncClientThread)
+{
+ // initialize the vncthread for this connection
+ //printf("Starting VNC thread for %s\n", ip.toUtf8().data());
+ _clientVNCThread = vncClientThread;
+
+ connect(_clientVNCThread, SIGNAL(imageUpdated(int,int,int,int)), this,
+ SLOT(updateImage(int,int,int,int)), Qt::BlockingQueuedConnection);
+ connect(_clientVNCThread, SIGNAL(finished()), this,
+ SLOT(iamDown()));
+
+ // start the thread
+ if(!_clientVNCThread->terminate)
+ _clientVNCThread->start();
+}
+
+/*
+ * To stop the vncThreadConnection, we only disconnect all connected signals on _clientVNCThread
+ * We don't need here to terminate the thread, this will appear in vncconnection, because
+ * we have set this thread there (in vncconnection).
+ */
+void Frame::stopVNCThreadConnection()
+{
+ disconnect(_clientVNCThread, SIGNAL(imageUpdated(int,int,int,int)), this,
+ SLOT(updateImage(int,int,int,int)));
+ disconnect(_clientVNCThread, SIGNAL(finished()), this,
+ SLOT(iamDown()));
+}
+
+void Frame::updateImage(int x, int y, int w, int h)
+{
+ if (_clientVNCThread == NULL)
+ return;
+
+ if (_clientVNCThread->getSize() != size())
+ {
+ // grow the update rectangle to avoid artifacts
+ x -= 3;
+ y -= 3;
+ w += 6;
+ h += 6;
+
+ _clientImg = _clientVNCThread->getImage().copy(x, y, w, h);
+
+ qreal sx = qreal(width()) / qreal(_clientVNCThread->getSize().width());
+ qreal sy = qreal(height()) / qreal(_clientVNCThread->getSize().height());
+
+ x = qRound(qreal(x) * sx);
+ y = qRound(qreal(y) * sy);
+ w = qRound(qreal(w) * sx);
+ h = qRound(qreal(h) * sy);
+ }
+ else
+ {
+ _clientImg = _clientVNCThread->getImage().copy(x, y, w, h);
+ }
+
+ _ux = w;
+ _uy = h;
+ repaint(x, y, w, h); // this will trigger the PaintEvent
+}
+
+void Frame::iamDown()
+{
+ if (_clientVNCThread == NULL) return;
+ _clientVNCThread = NULL;
+ update();
+}
+
+void Frame::paintEvent(QPaintEvent *event)
+{
+ QPainter painter(this);
+ QRect r = event->rect();
+ event->accept();
+
+ if (_clientImg.isNull())
+ {
+ _clientImg = QImage(":/terminal");
+ painter.drawImage(28,0, _clientImg.scaled(145,123, Qt::KeepAspectRatio, Qt::SmoothTransformation));
+ setAlignment(Qt::AlignCenter);
+ return;
+ }
+
+ if(_isLocked)
+ {
+ _clientImg = QImage(":/lock");
+ painter.drawImage(28,0, _clientImg.scaled(145,123, Qt::KeepAspectRatio, Qt::SmoothTransformation));
+ setAlignment(Qt::AlignCenter);
+ return;
+ }
+
+ if (_clientVNCThread != NULL)
+ {
+ if (r.width() != _ux || r.height() != _uy)
+ {
+ _clientImg = _clientVNCThread->getImage(); // redraw complete image (e.g. on resize)
+ r = rect();
+ }
+ else
+ {
+ _ux = -1;
+ }
+
+ if (_clientVNCThread->getSize() == size())
+ {
+
+ painter.drawImage(r.topLeft(), _clientImg); // don't scale
+ }
+ else
+ {
+ QImage i = _clientImg.scaled(r.size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ painter.drawImage(r.topLeft(), i);
+ }
+ }
+ else
+ {
+ _clientImg = QImage(":/terminal");
+ painter.drawImage(28,0, _clientImg.scaled(145,123, Qt::KeepAspectRatio, Qt::SmoothTransformation));
+ setAlignment(Qt::AlignCenter);
+ }
+}
+
+void Frame::slotClicked()
+{
+ //qDebug() << "clickableLabel :: Clicked, searching for" << ip;
+
+ if (ip != "") {
+ for (int i=0; i<MainWindow::getConnectionList()->model->rowCount(QModelIndex()); i++)
+ {
+ if (MainWindow::getConnectionList()->model->index(i, 1, QModelIndex()).data(Qt::DisplayRole).toString()
+ .compare(ip) == 0)
+ {
+ MainWindow::getConnectionList()->selectRow(i);
+ MainWindow::getConnectionList()->setCurrentIndex(MainWindow::getConnectionList()->currentIndex());
+ break;
+ }
+ }
+ }
+}
+
+void Frame::mousePressEvent(QMouseEvent* event)
+{
+ emit clicked();
+ if (event->button() == Qt::RightButton)
+ {
+ /*if (!_dummy)
+ DelDummy->setDisabled(true);
+ menu->exec(QCursor::pos());*/
+ }
+ else
+ {
+
+ }
+ QLabel::mousePressEvent(event);
+}
+
+void Frame::mouseReleaseEvent ( QMouseEvent * event )
+{
+ QLabel::mouseReleaseEvent(event);
+}
+
+QToolButton* Frame::createToolButton(const QString &toolTip, const QIcon &icon, const char *member)
+ {
+ QToolButton *button = new QToolButton(this);
+ button->setToolTip(toolTip);
+ button->setIcon(icon);
+ button->setIconSize(QSize(15, 15));
+ button->setStyleSheet(QString::fromUtf8("background-color: rgb(230, 230, 230);"));
+ addButton(button);
+ toolButtonList.append(button);
+ connect(button, SIGNAL(clicked()), this, member);
+
+ return button;
+}
+
+void Frame::addButton(QToolButton *button)
+{
+ button->move(X,Y);
+ Y += button->size().height()-5;
+}
+
+void Frame::setToolButtonListVisible(bool visible)
+{
+ foreach (QToolButton* tb, toolButtonList)
+ tb->setVisible(visible);
+ if (visible && MainWindow::getConnectionWindow()->hasDozent && !_dozent)
+ button_dozent->setVisible(false);//At this time this button should only be visible on the dozent machine (the superclient).
+
+}
+
+void Frame::setLockStatus(bool lock)
+{
+ if (lock)
+ {
+ button_lock->setToolTip(tr("Unlock this client"));
+ //button_lock->setIcon() TODO
+ }
+ else
+ {
+ button_lock->setToolTip(tr("Lock this client"));
+ //button_lock->setIcon() TODO
+ }
+ _isLocked = lock;
+}
+
+QImage Frame::getImageForFoto()
+{
+ return _clientVNCThread->getImage();
+}
+
+void Frame::closeUp()
+{
+ emit clicked();
+ MainWindow::getWindow()->closeUp();
+}
+
+void Frame::foto()
+{
+ emit clicked();
+ MainWindow::getWindow()->foto();
+}
+
+void Frame::setLock()
+{
+ if (!_dozent)
+ {
+ emit clicked();
+ if (_isLocked)
+ MainWindow::getConnectionWindow()->unlockStations();
+ else
+ MainWindow::getConnectionWindow()->lockStations();
+ }
+ else
+ {
+ QString message = QString(tr("You can't lock a Superclient-machine."));
+ QMessageBox::information(this, "PVS", message);
+ }
+}
+
+void Frame::setDozent()
+{
+ if (_dozent)
+ {
+ button_dozent->setToolTip(tr("Set client as Superclient"));
+ _dozent = false;
+ MainWindow::getConnectionWindow()->hasDozent = false;
+ getConFrame()->setDozent(false);
+ }
+ else
+ {
+ button_dozent->setToolTip(tr("Unset client as Superclient"));
+ _dozent = true;
+ MainWindow::getConnectionWindow()->hasDozent = true;
+ getConFrame()->setDozent(true);
+ }
+}
diff --git a/src/gui/frame.h b/src/gui/frame.h
new file mode 100644
index 0000000..3004e0c
--- /dev/null
+++ b/src/gui/frame.h
@@ -0,0 +1,90 @@
+#ifndef FRAME_H_
+#define FRAME_H_
+
+#include <QtGui>
+#include "../util/vncClientThread.h"
+
+class VNCClientThread;
+class ConnectionWindow;
+class ConnectionFrame;
+class MainWindow;
+
+class Frame: public QLabel
+{
+ Q_OBJECT
+
+public:
+ Frame(const QString & text, QWidget * parent = 0 );
+ virtual ~Frame();
+ void setVNCThreadConnection(VNCClientThread * VNCclientThread);
+ void stopVNCThreadConnection();
+ VNCClientThread * getVNCClientThread()
+ {
+ return _clientVNCThread;
+ }
+ void setConFrame (ConnectionFrame* cf)
+ {
+ _cFrame = cf;
+ }
+ ConnectionFrame* getConFrame()
+ {
+ return _cFrame;
+ }
+ void setToolButtonListVisible(bool visible);
+ void setLockStatus(bool lock);
+ bool getLockStatus()
+ {
+ return _isLocked;
+ }
+ bool isDozent()
+ {
+ return _dozent;
+ }
+ int X,Y;
+
+ QString ip;
+ QToolButton* button_closeUp;
+ QToolButton* button_foto;
+ QToolButton* button_lock;
+ QToolButton* button_unlock;
+ QToolButton* button_dozent;
+ QList<QToolButton*> toolButtonList;
+
+public Q_SLOTS:
+ void updateImage(int x, int y, int w, int h);
+ void iamDown();
+ void slotClicked();
+ QImage image()
+ {
+ return _clientImg;
+ };
+ void setImage(QImage img)
+ {
+ _clientImg = img;
+ };
+ QImage getImageForFoto();
+ void closeUp();
+ void foto();
+ void setLock();
+ //void unlock();
+ void setDozent();
+
+signals:
+ void clicked();
+protected:
+ void paintEvent(QPaintEvent *event);
+ void mousePressEvent ( QMouseEvent * event );
+ void mouseReleaseEvent ( QMouseEvent * event );
+
+private:
+ QToolButton* createToolButton(const QString &toolTip, const QIcon &icon, const char *member);
+ void addButton(QToolButton *button);
+ VNCClientThread *_clientVNCThread;
+ ConnectionFrame *_cFrame;
+ QImage _clientImg;
+ bool _isLocked;
+ bool _dozent;
+ int _ux, _uy;
+};
+
+#endif /* FRAME_H_ */
diff --git a/src/gui/mainWindow.cpp b/src/gui/mainWindow.cpp
new file mode 100644
index 0000000..eb15e82
--- /dev/null
+++ b/src/gui/mainWindow.cpp
@@ -0,0 +1,1205 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # -----------------------------------------------------------------------------
+ # mainWindow.cpp
+ This is the Main class for the pvsManager. The GUI is contructed here.
+ # -----------------------------------------------------------------------------
+ */
+
+#include <QtGui>
+#include <QFileDialog>
+#include <src/gui/mainWindow.h>
+using namespace std;
+
+// setting the IF-DEF Block for the touchgui and the normal gui, for later use
+
+#ifdef MAINWINDOW_USE_TOUCHGUI
+#include "ui_mainwindowtouch.h"
+#endif
+
+#ifdef MAINWINDOW_USE_NORMALGUI
+#include "ui_mainwindow.h"
+#endif
+
+#include <src/gui/connectionList.h>
+#include <src/gui/connectionWindow.h>
+#include <src/gui/profileDialog.h>
+//#include <src/gui/dialog.h>
+#include <src/core/pvsConnectionManager.h>
+#include <iostream>
+
+MainWindow::MainWindow(QWidget *parent) :
+ QMainWindow(parent), ui(new Ui::MainWindow)
+
+{
+
+ ui->setupUi(this);
+
+ ui->horizontalSlider->setValue(100);
+ ui->label_2->setText("100");
+
+ ui->separator->setVisible(false);
+
+ myself = this;
+ conWin = new ConnectionWindow(ui->widget);
+ ui->VconWinLayout->addWidget(conWin);
+ conList = new ConnectionList(ui->ClWidget);
+ ui->ClientGLayout->addWidget(conList);
+
+ bgimage = false;
+
+ _aboutDialog = new AboutDialog(this);
+
+ PVSConnectionManager::getManager();
+
+ //set the maximum width for list content
+ ui->ClWidget->setMaximumWidth(160);
+
+ ui->pvsLog->setReadOnly(true);
+ ui->pvsLog->hide();
+
+ onToggleLog(false);
+ // add ourself to the log listeners, so we can output them too
+ ConsoleLog addListener(this, &MainWindow::on_log_line);
+
+ _firstResize = 1;
+ _oldRatio = "100";
+ _isThumbnailrate = false;
+ is_closeup = false;
+ is_fullscreen = false;
+ _isLockAll = false;
+ locked = false;
+
+ /*
+ * _sessionName: The session name for this Connection
+ * _pwdCon: Password needed to connect to the session with the name _sessionName
+ */
+ _pwdCon = PVSConnectionManager::getManager()->setNeedPassword(false);
+ _sessionName = PVSConnectionManager::getManager()->getSessionName();
+
+ ui->setPassword->setCheckState(Qt::Checked);
+
+#ifdef MAINWINDOW_USE_TOUCHGUI //only used for the touchgui
+
+ // define the slots we want to use
+ connect(ui->comboBox_touch1, SIGNAL(currentIndexChanged(int)), this, SLOT(combobox1(int))); // Combobox 1 verknüpfen mit IndexChangend Signal
+ connect(ui->comboBox_touch1, SIGNAL(currentIndexChanged(int)), this, SLOT(setindexback()));
+
+
+ connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(createProfile())); // profile button
+ connect(ui->pushButton_2, SIGNAL(clicked()), this, SLOT(clientlisthide())); // clienlist button
+
+ // toolbar slots
+ connect(ui->actionresetall, SIGNAL(triggered()), this, SLOT(resetall()));
+ connect(ui->actionLocksingle, SIGNAL(triggered()), this, SLOT(locksingle()));
+ connect(ui->actionUnlocksingle, SIGNAL(triggered()), this, SLOT(unlocksingle()));
+ connect(ui->actionProjection, SIGNAL(triggered()), this, SLOT(projecttoolbar()));
+ connect(ui->actionUnprojection, SIGNAL(triggered()), this, SLOT(unprojecttoolbar()));
+ connect(ui->actionDozent, SIGNAL(triggered()), this, SLOT(setdozenttoolbar()));
+
+ // Ui specific settings
+
+ ui->ClWidget->hide();
+ ui->progressBar->hide();
+ ui->pvsLog->hide();
+
+
+#endif
+
+
+ // toolbar and actions in pvsmgr
+ connect(ui->action_Exit, SIGNAL(triggered()), this, SLOT(close()));
+ ui->action_Exit->setStatusTip(tr("Exit"));
+ connect(ui->action_Disconnect, SIGNAL(triggered()), this, SLOT(disconnect()));
+ ui->action_Disconnect->setStatusTip(tr("Remove the vnc-Connection for the selected client(s)"));
+ ui->action_Disconnect->setVisible(false);//we need it only for debug
+ connect(ui->actionView, SIGNAL(triggered()), this, SLOT(closeUp()));
+ ui->actionView->setStatusTip(tr("Show the selected client in the whole window"));
+ connect(ui->actionFoto, SIGNAL(triggered()), this, SLOT(foto()));
+ connect(ui->actionLock, SIGNAL(triggered()), this, SLOT(lockalltoolbar()));
+ connect(ui->actionChat, SIGNAL(triggered()), this, SLOT(startChatDialog()));
+ ui->actionFoto->setStatusTip(tr("Make a screenshot for the selected client(s)"));
+ ui->actionLock->setStatusTip(tr("Lock or Unlock all Clients"));
+ connect(ui->actionCreate_profile, SIGNAL(triggered()), this, SLOT(createProfile()));
+
+ connect(ui->actionShow_Username, SIGNAL(triggered()), this, SLOT(showusername()));
+ connect(ui->actionShow_Hostname_IP, SIGNAL(triggered()), this, SLOT(showip()));
+ connect(ui->actionShow_Fullname, SIGNAL(triggered()), this, SLOT(showname()));
+ connect(ui->horizontalSlider, SIGNAL(valueChanged (int)), this, SLOT(changeRatio(int)));
+ connect(ui->setPassword, SIGNAL(stateChanged (int)), this, SLOT(setPasswordForConnection(int)));
+ connect(ui->vncQuality, SIGNAL(currentIndexChanged (int)), this, SLOT(setVNCQuality(int)));
+ connect(ui->thumbStatus, SIGNAL(currentIndexChanged(int)), this, SLOT(changeStatus(int)));
+ connect(ui->actionShow_Log, SIGNAL(toggled(bool)), this, SLOT(setLogConsoleDisabled(bool)));
+ connect(ui->actionShow_Network, SIGNAL(toggled(bool)), this, SLOT(onToggleLog(bool)));
+ connect(ui->actionShow_Chat, SIGNAL(toggled(bool)), this, SLOT(onToggleLog(bool)));
+ connect(ui->actionShow_Terminal, SIGNAL(toggled(bool)), this, SLOT(onToggleLog(bool)));
+ connect(ui->actionShow_Normal, SIGNAL(toggled(bool)), this, SLOT(onToggleLog(bool)));
+ connect(ui->actionShow_Error, SIGNAL(toggled(bool)), this, SLOT(onToggleLog(bool)));
+ connect(ui->actionAbout_pvs, SIGNAL(triggered()), _aboutDialog, SLOT(open()));
+
+ loadSettings(); //we load the appliocation settings
+
+ setUnifiedTitleAndToolBarOnMac(true);
+ statusBar()->showMessage(tr("The pvs manager"));
+ this->showMaximized(); // show the Mainwindow maximized
+
+ // listen on port 29481 for incoming file transfers
+ _serverSocket = new QTcpServer();
+ _serverSocket->listen(QHostAddress::Any, 29481);
+ connect(_serverSocket, SIGNAL(newConnection()), this, SLOT(incomingFile()));
+
+
+}
+
+MainWindow::~MainWindow()
+{
+ delete ui;
+}
+
+/*
+ * This signal is received when the mainwindow is going to be closed.
+ * We have to check if the the chat-dialog is open. In this case we close
+ * this dialog and accept the event, the rest will be execute from Qt.
+ * Qt will be call the destroyer ~MainWindow().
+ */
+void MainWindow::closeEvent(QCloseEvent *e)
+{
+ if (sChatDialog.isVisible())
+ sChatDialog.close();
+ e->accept();
+}
+
+MainWindow* MainWindow::getWindow() // catches the window
+{
+
+ if (myself)
+ {
+ return myself;
+ }
+ else
+ {
+ return myself = new MainWindow;
+ }
+}
+
+ConnectionWindow* MainWindow::getConnectionWindow() // catches the ConnectionWindow
+{
+ if (conWin)
+ {
+ return conWin;
+ }
+ else
+ {
+ conWin = new ConnectionWindow;
+ return conWin;
+ }
+}
+
+ConnectionList* MainWindow::getConnectionList() // catches the ConnectionList
+{
+ if (conList)
+ return conList;
+ else
+ {
+ conList = new ConnectionList;
+ return conList;
+ }
+}
+
+int MainWindow::getConnectionWindowWidth() // returns the width of the ConnectionWindow
+{
+ return ui->widget->width();
+}
+
+int MainWindow::getConnectionWindowHeight() // returns the height of the CoonectionWindow
+{
+ return ui->widget->height();
+}
+
+QStringList MainWindow::getProfilList() // loads the profile list
+{
+ QSettings settings("openslx", "pvsmgr");
+ profilList = settings.childGroups();
+ return profilList;
+}
+
+#ifdef MAINWINDOW_USE_NORMALGUI
+void MainWindow::addProfileInMenu(QString name)
+{
+ QAction* action = new QAction(name,this);
+ ui->menuLoad_profile->addAction(action);
+ connect(ui->menuLoad_profile, SIGNAL(triggered(QAction*)), this, SLOT(loadProfile(QAction*)));
+ _mapProfileToAction.insert(name, action);
+}
+
+void MainWindow::removeProfileInMenu(QString name)
+{
+ if (_mapProfileToAction.contains(name))
+ {
+ QAction* action = _mapProfileToAction.value(name);
+ ui->menuLoad_profile->removeAction(action);
+ _mapProfileToAction.take(name);
+ }
+
+}
+
+#endif
+void MainWindow::loadSettings()
+{
+ QSettings settings("openslx", "pvsmgr");
+ QString current = settings.value("current", "default").toString();
+ currentProfi = current;
+ _profilName = current;
+
+ //When no profile is available, we define a default one whith 9 dummy screens
+ if (current.compare("default") == 0)
+ {
+ setWindowTitle("PVSmgr - Default");
+ QPoint pos1 = settings.value("default/1", QPoint(0, 0)).toPoint();
+ MainWindow::getConnectionWindow()->addFrameBySettings("1", pos1);
+ QPoint pos2 =
+ settings.value("default/2", QPoint(194, 0)).toPoint();
+ MainWindow::getConnectionWindow()->addFrameBySettings("2", pos2);
+ QPoint pos3 =
+ settings.value("default/3", QPoint(388, 0)).toPoint();
+ MainWindow::getConnectionWindow()->addFrameBySettings("3", pos3);
+ QPoint pos4 =
+ settings.value("default/4", QPoint(582, 0)).toPoint();
+ MainWindow::getConnectionWindow()->addFrameBySettings("4", pos4);
+ QPoint pos5 =
+ settings.value("default/5", QPoint(0, 173)).toPoint();
+ MainWindow::getConnectionWindow()->addFrameBySettings("5", pos5);
+ QPoint pos6 =
+ settings.value("default/6", QPoint(194, 173)).toPoint();
+ MainWindow::getConnectionWindow()->addFrameBySettings("6", pos6);
+ QPoint pos7 =
+ settings.value("default/7", QPoint(388, 173)).toPoint();
+ MainWindow::getConnectionWindow()->addFrameBySettings("7", pos7);
+ QPoint pos8 =
+ settings.value("default/8", QPoint(582, 173)).toPoint();
+ MainWindow::getConnectionWindow()->addFrameBySettings("8", pos8);
+ QPoint pos9 =
+ settings.value("default/9", QPoint(293, 346)).toPoint();
+ MainWindow::getConnectionWindow()->addFrameBySettings("9", pos9);
+
+ QString title = "PVSmgr - ";
+ title.append(_profilName);
+ title.append(" ["+_sessionName + " : ");
+ title.append(_pwdCon+"]");
+ setWindowTitle(title);
+ }
+ else
+ {
+ QString title = "PVSmgr - ";
+ title.append(_profilName);
+ title.append(" ["+_sessionName + " : ");
+ title.append(_pwdCon+"]");
+ setWindowTitle(title);
+ settings.beginGroup(current);
+ QStringList keys = settings.childKeys();
+ for (int i=0; i<keys.size(); i++)
+ {
+ QString profil = current;
+ profil = profil.append("/").append(keys.at(i));
+ QPoint pos = settings.value(keys.at(i)).toPoint();
+ MainWindow::getConnectionWindow()->addFrameBySettings(keys.at(i), pos);
+ }
+ }
+
+ MainWindow::getConnectionWindow()->showFrameFromSettings();
+#ifdef MAINWINDOW_USE_NORMALGUI
+ foreach (QString profile, getProfilList())
+ addProfileInMenu(profile);
+#endif
+}
+
+void MainWindow::loadProfile(QAction* actiontriggered)
+{
+ QString profilename = actiontriggered->text();
+ loadSettings(profilename);
+}
+
+void MainWindow::loadSettings(QString profilname) // loads the current profile
+{
+ QList<ConnectionFrame*> AllFrameOnWindow =
+ MainWindow::getConnectionWindow()->getAllFrameOnWindow();
+
+ if (AllFrameOnWindow.size() > 0)
+ {
+ _profilName = profilname;
+ MainWindow::getConnectionWindow()->ClientLocationList.clear();
+ QSettings settings("openslx", "pvsmgr");
+ settings.setValue("current", _profilName);
+ ConnectionFrame* cFrame;
+ foreach (cFrame, AllFrameOnWindow)
+ {
+ if (cFrame->isDummy())
+ {
+ AllFrameOnWindow.removeOne(cFrame);
+ MainWindow::getConnectionWindow()->removeFromList(cFrame);
+ cFrame->deleteLater();
+ }
+ }
+ settings.beginGroup(_profilName);
+ QStringList keys = settings.childKeys();
+ int rest = AllFrameOnWindow.size();
+ int init = 1;
+ for (int i = 0; i < keys.size(); i++)
+ {
+ if (init <= rest)
+ {
+ ConnectionFrame* cF = AllFrameOnWindow.at(i);
+ QString profil = _profilName;
+ profil = profil.append("/").append(cF->getTaskbarTitle());
+ if (!cF->isDummy())
+ cF->move(settings.value(keys.at(i)).toPoint());
+ else
+ cF->move(settings.value(profil, QPoint(10,(10+(5*i)))).toPoint());
+
+ init += 1;
+ }
+ else
+ {
+ MainWindow::getConnectionWindow()->addFrameBySettings(
+ keys.at(i), settings.value(keys.at(i)).toPoint());
+ }
+ }
+
+ MainWindow::getConnectionWindow()->showFrameFromSettings();
+
+ QString title = "PVSmgr - ";
+ title.append(_profilName);
+ title.append(" ["+_sessionName + " : ");
+ title.append(_pwdCon+"]");
+ setWindowTitle(title);
+ }
+}
+
+void MainWindow::saveSettings(QString profilname)
+{
+ QList<ConnectionFrame*> AllFrameOnWindow =
+ MainWindow::getConnectionWindow()->getAllFrameOnWindow();
+ QSettings settings("openslx", "pvsmgr");
+ settings.setValue("current", profilname);
+ settings.setValue("size", QString("%1").arg(AllFrameOnWindow.size()));
+
+ for (int i = 0; i < AllFrameOnWindow.size(); i++)
+ {
+ ConnectionFrame* current = AllFrameOnWindow.at(i);
+ QString profil = "";
+ profil = settings.value("current").toString().append("/");
+ if (!current->isDummy())
+ profil.append(QString(current->getTaskbarTitle()));
+ else
+ profil.append(QString("%1").arg(i + 1));
+ settings.setValue(profil, current->pos());
+ }
+#ifdef MAINWINDOW_USE_NORMALGUI
+addProfileInMenu(profilname);
+#endif
+}
+
+void MainWindow::removeProfil(QString profilname)
+{
+ QSettings settings("openslx", "pvsmgr");
+ settings.remove(profilname);
+#ifdef MAINWINDOW_USE_NORMALGUI
+removeProfileInMenu(profilname);
+#endif
+}
+
+void MainWindow::addConnection(PVSClient* newCon)
+{
+ conWin->addConnection(newCon);
+ if (!_chatListClients.contains(newCon->getUserName()))
+ {
+ _chatListClients.append(newCon->getUserName());
+ sChatDialog.chat_client_add(newCon->getUserName());
+ sChatDialog.chat_nicklist_update();
+ }
+ // sChatDialog->chat_nicklist_update(newCon->getUserName());
+}
+
+void MainWindow::removeConnection(PVSClient* newCon)
+{
+ conWin->removeConnection(newCon);
+ if (_chatListClients.contains(newCon->getUserName()))
+ {
+ _chatListClients.removeOne(newCon->getUserName());
+ sChatDialog.chat_client_remove(newCon->getUserName());
+ sChatDialog.chat_nicklist_update();
+ }
+}
+
+void MainWindow::onConnectionFailed(QString host)
+{
+#ifdef never
+ // code is voided because the info-management will be overhauled sometime
+
+ if (pwDiag) // assume this thing failed after the pw-question... so a wrong password, ey?
+
+ {
+ onPasswordFailed(host);
+ return;
+ }
+
+ QString caption, secondary;
+ if (host != "")
+ {
+ caption = ("PVSConnection with hostname \"");
+ caption.append(host);
+ caption.append("\" failed.");
+ secondary = "PVSConnection attempt for this hostname failed.Maybe the host is not prepared to accept vnc connections. Please make sure hostname and (if needed) password are correct.";
+ }
+ else
+ {
+ caption = "No IP given";
+ secondary = "PVSConnection attempt for this host failed. There was either no or an errorous Hostname given.";
+ }
+ QMessageBox::information(*this, caption, secondary);
+ /* Gtk::MessageDialog dialog(*this, Glib::ustring(caption));
+ dialog.set_secondary_text(secondary);
+ dialog.run();*/
+#endif
+}
+
+void MainWindow::onConnectionTerminated(PVSClient* newConnection)
+{
+#ifdef never
+ // code is voided because the info-management will be overhauled sometime
+
+ QString host;
+ if (newConnection)
+ {
+ host = newConnection->getIp(); // copy hostname for message
+ }
+ else
+ host = "spooky unknown";
+
+ // now inform
+ QString caption, secondary;
+
+ caption = "Hostname \"";
+ caption.append(host);
+ caption.append("\" terminated connection.");
+ secondary = "The server has closed the connection to your client.";
+
+ QMessageBox::information(*this, caption, secondary);
+ /*Gtk::MessageDialog dialog(*this, Glib::ustring(caption));
+ dialog.set_secondary_text(secondary);
+ dialog.run();*/
+#endif
+}
+
+void MainWindow::onConnectionRemoved(PVSClient* newConnection)
+{
+ // TODO this would be the place to handle the rest of the fullscreen issue
+ conWin->onConnectionRemoved(newConnection);
+}
+
+void MainWindow::onPasswordFailed(QString Qhost)
+{
+#ifdef never
+ // code is voided because the info-management will be overhauled sometime
+ QString caption, secondary;
+ if (Qhost != "")
+ {
+ caption = "Hostname \"";
+ caption.append(Qhost);
+ caption.append("\" refused password.");
+ secondary = "You have entered no or a wrong password.";
+ }
+ else
+ return; // unknown connection was terminated? too spooky
+ QMessageBox::information(*this, caption, secondary);
+ /* Gtk::MessageDialog dialog(*this, Glib::ustring(caption));
+ dialog.set_secondary_text(secondary);
+ Gtk::Main::run(dialog);*/
+#endif
+}
+
+void MainWindow::sendChatMsg(PVSMsg myMsg)
+{
+ PVSConnectionManager::getManager()->onChat(myMsg);
+}
+
+void MainWindow::receiveChatMsg(QString nick_from, QString nick_to, QString msg)
+{
+ sChatDialog.chat_receive(nick_from, nick_to, msg);
+}
+
+int MainWindow::getPrevWidth() // PVSConnectionManager::getManager()->getPrevWidth()
+{
+ return prev_width;
+}
+
+void MainWindow::setPrevWidth(int newWidth)
+{
+ if (newWidth > 100)
+ prev_width = newWidth;
+ else
+ prev_width = 100;
+}
+
+int MainWindow::getPrevHeight()
+{
+ return prev_height;
+}
+
+void MainWindow::setPrevHeight(int newHeight)
+{
+ if (newHeight > 100)
+ prev_height = newHeight;
+ else
+ prev_height = 100;
+}
+
+void MainWindow::changeEvent(QEvent *e)
+{
+ QMainWindow::changeEvent(e);
+ switch (e->type())
+ {
+ case QEvent::LanguageChange:
+ ui->retranslateUi(this);
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+ * The resize Event is called when the mainwindow is resized!
+ * Whe need this event to resize the Frame on the Connectionwindow.
+ * The Frames are resized proportionally to the new size of the mainwindow.
+ * But this Function is called by Qt 3 times before the whole
+ * mainwdow is constructed. We can only resize the Frame on Window and
+ * get the initial size of the Connectionwindow after this 3 times.
+ */
+void MainWindow::resizeEvent(QResizeEvent *event)
+{
+
+ if (bgimage == true){
+ repaintbackgroundpicture(); // repaint the backgroundpicture scaled to the window size
+ }
+
+ if (_firstResize == 3)
+ {
+ QSize oldSize = event->oldSize();
+ _initW = ui->widget->width();
+ _initH = ui->widget->height();
+ _firstResize++;
+ }
+ std::list<QString>* selectedClients =
+ MainWindow::getConnectionList()->getSelectedClients();
+ if (is_closeup && selectedClients->size() == 1)
+ {
+ PVSClient* pvsClient =
+ PVSConnectionManager::getManager()->getClientFromIp(
+ selectedClients->front().toStdString().c_str());
+ pvsClient->getConnectionFrame()->paintCloseUp(ui->widget->width(),
+ ui->widget->height());
+ }
+ else if (!is_closeup && _firstResize > 3)
+ {
+ int ratio_w = (ui->widget->width()*100)/_initW;
+ int ratio_h = (ui->widget->height()*100)/_initH;
+ foreach (ConnectionFrame* cf, getConnectionWindow()->getFrameList())
+ {
+ /*int margin = ui->widget->style()->pixelMetric(QStyle::PM_DefaultTopLevelMargin);
+ int x = ui->widget->width() - margin;
+ int y = ui->widget->height() - margin;
+ updatePos(cf, x, y);*/
+ int w = (cf->init_w * ratio_w) / 100;
+ int h = (cf->init_h * ratio_h) / 100;
+ cf->paintCloseUp(w,h);
+ }
+ }
+
+ if (_firstResize < 3)
+ _firstResize++;
+}
+
+void MainWindow::updatePos(ConnectionFrame* cf, int x, int y)
+{
+ int posx = (x*cf->pos().x())/_initW;
+ int posy = (y*cf->pos().y())/_initH;
+ cf->move(posx, posy);
+ /*QSize size = cf->sizeHint();
+ cf->setGeometry(x - size.rwidth(), y - size.rheight(),
+ size.rwidth(), size.rheight());*/
+}
+
+void MainWindow::on_log_line(LogEntry consoleEntry)
+{
+ ConsoleLogger::LOG_LEVEL level = consoleEntry.getLevel();
+ if (level == ConsoleLogger::LOG_ERROR && !showError)
+ return;
+ if (level == ConsoleLogger::LOG_NORMAL && !showNormal)
+ return;
+ if (level == ConsoleLogger::LOG_NETWORK && !showNetwork)
+ return;
+ if (level == ConsoleLogger::LOG_TERMINAL && !showTerminal)
+ return;
+ if (level == ConsoleLogger::LOG_CHAT && !showChat)
+ return;
+
+ ui->pvsLog->insertPlainText(consoleEntry.getLine());
+
+}
+
+void MainWindow::onToggleLog(bool showtime)
+{
+ if (showtime)
+ ;//to kill the system warning due "unused variable"
+ showError = ui->actionShow_Error->isChecked();
+ showTerminal = ui->actionShow_Terminal->isChecked();
+ showNetwork = ui->actionShow_Network->isChecked();
+ showChat = ui->actionShow_Chat->isChecked();
+ showNormal = ui->actionShow_Normal->isChecked();
+ //showAtAll = ui->logAtAllAction->get_active();
+
+
+ ConsoleLog dump2Listener(this, &MainWindow::on_log_line);
+}
+
+void MainWindow::setLogConsoleDisabled(bool visible)
+{
+ if (!visible)
+ ui->pvsLog->hide();
+ else
+ ui->pvsLog->show();
+}
+
+/*void MainWindow::close()
+{
+ //sChatDialog.close();
+ QApplication::closeAllWindows();
+}*/
+
+void MainWindow::disconnect()
+{
+ conWin->removeVNC();
+}
+
+void MainWindow::lockUnlockAll()
+{
+ if (_isLockAll)
+ {
+ //ui->actionLock set icon to unlock
+ MainWindow::getConnectionWindow()->unlockAllStations();
+ _isLockAll = false;
+ }
+ else
+ {
+ //ui->actionLock set icon to lock
+ MainWindow::getConnectionWindow()->lockAllStations();
+ _isLockAll = true; //tell the manager all the clients are locked
+ }
+}
+
+void MainWindow::closeUp()
+{
+ std::list<QString>* selectedClients =
+ MainWindow::getConnectionList()->getSelectedClients();
+ if (!is_closeup)
+ {
+ if (selectedClients->size() == 1)
+ {
+ PVSClient
+ * pvsClient =
+ PVSConnectionManager::getManager()->getClientFromIp(
+ selectedClients->front().toStdString().c_str());
+ _framePosOnCloseUp = pvsClient->getConnectionFrame()->pos();//get the actualy position before run closeup
+ if (pvsClient->getVNCConnection())
+ {
+ conWin->setCloseupFrame(pvsClient->getConnectionFrame());
+ _updatefreq = pvsClient->getConnectionFrame()->getFrame()->getVNCClientThread()->getUpdatefreq();
+ pvsClient->getConnectionFrame()->getFrame()->getVNCClientThread()->setUpdatefreq(50);
+ pvsClient->getConnectionFrame()->move(5,5);
+ pvsClient->getConnectionFrame()->setWindowFlags(Qt::WindowStaysOnTopHint);
+ pvsClient->getConnectionFrame()->raise();
+ pvsClient->getConnectionFrame()->paintCloseUp(ui->widget->width(),ui->widget->height());
+
+ is_closeup = true;
+ conWin->setCloseupFrame(pvsClient->getConnectionFrame());
+ }
+ }
+ else
+ {
+ QString
+ message =
+ QString(
+ tr(
+ "This operation can only be performed for one selected Client!"));
+ QMessageBox::information(this, "PVS", message);
+ }
+ }
+ else if (conWin->getCloseupFrame())
+ {
+ /*PVSClient* pvsClient =
+ PVSConnectionManager::getManager()->getClientFromIp(
+ selectedClients->front().toStdString().c_str());*/
+ conWin->getCloseupFrame()->setWindowFlags(Qt::Widget);
+ conWin->getCloseupFrame()->paintCloseUp(conWin->getCloseupFrame()->getPrevWidth(), conWin->getCloseupFrame()->getPrevHeight());
+ conWin->getCloseupFrame()->move(_framePosOnCloseUp);//back to the position before the closeup
+ if (conWin->getCloseupFrame()->getConnection()->getVNCConnection())
+ conWin->getCloseupFrame()->getFrame()->getVNCClientThread()->setUpdatefreq(_updatefreq);
+
+ is_closeup = false;
+ conWin->setCloseupFrame(NULL);
+ }
+}
+
+void MainWindow::foto() // makes a screenshot of the selected client
+{
+ std::list<QString>* selectedClients =
+ MainWindow::getConnectionList()->getSelectedClients();
+ if (selectedClients->size() > 0)
+ {
+ QString format = "png";
+ for (std::list<QString>::iterator tmpIt = selectedClients->begin(); tmpIt
+ != selectedClients->end(); tmpIt++)
+ {
+
+ QString path = QDir::homePath().append("/").append(*tmpIt).append(
+ ".png");
+ PVSClient
+ * pvsClient =
+ PVSConnectionManager::getManager()->getClientFromIp(
+ (*tmpIt).toUtf8().data());
+ if (pvsClient->getVNCConnection())
+ {
+ const QImage img = pvsClient->getConnectionFrame()->getFrame()->getImageForFoto();
+ if (!img.isNull())
+ img.save(path, format.toAscii());
+ }
+ else printf("Cannot save screen: Image is null.\n");
+ }
+ }
+ else
+ {
+ QString
+ message =
+ QString(
+ tr(
+ "This operation can only be performed for at least one selected Client!"));
+ QMessageBox::information(this, "PVS", message);
+ }
+}
+
+void MainWindow::createProfile()
+{
+ profileDialog proDiag;
+ proDiag.exec();
+}
+
+void MainWindow::showusername()
+{
+ MainWindow::getConnectionList()->setColumnHidden(2, false);
+ MainWindow::getConnectionList()->setColumnHidden(0, true);
+ MainWindow::getConnectionList()->setColumnHidden(1, true);
+}
+
+void MainWindow::showname()
+{
+ MainWindow::getConnectionList()->setColumnHidden(0, false);
+ MainWindow::getConnectionList()->setColumnHidden(1, true);
+ MainWindow::getConnectionList()->setColumnHidden(2, true);
+}
+
+void MainWindow::showip()
+{
+ MainWindow::getConnectionList()->setColumnHidden(1, false);
+ MainWindow::getConnectionList()->setColumnHidden(2, true);
+ MainWindow::getConnectionList()->setColumnHidden(0, true);
+}
+
+void MainWindow::incomingFile()
+{
+ QTcpSocket *socket = _serverSocket->nextPendingConnection();
+ ServerFileTransfert* sft = new ServerFileTransfert(this);
+ sft->receiveFileFromHost(socket);
+}
+
+void MainWindow::changeRatio(int ratio) // needed the change the size of the vnc-screens
+{
+
+ if (!_isThumbnailrate)
+ {
+ QString str;
+ str.append(QString("%1").arg(ratio));
+ ui->label_2->setText(str);
+
+ std::list<QString>* selClients = getConnectionList()->getSelectedClients();
+ if (selClients->size() > 0)
+ {
+ for (std::list<QString>::iterator client = selClients->begin(); client
+ != selClients->end(); client++)
+ {
+ PVSClient* pvsClient =
+ PVSConnectionManager::getManager()->getClientFromIp(
+ (*client).toUtf8().data());
+ ConnectionFrame *frame = pvsClient->getConnectionFrame();
+ int w = (frame->init_w * ratio) / 100;
+ int h = (frame->init_h * ratio) / 100;
+ frame->setPrevWidth(w);
+ frame->setPrevHeight(h);
+ frame->paintCloseUp(w, h);
+ frame->setRatio(ratio);
+ }
+ }
+ else
+ {
+ QList<ConnectionFrame *> frameList =
+ MainWindow::getConnectionWindow()->getFrameList();
+ ConnectionFrame *frame;
+ foreach(frame, frameList)
+ {
+ int w = (frame->init_w * ratio) / 100;
+ int h = (frame->init_h * ratio) / 100;
+ frame->setPrevWidth(w);
+ frame->setPrevHeight(h);
+ frame->paintCloseUp(w, h);
+ }
+ }
+ }
+ else
+ {
+ int updatefreq = (ratio*500)/100;
+ QString str;
+ str.append(QString("%1").arg(updatefreq));
+ ui->label_2->setText(str);
+ std::list<QString>* selClients = getConnectionList()->getSelectedClients();
+ if (selClients->size() > 0)
+ {
+ for (std::list<QString>::iterator client = selClients->begin(); client
+ != selClients->end(); client++)
+ {
+ PVSClient* pvsClient =
+ PVSConnectionManager::getManager()->getClientFromIp(
+ (*client).toUtf8().data());
+ if (pvsClient->getVNCConnection())
+ pvsClient->getConnectionFrame()->getFrame()->getVNCClientThread()->setUpdatefreq(updatefreq);
+ }
+ }
+ else
+ {
+ std::list<PVSClient*> clients = PVSConnectionManager::getManager()->getConnections();
+ foreach (PVSClient* client, clients)
+ {
+ if (client->getVNCConnection())
+ client->getConnectionFrame()->getFrame()->getVNCClientThread()->setUpdatefreq(updatefreq);
+ }
+ }
+
+ }
+}
+
+/*
+ * We can change the status for the action that we want to assign to the thumbnails.
+ * The actions are to be perform over the horizontalslider from QSlider only on the not dummies clients.
+ * The dummies clients aren't involved.
+ * We distingue two status:
+ * -Thumbnailratio:hier we can change the ratio of the thumbnails.
+ * -Thumbnailrate:we change the rate of the VNCClientThread of the frames. These actions are perform on the selected clients.
+ * If no clients are selected, we change the ratio of the whole clients on the clientlist *
+ */
+void MainWindow::changeStatus(int index)
+{
+ QString status = ui->thumbStatus->currentText ();
+
+ if (status == "Thumbnailratio")
+ {
+ _isThumbnailrate = false;
+ ui->label_3->setText("%");
+ std::list<QString>* selClients = getConnectionList()->getSelectedClients();
+ if (selClients->size() == 1)
+ {
+ PVSClient* pvsClient =
+ PVSConnectionManager::getManager()->getClientFromIp(
+ selClients->front().toStdString().c_str());
+ int ratio = pvsClient->getConnectionFrame()->getRatio();
+ ui->label_2->setText(QString::number(ratio));
+ ui->horizontalSlider->setValue(ratio);
+ }
+ else
+ {
+ ui->label_2->setText("100");
+ ui->horizontalSlider->setValue(100);
+ }
+
+ }
+ else if (status == "Thumbnailrate")
+ {
+ _isThumbnailrate = true;
+ ui->label_3->setText("ms");
+ std::list<QString>* selClients = getConnectionList()->getSelectedClients();
+ if (selClients->size() == 1)
+ {
+ PVSClient* pvsClient =
+ PVSConnectionManager::getManager()->getClientFromIp(
+ selClients->front().toStdString().c_str());
+ if (pvsClient->getVNCConnection())
+ {
+ int updatefreq = pvsClient->getConnectionFrame()->getFrame()->getVNCClientThread()->getUpdatefreq();
+ int showfreq = (updatefreq*100)/500;
+ ui->label_2->setText(QString::number(updatefreq));
+ ui->horizontalSlider->setValue(showfreq);
+ }
+ }
+ else
+ {
+ ui->label_2->setText("500");
+ ui->horizontalSlider->setValue(100);
+ }
+ }
+}
+
+
+/*
+ * Going to run a new vncthread with quality: quality
+ */
+void MainWindow::setVNCQuality(int quality)
+{
+ std::list<QString>* selClients = getConnectionList()->getSelectedClients();
+ if (selClients->size() > 0)
+ {
+ for (std::list<QString>::iterator client = selClients->begin(); client
+ != selClients->end(); client++)
+ {
+ PVSClient* pvsClient =
+ PVSConnectionManager::getManager()->getClientFromIp(
+ (*client).toUtf8().data());
+ pvsClient->getConnectionFrame()->resetConnectionWithQuality(quality);
+ pvsClient->getConnectionFrame()->update();
+ }
+ }
+ else
+ {
+ QList<ConnectionFrame*> FrameList = MainWindow::getConnectionWindow()->getFrameList();
+ foreach(ConnectionFrame* frame, FrameList)
+ {
+ frame->resetConnectionWithQuality(quality);
+ frame->update();
+ }
+ }
+
+}
+
+
+void MainWindow::setPasswordForConnection(int enabled)
+{
+ if(enabled == 0)//the checkbox isn't checked, so no passowrd needed, we remove it in the titlebar
+ {
+ QString dummy = PVSConnectionManager::getManager()->setNeedPassword(false);
+ _sessionName = PVSConnectionManager::getManager()->getSessionName();
+ QString title = "PVSmgr - ";
+ title.append(_profilName);
+ title.append(" ["+_sessionName + " : ]");
+ setWindowTitle(title);
+ }
+ else if (enabled == 2) //password is needed, we show it in the titlebar
+ {
+ _pwdCon = PVSConnectionManager::getManager()->setNeedPassword(true);
+ _sessionName = PVSConnectionManager::getManager()->getSessionName();
+ QString title = "PVSmgr - ";
+ title.append(_profilName);
+ title.append(" ["+_sessionName + " : ");
+ title.append(_pwdCon+"]");
+ setWindowTitle(title);
+ }
+}
+//#endif
+
+
+void MainWindow::setindexback() //sets the index of the combobox back
+{
+#ifdef MAINWINDOW_USE_TOUCHGUI
+ ui->comboBox_touch1->setCurrentIndex(0);
+#endif
+}
+
+void MainWindow::clientlisthide() // hide or show the clientlist
+{
+
+ if (locked1 == false)
+ {
+ ui->ClWidget->show();
+ locked1 = true;
+ }
+
+ else
+ {
+ ui->ClWidget->hide();
+ locked1 = false;
+ }
+
+}
+
+
+void MainWindow::lockalltoolbar() // locks all if a dozent is set
+{
+
+
+ if (locked == false)
+ {
+ if (MainWindow::getConnectionWindow()->hasDozent)
+ {
+ MainWindow::getConnectionList()->on_lock_all();
+ locked = true;
+ }
+ else
+ {
+ QString message = QString(tr("You have to set a Superclient-machine before performing this action."));
+ QMessageBox::information(this, "PVS", message);
+ }
+ }
+
+ else
+ {
+ MainWindow::getConnectionList()->on_unlock_all();
+ locked = false;
+ }
+
+}
+
+void MainWindow::locksingle() // locks a single client
+{
+
+ MainWindow::getConnectionList()->on_lock();
+
+}
+
+void MainWindow::unlocksingle() // unlocks a single client
+{
+
+ MainWindow::getConnectionList()->on_unlock();
+
+}
+
+
+void MainWindow::combobox1(int menuindex1) // defines the functions to call from the combobox
+{
+ switch (menuindex1)
+ // index comes from the slot definition
+ {
+ case 1:
+ // Lock all
+ MainWindow::getConnectionList()->on_lock_all();
+ break;
+
+ case 2:
+ // UnLock all
+ MainWindow::getConnectionList()->on_unlock_all();
+ break;
+
+ case 3:
+ // UnProject all
+ MainWindow::getConnectionList()->on_unproject_all();
+ break;
+
+ case 4:
+ //Background Picture
+ backgroundpicture();
+ break;
+ }
+}
+
+void MainWindow::resetall() // unlock and unproject all in toolbar
+ {
+ MainWindow::getConnectionList()->on_unlock_all();
+ MainWindow::getConnectionList()->on_unproject_all();
+ }
+
+
+void MainWindow::projecttoolbar() // projection from toolbar button
+ {
+
+ MainWindow::getConnectionList()->on_projection();
+
+ }
+void MainWindow::unprojecttoolbar() // unproject all in toolbar
+ {
+
+ MainWindow::getConnectionList()->on_unprojection();
+
+ }
+
+void MainWindow::backgroundpicture()
+ {
+
+
+ fileName = QFileDialog::getOpenFileName(this,
+ tr("Open Image"), "/home", tr("Image Files (*.png *.jpg *.svg)")); // user chooses a file
+
+ QImage img(""+fileName+""); // set image
+ QString test("/tmp/test.png"); // set path for saving the scaled picture
+ QImage img2 = img.scaled(ui->widget->size(),Qt::IgnoreAspectRatio,Qt::FastTransformation); // scale it
+
+ img2.save(""+test+""); // save it
+
+ ui->widget->setStyleSheet("background-image: url(/tmp/test.png);background-repeat:no-repeat; background-position:center;"); //set the picture as background
+ foreach (ConnectionFrame* cf, MainWindow::getConnectionWindow()->getAllFrameOnWindow())
+ {
+ cf->setStyleSheet(QString::fromUtf8("background-color: rgb(150, 150, 168);"));
+ }
+
+ bgimage=true; // for the resize event, set background true
+
+
+ }
+
+void MainWindow::repaintbackgroundpicture() // same as backgroundpicture but called when mainwindow is resized
+ {
+
+ QImage img("/tmp/test.png");
+ QString test("/tmp/test.png");
+ QImage img2 = img.scaled(ui->widget->size(),Qt::IgnoreAspectRatio,Qt::FastTransformation);
+
+ img2.save(""+test+"");
+
+ ui->widget->setStyleSheet("background-image: url(/tmp/test.png);background-repeat:no-repeat; background-position:center;");
+
+
+ }
+
+void MainWindow::setdozenttoolbar() // set the dozents pc which is not locked with lockedall
+{
+
+ std::list<QString>* selectedClients =
+ MainWindow::getConnectionList()->getSelectedClients();
+
+ if (selectedClients->size() == 1)
+ {
+
+ PVSClient* pvsClient =
+ PVSConnectionManager::getManager()->getClientFromIp(
+ selectedClients->front().toStdString().c_str());
+ if (pvsClient->getVNCConnection())
+ pvsClient->getConnectionFrame()->getFrame()->setDozent();
+ }
+
+}
+
+void MainWindow::startChatDialog()
+{
+ if (!sChatDialog.isVisible())
+ sChatDialog.show(); //show the chat dialog
+ else
+ sChatDialog.raise();//show the chat dialog on top level
+}
+
+
+
+MainWindow* MainWindow::myself = NULL;
+ConnectionList* MainWindow::conList = NULL;
+ConnectionWindow* MainWindow::conWin = NULL;
+bool MainWindow::_isLockAll = false;
diff --git a/src/gui/mainWindow.h b/src/gui/mainWindow.h
new file mode 100644
index 0000000..00bd927
--- /dev/null
+++ b/src/gui/mainWindow.h
@@ -0,0 +1,200 @@
+#ifndef _MAINWINDOW_H_
+#define _MAINWINDOW_H_
+
+#include <QtGui>
+#include <QtNetwork>
+#include <QMainWindow>
+#include <QFileDialog>
+#include <src/gui/connectionList.h>
+#include <src/util/consoleLogger.h>
+#include <src/gui/connectionWindow.h>
+#include <src/gui/profileDialog.h>
+//#include <src/gui/dialog.h>
+#include <src/core/pvsClient.h>
+#include <src/core/pvsConnectionManager.h>
+#include "src/gui/aboutDialog.h"
+#include "src/gui/serverChatDialog.h"
+#include <src/gui/serverFileTransfert.h>
+
+
+namespace Ui
+{
+class MainWindow;
+}
+
+
+class PVSClient;
+class ConnectionList;
+class ConnectionWindow;
+class profileDialog;
+class ServerChatDialog;
+//class Dialog;
+
+
+class MainWindow : public QMainWindow
+{
+ friend class PVSConnectionManager;
+
+ Q_OBJECT
+
+
+public:
+ MainWindow(QWidget *parent = 0);
+ ~MainWindow();
+
+ //singleton methods
+ static MainWindow* getWindow();
+ static ConnectionWindow* getConnectionWindow();
+ static ConnectionList* getConnectionList();
+
+ ServerChatDialog sChatDialog;
+
+
+ int getConnectionWindowWidth();
+ int getConnectionWindowHeight();
+ int x,y;
+ QImage img;
+ QImage img2;
+ QString test;
+ QStringList profilList;
+ QStringList getProfilList();
+ void addProfileInMenu(QString name);
+ void removeProfileInMenu(QString name);
+ QString currentProfi;
+ QString getCurrentProfi()
+ {
+ return currentProfi;
+ }
+ void loadSettings();
+ void loadSettings(QString profilname);
+ void saveSettings(QString profilname);
+ void removeProfil(QString profilname);
+
+ // connection add/remove and dialog methods
+ void addConnection(PVSClient* newCon);
+ void removeConnection(PVSClient* newCon);
+ //ConnectionFrame* getNewFrame();
+ void onConnectionFailed(QString host = "");
+ void onConnectionTerminated(PVSClient* newConnection);
+ void onConnectionRemoved(PVSClient* newConnection);
+ void onPasswordFailed(QString Qhost = "");
+
+ void sendChatMsg(PVSMsg myMsg);
+ void receiveChatMsg(QString nick_from, QString nick_to, QString msg);
+
+ // view mode related methods
+ unsigned int getGlobalFrameRate();
+ void setGlobalFrameRate(unsigned int newRate);
+ int getPrevWidth();
+ void setPrevWidth(int newWidth);
+ int getPrevHeight();
+ void setPrevHeight(int newHeight);
+
+ // int createMsgDiag();
+ void setMsgDialog(QString msgd){msgDialog = msgd;};
+ QString getMsgDialog(){return msgDialog;};
+
+ bool isLockAllStatus()
+ {
+ return _isLockAll;
+ }
+
+ void appendLogMsg();
+
+
+
+protected:
+ void closeEvent(QCloseEvent *e);
+ void changeEvent(QEvent *e);
+ void resizeEvent(QResizeEvent *event); //We need this to resize the frame in the window when window are resized.
+ void updatePos(ConnectionFrame* cf, int x, int y);
+ virtual void on_log_line(LogEntry consoleEntry);
+
+
+
+
+private:
+ Ui::MainWindow *ui;
+ static ConnectionWindow* conWin;
+ static ConnectionList* conList;
+ //Dialog messageDiag;
+ static MainWindow* myself;
+ QString _pwdCon;
+ QString _sessionName;
+ QString _profilName;
+
+ QStringList _chatListClients;
+
+
+
+ /*ConnectionDialog* myConDiag;
+ ConnectionDialog* pwDiag;
+ ConnectionDialog* messageDiag;*/
+
+ AboutDialog *_aboutDialog;
+
+ QString msgDialog;
+ bool bgimage;
+ bool locked, locked1;
+ bool force_square;
+ bool is_fullscreen;
+ bool is_closeup;
+ static bool _isLockAll;
+ bool showError, showNormal, showNetwork, showTerminal, showChat, showAtAll;
+ bool isDozent;
+ QString fileName;
+
+ int _initW, _initH, _firstResize;
+
+ unsigned int updateRate, frameRate;
+ int prev_width, prev_height, menuindex1, menuindex2;
+
+ QTcpServer *_serverSocket;
+ QPoint _framePosOnCloseUp;
+
+ bool _isThumbnailrate;
+ int _updatefreq;
+ QString _oldRatio;
+
+ QMenu* _profileMenuList;
+ QMap<QString, QAction*> _mapProfileToAction;
+
+public slots:
+ void loadProfile(QAction* actiontriggered);
+ void setindexback();
+ //void setindexback2();
+ void lockalltoolbar();
+ void resetall();
+ void locksingle();
+ void unlocksingle();
+ void clientlisthide();
+ void projecttoolbar();
+ void unprojecttoolbar();
+ void closeUp();
+ void foto();
+ void backgroundpicture();
+ void repaintbackgroundpicture();
+ void setdozenttoolbar();
+ void startChatDialog();
+
+private slots:
+ void onToggleLog(bool showtime);
+ void setLogConsoleDisabled(bool visible);
+ //void close();
+ void disconnect();
+ void lockUnlockAll();
+ void createProfile();
+ void showusername();
+ void showname();
+ void showip();
+ void incomingFile();
+ void changeRatio(int ratio);
+ void changeStatus (int index);
+ void setVNCQuality(int quality);
+ void setPasswordForConnection(int enabled);
+ void combobox1(int menuindex1); // Funktion um index der combobox auszulesen und weiterzuverarbeiten s. Ticker 671
+ //void combobox2(int menuindex2); // Funktion um index der combobox auszulesen und weiterzuverarbeiten
+};
+
+
+#endif
diff --git a/src/gui/profileDialog.cpp b/src/gui/profileDialog.cpp
new file mode 100644
index 0000000..2cbc155
--- /dev/null
+++ b/src/gui/profileDialog.cpp
@@ -0,0 +1,179 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # -----------------------------------------------------------------------------
+ # profileDialog.cpp
+ # - GUI to define the profile.
+ # -----------------------------------------------------------------------------
+ */
+
+#include "profileDialog.h"
+#include "ui_profileDialog.h"
+#include <src/gui/mainWindow.h>
+#include <iostream>
+
+profileDialog::profileDialog(QWidget * parent):
+ QDialog(parent),
+ uidiag(new Ui::Dialog)
+{
+ uidiag->setupUi(this);
+ content = new QTableView(uidiag->widget);
+ uidiag->gridLayout->addWidget(content);
+
+ /*Das Modelfestlegen, wo die Clientname angezeigt werden.*/
+ model = new QStandardItemModel(0,1,content); //Leere Tabelle mit einer Spalte erstellen
+ model->setHeaderData(0, Qt::Horizontal, tr("Profile")); //Spalte name definieren
+ content->setModel(model);
+
+ QItemSelectionModel *selectionModel = new QItemSelectionModel(model);
+ content->setSelectionModel(selectionModel);
+ QHeaderView *headerView = content->horizontalHeader();
+ headerView->setStretchLastSection(true);
+
+ content->setEditTriggers(QAbstractItemView::NoEditTriggers); //Die Einträge in der Tabelle werden nicht editierbar.
+ content->setSelectionMode(QAbstractItemView::ExtendedSelection); //Damit mehere Einträge selektierbar werden.
+
+ content->resizeColumnToContents(0);
+
+
+
+ uidiag->add->setDisabled(true);
+ uidiag->edit->setDisabled(true);
+ uidiag->edit->setVisible(false);
+ uidiag->remove->setDisabled(true);
+ uidiag->load->setDisabled(true);
+ uidiag->lineEdit->setDisabled(true);
+
+ setUpProfile();
+
+ connect(uidiag->add, SIGNAL(clicked ()), this, SLOT(AddProfile()));
+ connect(uidiag->new_2, SIGNAL(clicked ()), this, SLOT(onNew()));
+ connect(uidiag->load, SIGNAL(clicked ()), this, SLOT(onLoad()));
+ connect(uidiag->remove, SIGNAL(clicked ()), this, SLOT(removeProfile()));
+ connect(uidiag->close, SIGNAL(clicked ()), this, SLOT(accept()));
+ connect(content, SIGNAL(clicked(const QModelIndex)), this, SLOT(selectionChange(const QModelIndex)));
+ //show();
+
+}
+
+profileDialog::~profileDialog()
+{
+ // TODO Auto-generated destructor stub
+}
+
+void profileDialog::setUpProfile()
+{
+ QStringList list = MainWindow::getWindow()->getProfilList();
+ for (int i=0; i<list.size(); i++)
+ {
+ model->insertRow(0, QModelIndex());
+ model->setData(model->index(0, 0, QModelIndex()),list.at(i));
+ }
+}
+
+void profileDialog::AddProfile()
+{
+ QString name = QString(uidiag->lineEdit->text());
+ if (!ProfilList.contains(name))
+ {
+ if (!name.isEmpty())
+ {
+ model->insertRow(0, QModelIndex());
+ model->setData(model->index(0, 0, QModelIndex()),name);
+ ProfilList.append(name);
+ MainWindow::getWindow()->saveSettings(name);
+ uidiag->lineEdit->setText("");
+ }
+ else
+ {
+ QString message = QString(tr("This field can't be empty."));
+ QMessageBox::information(this, "PVS", message);
+ }
+ }
+ else
+ {
+ QString message = QString(tr("This name is already in the list."));
+ QMessageBox::information(this, "PVS", message);
+ }
+}
+
+void profileDialog::removeProfile()
+{
+ QTableView *temp = static_cast<QTableView*>(content);
+ QItemSelectionModel *selectionModel = temp->selectionModel();
+
+ QModelIndexList indexes = selectionModel->selectedRows();
+ QModelIndex index;
+
+ foreach(index, indexes)
+ {
+ int row = content->currentIndex().row();
+ QString current = model->index(content->currentIndex().row(), 0).data(Qt::DisplayRole).toString();
+ model->removeRow(row, QModelIndex());
+ ProfilList.removeOne(current);
+ MainWindow::getWindow()->removeProfil(current);
+ }
+
+
+ /* if (temp->model()->rowCount()<=0)
+ {*/
+ uidiag->remove->setDisabled(true);
+ uidiag->edit->setDisabled(true);
+ uidiag->add->setDisabled(true);
+ uidiag->load->setDisabled(true);
+ //}
+}
+
+void profileDialog::onNew()
+{
+ uidiag->add->setDisabled(false);
+ uidiag->lineEdit->setDisabled(false);
+ uidiag->lineEdit->setFocus();
+}
+
+void profileDialog::onLoad()
+{
+ QTableView *temp = static_cast<QTableView*>(content);
+ QItemSelectionModel *selectionModel = temp->selectionModel();
+
+ QModelIndexList indexes = selectionModel->selectedRows();
+ QModelIndex index;
+ if (indexes.size()>1)
+ {
+ QMessageBox::information(this, "PVS", tr("You can only load one profile at time"));
+ }
+ else if(indexes.size() == 1)
+ {
+ foreach(index, indexes)
+ {
+ //int row = content->currentIndex().row();
+ QString current = model->index(content->currentIndex().row(), 0).data(Qt::DisplayRole).toString();
+ MainWindow::getWindow()->loadSettings(current);
+ }
+ }
+
+ emit accept();
+}
+
+void profileDialog::selectionChange(const QModelIndex & index)
+{
+ uidiag->remove->setDisabled(false);
+ uidiag->edit->setDisabled(false);
+ uidiag->add->setDisabled(false);
+ uidiag->load->setDisabled(false);
+
+}
+
+void profileDialog::close()
+{
+ close();
+}
+
+
diff --git a/src/gui/profileDialog.h b/src/gui/profileDialog.h
new file mode 100644
index 0000000..5caebfa
--- /dev/null
+++ b/src/gui/profileDialog.h
@@ -0,0 +1,46 @@
+#ifndef PROFILEDIALOG_H_
+#define PROFILEDIALOG_H_
+
+#include <QtGui>
+#include <QDialog>
+#include <src/gui/mainWindow.h>
+
+namespace Ui
+{
+class Dialog;
+}
+
+class MainWindow;
+
+class profileDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ profileDialog(QWidget * parent = 0);
+ virtual ~profileDialog();
+
+ void setUpProfile();
+
+
+
+signals:
+ void selectionChanged (const QItemSelection &selected);
+
+private:
+ Ui::Dialog *uidiag;
+ QTableView *content;
+ QAbstractItemModel *model;
+ QItemSelectionModel *selectionModel;
+ QList<QString> ProfilList;
+
+private Q_SLOTS:
+ void AddProfile();
+ void removeProfile();
+ void onNew();
+ void onLoad();
+ void selectionChange(const QModelIndex & index);
+ void close();
+};
+
+#endif /* PROFILEDIALOG_H_ */
diff --git a/src/gui/projectionDialog.cpp b/src/gui/projectionDialog.cpp
new file mode 100644
index 0000000..c091f54
--- /dev/null
+++ b/src/gui/projectionDialog.cpp
@@ -0,0 +1,140 @@
+/*
+# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+# -----------------------------------------------------------------------------
+# projectionDialog.cpp
+ Dialog to select client for the projection
+# -----------------------------------------------------------------------------
+*/
+
+#include "projectionDialog.h"
+#include "ui_projectionDialog.h"
+#include <src/gui/mainWindow.h>
+#include <QtGui>
+#include <iostream>
+
+ProjectionDialog::ProjectionDialog(QWidget *parent) :
+ QDialog(parent),
+ pui(new Ui::projectionDialog)
+{
+ pui->setupUi(this);
+ this->setWindowTitle(tr("Target for Projection"));
+
+ source = MainWindow::getConnectionList()->getSelectedClients()->front();
+ setupContent(MainWindow::getWindow()->getConnectionList()->getTargetToDisplay(source));
+
+ pui->send->setDisabled(true);
+
+ connect( pui->send, SIGNAL( clicked() ), this, SLOT( sendListToProject() ) );
+ connect( pui->cancel, SIGNAL( clicked() ), this, SLOT( cancelProject() ) );
+ connect( pui->checkBox, SIGNAL( clicked() ), this, SLOT( selectAll() ) );
+}
+
+ProjectionDialog::~ProjectionDialog()
+{
+ delete pui;
+ QCheckBox* cbox;
+ foreach(cbox, checkList)
+ {
+ disconnect( cbox, SIGNAL( clicked() ), this, SLOT( sendState() ) );
+ }
+}
+
+void ProjectionDialog::setupContent(QList<QString> content)
+{
+ if (!content.isEmpty())
+ {
+ QString item;
+ foreach(item, content)
+ {
+ QCheckBox *checkbox = new QCheckBox(item,this);
+ pui->verticalLayout_2->addWidget(checkbox);
+ checkList.push_back(checkbox);
+ connect( checkbox, SIGNAL( clicked() ), this, SLOT( sendState() ) );
+ }
+ }
+ else
+ {
+ QLabel *textInfo = new QLabel(this);
+ textInfo->setText("No Target available");
+ pui->verticalLayout_2->addWidget(textInfo);
+ pui->checkBox->setDisabled(true);
+ }
+}
+
+void ProjectionDialog::sendListToProject()
+{
+ MainWindow::getConnectionList()->setProjectProporties(source);
+ QCheckBox* cbox;
+
+ foreach(cbox, checkList)
+ {
+ if (cbox->isChecked())
+ {
+ MainWindow::getConnectionList()->addTargetToProjectList(cbox->text());
+ }
+ }
+ emit accept();
+}
+
+void ProjectionDialog::cancelProject()
+{
+ emit reject();
+}
+
+void ProjectionDialog::sendState()
+{
+ QCheckBox* cbox;
+ bool set = false;
+
+ foreach(cbox, checkList)
+ {
+ if (cbox->isChecked())
+ {
+ pui->send->setDisabled(false);
+ set = true;
+ break;
+ }
+ }
+
+ if (!set)
+ pui->send->setDisabled(true);
+
+}
+
+void ProjectionDialog::selectAll()
+{
+ if(pui->checkBox->isChecked())
+ {
+ QCheckBox* cbox;
+ foreach(cbox, checkList)
+ cbox->setChecked(true);
+ pui->send->setDisabled(false);
+ }
+ else
+ {
+ QCheckBox* cbox;
+ foreach(cbox, checkList)
+ cbox->setChecked(false);
+ pui->send->setDisabled(true);
+ }
+}
+
+void ProjectionDialog::changeEvent(QEvent *e)
+{
+ QDialog::changeEvent(e);
+ switch (e->type()) {
+ case QEvent::LanguageChange:
+ pui->retranslateUi(this);
+ break;
+ default:
+ break;
+ }
+}
diff --git a/src/gui/projectionDialog.h b/src/gui/projectionDialog.h
new file mode 100644
index 0000000..842d255
--- /dev/null
+++ b/src/gui/projectionDialog.h
@@ -0,0 +1,46 @@
+/*
+ * projectionDialog.h
+ *
+ * Created on: 28.02.2010
+ * Author: achillenana
+ */
+
+#ifndef PROJECTIONDIALOG_H_
+#define PROJECTIONDIALOG_H_
+
+#include <QDialog>
+#include <QCheckBox>
+//#include <src/gui/mainWindow.h>
+
+
+class MainWindow;
+
+namespace Ui {
+ class projectionDialog;
+}
+
+class ProjectionDialog : public QDialog {
+ Q_OBJECT
+public:
+ ProjectionDialog(QWidget *parent = 0);
+ ~ProjectionDialog();
+
+ void setupContent(QList<QString> content);
+
+protected:
+ void changeEvent(QEvent *e);
+
+private:
+ Ui::projectionDialog *pui;
+ std::list<QCheckBox *> checkList;
+ QString source;
+
+private slots:
+ void sendListToProject();
+ void cancelProject();
+ void sendState();
+ void selectAll();
+};
+
+
+#endif /* PROJECTIONDIALOG_H_ */
diff --git a/src/gui/serverChatDialog.cpp b/src/gui/serverChatDialog.cpp
new file mode 100644
index 0000000..ec1f299
--- /dev/null
+++ b/src/gui/serverChatDialog.cpp
@@ -0,0 +1,281 @@
+/*
+ # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of
+ # Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # -----------------------------------------------------------------------------
+ # serverChatDialog.cpp
+ # - graphical chat interface for the pvsmgr
+ # -----------------------------------------------------------------------------
+ */
+
+#include "serverChatDialog.h"
+#include <src/gui/mainWindow.h>
+#include "ui_serverChatDialog.h"
+
+ServerChatDialog::ServerChatDialog(QWidget *parent) :
+ QDialog(parent), uichat(new Ui::ServerChatDialogClass)
+{
+ uichat->setupUi(this);
+ _nickname = "PVSMGR";
+ connect(uichat->pushButton, SIGNAL(clicked()), this, SLOT(chat_send()));
+
+ // add first tab for public messages
+ uichat->tabWidget->clear();
+ QTextEdit *t = new QTextEdit();
+ t->setReadOnly(true);
+ uichat->tabWidget->addTab(t, "@all");
+ _hash = new QHash<QString, QTextEdit*> ();
+ _hash->insert(uichat->tabWidget->tabText(0), t);
+
+ // setup menu
+ _menu = new QMenu();
+ _sendFileAction = new QAction(tr("&Send File..."), this);
+ _menu->addAction(_sendFileAction);
+
+ connect(uichat->listWidget, SIGNAL(doubleClicked(QModelIndex)), this,
+ SLOT(addTab(QModelIndex)));
+ connect(uichat->tabWidget, SIGNAL(tabCloseRequested(int)), this,
+ SLOT(removeTab(int)));
+ connect(uichat->tabWidget, SIGNAL(currentChanged(int)), this, SLOT(removeIcon(int)));
+ connect(uichat->listWidget, SIGNAL(customContextMenuRequested(QPoint)), this,
+ SLOT(showMenu(QPoint)));
+ connect(_sendFileAction, SIGNAL(triggered()), this, SLOT(sendFile()));
+
+ this->setAcceptDrops(true);
+}
+
+ServerChatDialog::~ServerChatDialog()
+{
+}
+
+void ServerChatDialog::setTrayIcon(QSystemTrayIcon *trayIcon)
+{
+ // _trayIcon = trayIcon;
+ // FIXME: messageClicked() is always emitted, not only on chat msg
+ //connect(_trayIcon, SIGNAL(messageClicked()), this, SLOT(open()));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Slots
+
+void ServerChatDialog::open()
+{
+ uichat->lineEdit->setFocus();
+ setVisible(true);
+}
+
+void ServerChatDialog::chat_receive(QString nick_from, QString nick_to,
+ QString msg)
+{
+ qDebug("[%s] R %s <- %s : %s", metaObject()->className(),
+ qPrintable(nick_to), qPrintable(nick_from), qPrintable(msg));
+
+ if (nick_to == uichat->tabWidget->tabText(0))
+ showMsg(nick_from, msg, getTab(nick_to)); // public message or own msg
+ else
+ {
+ if (nick_to == "PVSMGR")
+ showMsg(nick_from, msg, getTab(nick_from)); // private message
+ else if (nick_from == "PVSMGR")
+ showMsg(nick_from, msg, getTab(nick_to)); // private message
+ }
+}
+
+void ServerChatDialog::chat_send()
+{
+ QString msg = uichat->lineEdit->text();
+ if (msg != "")
+ {
+ msg = "PVSMGR:"+ msg;
+ QString nick_to = uichat->tabWidget->tabText(uichat->tabWidget->currentIndex());
+ PVSMsg myMsg(PVSMESSAGE, nick_to, msg, 0);
+ MainWindow::getWindow()->sendChatMsg(myMsg);
+ uichat->lineEdit->clear();
+ uichat->lineEdit->setFocus();
+
+ qDebug("[%s] S %s -> %s : %s", metaObject()->className(),
+ qPrintable(_nickname), qPrintable(nick_to), qPrintable(msg));
+
+ }
+}
+
+void ServerChatDialog::chat_nicklist_update()
+{
+ uichat->listWidget->clear();
+ uichat->listWidget->addItems(_nickList);
+}
+
+void ServerChatDialog::chat_client_add(QString nick)
+{
+ if (!_nickList.contains(nick))
+ _nickList.append(nick);
+ showEvent("-> " + nick + tr(" has joined the chat."));
+}
+
+void ServerChatDialog::chat_client_remove(QString nick)
+{
+ _nickList.removeOne(nick);
+ showEvent("<- " + nick + tr(" has left the chat."));
+}
+
+void ServerChatDialog::addTab(QModelIndex i)
+{
+ QString text = i.data().toString();
+ if (_hash->contains(text))
+ {
+ uichat->tabWidget->setCurrentWidget(_hash->value(text));
+ }
+ else
+ {
+ QTextEdit *t = new QTextEdit();
+ t->setReadOnly(true);
+ uichat->tabWidget->setCurrentIndex(uichat->tabWidget->addTab(t, text));
+ _hash->insert(text, t);
+ }
+ uichat->lineEdit->setFocus();
+}
+
+void ServerChatDialog::removeTab(int i)
+{
+ if (i != 0)
+ {
+ _tabList.removeOne(_hash->value(uichat->tabWidget->tabText(i)));
+ _hash->remove(uichat->tabWidget->tabText(i));
+ uichat->tabWidget->removeTab(i);
+ uichat->lineEdit->setFocus();
+ }
+}
+
+void ServerChatDialog::removeIcon(int i)
+{
+ uichat->tabWidget->setTabIcon(i, QIcon());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Private
+
+QTextEdit* ServerChatDialog::getTab(QString text)
+{
+ if (!_hash->contains(text))
+ {
+ QTextEdit *t = new QTextEdit();
+ t->setReadOnly(true);
+ uichat->tabWidget->addTab(t, text);
+ _hash->insert(text, t);
+ _tabList.append(t);
+ }
+ uichat->lineEdit->setFocus();
+ return _hash->value(text);
+}
+
+void ServerChatDialog::showMsg(QString nick_from, QString msg, QTextEdit *t)
+{
+ // move cursor at the end
+ t->moveCursor(QTextCursor::End);
+
+ // print time
+ if (nick_from == "PVSMGR")
+ t->setTextColor(QColor(0, 100, 100));
+ else
+ t->setTextColor(QColor(0, 100, 0));
+ t->append("[" + QTime::currentTime().toString("hh:mm") + "] ");
+
+ // print nickname
+ if (nick_from == "PVSMGR")
+ t->setTextColor(QColor(0, 100, 255));
+ else
+ t->setTextColor(QColor(0, 0, 255));
+ t->insertPlainText("<" + nick_from + "> ");
+
+ // print message
+ if (nick_from == "PVSMGR")
+ t->setTextColor(QColor(100, 100, 100));
+ else
+ t->setTextColor(QColor(0, 0, 0));
+ t->insertPlainText(msg);
+
+ // show icon if not current tab
+ if (uichat->tabWidget->currentIndex() != uichat->tabWidget->indexOf(t))
+ uichat->tabWidget->setTabIcon(uichat->tabWidget->indexOf(t), QIcon(":chat_msg16.svg"));
+}
+
+void ServerChatDialog::showMenu(QPoint p)
+{
+ _menu->popup(uichat->listWidget->mapToGlobal(p));
+}
+
+void ServerChatDialog::sendFile()
+{
+ ServerFileTransfert* sft = new ServerFileTransfert(this);
+ QString cTab = uichat->listWidget->currentItem()->text();
+ QString hostIP = PVSConnectionManager::getManager()->getClientFromUsername(cTab)->getIp();
+ if (hostIP != "")
+ sft->sendFileToHost(hostIP);
+}
+
+void ServerChatDialog::sendFile(QString filename)
+{
+ if (uichat->tabWidget->currentIndex() == 0 || filename == "")
+ return;
+
+ // ask user
+ QString nick = uichat->tabWidget->tabText(uichat->tabWidget->currentIndex());
+ QMessageBox::StandardButton result = QMessageBox::question(0,
+ tr("PVS File Transfer with ")+nick,
+ tr("Send file '") + filename + tr("' to ") + nick + "?",
+ QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
+
+ if (result != QMessageBox::Ok)
+ return;
+
+ ServerFileTransfert* sft = new ServerFileTransfert(this);
+ QString hostIP = PVSConnectionManager::getManager()->getClientFromUsername(nick)->getIp();
+ if (hostIP != "")
+ sft->sendFileToHost(hostIP, filename);
+}
+
+
+void ServerChatDialog::showEvent(QString msg)
+{
+ QTextEdit *t = _hash->value(uichat->tabWidget->tabText(0));
+
+ // move cursor at the end
+ t->moveCursor(QTextCursor::End);
+
+ t->setTextColor(QColor(150, 150, 150));
+
+ // print time
+ t->append("[" + QTime::currentTime().toString("hh:mm") + "] ");
+
+ // print message
+ t->insertPlainText(msg);
+}
+
+void ServerChatDialog::dragEnterEvent(QDragEnterEvent *event)
+{
+ event->accept();
+}
+
+void ServerChatDialog::dragMoveEvent(QDragMoveEvent *event)
+{
+ event->accept();
+}
+
+void ServerChatDialog::dragLeaveEvent(QDragLeaveEvent *event)
+{
+ event->accept();
+}
+
+void ServerChatDialog::dropEvent(QDropEvent *event)
+{
+ event->accept();
+ if (event->mimeData()->hasUrls())
+ sendFile(event->mimeData()->urls()[0].toLocalFile());
+}
diff --git a/src/gui/serverChatDialog.h b/src/gui/serverChatDialog.h
new file mode 100644
index 0000000..728af05
--- /dev/null
+++ b/src/gui/serverChatDialog.h
@@ -0,0 +1,67 @@
+#ifndef SERVERCHATDIALOG_H_
+#define SERVERCHATDIALOG_H_
+
+#include <QtGui>
+#include <src/gui/serverFileTransfert.h>
+#include "pvsinterface.h"
+
+class MainWindow;
+
+namespace Ui
+{
+ class ServerChatDialogClass;
+}
+
+class ServerChatDialog: public QDialog
+{
+ Q_OBJECT
+
+public:
+ ServerChatDialog(QWidget *parent = 0);
+ ~ServerChatDialog();
+ void setTrayIcon(QSystemTrayIcon *trayIcon);
+ void chat_nicklist_update();
+ void chat_client_add(QString nick);
+ void chat_client_remove(QString nick);
+
+public Q_SLOTS:
+ void open();
+ void chat_receive(QString nick_from, QString nick_to, QString msg);
+ void chat_send();
+
+
+private Q_SLOTS:
+ void addTab(QModelIndex i);
+ void sendFile();
+ void showMenu(QPoint p);
+ void removeTab(int i);
+ void removeIcon(int i);
+
+private:
+ Ui::ServerChatDialogClass *uichat;
+ QTextEdit* getTab(QString text);
+ void showMsg(QString nick_from, QString msg, QTextEdit *t);
+ void sendFile(QString filename);
+ void showEvent(QString msg);
+
+ QList<QTextEdit *> _tabList;
+
+ QHash<QString, QTextEdit*> *_hash;
+
+ QString _nickname;
+ QStringList _nickList;
+
+ QMenu* _menu;
+ QAction* _sendFileAction;
+
+protected:
+ void dragEnterEvent(QDragEnterEvent *event);
+ void dragMoveEvent(QDragMoveEvent *event);
+ void dragLeaveEvent(QDragLeaveEvent *event);
+ void dropEvent(QDropEvent *event);
+
+};
+
+
+
+#endif /* SERVERCHATDIALOG_H_ */
diff --git a/src/gui/serverFileTransfert.cpp b/src/gui/serverFileTransfert.cpp
new file mode 100644
index 0000000..22e268b
--- /dev/null
+++ b/src/gui/serverFileTransfert.cpp
@@ -0,0 +1,265 @@
+/*
+# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+# -----------------------------------------------------------------------------
+# src/gui/serverFileTransfert.cpp
+# This class manage any file transfert from and to server.
+# -----------------------------------------------------------------------------
+*/
+
+#include "serverFileTransfert.h"
+
+ServerFileTransfert::ServerFileTransfert(QWidget *parent):
+ QDialog(parent)
+{
+ setupUi(this);
+ _file = NULL;
+ _socket = NULL;
+
+ connect(this, SIGNAL(finished(int)), this, SLOT(deleteLater()));
+}
+
+ServerFileTransfert::~ServerFileTransfert()
+{
+}
+
+void ServerFileTransfert::sendFileToHost(QString host)
+{
+ QString filename = QFileDialog::getOpenFileName(this, tr("Open File"),
+ QDir::homePath(), "");
+ if (filename == "")
+ {
+ reject();
+ return;
+ }
+ sendFileToHost(host, filename);
+}
+
+void ServerFileTransfert::sendFileToHost(QString host, QString filename)
+{
+ // open file
+ _file = new QFile(filename);
+ _file->open(QIODevice::ReadOnly);
+ _bytesToWrite = _file->size();
+ div = 1 + _bytesToWrite / 1000000000; // bc. progressBar supports only int
+
+ // get host from backend
+
+ // gui
+ filenameLabel->setText(filename);
+ progressBar->setValue(0);
+ progressBar->setMaximum(_bytesToWrite/div);
+ labelB->setText(formatSize(_bytesToWrite));
+ connect(cancelButton, SIGNAL(clicked()), this, SLOT(close()));
+
+ // open socket
+ _socket = new QTcpSocket();
+ _socket->connectToHost(host, 29481);
+ if (_socket->isOpen())
+ qDebug("connection open");
+ else
+ qDebug("connection closed");
+ qDebug("[%s] Remote host: %s", metaObject()->className(), qPrintable(host));
+
+ connect(_socket, SIGNAL(connected()), this, SLOT(sendHeader()));
+ connect(_socket, SIGNAL(disconnected()), this, SLOT(close()));
+ connect(_socket, SIGNAL(error(QAbstractSocket::SocketError)),
+ this, SLOT(error(QAbstractSocket::SocketError)));
+ qDebug("connect is set");
+}
+
+void ServerFileTransfert::receiveFileFromHost(QTcpSocket* socket)
+{
+
+ _bytesToRead = 0;
+ _socket = socket;
+
+ connect(_socket, SIGNAL(readyRead()), this, SLOT(receiveHeader()));
+ connect(_socket, SIGNAL(disconnected()), this, SLOT(close()));
+ connect(_socket, SIGNAL(error(QAbstractSocket::SocketError)),
+ this, SLOT(error(QAbstractSocket::SocketError)));
+
+ qDebug("[%s] New Connection: %s", metaObject()->className(),
+ qPrintable(_socket->peerAddress().toString()));
+}
+
+void ServerFileTransfert::sendHeader()
+{
+ qDebug("[%s] Sending header(1)...", metaObject()->className());
+ QFileInfo info(_file->fileName());
+ QString size = QString::number(_bytesToWrite);
+ QString header = "PVSMGR;" + info.fileName() + ";" + size + "\n";
+ _socket->write(header.toLocal8Bit());
+ connect(_socket, SIGNAL(readyRead()), this, SLOT(receiveAck()));
+ qDebug("[%s] Sending header...", metaObject()->className());
+}
+
+void ServerFileTransfert::receiveHeader()
+{
+ // parse header
+ QString header = QString::fromUtf8(_socket->readLine());
+ QStringList args = header.split(";");
+ QString nick = args[0];
+ QString filename = args[1];
+ _bytesToRead = args[2].toLongLong();
+ div = 1 + _bytesToRead / 1000000000; // bc. progressBar supports only int
+
+ qDebug("[%s] Received header.", metaObject()->className());
+
+ // ask user
+ QMessageBox::StandardButton result = QMessageBox::question(0,
+ tr("PVS File Transfer"),tr("User '") + nick +
+ tr("' would like to send you a file: ") + filename +
+ " (" + formatSize(_bytesToRead) + ").",
+ QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
+
+ if (result != QMessageBox::Ok)
+ {
+ sendAck(false);
+ return;
+ }
+
+ // open file
+ QString saveAs = QFileDialog::getSaveFileName(this, tr("Open File"),
+ QDir::homePath() + QDir::separator() + filename, "");
+ if (saveAs == "")
+ {
+ sendAck(false);
+ return;
+ }
+ _file = new QFile(saveAs);
+ _file->open(QIODevice::WriteOnly);
+
+ // gui
+ filenameLabel->setText(saveAs);
+ progressBar->setValue(0);
+ progressBar->setMaximum(_bytesToRead/div);
+ labelB->setText(formatSize(_bytesToRead));
+ connect(cancelButton, SIGNAL(clicked()), this, SLOT(close()));
+
+ sendAck(true);
+ show();
+}
+
+void ServerFileTransfert::sendAck(bool b)
+{
+ disconnect(_socket, SIGNAL(readyRead()), this, SLOT(receiveHeader()));
+
+ if (b)
+ {
+ QString ack = QString("ok\n");
+ _socket->write(ack.toUtf8());
+ qDebug("[%s] Sending ack...", metaObject()->className());
+ connect(_socket, SIGNAL(readyRead()), this, SLOT(receiveFile()));
+ }
+ else
+ {
+ QString ack = QString("no\n");
+ _socket->write(ack.toUtf8());
+ qDebug("[%s] Sending nack!!!", metaObject()->className());
+ close();
+ }
+}
+
+void ServerFileTransfert::receiveAck()
+{
+ QString ack = QString::fromUtf8(_socket->readLine());
+ if (ack != "ok\n")
+ {
+ qDebug("[%s] Received nack!", metaObject()->className());
+ close();
+ return;
+ }
+ qDebug("[%s] Received ack.", metaObject()->className());
+
+ disconnect(_socket, SIGNAL(readyRead()), this, SLOT(receiveAck()));
+ connect(_socket, SIGNAL(bytesWritten(qint64)), this, SLOT(sendFile()));
+ this->show();
+ qDebug("[%s] Sending file...", metaObject()->className());
+ sendFile();
+}
+
+void ServerFileTransfert::sendFile()
+{
+ if (_bytesToWrite == 0)
+ {
+ qDebug("[%s] Transfer completed.", metaObject()->className());
+ close(); // finished
+ }
+ else
+ {
+ qint64 bytesWritten = _socket->write(_file->read(1024)); // data left
+ _bytesToWrite -= bytesWritten;
+ progressBar->setValue(progressBar->value() + bytesWritten/div);
+ labelA->setText(formatSize(progressBar->value()*div));
+ }
+}
+
+void ServerFileTransfert::receiveFile()
+{
+ qint64 bytesRead = _file->write(_socket->readAll());
+ _bytesToRead -= bytesRead;
+ progressBar->setValue(progressBar->value() + bytesRead/div);
+ labelA->setText(formatSize(progressBar->value()*div));
+}
+
+void ServerFileTransfert::close()
+{
+ if (_file && _file->isOpen())
+ {
+ _file->close();
+ qDebug("[%s] File closed.", metaObject()->className());
+ }
+
+ if (_socket && _socket->isOpen())
+ {
+ disconnect(_socket, SIGNAL(readyRead()), this, SLOT(receiveAck()));
+ disconnect(_socket, SIGNAL(bytesWritten(qint64)), this, SLOT(sendFile()));
+ disconnect(_socket, SIGNAL(disconnected()), this, SLOT(close()));
+ disconnect(_socket, SIGNAL(connected()), this, SLOT(sendHeader()));
+ disconnect(_socket, SIGNAL(error(QAbstractSocket::SocketError)),
+ this, SLOT(error(QAbstractSocket::SocketError)));
+ _socket->disconnectFromHost();
+ qDebug("[%s] Connection closed.", metaObject()->className());
+ }
+
+ disconnect(cancelButton, SIGNAL(clicked()), this, SLOT(close()));
+
+ if (_bytesToWrite == 0)
+ {
+ accept();
+ QMessageBox::information(0, tr("PVS - File Transfer"),
+ tr("File Transfer complete."));
+ }
+ else
+ {
+ reject();
+ QMessageBox::warning(0, tr("PVS - File Transfer"),
+ tr("File Transfer canceled!"));
+ }
+}
+
+void ServerFileTransfert::error(QAbstractSocket::SocketError error)
+{
+ qDebug("[%s] Socket error: %i", metaObject()->className(), error);
+ close();
+}
+
+QString ServerFileTransfert::formatSize(qint64 size)
+{
+ if (size >= 1000000000) // GB
+ return QString("%1GB").arg((qreal)size / 1000000000, 0, 'f',1);
+ else if (size >= 1000000) // MB
+ return QString("%1MB").arg((qreal)size / 1000000, 0, 'f',1);
+ else if (size >= 1000) // KB
+ return QString("%1KB").arg((qreal)size / 1000, 0, 'f',1);
+ else // B
+ return QString("%1B").arg((qreal)size, 0, 'f',1);
+}
diff --git a/src/gui/serverFileTransfert.h b/src/gui/serverFileTransfert.h
new file mode 100644
index 0000000..96b30e5
--- /dev/null
+++ b/src/gui/serverFileTransfert.h
@@ -0,0 +1,52 @@
+#ifndef SERVERFILETRANSFERT_H_
+#define SERVERFILETRANSFERT_H_
+
+
+#include <QtGui>
+#include <QtNetwork>
+#include "ui_clientFileSendDialog.h"
+
+/*namespace Ui
+{
+ class ClientFileSendDialogClass;
+}*/
+
+class ServerFileTransfert: public QDialog,
+ private Ui::ClientFileSendDialogClass
+
+{
+ Q_OBJECT
+
+public:
+ ServerFileTransfert (QWidget *parent=0);
+ ~ServerFileTransfert ();
+
+ void sendFileToHost(QString host);
+ void sendFileToHost(QString host, QString filename);
+ void receiveFileFromHost(QTcpSocket* socket);
+
+ //Ui::ClientFileSendDialogClass* uitr;
+
+private Q_SLOTS:
+ void sendHeader();
+ void receiveHeader();
+ void receiveAck();
+ void sendFile();
+ void receiveFile();
+ void close();
+ void error(QAbstractSocket::SocketError error);
+
+private:
+ void sendAck(bool b);
+ QString formatSize(qint64 size);
+
+ QTcpSocket *_socket;
+ QFile *_file;
+ qint64 _bytesToWrite;
+ qint64 _bytesToRead;
+ int div;
+
+};
+
+
+#endif /* SERVERFILETRANSFERT_H_ */
diff --git a/src/gui/ui/aboutDialog.ui b/src/gui/ui/aboutDialog.ui
new file mode 100644
index 0000000..07d9852
--- /dev/null
+++ b/src/gui/ui/aboutDialog.ui
@@ -0,0 +1,251 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AboutDialogClass</class>
+ <widget class="QDialog" name="AboutDialogClass">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>460</width>
+ <height>363</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>PVS - About</string>
+ </property>
+ <property name="windowIcon">
+ <iconset resource="../../../pvsgui.qrc">
+ <normaloff>:/cam32.svg</normaloff>:/cam32.svg</iconset>
+ </property>
+ <property name="locale">
+ <locale language="English" country="UnitedStates"/>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_7">
+ <property name="text">
+ <string/>
+ </property>
+ <property name="pixmap">
+ <pixmap resource="../../../pvsgui.qrc">:/cam32.svg</pixmap>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string notr="true">&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'DejaVu Sans'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:24pt; font-weight:600;&quot;&gt;PVS&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <spacer name="horizontalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_version">
+ <property name="text">
+ <string notr="true">Version: xx.xx.xx</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_5">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="tab">
+ <attribute name="title">
+ <string>About</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string notr="true">Pool Video Switch</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string notr="true">feedback@openslx.org</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string notr="true">(c) 2009-2010, OpenSLX Project, University of Freiburg</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string notr="true">&lt;a href=&quot;http://lab.openslx.org/projects/pvs&quot;&gt;http://lab.openslx.org/projects/pvs&lt;/a&gt;</string>
+ </property>
+ <property name="openExternalLinks">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_6">
+ <property name="text">
+ <string>&lt;a href=&quot;http://www.gnu.org/licenses/gpl-2.0.txt&quot;&gt;License: GNU General Public License Version 2&lt;/a&gt;</string>
+ </property>
+ <property name="openExternalLinks">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab_1">
+ <attribute name="title">
+ <string>Authors</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <widget class="QPlainTextEdit" name="plainTextEdit_authors">
+ <property name="lineWrapMode">
+ <enum>QPlainTextEdit::NoWrap</enum>
+ </property>
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ <property name="plainText">
+ <string/>
+ </property>
+ <property name="centerOnScroll">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab_2">
+ <attribute name="title">
+ <string>Translation</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <item>
+ <widget class="QPlainTextEdit" name="plainTextEdit_translation">
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Close</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="../../../pvsgui.qrc"/>
+ </resources>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>AboutDialogClass</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>388</x>
+ <y>351</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>109</x>
+ <y>333</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/gui/ui/clientChatDialog.ui b/src/gui/ui/clientChatDialog.ui
new file mode 100644
index 0000000..43f64a9
--- /dev/null
+++ b/src/gui/ui/clientChatDialog.ui
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ClientChatDialogClass</class>
+ <widget class="QDialog" name="ClientChatDialogClass">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>641</width>
+ <height>659</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>PVS - Chat </string>
+ </property>
+ <property name="windowIcon">
+ <iconset resource="../../../pvsgui.qrc">
+ <normaloff>:/cam32.svg</normaloff>:/cam32.svg</iconset>
+ </property>
+ <property name="locale">
+ <locale language="English" country="UnitedStates"/>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QSplitter" name="splitter">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <widget class="QListWidget" name="listWidget">
+ <property name="maximumSize">
+ <size>
+ <width>150</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="contextMenuPolicy">
+ <enum>Qt::CustomContextMenu</enum>
+ </property>
+ <property name="sortingEnabled">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="tabPosition">
+ <enum>QTabWidget::South</enum>
+ </property>
+ <property name="tabsClosable">
+ <bool>true</bool>
+ </property>
+ <widget class="QWidget" name="tab">
+ <attribute name="title">
+ <string notr="true">@all</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout"/>
+ </widget>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="lineEdit"/>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pushButton">
+ <property name="text">
+ <string>&amp;Send</string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="../../../pvsgui.qrc"/>
+ </resources>
+ <connections>
+ <connection>
+ <sender>lineEdit</sender>
+ <signal>returnPressed()</signal>
+ <receiver>pushButton</receiver>
+ <slot>click()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>252</x>
+ <y>560</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>529</x>
+ <y>589</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/gui/ui/clientConfigDialog.ui b/src/gui/ui/clientConfigDialog.ui
new file mode 100644
index 0000000..3262b6b
--- /dev/null
+++ b/src/gui/ui/clientConfigDialog.ui
@@ -0,0 +1,280 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ClientConfigDialogClass</class>
+ <widget class="QDialog" name="ClientConfigDialogClass">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>438</width>
+ <height>257</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>PVS - Configuration</string>
+ </property>
+ <property name="windowIcon">
+ <iconset resource="../../../pvsgui.qrc">
+ <normaloff>:/cam32.svg</normaloff>:/cam32.svg</iconset>
+ </property>
+ <property name="locale">
+ <locale language="English" country="UnitedStates"/>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="tabPosition">
+ <enum>QTabWidget::North</enum>
+ </property>
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="tabPermissions">
+ <attribute name="title">
+ <string>Permissions</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_6">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Allow vnc access to lecturer?</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ <property name="checkable">
+ <bool>false</bool>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <item>
+ <widget class="QRadioButton" name="radioButtonLecturerRW">
+ <property name="text">
+ <string>Full access</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="radioButtonLecturerRO">
+ <property name="text">
+ <string>View only</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="radioButtonLecturerNO">
+ <property name="text">
+ <string>None</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="Line" name="line_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="title">
+ <string>Allow vnc access to other?</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QRadioButton" name="radioButtonOtherRW">
+ <property name="text">
+ <string>Full access</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="radioButtonOtherRO">
+ <property name="text">
+ <string>View only</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="radioButtonOtherNO">
+ <property name="text">
+ <string>None</string>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_5">
+ <item>
+ <widget class="QCheckBox" name="checkBoxAllowChat">
+ <property name="text">
+ <string>Accept chat messages</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="checkBoxAllowFiletransfer">
+ <property name="text">
+ <string>Accept file transfers</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tabDisplay">
+ <attribute name="title">
+ <string>Display</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <widget class="QComboBox" name="comboBox">
+ <item>
+ <property name="text">
+ <string>Top Left</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Top Center</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Top Right</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Bottom Left</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Bottom Center</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Bottom Right</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Save</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="../../../pvsgui.qrc"/>
+ </resources>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>ClientConfigDialogClass</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>62</x>
+ <y>274</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>4</x>
+ <y>37</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>ClientConfigDialogClass</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>195</x>
+ <y>274</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>233</x>
+ <y>32</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>radioButtonOtherRW</sender>
+ <signal>clicked()</signal>
+ <receiver>radioButtonLecturerRW</receiver>
+ <slot>click()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>87</x>
+ <y>167</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>198</x>
+ <y>56</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>radioButtonLecturerNO</sender>
+ <signal>clicked()</signal>
+ <receiver>radioButtonOtherNO</receiver>
+ <slot>click()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>149</x>
+ <y>106</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>84</x>
+ <y>219</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/gui/ui/clientFileReceiveDialog.ui b/src/gui/ui/clientFileReceiveDialog.ui
new file mode 100644
index 0000000..af3a135
--- /dev/null
+++ b/src/gui/ui/clientFileReceiveDialog.ui
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ClientFileReceiveDialogClass</class>
+ <widget class="QDialog" name="ClientFileReceiveDialogClass">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>208</width>
+ <height>108</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>PVS - File Transfer</string>
+ </property>
+ <property name="windowIcon">
+ <iconset resource="../../../pvsgui.qrc">
+ <normaloff>:/cam32.svg</normaloff>:/cam32.svg</iconset>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="filenameLabel">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QProgressBar" name="progressBar">
+ <property name="value">
+ <number>0</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Receiving from:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="labelNick">
+ <property name="text">
+ <string>unknown</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="labelA">
+ <property name="text">
+ <string>0</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>/</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="labelB">
+ <property name="text">
+ <string>0</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="cancelButton">
+ <property name="text">
+ <string>&amp;Cancel</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="../../../pvsgui.qrc"/>
+ </resources>
+ <connections>
+ <connection>
+ <sender>cancelButton</sender>
+ <signal>clicked()</signal>
+ <receiver>ClientFileReceiveDialogClass</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>220</x>
+ <y>242</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>345</x>
+ <y>270</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/gui/ui/clientFileSendDialog.ui b/src/gui/ui/clientFileSendDialog.ui
new file mode 100644
index 0000000..d2d9c75
--- /dev/null
+++ b/src/gui/ui/clientFileSendDialog.ui
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ClientFileSendDialogClass</class>
+ <widget class="QDialog" name="ClientFileSendDialogClass">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>186</width>
+ <height>108</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>PVS - File Transfer</string>
+ </property>
+ <property name="windowIcon">
+ <iconset resource="../../../pvsgui.qrc">
+ <normaloff>:/cam32.svg</normaloff>:/cam32.svg</iconset>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="filenameLabel">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QProgressBar" name="progressBar">
+ <property name="value">
+ <number>0</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Sending to:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="labelNick">
+ <property name="text">
+ <string>unknown</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="labelA">
+ <property name="text">
+ <string>0</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>/</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="labelB">
+ <property name="text">
+ <string>0</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="cancelButton">
+ <property name="text">
+ <string>&amp;Cancel</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="../../../pvsgui.qrc"/>
+ </resources>
+ <connections>
+ <connection>
+ <sender>cancelButton</sender>
+ <signal>clicked()</signal>
+ <receiver>ClientFileSendDialogClass</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>116</x>
+ <y>61</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>38</x>
+ <y>55</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/gui/ui/clientInfoDialog.ui b/src/gui/ui/clientInfoDialog.ui
new file mode 100644
index 0000000..a186641
--- /dev/null
+++ b/src/gui/ui/clientInfoDialog.ui
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>InfoDialogClass</class>
+ <widget class="QDialog" name="InfoDialogClass">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>312</width>
+ <height>203</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>PVS - Information</string>
+ </property>
+ <property name="windowIcon">
+ <iconset resource="../../../pvsgui.qrc">
+ <normaloff>:/cam32.svg</normaloff>:/cam32.svg</iconset>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">QDialog {
+ background-color: white;
+}</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="hostLabel">
+ <property name="text">
+ <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'DejaVu Sans'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:72pt; font-weight:600; color:#0000ff;&quot;&gt;HOST&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="passwdLabel">
+ <property name="text">
+ <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'DejaVu Sans'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:48pt; font-weight:600; color:#ff0000;&quot;&gt;PASSWD&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="../../../pvsgui.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/gui/ui/clientNicklistDialog.ui b/src/gui/ui/clientNicklistDialog.ui
new file mode 100644
index 0000000..afd84f1
--- /dev/null
+++ b/src/gui/ui/clientNicklistDialog.ui
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ClientNicklistDialogClass</class>
+ <widget class="QDialog" name="ClientNicklistDialogClass">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>264</width>
+ <height>396</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>PVS - Users</string>
+ </property>
+ <property name="windowIcon">
+ <iconset resource="../../../pvsgui.qrc">
+ <normaloff>:/cam32.svg</normaloff>:/cam32.svg</iconset>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Select user:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QListWidget" name="listWidget"/>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="../../../pvsgui.qrc"/>
+ </resources>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>ClientNicklistDialogClass</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>258</x>
+ <y>390</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>373</x>
+ <y>526</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>ClientNicklistDialogClass</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>258</x>
+ <y>390</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>428</x>
+ <y>525</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>listWidget</sender>
+ <signal>doubleClicked(QModelIndex)</signal>
+ <receiver>ClientNicklistDialogClass</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>88</x>
+ <y>120</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>27</x>
+ <y>375</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/gui/ui/clientToolbar.ui b/src/gui/ui/clientToolbar.ui
new file mode 100644
index 0000000..5a59c5f
--- /dev/null
+++ b/src/gui/ui/clientToolbar.ui
@@ -0,0 +1,214 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ClientToolbarClass</class>
+ <widget class="QWidget" name="ClientToolbarClass">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>577</width>
+ <height>28</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">QFrame {
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #f6f7fa, stop: 1 #dadbde);
+ border-radius: 0px;
+}
+QLabel {
+ background-color: none;
+}
+/* QPushButton */
+QPushButton {
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #f6f7fa, stop: 1 #dadbde);
+ border: 2px solid #8f8f91;
+ border-radius: 4px;
+ min-width: 80px;
+}
+QPushButton:hover {
+ border: 2px solid rgb(0, 170, 255);
+}
+QPushButton:pressed {
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #dadbde, stop: 1 #f6f7fa);
+}
+QPushButton::menu-indicator {
+ image: url(:/darrow16.svg);
+}
+/* QCheckBox */
+QCheckBox {
+}
+QCheckBox::indicator {
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #f6f7fa, stop: 1 #dadbde);
+ border: 2px solid #8f8f91;
+ border-radius: 4px;
+ width: 16px;
+ height: 16px;
+}
+QCheckBox::indicator:unchecked {
+}
+QCheckBox::indicator:unchecked:hover {
+ border: 2px solid rgb(0, 170, 255);
+}
+QCheckBox::indicator:unchecked:pressed {
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #dadbde, stop: 1 #f6f7fa);
+}
+QCheckBox::indicator:checked {
+ image: url(:/ok16.svg);
+}
+QCheckBox::indicator:checked:hover {
+ border: 2px solid rgb(0, 170, 255);
+}
+QCheckBox::indicator:checked:pressed {
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #dadbde, stop: 1 #f6f7fa);
+}
+</string>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QFrame" name="frame">
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QPushButton" name="pvsButton">
+ <property name="toolTip">
+ <string>Menu</string>
+ </property>
+ <property name="text">
+ <string notr="true">Menu</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Host:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="hostButton">
+ <property name="toolTip">
+ <string>Click to connect</string>
+ </property>
+ <property name="text">
+ <string>-</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="statusLabel">
+ <property name="text">
+ <string notr="true">&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'DejaVu Sans'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; color:#ff0000;&quot;&gt;Offline&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="vncCheckBox">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Enable/Disable VNC only for this session</string>
+ </property>
+ <property name="text">
+ <string>Allow VNC</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'DejaVu Sans'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt; font-weight:600; font-style:italic; color:#0055ff;&quot;&gt;Pool Video Switch&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="maximumSize">
+ <size>
+ <width>16</width>
+ <height>16</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="pixmap">
+ <pixmap resource="../../../pvsgui.qrc">:/cam32.svg</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="../../../pvsgui.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/gui/ui/dialog.ui b/src/gui/ui/dialog.ui
new file mode 100644
index 0000000..ec16160
--- /dev/null
+++ b/src/gui/ui/dialog.ui
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MsgDialog</class>
+ <widget class="QDialog" name="MsgDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>193</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ <widget class="QWidget" name="layoutWidget">
+ <property name="geometry">
+ <rect>
+ <x>20</x>
+ <y>20</y>
+ <width>351</width>
+ <height>171</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QTextEdit" name="message"/>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>108</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="cancel">
+ <property name="text">
+ <string>Cancel</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="send">
+ <property name="text">
+ <string>Send</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/gui/ui/mainwindow.ui b/src/gui/ui/mainwindow.ui
new file mode 100644
index 0000000..eb49d1b
--- /dev/null
+++ b/src/gui/ui/mainwindow.ui
@@ -0,0 +1,540 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>838</width>
+ <height>607</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>PVSmgr</string>
+ </property>
+ <widget class="QWidget" name="centralWidget">
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QScrollArea" name="scrollArea">
+ <property name="styleSheet">
+ <string>border-color: rgb(0, 0, 0);</string>
+ </property>
+ <property name="widgetResizable">
+ <bool>true</bool>
+ </property>
+ <widget class="QWidget" name="scrollAreaWidgetContents">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>776</width>
+ <height>534</height>
+ </rect>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="0">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>VNC quality</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="vncQuality">
+ <item>
+ <property name="text">
+ <string>HIGH</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>MEDIUM</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>LOW</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item>
+ <widget class="Line" name="separator">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="setPassword">
+ <property name="text">
+ <string>Set password</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="thumbStatus">
+ <item>
+ <property name="text">
+ <string>Thumbnailratio</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Thumbnailrate</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSlider" name="horizontalSlider">
+ <property name="minimum">
+ <number>25</number>
+ </property>
+ <property name="maximum">
+ <number>200</number>
+ </property>
+ <property name="singleStep">
+ <number>25</number>
+ </property>
+ <property name="pageStep">
+ <number>25</number>
+ </property>
+ <property name="value">
+ <number>25</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksBothSides</enum>
+ </property>
+ <property name="tickInterval">
+ <number>0</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string> 0</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>%</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QSplitter" name="splitter_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <widget class="QSplitter" name="splitter">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <widget class="QWidget" name="ClWidget" native="true">
+ <property name="minimumSize">
+ <size>
+ <width>150</width>
+ <height>240</height>
+ </size>
+ </property>
+ <property name="styleSheet">
+ <string>background-color: rgb(255, 255, 255);</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_5">
+ <item row="0" column="0">
+ <layout class="QGridLayout" name="ClientGLayout"/>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="widget" native="true">
+ <property name="styleSheet">
+ <string>background-color: rgb(150, 150, 150);</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_4">
+ <item row="0" column="0">
+ <layout class="QVBoxLayout" name="VconWinLayout"/>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <widget class="QTextEdit" name="pvsLog"/>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QMenuBar" name="menuBar">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>838</width>
+ <height>28</height>
+ </rect>
+ </property>
+ <widget class="QMenu" name="menu_File">
+ <property name="title">
+ <string>&amp;File</string>
+ </property>
+ <widget class="QMenu" name="menuLoad_profile">
+ <property name="title">
+ <string>Load profile </string>
+ </property>
+ </widget>
+ <addaction name="action_Disconnect"/>
+ <addaction name="separator"/>
+ <addaction name="actionCreate_profile"/>
+ <addaction name="separator"/>
+ <addaction name="menuLoad_profile"/>
+ <addaction name="separator"/>
+ <addaction name="action_Exit"/>
+ </widget>
+ <widget class="QMenu" name="menuClients">
+ <property name="title">
+ <string>&amp;Clients</string>
+ </property>
+ <addaction name="actionShow_Fullname"/>
+ <addaction name="actionShow_Hostname_IP"/>
+ <addaction name="actionShow_Username"/>
+ <addaction name="separator"/>
+ <addaction name="actionVNC_Placeholders"/>
+ </widget>
+ <widget class="QMenu" name="menuLogging">
+ <property name="title">
+ <string>&amp;Logging</string>
+ </property>
+ <addaction name="actionShow_Log"/>
+ <addaction name="separator"/>
+ <addaction name="actionShow_Normal"/>
+ <addaction name="actionShow_Error"/>
+ <addaction name="actionShow_Network"/>
+ <addaction name="actionShow_Terminal"/>
+ <addaction name="actionShow_Chat"/>
+ </widget>
+ <widget class="QMenu" name="menu_Help">
+ <property name="title">
+ <string>&amp;Help</string>
+ </property>
+ <addaction name="actionAbout_pvs"/>
+ </widget>
+ <addaction name="menu_File"/>
+ <addaction name="menuClients"/>
+ <addaction name="menuLogging"/>
+ <addaction name="menu_Help"/>
+ </widget>
+ <widget class="QStatusBar" name="statusBar"/>
+ <widget class="QToolBar" name="toolBar">
+ <property name="maximumSize">
+ <size>
+ <width>129000</width>
+ <height>12900</height>
+ </size>
+ </property>
+ <property name="windowTitle">
+ <string>toolBar</string>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="autoFillBackground">
+ <bool>true</bool>
+ </property>
+ <property name="movable">
+ <bool>true</bool>
+ </property>
+ <property name="toolButtonStyle">
+ <enum>Qt::ToolButtonIconOnly</enum>
+ </property>
+ <property name="floatable">
+ <bool>false</bool>
+ </property>
+ <attribute name="toolBarArea">
+ <enum>LeftToolBarArea</enum>
+ </attribute>
+ <attribute name="toolBarBreak">
+ <bool>false</bool>
+ </attribute>
+ <addaction name="action_Exit"/>
+ <addaction name="action_Disconnect"/>
+ <addaction name="actionFoto"/>
+ <addaction name="actionView"/>
+ <addaction name="actionLock"/>
+ <addaction name="actionChat"/>
+ </widget>
+ <action name="actionShow_Username">
+ <property name="checkable">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Show Username</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+3</string>
+ </property>
+ </action>
+ <action name="actionShow_Hostname_IP">
+ <property name="checkable">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Show IP</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+2</string>
+ </property>
+ </action>
+ <action name="actionVNC_Placeholders">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>VNC-Placeholders</string>
+ </property>
+ </action>
+ <action name="actionShow_Log">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Show Log</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+L</string>
+ </property>
+ </action>
+ <action name="actionShow_Normal">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Show Normal</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+O</string>
+ </property>
+ </action>
+ <action name="actionShow_Error">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Show Error</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+E</string>
+ </property>
+ </action>
+ <action name="actionShow_Network">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Show Network</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+N</string>
+ </property>
+ </action>
+ <action name="actionShow_Terminal">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Show Terminal</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+T</string>
+ </property>
+ </action>
+ <action name="actionShow_Chat">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Show Chat</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+G</string>
+ </property>
+ </action>
+ <action name="actionAbout_pvs">
+ <property name="text">
+ <string>About pvs</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+P</string>
+ </property>
+ </action>
+ <action name="action100_x_100">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>100 x 100</string>
+ </property>
+ </action>
+ <action name="action200_x_200">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>200 x 200</string>
+ </property>
+ </action>
+ <action name="action500_x_500">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>500 x 500</string>
+ </property>
+ </action>
+ <action name="action_Disconnect">
+ <property name="icon">
+ <iconset resource="../../../pvsmgr.qrc">
+ <normaloff>:/logout</normaloff>:/logout</iconset>
+ </property>
+ <property name="text">
+ <string>&amp;Disconnect</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+W</string>
+ </property>
+ </action>
+ <action name="action_Exit">
+ <property name="icon">
+ <iconset resource="../../../pvsmgr.qrc">
+ <normaloff>:/exit</normaloff>
+ <normalon>:/exit</normalon>:/exit</iconset>
+ </property>
+ <property name="text">
+ <string>&amp;Exit</string>
+ </property>
+ <property name="toolTip">
+ <string>Exit</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+Q</string>
+ </property>
+ </action>
+ <action name="actionFoto">
+ <property name="icon">
+ <iconset resource="../../../pvsmgr.qrc">
+ <normaloff>:/photos</normaloff>:/photos</iconset>
+ </property>
+ <property name="text">
+ <string>Foto</string>
+ </property>
+ <property name="toolTip">
+ <string>Foto</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+F</string>
+ </property>
+ </action>
+ <action name="actionView">
+ <property name="icon">
+ <iconset resource="../../../pvsmgr.qrc">
+ <normaloff>:/restore</normaloff>:/restore</iconset>
+ </property>
+ <property name="text">
+ <string>view</string>
+ </property>
+ <property name="toolTip">
+ <string>View</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+V</string>
+ </property>
+ </action>
+ <action name="actionLock">
+ <property name="icon">
+ <iconset resource="../../../pvsmgr.qrc">
+ <normaloff>:/lock</normaloff>:/lock</iconset>
+ </property>
+ <property name="text">
+ <string>lock</string>
+ </property>
+ <property name="toolTip">
+ <string>Lock or Unlock all Clients</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+A</string>
+ </property>
+ </action>
+ <action name="actionCreate_profile">
+ <property name="icon">
+ <iconset resource="../../../pvsmgr.qrc">
+ <normaloff>:/profile</normaloff>:/profile</iconset>
+ </property>
+ <property name="text">
+ <string>Profile &amp;manager</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+M</string>
+ </property>
+ </action>
+ <action name="actionShow_Fullname">
+ <property name="text">
+ <string>Show Name</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+1</string>
+ </property>
+ </action>
+ <action name="actionChat">
+ <property name="icon">
+ <iconset resource="../../../pvsmgr.qrc">
+ <normaloff>:/chat</normaloff>:/chat</iconset>
+ </property>
+ <property name="text">
+ <string>Chat</string>
+ </property>
+ <property name="toolTip">
+ <string>Start Chat with client(s)</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+D</string>
+ </property>
+ </action>
+ <action name="dummy">
+ <property name="text">
+ <string>-</string>
+ </property>
+ </action>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources>
+ <include location="../../../pvsmgr.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/gui/ui/mainwindowtouch.ui b/src/gui/ui/mainwindowtouch.ui
new file mode 100644
index 0000000..9030b17
--- /dev/null
+++ b/src/gui/ui/mainwindowtouch.ui
@@ -0,0 +1,645 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>1349</width>
+ <height>768</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>PVSmgr</string>
+ </property>
+ <widget class="QWidget" name="centralWidget">
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QScrollArea" name="scrollArea">
+ <property name="styleSheet">
+ <string>border-color: rgb(0, 0, 0);</string>
+ </property>
+ <property name="widgetResizable">
+ <bool>true</bool>
+ </property>
+ <widget class="QWidget" name="scrollAreaWidgetContents">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>1327</width>
+ <height>658</height>
+ </rect>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="0" column="0">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QComboBox" name="comboBox_touch1">
+ <property name="font">
+ <font>
+ <pointsize>15</pointsize>
+ </font>
+ </property>
+ <item>
+ <property name="text">
+ <string>All</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Lock</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Unlock</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Unproject</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Backgroundimage</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item>
+ <widget class="Line" name="line_5">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>VNC-Quality</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="vncQuality">
+ <property name="font">
+ <font>
+ <pointsize>15</pointsize>
+ </font>
+ </property>
+ <item>
+ <property name="text">
+ <string>HIGH</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>MEDIUM</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>LOW</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item>
+ <widget class="Line" name="line_3">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pushButton_2">
+ <property name="font">
+ <font>
+ <pointsize>15</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>ClientList</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Line" name="line_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pushButton">
+ <property name="font">
+ <font>
+ <pointsize>15</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>Profile</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Line" name="line_4">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QProgressBar" name="progressBar">
+ <property name="styleSheet">
+ <string>border-color: rgb(0, 0, 0);</string>
+ </property>
+ <property name="value">
+ <number>0</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Line" name="separator">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="setPassword">
+ <property name="font">
+ <font>
+ <pointsize>15</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>setPassword</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="thumbStatus">
+ <property name="font">
+ <font>
+ <pointsize>15</pointsize>
+ </font>
+ </property>
+ <item>
+ <property name="text">
+ <string>Thumbnailratio</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Thumbnailrate</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSlider" name="horizontalSlider">
+ <property name="minimum">
+ <number>25</number>
+ </property>
+ <property name="maximum">
+ <number>200</number>
+ </property>
+ <property name="singleStep">
+ <number>25</number>
+ </property>
+ <property name="pageStep">
+ <number>25</number>
+ </property>
+ <property name="value">
+ <number>25</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksBothSides</enum>
+ </property>
+ <property name="tickInterval">
+ <number>0</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string> 0</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>%</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="0">
+ <widget class="QSplitter" name="splitter_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <widget class="QSplitter" name="splitter">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <widget class="QWidget" name="ClWidget" native="true">
+ <property name="minimumSize">
+ <size>
+ <width>150</width>
+ <height>240</height>
+ </size>
+ </property>
+ <property name="styleSheet">
+ <string>background-color: rgb(255, 255, 255);</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_5">
+ <item row="0" column="0">
+ <layout class="QGridLayout" name="ClientGLayout"/>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="widget" native="true">
+ <property name="styleSheet">
+ <string>background-color: rgb(150, 150, 150);</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_4">
+ <item row="0" column="0">
+ <layout class="QVBoxLayout" name="VconWinLayout"/>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <widget class="QTextEdit" name="pvsLog"/>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QStatusBar" name="statusBar"/>
+ <widget class="QToolBar" name="toolBar">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>129000</width>
+ <height>12900</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>15</pointsize>
+ <kerning>true</kerning>
+ </font>
+ </property>
+ <property name="windowTitle">
+ <string>toolBar</string>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="autoFillBackground">
+ <bool>true</bool>
+ </property>
+ <property name="movable">
+ <bool>false</bool>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>50</width>
+ <height>50</height>
+ </size>
+ </property>
+ <property name="toolButtonStyle">
+ <enum>Qt::ToolButtonIconOnly</enum>
+ </property>
+ <property name="floatable">
+ <bool>false</bool>
+ </property>
+ <attribute name="toolBarArea">
+ <enum>TopToolBarArea</enum>
+ </attribute>
+ <attribute name="toolBarBreak">
+ <bool>false</bool>
+ </attribute>
+ <addaction name="action_Exit"/>
+ <addaction name="separator"/>
+ <addaction name="actionFoto"/>
+ <addaction name="separator"/>
+ <addaction name="actionView"/>
+ <addaction name="separator"/>
+ <addaction name="actionProjection"/>
+ <addaction name="separator"/>
+ <addaction name="actionUnprojection"/>
+ <addaction name="separator"/>
+ <addaction name="actionLocksingle"/>
+ <addaction name="separator"/>
+ <addaction name="actionUnlocksingle"/>
+ <addaction name="separator"/>
+ <addaction name="actionLock"/>
+ <addaction name="separator"/>
+ <addaction name="actionresetall"/>
+ <addaction name="separator"/>
+ <addaction name="actionDozent"/>
+ </widget>
+ <action name="actionShow_Username">
+ <property name="checkable">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Show Username</string>
+ </property>
+ </action>
+ <action name="actionShow_Hostname_IP">
+ <property name="checkable">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Show Hostname/IP</string>
+ </property>
+ </action>
+ <action name="actionVNC_Placeholders">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>VNC-Placeholders</string>
+ </property>
+ </action>
+ <action name="actionShow_Log">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Show Log</string>
+ </property>
+ </action>
+ <action name="actionShow_Normal">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Show Normal</string>
+ </property>
+ </action>
+ <action name="actionShow_Error">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Show Error</string>
+ </property>
+ </action>
+ <action name="actionShow_Network">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Show Network</string>
+ </property>
+ </action>
+ <action name="actionShow_Terminal">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Show Terminal</string>
+ </property>
+ </action>
+ <action name="actionShow_Chat">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Show Chat</string>
+ </property>
+ </action>
+ <action name="actionAbout_pvs">
+ <property name="text">
+ <string>About pvs</string>
+ </property>
+ </action>
+ <action name="action100_x_100">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>100 x 100</string>
+ </property>
+ </action>
+ <action name="action200_x_200">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>200 x 200</string>
+ </property>
+ </action>
+ <action name="action500_x_500">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>500 x 500</string>
+ </property>
+ </action>
+ <action name="action_Disconnect">
+ <property name="icon">
+ <iconset resource="../../../pvsmgr.qrc">
+ <normaloff>:/logout</normaloff>:/logout</iconset>
+ </property>
+ <property name="text">
+ <string>&amp;Disconnect</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+W</string>
+ </property>
+ </action>
+ <action name="action_Exit">
+ <property name="icon">
+ <iconset resource="../../../pvsmgr.qrc">
+ <normaloff>:/exit</normaloff>
+ <normalon>:/exit</normalon>:/exit</iconset>
+ </property>
+ <property name="text">
+ <string>&amp;Exit</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+Q</string>
+ </property>
+ </action>
+ <action name="actionFoto">
+ <property name="icon">
+ <iconset resource="../../../pvsmgr.qrc">
+ <normaloff>:/photos</normaloff>:/photos</iconset>
+ </property>
+ <property name="text">
+ <string>Foto</string>
+ </property>
+ <property name="toolTip">
+ <string>Foto</string>
+ </property>
+ </action>
+ <action name="actionView">
+ <property name="icon">
+ <iconset resource="../../../pvsmgr.qrc">
+ <normaloff>:/restore</normaloff>:/restore</iconset>
+ </property>
+ <property name="text">
+ <string>view</string>
+ </property>
+ <property name="toolTip">
+ <string>View</string>
+ </property>
+ </action>
+ <action name="actionLock">
+ <property name="icon">
+ <iconset resource="../../../pvsmgr.qrc">
+ <normaloff>:/lock</normaloff>:/lock</iconset>
+ </property>
+ <property name="text">
+ <string>lock</string>
+ </property>
+ <property name="toolTip">
+ <string>Lock All Clients</string>
+ </property>
+ </action>
+ <action name="actionCreate_profile">
+ <property name="icon">
+ <iconset resource="../../../pvsmgr.qrc">
+ <normaloff>:/profile</normaloff>:/profile</iconset>
+ </property>
+ <property name="text">
+ <string>Create profile</string>
+ </property>
+ </action>
+ <action name="actionresetall">
+ <property name="icon">
+ <iconset>
+ <activeon>:/icons/reset.png</activeon>
+ </iconset>
+ </property>
+ <property name="text">
+ <string>resetall</string>
+ </property>
+ <property name="toolTip">
+ <string>Reset Projections and Locks</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+R</string>
+ </property>
+ </action>
+ <action name="actionLocksingle">
+ <property name="icon">
+ <iconset resource="../../../pvsmgr.qrc">
+ <normaloff>:/icons/locksingle.png</normaloff>:/icons/locksingle.png</iconset>
+ </property>
+ <property name="text">
+ <string>locksingle</string>
+ </property>
+ <property name="toolTip">
+ <string>Locks a Single Target</string>
+ </property>
+ </action>
+ <action name="actionUnlocksingle">
+ <property name="icon">
+ <iconset resource="../../../pvsmgr.qrc">
+ <normaloff>:/icons/unlocksingle.png</normaloff>:/icons/unlocksingle.png</iconset>
+ </property>
+ <property name="text">
+ <string>unlocksingle</string>
+ </property>
+ <property name="toolTip">
+ <string>Unlocks a single target</string>
+ </property>
+ </action>
+ <action name="actionProjection">
+ <property name="icon">
+ <iconset resource="../../../pvsmgr.qrc">
+ <normaloff>:/icons/projection.png</normaloff>:/icons/projection.png</iconset>
+ </property>
+ <property name="text">
+ <string>projection</string>
+ </property>
+ <property name="toolTip">
+ <string>Projects a single target</string>
+ </property>
+ </action>
+ <action name="actionUnprojection">
+ <property name="icon">
+ <iconset resource="../../../pvsmgr.qrc">
+ <normaloff>:/icons/unprojection.png</normaloff>:/icons/unprojection.png</iconset>
+ </property>
+ <property name="text">
+ <string>unprojection</string>
+ </property>
+ <property name="toolTip">
+ <string>Unprojects a single target</string>
+ </property>
+ </action>
+ <action name="actionDozent">
+ <property name="icon">
+ <iconset resource="../../../pvsmgr.qrc">
+ <normaloff>:/dozent2</normaloff>:/dozent2</iconset>
+ </property>
+ <property name="text">
+ <string>dozent</string>
+ </property>
+ <property name="toolTip">
+ <string>Select Tutor PC</string>
+ </property>
+ </action>
+ <action name="actionShow_Fullname">
+ <property name="text">
+ <string>Show Name</string>
+ </property>
+ </action>
+ <action name="actionChat">
+ <property name="icon">
+ <iconset resource="../../../pvsmgr.qrc">
+ <normaloff>:/chat</normaloff>:/chat</iconset>
+ </property>
+ <property name="text">
+ <string>Chat</string>
+ </property>
+ <property name="toolTip">
+ <string>Start chat with client(s)</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+D</string>
+ </property>
+ </action>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources>
+ <include location="../../../pvsmgr.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/gui/ui/profileDialog.ui b/src/gui/ui/profileDialog.ui
new file mode 100644
index 0000000..3302a56
--- /dev/null
+++ b/src/gui/ui/profileDialog.ui
@@ -0,0 +1,179 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Dialog</class>
+ <widget class="QDialog" name="Dialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>332</width>
+ <height>485</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>ProfileDialog</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="0" column="0">
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QSplitter" name="splitter">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <widget class="QWidget" name="widget" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="styleSheet">
+ <string>background-color: rgb(255, 255, 255);</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="0">
+ <layout class="QGridLayout" name="gridLayout"/>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="layoutWidget_2">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QPushButton" name="remove">
+ <property name="text">
+ <string>&amp;Remove</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_6">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>18</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="edit">
+ <property name="text">
+ <string>&amp;Edit</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_5">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>18</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="new_2">
+ <property name="text">
+ <string>&amp;New</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="load">
+ <property name="text">
+ <string>&amp;Load</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>218</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLineEdit" name="lineEdit"/>
+ </item>
+ <item>
+ <widget class="QPushButton" name="add">
+ <property name="text">
+ <string>Add</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QPushButton" name="close">
+ <property name="text">
+ <string>Close</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/gui/ui/projectionDialog.ui b/src/gui/ui/projectionDialog.ui
new file mode 100644
index 0000000..17cdf05
--- /dev/null
+++ b/src/gui/ui/projectionDialog.ui
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>projectionDialog</class>
+ <widget class="QDialog" name="projectionDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>234</width>
+ <height>282</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="1" column="0">
+ <widget class="QFrame" name="frame">
+ <property name="styleSheet">
+ <string notr="true">QFrame{
+border-color: rgb(0, 0, 0);
+border: 1px outset black;
+}</string>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Sunken</enum>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <layout class="QVBoxLayout" name="verticalLayout_2"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QCheckBox" name="checkBox">
+ <property name="text">
+ <string>Select all</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>108</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="cancel">
+ <property name="text">
+ <string>Cancel</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="send">
+ <property name="text">
+ <string>Project</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>15</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Select Target for projection</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/gui/ui/serverChatDialog.ui b/src/gui/ui/serverChatDialog.ui
new file mode 100644
index 0000000..973d803
--- /dev/null
+++ b/src/gui/ui/serverChatDialog.ui
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ServerChatDialogClass</class>
+ <widget class="QDialog" name="ServerChatDialogClass">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>641</width>
+ <height>659</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>PVSmgr - Chat </string>
+ </property>
+ <property name="windowIcon">
+ <iconset resource="../../../pvsgui.qrc">
+ <normaloff>:/cam32.svg</normaloff>:/cam32.svg</iconset>
+ </property>
+ <property name="locale">
+ <locale language="English" country="UnitedStates"/>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QSplitter" name="splitter">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <widget class="QListWidget" name="listWidget">
+ <property name="maximumSize">
+ <size>
+ <width>150</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="contextMenuPolicy">
+ <enum>Qt::CustomContextMenu</enum>
+ </property>
+ <property name="sortingEnabled">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="tabPosition">
+ <enum>QTabWidget::South</enum>
+ </property>
+ <property name="tabsClosable">
+ <bool>true</bool>
+ </property>
+ <widget class="QWidget" name="tab">
+ <attribute name="title">
+ <string notr="true">@all</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout"/>
+ </widget>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="lineEdit"/>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pushButton">
+ <property name="text">
+ <string>&amp;Send</string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="../../../pvsgui.qrc"/>
+ </resources>
+ <connections>
+ <connection>
+ <sender>lineEdit</sender>
+ <signal>returnPressed()</signal>
+ <receiver>pushButton</receiver>
+ <slot>click()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>252</x>
+ <y>560</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>529</x>
+ <y>589</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/gui/ui/startdialog.ui b/src/gui/ui/startdialog.ui
new file mode 100644
index 0000000..8001862
--- /dev/null
+++ b/src/gui/ui/startdialog.ui
@@ -0,0 +1,195 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Test</class>
+ <widget class="QDialog" name="Test">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>367</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="geometry">
+ <rect>
+ <x>20</x>
+ <y>250</y>
+ <width>341</width>
+ <height>32</height>
+ </rect>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ <widget class="QWidget" name="gridLayoutWidget">
+ <property name="geometry">
+ <rect>
+ <x>60</x>
+ <y>10</y>
+ <width>301</width>
+ <height>231</height>
+ </rect>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="1" column="0">
+ <widget class="QCheckBox" name="checkBox">
+ <property name="toolTip">
+ <string>Zur Bedienung mit Tastatur und Maus</string>
+ </property>
+ <property name="text">
+ <string>Standard-Oberfläche</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QCheckBox" name="checkBox_2">
+ <property name="toolTip">
+ <string>Zur Bedienung an einem Touchscreen</string>
+ </property>
+ <property name="text">
+ <string>Touchscreen-Oberfläche</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="Line" name="line_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="Line" name="line_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="KIconButton" name="kiconbutton">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>150</y>
+ <width>51</width>
+ <height>41</height>
+ </rect>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">background-image: url(:icons/touch.jpg);</string>
+ </property>
+ </widget>
+ <widget class="KIconButton" name="kiconbutton_2">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>60</y>
+ <width>51</width>
+ <height>41</height>
+ </rect>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">background-image: url(:icons/keyboard.jpg);</string>
+ </property>
+ </widget>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>KIconButton</class>
+ <extends>QPushButton</extends>
+ <header>kicondialog.h</header>
+ </customwidget>
+ </customwidgets>
+ <tabstops>
+ <tabstop>buttonBox</tabstop>
+ <tabstop>kiconbutton_2</tabstop>
+ <tabstop>checkBox_2</tabstop>
+ <tabstop>checkBox</tabstop>
+ <tabstop>kiconbutton</tabstop>
+ </tabstops>
+ <resources>
+ <include location="startdialog.qrc"/>
+ </resources>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>Test</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>Test</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>checkBox</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>checkBox_2</receiver>
+ <slot>setDisabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>180</x>
+ <y>81</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>180</x>
+ <y>169</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>checkBox_2</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>checkBox</receiver>
+ <slot>setDisabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>180</x>
+ <y>169</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>180</x>
+ <y>81</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/gui/ui/touchgui.ui b/src/gui/ui/touchgui.ui
new file mode 100644
index 0000000..05d7614
--- /dev/null
+++ b/src/gui/ui/touchgui.ui
@@ -0,0 +1,322 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>PVSMainWindow</class>
+ <widget class="QMainWindow" name="PVSMainWindow">
+ <property name="windowModality">
+ <enum>Qt::NonModal</enum>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>800</width>
+ <height>600</height>
+ </rect>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>800</width>
+ <height>600</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>800</width>
+ <height>600</height>
+ </size>
+ </property>
+ <property name="cursor">
+ <cursorShape>PointingHandCursor</cursorShape>
+ </property>
+ <property name="windowTitle">
+ <string>MainWindow</string>
+ </property>
+ <widget class="QWidget" name="centralWidget">
+ <widget class="QWidget" name="horizontalLayoutWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>801</width>
+ <height>41</height>
+ </rect>
+ </property>
+ <layout class="QHBoxLayout" name="ButtonList">
+ <item>
+ <widget class="QComboBox" name="AllUsersBox">
+ <property name="font">
+ <font>
+ <pointsize>15</pointsize>
+ </font>
+ </property>
+ <item>
+ <property name="text">
+ <string>Alle</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Sperren/entsperren</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Beamerbild verteilen</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="MarkedUsersBox">
+ <property name="font">
+ <font>
+ <pointsize>15</pointsize>
+ </font>
+ </property>
+ <item>
+ <property name="text">
+ <string>Auswahl</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Aktualisieren</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Sperren/Entsperren</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Einzelansicht</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Einzelhilfe</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="PropertyButton">
+ <property name="font">
+ <font>
+ <pointsize>15</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>Einstellungen</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="ExitButton">
+ <property name="font">
+ <font>
+ <pointsize>15</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>Beenden</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="horizontalLayoutWidget_2">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>530</y>
+ <width>801</width>
+ <height>31</height>
+ </rect>
+ </property>
+ <layout class="QHBoxLayout" name="Slider">
+ <item>
+ <widget class="QPushButton" name="NavigateLeft">
+ <property name="text">
+ <string>&lt;-</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSlider" name="horizontalSlider">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="NavigateRight">
+ <property name="text">
+ <string>-&gt;</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="ClWidget" native="true">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>40</y>
+ <width>151</width>
+ <height>481</height>
+ </rect>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>150</width>
+ <height>240</height>
+ </size>
+ </property>
+ <property name="styleSheet">
+ <string>background-color: rgb(255, 255, 255);</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_5">
+ <item row="0" column="0">
+ <layout class="QGridLayout" name="ClientGLayout"/>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="widget" native="true">
+ <property name="geometry">
+ <rect>
+ <x>160</x>
+ <y>40</y>
+ <width>631</width>
+ <height>481</height>
+ </rect>
+ </property>
+ <property name="styleSheet">
+ <string>background-color: rgb(150, 150, 150);</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_4">
+ <item row="0" column="0">
+ <layout class="QVBoxLayout" name="VconWinLayout"/>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <widget class="QMenuBar" name="menuBar">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>800</width>
+ <height>24</height>
+ </rect>
+ </property>
+ <widget class="QMenu" name="menuTestApp">
+ <property name="title">
+ <string>Datei</string>
+ </property>
+ <addaction name="actionDisconnect"/>
+ <addaction name="actionBeenden"/>
+ </widget>
+ <widget class="QMenu" name="menuAnsicht">
+ <property name="title">
+ <string>Ansicht</string>
+ </property>
+ <addaction name="actionVollbild"/>
+ </widget>
+ <widget class="QMenu" name="menuHilfe">
+ <property name="title">
+ <string>Hilfe</string>
+ </property>
+ <addaction name="actionGibts_noch_keine"/>
+ </widget>
+ <widget class="QMenu" name="menuLogging">
+ <property name="title">
+ <string>Logging</string>
+ </property>
+ </widget>
+ <addaction name="menuTestApp"/>
+ <addaction name="menuAnsicht"/>
+ <addaction name="menuHilfe"/>
+ <addaction name="menuLogging"/>
+ </widget>
+ <action name="actionBeenden">
+ <property name="text">
+ <string>Beenden</string>
+ </property>
+ <property name="shortcut">
+ <string>Alt+B</string>
+ </property>
+ </action>
+ <action name="actionGibts_noch_keine">
+ <property name="text">
+ <string>Version</string>
+ </property>
+ </action>
+ <action name="actionVollbild">
+ <property name="text">
+ <string>Vollbild</string>
+ </property>
+ </action>
+ <action name="actionDisconnect">
+ <property name="text">
+ <string>Disconnect</string>
+ </property>
+ </action>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>actionBeenden</sender>
+ <signal>activated()</signal>
+ <receiver>PVSMainWindow</receiver>
+ <slot>close()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>-1</x>
+ <y>-1</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>399</x>
+ <y>299</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>ExitButton</sender>
+ <signal>clicked()</signal>
+ <receiver>PVSMainWindow</receiver>
+ <slot>close()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>109</x>
+ <y>129</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>299</x>
+ <y>199</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>actionVollbild</sender>
+ <signal>activated()</signal>
+ <receiver>PVSMainWindow</receiver>
+ <slot>showMaximized()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>-1</x>
+ <y>-1</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>399</x>
+ <y>299</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/net/SslServer.cpp b/src/net/SslServer.cpp
new file mode 100644
index 0000000..e353e0a
--- /dev/null
+++ b/src/net/SslServer.cpp
@@ -0,0 +1,130 @@
+/*
+# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+# -----------------------------------------------------------------------------
+# src/net/SslServer.cpp
+# - provide QTcpServer-like behaviour for SSL
+# -----------------------------------------------------------------------------
+*/
+
+#include "SslServer.h"
+#include <QtNetwork/QSslCipher>
+#include <QtNetwork/QSslSocket>
+#include "src/util/CertManager.h"
+
+
+SslServer::SslServer()
+{
+ _tmr = startTimer(7000);
+ //QSslSocket::setDefaultCiphers(QSslSocket::supportedCiphers());
+}
+
+SslServer::~SslServer()
+{
+ killTimer((_tmr));
+}
+
+void SslServer::incomingConnection(int socketDescriptor)
+{
+ QSslSocket *serverSocket = new QSslSocket(this);
+ connect(serverSocket,
+ SIGNAL(sslErrors(const QList<QSslError> &)),
+ this,
+ SLOT(sslErrors(const QList<QSslError> &))
+ );
+ serverSocket->setPrivateKey(CertManager::getPrivateKey("manager"));
+ serverSocket->setLocalCertificate(CertManager::getCertificate("manager"));
+ serverSocket->setPeerVerifyMode(QSslSocket::VerifyNone);
+ serverSocket->setProtocol(QSsl::SslV3);
+ //printf("Keylen %d\n", serverSocket->privateKey().length());
+ if (serverSocket->setSocketDescriptor(socketDescriptor))
+ {
+ // Once the connection is successfully encrypted, raise out newConnection event
+ connect(serverSocket, SIGNAL(encrypted()), this, SIGNAL(newConnection()));
+ serverSocket->startServerEncryption();
+ _pending.push_back(serverSocket);
+ }
+ else
+ {
+ delete serverSocket;
+ }
+}
+
+void SslServer :: sslErrors ( const QList<QSslError> & errors )
+{
+ printf("FIXME: SSL ERRORS on SERVER: %s\n", errors.begin()->errorString().toUtf8().data());
+}
+
+void SslServer::timerEvent (QTimerEvent* event)
+{
+ // Remove all sockets marked for deletion
+ for (QList<QSslSocket*>::iterator it = _delete.begin(); it != _delete.end(); it++)
+ {
+ (*it)->deleteLater();
+ }
+ _delete.clear();
+ // Mark all sockets for deletion where the ssl handshake did not happen after connecting
+ /*
+ bool flag;
+ do
+ {
+ flag = false;
+ for (QList<QSslSocket*>::iterator it = _pending.begin(); it != _pending.end(); it++)
+ {
+ if ((*it)->state() != QAbstractSocket::ConnectedState || !(*it)->isEncrypted())
+ {
+ _delete.push_back(*it);
+ _pending.removeAll(*it);
+ flag = true;
+ break;
+ }
+
+ }
+ }
+ while (flag);
+ */
+ _delete.append(_pending);
+ _pending.clear();
+}
+
+bool SslServer::hasPendingConnections()
+{
+ for (QList<QSslSocket*>::iterator it = _pending.begin(); it != _pending.end(); it++)
+ {
+ printf("State: %d - Encrypted: %d\n", (int)(*it)->state(), (*it)->isEncrypted());
+ if ((*it)->state() == QAbstractSocket::ConnectedState && (*it)->isEncrypted()) return true;
+ }
+ return false;
+}
+
+QTcpSocket* SslServer::nextPendingConnection()
+{
+ for (QList<QSslSocket*>::iterator it = _pending.begin(); it != _pending.end(); it++)
+ {
+ if ((*it)->state() == QAbstractSocket::ConnectedState && (*it)->isEncrypted())
+ {
+ _pending.removeAll(*it);
+ _delete.removeAll(*it);
+ return *it;
+ }
+ }
+ for (QList<QSslSocket*>::iterator it = _delete.begin(); it != _delete.end(); it++)
+ {
+ if ((*it)->state() == QAbstractSocket::ConnectedState && (*it)->isEncrypted())
+ {
+ _pending.removeAll(*it);
+ _delete.removeAll(*it);
+ return *it;
+ }
+ }
+ return NULL;
+}
+
+
diff --git a/src/net/SslServer.h b/src/net/SslServer.h
new file mode 100644
index 0000000..b1efeea
--- /dev/null
+++ b/src/net/SslServer.h
@@ -0,0 +1,50 @@
+/*
+# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+# -----------------------------------------------------------------------------
+# src/net/SslServer.cpp
+# - provide QTcpServer-like behaviour for SSL
+# -----------------------------------------------------------------------------
+*/
+
+#ifndef SSLSERVER_H_
+#define SSLSERVER_H_
+
+#include <QtCore/QList>
+#include <QtNetwork/QTcpServer>
+#include <QtNetwork/QSslError>
+
+class QSslSocket;
+
+class SslServer : public QTcpServer
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void sslErrors ( const QList<QSslError> & errors );
+
+public:
+ SslServer();
+ virtual ~SslServer();
+
+ virtual bool hasPendingConnections ();
+ // This one has to return a TcpSocket as we're overwriting from the base class
+ // just cast it to QSslSocket later
+ virtual QTcpSocket* nextPendingConnection();
+
+protected:
+ virtual void incomingConnection(int socketDescriptor);
+ void timerEvent (QTimerEvent* event);
+ QList<QSslSocket*> _pending;
+ QList<QSslSocket*> _delete;
+ int _tmr;
+};
+
+#endif /* SSLSERVER_H_ */
diff --git a/src/net/pvsClientConnection.cpp b/src/net/pvsClientConnection.cpp
new file mode 100644
index 0000000..dff40d5
--- /dev/null
+++ b/src/net/pvsClientConnection.cpp
@@ -0,0 +1,178 @@
+/*
+# Copyright (c) 2009,2010 - OpenSLX Project, Computer Center University of
+# Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+# -----------------------------------------------------------------------------
+# pvsClientConnection.cpp
+# - ???.
+# -----------------------------------------------------------------------------
+*/
+
+#include "pvsClientConnection.h"
+#include "pvsListenServer.h"
+#include "src/util/consoleLogger.h"
+
+#include <cassert>
+#include <QtNetwork/QHostAddress>
+
+
+PVSClientConnection::PVSClientConnection(PVSListenServer* server, QSslSocket* sock)
+{
+ assert(sock);
+ assert(server);
+ _socket = sock;
+ _incomplete = NULL;
+ _toldDisconnect = false;
+ _server = server;
+ _lastData = time(NULL);
+ sock->setParent(this); // for automatic deletion
+ connect(_socket, SIGNAL(readyRead()), this, SLOT(sock_dataArrival()));
+ connect(_socket, SIGNAL(disconnected()), this, SLOT(sock_closed()));
+ connect(_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(sock_error(QAbstractSocket::SocketError)));
+}
+
+PVSClientConnection::~PVSClientConnection()
+{
+ this->closeConnection();
+ if (_incomplete != NULL) delete _incomplete;
+ if (_socket != NULL)
+ {
+ disconnect(_socket, SIGNAL(readyRead()), this, SLOT(sock_dataArrival()));
+ disconnect(_socket, SIGNAL(disconnected()), this, SLOT(sock_closed()));
+ disconnect(_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(sock_error(QAbstractSocket::SocketError)));
+ _socket->abort();
+ }
+}
+
+void PVSClientConnection::closeConnection()
+{
+ if (_toldDisconnect) return; // we already got served
+ if (_socket == NULL || _socket->state() == QAbstractSocket::UnconnectedState)
+ {
+ // should not happen but handled anyway
+ _toldDisconnect = true;
+ _server->disconnectClient(this);
+ return;
+ }
+ if (_socket->state() == QAbstractSocket::ClosingState) return; // sock_close() slot should eventually be called, nothing to do
+ if (_socket->state() == QAbstractSocket::ConnectedState) // this is what should be the case normally
+ {
+ _socket->disconnectFromHost(); // graceful shutdown of socket, sock_close() will be called once complete
+ return;
+ }
+ // otherwise the socket is in some unknown state, so do a harsh shutdown
+ _socket->abort();
+ _toldDisconnect = true;
+ _server->disconnectClient(this);
+}
+
+void PVSClientConnection::sock_dataArrival()
+{
+ if (_socket == NULL || _socket->state() != QAbstractSocket::ConnectedState)
+ {
+ ConsoleLog writeError("dataArrival called in bad state");
+ return;
+ }
+
+ _lastData = time(NULL);
+ while (_socket->bytesAvailable())
+ {
+ int retval = 0;
+ do
+ {
+ if (_incomplete == NULL) _incomplete = new PVSMsg(); // we need a pvsmsg object
+ retval = _incomplete->readMessage(_socket); // let the message read data from socket
+ if (retval == -1) // error parsing msg, disconnect client!
+ {
+ this->closeConnection();
+ return;
+ }
+ if (retval == 1) // message is complete
+ {
+ _server->handleClientMsg(_id, *_incomplete);
+ delete _incomplete; // ...and delete...
+ _incomplete = NULL; // ...so the next msg can be parsed
+ }
+ } while (retval == 1);
+ }
+}
+
+void PVSClientConnection::sock_closed()
+{
+ // should this be unreliable in some way i suggest using the signal "stateChanged()" instead
+ // and check if the state changed to unconnected.
+ if (_toldDisconnect) return;
+ _toldDisconnect = true;
+ _server->disconnectClient(this);
+}
+
+void PVSClientConnection::sock_error(QAbstractSocket::SocketError errcode)
+{
+ this->closeConnection();
+}
+
+/*
+void PVSClientConnection::push_back_receive(PVSMsg newMsg)
+{
+ _recQueue.push_back(newMsg);
+}
+*/
+
+bool PVSClientConnection::push_back_send(PVSMsg newMsg)
+{
+ if (_socket == NULL || _socket->state() != QAbstractSocket::ConnectedState) return false;
+ newMsg.setSndID(_id);
+ int len;
+ char data[2000];
+ char *tmp = data;
+ if (!newMsg.getBinaryData(tmp, len))
+ {
+ printf("Message empty. Ignored.\n");
+ return false;
+ }
+ QByteArray ba;
+ ba.append(tmp, len);
+ int ret = (int)_socket->write(ba);
+ //printf("Sent %d of %d bytes.\n", ret, len);
+ if (ret == -1)
+ {
+ this->closeConnection();
+ return false;
+ }
+ return true;
+}
+
+QSslSocket* PVSClientConnection::getSocket()
+{
+ return _socket;
+}
+
+void PVSClientConnection::setID(unsigned int id)
+{
+ _id = id;
+ this->push_back_send(PVSMsg(PVSLOGIN, "ID", int2String(_id)));
+}
+
+void PVSClientConnection::ping()
+{
+ // still needs flag/timer to check for a ping timeout (and a reply from the client)
+ this->push_back_send(PVSMsg(PVSCOMMAND, "PING", "HELLO?", _id));
+}
+
+QString PVSClientConnection::getAddress()
+{
+ if (_socket == NULL) return QString();
+ return _socket->peerAddress().toString();
+}
+
+QString PVSClientConnection::getNameUser()
+{
+ return getUserName();
+}
diff --git a/src/net/pvsClientConnection.h b/src/net/pvsClientConnection.h
new file mode 100644
index 0000000..cfbf98e
--- /dev/null
+++ b/src/net/pvsClientConnection.h
@@ -0,0 +1,67 @@
+/**
+ * PVSClientConnection
+ *
+ * holds and maintains a Connection made from/to a PVSServerConnection (or derivate)
+ * PVSClientConnections are created by the PVSListenServer if a PVSCLientConnection is accepted
+ *
+ */
+
+#include "pvsMsg.h"
+
+#include <QtNetwork/QSslSocket>
+
+
+#ifndef _PVSCLIENTCONNECTION_H_
+#define _PVSCLIENTCONNECTION_H_
+
+class PVSListenServer;
+
+class PVSClientConnection : public QObject
+{
+ Q_OBJECT
+
+public:
+ //C'Tor
+ PVSClientConnection(PVSListenServer* server, QSslSocket* sock = NULL);
+ // D'Tor
+ ~PVSClientConnection();
+
+ void closeConnection();
+ bool isConnected()
+ {
+ return _socket != NULL && _socket->state() == QAbstractSocket::ConnectedState;
+ }
+ time_t lastData()
+ {
+ return _lastData;
+ }
+
+ //void push_back_receive(PVSMsg newMsg);
+ bool push_back_send(PVSMsg newMsg);
+ QSslSocket* getSocket();
+
+ int getID() { return _id; }
+ void setID(unsigned int id);
+ void setServerID(unsigned int id) { _serverId = id; }
+
+ QString getAddress();
+ void setUsername(QString username);
+ QString getNameUser();
+ void ping();
+
+private Q_SLOTS:
+ void sock_dataArrival();
+ void sock_closed();
+ void sock_error(QAbstractSocket::SocketError errcode);
+
+private:
+ QSslSocket *_socket;
+ int _id;
+ unsigned int _serverId;
+ PVSMsg *_incomplete;
+ PVSListenServer *_server;
+ bool _toldDisconnect;
+ time_t _lastData;
+};
+
+#endif
diff --git a/src/net/pvsDiscoveredServer.cpp b/src/net/pvsDiscoveredServer.cpp
new file mode 100644
index 0000000..dddb5a0
--- /dev/null
+++ b/src/net/pvsDiscoveredServer.cpp
@@ -0,0 +1,152 @@
+/*
+# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+# -----------------------------------------------------------------------------
+# src/net/pvsDiscoveredServer.cpp
+# - represents an entry in the list of available servers
+# - handles some extra things like validating the identity of the remote host
+# -----------------------------------------------------------------------------
+*/
+
+#include "pvsDiscoveredServer.h"
+#include "src/util/serviceDiscoveryUtil.h"
+#include <QtNetwork/QSslKey>
+
+PVSDiscoveredServer::PVSDiscoveredServer(QObject* parent, QHostAddress host, int port, QByteArray fingerprint, QString name)
+ : QObject(parent)
+{
+ _validated = false;
+ _socket = NULL;
+ _host = host;
+ _port = port;
+ _fingerprint = fingerprint;
+ _name = name;
+ _lastUpdate = QDateTime::currentDateTime();
+ _lastCheck = QDateTime::fromTime_t(1000000);
+ this->validateCertificate();
+}
+
+PVSDiscoveredServer::~PVSDiscoveredServer() {
+ delete _socket;
+}
+
+void PVSDiscoveredServer::ssl_Error( const QList<QSslError> & errors )
+{
+ for (QList<QSslError>::const_iterator it = errors.begin(); it != errors.end(); it++)
+ {
+ QSslError err = *it;
+ if (err.error() == QSslError::HostNameMismatch) continue; // We don't pay attention to hostnames for validation
+ if (err.error() == QSslError::SelfSignedCertificate) {
+ continue; // Also, this will always be the case; we check the fingerprint later
+ }
+ //ConsoleLog writeNetwork(err.errorString().toUtf8().data());
+ //ConsoleLog writeNetwork("***** SSL ERROR, ABORTING *****");
+ printf("Unhandled SSL Error in SD: %s\n", err.errorString().toUtf8().data());
+ return;
+ }
+ _socket->ignoreSslErrors();
+}
+
+void PVSDiscoveredServer::sock_dataArrival()
+{
+ if (_socket == NULL) return;
+
+ char charbuff[2000];
+ while (_socket->bytesAvailable())
+ {
+ _socket->read(charbuff, 2000);
+ }
+}
+
+void PVSDiscoveredServer::sock_connected()
+{
+ QByteArray cert = _socket->peerCertificate().digest(QCryptographicHash::Sha1);
+ if (_socket->peerCertificate().isNull())
+ {
+ printf("**** WARNING - PEER CERTIFICATE IS NULL ****\n");
+ }
+ else
+ {
+ printf("%s\n", _socket->peerCertificate().subjectInfo(QSslCertificate::Organization).toUtf8().data());
+ printf("%s\n", _socket->peerCertificate().subjectInfo(QSslCertificate::CommonName).toUtf8().data());
+ printf("%s\n", _socket->peerCertificate().subjectInfo(QSslCertificate::LocalityName).toUtf8().data());
+ printf("%s\n", _socket->peerCertificate().subjectInfo(QSslCertificate::OrganizationalUnitName ).toUtf8().data());
+ printf("%s\n", _socket->peerCertificate().subjectInfo(QSslCertificate::CountryName ).toUtf8().data());
+ printf("%s\n", _socket->peerCertificate().subjectInfo(QSslCertificate::StateOrProvinceName ).toUtf8().data());
+ }
+ if (cert == _fingerprint && !_validated)
+ {
+ _validated = true;
+ emit validated(this);
+ printf("Validated certificate of %s :)\n", _socket->peerAddress().toString().toUtf8().data());
+ }
+ else
+ {
+ printf("Certificate of %s is invalid :(\n", _socket->peerAddress().toString().toUtf8().data());
+ QByteArray is, should;
+ is = cert.toBase64();
+ should = _fingerprint.toBase64();
+ printf("Is %s and should be %s\n", is.data(), should.data());
+ }
+ _socket->disconnectFromHost();
+}
+
+void PVSDiscoveredServer::validateCertificate()
+{
+ if (_validated) return; // Nothing to do, this one is legit
+ QDateTime now = QDateTime::currentDateTime();
+ if (_lastCheck.secsTo(now) < 30) return; // Too soon!
+ if (_host.isNull() || _port < 1 || _port > 65535) return; // Invalid
+ if (_socket != NULL) {
+ disconnect(_socket, SIGNAL(connected()), this, SLOT(sock_connected()));
+ disconnect(_socket, SIGNAL(readyRead()), this, SLOT(sock_dataArrival()));
+ disconnect(_socket, SIGNAL(sslErrors(const QList<QSslError> &)),
+ this, SLOT(ssl_Error(const QList<QSslError> &))
+ );
+ _socket->abort();
+ _socket->deleteLater();
+ }
+ _socket = new QSslSocket(this);
+ _socket->setProtocol(QSsl::SslV3);
+ _socket->setPeerVerifyMode(QSslSocket::VerifyPeer);
+ connect(_socket, SIGNAL(encrypted()), this, SLOT(sock_connected()));
+ connect(_socket, SIGNAL(readyRead()), this, SLOT(sock_dataArrival()));
+ connect(_socket, SIGNAL(sslErrors(const QList<QSslError> &)),
+ this, SLOT(ssl_Error(const QList<QSslError> &))
+ );
+ _socket->connectToHostEncrypted(_host.toString(), _port);
+ _lastCheck = now;
+}
+
+bool PVSDiscoveredServer::hasFingerprint(QByteArray &fingerprint)
+{
+ return _fingerprint == fingerprint;
+}
+
+bool PVSDiscoveredServer::hasHost(QHostAddress &host)
+{
+ return _host == host;
+}
+
+void PVSDiscoveredServer::update(int port)
+{
+ _port = port;
+ _lastUpdate = QDateTime::currentDateTime();
+}
+
+int PVSDiscoveredServer::getAge()
+{
+ return _lastUpdate.secsTo(QDateTime::currentDateTime());
+}
+
+QString PVSDiscoveredServer::getName()
+{
+ return _name;
+}
diff --git a/src/net/pvsDiscoveredServer.h b/src/net/pvsDiscoveredServer.h
new file mode 100644
index 0000000..d9f0c01
--- /dev/null
+++ b/src/net/pvsDiscoveredServer.h
@@ -0,0 +1,63 @@
+/*
+# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+# -----------------------------------------------------------------------------
+# src/net/pvsDiscoveredServer.h
+# - represents an entry in the list of available servers
+# - handles some extra things like validating the identity of the remote host
+# -----------------------------------------------------------------------------
+*/
+
+#ifndef PVSDISCOVEREDSERVER_H_
+#define PVSDISCOVEREDSERVER_H_
+
+#include <QtNetwork/QSslSocket>
+#include <QtNetwork/QHostAddress>
+#include <QtCore/QDateTime>
+
+class PVSDiscoveredServer;
+
+class PVSDiscoveredServer : public QObject {
+ Q_OBJECT
+
+private:
+ QHostAddress _host;
+ int _port;
+ QByteArray _fingerprint;
+ bool _validated;
+ QSslSocket *_socket;
+ QDateTime _lastCheck;
+ QDateTime _lastUpdate;
+ QString _name;
+
+public:
+ PVSDiscoveredServer(QObject* parent, QHostAddress host, int port, QByteArray fingerprint, QString name);
+ virtual ~PVSDiscoveredServer();
+ bool isValid() { return _validated; }
+ bool hasFingerprint(QByteArray &fingerprint);
+ bool hasHost(QHostAddress &host);
+ void update(int port);
+ int getAge();
+ QString getName();
+ QHostAddress getHost() { return _host; }
+ QByteArray getFingerprint() { return _fingerprint; }
+ int getPort() { return _port; }
+ void validateCertificate();
+
+private Q_SLOTS:
+ void ssl_Error( const QList<QSslError> & errors );
+ void sock_dataArrival();
+ void sock_connected();
+
+Q_SIGNALS:
+ void validated(PVSDiscoveredServer*);
+};
+
+#endif /* PVSDISCOVEREDSERVER_H_ */
diff --git a/src/net/pvsListenServer.cpp b/src/net/pvsListenServer.cpp
new file mode 100644
index 0000000..1dac9c0
--- /dev/null
+++ b/src/net/pvsListenServer.cpp
@@ -0,0 +1,308 @@
+/*
+ # Copyright (c) 2009,2010 - OpenSLX Project, Computer Center University of
+ # Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # -----------------------------------------------------------------------------
+ # src/net/pvsListenServer.cpp
+ # - handling of clients (server side)
+ # - accepting new connections etc.
+ # -----------------------------------------------------------------------------
+ */
+
+#include "pvsListenServer.h"
+#include "pvsMsg.h"
+#include "pvsClientConnection.h"
+#include "src/util/consoleLogger.h"
+#include <QtNetwork/QSslSocket>
+#include "SslServer.h"
+#include <cassert>
+//#define verbose
+
+// Create listener
+PVSListenServer::PVSListenServer(int port, int clients)
+{
+ _id = generateID();
+ _listenSocket = NULL;
+ _timer = 0;
+ if (clients < 1)
+ _clientsMax = 100;
+ else
+ _clientsMax = clients;
+ _port = port;
+ init();
+
+}
+
+PVSListenServer::~PVSListenServer()
+{
+ if (_listenSocket != NULL)
+ {
+ disconnect(_listenSocket, SIGNAL(newConnection()), this, SLOT(
+ server_connectionRequest()));
+ _listenSocket->deleteLater();
+ }
+}
+
+PVSClientConnection* PVSListenServer::getConnectionFromId(int id)
+{
+ if (!(_clients.empty()))
+ {
+ // Check for ping timeout
+ for (std::list<PVSClientConnection*>::iterator it = _clients.begin(); it
+ != _clients.end(); it++)
+ {
+ PVSClientConnection *client = *it;
+ if (client)
+ if (client->getID() == id)
+ return client;
+ }
+ }
+ return NULL;
+}
+
+void PVSListenServer::sendToAll(PVSMsg msg)
+{
+ if (!(_clients.empty()))
+ {
+ // Check for ping timeout
+ for (std::list<PVSClientConnection*>::iterator it = _clients.begin(); it
+ != _clients.end(); it++)
+ {
+ PVSClientConnection *client = *it;
+ if (client)
+ client->push_back_send(msg);
+ }
+ }
+}
+
+// listen on a specific port
+bool PVSListenServer::startListen(int port)
+{
+ if (_listenSocket != NULL)
+ {
+ ConsoleLog writeError(
+ QString("Server already listening on port :").append(
+ int2String(_port)));
+ if (shutdown())
+ {
+ ConsoleLog writeError(QString("Server shutdown failed!"));
+ return false;
+ }
+ }
+ _port = port;
+ return init();
+}
+
+// stop listening and free socket descriptor
+bool PVSListenServer::shutdown()
+{
+ if (_timer != 0)
+ killTimer( _timer);
+ _timer = 0;
+ if (_listenSocket != NULL)
+ {
+ disconnect(_listenSocket, SIGNAL(newConnection()), this, SLOT(
+ server_connectionRequest()));
+ _listenSocket->close();
+ _listenSocket->deleteLater();
+ }
+ _listenSocket = NULL;
+ _fresh = true;
+ return false;
+}
+
+// timer event, 5 second interval
+void PVSListenServer::timerEvent(QTimerEvent *event)
+{
+ if (!(_clients.empty()))
+ {
+ // Check for ping timeout
+ time_t refval = time(NULL) - 10;
+ for (std::list<PVSClientConnection*>::iterator it = _clients.begin(); it
+ != _clients.end(); it++)
+ {
+ PVSClientConnection *client = *it;
+ client->ping();
+ if (!client->isConnected())
+ { // disconnected
+ if (disconnectClient(client))
+ break; // list was modified, iterator not valid anymore
+ }
+ if (client->lastData() < refval)
+ { // ping timeout
+ printf("Ping timeout for client %s\n", client->getNameUser().toLocal8Bit().data());
+ if (disconnectClient(client))
+ break; // list was modified, iterator not valid anymore
+ }
+ }
+ }
+}
+
+// remove a client
+bool PVSListenServer::disconnectClient(PVSClientConnection* delinquent)
+{
+ assert(delinquent);
+ delinquent->deleteLater();
+ if (!(_clients.empty()))
+ {
+ for (std::list<PVSClientConnection*>::iterator it = _clients.begin(); it
+ != _clients.end(); it++)
+ {
+ if ((*it) == delinquent)
+ {
+ (*it)->closeConnection();
+ _clients.remove((*it));
+ onClientDisconnected(delinquent);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+// All sorts of events:
+
+void PVSListenServer::onConnectionRemoved(PVSClientConnection* delinquent)
+{
+
+}
+
+void PVSListenServer::onClientConnected(PVSClientConnection* connected)
+{
+ connected->setServerID(_id);
+ connected->setID(generateID());
+}
+
+void PVSListenServer::onClientDisconnected(PVSClientConnection* disconnected)
+{
+ //
+}
+
+// Get client class for a given socket
+PVSClientConnection* PVSListenServer::getConnectionFromSocket(QSslSocket* sock)
+{
+ for (std::list<PVSClientConnection*>::iterator it = _clients.begin(); it
+ != _clients.end(); it++)
+ {
+ if ((*it)->getSocket() == sock) // match!
+ return (*it);
+ }
+ return NULL;
+}
+
+// generate a random (unique) id
+unsigned int PVSListenServer::generateID()
+{
+ int random_integer;
+ do
+ {
+ random_integer = getRandom(0, 0);
+ }
+ while (getConnectionFromID(random_integer));
+
+ return (unsigned int) random_integer;
+}
+
+// Get client class for a given id
+PVSClientConnection* PVSListenServer::getConnectionFromID(int id)
+{
+ for (std::list<PVSClientConnection*>::iterator it = _clients.begin(); it
+ != _clients.end(); it++)
+ {
+ if ((*it)->getID() == id || id == _id)
+ {
+ return (*it);
+ }
+ }
+ return NULL;
+}
+
+// Initialize listening socket
+bool PVSListenServer::init()
+{
+ if (_listenSocket != NULL)
+ shutdown();
+
+ if (_port > 0)
+ {
+ // make a socket, bind it, and listen on it:
+ _listenSocket = new SslServer;
+ QHostAddress addr(QHostAddress::Any);
+ _listenSocket->listen(addr, _port);
+
+ if (!_listenSocket->isListening())
+ {
+ ConsoleLog writeNetwork(
+ QString("Error listening on Port ").append(int2String(
+ _port)));
+ return false;
+ }
+ ConsoleLog writeNetwork(
+ QString("Server is listening. Socket: ").append(int2String(
+ (int) _listenSocket)));
+ connect(_listenSocket, SIGNAL(newConnection()), this, SLOT(
+ server_connectionRequest()));
+
+ _fresh = true;
+ if (_timer != 0)
+ killTimer( _timer);
+ _timer = startTimer(5000);
+ return true;
+ }
+ return false;
+}
+
+void PVSListenServer::server_connectionRequest()
+{
+ //printf("ConnReq\n");
+ if (_listenSocket == NULL)
+ return; // o.O
+ while (_listenSocket->hasPendingConnections())
+ {
+ QSslSocket* sock = (QSslSocket*)_listenSocket->nextPendingConnection();
+ //printf("Got one: %d: %s\n", (int)sock->isEncrypted(), sock->peerAddress().toString().toUtf8().data());
+ if (_clients.size() >= _clientsMax)
+ {
+ sock->abort();
+ sock->deleteLater();
+ continue;
+ }
+ PVSClientConnection* client = new PVSClientConnection(this, sock);
+ _clients.push_back(client); // create new client class and add to list
+ onClientConnected(client); // trigger event
+ _fresh = false;
+ }
+}
+
+void PVSListenServer::handleClientMsg(unsigned int clientID, PVSMsg msg)
+{
+ printf("Got Message for client %ud: [%c][%s][%s]\n", clientID,
+ (char) msg.getType(), msg.getIdent().toUtf8().data(),
+ msg.getMessage().toUtf8().data());
+ msg.setSndID(clientID);
+ if (msg.getType() == PVSCOMMAND)
+ _commandDispatcher.fire(msg.getIdent(), msg);
+ else if (msg.getType() == PVSMESSAGE)
+ _chatDispatcher.fire(msg.getIdent(), msg);
+ else if (msg.getType() == PVSLOGIN)
+ _loginDispatcher.fire(msg.getIdent(), msg);
+ else
+ ConsoleLog
+ writeNetwork(
+ QString(
+ "Could not dispatch Message of unknown Type.\n\t Message was: ").append(
+ msg.getIdent().append(QString(":").append(
+ msg.getMessage()))));
+}
+
+bool PVSListenServer::isListening()
+{
+ return _listenSocket != NULL && _listenSocket->isListening();
+}
diff --git a/src/net/pvsListenServer.h b/src/net/pvsListenServer.h
new file mode 100644
index 0000000..ab021c7
--- /dev/null
+++ b/src/net/pvsListenServer.h
@@ -0,0 +1,106 @@
+#ifndef _PVSLISTENSERVER_H_
+#define _PVSLISTENSERVER_H_
+#include <list>
+#include <src/util/dispatcher.h>
+#include <src/util/consoleLogger.h>
+#include <QtNetwork/QSslSocket>
+//#include <QtNetwork/QTcpServer>
+
+class SslServer;
+
+class PVSClientConnection;
+class PVSMsg;
+
+class PVSListenServer : public QObject
+{
+ Q_OBJECT
+
+private:
+
+ // internal control functions
+
+ std::list<PVSClientConnection*> _clients;
+
+
+ int _numCon;
+ bool _fresh;
+ unsigned int _clientsMax;
+ int _port;
+
+ //QTcpServer *_listenSocket;
+ SslServer *_listenSocket;
+
+ int _id;
+ EventIdentDispatcher<PVSMsg> _loginDispatcher;
+ EventIdentDispatcher<PVSMsg> _commandDispatcher;
+ EventIdentDispatcher<PVSMsg> _chatDispatcher;
+ int _timer;
+
+ // obvious init method is obvious
+ bool init();
+ unsigned int generateID();
+
+protected:
+ void timerEvent(QTimerEvent *event);
+
+public:
+
+
+// typedef void (A::*function)(void);
+ // C'Tor
+ explicit PVSListenServer(int port = 0, int clients = 0);
+ virtual ~PVSListenServer();
+
+ PVSClientConnection* getConnectionFromId(int id);
+ void sendToAll(PVSMsg msg);
+ // control methods
+ bool startListen(int port);
+ bool shutdown();
+ bool isListening();
+ bool disconnectClient(PVSClientConnection* delinquent);
+ void onConnectionRemoved(PVSClientConnection* delinquent);
+
+ std::list<PVSClientConnection*>* getClientListPtr()
+ {
+ return &_clients;
+ }
+ // methods which can/should be overwritten by derivates
+ virtual void onClientConnected(PVSClientConnection* connected); // you can hook up additional services on client connection here
+ virtual void onClientDisconnected(PVSClientConnection* disconnected); // deletes the client, but you can hook up stuff here too
+
+ void handleClientMsg(unsigned int clientID, PVSMsg msg); ///< called by a clientconnection if a msg was received
+
+
+ template<class T> void addLoginHandler(QString ident, T* who, void (T :: *func)(PVSMsg))
+ {
+ printf("Listener got added to LoginHandler\n");
+ _loginDispatcher.addListener(ident, who, func);
+ };
+ template<class T> void removeLoginHandler(QString ident, T* who, void (T :: *func)(PVSMsg))
+ {
+ _loginDispatcher.removeListener(ident, who, func);
+ };
+ template<class T> void addChatHandler(QString ident, T* who, void (T :: *func)(PVSMsg))
+ {
+ _chatDispatcher.addListener(ident, who, func);
+ };
+ template<class T> void removeChatHandler(QString ident, T* who, void (T :: *func)(PVSMsg))
+ {
+ _chatDispatcher.removeListener(ident, who, func);
+ };
+ template<class T> void addCommandHandler(QString ident, T* who, void (T :: *func)(PVSMsg))
+ {
+ _commandDispatcher.addListener(ident, who, func);
+ };
+ template<class T> void removeCommandHandler(QString ident, T* who, void (T :: *func)(PVSMsg))
+ {
+ _commandDispatcher.removeListener(ident, who, func);
+ };
+ PVSClientConnection* getConnectionFromSocket(QSslSocket* sock);
+ PVSClientConnection* getConnectionFromID(int id);
+
+private Q_SLOTS:
+ void server_connectionRequest();
+};
+
+#endif
diff --git a/src/net/pvsLocalhostCommunicator.cpp b/src/net/pvsLocalhostCommunicator.cpp
new file mode 100644
index 0000000..199b39c
--- /dev/null
+++ b/src/net/pvsLocalhostCommunicator.cpp
@@ -0,0 +1,104 @@
+#include "pvsLocalhostCommunicator.h"
+#include "src/util/consoleLogger.h"
+#include "src/net/pvsMsg.h"
+
+static QHostAddress localhost(QHostAddress::LocalHost);
+#define localport 14913
+
+PVSLocalhostCommunicator::PVSLocalhostCommunicator(QString path)
+{
+ _isServer = _isRunning = false;
+ _sock = NULL;
+}
+
+void PVSLocalhostCommunicator::run()
+{
+ if (_isRunning)
+ return;
+
+ // First try to run as server
+ _sock = new QUdpSocket();
+ // We'll bind only to localhost, so nobody else can send commands (from remote hosts)
+ // Otherwise we had to check the remote addr when receiving a datagram, but this
+ // wouldn't be as secure since you can easily fake it
+ _sock->bind(localhost, localport); // QUdpSocket::DontShareAddress? would need root
+ connect(_sock, SIGNAL(readyRead()), this, SLOT(sock_dataArrival()));
+
+ if (_sock->state() == QAbstractSocket::BoundState)
+ {
+ // OK, we are the first daemon to run
+ _isServer = true;
+ _isRunning = true;
+ return;
+ }
+ if (_sock->bind())
+ {
+ _isRunning = true;
+ }
+}
+
+void PVSLocalhostCommunicator::stop()
+{
+ _isRunning = false;
+ _sock->deleteLater();
+ _sock = NULL;
+}
+
+void PVSLocalhostCommunicator::sock_dataArrival()
+{
+ if (_sock == NULL) return;
+
+ qint64 dsize;
+ while ((dsize = _sock->pendingDatagramSize()) > -1) // returns -1 if no more datagrams are pending
+ {
+ if (dsize < 4) // anything shorter than 4 bytes is not a valid PVSMsg anyways, so take a shortcut
+ {
+ char x;
+ _sock->readDatagram(&x, 1, NULL, NULL);
+ continue; // discard the packet and see if there is more
+ }
+
+ PVSMsg receiver;
+ receiver.readMessage(_sock, true);
+
+ if (receiver.isMsgComplete())
+ {
+ // we received a message, so fire away
+ ConsoleLog writeNetwork(QString("Received UDS command: ").append(receiver.getIdent()));
+ _daemonDispatcher.fire(receiver.getIdent(), receiver);
+ } // If the msg is not complete we have to discard it, since UDP
+ // is packet oriented and we could not say for sure if the next one
+ // would be the continuation of this msg.
+ // Usually on the loopback interface it is safe to send datagrams
+ // up to 8kb, so this is not be an issue anyway.
+ }
+}
+
+void PVSLocalhostCommunicator::sendCommand(QString ident, QString cmd)
+{
+ if (_isRunning && !_isServer && _sock != NULL)
+ {
+ PVSMsg sender(PVSDAEMON, ident, cmd);
+ char *data;
+ int len;
+ sender.getBinaryData(data, len);
+ QByteArray qba(data, len);
+ printf("Sending %d bytes to daemon...\n", qba.length());
+ qint64 result = _sock->writeDatagram(qba, localhost, localport);
+ _sock->waitForBytesWritten(100);
+
+ // simply bail out on an error or disconnect or whatever
+ if (result != len)
+ {
+ if (result == -1)
+ {
+ printf("Error sending PVSMsg to daemon: %s\n", _sock->errorString().toUtf8().data());
+ }
+ else
+ {
+ printf("Sent PVSMsg was incomplete.\n");
+ }
+ stop();
+ }
+ }
+}
diff --git a/src/net/pvsLocalhostCommunicator.h b/src/net/pvsLocalhostCommunicator.h
new file mode 100644
index 0000000..425cc37
--- /dev/null
+++ b/src/net/pvsLocalhostCommunicator.h
@@ -0,0 +1,51 @@
+/// test documentation
+/// whatever
+//! and one more
+
+
+
+#ifndef _PVSLocalhostCommunicator_H_
+#define _PVSLocalhostCommunicator_H_
+#include <src/util/dispatcher.h>
+#include <QtNetwork/QUdpSocket>
+
+
+class PVSMsg;
+
+class PVSLocalhostCommunicator : public QObject
+{
+ Q_OBJECT
+public:
+ PVSLocalhostCommunicator(QString path);
+ void run();
+ bool server()
+ {
+ return _isServer;
+ };
+ bool running()
+ {
+ return _isRunning;
+ };
+ void stop();
+ void sendCommand(QString ident, QString cmd);
+ EventIdentDispatcher<PVSMsg>* getDispatcher()
+ {
+ return &_daemonDispatcher;
+ };
+
+private Q_SLOTS:
+ void sock_dataArrival();
+
+private:
+
+ bool _isServer, _isRunning;
+ QUdpSocket* _sock;
+
+
+
+ EventIdentDispatcher<PVSMsg> _daemonDispatcher; //!< Dispatcher for Daemon Commands
+};
+
+typedef PVSLocalhostCommunicator PVSUDSC;
+
+#endif
diff --git a/src/net/pvsMsg.cpp b/src/net/pvsMsg.cpp
new file mode 100644
index 0000000..b56c979
--- /dev/null
+++ b/src/net/pvsMsg.cpp
@@ -0,0 +1,207 @@
+/*
+ # Copyright (c) 2010 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # -----------------------------------------------------------------------------
+ # src/net/pvsMsg.cpp
+ # - ??? .
+ # -----------------------------------------------------------------------------
+ */
+
+#include "pvsMsg.h"
+#include <cstring>
+#include <QtNetwork/QUdpSocket>
+#include <QtNetwork/QHostAddress>
+
+#ifndef min
+#define min(a,b) (((a)<(b))?(a):(b))
+#endif
+
+static unsigned char PVS_ID = 'P';
+
+// Several constructors for the PVSMsg class...
+PVSMsg::PVSMsg()
+{
+ _msgType = PVSMESSAGE;
+ _buffer = NULL;
+ _buffLen = 0;
+ _buffFill = 0;
+}
+
+PVSMsg::PVSMsg(PVSMsgType type, QString ident, QString msg, int recID)
+{
+ this->_recID = recID;
+
+ if (ident.size())
+ _msgIdent = ident;
+ else
+ _msgIdent = QString("invalid");
+
+ _msgType = type;
+ _msgString = msg;
+ _buffer = NULL;
+ _buffLen = 0;
+ _buffFill = 0;
+}
+
+PVSMsg::PVSMsg(PVSMsg const& copyMe)
+{
+ _msgType = copyMe._msgType;
+ _msgString = copyMe._msgString;
+ _msgIdent = copyMe._msgIdent;
+ _remoteIp = copyMe._remoteIp;
+
+ _buffLen = copyMe._buffLen;
+ _buffFill = copyMe._buffFill;
+ if (_buffLen > 0)
+ {
+ _buffer = new char[_buffLen];
+ memcpy(_buffer, copyMe._buffer, _buffLen);
+ }
+ else
+ _buffer = NULL;
+ _sndID = copyMe._sndID;
+ _recID = copyMe._recID;
+}
+
+// Destructor...
+PVSMsg::~PVSMsg()
+{
+ if (_buffer)
+ delete[] _buffer;
+}
+
+int PVSMsg::readMessage(QAbstractSocket* sock, bool udp)
+{
+ if (_buffFill > 0 && _buffLen <= _buffFill)
+ return 1;
+ qint64 ret = 0;
+ if (_buffFill < 4) // message header is not complete yet
+ {
+ if (_buffer == NULL)
+ {
+ _remoteIp = sock->peerAddress().toString();
+ if (udp)
+ _buffer = new char[1000];
+ else
+ _buffer = new char[4];
+ }
+ // Read as many bytes as needed to complete the 4 byte header
+ if (udp)
+ ret = ((QUdpSocket*)sock)->readDatagram(_buffer, 1000);
+ else
+ ret = sock->read(_buffer + _buffFill, 4 - _buffFill);
+ if (ret == -1) return -1;
+ _buffFill += (int)ret;
+ if (_buffFill == 0)
+ return 0;
+ if (_buffer[0] != PVS_ID)
+ {
+ // check if the id byte is correct
+ // otherwise either the message parsing is broken
+ // or someone is sending garbage
+ return -1;
+ }
+ if (_buffFill >= 4)
+ {
+ // header complete, allocate buffer
+ _buffLen = 4 + (unsigned char)_buffer[2] + (unsigned char)_buffer[3];
+ char *nb = new char[_buffLen + 1]; // +1 for \0
+ memcpy(nb, _buffer, _buffFill);
+ delete[] _buffer;
+ _buffer = nb;
+ }
+ }
+ if (_buffFill >= 4)
+ {
+ // got header, assemble rest of msg
+ if (!udp)
+ {
+ ret = sock->read(_buffer + _buffFill, _buffLen - _buffFill); // read remaining bytes
+ if (ret == -1) return -1;
+ _buffFill += (int)ret;
+ }
+ if (_buffFill >= _buffLen)
+ {
+ // message is complete
+ _buffer[_buffLen] = '\0'; // first, terminate with nullchar
+ _msgString = QString::fromUtf8(_buffer + 4 + (unsigned char)_buffer[2]); // get message
+ _buffer[4 + (unsigned char)_buffer[2]] = '\0';
+ _msgIdent = QString::fromUtf8(_buffer + 4); // get ident
+ _msgType = (PVSMsgType)_buffer[1]; // get msg type
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void PVSMsg::setMessage(QString text)
+{
+ _msgString = text;
+}
+
+void PVSMsg::setIdent(QString ident)
+{
+ _msgIdent = ident;
+}
+
+QString PVSMsg::getMessage()
+{
+ return _msgString;
+}
+
+QString PVSMsg::getIdent()
+{
+ return _msgIdent;
+}
+
+bool PVSMsg::getBinaryData(char*& data, int& dataLen)
+{
+ if (_msgIdent.size() == 0)
+ return false;
+ this->makeSndBuff();
+ data = (char*) _buffer;
+ dataLen = _buffLen;
+ return true;
+}
+
+void PVSMsg::setSndID(int id)
+{
+ _sndID = id;
+}
+
+void PVSMsg::setRecID(int id)
+{
+ _recID = id;
+}
+
+// Create a send buffer with the necessary size
+bool PVSMsg::makeSndBuff()
+{
+ QByteArray uIdent = _msgIdent.toUtf8();
+ QByteArray uString = _msgString.toUtf8();
+ uIdent.truncate(255);
+ uString.truncate(255);
+ _buffLen = 4 + uIdent.size() + uString.size();
+ if (_buffer != NULL)
+ delete[] _buffer;
+ unsigned char *tmpBuffer = new unsigned char[_buffLen + 1];
+
+ tmpBuffer[0] = PVS_ID;
+ tmpBuffer[1] = (unsigned char) _msgType;
+ tmpBuffer[2] = (unsigned char) uIdent.size();
+ tmpBuffer[3] = (unsigned char) uString.size();
+ memcpy(tmpBuffer + 4, uIdent.data(), uIdent.size());
+ memcpy(tmpBuffer + 4 + uIdent.size(), uString.data(), uString.size());
+ //printf("[%c] '%s' - '%s'\n", (char)_msgType, _msgIdent.toUtf8().data(), _msgString.toUtf8().data());
+ tmpBuffer[_buffLen] = '\0';
+ //printf("Binary: '%s'\n", _buffer);
+ _buffer = (char*)tmpBuffer;
+ return true;
+}
diff --git a/src/net/pvsMsg.h b/src/net/pvsMsg.h
new file mode 100644
index 0000000..6fbcd99
--- /dev/null
+++ b/src/net/pvsMsg.h
@@ -0,0 +1,73 @@
+/*
+ * pvsMsg.h
+ *
+ * Created on: 08.01.2010
+ * Author: sr
+ */
+
+#ifndef PVSMSG_H_
+#define PVSMSG_H_
+
+
+#include <QtCore/QString>
+
+enum PVSMsgType
+{
+ PVSCOMMAND = 'C',
+ PVSMESSAGE = 'M',
+ PVSLOGIN = 'L',
+ PVSDAEMON = 'D',
+ PVSUNKNOWN = 'U'
+};
+
+class PVSServerConnection;
+class PVSListenServer;
+class PVSClientConnection;
+class QAbstractSocket;
+
+class PVSMsg
+{
+public:
+ friend class PVSServerConnection;
+ friend class PVSListenServer;
+ friend class PVSClientConnection;
+
+ PVSMsg();
+ PVSMsg(PVSMsgType type, QString _ident, QString msg, int recID = 0);
+ PVSMsg(PVSMsg const& copyMe);
+ ~PVSMsg();
+
+ int readMessage(QAbstractSocket* sock, bool udp = false); ///< -1 = error, 0 = incomplete, 1 = complete
+ unsigned int getLength()
+ {
+ return _msgString.size();
+ };
+ void setIdent(QString ident);
+ QString getIdent();
+ void setMessage(QString text);
+ QString getMessage();
+ PVSMsgType getType() { return _msgType; }
+ bool getBinaryData(char*& data, int& dataLen); ///< get binary representation of this PVSmsg
+
+ unsigned int getRecID() { return _recID; }
+ int getSndID() { return _sndID; }
+ QString getRemoteIp() { return _remoteIp; }
+ bool isMsgComplete() { return _buffFill > 0 && _buffFill == _buffLen; }
+
+private:
+ void setSndID(int id);
+ void setRecID(int id);
+ bool makeSndBuff();
+ PVSMsgType _msgType; ///< type of message (command, message, login, daemon)
+ QString _msgIdent; ///< message ident
+ QString _msgString; ///< message string
+ char *_buffer; ///< receive buffer
+ int _buffLen; ///< size of complete message in bytes
+ int _buffFill; ///< actual number of bytes in buffer
+
+ int _sndID;
+ int _recID;
+ QString _remoteIp;
+};
+
+#endif /* PVSMSG_H_ */
diff --git a/src/net/pvsServerConnection.cpp b/src/net/pvsServerConnection.cpp
new file mode 100644
index 0000000..04a1ef6
--- /dev/null
+++ b/src/net/pvsServerConnection.cpp
@@ -0,0 +1,243 @@
+#include "pvsServerConnection.h"
+#include "src/util/consoleLogger.h"
+#include "src/util/util.h"
+#include "pvsMsg.h"
+#include "src/pvs.h"
+#include <QtNetwork/QHostAddress>
+#include "src/core/pvsChatClient.h"
+#include "src/util/serviceDiscoveryUtil.h"
+#include "src/net/pvsDiscoveredServer.h"
+//#define verbose
+
+PVSServerConnection::PVSServerConnection(PVS *parent) : QObject(parent)
+{
+ _client = parent;
+ _incomplete = NULL;
+ _socket = NULL;
+ _timerId = 0;
+ _timer = 0;
+ _wasConnected = false;
+ loadCommands();
+}
+
+inline void PVSServerConnection::timerStop()
+{
+ if (_timer == 0) return;
+ killTimer(_timer);
+ _timer = 0;
+}
+
+bool PVSServerConnection::connectToServer(PVSDiscoveredServer* server, QString passwd)
+{
+ QHostAddress host = server->getHost();
+ if (_socket != NULL && _socket->state() == QAbstractSocket::ConnectedState
+ && _socket->peerAddress() == host) return false;
+ int port = server->getPort();
+ if (port < 1 || port > 65535) port = SERVER_PORT_INT;
+ ConsoleLog writeNetwork("Connecting to host:");
+ ConsoleLog writeNetwork(host.toString().toUtf8().data());
+ timerStop();
+ if (_socket != NULL)
+ {
+ _socket->blockSignals(true);
+ _socket->abort();
+ _socket->deleteLater();
+ }
+ _name = server->getName();
+ _expectedFingerprint = server->getFingerprint();
+ _passwd = passwd;
+ _socket = new QSslSocket(this);
+ connect(_socket, SIGNAL(encrypted()), this, SLOT(sock_connected()));
+ connect(_socket, SIGNAL(readyRead()), this, SLOT(sock_dataArrival()));
+ connect(_socket, SIGNAL(disconnected()), this, SLOT(sock_closed()));
+ connect(_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(sock_error(QAbstractSocket::SocketError)));
+ char tex[2000];
+ snprintf(tex, 2000, "Connecting to %s on port %d", host.toString().toUtf8().data(), (int)port);
+ ConsoleLog writeNetwork(tex);
+ connect(_socket,
+ SIGNAL(sslErrors(const QList<QSslError> &)),
+ this,
+ SLOT(sslErrors(const QList<QSslError> &))
+ );
+ _socket->connectToHostEncrypted(host.toString(), port);
+ if (_timer == 0) _timer = startTimer(10000);
+
+ return true; // we really don't know yet if it will succeed since its async
+}
+
+void PVSServerConnection::sslErrors ( const QList<QSslError> & errors )
+{
+ for (QList<QSslError>::const_iterator it = errors.begin(); it != errors.end(); it++)
+ {
+ QSslError err = *it;
+ printf("Connect SSL: %s\n", err.errorString().toUtf8().data());
+ if (err.error() == QSslError::HostNameMismatch) continue; // We don't pay attention to hostnames for validation
+ if (err.error() == QSslError::SelfSignedCertificate) continue; // Also, this will always be the case; we check the fingerprint later
+ ConsoleLog writeNetwork(err.errorString().toUtf8().data());
+ ConsoleLog writeNetwork("***** SSL ERROR, ABORTING *****");
+ return;
+ }
+ _socket->ignoreSslErrors();
+}
+
+void PVSServerConnection::disconnectFromServer()
+{
+ if (_socket == NULL) return;
+ _socket->disconnectFromHost();
+ handleDisconnectInternal();
+}
+
+void PVSServerConnection::timerEvent(QTimerEvent *event)
+{
+ if (_socket != NULL && _socket->state() == QAbstractSocket::ConnectedState) return;
+ // TODO: Check for ping timeout
+}
+
+void PVSServerConnection::sendMessage(PVSMsg newMessage)
+{
+ if (_socket == NULL || _socket->state() != QAbstractSocket::ConnectedState) return;
+ char *data;
+ int len;
+ newMessage.getBinaryData(data, len);
+ QByteArray qba(data, len);
+ _socket->write(qba);
+}
+
+void PVSServerConnection::ping()
+{
+ sendMessage(PVSMsg(PVSCOMMAND, "PING", "U THERE?"));;
+}
+
+QString PVSServerConnection::getServerName()
+{
+ if (!isConnected()) return QString();
+ return _name;
+}
+
+void PVSServerConnection::loadCommands()
+{
+ addLoginHandler("ID", this, &PVSServerConnection::onID);
+ addCommandHandler("PING", this, &PVSServerConnection::onPing);
+}
+
+void PVSServerConnection::onID(PVSMsg idmsg)
+{
+ _id = (unsigned int)string2Int(idmsg.getMessage());
+}
+
+void PVSServerConnection::onPing(PVSMsg pingmsg)
+{
+ if (pingmsg.getMessage().at(pingmsg.getMessage().size()-1) == '?')
+ {
+ sendMessage(PVSMsg(PVSCOMMAND, "PING", "HI!"));
+ }
+}
+
+void PVSServerConnection::handleClientMsg(PVSMsg receiver)
+{
+ // FIXME: @SimonR, this line cuase problems with pvs in daemon mode and dbus
+ //qDebug("Got Message for this client: [%c][%s][%s]\n", (char)receiver.getType(), receiver.getIdent().toUtf8().data(), receiver.getMessage().toUtf8().data());
+ if (receiver.getType() == PVSCOMMAND)
+ {
+ _commandDispatcher.fire(receiver.getIdent(), receiver);
+// ConsoleLog writeNetwork(QString("Received a command and handled it.").append(receiver.getIdent().append(QString(":").append(receiver.getMessage()))));
+ }
+ else if (receiver.getType() == PVSMESSAGE)
+ {
+ _chatDispatcher.fire(receiver.getIdent(), receiver);
+ ConsoleLog writeNetwork(QString("Received a chat message and handled it.").append(receiver.getIdent().append(QString(":").append(receiver.getMessage()))));
+ }
+ else if (receiver.getType() == PVSLOGIN)
+ {
+ _loginDispatcher.fire(receiver.getIdent(), receiver);
+// ConsoleLog writeNetwork(QString("Received a login and handled it. Ident: ").append(receiver.getIdent().append(QString(":")).append(receiver.getMessage())));
+ }
+ else if (receiver.getType() == PVSUNKNOWN)
+ {
+ ConsoleLog writeNetwork(QString("Received an unknown type. Ident : ").append(receiver.getIdent().append(QString(" : ").append(receiver.getMessage()))));
+ }
+}
+
+void PVSServerConnection::sock_dataArrival()
+{
+ if (_socket == NULL || _socket->state() != QAbstractSocket::ConnectedState)
+ {
+ ConsoleLog writeError("dataArrival called in bad state");
+ return;
+ }
+
+ while (_socket->bytesAvailable())
+ {
+ int retval = 0;
+ do
+ {
+ if (_incomplete == NULL) _incomplete = new PVSMsg(); // we need a pvsmsg object
+ retval = _incomplete->readMessage(_socket); // let the message read data from socket
+ if (retval == -1) // error parsing msg, disconnect client!
+ {
+ this->disconnectFromServer();
+ return;
+ }
+ if (retval == 1) // message is complete
+ {
+ this->handleClientMsg(*_incomplete);
+ delete _incomplete; // ...and delete...
+ _incomplete = NULL; // ...so the next msg can be parsed
+ }
+ } while (retval == 1);
+ }
+}
+
+void PVSServerConnection::sock_closed()
+{
+ // should this be unreliable in some way i suggest using the signal "stateChanged()" instead
+ // and check if the state changed to unconnected.
+ ConsoleLog writeNetwork("Socket was closed... oh well..");
+ handleDisconnectInternal();
+}
+
+void PVSServerConnection::sock_error(QAbstractSocket::SocketError errcode)
+{
+ char txt[204];
+ snprintf(txt, 200, "Connection error: %d", (int)errcode);
+ ConsoleLog writeNetwork(txt);
+ handleDisconnectInternal();
+}
+
+// Send to server username and loginname.
+void PVSServerConnection::sock_connected()
+{
+ QByteArray cert = _socket->peerCertificate().digest(QCryptographicHash::Sha1);
+ if (_expectedFingerprint != cert)
+ { // Nich mit mir, Freundchen!
+ disconnectFromServer();
+ // Maybe you want to inform the user that there was a certificate mismatch
+ // and that it is very possible that the CIA is trying to eavesdrop on the connection
+ return;
+ }
+ ConsoleLog writeNetwork("Connected!");
+ _wasConnected = true;
+ sendMessage(
+ PVSMsg(PVSLOGIN, "USERNAME", getFullUsername()+","+getenv("USER")));
+ sendMessage(
+ PVSMsg(PVSLOGIN, "PASSWORD", _passwd));
+ ConsoleLog writeNetwork("Sent Username and password.");
+
+ _client->onConnected(_name);
+}
+
+void PVSServerConnection::handleDisconnectInternal()
+{
+ _socket->blockSignals(true);
+ _socket->abort();
+ _socket->deleteLater();
+ _socket = NULL;
+ _name = QString();
+ _client->securityUnlock();
+ timerStop();
+ if (_wasConnected)
+ {
+ _wasConnected = false;
+ _client->onDisconnected();
+ }
+}
diff --git a/src/net/pvsServerConnection.h b/src/net/pvsServerConnection.h
new file mode 100644
index 0000000..0669d88
--- /dev/null
+++ b/src/net/pvsServerConnection.h
@@ -0,0 +1,99 @@
+/**
+ * PVSServerConnection
+ *
+ * holds and maintains a Connection to a PVSListenServer (or derivate)
+ *
+ */
+
+
+
+#ifndef _PVSSERVERCONNECTION_H_
+#define _PVSSERVERCONNECTION_H_
+
+#include "src/util/dispatcher.h"
+#include <QtNetwork/QSslSocket>
+
+class PVSMsg;
+class PVS;
+class PVSDiscoveredServer;
+
+class PVSServerConnection : public QObject
+{
+ Q_OBJECT
+public:
+ PVSServerConnection(PVS *parent);
+ ~PVSServerConnection() {}
+ bool connectToServer(PVSDiscoveredServer* server, QString passwd = QString());
+ void disconnectFromServer();
+ bool isConnected()
+ {
+ return _socket != NULL && _socket->state() == QAbstractSocket::ConnectedState;
+ }
+
+ void sendMessage(PVSMsg newMessage);
+
+ void ping();
+ QString getServerName();
+
+ virtual void loadCommands();
+ void onID(PVSMsg idmsg);
+ void onPing(PVSMsg pingmsg);
+ template<class T> void addLoginHandler(QString ident, T* who, void (T :: *func)(PVSMsg))
+ {
+ _loginDispatcher.addListener(ident, who, func);
+ };
+ template<class T> void removeLoginHandler(QString ident, T* who, void (T :: *func)(PVSMsg))
+ {
+ _loginDispatcher.removeListener(ident, who, func);
+ };
+ template<class T> void addChatHandler(QString ident, T* who, void (T :: *func)(PVSMsg))
+ {
+ _chatDispatcher.addListener(ident, who, func);
+ };
+ template<class T> void removeChatHandler(QString ident, T* who, void (T :: *func)(PVSMsg))
+ {
+ _chatDispatcher.removeListener(ident, who, func);
+ };
+ template<class T> void addCommandHandler(QString ident, T* who, void (T :: *func)(PVSMsg))
+ {
+ _commandDispatcher.addListener(ident, who, func);
+ };
+ template<class T> void removeCommandHandler(QString ident, T* who, void (T :: *func)(PVSMsg))
+ {
+ _commandDispatcher.removeListener(ident, who, func);
+ };
+
+protected:
+ void timerEvent(QTimerEvent *event);
+
+private Q_SLOTS:
+ void sslErrors(const QList<QSslError> & errors); // triggered for errors that occur during SSL negotiation
+ void sock_dataArrival(); // triggered if data is available for reading
+ void sock_closed(); // triggered if the socket is closed
+ void sock_error(QAbstractSocket::SocketError errcode); // triggered if an error occurs on the socket
+ void sock_connected(); // triggered if the connection is established and ready to use
+
+private:
+
+ inline void timerStop();
+ void handleClientMsg(PVSMsg receiver);
+ void handleDisconnectInternal();
+
+ EventIdentDispatcher<PVSMsg> _commandDispatcher;
+ EventIdentDispatcher<PVSMsg> _chatDispatcher;
+ EventIdentDispatcher<PVSMsg> _loginDispatcher;
+ PVSMsg *_incomplete;
+ QSslSocket *_socket;
+ unsigned int _id;
+ int _timerId;
+ //QString _host;
+ //quint16 _port;
+ int _timer;
+ PVS *_client;
+ bool _wasConnected;
+ QByteArray _expectedFingerprint;
+ QString _name;
+ QString _passwd;
+};
+
+#endif
diff --git a/src/net/pvsServiceBroadcast.cpp b/src/net/pvsServiceBroadcast.cpp
new file mode 100644
index 0000000..cf15b5b
--- /dev/null
+++ b/src/net/pvsServiceBroadcast.cpp
@@ -0,0 +1,51 @@
+/*
+# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+# -----------------------------------------------------------------------------
+# src/net/pvsServiceBroadcast.cpp
+# - broadcast sessionname
+# -----------------------------------------------------------------------------
+*/
+/********** COMPILE-TIME SETTINGS ***************/
+
+#include "pvsServiceBroadcast.h"
+#include "src/setup.h"
+#include <cassert>
+#include "src/util/serviceDiscoveryUtil.h"
+
+PVSServiceBroadcast::PVSServiceBroadcast()
+{
+ _announce = NULL;
+ _timer = 0;
+ _broadcaster.bind(SD_PORT_CONSOLE);
+ _everyone = QHostAddress(QHostAddress::Broadcast);
+}
+
+PVSServiceBroadcast::~PVSServiceBroadcast()
+{
+ if (_announce != NULL) delete _announce;
+ if (_timer != 0) this->killTimer(_timer);
+}
+
+void PVSServiceBroadcast::setFingerprint(QByteArray sha1)
+{
+ if (_announce != NULL) _announce->clear();
+ else _announce = new QByteArray();
+ appendSdField(_announce, "hsh", QString(sha1.toBase64()));
+ appendSdField(_announce, "prt", SERVER_PORT); // TODO: maybe this has to come from somewhere else if configurable
+ appendSdField(_announce, "aut", "SHA1");
+ if (_timer == 0) _timer = this->startTimer(SB_INTERVAL * 1000);
+}
+
+void PVSServiceBroadcast::timerEvent(QTimerEvent *event)
+{
+ if (_announce == NULL) return;
+ _broadcaster.writeDatagram(*_announce, _everyone, SD_PORT_CLIENT);
+}
diff --git a/src/net/pvsServiceBroadcast.h b/src/net/pvsServiceBroadcast.h
new file mode 100644
index 0000000..cf3f63d
--- /dev/null
+++ b/src/net/pvsServiceBroadcast.h
@@ -0,0 +1,46 @@
+/*
+# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+# -----------------------------------------------------------------------------
+# src/net/pvsServiceBroadcast.cpp
+# - broadcast sessionname, port, auth/encryption
+# -----------------------------------------------------------------------------
+*/
+
+#ifndef PVSSERVICEBROADCAST_H_
+#define PVSSERVICEBROADCAST_H_
+
+#include <QtCore/QString>
+#include <QtCore/QObject>
+#include <QtNetwork/QUdpSocket>
+#include "src/net/pvsMsg.h"
+
+class PVSMsg;
+
+class PVSServiceBroadcast : public QObject
+{
+ Q_OBJECT
+
+public:
+ PVSServiceBroadcast();
+ virtual ~PVSServiceBroadcast();
+ void setFingerprint(QByteArray sha1);
+
+protected:
+ void timerEvent(QTimerEvent *event);
+
+private:
+ QByteArray *_announce;
+ QUdpSocket _broadcaster;
+ QHostAddress _everyone;
+ int _timer;
+};
+
+#endif /* PVSSERVICEBROADCAST_H_ */
diff --git a/src/net/pvsServiceDiscovery.cpp b/src/net/pvsServiceDiscovery.cpp
new file mode 100644
index 0000000..0a99802
--- /dev/null
+++ b/src/net/pvsServiceDiscovery.cpp
@@ -0,0 +1,181 @@
+/*
+# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+# -----------------------------------------------------------------------------
+# src/net/pvsServiceDiscovery.cpp
+# - handle console broadcasts, tell client to connect on match
+# -----------------------------------------------------------------------------
+*/
+
+#include <QtCore/QHash>
+#include "src/pvs.h"
+#include "pvsServiceDiscovery.h"
+#include "pvsDiscoveredServer.h"
+#include "src/setup.h"
+#include "src/util/serviceDiscoveryUtil.h"
+#include <cassert>
+
+
+
+PVSServiceDiscovery::PVSServiceDiscovery(PVS* client)
+{
+ assert(client);
+ bool ret = _sock.bind(SD_PORT_CLIENT);
+ if (!ret)
+ {
+ printf("Could not open SERVICE DISCOVERY port\n");
+ exit(1);
+ }
+ connect(&_sock, SIGNAL(readyRead()), this, SLOT(sock_dataArrival()));
+ _currentServer = 0;
+ _last = QDateTime::currentDateTime();
+ _client = client;
+ _timerId = startTimer(10000);
+}
+
+PVSServiceDiscovery::~PVSServiceDiscovery()
+{
+ killTimer(_timerId);
+}
+
+void PVSServiceDiscovery::connectToSession(QString name, QString passwd)
+{
+ _sessionName = name;
+ _sessionPasswd = passwd;
+ if (name.length() == 0) return;
+ for (tServerList::iterator it = _servers.begin(); it != _servers.end(); it++)
+ {
+ PVSDiscoveredServer *ds = *it;
+ if (ds->isValid() && ds->getName() == name)
+ {
+ _client->connectToHost(ds, _sessionPasswd);
+ }
+ }
+}
+
+void PVSServiceDiscovery::sock_dataArrival()
+{
+ int len;
+ while ((len = _sock.pendingDatagramSize()) > -1)
+ {
+ if (len == 0) continue;
+ char *data = new char[len];
+ QHostAddress host;
+ len = _sock.readDatagram(data, len, &host);
+ SdFields fields = parseSdFields((unsigned char*)data, len);
+ QDateTime now = QDateTime::currentDateTime();
+ if (fields.contains("hsh") && fields.contains("prt") && fields.contains("aut"))
+ {
+ if (fields["aut"] == "SHA1")
+ {
+ this->handleDiscovery(
+ host,
+ atoi(fields["prt"].toUtf8().data()),
+ QByteArray::fromBase64(fields["hsh"].toAscii())
+ );
+ }
+ }
+ /*
+ // DEBUG ONLY: connect to any host without matching the session name
+ if (_last.secsTo(now) > 9 && fields.contains("prt"))
+ {
+ _last = now;
+ int port = atoi(fields["prt"].toUtf8().data());
+ _client->connectToHost(host, QByteArray(), port);
+ }
+ // ^^^^^^^^^^
+ */
+ }
+}
+
+void PVSServiceDiscovery::handleDiscovery(QHostAddress host, int port, QByteArray hash)
+{
+ int numhosts = 0; ///< while iterating we count how many entries have the same host
+ for (tServerList::iterator it = _servers.begin(); it != _servers.end(); it++)
+ {
+ if ((**it).hasHost(host))
+ {
+ ConsoleLog writeNetwork(host.toString() + " == " + (**it).getHost().toString());
+ if (++numhosts >= 5) return; // ddos through faked service broadcasts? ignore...
+ if ((**it).hasFingerprint(hash) && (**it).getPort() == port) // known entry...
+ {
+ if ((*it)->isValid() && (*it)->getName() == _sessionName && _sessionName.length() > 0)
+ {
+ ConsoleLog writeNetwork(QString("Connecting to ").append(_sessionName));
+ _client->connectToHost((*it), _sessionPasswd);
+ }
+ (**it).update(port);
+ return;
+ }
+ }
+ }
+ if (_servers.length() >= 30) return; // !?
+ QString oname = sha1ToReadable(hash);
+ QString name = oname;
+ int dup = 0;
+ while (nameExists(name))
+ {
+ name = "(" + QString::number(++dup) + ") " + oname;
+ }
+ PVSDiscoveredServer *ds = new PVSDiscoveredServer(this, host, port, hash, name);
+ connect(ds, SIGNAL(validated(PVSDiscoveredServer*)), this, SLOT(sendServerToGui(PVSDiscoveredServer*)));
+ _servers.push_back(ds);
+ setTimerInterval();
+}
+
+bool PVSServiceDiscovery::nameExists(QString name)
+{
+ for (tServerList::iterator it = _servers.begin(); it != _servers.end(); it++)
+ {
+ if ((**it).getName() == name) return true;
+ }
+ return false;
+}
+
+QStringList PVSServiceDiscovery::getAllServers()
+{
+ QStringList hosts;
+ for (tServerList::iterator it = _servers.begin(); it != _servers.end(); it++)
+ {
+ if ((**it).isValid()) hosts.append((**it).getName());
+ }
+ return hosts;
+}
+
+void PVSServiceDiscovery::sendServerToGui(PVSDiscoveredServer* ds)
+{
+ _client->guiAddHost(ds->getName());
+}
+
+void PVSServiceDiscovery::timerEvent(QTimerEvent *event)
+{
+ if (_servers.size() == 0) return;
+ if (_currentServer >= _servers.size()) _currentServer = 0;
+ PVSDiscoveredServer *ds = _servers.at(_currentServer);
+ if (ds->getAge() >= SB_INTERVAL*2 + 1) // Entry too old?
+ {
+ disconnect(ds, SIGNAL(validated(PVSDiscoveredServer*)), this, SLOT(sendServerToGui(PVSDiscoveredServer*)));
+ _client->guiDelHost(ds->getName());
+ delete ds;
+ _servers.removeAt(_currentServer); // Clean it up
+ setTimerInterval();
+ }
+ else
+ {
+ ds->validateCertificate();
+ }
+ ++_currentServer;
+}
+
+void PVSServiceDiscovery::setTimerInterval()
+{
+ killTimer(_timerId);
+ _timerId = startTimer(10000 / (_servers.size() + 1));
+}
diff --git a/src/net/pvsServiceDiscovery.h b/src/net/pvsServiceDiscovery.h
new file mode 100644
index 0000000..08a38b8
--- /dev/null
+++ b/src/net/pvsServiceDiscovery.h
@@ -0,0 +1,57 @@
+/*
+# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+# -----------------------------------------------------------------------------
+# src/net/pvsServiceDiscovery.cpp
+# - handle console broadcasts, tell client to connect on match
+# -----------------------------------------------------------------------------
+*/
+
+#ifndef PVSSERVICEDISCOVERY_H_
+#define PVSSERVICEDISCOVERY_H_
+
+#include <QtNetwork/QUdpSocket>
+#include <QtCore/QDateTime>
+
+class PVS;
+class PVSDiscoveredServer;
+typedef QList<PVSDiscoveredServer*> tServerList;
+
+class PVSServiceDiscovery : public QObject
+{
+ Q_OBJECT
+public:
+ PVSServiceDiscovery(PVS* client);
+ virtual ~PVSServiceDiscovery();
+ void connectToSession(QString name, QString passwd);
+ bool nameExists(QString name);
+ QStringList getAllServers();
+
+protected:
+ void timerEvent(QTimerEvent *event);
+
+private Q_SLOTS:
+ void sock_dataArrival();
+ void sendServerToGui(PVSDiscoveredServer*);
+
+private:
+ void handleDiscovery(QHostAddress host, int port, QByteArray hash);
+ void setTimerInterval();
+ QUdpSocket _sock;
+ QString _sessionName;
+ QString _sessionPasswd;
+ PVS *_client;
+ QDateTime _last; ///< to protect us from being abused as a ddos zombie
+ tServerList _servers;
+ int _currentServer;
+ int _timerId;
+};
+
+#endif /* PVSSERVICEDISCOVERY_H_ */
diff --git a/src/pvs.cpp b/src/pvs.cpp
new file mode 100644
index 0000000..2069e36
--- /dev/null
+++ b/src/pvs.cpp
@@ -0,0 +1,629 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ */
+
+#include "pvs.h"
+#include "src/util/dispatcher.h"
+#include "src/net/pvsMsg.h"
+#include "src/net/pvsServiceDiscovery.h"
+#include "src/net/pvsDiscoveredServer.h"
+
+// D-Bus
+#include "pvsadaptor.h"
+
+extern PVS *mainClient;
+
+// !!STATION LOCK TESTING!!
+//#define lock_test_unlock_time 3
+// uncomment the following line to test locking in a local context
+// it disables the lock of a station #(lock_test_unlock_time) seconds after it has been locked
+//#define lock_test
+
+PVS::PVS() :
+ QObject()
+{
+ _pvsServerConnection = new PVSServerConnection(this);
+ _locked = false;
+ _vncAllowed = false;
+ _vncRequested = false;
+ readPolicyFiles();
+ loadCommands();
+ _blankScreen = NULL;
+ _vncPort = -1;
+
+ // add a notify to the allow file, so we get informed when the file is changed
+ QString watchPath("/home/");
+ watchPath.append(getUserName().append(QString("/.pvs/.allow")));
+ _notify = new QFileSystemWatcher(this);
+ _notify->addPath(QString(watchPath.toUtf8().data()));
+
+ connect(_notify, SIGNAL(fileChanged(const QString &)), this,
+ SLOT(fileChanged(const QString &)));
+
+ // connect to D-Bus
+ new PvsAdaptor(this);
+ QDBusConnection dbus = QDBusConnection::sessionBus();
+ dbus.registerObject("/", this);
+ dbus.registerService("org.openslx.pvs");
+
+ _sdClient = new PVSServiceDiscovery(this);
+
+ _chat = new PVSChatClient();
+ _chat->setServerConnection(_pvsServerConnection);
+ _chat->getChatMsgHandler().addListener(this, &PVS::chat_receive);
+ _chat->getChatCommandHandler().addListener(this, &PVS::UpdateChatClients);
+
+ _timerLockTest = 0;
+ _timerLockDelay = 0;
+
+ //add signalhandling for sigterm signals
+ struct sigaction act;
+ act.sa_handler = &PVS::signalHandler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+
+ //register signals with actions
+ sigaction(SIGTERM, &act, 0);
+ sigaction(SIGHUP, &act, 0);
+ sigaction(SIGINT, &act, 0);
+ sigaction(SIGQUIT, &act, 0);
+
+}
+
+PVS::~PVS()
+{
+ // make sure we dont leave a locked computer
+ if (_notify)
+ disconnect(_notify, SIGNAL(fileChanged(const QString &)), this,
+ SLOT(fileChanged(const QString &)));
+ unlock();
+ delete _sdClient;
+}
+
+void PVS::connectToHost(PVSDiscoveredServer* server, QString passwd)
+{
+ _pvsServerConnection->connectToServer(server, passwd);
+}
+
+/**
+ * onCommand Callback method
+ * handles incoming commands
+ */
+void PVS::onCommand(PVSMsg cmdMessage)
+{
+ QString message = cmdMessage.getMessage();
+ QString ident = cmdMessage.getIdent();
+ if (ident.compare("LOCKSTATION") == 0)
+ {
+ if (_blankScreen)
+ {
+ return;
+ }
+ else
+ {
+ _lockMsg = message;
+ //TODO:@Javier: lock it eith message.
+ // Sent message.
+ if(message.size() > 0) // Lock client with message.
+ {
+ message = message + "\n \n WARNING: Your screen will be blocked in 10 seconds.";
+ emit showMessage("Lock Message", message, true);
+ _timerLockDelay = startTimer(10*1000); // 10 sec.
+ }
+ else // lock client without message.
+ {
+ lock();
+ }
+ }
+
+ return;
+ }
+ if (ident.compare("UNLOCKSTATION") == 0)
+ {
+ _timerLockDelay = 0;
+ if (!_blankScreen)
+ {
+ return;
+ }
+ else
+ {
+ ConsoleLog writeLine("Unlocked.");
+ unlock();
+ }
+ return;
+ }
+ if (ident.compare("VNCREQUEST") == 0)
+ {
+ // a vnc connection was requested, so lets check if this is against our policies
+ _vncRequested = (message.compare("YES") == 0);
+ if (!_vncRequested) return;
+ getVNCAllow();
+ return;
+ }
+ if (ident.compare("PROJECT") == 0)
+ {
+ std::vector<QString> connDetails;
+ std::string buf;
+ std::stringstream ss(message.toStdString());
+ while (ss >> buf)
+ connDetails.push_back(QString::fromStdString(buf));
+
+ if(connDetails.size() == 4) {
+ int port, quality;
+ bool fullscreen, smooth;
+ fullscreen = smooth = true;
+ port = connDetails[1].toInt();
+ quality = connDetails[3].toInt();
+ if(port > 0) {
+ emit project(connDetails[0], port, connDetails[2], fullscreen, smooth, quality);
+ lock_inputs();
+ ConsoleLog writeNetwork(QString("Received Projection Information: Projsrc: ").append(connDetails[0]).append( " port: ").append(connDetails[1]).append(" pass:").append(connDetails[2]));
+ }
+ ConsoleLog writeNetwork(QString("Received illegal port! (").append(port).append(")"));
+ }
+ }
+ if (ident.compare("UNPROJECT") == 0)
+ {
+ emit unproject();
+ unlock();
+ return;
+ }
+
+#ifdef never
+ // prototype
+ if (command.compare(<<string>>) == 0)
+ {
+ // do stuff
+ return;
+ }
+#endif
+}
+
+/**
+ * onLogin Callback method
+ * handles the servers login messages (see PVSListenServer)
+ */
+void PVS::onLogin(PVSMsg login)
+{
+ if (login.getIdent().compare(QString("ACCEPTED")) == 0)
+ {
+ ConsoleLog writeNetwork("Server accepted connection.");
+ login.getMessage();
+ }
+ else if (login.getIdent().compare(QString("DENIED")) == 0)
+ {
+
+ ConsoleLog writeNetwork(QString("Sent Username."));
+ }
+}
+
+void PVS::chat_send(QString nick_to, QString nick_from, QString msg)
+{
+ _chat->send(nick_to, msg);
+}
+
+void PVS::UpdateChatClients(PVSChatMsg chatCommand)
+{
+ if(chatCommand.getCommand().compare("clientToAdd") == 0)
+ {
+ _chat->addClient(chatCommand.getUsername(), chatCommand.getIp());
+ emit chat_client_add(chatCommand.getUsername());
+ }
+
+ if(chatCommand.getCommand().compare("clientToRemove") == 0)
+ {
+ _chat->removeClient(chatCommand.getUsername());
+ emit chat_client_remove(chatCommand.getUsername());
+ }
+
+ if(chatCommand.getCommand().compare("assignedName") == 0)
+ {
+ _chat->setSource(chatCommand.getUsername());
+ }
+}
+
+void PVS::chat_receive(PVSChatMsg msg)
+{
+ emit chat_receive(msg.getNickFrom(), msg.getNickTo(), msg.getMsg());
+}
+
+/**
+ * onDaemon Callback method
+ * handles incoming UDS Communicator messages
+ */
+void PVS::onDaemonCommand(PVSMsg msg)
+{
+ if (msg.getIdent().compare(QString("stop")) == 0)
+ {
+ stop();
+ unlock();
+ exit(0);
+ }
+}
+
+void PVS::onMessage(PVSMsg msg)
+{
+ QString ident = msg.getIdent();
+ QString message = msg.getMessage();
+
+ if (ident.compare("BROADCAST") == 0)
+ {
+ emit showMessage(tr("Message"), message, true);
+ }
+}
+
+/**
+ * load custom commands by adding callbacks to the dispatchers
+ */
+void PVS::loadCommands()
+{
+ if (_pvsServerConnection)
+ {
+ _pvsServerConnection->addCommandHandler("*", this, &PVS::onCommand);
+ _pvsServerConnection->addLoginHandler("*", this, &PVS::onLogin);
+ _pvsServerConnection->addChatHandler("*", this, &PVS::onMessage);
+ }
+}
+
+void PVS::quit()
+{
+ stop();
+ unlock();
+ exit(0);
+}
+
+/**
+ * stops the client
+ */
+void PVS::stop()
+{
+ _pvsServerConnection->disconnectFromServer();
+ stopVNCScript();
+}
+
+/**
+ * used to unlock the client after 3 seconds
+ * this a maintainance method
+ * uncomment the define to use it
+ */
+void PVS::timerEvent(QTimerEvent *event)
+{
+#ifdef lock_test
+ if (_locked && event->timerId()== _timerLockTest) unlock();
+#endif
+ if(_timerLockDelay == event->timerId())
+ {
+ if (lock()) ConsoleLog writeLine(QString("Locked."));
+ _timerLockDelay = 0;
+ }
+ killTimer(event->timerId());
+}
+
+bool PVS::allowExists()
+{
+ return policyFileExists(QString(".allow"));
+}
+
+/**
+ * check whether we want to allow vnc connections to this client
+ */
+bool PVS::getVNCAllow()
+{
+ if (allowExists())
+ {
+ if (getAllowed())
+ {
+ _vncAllowed = true;
+ }
+ else
+ {
+ _vncAllowed = false;
+ }
+ }
+ else
+ {
+ ConsoleLog writeError("No .allow file found.");
+ _vncAllowed = false;
+ //make sure the vncsever is off
+ ConsoleLog writeError("Shutting down vnc-server because we have no .allow file.");
+ }
+
+ if (_vncAllowed && _vncRequested)
+ {
+ // then boot up the vnc-server and set password and port
+ int result = bootVNC();
+ if (result == 0)
+ {
+ // now inform the server
+ _pvsServerConnection->sendMessage(PVSMsg(PVSCOMMAND, "PORT", int2String(_vncPort)));
+ _pvsServerConnection->sendMessage(PVSMsg(PVSCOMMAND, "PASSWORD", _vncPassword));
+ _pvsServerConnection->sendMessage(PVSMsg(PVSCOMMAND, "RWPASSWORD", _vncRwPassword));
+ _pvsServerConnection->sendMessage(PVSMsg(PVSCOMMAND, "VNC","YES"));
+ ConsoleLog writeNetwork(QString("Sent password, port and granted access."));
+ // show message on clientgui
+ emit showMessage(tr("VNC connection"), tr("The host ")
+ .append(_pvsServerConnection->getServerName()
+ .append(tr(" requested your screen!"))));
+ }
+ _pvsServerConnection->sendMessage(PVSMsg(PVSCOMMAND, "VNCSRVRESULT", int2String(result)));
+
+ }
+ else if (!_vncAllowed)
+ {
+ stopVNCScript();
+ _pvsServerConnection->sendMessage(PVSMsg(PVSCOMMAND, "VNC","NO"));
+ }
+ return _vncAllowed;
+}
+
+/**
+ * read the policy files
+ */
+void PVS::readPolicyFiles()
+{
+ getVNCAllow();
+ // Add more policyfiles here if any
+}
+
+/**
+ * callback which gets invoked when the watched file is changed
+ */
+void PVS::fileChanged(const QString& path)
+{
+ getVNCAllow();
+}
+
+/**
+ * lock the client
+ */
+bool PVS::lock()
+{
+
+#ifdef lock_test
+ _timerLockTest = startTimer(lock_test_unlock_time * 1000);
+ printf("will auto-unlock in %d secs\n", int(lock_test_unlock_time));
+#endif
+
+ if (!_blankScreen)
+ {
+ _blankScreen = new BlankScreen();
+ if (_blankScreen)
+ return _locked = _blankScreen->lock();
+ else
+ return false;
+ }
+ return true;
+}
+
+/**
+ * lock the client inputs only
+ */
+bool PVS::lock_inputs()
+{
+
+#ifdef lock_test
+ _timerLockTest = startTimer(lock_test_unlock_time * 1000);
+ printf("will auto-unlock in %d secs\n", int(lock_test_unlock_time));
+#endif
+
+ if (!_blankScreen)
+ {
+ _blankScreen = new BlankScreen();
+ if (_blankScreen)
+ return _locked = _blankScreen->lock_inputs();
+ else
+ return false;
+ }
+ return true;
+}
+
+/**
+ * unlock the client
+ */
+bool PVS::unlock()
+{
+ if (_blankScreen)
+ {
+ if (_blankScreen->unlock())
+ {
+ delete _blankScreen;
+ _blankScreen = NULL;
+ }
+ }
+ return false;
+}
+
+void PVS::setScriptPath(QString path)
+{
+ _vncScriptPath = path;
+ _vncScriptName = getFilenameFromPath(_vncScriptPath);
+}
+
+bool PVS::gotVNCScript()
+{
+ if (fileExists(_vncScriptPath))
+ return true;
+ if (policyFileExists(_vncScriptName))
+ return true;
+ return false;
+
+}
+/**
+ * setup password and port
+ * the local_test define is used to enable local testing modes without invoking the vnc-script
+ */
+int PVS::bootVNC()
+{
+ // #define local_test
+
+ stopVNCScript(); // just to be sure
+#ifndef local_test
+ _vncPassword = int2String(getRandom(0, 99999999));
+ do {
+ _vncRwPassword = int2String(getRandom(0, 99999999));
+ } while (_vncRwPassword == _vncPassword);
+
+ _vncPort = getRandom(5901, 6000);
+ return startVNCScript(_vncPort, _vncPassword, _vncRwPassword);
+#else
+ _vncPassword = QString("1234");
+ _vncPort = 5901;
+ return startVNCScript(_vncPort, _vncPassword);
+#endif
+ //#undef local_test
+}
+
+/**
+ * launch the vnc script (if present) to start the vnc-server
+ */
+int PVS::startVNCScript(int port, QString pass, QString rwpass)
+{
+ if (gotVNCScript())
+ {
+ ConsoleLog writeLine("Starting VNC-Script");
+ QString commandLine(_vncScriptPath);
+ commandLine.append(" ");
+ commandLine.append("start");
+ commandLine.append(" ");
+ commandLine.append(int2String(port));
+ commandLine.append(" ");
+ commandLine.append(pass);
+ commandLine.append(" ");
+ commandLine.append(rwpass);
+ if (!system(NULL))
+ ConsoleLog writeError("No Command processor available");
+
+ int result = system(commandLine.toUtf8().data());
+ result = WEXITSTATUS(result);
+ if (result != 0)
+ ConsoleLog writeError(QString("VNC-Server is not running, code: ") + int2String(result));
+ else
+ ConsoleLog writeLine("VNC-Server should be running");
+ return result;
+ }
+ else
+ {
+ ConsoleLog writeError("VNC-Script not found.");
+ return 3;
+ }
+}
+
+/**
+ * launch the vnc script (if present) to stop the vnc-server
+ */
+int PVS::stopVNCScript()
+{
+ if (gotVNCScript())
+ {
+ ConsoleLog writeLine("Stopping VNC-Script");
+ QString commandLine(_vncScriptPath);
+ commandLine.append(" ");
+ commandLine.append("stop");
+ commandLine.append(" ");
+ commandLine.append("dummy");
+ commandLine.append(" ");
+ commandLine.append("dummy");
+ ConsoleLog writeLine("VNC-Server should be stopped");
+ int result = system(commandLine.toUtf8().data());
+ return WEXITSTATUS(result);
+ }
+ else
+ {
+ return 3;
+ }
+}
+
+void PVS::start()
+{
+ _pvsServerConnection->sendMessage(PVSMsg(PVSCOMMAND, "PROJECTING", "YES"));
+}
+
+void PVS::onConnected(QString name)
+{
+ emit connected(name);
+}
+
+void PVS::onDisconnected()
+{
+ emit disconnected();
+ _chat->clearClients();
+ stopVNCScript();
+}
+
+QString PVS::isConnected()
+{
+ return _pvsServerConnection->getServerName();
+}
+
+QString PVS::chat_getNickname()
+{
+ return _chat->getSource();
+}
+
+QStringList PVS::chat_getNicknames()
+{
+ return _chat->getClients();
+}
+
+void PVS::pvsConnect(QString host, QString passwd)
+{
+ _pvsServerConnection->disconnectFromServer();
+ _sdClient->connectToSession(host, passwd);
+}
+void PVS::pvsDisconnect()
+{
+ _chat->clearClients();
+ _sdClient->connectToSession("", "");
+ stop();
+}
+
+
+QStringList PVS::getAvailableHosts()
+{
+ return _sdClient->getAllServers();
+}
+
+void PVS::guiAddHost(QString host)
+{
+ emit addHost(host);
+}
+
+void PVS::guiDelHost(QString host)
+{
+ emit delHost(host);
+}
+
+QString PVS::getIpByNick(QString nick)
+{
+ return _chat->getIPFromUsername(nick);
+}
+
+//Handles signals (SIGTERM and SIGHUP)
+void PVS::signalHandler(int signal)
+{
+ ConsoleLog writeLine(QString("Received Signal ").append (int2String(signal)));
+ switch (signal) {
+ case SIGHUP:
+ mainClient->quit();
+ break;
+ case SIGTERM:
+ mainClient->quit();
+ break;
+ case SIGINT:
+ mainClient->quit();
+ break;
+ case SIGQUIT:
+ mainClient->quit();
+ break;
+ }
+
+}
+
diff --git a/src/pvs.h b/src/pvs.h
new file mode 100644
index 0000000..4b1e29e
--- /dev/null
+++ b/src/pvs.h
@@ -0,0 +1,146 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ */
+#ifndef PVSCLIENT_H_
+#define PVSCLIENT_H_
+
+#include <QtCore>
+#include <X11/Xlib.h>
+#include <X11/cursorfont.h>
+#include <signal.h>
+
+#include "setup.h"
+#include "src/core/pvsChatClient.h"
+#include "src/core/pvsChatMsg.h"
+#include "src/net/pvsServerConnection.h"
+#include "src/version.h"
+#include "src/util/consoleLogger.h"
+#include "src/util/clientGUIUtils.h"
+
+
+class PVSServiceDiscovery;
+class PVSDiscoveredServer;
+
+/**
+ * PVSClient
+ * base class for the pool video switch client
+ */
+class PVS: public QObject
+{
+ Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "org.openslx.pvs")
+
+public:
+ PVS();
+ ~PVS();
+
+ void loadCommands(); ///< not inherited, just named like the virtual methods of other net objects
+ void onCommand(PVSMsg cmdMessage); ///< not inherited, just named like the virtual methods of other net objects
+ void onLogin(PVSMsg cmdMessage); ///< not inherited, just named like the virtual methods of other net objects
+ void onDaemonCommand(PVSMsg cmdMessage); ///< not inherited, just named like the virtual methods of other net objects
+ void onMessage(PVSMsg cmdMessage);
+
+ void securityUnlock()
+ {
+ unlock();
+ }
+ ; ///< public forward to the unlock method
+ void stop(); ///< stop the client
+
+ void setScriptPath(QString path); ///< vnc-start related
+
+ void onConnected(QString name);
+ void onDisconnected();
+
+ void connectToHost(PVSDiscoveredServer* server, QString passwd);
+ void UpdateChatClients(PVSChatMsg chatCommand);
+ void chat_receive(PVSChatMsg msg);
+
+ void guiAddHost(QString host);
+ void guiDelHost(QString host);
+
+public Q_SLOTS:
+ void start();
+ void quit();
+ void chat_send(QString nick_to, QString nick_from, QString msg);
+ QString chat_getNickname();
+ QStringList chat_getNicknames();
+ void fileChanged(const QString& path);
+ void pvsConnect(QString host, QString passwd);
+ void pvsDisconnect();
+ QString isConnected();
+ QStringList getAvailableHosts();
+ QString getIpByNick(QString nick);
+
+Q_SIGNALS:
+ void project(QString host, int port, QString passwd, bool fullscreen,
+ bool smoothTransformation, int quality);
+ void unproject();
+ void chat_receive(QString nick_from, QString nick_to, QString msg);
+ void chat_client_add(QString nick);
+ void chat_client_remove(QString nick);
+ void showMessage(QString title, QString msg, bool useDialog = false);
+ void connected(QString host);
+ void disconnected();
+ void addHost(QString host);
+ void delHost(QString host);
+
+protected:
+
+ void timerEvent(QTimerEvent *event);
+
+private:
+
+ // own
+ bool allowExists(); ///< whether the .allow file exists
+ bool getVNCAllow(); ///< whether vnc-connections to this client are allowed
+ void readPolicyFiles(); ///< pars the policy files
+
+
+ // pvs features and related
+ bool lock(); ///< lock this client (blankscreen etc)
+ bool lock_inputs(); ///< lock this client mouse&keyboard only
+ bool unlock(); ///< remove the lock on this client
+
+ bool _locked; ///< are we locked?
+ QString _lockMsg; ///< message to display while we're locked
+ bool _vncAllowed; ///< whether vncConnections to this client are allowed (dup?)
+ BlankScreen *_blankScreen;///< obhject to blank the screen
+
+ QFileSystemWatcher* _notify; ///< used to get notifies about file changes
+ //vnc-server
+ QString _vncScriptPath; ///< path to the vnc script file
+ QString _vncScriptName; ///< name of the vnc script file
+ int _vncPort; ///< port to use for the vnc-server (also gets send to the pvsServer)
+ QString _vncPassword; ///< password to use for the vnc-server (also gets send to the pvsServer) - viewonly password
+ QString _vncRwPassword; ///< password to use for the vnc-server (also gets send to the pvsServer) - read-write password
+
+ bool gotVNCScript(); ///< whether we got a vnc script
+ int bootVNC(); ///< init the password and port, then call the startVNCScript() method
+ int startVNCScript(int port, QString pass, QString rwpass); ///< start the vnc server (via script)
+ int stopVNCScript(); ///< stop the vnc server (via script)
+ static void signalHandler(int signal); //handles posix signals
+
+ PVSServerConnection* _pvsServerConnection; ///< our tcp connection object to the pvsserver
+
+ QSettings _settings;
+
+ PVSServiceDiscovery *_sdClient;
+
+ PVSChatClient *_chat;
+
+ bool _vncRequested; ///< did pvsmgr request our screen?
+
+ int _timerLockTest;
+ int _timerLockDelay;
+
+};
+#endif /* PVSCLIENT_H_ */
diff --git a/src/pvsDaemon.cpp b/src/pvsDaemon.cpp
new file mode 100644
index 0000000..961e0f3
--- /dev/null
+++ b/src/pvsDaemon.cpp
@@ -0,0 +1,362 @@
+#include <QCoreApplication>
+#include <getopt.h>
+#include <stdlib.h>
+#include "pvs.h"
+#include "src/net/pvsLocalhostCommunicator.h"
+#include "src/util/pvsSettingsManager.h"
+#include "setup.h"
+#include "src/net/pvsMsg.h"
+#include "src/core/pvsChatClient.h"
+
+PVS *mainClient = NULL;
+
+// This define works as a switch whether to run as deamon or regular app
+#define as_daemon
+
+/// VERSION_STRING is defined in src/version.h
+void printVersion(bool doExit)
+{
+
+ printf("Version:\t"VERSION_STRING"\n");
+ if (doExit)
+ exit(0);
+}
+
+/// outputs the full help text
+void printHelp()
+{
+ printf("**************************************************************\n");
+ printf("\nPool Video Switch Client\n");
+ printf("**************************************************************\n");
+ printVersion(false);
+ printf("**************************************************************\n");
+ printf("Usage:\tpoolVSClient <<option> <value>, ... >\n\n");
+ printf("Options:\n\n");
+ printf("-vncScriptFile <fullpath\\filename>\n\tSpecifies a custom location for the vnc-start/stop-script.\n\tIf not specified, ~/.pvs/pvs-vncsrv is expected.\n\n");
+ printf("-freq <seconds>\n\tSpecifies how long to wait until a reconnection attempt is made.\n\tDefault is 5.\n\n");
+ printf("-port <port>\n\tSpecifies on which port to run.\n\tDefault is %d.\n\n", SERVER_PORT_INT);
+ printf("-h or --help\n\t Shows this help text and exits.\n\n");
+ printf("-v or --version\n\t Shows the current version and exits.\n");
+ printf(
+ "-c <string command>:<string value> \n\t Sends the command and the optional value to a running PVS-Client.\n\t Command and value may not contain spaces or colons.\n\t The dividing colon is mandatory.\n");
+ printf("-commands: \n\tPrints out available commands to use with -c . \n ");
+ printf("**************************************************************\n");
+ exit(0);
+}
+
+/// outputs a brief help text
+void printNotice()
+{
+ printf(
+ "Use -h or --help to get a listing of all options.\n-v or --version gives you the current version.\n\n");
+}
+
+void printCommands()
+{
+ printf("**************************************************************\n");
+ printf("chat:<on/ off/ 1/ 2/ 3>\n ");
+ printf("on = turns that chat option on\n off = turns the chat option off\n 1 = bossmode\n 2 = community\n 3 = private\n");
+ printf("stop \n\t Stops the running PVS-Client.\n");
+ printf("**************************************************************\n");
+ exit(0);
+}
+
+///
+int main(int argc, char** argv)
+{
+ int frequency = 5;
+ int port = -1;
+ QString homeDir("/home/");
+ QString scriptPath = homeDir;
+ scriptPath.append(getUserName().append(QString("/.pvs/pvs-vncsrv")));
+ QString scriptName;
+ scriptName = getFilenameFromPath(scriptPath);
+
+ QCoreApplication app(argc, argv);
+ app.setOrganizationName("openslx");
+ app.setOrganizationDomain("openslx.org");
+ app.setApplicationName("pvs");
+ // use system locale as language to translate gui
+ QTranslator translator;
+ translator.load(":pvs");
+ app.installTranslator(&translator);
+
+
+ PVSLocalhostCommunicator com(getPolicyFilePath(QString(
+ ".comfile")));
+ com.run();
+ if (!(com.running()))
+ {
+ printf("Error. UDS Communicator is not running. Exiting.\n");
+ exit(0);
+ }
+
+ printf("UDS Communicator is running.\n");
+ int option_index = 0;
+
+ while (1)
+ {
+ static struct option long_options[] =
+ {
+ { "help", no_argument, 0, 'h' },
+ { "commands", no_argument, 0, 'o' },
+ { "version", no_argument, 0, 'v' },
+ { "port", required_argument, 0, 'p' },
+ { "freq", required_argument, 0, 'f' },
+ { "client", required_argument, 0, 'e' },
+ { "script", required_argument, 0, 's' },
+ { 0, 0, 0, 0 },
+ };
+ /* getopt_long stores the option index here. */
+
+ int c = getopt_long(argc, argv, "hvoc:f:e:s:p:", long_options,
+ &option_index);
+ option_index++;
+ if (c == -1)
+ break;
+
+ switch (c)
+ {
+ case 'h':
+ printHelp();
+ break;
+ case 'o':
+ printCommands();
+ break;
+ case 'v':
+ printVersion(true);
+ break;
+ case 'c':
+ {
+ if (option_index + 1 < argc)
+ {
+ if (com.server())
+ {
+ // wont work, no daemon running
+ printf("Error. No running PVS-Client found. Exiting.\n");
+ com.stop();
+ }
+ else
+ {
+ QStringList line = QString::fromLocal8Bit(argv[option_index
+ + 1]).split(":");
+ QString &ident = line[0];
+ QString message;
+ if (line.size() > 1)
+ message = line[1];
+ if (ident.size() > 0) // no use sending empty idents... not even sure if this COULD happen
+ {
+ bool flag = false;
+ if (ident == "make")
+ PVSSettingsManager::getManager()->setConfigs();
+ else if (ident == "chat" && message == "boss")
+ {
+ PVSSettingsManager::getManager()->reWriteConfigs("chatmode", "bossmode");
+ flag = true;
+
+ }
+ else if (ident == "chat" && message == "all")
+ {
+ PVSSettingsManager::getManager()->reWriteConfigs("chatmode", "community");
+ flag = true;
+ }
+ else if (ident == "chat" && message == "private")
+ {
+ PVSSettingsManager::getManager()->reWriteConfigs("chatmode", "private");
+ flag = true;
+ }
+ else if (ident == "chat" && message == "on")
+ {
+ PVSSettingsManager::getManager()->reWriteConfigs("chatstate", "on");
+ flag = true;
+ }
+ else if (ident == "chat" && message == "off")
+ {
+ PVSSettingsManager::getManager()->reWriteConfigs("chatstate", "off");
+ flag = true;
+ }
+ else if (ident == "room")
+ {
+ //PVSSettingsManager::getManager()->reWriteConfigs(ident, message);
+ flag = true;
+ }
+ else if (ident == "stop" && message == NULL)
+ flag = true;
+ else
+ printf("option %s doesn't exist\n", ident.toUtf8().data());
+
+ if (flag)
+ {
+ qDebug("Will send i: %s, m: %s\n", ident.toUtf8().data(), message.toUtf8().data());
+ com.sendCommand(ident, message);
+ QCoreApplication::processEvents(QEventLoop::AllEvents);
+ printf("Sent command. Exiting.\n");
+ }
+ }
+
+ else
+ printf("Something went horribly wrong, since the ident is empty.\n");
+
+ }
+ }
+ else
+ {
+ printf("Error. No command issued. Exiting.\n");
+ }
+ exit(0); // and gone
+ break;
+ }
+ case 'f':
+ {
+ if (option_index + 1 < argc)
+ {
+ frequency = atoi(argv[option_index + 1]);
+ if (frequency <= 0)
+ {
+ frequency = 5; // return to standard
+ ConsoleLog writeError(QString(
+ "malformed frequency, setting standard = 5"));
+ printNotice();
+ }
+ else
+ ConsoleLog writeLine(QString("Using frequency ").append(
+ int2String(frequency)));
+ option_index++;
+ continue;
+ }
+ break;
+ }
+ case 'p':
+ {
+ if (option_index + 1 < argc)
+ {
+ port = atoi(argv[option_index + 1]);
+ if (port <= 0)
+ {
+ ConsoleLog writeTerminal(QString("port maybe malformed"));
+ printNotice();
+ port = -1; // return to standard
+ }
+ else
+ ConsoleLog writeTerminal(QString("Using port ").append(
+ int2String(port)));
+ option_index++;
+ continue;
+ }
+ break;
+ }
+ case 'e':
+ {
+ if (option_index + 1 < argc)
+ {
+ printf("WARNING: -e is deprecated\n");
+ option_index++;
+ continue;
+ }
+ break;
+ }
+ case 's':
+ {
+ if (option_index + 1 < argc)
+ {
+ scriptPath = QString(argv[option_index + 1]);
+ scriptName = getFilenameFromPath(scriptPath);
+ option_index++;
+ continue;
+ }
+ break;
+ }
+ case '?':
+ {
+ ConsoleLog writeError(
+ QString("Unrecognized option/paramter: ").append(
+ argv[option_index]));
+ printNotice();
+ }
+ default:
+ abort();
+ }
+ //else
+ // printNotice();
+ }
+
+ if (!com.server())
+ {
+ printf("Error. PoolVSClient already running. Exiting\n");
+ com.stop();
+ exit(0);
+ }
+
+ ConsoleLog setLogName(QString("log.client"));
+ ConsoleLog writeLine(QString("PVS-Client started."));
+
+#ifdef as_daemon
+
+ /* Our process ID and Session ID */
+ pid_t pid, sid;
+
+ /* Fork off the parent process */
+ pid = fork();
+ if (pid < 0)
+ {
+ exit(-1);
+ }
+ /* If we got a good PID, then
+ we can exit the parent process. */
+ if (pid > 0)
+ {
+ exit(0);
+ }
+
+ /* Change the file mode mask */
+ umask(0);
+
+ /* Open any logs here */
+
+ /* Create a new SID for the child process */
+ sid = setsid();
+ if (sid < 0)
+ {
+ /* Log the failure */
+ exit(-1);
+ }
+
+ /* Change the current working directory */
+ if ((chdir("/")) < 0)
+ {
+ /* Log the failure */
+ exit(-1);
+ }
+
+ /* Close out the standard file descriptors */
+ close(STDIN_FILENO);
+ freopen ((QString("/home/").append(getUserName().append(QString("/.pvs/dump")))).toUtf8().data(),"w",stdout);
+ //close(STDOUT_FILENO);
+ close(STDERR_FILENO);
+
+ /* Daemon-specific initialization goes here */
+
+ /* The Big Loop */
+
+#endif
+
+ mainClient = new PVS();
+ PVSSettingsManager::getManager()->setConfigFile(getPolicyFilePath("clientconf"));
+ com.getDispatcher()->addListener("*", mainClient, &PVS::onDaemonCommand);
+
+ if (port <= 0)
+ port = SERVER_PORT_INT;
+ ConsoleLog writeLine(QString("TCP-Port: ").append(int2String(port)));
+ mainClient->setScriptPath(scriptPath);
+ ConsoleLog writeLine(QString("VNCScriptPath: ").append(scriptPath));
+ createPolicyDir();
+ createPolicyFiles();
+
+ // long int gr = 0;
+ mainClient->setScriptPath(scriptPath);
+ app.exec();
+ delete mainClient;
+
+ return 0;
+}
+
diff --git a/src/pvsgui.cpp b/src/pvsgui.cpp
new file mode 100644
index 0000000..25f1cd6
--- /dev/null
+++ b/src/pvsgui.cpp
@@ -0,0 +1,444 @@
+/*
+ # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of
+ # Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # -----------------------------------------------------------------------------
+ # pvsClientGUI.cpp
+ # - main loop for pvs client GUI.
+ # - draws toolbar and system tray icon.
+ # - uses DBUS to communicate with pvs client.
+ # -----------------------------------------------------------------------------
+ */
+
+#include "pvsgui.h"
+
+PVSGUI::PVSGUI(QWidget *parent) :
+ QWidget(parent)
+{
+ setupUi(this);
+
+ _menu = new QMenu(this);
+ _hostMenu = new QMenu(tr("Connect"), this);
+ _hosts = new QHash<QString, QAction*> ();
+ _vncViewer = new ClientVNCViewer();
+ _chatDialog = new ClientChatDialog();
+ _configDialog = new ClientConfigDialog();
+ _infoDialog = new ClientInfoDialog();
+ _aboutDialog = new AboutDialog();
+
+ _hostMenu->setEnabled(false);
+ hostButton->setEnabled(false);
+
+ setupMenu();
+
+ if (QSystemTrayIcon::isSystemTrayAvailable())
+ {
+ qDebug("[%s] System tray available.", metaObject()->className());
+ _trayIcon = new QSystemTrayIcon(QIcon(":cam_off32.svg"), this);
+ _trayIcon->setContextMenu(_menu);
+ _trayIcon->setVisible(true);
+ _chatDialog->setTrayIcon(_trayIcon);
+ }
+ else
+ _trayIcon = NULL;
+
+ // connect to D-Bus and get interface
+ QDBusConnection dbus = QDBusConnection::sessionBus();
+ dbus.registerObject("/", this);
+ dbus.registerService("org.openslx.pvsgui");
+ _ifaceDBus = new OrgOpenslxPvsInterface("org.openslx.pvs", "/", dbus, this);
+ _ifaceDBus->start(); // start pvs if not running
+
+ // get available hosts
+ QDBusPendingReply<QStringList> reply0 = _ifaceDBus->getAvailableHosts();
+ reply0.waitForFinished();
+ QStringList hosts = reply0.value();
+ if (reply0.isValid() && !hosts.isEmpty())
+ foreach (QString host, hosts)
+ addHost(host);
+
+ // already connected?
+ QDBusPendingReply<QString> reply1 = _ifaceDBus->isConnected();
+ reply1.waitForFinished();
+ QString host = reply1.value();
+ if (reply1.isValid() && host != "")
+ connected(host);
+ else
+ disconnected();
+
+ if (dbus.isConnected())
+ qDebug("[%s] Connection to DBus successful!", metaObject()->className());
+
+ // TODO: perhaps this can go if fadi does his work
+ // check if vnc is allowed and setup checkbox
+ QFile file(QDir::toNativeSeparators(QDir::homePath() + "/.pvs/.allow"));
+ if (file.open(QIODevice::ReadOnly | QIODevice::Text))
+ {
+ QTextStream in(&file);
+ QString line = in.readLine();
+ if (line == "1")
+ vncCheckBox->setChecked(true);
+ file.close();
+ }
+
+ // listen on port 29481 for incoming file transfers
+ _serverSocket = new QTcpServer();
+ _serverSocket->listen(QHostAddress::Any, 29481);
+ connect(_serverSocket, SIGNAL(newConnection()), this, SLOT(receiveFile()));
+
+ // signals & slots - menu
+ connect(_disconnectAction, SIGNAL(triggered()), this, SLOT(pvsDisconnect()));
+ connect(_startChatAction, SIGNAL(triggered()), _chatDialog, SLOT(open()));
+ connect(_sendFileAction, SIGNAL(triggered()), this, SLOT(sendFile()));
+ connect(_configAction, SIGNAL(triggered()), _configDialog, SLOT(open()));
+ connect(_showInfoAction, SIGNAL(triggered()), _infoDialog, SLOT(open()));
+ connect(_aboutAction, SIGNAL(triggered()), _aboutDialog, SLOT(open()));
+ connect(_quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
+ connect(_configDialog, SIGNAL(configChanged()), this, SLOT(updateConfig()));
+
+ // signals & slots - toolbar
+ connect(_menu, SIGNAL(aboutToHide()), this, SLOT(hide()));
+ connect(_hostMenu, SIGNAL(aboutToHide()), this, SLOT(hide()));
+ connect(_hostMenu, SIGNAL(triggered(QAction*)), this,
+ SLOT(pvsConnect(QAction*)));
+ connect(vncCheckBox, SIGNAL(stateChanged(int)), this,
+ SLOT(setVncAllow(int)));
+
+ // signals & slots - dbus
+ connect(_ifaceDBus, SIGNAL(showMessage(QString, QString, bool)), this,
+ SLOT(showMessage(QString, QString, bool)));
+ connect(_ifaceDBus, SIGNAL(connected(QString)), this,
+ SLOT(connected(QString)));
+ connect(_ifaceDBus, SIGNAL(disconnected()), this, SLOT(disconnected()));
+ connect(_ifaceDBus, SIGNAL(addHost(QString)), this, SLOT(addHost(QString)));
+ connect(_ifaceDBus, SIGNAL(delHost(QString)), this, SLOT(delHost(QString)));
+
+ // show toolbar
+ setWindowFlags(Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint);
+ setAttribute(Qt::WA_AlwaysShowToolTips);
+ updateConfig();
+ setVisible(true);
+ hide();
+}
+
+PVSGUI::~PVSGUI()
+{
+ _ifaceDBus->quit();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Public
+
+void PVSGUI::updateConfig()
+{
+ if (_settings.value("Display/location").isNull())
+ setLocation(POSITION_TOP_CENTER);
+ else
+ setLocation(_settings.value("Display/location").toInt());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Protected
+
+void PVSGUI::leaveEvent(QEvent * e)
+{
+ if (!_menu->isVisible() && !_hostMenu->isVisible())
+ hide(true);
+ QWidget::leaveEvent(e);
+}
+
+void PVSGUI::enterEvent(QEvent * e)
+{
+ hide(false);
+ QWidget::enterEvent(e);
+}
+
+void PVSGUI::mousePressEvent(QMouseEvent *event)
+{
+ QApplication::setOverrideCursor(QCursor(Qt::ClosedHandCursor));
+ _clickPoint = event->pos();
+}
+
+void PVSGUI::mouseReleaseEvent(QMouseEvent *event)
+{
+ QApplication::setOverrideCursor(QCursor(Qt::ArrowCursor));
+}
+
+void PVSGUI::mouseMoveEvent(QMouseEvent *event)
+{
+ if (event->globalX() - _clickPoint.x() >= 0 && event->globalX()
+ - _clickPoint.x() + width() <= QApplication::desktop()->width())
+ {
+ move(event->globalX() - _clickPoint.x(), y());
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Private
+
+void PVSGUI::setupMenu()
+{
+ // setup actions
+ _disconnectAction = new QAction(tr("&Disconnect"), this);
+ _startChatAction = new QAction(tr("C&hat"), this);
+ _sendFileAction = new QAction(tr("&Send File"), this);
+ _configAction = new QAction(tr("&Config"), this);
+ _showInfoAction = new QAction(tr("&Information"), this);
+ _aboutAction = new QAction(tr("&About"), this);
+ _quitAction = new QAction(tr("&Quit"), this);
+
+ // setup menu
+ _menu->addMenu(_hostMenu);
+ _menu->addAction(_disconnectAction);
+ _menu->addAction(_showInfoAction);
+ _menu->addSeparator();
+ _menu->addAction(_startChatAction);
+ _menu->addAction(_sendFileAction);
+ _menu->addSeparator();
+ _menu->addAction(_configAction);
+ _menu->addAction(_aboutAction);
+ _menu->addSeparator();
+ _menu->addAction(_quitAction);
+
+ pvsButton->setMenu(_menu);
+ hostButton->setMenu(_hostMenu);
+}
+
+void PVSGUI::setLocation(int location)
+{
+ _location = location;
+ switch (_location)
+ {
+ case POSITION_TOP_LEFT:
+ move(0, 0);
+ break;
+ case POSITION_TOP_CENTER:
+ move((QApplication::desktop()->width() - width()) / 2, 0);
+ break;
+ case POSITION_TOP_RIGHT:
+ move(QApplication::desktop()->width() - width(), 0);
+ break;
+ case POSITION_BOTTOM_LEFT:
+ move(0, QApplication::desktop()->height() - height());
+ break;
+ case POSITION_BOTTOM_CENTER:
+ move((QApplication::desktop()->width() - width()) / 2,
+ QApplication::desktop()->height() - height());
+ break;
+ case POSITION_BOTTOM_RIGHT:
+ move(QApplication::desktop()->width() - width(),
+ QApplication::desktop()->height() - height());
+ break;
+ default:
+ break;
+ }
+}
+
+void PVSGUI::hide(bool b)
+{
+ if (b)
+ {
+ if (_location <= POSITION_TOP_RIGHT)
+ move(x(), 2 - height());
+ else
+ move(x(), QApplication::desktop()->height() - 2);
+ }
+ else
+ {
+ if (_location <= POSITION_TOP_RIGHT)
+ move(x(), 0);
+ else
+ move(x(), QApplication::desktop()->height() - height());
+ }
+}
+
+void PVSGUI::hide()
+{
+ if (!_menu->isVisible() && !_hostMenu->isVisible())
+ hide(true);
+}
+
+void PVSGUI::pvsConnect(QAction *action)
+{
+ QString host = action->text();
+ action->setChecked(false); // we set it manually
+
+ // already connected?
+ if (host == hostButton->text())
+ {
+ action->setChecked(true);
+ return;
+ }
+
+ // ask user for passwd
+ bool ok = false;
+ QString passwd = QInputDialog::getText(0, tr("PVS Connection"), tr(
+ "Please enter password (If not needed leave blank):"),
+ QLineEdit::Password, QString(), &ok);
+
+ if (ok)
+ {
+ _ifaceDBus->pvsConnect(host, passwd); // send via dbus
+ _passwd = passwd; // TODO: we have to ask the backend for passwd!
+ qDebug("[%s] Host '%s' send via DBus.", metaObject()->className(),
+ qPrintable(host));
+ }
+}
+
+void PVSGUI::pvsDisconnect()
+{
+ QMessageBox::StandardButton result = QMessageBox::question(0, tr(
+ "PVS Connection"), tr("Are you sure you want to disconnect?"),
+ QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
+
+ if (result == QMessageBox::Ok)
+ _ifaceDBus->pvsDisconnect();
+}
+
+void PVSGUI::showMessage(QString title, QString msg, bool useDialog)
+{
+ if (!isVisible())
+ return;
+
+ // show balloon message if supported, otherwise show message dialog
+ if (!useDialog && _trayIcon && QSystemTrayIcon::supportsMessages())
+ _trayIcon->showMessage(title, msg, QSystemTrayIcon::Information, 10000);
+ else
+ QMessageBox::about(0, title, msg);
+}
+
+void PVSGUI::connected(QString host)
+{
+ statusLabel->setText(
+ "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\"><html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">p, li { white-space: pre-wrap; }</style></head><body style=\" font-family:'DejaVu Sans'; font-size:9pt; font-weight:400; font-style:normal;\"><p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" color:#00aa00;\">Online</span></p></body></html>");
+ showMessage(tr("PVS connection"), tr("Connected to ") + host);
+ if (_hosts->contains(host))
+ _hosts->value(host)->setChecked(true);
+ hostButton->setText(host);
+ _disconnectAction->setEnabled(true);
+ _startChatAction->setEnabled(true);
+ _sendFileAction->setEnabled(true);
+ _showInfoAction->setEnabled(true);
+ _infoDialog->setHost(host);
+ _infoDialog->setPasswd(_passwd);
+
+ if (_trayIcon)
+ {
+ _trayIcon->setIcon(QIcon(":cam_on32.svg"));
+ _trayIcon->setToolTip(tr("Connected to ") + host);
+ }
+}
+
+void PVSGUI::disconnected()
+{
+ statusLabel->setText(
+ "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\"><html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">p, li { white-space: pre-wrap; }</style></head><body style=\" font-family:'DejaVu Sans'; font-size:9pt; font-weight:400; font-style:normal;\"><p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" color:#ff0000;\">Offline</span></p></body></html>");
+ showMessage(tr("PVS connection"), tr("Disconnected"));
+ if (_hosts->contains(hostButton->text()))
+ _hosts->value(hostButton->text())->setChecked(false);
+ hostButton->setText("-");
+ _disconnectAction->setEnabled(false);
+ _startChatAction->setEnabled(false);
+ _sendFileAction->setEnabled(false);
+ _showInfoAction->setEnabled(false);
+ _passwd = "";
+ if (_trayIcon)
+ {
+ _trayIcon->setIcon(QIcon(":cam_off32.svg"));
+ _trayIcon->setToolTip(tr("Disconnected"));
+ }
+ _vncViewer->close();
+}
+
+void PVSGUI::addHost(QString host)
+{
+ // avoid duplicates
+ if (_hosts->contains(host))
+ return;
+
+ QAction *action = _hostMenu->addAction(host);
+ action->setCheckable(true);
+ _hosts->insert(host, action);
+
+ if (!_hosts->isEmpty())
+ {
+ _hostMenu->setEnabled(true);
+ hostButton->setEnabled(true);
+ }
+
+ if (hostButton->text() == "-")
+ showMessage(tr("PVS Connection"), tr("New host available: ") + host);
+}
+
+void PVSGUI::delHost(QString host)
+{
+ if (_hosts->contains(host))
+ {
+ _hostMenu->removeAction(_hosts->value(host));
+ _hosts->remove(host);
+ }
+
+ if (_hosts->isEmpty())
+ {
+ _hostMenu->setEnabled(false);
+ hostButton->setEnabled(false);
+ }
+}
+
+// TODO: perhaps this can go if fadi does his work
+void PVSGUI::setVncAllow(int i)
+{
+ QFile file(QDir::toNativeSeparators(QDir::homePath() + "/.pvs/.allow"));
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
+ return;
+
+ QTextStream out(&file);
+ if (i == 0)
+ out << 0;
+ else
+ out << 1;
+
+ file.close();
+}
+
+void PVSGUI::sendFile()
+{
+ ClientFileSendDialog *d = new ClientFileSendDialog();
+ d->open();
+}
+
+void PVSGUI::receiveFile()
+{
+ QTcpSocket *socket = _serverSocket->nextPendingConnection();
+ ClientFileReceiveDialog *d = new ClientFileReceiveDialog(socket);
+ d->open();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+// Main
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ app.setOrganizationName("openslx");
+ app.setOrganizationDomain("openslx.org");
+ app.setApplicationName("pvsgui");
+
+ // use system locale as language to translate gui
+ QTranslator translator;
+ translator.load(":pvsgui");
+ app.installTranslator(&translator);
+
+ PVSGUI pvsgui;
+
+ return app.exec();
+}
diff --git a/src/pvsgui.h b/src/pvsgui.h
new file mode 100644
index 0000000..f9a0ab8
--- /dev/null
+++ b/src/pvsgui.h
@@ -0,0 +1,103 @@
+/*
+ # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of
+ # Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ */
+
+#ifndef PVSCLIENTGUI_H_
+#define PVSCLIENTGUI_H_
+
+#include <QtGui>
+#include <QtNetwork>
+#include "ui_clientToolbar.h"
+#include "src/gui/clientConfigDialog.h"
+#include "src/gui/clientChatDialog.h"
+#include "src/gui/clientFileSendDialog.h"
+#include "src/gui/clientFileReceiveDialog.h"
+#include "src/gui/clientVNCViewer.h"
+#include "src/gui/clientInfoDialog.h"
+#include "src/gui/aboutDialog.h"
+
+#include "pvsinterface.h"
+
+class PVSGUI: public QWidget, private Ui_ClientToolbarClass
+{
+ Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "org.openslx.pvsgui")
+
+public:
+ PVSGUI(QWidget *parent = 0);
+ ~PVSGUI();
+
+ int const static POSITION_TOP_LEFT = 0;
+ int const static POSITION_TOP_CENTER = 1;
+ int const static POSITION_TOP_RIGHT = 2;
+ int const static POSITION_BOTTOM_LEFT = 3;
+ int const static POSITION_BOTTOM_CENTER = 4;
+ int const static POSITION_BOTTOM_RIGHT = 5;
+
+public Q_SLOTS:
+ void updateConfig();
+
+protected:
+ void enterEvent(QEvent *e);
+ void leaveEvent(QEvent *e);
+ void mousePressEvent(QMouseEvent *event);
+ void mouseReleaseEvent(QMouseEvent *event);
+ void mouseMoveEvent(QMouseEvent *event);
+
+private Q_SLOTS:
+ void showMessage(QString title, QString msg, bool useDialog = false);
+ void hide();
+ void connected(QString host);
+ void disconnected();
+ void addHost(QString host);
+ void delHost(QString host);
+ void pvsConnect(QAction *action);
+ void pvsDisconnect();
+ void setVncAllow(int i);
+ void sendFile();
+ void receiveFile();
+
+private:
+ void setupMenu();
+ void setLocation(int location);
+ void hide(bool b);
+
+ QMenu *_menu;
+ QMenu *_hostMenu;
+ QHash<QString, QAction*> *_hosts;
+ QSettings _settings;
+ QSystemTrayIcon *_trayIcon;
+ ClientChatDialog *_chatDialog;
+ ClientConfigDialog *_configDialog;
+ ClientInfoDialog *_infoDialog;
+ ClientVNCViewer *_vncViewer;
+ AboutDialog *_aboutDialog;
+
+ QAction *_disconnectAction;
+ QAction *_startChatAction;
+ QAction *_sendFileAction;
+ QAction *_configAction;
+ QAction *_showInfoAction;
+ QAction *_aboutAction;
+ QAction *_quitAction;
+
+ int _location;
+ QPoint _clickPoint;
+ QString _passwd;
+
+ QTcpServer *_serverSocket;
+
+ OrgOpenslxPvsInterface *_ifaceDBus;
+
+};
+
+#endif /* PVSCLIENTGUI_H_ */
diff --git a/src/pvsmgr.cpp b/src/pvsmgr.cpp
new file mode 100644
index 0000000..83f5fe0
--- /dev/null
+++ b/src/pvsmgr.cpp
@@ -0,0 +1,55 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # -----------------------------------------------------------------------------
+ # pvs.cpp
+ # - main loop for pvsmgr GUI.
+ # -----------------------------------------------------------------------------
+ */
+
+#include <QtGui>
+#include <QtGui/QDesktopServices>
+#include "gui/mainWindow.h"
+#include "util/consoleLogger.h"
+#include "util/pvsSettingsManager.h"
+#include "util/CertManager.h"
+
+QApplication *qtApp;
+
+int main(int argc, char** argv)
+{
+ //system("openssl genrsa 1024 >~/.pvs/");
+ qtApp = new QApplication(argc, argv);
+ qtApp->setOrganizationName("openslx");
+ qtApp->setOrganizationDomain("openslx.org");
+ qtApp->setApplicationName("pvsmgr");
+
+ // use system locale as language to translate gui
+ QTranslator translator;
+ translator.load(":pvsmgr");
+ qtApp->installTranslator(&translator);
+
+ ConsoleLog setLogName(QString("log.server"));
+ ConsoleLog writeLine(QString("PVS-Server started."));
+
+ QSslKey k = CertManager::getPrivateKey("manager"); // preload key so the gui won't hang later
+ /*
+ if (k.isNull())
+ {
+ printf("FATAL: Private key could not be generated or loaded!\n");
+ exit(123);
+ }
+ */
+ PVSSettingsManager::getManager()->setConfigFile(getPolicyFilePath("serverconf"));
+ MainWindow w;
+ w.show();
+ return qtApp->exec();
+}
+
diff --git a/src/pvsmgrtouch.cpp b/src/pvsmgrtouch.cpp
new file mode 100644
index 0000000..fa34294
--- /dev/null
+++ b/src/pvsmgrtouch.cpp
@@ -0,0 +1,55 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # -----------------------------------------------------------------------------
+ # pvs.cpp
+ # - main loop for pvs GUI.
+ # -----------------------------------------------------------------------------
+ */
+
+#include <QtGui>
+#include <QtGui/QDesktopServices>
+#include "gui/touchgui.h"
+#include "util/consoleLogger.h"
+#include "util/pvsSettingsManager.h"
+#include "util/CertManager.h"
+
+QApplication *qtApp;
+
+int main(int argc, char** argv)
+{
+ //system("openssl genrsa 1024 >~/.pvs/");
+ qtApp = new QApplication(argc, argv);
+ qtApp->setOrganizationName("openslx");
+ qtApp->setOrganizationDomain("openslx.org");
+ qtApp->setApplicationName("pvsmgr");
+
+ // use system locale as language to translate gui
+ /*QTranslator translator;
+ translator.load(":pvsmgr");
+ qtApp->installTranslator(&translator);*/
+
+ ConsoleLog setLogName(QString("log.server"));
+ ConsoleLog writeLine(QString("PVS-Server started."));
+
+ QSslKey k = CertManager::getPrivateKey("manager"); // preload key so the gui won't hang later
+ /*
+ if (k.isNull())
+ {
+ printf("FATAL: Private key could not be generated or loaded!\n");
+ exit(123);
+ }
+ */
+ PVSSettingsManager::getManager()->setConfigFile(getPolicyFilePath("serverconf"));
+ pvsMainWindow w;
+ w.show();
+ return qtApp->exec();
+}
+
diff --git a/src/setup.h b/src/setup.h
new file mode 100644
index 0000000..4a21754
--- /dev/null
+++ b/src/setup.h
@@ -0,0 +1,13 @@
+#ifndef _SETUP_H_
+#define _SETUP_H_
+
+#define SERVER_PORT "3490" // the port users will be connecting to
+#define SERVER_PORT_INT 3490 // the port users will be connecting to
+#define VNC_PORT_STRING "59000"
+#define VNC_PORT_INT 59000
+
+#define SB_INTERVAL 7 // Broadcast interval in seconds
+#define SD_PORT_CONSOLE 3491 // Not really used, Qt just wants a bind
+#define SD_PORT_CLIENT 3492 // This is where we expect announcements
+
+#endif
diff --git a/src/util/CertManager.cpp b/src/util/CertManager.cpp
new file mode 100644
index 0000000..99d2438
--- /dev/null
+++ b/src/util/CertManager.cpp
@@ -0,0 +1,87 @@
+/*
+# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+# -----------------------------------------------------------------------------
+# src/util/CertManager.cpp
+# - Manage SSL certificates
+# - provide access by name
+# -----------------------------------------------------------------------------
+*/
+
+#include "CertManager.h"
+#include "util.h"
+#include <QMap>
+#include <QFileInfo>
+#include <cstdlib>
+
+namespace CertManager
+{
+ static QMap<QString, QSslCertificate> _certs;
+ static QMap<QString, QSslKey> _keys;
+
+ void generateFiles(QString key, QString cert);
+
+ QSslKey getPrivateKey(QString name) {
+ if (_keys.contains(name)) return _keys[name];
+ QString cert = getPolicyFilePath(name);
+ QString key = cert;
+ key.append(".rsa");
+ cert.append(".crt");
+ //
+ QFileInfo keyfile(key);
+ QFileInfo certfile(cert);
+ if (keyfile.exists() && certfile.exists())
+ { // It wouldn't make sense to have one without the other
+ if (getCertificate(name).isNull()) return QSslKey();
+ QFile f(key);
+ f.open(QFile::ReadOnly);
+ QSslKey k = QSslKey(&f, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
+ _keys.insert(name, k);
+ return k;
+ }
+ generateFiles(key, cert);
+ keyfile = QFileInfo(key);
+ if (!keyfile.exists() || getCertificate(name).isNull()) return QSslKey();
+ QFile f(key);
+ f.open(QFile::ReadOnly);
+ QSslKey k = QSslKey(&f, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
+ if (!k.isNull()) _keys.insert(name, k);
+ return k;
+ }
+
+ QSslCertificate getCertificate(QString name) {
+ if (_certs.contains(name)) return _certs[name];
+ QString cert = getPolicyFilePath(name);
+ cert.append(".crt");
+ //
+ QFileInfo certfile(cert);
+ if (certfile.exists())
+ {
+ QList<QSslCertificate> certlist = QSslCertificate::fromPath(cert);
+ if (certlist.empty()) return QSslCertificate();
+ QSslCertificate c = certlist.first();
+ if (!c.isNull()) _certs.insert(name, c);
+ return c;
+ }
+ return QSslCertificate();
+ }
+
+ void generateFiles(QString key, QString cert)
+ {
+ char tmp[1000];
+ unlink(key.toLocal8Bit().data());
+ unlink(cert.toLocal8Bit().data());
+ snprintf(tmp, 1000, "openssl req -x509 -nodes -days 3650 -newkey rsa:1024 -subj '/C=DE/ST=BaWue/L=Freiburg/CN=openslx.org' -keyout \"%s\" -out \"%s\"",
+ key.toLocal8Bit().data(), cert.toLocal8Bit().data());
+ system(tmp);
+ snprintf(tmp, 1000, "chmod 0600 \"%s\" \"%s\"", key.toLocal8Bit().data(), cert.toLocal8Bit().data());
+ system(tmp);
+ }
+}
diff --git a/src/util/CertManager.h b/src/util/CertManager.h
new file mode 100644
index 0000000..8caab8b
--- /dev/null
+++ b/src/util/CertManager.h
@@ -0,0 +1,30 @@
+/*
+# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+# -----------------------------------------------------------------------------
+# src/util/CertManager.cpp
+# - Manage SSL certificates
+# - provide access by name
+# -----------------------------------------------------------------------------
+*/
+
+#ifndef CERTMANAGER_H_
+#define CERTMANAGER_H_
+
+#include <QtNetwork/QSslCertificate>
+#include <QtNetwork/QSslKey>
+
+namespace CertManager
+{
+ QSslKey getPrivateKey(QString name);
+ QSslCertificate getCertificate(QString name);
+}
+
+#endif /* CERTMANAGER_H_ */
diff --git a/src/util/TextFile.cpp b/src/util/TextFile.cpp
new file mode 100644
index 0000000..0d04e47
--- /dev/null
+++ b/src/util/TextFile.cpp
@@ -0,0 +1,39 @@
+/*
+ * TextFile.cpp
+ *
+ * Created on: 13.02.2010
+ * Author: Zahl
+ */
+
+#include "TextFile.h"
+
+TextFile::TextFile(QString filename) : QTextStream()
+{
+ _file = new QFile(filename);
+ if (_file->open(QIODevice::ReadOnly))
+ {
+ this->setDevice(_file);
+ _good = true;
+ }
+ else
+ {
+ _good = false;
+ }
+}
+
+bool TextFile::good()
+{
+ return _good;
+}
+
+bool TextFile::eof()
+{
+ if (!_good || this->atEnd()) return true;
+ return false;
+}
+
+TextFile::~TextFile()
+{
+ _file->close();
+ delete _file;
+}
diff --git a/src/util/TextFile.h b/src/util/TextFile.h
new file mode 100644
index 0000000..49932fa
--- /dev/null
+++ b/src/util/TextFile.h
@@ -0,0 +1,26 @@
+/*
+ * TextFile.h
+ *
+ * Created on: 13.02.2010
+ * Author: Zahl
+ */
+
+#ifndef TEXTFILE_H_
+#define TEXTFILE_H_
+
+#include <QtCore/QFile>
+#include <QtCore/QTextStream>
+
+class TextFile : public QTextStream
+{
+public:
+ TextFile(QString filename);
+ virtual ~TextFile();
+ bool good();
+ bool eof();
+protected:
+ QFile *_file;
+ bool _good;
+};
+
+#endif /* TEXTFILE_H_ */
diff --git a/src/util/clientGUIUtils.cpp b/src/util/clientGUIUtils.cpp
new file mode 100644
index 0000000..4d4cc0d
--- /dev/null
+++ b/src/util/clientGUIUtils.cpp
@@ -0,0 +1,144 @@
+#include "clientGUIUtils.h"
+
+BlankScreen::BlankScreen()
+{
+ dpy = XOpenDisplay(NULL);
+ scr = DefaultScreen(dpy);
+ assert(dpy);
+ blackColor = BlackPixel(dpy, DefaultScreen(dpy));
+ whiteColor = WhitePixel(dpy, DefaultScreen(dpy));
+// win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, 200, 100, 0, blackColor, whiteColor);
+ win = XCreateSimpleWindow(dpy, RootWindow(dpy, scr), 10, 10, 200, 200, 1, WhitePixel(dpy, scr), BlackPixel(dpy, scr));
+
+ XSelectInput(dpy, win, ExposureMask | KeyPressMask);
+ locked = false;
+ offX = offY = 0;
+}
+
+void BlankScreen::draw(bool force)
+{
+ if (locked)// no need to draw if we're not showing the window
+ {
+ XWindowAttributes xwa;
+ XGetWindowAttributes(dpy, DefaultRootWindow(dpy), &xwa);
+ int hx = (xwa.width)>>2, hy = (xwa.height)>>2;
+
+ if (XCheckTypedEvent(dpy, Expose, &ev) || force )
+ {
+ hx += offX;
+ hy += offY;
+
+ GC gcc = XCreateGC(dpy, win, 0, NULL);
+ XSetForeground(dpy, gcc, whiteColor);
+// XClearArea(dpy, win, 0, 0, xwa.width, xwa.height, false);
+ if (lockMsg.size() > 0)
+ {
+ char *msg = const_cast<char*>(lockMsg.toUtf8().data());
+ XDrawString(dpy, win, gcc/*DefaultGC(dpy, scr)*/, hx, hy, msg, strlen(msg));
+ }
+ else
+ {
+ }
+ }
+ }
+}
+
+bool BlankScreen::lock()
+{
+#define lock_test
+
+ if (locked)
+ return locked;
+
+ // We want to get MapNotify events
+ XSelectInput(dpy, win, StructureNotifyMask);
+
+ // "Map" the window (that is, make it appear on the screen)
+ XMapWindow(dpy, win);
+
+ // Create a "Graphics Context"
+ //GC gc = XCreateGC(dpy, win, 0, NULL);
+
+ XEvent xev;
+ Atom wm_state = XInternAtom(dpy, "_NET_WM_STATE", False);
+ Atom fullscreen = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
+ memset(&xev, 0, sizeof(xev));
+ xev.type = ClientMessage;
+ xev.xclient.window = win;
+ xev.xclient.message_type = wm_state;
+ xev.xclient.format = 32;
+ xev.xclient.data.l[0] = 1;
+ xev.xclient.data.l[1] = fullscreen;
+ xev.xclient.data.l[2] = 0;
+
+ XSendEvent(dpy, DefaultRootWindow(dpy), False,
+ SubstructureNotifyMask, &xev);
+
+
+
+
+ // Wait for the MapNotify event
+ for (;;)
+ {
+ XEvent e;
+ XNextEvent(dpy, &e);
+ if (e.type == MapNotify)
+ break;
+ }
+ //Flush it!
+ //XFlush(dpy);
+
+#ifndef lock_test
+ // load the locked cursor, so people dont think they can click anything
+ // TODO: Use some kind of invisible cursor instead of the wait-cursor
+ Cursor locked_cur = XCreateFontCursor(dpy, XC_watch);
+ XDefineCursor(dpy, DefaultRootWindow(dpy),locked_cur);
+#endif
+
+ // grabbing of keyboard and mouse and hide the cursor
+ XGrabKeyboard(dpy, DefaultRootWindow(dpy), false, GrabModeAsync, GrabModeAsync, CurrentTime);
+ XGrabPointer(dpy, DefaultRootWindow(dpy), false, 0, GrabModeAsync, GrabModeAsync, None, NULL, CurrentTime);
+
+ if (!locked)
+ ConsoleLog writeLine(QString("Locked"));
+
+ // see header for more information on this switch
+ return locked = true;
+}
+
+bool BlankScreen::lock_inputs()
+{
+ // grabbing of keyboard and mouse and hide the cursor
+ XGrabKeyboard(dpy, DefaultRootWindow(dpy), false, GrabModeAsync, GrabModeAsync, CurrentTime);
+ XGrabPointer(dpy, DefaultRootWindow(dpy), false, 0, GrabModeAsync, GrabModeAsync, None, NULL, CurrentTime);
+ return true;
+}
+
+bool BlankScreen::unlock()
+{
+
+ if (dpy)
+ {
+
+ int retval = -1;
+
+ //reset cursor to arrow (no *real* default here...)
+ Cursor normal_cur = XCreateFontCursor(dpy, XC_arrow);
+ XDefineCursor(dpy, DefaultRootWindow(dpy), normal_cur);
+
+ // ungrabbing of keyboard and mouse
+ XUngrabPointer(dpy, CurrentTime);
+ XUngrabKeyboard(dpy, CurrentTime);
+
+
+ retval = XUnmapWindow(dpy,win);
+ if (retval == BadWindow)
+ ConsoleLog writeError(QString("Bad window while unmapping. Badwindow: ").append(int2String(retval)));
+ XFlush(dpy);
+ }
+ if (locked)
+ ConsoleLog writeLine(QString("Unlocked"));
+
+ lockMsg.clear();
+ return !(locked = false);
+}
diff --git a/src/util/clientGUIUtils.h b/src/util/clientGUIUtils.h
new file mode 100644
index 0000000..28b05cc
--- /dev/null
+++ b/src/util/clientGUIUtils.h
@@ -0,0 +1,39 @@
+#include "src/util/consoleLogger.h"
+#include <X11/Xlib.h> // Every Xlib program must include this
+#include <X11/cursorfont.h>
+#include <assert.h>
+#include <unistd.h>
+#include <stdio.h>
+
+
+
+#define REFRESH_RATE 0.15
+
+#ifndef _BLANKSCREEN_H_
+#define _BLANKSCREEN_H_
+
+class BlankScreen
+{
+public:
+ BlankScreen();
+ void draw(bool force = false);
+ bool lock();
+ bool unlock();
+ void setLogMsg(QString msg);
+ bool lock_inputs();
+
+private:
+ Display *dpy;
+ Window win;
+ XEvent ev;
+ int scr;
+
+ bool locked;
+
+
+ QString lockMsg;
+ int blackColor, whiteColor;
+ int offX, offY;
+};
+
+#endif
diff --git a/src/util/consoleLogger.cpp b/src/util/consoleLogger.cpp
new file mode 100644
index 0000000..b523b40
--- /dev/null
+++ b/src/util/consoleLogger.cpp
@@ -0,0 +1,355 @@
+/*
+ # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of
+ # Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # -----------------------------------------------------------------------------
+ # consoleLogger.cpp
+ # - ???.
+ # -----------------------------------------------------------------------------
+ */
+
+#include "consoleLogger.h"
+
+#ifdef never
+template<class T>
+void ConsoleLogger::addListener(T* who, void (T :: *func)(QString))
+{
+ LogNotify<T> *test = new LogNotify<T>(who, func);
+ _CBLog.push_back(dynamic_cast<LogNotifyEntry*>(test));
+}
+
+template<class T>
+void ConsoleLogger::removeListener(T* who, void (T :: *func)(QString))
+{
+ if (_CBLog.size())
+ {
+ for (std::list<LogNotifyEntry*>::iterator it = _CBLog.begin(); it != _CBLog.end(); it++)
+ {
+ LogNotify<T> *probe = dynamic_cast<LogNotify<T>*>((*it));
+ if (probe)
+ {
+ if (probe->getCallee() == who && probe->getCB() == func)
+ {
+ _CBLog.remove((*it));
+ }
+ }
+ }
+ }
+// LogNotify<T> *test = new LogNotify<T>(who, func);
+ // _CBLog.push_back(dynamic_cast<LogNotifyEntry*>(test));
+}
+
+#endif
+int ConsoleLogger::writeLine(QString message, LOG_LEVEL level)
+{
+ if (message.size() == 0)
+ return -1;
+
+ ConsoleEntry consoleEntry(_getTimeStamp(), message, level);
+ _announceWrite(consoleEntry); // tell the listeners!
+ _writeLine2File(consoleEntry.getLine());
+ _log.push_back(consoleEntry);
+
+ return _log.size();
+}
+
+int ConsoleLogger::writeline(const char* message, LOG_LEVEL level)
+{
+ if (message)
+ {
+ if (strlen(message) > 0)
+ return writeLine(QString(message), level);
+ }
+ return -1;
+}
+
+int ConsoleLogger::writeError(QString error)
+{
+ return writeLine(error, LOG_ERROR);
+}
+
+int ConsoleLogger::writeError(const char* error)
+{
+ return writeLine(error, LOG_ERROR);
+}
+
+int ConsoleLogger::writeTerminal(QString terminal)
+{
+ // printing the line on the console happens further down the line!
+ return writeLine(terminal, LOG_TERMINAL);
+}
+
+int ConsoleLogger::writeTerminal(const char* terminal)
+{
+ if (terminal)
+ if (strlen(terminal) > 0)
+ return writeTerminal(QString(terminal));
+
+ terminal = NULL;
+ return -1;
+}
+
+int ConsoleLogger::writeNetwork(QString network)
+{
+ // printing the line on the console happens further down the line!
+ return writeLine(network, LOG_NETWORK);
+}
+
+int ConsoleLogger::writeNetwork(const char* network)
+{
+ if (network)
+ if (strlen(network) > 0)
+ return writeNetwork(QString(network));
+
+ network = NULL;
+ return -1;
+}
+
+int ConsoleLogger::writeChat(QString chat)
+{
+ return writeLine(chat, LOG_CHAT);
+}
+
+int ConsoleLogger::writeChat(const char* chat)
+{
+ if (chat)
+ if (strlen(chat) > 0)
+ return writeChat(QString(chat));
+
+ chat = NULL;
+ return -1;
+}
+
+void ConsoleLogger::getLine(int lineNum, char* line)
+{
+ QString tmp;
+ getLine(lineNum, &tmp);
+ if (tmp.size() > 0)
+ {
+ line = new char[_log[lineNum].getLine().size()+1];
+ if (line)
+ {
+ memcpy(line, _log[lineNum].getLine().toUtf8().data(), _log[lineNum].getLine().size());
+ if (strlen(line) > 0)
+ return;
+ }
+ }
+ line = NULL;
+
+}
+
+void ConsoleLogger::getLine(int lineNum, QString* line)
+{
+ if (lineNum <= int(_log.size()))
+ {
+ if (lineNum > 0)
+ lineNum--;
+ else if (lineNum < 0)
+ {
+ line = NULL;
+ return;
+ }
+ }
+ else
+ {
+ line->clear();
+ line = NULL;
+ }
+}
+
+void ConsoleLogger::setLogPath(QString logPath)
+{
+ getLogger()->_logPath = logPath;
+ getLogger()->_prepareLog();
+}
+
+void ConsoleLogger::setLogName(QString logName)
+{
+ getLogger()->_logName = logName;
+ getLogger()->_prepareLog();
+}
+
+void ConsoleLogger::dumpLog(DUMP_MODE mode)
+{
+ if (mode == DUMP_FILE || (DUMP_FILE_CONCAT && !_fileRead))
+ getLogger()->_writeLog();
+ if (mode == DUMP_FILE_CONCAT && _fileRead)
+ getLogger()->_writeLog(true);
+ if (mode == DUMP_ALL_LISTENERS)
+ {
+ for (int i = 0; i <int(_log.size()); i++)
+ {
+ _announceWrite(_log[i]);
+ }
+ }
+}
+
+int ConsoleLogger::count = 0;
+
+ConsoleLogger* ConsoleLogger::_logger;
+
+ConsoleLogger* ConsoleLogger::getLogger()
+{
+ if (!_logger)
+ {
+ return ConsoleLogger::_logger = new ConsoleLogger();
+ }
+ else
+ return ConsoleLogger::_logger;
+}
+
+ConsoleLogger::ConsoleLogger()
+ : _logName(""),
+ _logPath(getPolicyFilePath(QString(""))),
+ _fileRead(false),
+ entryDispatcher()
+{
+// _prepareLog();
+}
+
+ConsoleLogger::~ConsoleLogger()
+{
+ // doesnt work!?
+ _writeLog();
+}
+
+void ConsoleLogger::_prepareLog()
+{
+ _logFile.close();
+ _logFileGood = false;
+ _readLog();
+
+ mkdir(getPolicyFilePath(QString()).toUtf8().data(), 0777);
+ QString fullpath;
+ fullpath.append(_logPath);
+ //TODO: handle wether path/ or path were entered?
+ fullpath.append(_logName);
+ _logFile.open(fullpath.toUtf8().data(), std::ofstream::out | std::ofstream::app);
+ if (_logFile.good())
+ {
+ _logFileGood = true;
+ writeTerminal(QString("LogPath/Name changed to: ").append(fullpath));
+ }
+ else
+ {
+ printf("ERROR: Logfile ( %s ) not accessible/found. Logs will not be available.\n", _logPath.toUtf8().data());
+ }
+ _logFile.close();
+}
+
+void ConsoleLogger::_writeLine2File(QString line)
+{
+ if (_logFileGood)
+ {
+ QString fullpath;
+ fullpath.append(_logPath);
+ //TODO: handle wether path/ or path were entered?
+ fullpath.append(_logName);
+ _logFile.open(fullpath.toUtf8().data(), std::ofstream::out | std::ofstream::app);
+
+ if (_logFile.good()) // one can never be too sure
+ {
+ _logFile.write(line.toUtf8().data(), line.size());
+ }
+
+ _logFile.close();
+ }
+
+}
+
+// overwrites the file and dumps the complete log archive of this session
+void ConsoleLogger::_writeLog(bool concat)
+{
+ if (_logFileGood)
+ {
+ QString fullpath;
+ fullpath.append(_logPath);
+ //TODO: handle wether path/ or path were entered?
+ fullpath.append(_logName);
+
+ std::vector<ConsoleEntry> *tmpLog = NULL;
+
+ if (concat)
+ {
+ std::vector<ConsoleEntry> newLog = _prev_log;
+ newLog.insert(newLog.end(), _log.begin(), _log.end());
+ tmpLog = &newLog;
+ }
+ else
+ {
+ tmpLog = &_log;
+ }
+ _logFile.open(fullpath.toUtf8().data(), std::ofstream::out | std::ofstream::trunc);
+
+ if (_logFile.good()) // one can never be too sure
+ {
+ for (int i = 0; i < int(tmpLog->size()); i++)
+ {
+ _logFile.write(tmpLog->at(i).getLine().toUtf8().data(), tmpLog->at(i).getLine().size());
+ }
+ }
+
+ _logFile.close();
+ }
+}
+
+void ConsoleLogger::_announceWrite(ConsoleEntry consoleEntry)
+{
+
+ entryDispatcher.fire(consoleEntry);
+}
+
+void ConsoleLogger::_readLog(QString path)
+{
+ // todo, read the file, filter the entries and recombine them if possible etc..
+ // then save it all to _log_prev.
+ // then set _readFile to true, so the dump will concat our current log to the old and THEN overwrite the whole file
+ _prev_log.clear();
+ _fileRead = false;
+}
+
+QString ConsoleLogger::_getTimeStamp()
+{
+ time_t rawtime;
+ tm * ptm;
+ time ( &rawtime );
+
+ //ptm = gmtime ( &rawtime );
+ ptm = localtime ( &rawtime );
+
+ QString tmpStr;
+ if (ptm->tm_mday < 10)
+ tmpStr.append(QString("0"));
+ tmpStr.append(int2String(ptm->tm_mday));
+ tmpStr.push_back('.');
+ if (ptm->tm_mon < 10)
+ tmpStr.append(QString("0"));
+ tmpStr.append(int2String(int(ptm->tm_mon) +1));
+ tmpStr.push_back('.');
+ int year = (ptm->tm_year % 100);
+ if (year < 10)
+ tmpStr.append(QString("0"));
+ tmpStr.append(int2String(year));
+ tmpStr.push_back(' ');
+ if (ptm->tm_hour < 10)
+ tmpStr.append(QString("0"));
+ tmpStr.append(int2String(ptm->tm_hour));
+ tmpStr.push_back(':');
+ if (ptm->tm_min < 10)
+ tmpStr.append(QString("0"));
+ tmpStr.append(int2String(ptm->tm_min));
+ tmpStr.push_back(':');
+ if (ptm->tm_sec < 10)
+ tmpStr.append(QString("0"));
+ tmpStr.append(int2String(ptm->tm_sec));
+
+ return tmpStr;
+}
+
diff --git a/src/util/consoleLogger.h b/src/util/consoleLogger.h
new file mode 100644
index 0000000..3a0950d
--- /dev/null
+++ b/src/util/consoleLogger.h
@@ -0,0 +1,273 @@
+
+#include "util.h"
+#include "dispatcher.h"
+#include <vector>
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <list>
+
+
+//#define as_daemon
+#ifndef _CONSOLELOGGER_H_
+#define _CONSOLELOGGER_H_
+
+/**********************************************************************************************************************/
+// Console-, and Message Dispatching / Logging (With timestamping!)
+/**********************************************************************************************************************/
+//
+// :: Usage ::
+//
+#define ConsoleLog ConsoleLogger::getLogger()-> //ease of acces!
+//
+//
+// *Logging:
+//
+// ConsoleLog writeLine(<string/char*>); // sends out a message with "normal" loglevel
+// ConsoleLog writeLine(<string/char*>, <loglevel>); // sends out a message with the chosen loglevel --> enum LOG_LEVEL
+// ConsoleLog writeError(<string/char*>); // sends out a message with "Error" loglevel
+// ConsoleLog writeTerminal(<string/char*>); // sends out a message with "Terminal" loglevel, which means it is
+// // also printed on stdout
+// ConsoleLog writeNetwork(<string/char*>); // sends out a message with "network" loglevel
+// ConsoleLog writeChat(<string/char*>); // sends out a message with "Chat" loglevel
+//
+// *un/subscribing to the LogDispatcher
+//
+// ConsoleLog addListener(<pointer-to-object-of-Type-myClass>, &myClass::myMethod);
+// callback signature --> typedef void (T::*callback)(ConsoleEntry); // with <U, T> as template // for more on ConsoleEntry, see later
+// ConsoleLog removeListener(<pointer-to-object-of-Type-myClass>, &myClass::myMethod);
+//
+// *Misc
+//
+// ConsoleLog setLogPath(<string-path-to-log-directory>); // set the log directory (with a final /, the logfilename is appended.)
+// ConsoleLog setLogName(<string-name>); // like the above, but for the filename.
+// ConsoleLog dumpLog(DUMP_MODE);
+//
+// DUMP_FILE ::>> Dumps the whole log since the logger was started into the specified logfile. the file content gets overwritten
+// DUMP_FILE_CONCAT ::>> The Same as above, but it will just append itself to the previously (if implemented) log which got \**
+// ***\ read from the logfile which was present at logger start. if no log is found or logfile was not read, behaves as DUMP_FILE
+// DUMP_TERMINAL ::>> Dumps the whole log into the terminal
+// DUMP_ALL_LISTENERS ::>> Dumps the whole log to all listeners
+//
+// Alternatively, you can request a dump to a certain listener:
+// ConsoleLog dump2Listener(<pointer-to-object-of-Type-myClass>, &myClass::myMethod); // it expects the same information as when subscribing
+// // the PVS-Server console makes heavy use of this feature to implement its filters
+//
+//
+// :: using the ConsoleEntry class ::
+//
+// *methods and members
+//
+//
+// LOG_LEVEL getLevel() // returns the loglevel as LOG_LEVEL Enum-type
+// QString getLine() // returns the complete line as shown in the logfile, with timestamp, loglevel prefix etc
+// QString getMessage() // returns the message body, no gimmicks attached
+// QString getPrefix() // returns the loglevel as string-represenation
+// QString getTimeStamp() // returns the timestamp which was set at the creation of the object
+//
+//
+//
+//
+//
+//
+/**********************************************************************************************************************/
+
+
+
+
+
+
+// Typdef at bottom of file :
+// typedef ConsoleLogger::ConsoleEntry LogEntry;
+
+
+class ConsoleLogger
+{
+public:
+
+ enum LOG_LEVEL { LOG_NORMAL,
+ LOG_ERROR,
+ LOG_CHAT,
+ LOG_TERMINAL,
+ LOG_NETWORK
+ };
+ enum DUMP_MODE { DUMP_FILE,
+ DUMP_FILE_CONCAT,
+ DUMP_TERMINAL,
+ DUMP_ALL_LISTENERS,
+ };
+ class ConsoleEntry
+ {
+ public:
+ ConsoleEntry(QString timeStamp, QString message, LOG_LEVEL level)
+ {
+ setLine(timeStamp, message, level);
+ };
+ void setLine(QString timeStamp, QString message, LOG_LEVEL level)
+ {
+ _message = message;
+ _prefix = _prefixLine(level);
+ _timeStamp = timeStamp;
+ _line.append(QString("[ ").append(timeStamp));
+ _line.append(QString(" ] ").append(_prefix));
+ _line.append(QString(": ").append(message));
+ _level = level;
+ if ('\n' != _line[_line.size()-1] && '\n' != _line[_line.size()])
+ _line.push_back('\n'); // add an explicit newline char, so it looks better in the logfile
+ //#ifndef as_daemon
+ if (_level == LOG_TERMINAL) // may look strange here, but its quite central :-)
+ printf("%s\n", _line.toUtf8().data());
+ //#endif
+ };
+ LOG_LEVEL getLevel()
+ {
+ return _level;
+ };
+ QString getLine()
+ {
+ return _line;
+ };
+ QString getMessage()
+ {
+ return _message;
+ };
+ QString getPrefix()
+ {
+ return _prefix;
+ };
+ QString getTimeStamp()
+ {
+ return _timeStamp;
+ };
+
+ private:
+ QString _prefixLine(LOG_LEVEL level)
+ {
+ // switch anyone?
+ if (level == LOG_NORMAL)
+ return QString("PVS");
+ if (level == LOG_ERROR)
+ return QString("PVS ERROR");
+ if (level == LOG_TERMINAL)
+ return QString("PVS Terminal");
+ if (level == LOG_CHAT)
+ return QString("PVS Chat");
+ if (level == LOG_NETWORK)
+ return QString("PVS Network");
+ return QString("UNDEFINED");
+ };
+ QString _line; // the complete line with timestamp and everything
+ QString _message; // the message itself
+ QString _prefix; // just the prefix
+ QString _timeStamp; // just the timestamp
+ LOG_LEVEL _level;
+ };
+
+ class LogNotifyEntry
+ {
+ public:
+ virtual void fire(ConsoleEntry consoleEntry) {};
+ LogNotifyEntry() {};
+ };
+
+#ifdef never
+private:
+ template<class T>
+ class LogNotify : public LogNotifyEntry
+ {
+ public:
+ typedef void (T::*callback)(ConsoleEntry);
+ LogNotify(T* who, callback func )//void (T :: *func)(QString))
+ {
+ callee = who;
+ //callback = func;
+ myCB = func;
+ };
+ virtual void fire(ConsoleEntry consoleEntry)
+ {
+ if (callee)
+ (callee->*myCB)(consoleEntry);
+ };
+ T* getCallee()
+ {
+ return callee;
+ };
+ callback getCB()
+ {
+ return myCB;
+ };
+
+ private:
+ T *callee;
+ callback myCB;
+ };
+
+public:
+#endif
+ // interfaces for the dispatcher for easy of access ( --> ConsoleLog Makro)
+ template<class T> void addListener(T* who, void (T :: *func)(ConsoleEntry))
+ {
+ entryDispatcher.addListener(who, func);
+ };
+ template<class T> void removeListener(T* who, void (T :: *func)(ConsoleEntry))
+ {
+ entryDispatcher.removeListener(who, func);
+ };
+ template<class T> void dump2Listener(T* who, void (T :: *func)(ConsoleEntry))
+ {
+ for (int i = 0; i < int(_log.size()) ; i++)
+ (who->*func)(_log[i]);
+ };
+
+ int writeLine(QString message, LOG_LEVEL = LOG_NORMAL);
+ int writeline(const char* message, LOG_LEVEL = LOG_NORMAL);
+ int writeError(QString error);
+ int writeError(const char* error);
+ int writeTerminal(QString terminal);
+ int writeTerminal(const char* terminal);
+ int writeNetwork(QString network);
+ int writeNetwork(const char* network);
+ int writeChat(QString chat);
+ int writeChat(const char* chat);
+ void getLine(int lineNum, char* line);
+ void getLine(int lineNum, QString* line);
+ void setLogPath(QString logPath);
+ void setLogName(QString logName);
+ void dumpLog(DUMP_MODE mode = DUMP_FILE);
+ static ConsoleLogger* getLogger();
+ static int count;
+private:
+
+
+ std::vector<ConsoleEntry>* _getLog()
+ {
+ return &_log;
+ };
+ static ConsoleLogger* _logger;
+ void _prepareLog();
+ void _writeLine2File(QString line);
+ void _writeLog(bool concat = false);
+ void _announceWrite(ConsoleEntry consoleEntry);
+ void _readLog(QString path = QString(""));
+ QString _getTimeStamp();
+ void _prefixLine(QString* line, LOG_LEVEL level = LOG_NORMAL);
+
+
+
+ ConsoleLogger();
+ ~ConsoleLogger();
+
+ QString _logName;
+ QString _logPath;
+
+ bool _logFileGood, _fileRead;
+// std::list<LogNotifyEntry*> _CBLog;
+ EventDispatcher<ConsoleEntry> entryDispatcher;
+ std::vector<ConsoleEntry> _log;
+ std::vector<ConsoleEntry> _prev_log;
+ std::ofstream _logFile;
+};
+
+typedef ConsoleLogger::ConsoleEntry LogEntry;
+
+#endif
diff --git a/src/util/dispatcher.h b/src/util/dispatcher.h
new file mode 100644
index 0000000..490a3be
--- /dev/null
+++ b/src/util/dispatcher.h
@@ -0,0 +1,210 @@
+#ifndef _DISPATCHER_H_
+#define _DISPATCHER_H_
+#include <list>
+#include <QString>
+#include <iostream>
+#include <map>
+
+
+//****************************************************************************************************/
+// EventDispatcher && EventIdentDispatcher //
+/***************************************************************************************************/
+// This handy class(es) act as very simple signals/events.
+// Its OOP-only, so dont even try to add static functions
+// or C-like methods!
+//
+// :: Return Types ::
+//
+// at the moment only callbacks for void methods with a parameter
+// count of one ( whos type is the primary template parameter)
+//
+// :: callback signature ::
+//
+// typedef void (T::*callback)(U); // with <U, T> as template
+//
+// :: Usage Example ::
+//
+// *creating a Dispatcher
+//
+// -- EventDispatcher<Type A>* nameYourDispatcher = new EventDispatcher<Type A>; // simple Dispatcher
+// -- EventIdentDispatcher<Type A>* nameYourIdentDispatcher = new EventIdentDispatcher<Type A>; // ident dispatcher
+//
+// *difference between simple and ident
+//
+// a simple dispatcher features only one type of signal, so you can only call all
+// attached listeners at once or none at all
+//
+// an ident dispatcher uses an ident string to hold and fire more than one event type at once
+// but is limited to the one defined parameter type for its methods
+//
+// *subscribung to a dispatcher
+//
+// -- nameYourDispatcher->addListener(<pointer-to-object-of-Type-myClass>, &myClass::myMethod); // simple Dispatcher
+// -- nameYourIdentDispatcher->addListener(<string-as-ident>, <pointer-to-object-of-Type-myClass>, &myClass::myMethod); // ident dispatcher//
+//
+// you can add the same method/instance to different dispatchers oder differnt ident-distinguished dispatchers in a identdispatcher.
+// you can also add the same method/instance to the same dispatchers all over again, which is not recommended
+//
+//
+// *firing a dispatcher
+//
+// -- nameYourDispatcher->fire(Type_A Object); // simple Dispatcher
+// -- nameYourIdentDispatcher->fire(<string-as-ident>, Type_A Object); // ident dispatcher//
+//
+// All respective attached callbacks are called in the order they were added
+//
+//
+// *unsubscribing
+//
+// -- nameYourDispatcher->removeListener(<pointer-to-object-of-Type-myClass>, &myClass::myMethod); // simple Dispatcher
+// -- nameYourIdentDispatcher->removeListener(<string-as-ident>, <pointer-to-object-of-Type-myClass>, &myClass::myMethod); // ident dispatcher//
+//
+// just the reverse of addListener. currently no removeAll() available
+//
+//
+//
+/***************************************************************************************************/
+class CallbackHandle
+{
+};
+
+template<class U>
+class CallbackBase : public CallbackHandle
+{
+public:
+ virtual void fire(U u) {};
+
+private:
+};
+
+template<class T, class U>
+class Callback : public CallbackBase<U>
+{
+public:
+
+ virtual void fire(U u)
+ {
+ if (cbVU)
+ (callee->*cbVU)(u);
+ };
+
+ typedef void (T::*callbackVU)(U);
+
+ Callback(T* who, callbackVU cb)
+ {
+ cbVU = cb;
+ callee = who;
+ };
+
+ T* getCallee()
+ {
+ return callee;
+ };
+ callbackVU getCBVU()
+ {
+ return cbVU;
+ };
+
+private:
+ callbackVU cbVU;
+ T* callee;
+
+};
+
+template<class U>
+class EventDispatcher
+{
+public:
+ template<class T> void addListener(T *who, void (T :: *func)(U))
+ {
+ Callback<T, U> *tmp = new Callback<T, U>(who, func);
+ _listener.push_back(dynamic_cast<CallbackBase<U>*>(tmp));
+ };
+ void fire(U u)
+ {
+ for (typename std::list<CallbackBase<U>*>::iterator it = _listener.begin(); it != _listener.end(); it++)
+ {
+ if (*it)
+ {
+ (*it)->fire(u);
+ }
+ }
+ };
+
+ template<class T> void removeListener(T* who, void (T :: *func)(U))
+ {
+ if (_listener.size())
+ {
+ for (typename std::list<CallbackBase<U>*>::iterator it = _listener.begin(); it != _listener.end(); it++)
+ {
+ CallbackBase<U>* pro = (*it);
+ Callback<T, U> *probe = dynamic_cast<Callback<T,U>*>(pro);
+ if (probe)
+ {
+ if (probe->getCallee() == who && probe->getCBVU() == func )
+ {
+ delete (probe);
+ _listener.remove((*it));
+ return;
+ }
+ }
+ }
+ }
+ };
+
+private:
+
+ std::list<CallbackBase<U>*> _listener;
+};
+
+template<class U>
+class EventIdentDispatcher
+{
+public:
+ template<class T> void addListener(QString ident, T* who, void (T :: *func)(U))
+ {
+ Callback<T, U>* tmp = new Callback<T, U>(who, func);
+ _listener.push_back(std::pair<QString, CallbackBase<U>*>(ident, dynamic_cast<CallbackBase<U>*>(tmp)));
+ };
+
+ void fire(QString ident, U u)
+ {
+ for ( typename std::list<std::pair<QString, CallbackBase<U>* > >::iterator it = _listener.begin(); it != _listener.end(); it++)
+ {
+ if ((*it).first.compare(ident) == 0 || QString("*").compare((*it).first) == 0)
+ {
+ if ((*it).second)
+ {
+ (*it).second->fire(u);
+ }
+ }
+ }
+ };
+ template<class T> void removeListener(QString ident, T* who, void (T :: *func)(U))
+ {
+ if (_listener.size())
+ {
+ for (std::list<std::pair <QString, CallbackHandle*> >::iterator it = _listener.begin(); it != _listener.end(); it++)
+ {
+ if ((*it).first.compare(ident) == 0)
+ {
+ CallbackBase<U>* pro = (*it).second;
+ Callback<T, U> *probe = dynamic_cast<Callback<T,U>*>(pro);
+ if (probe)
+ {
+ if (probe->getCallee() == who && probe->getVoidCB == func)
+ {
+ delete (*it).second;
+ _listener.remove((*it));
+ return;
+ }
+ }
+ }
+ }
+ }
+ };
+private:
+ std::list<std::pair<QString, CallbackBase<U>* > > _listener;
+};
+
+#endif
diff --git a/src/util/pvsSettingsManager.cpp b/src/util/pvsSettingsManager.cpp
new file mode 100644
index 0000000..a6a742b
--- /dev/null
+++ b/src/util/pvsSettingsManager.cpp
@@ -0,0 +1,185 @@
+#include "pvsSettingsManager.h"
+#include "TextFile.h"
+
+PVSSettingsManager* PVSSettingsManager::getManager()
+{
+ if (myself)
+ return myself;
+ else
+ return myself = new PVSSettingsManager;
+}
+
+void PVSSettingsManager::setConfigFile(QString path)
+{
+ if (path.size() && fileExists(path))
+ {
+ _path = path;
+ _parseFile(_path);
+
+ }
+ else
+ ConsoleLog writeError(QString("Can't open config file \"").append(QString(path).append("\"")));
+}
+
+bool PVSSettingsManager::hasEntry(QString name)
+{
+ for (SettingsIter it = settingsList.begin(); it != settingsList.end(); it++)
+ {
+ if ((*it).first.compare(name) == 0)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+QString PVSSettingsManager::getEntryString(QString name)
+{
+ for (SettingsIter it = settingsList.begin(); it != settingsList.end(); it++)
+ {
+ if ((*it).first.compare(name) == 0)
+ {
+ return (*it).second;
+ }
+ }
+ return QString();
+}
+
+void PVSSettingsManager::writeEntry(QString name, QString value)
+{
+ if (name.size() && value.size())
+ return;
+ bool unique = true;
+ for (SettingsIter it = settingsList.begin(); it != settingsList.end(); it++)
+ {
+ if ((*it).first.compare(name) == 0)
+ {
+ unique = false;
+ (*it).second = value;
+ break;
+ }
+ }
+ if (unique)
+ {
+ SettingsEntry tmp(name, value);
+ settingsList.push_back(tmp);
+ }
+}
+
+
+PVSSettingsManager* PVSSettingsManager::myself = NULL;
+
+PVSSettingsManager::PVSSettingsManager()
+{
+
+}
+
+void PVSSettingsManager::setConfigs()
+{
+ //default settings
+ _configs.setValue("Chat/chatstate", "on");
+ _configs.setValue("Chat/chatmode", "bossmode");
+ _configs.setValue("Room/roomId", "0");
+ _configs.setValue("VNC/permit", "off");
+ _configs.setValue("VNC/quality", "high");
+ _configs.sync();
+}
+void PVSSettingsManager::reWriteConfigs(QString set, QString val)
+{
+ _configs.setValue(set, val);
+ _configs.sync();
+}
+
+void PVSSettingsManager::readConfigs(QString sett, QString vall)
+{
+ //TODO: read the config file..
+ _configs.value("Chat/chatstate").toBool();
+ _configs.value("Chat/chatmode").toString();
+ _configs.value("Room/room").toInt();
+ _configs.value("VNC/permit").toBool();
+ _configs.value("VNC/quality").toString();
+}
+
+void PVSSettingsManager::_parseFile(QString path)
+{
+ QString line;
+ TextFile file(path);
+
+ SettingsList tmpList;
+
+ if (file.good())
+ {
+ while (!file.eof())
+ {
+ line = file.readLine();
+ if (!(line.length() <=1)) // ignore blank
+ {
+ if (!(line[0] == '#' || line[0] == '/' || line[0] == '[')) // ignore comments and section headers
+ {
+ SettingsEntry tmp = _parseLine(line);
+ if (tmp.first.size() && tmp.second.size())
+ {
+ bool unique = true;
+ for (SettingsIter it = tmpList.begin(); it != tmpList.end(); it++)
+ {
+ if ((*it).first.compare(tmp.first) == 0)
+ {
+ unique = false;
+ break;
+ }
+ }
+ if (unique)
+ tmpList.push_back(tmp);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ ConsoleLog writeError(QString("No configfile \"").append(QString(path).append("\" found or file corrupt.")));
+ }
+
+ if (tmpList.size())
+ settingsList = tmpList;
+}
+#ifdef verbose
+ConsoleLog writeLine(QString("Dumping Config Content of ").append(QString(path).append(" : ")));
+for (SettingsIter it = settingsList.begin(); it != settingsList.end(); it++)
+{
+ ConsoleLog writeLine(QString("Option: ").append(QString((*it).first).append(QString(" | Value: ").append((*it).second))));
+}
+ConsoleLog writeLine(QString("End of ").append(QString(path).append(".")));
+#endif
+
+SettingsEntry PVSSettingsManager::_parseLine(QString line)
+{
+ QString name;
+ QString value;
+
+ name = lineSplitter(line, "=\n\t", true);
+ value = lineSplitter(line, "=\n\t", false);
+
+ if (!(name.size() && value.size()))
+ return SettingsEntry("","");
+
+
+ // remove whitespaces in front of option name
+ for (int i = 0; i < name.size(); i++)
+ {
+ if (name[i] == '\t' || name[i] == ' ')
+ {
+ name.remove(i, 1);
+ i--;
+ }
+ else
+ break;
+ }
+ // whitespaces after the value are trimmed by the lineSplitter
+
+ SettingsEntry tmp(name, value);
+ return tmp;
+}
+
+
+
diff --git a/src/util/pvsSettingsManager.h b/src/util/pvsSettingsManager.h
new file mode 100644
index 0000000..78607eb
--- /dev/null
+++ b/src/util/pvsSettingsManager.h
@@ -0,0 +1,50 @@
+/// documentation test 1
+/// line 2
+/// line 3
+#ifndef _PVSSETTINGSMANGER_H_
+#define _PVSSETTINGSMANGER_H_
+
+#include <list>
+#include <map>
+#include <src/util/util.h>
+#include <src/util/consoleLogger.h>
+#include <QSettings>
+
+
+/// documentation test 1.1
+/// line 2.1
+/// line 3.1
+
+typedef std::pair<QString, QString> SettingsEntry; ///< first = option name, second = option value
+typedef std::list<SettingsEntry> SettingsList; ///< obvious
+typedef std::list<SettingsEntry>::iterator SettingsIter;
+
+
+class PVSSettingsManager;
+/// documentation test 1.2
+/// line 2.2
+/// line 3.2
+class PVSSettingsManager
+{
+public:
+ static PVSSettingsManager* getManager();
+ void setConfigFile(QString path);
+ bool hasEntry(QString name);
+ QString getEntryString(QString name);
+ void writeEntry(QString name, QString value);
+ void setConfigs();
+ void reWriteConfigs(QString set, QString val);
+ void readConfigs(QString sett, QString vall);
+private:
+ static PVSSettingsManager* myself;
+ PVSSettingsManager();
+ void _parseFile(QString path);
+ SettingsEntry _parseLine(QString line);
+ QString _path;
+ SettingsList settingsList;
+ QSettings _configs;
+
+};
+
+
+#endif
diff --git a/src/util/serviceDiscoveryUtil.cpp b/src/util/serviceDiscoveryUtil.cpp
new file mode 100644
index 0000000..32aa0fc
--- /dev/null
+++ b/src/util/serviceDiscoveryUtil.cpp
@@ -0,0 +1,65 @@
+#include "serviceDiscoveryUtil.h"
+#include <cassert>
+
+void appendSdField(QByteArray* target, const char* id, QString data)
+{
+ assert(strlen(id) == 3);
+ target->append(id);
+ QByteArray tmp = data.toUtf8();
+ if (tmp.size() > 100) tmp.truncate(100);
+ target->append((char)tmp.size());
+ target->append(tmp);
+}
+
+SdFields parseSdFields(unsigned char* data, int len)
+{
+ SdFields fields;
+ for (;;)
+ {
+ //printf("%d bytes left: %s\n", len, (char*)data);
+ if (len < 4 || len < 4 + data[3]) break; // end of data
+ QString key = QString::fromUtf8((char*)data, 3);
+ QString val = QString::fromUtf8((char*)data+4, data[3]);
+ //printf("Key: %s, Val: %s\n", key.toUtf8().data(), val.toUtf8().data());
+ fields.insert(key, val);
+ len -= (4 + data[3]);
+ data += (4 + data[3]);
+ }
+ return fields;
+}
+
+QString sha1ToReadable(QByteArray input)
+{
+ unsigned char *ptr = (unsigned char *)input.data();
+ QString retval;
+ for (int i = (input.length() < 10 ? input.length() : 10); i; --i)
+ {
+ switch(*ptr++ % 0xD)
+ {
+ case 0x0: retval.append('S'); break;
+ case 0x1: retval.append('F'); break;
+ case 0x2: retval.append('M'); break;
+ case 0x3: retval.append('K'); break;
+ case 0x4: retval.append('H'); break;
+ case 0x5: retval.append('T'); break;
+ case 0x6: retval.append('P'); break;
+ case 0x7: retval.append('D'); break;
+ case 0x8: retval.append('Y'); break;
+ case 0x9: retval.append('W'); break;
+ case 0xA: retval.append('G'); break;
+ case 0xB: retval.append('L'); break;
+ case 0xC: retval.append('B'); break;
+ }
+ if (--i == 0) break;
+ switch((*ptr >> 2) % 5)
+ {
+ case 0: retval.append('a'); break;
+ case 1: retval.append('i'); break;
+ case 2: retval.append('u'); break;
+ case 3: retval.append('e'); break;
+ case 4: retval.append('o'); break;
+ }
+ if ((*ptr++ & 3) == 0) retval.append('n');
+ }
+ return retval;
+}
diff --git a/src/util/serviceDiscoveryUtil.h b/src/util/serviceDiscoveryUtil.h
new file mode 100644
index 0000000..537daeb
--- /dev/null
+++ b/src/util/serviceDiscoveryUtil.h
@@ -0,0 +1,19 @@
+#ifndef SERVICEDISCOVERYUTIL_H_
+#define SERVICEDISCOVERYUTIL_H_
+
+#include <QtCore/QString>
+#include <QtCore/QHash>
+
+typedef QHash<QString, QString> SdFields;
+
+// These two functions build/parse the message format used in SD broadcasts
+// It is some kind of key-value pairs, encoded as follows:
+// <3 chars/bytes, key><1 byte, value length in bytes><up to 100 chars/bytes, value>
+void appendSdField(QByteArray* target, const char* id, QString data);
+SdFields parseSdFields(unsigned char* data, int len);
+
+// This algorithm is supposed to generate a readable and maybe pronouncable
+// string from the fingerprint of the servers certificate
+QString sha1ToReadable(QByteArray input);
+
+#endif /* SERVICEDISCOVERYUTIL_H_ */
diff --git a/src/util/timeUtil.cpp b/src/util/timeUtil.cpp
new file mode 100644
index 0000000..6f8e93d
--- /dev/null
+++ b/src/util/timeUtil.cpp
@@ -0,0 +1,42 @@
+/*
+ # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of
+ # Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # -----------------------------------------------------------------------------
+ # timeUtil.cpp
+ # - ???.
+ # -----------------------------------------------------------------------------
+ */
+
+#include "timeUtil.h"
+
+TimeUtil::TimeUtil()
+{
+ seconds = useconds = mtime = 0;
+}
+
+void TimeUtil::start()
+{
+ gettimeofday(&Begin, NULL);
+}
+
+void TimeUtil::stop()
+{
+ gettimeofday(&End, NULL);
+ seconds = End.tv_sec - Begin.tv_sec;
+ useconds = End.tv_usec - Begin.tv_usec;
+ mtime = ((seconds) * 1000 + useconds/1000.0) + 0.5;
+}
+
+long TimeUtil::getMS()
+{
+ return mtime;
+}
+
diff --git a/src/util/timeUtil.h b/src/util/timeUtil.h
new file mode 100644
index 0000000..90d647d
--- /dev/null
+++ b/src/util/timeUtil.h
@@ -0,0 +1,34 @@
+#ifndef TIME_UTIL
+#define TIME_UTIL
+
+#include <sys/time.h>
+#include <stdio.h>
+#include <unistd.h>
+
+
+#ifdef PROFILE
+#define startTime(aaa) TimeUtil aaa ## Time = TimeUtil(); aaa ## Time.start();
+#define endTime(aaa) aaa ## Time.stop(); printf("Time to execute " #aaa " : %ld\n", aaa ## Time.getMS());
+#endif
+
+#ifndef PROFILE
+#define startTime(aaa)
+#define endTime(aaa)
+#endif
+
+
+
+class TimeUtil
+{
+
+public:
+ TimeUtil();
+ void start();
+ void stop();
+ long getMS();
+private:
+ long mtime, seconds, useconds;
+ struct timeval Begin, End; //initialize Begin and End for the timer
+};
+
+#endif
diff --git a/src/util/util.cpp b/src/util/util.cpp
new file mode 100644
index 0000000..c2d06a0
--- /dev/null
+++ b/src/util/util.cpp
@@ -0,0 +1,416 @@
+#include "util.h"
+#include <QtGui/QDesktopServices>
+#include "consoleLogger.h"
+#include "TextFile.h"
+#include <ctime>
+#include <cstdlib>
+#include <QStringList>
+#include <iostream>
+
+
+PVSServerEntry::PVSServerEntry(QString name)
+{
+ name_ = name;
+}
+void PVSServerEntry::addClient(QString client)
+{
+ clientList_.push_back(client);
+}
+bool PVSServerEntry::hasClient(QString client)
+{
+ for (std::list<QString>::iterator it = clientList_.begin(); it != clientList_.end(); it++)
+ {
+ if ((*it).compare(client) == 0)
+ return true;
+ }
+ return false;
+}
+QString PVSServerEntry::getName()
+{
+ return name_;
+}
+
+int PVSServerEntry::getSize()
+{
+ return clientList_.size();
+}
+
+
+//namespace util
+//{
+
+int getRandom(int min, int max)
+{
+ static bool init = true;
+ if (init)
+ {
+ init = false;
+ srand ( time(NULL) + getpid() );
+ }
+ if (min >= max) return rand();
+ return rand() % (max-min+1) + min;
+}
+
+std::list<PVSServerEntry> getPVSServerEntryList(QString fileName)
+{
+ QString line;
+ TextFile file(fileName);
+ std::list<PVSServerEntry> entryList;
+
+ if (file.good())
+ {
+// std::cout << "reading table file \"" << fileName <<"\"" << std::endl;
+ PVSServerEntry* tmpEntry = NULL;
+ while (!file.eof())
+ {
+ line = file.readLine();
+
+ if (!(line.length() <=1)) // ignore blank
+ if (!(line[0] == '#' || line[0] == '/')) // ignore comments
+ {
+ if (line.mid(0, 5).compare(QString("start")) == 0)
+ {
+ if (tmpEntry != NULL)
+ {
+ // unclean file... but no reason to break down
+ //PVSServerEntry tmpEntry2 = *tmpEntry;
+ entryList.push_back(*tmpEntry);
+ delete tmpEntry;
+ tmpEntry = NULL;
+ }
+ QString tmpName(colonSplitter(line, false));
+ if (tmpName.size()<1)
+ tmpName = QString("localhost");
+
+ tmpEntry = new PVSServerEntry(tmpName);
+ continue;
+ }
+ if (line.mid(0, 3).compare(QString("end")) == 0)
+ {
+ if (tmpEntry!=NULL)
+ {
+ entryList.push_back(*tmpEntry);
+ delete tmpEntry;
+ tmpEntry = NULL;
+ }
+ else
+ ;// ignore
+
+ continue;
+ }
+ if (tmpEntry != NULL)
+ {
+ tmpEntry->addClient(line);
+ }
+ }
+ }
+ if (tmpEntry != NULL)
+ {
+ delete tmpEntry;
+ tmpEntry = NULL;
+ }
+
+ return entryList;
+ }
+ else
+ {
+ std::cout << "ERROR: no file \"" << fileName.toStdString() <<"\" found or file corrupt" << std::endl;
+ }
+ return std::list<PVSServerEntry>();
+}
+QString getFilenameFromPath(QString line)
+{
+ int lastSlash = 0;
+ for (int i = 0; i < line.length(); i++)
+ {
+ if (line.at(i) == '/')
+ {
+ lastSlash = i;
+ }
+ }
+ QString result;
+ if (lastSlash != 0 && lastSlash != line.length() -1)
+ {
+ result = line.mid(lastSlash+1, line.length()-(lastSlash+1));
+ }
+ return result;
+}
+
+QString lineSplitter(QString line, const char* signs, bool first)
+{
+ char *pch;
+ char* cLine = new char[line.length()+1];
+ strcpy(cLine, line.toUtf8().data());
+ pch = strtok (cLine,signs);
+ if (first)
+ {
+ QString tmp(pch);
+ delete cLine;
+ return tmp;
+ }
+ else
+ {
+ QString tmp;
+ char* tmpp = strtok(NULL, ";,\t\n");
+ if (tmpp)
+ tmp = QString(tmpp);
+ delete cLine;
+ return tmp;
+ }
+}
+
+QString colonSplitter(QString line, bool first)
+{
+ char *pch;
+ char* cLine = new char[line.length()+1];
+ strcpy(cLine, line.toUtf8().data());
+ pch = strtok (cLine," :\t\n");
+ if (first)
+ {
+ QString tmp(pch);
+ delete[] cLine;
+ return tmp;
+ }
+ else
+ {
+ QString tmp;
+ char* tmpp = strtok(NULL, " ;,\t\n");
+ if (tmpp)
+ tmp = QString(tmpp);
+ delete[] cLine;
+ return tmp;
+ }
+}
+
+QString getUserName()
+{
+ struct passwd* passUser = getpwuid(getuid());
+ QString username;
+ if (passUser)
+ {
+ username = QString(passUser->pw_name);
+ }
+ if (username.isEmpty())
+ {
+ printf("USERNAME COULDNT BE RETRIEVED!\n");
+ username = QString("USERNAMEERROR");
+ }
+ return username;
+}
+
+// Get full username.
+QString getFullUsername()
+{
+ QString fullname = getUserName();
+ struct passwd *pd;
+
+ if (NULL == (pd = getpwuid(getuid())))
+ {ConsoleLog writeError("getpwuid() error.");}
+ else
+ {
+ QString tmp = pd->pw_gecos;
+ QStringList userData = tmp.split(",");
+ if(userData[0].length() > 0 )
+ {
+ fullname = userData[0];
+ }
+ }
+ return fullname;
+}
+
+bool fileExists(QString fileName)
+{
+ std::ifstream file(fileName.toLocal8Bit().data());
+ if (file.good())
+ {
+#ifdef verbose
+ printf("fileExists(): file good.\n");
+#endif
+ file.close();
+ return true;
+ }
+ return false;
+
+}
+
+QString getHomeDir()
+{
+ return QDesktopServices::storageLocation(QDesktopServices::HomeLocation);
+}
+
+QString getPolicyDir()
+{
+ QString policyDir = getHomeDir();
+ QString subPath("/.pvs/");
+ policyDir.append(subPath);
+ return policyDir;
+}
+
+QString getPolicyFilePath(QString fileName)
+{
+
+ QString fullPath = getPolicyDir();
+ fullPath.append(fileName);
+ return fullPath;
+}
+bool policyFileExists(QString fileName)
+{
+ std::ifstream file(getPolicyFilePath(fileName).toUtf8().data());
+ if (file.good())
+ {
+ file.close();
+ return true;
+ }
+ return false;
+}
+
+void createPolicyDir()
+{
+ mkdir(getPolicyDir().toUtf8().data(), 0777);
+}
+
+void createPolicyFiles()
+{
+ if (!policyFileExists(QString(".allow")))
+ {
+ std::ofstream file(getPolicyFilePath(QString(".allow")).toUtf8().data());
+ file.close();
+ }
+#ifdef old_method
+ if (!policyFileExists(QString(".pass")))
+ {
+ std::ofstream file(getPolicyFilePath(QString(".pass")).toUtf8().data());
+ file.close();
+ }
+#endif
+}
+
+QString readPassFromPassFile()
+{
+ TextFile file(getPolicyFilePath(".pass"));
+ if (file.good()) // should have been checked via exists before, but better be safe
+ {
+ QString pass;
+ pass = file.readLine(); // we expect a password in correct format. otherwise their fault
+ return pass;
+ }
+ else
+ return QString();
+}
+bool getAllowed()
+{
+ printf("Checking %s\n", getPolicyFilePath(QString(".allow")).toUtf8().data());
+ TextFile file(getPolicyFilePath(".allow"));
+ if (file.good()) // should have been checked via exists before, but better be safe
+ {
+ QString allowed;
+ allowed = file.readLine();
+ if ( (allowed.compare(QString("1")) == 0) ||
+ (allowed.compare(QString("true")) == 0) ||
+ (allowed.compare(QString("t")) == 0) ||
+ (allowed.compare(QString("T")) == 0) ||
+ (allowed.compare(QString("true")) == 0) ||
+ (allowed.compare(QString("allow")) == 0) ||
+ (allowed.compare(QString("TRUE")) == 0) )
+ return true;
+ }
+ printf("...negative\n");
+ return false;
+}
+
+QString int2String(int intInt)
+{
+ char tmp[50];
+ snprintf(tmp, 49, "%d", intInt);
+ return QString(tmp);
+}
+
+int string2Int(QString string)
+{
+ return atoi(string.toUtf8().data());
+}
+
+//}//end namespace util
+
+
+#ifdef neverever
+std::list<VNCConnectInfo*> readFile(char* fileName)
+{
+ QString line;
+ std::ifstream file(fileName);
+ std::list<VNCConnectInfo*> infoList;
+
+ if (file.good())
+ {
+// std::cout << "reading clients file \"" << fileName <<"\"" << std::endl;
+ while (!file.eof())
+ {
+ getline(file, line);
+
+ if (!(line.length() <=1)) // ignore blank
+ if (!(line[0] == '#' || line[0] == '/')) // ignore comments
+ infoList.push_back(getConInfo(line));
+ }
+ }
+ else
+ {
+ std::cout << "ERROR: no file \"" << fileName <<"\" found or file corrupt" << std::endl;
+ }
+ return infoList;
+}
+
+VNCConnectInfo* getConInfo(QString line)
+{
+ char** arguments = new char*[100];
+ char* cLine = new char[line.length()+1];
+ strcpy(cLine, line.toUtf8().data());
+ int count;
+ makeArgs(cLine , &count , arguments);
+ std::cout << "found " << count << " arguments" << std::endl;
+ if (count > 2) // assume that a password would be the second argument in the line, therefore the third argument in the argv
+ {
+ QString pass = QString(arguments[2]);
+ std::cout << "think i found a password" << std::endl;
+ count--;
+ delete arguments[2];
+ // no changes to the arguments though, since the vnc-lib will ignore most of it anyway
+ return new VNCConnectInfo(count, arguments, pass);
+ }
+
+ return new VNCConnectInfo(count, arguments);
+}
+
+void makeArgs(char* line, int* count, char** arguments)
+{
+ (*count) = 1;
+
+ arguments[(*count)-1] = new char[strlen("dummy")+1]; // get program name from somewhere
+ strcpy(arguments[(*count)-1], "dummy");
+
+ /*// include encodings
+ arguments[(*count)++] = new char[strlen("-encodings")+1];
+ strcpy(arguments[(*count)], "-encodings");
+ (*count)++;
+ arguments[(*count)++] = new char[strlen("tight")+1];
+ strcpy(arguments[(*count)], "tight");
+ (*count)++;
+ */
+
+
+ if (line[strlen(line)-1] == '\n' || line[strlen(line)-1] == '\r')
+ line[strlen(line)-1] = '\0'; // remove newline
+
+ char *pch;
+ pch = strtok (line," ,\t");
+ while (pch != NULL && (*count) <= 3)
+ {
+ (*count)++; // count args
+ arguments[(*count)-1] = new char[strlen(pch)+1];
+ strcpy(arguments[(*count)-1], pch);
+ pch = strtok (NULL, " ,\t");
+ }
+}
+
+
+#endif
+
diff --git a/src/util/util.h b/src/util/util.h
new file mode 100644
index 0000000..37565cb
--- /dev/null
+++ b/src/util/util.h
@@ -0,0 +1,59 @@
+#include <QString>
+#include <cstdio>
+//#include <cstring>
+#include <list>
+#include <fstream>
+#include <iostream>
+#include <pwd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+
+
+#ifndef _PVSSERVERENTRY_H_
+#define _PVSSERVERENTRY_H_
+class PVSServerEntry
+{
+public:
+ PVSServerEntry(QString name);
+ void addClient(QString client);
+ bool hasClient(QString client);
+ QString getName();
+ int getSize();
+private:
+ QString name_;
+ std::list<QString> clientList_;
+};
+#endif
+
+//namespace util
+//{
+int getRandom(int min, int max);
+std::list<PVSServerEntry> getPVSServerEntryList(QString fileName);
+QString getFilenameFromPath(QString line);
+QString lineSplitter(QString line, const char* signs, bool first);
+QString colonSplitter(QString line, bool first);
+QString getUserName();
+QString getFullUsername();
+bool fileExists(QString fileName);
+QString getHomeDir();
+QString getPolicyDir();
+QString getPolicyFilePath(QString fileName);
+bool policyFileExists(QString fileName);
+void createPolicyFiles();
+void createPolicyDir();
+QString readPassFromPassFile();
+bool getAllowed();
+
+QString int2String(int intInt);
+int string2Int(QString string);
+int string2Int(QString string);
+//} // end namespace util
+
+//std::list<VNCConnectInfo*> readFile(char* fileName);
+//void makeArgs(char* line, int* count, char** arguments);
+//VNCConnectInfo* getConInfo(QString line);
+
+
+
+
diff --git a/src/util/vncClientThread.cpp b/src/util/vncClientThread.cpp
new file mode 100644
index 0000000..bb1d457
--- /dev/null
+++ b/src/util/vncClientThread.cpp
@@ -0,0 +1,249 @@
+/*
+ # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of
+ # Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # -----------------------------------------------------------------------------
+ # vncClientThread.cpp
+ # - Connection to remove vnc server
+ # - Emits Qt signal on framebuffer updates
+ # -----------------------------------------------------------------------------
+ */
+
+#include "vncClientThread.h"
+
+VNCClientThread::VNCClientThread(QString host, int port, QString passwd,
+ int quality, int updatefreq) :
+ QThread(), _frameBuffer(0)
+{
+ _host = host;
+ _port = port;
+ _passwd = passwd;
+ _quality = quality;
+ _updatefreq = updatefreq;
+ terminate = false;
+ _client = NULL;
+ _connected = false;
+}
+
+VNCClientThread::~VNCClientThread()
+{
+ if (this->isRunning()) this->wait(2000);
+ if (_frameBuffer) delete[] _frameBuffer;
+ _frameBuffer = NULL;
+ if (_client != NULL)
+ {
+ ::close(_client->sock);
+ _client->frameBuffer = NULL;
+ rfbClientCleanup(_client);
+ _client = NULL;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Public
+
+void VNCClientThread::run()
+{
+ qDebug("[%s] VNC client started.", metaObject()->className());
+ qDebug("[%s] Host: '%s' Port: %i Passwd: '%s' Quality: %i",
+ metaObject()->className(), qPrintable(_host), _port,
+ qPrintable(_passwd), _quality);
+
+ // setup network
+ _client = rfbGetClient(8, 3, 4);
+ _client->MallocFrameBuffer = frameBufferHandler;
+ _client->canHandleNewFBSize = true;
+ _client->serverHost = strdup(_host.toUtf8().constData());
+ _client->desktopName = NULL;
+ _client->serverPort = _port;
+ _client->GetPassword = passwdHandler;
+ _client->GotFrameBufferUpdate = updateImage;
+ _client->frameBuffer = NULL;
+
+ // save this instance in vnc-struct for callbacks
+ rfbClientSetClientData(_client, 0, this);
+
+ // start client
+ if (!rfbInitClient(_client, NULL, NULL))
+ {
+ _client = NULL; // !!! <- if you don't do this you will get a segfault
+ return; // later when you try to clean up _client, as rfbInitClient already did so
+ }
+
+ qDebug("[%s] Connection successful!", metaObject()->className());
+
+ // Main VNC event loop
+ while (!terminate)
+ {
+ _connected = true;
+ const int i = WaitForMessage(_client, 500); // its usec, not msec
+ if (i < 0)
+ break;
+ if (i) if (!HandleRFBServerMessage(_client))
+ break;
+
+ /*
+ //work yourself through event queue and fire every event...
+ while (!_eventQueue.isEmpty()) {
+ SomeEvent* event = _eventQueue.dequeue();
+ event->fire(_client);
+ delete event;
+ }*/
+
+ this->msleep(_updatefreq);
+ }
+
+ // cleanup
+ ::close(_client->sock);
+
+ qDebug("[%s] VNC client stopped.", metaObject()->className());
+ _connected = false;
+}
+
+QImage VNCClientThread::getImage()
+{
+ return _img;
+}
+
+QSize VNCClientThread::getSize()
+{
+ return _clientSize;
+}
+
+int VNCClientThread::getUpdatefreq()
+{
+ if (_updatefreq > 0)
+ return _updatefreq;
+ return 500;
+}
+
+void VNCClientThread::setUpdatefreq(int updatefreq)
+{
+ _updatefreq = updatefreq;
+}
+
+QString VNCClientThread::getDesktopName()
+{
+ if (_client == NULL || _client->desktopName == NULL) return QString();
+ return QString(_client->desktopName);
+}
+
+char* VNCClientThread::passwdHandler(rfbClient *client)
+{
+ VNCClientThread* t = (VNCClientThread*) rfbClientGetClientData(client, 0);
+ return strdup(t->_passwd.toLocal8Bit());
+}
+
+rfbBool VNCClientThread::frameBufferHandler(rfbClient *client)
+{
+ VNCClientThread *t = (VNCClientThread*) rfbClientGetClientData(client, 0);
+ const int width = client->width, height = client->height, depth =
+ client->format.bitsPerPixel;
+ const int size = width * height * (depth / 8);
+ qDebug("[%s] Remote desktop: %ix%ix%i", t->metaObject()->className(),
+ width, height, depth);
+
+ if (t->_frameBuffer)
+ delete[] t->_frameBuffer;
+
+ t->_frameBuffer = new uint8_t[size];
+ client->frameBuffer = t->_frameBuffer;
+ memset(client->frameBuffer, '\0', size);
+ client->format.bitsPerPixel = 32;
+ client->format.redShift = 16;
+ client->format.greenShift = 8;
+ client->format.blueShift = 0;
+ client->format.redMax = 0xff;
+ client->format.greenMax = 0xff;
+ client->format.blueMax = 0xff;
+
+ const int quality = t->_quality;
+ switch (quality)
+ {
+ case VNCClientThread::HIGH:
+ client->appData.useBGR233 = 0;
+ client->appData.encodingsString = "copyrect hextile raw";
+ client->appData.compressLevel = 0;
+ client->appData.qualityLevel = 9;
+ client->appData.scaleSetting = 10; // FIXME: Doesn't work
+ break;
+ case VNCClientThread::MEDIUM:
+ client->appData.useBGR233 = 0;
+ client->appData.encodingsString
+ = "tight zrle ultra copyrect hextile zlib corre rre raw";
+ client->appData.compressLevel = 5;
+ client->appData.qualityLevel = 7;
+ client->appData.scaleSetting = 10;
+ break;
+ case VNCClientThread::LOW:
+ default:
+ client->appData.useBGR233 = 1;
+ client->appData.encodingsString
+ = "tight zrle ultra copyrect hextile zlib corre rre raw";
+ client->appData.compressLevel = 9;
+ client->appData.qualityLevel = 1;
+ client->appData.scaleSetting = 10;
+ break;
+ }
+ SetFormatAndEncodings(client);
+
+ t->_clientSize = QSize(width, height);
+
+ // If something stops working with VNC images/updates, move these two
+ // commands back tp updateImage
+ const QImage img = QImage(client->frameBuffer, client->width,
+ client->height, QImage::Format_RGB32);
+ t->_img = img;
+ // <>
+
+ return true;
+}
+
+void VNCClientThread::updateImage(rfbClient* client, int x, int y, int w, int h)
+{
+ VNCClientThread* t = (VNCClientThread*) rfbClientGetClientData(client, 0);
+ emit t->imageUpdated(x, y, w, h);
+}
+
+/* rfbClient* VNCClientThread::getRfbClient(){
+ return _client;
+}*/
+
+SomeEvent::~SomeEvent()
+{
+}
+
+void PointerEvent::fire(rfbClient* cl)
+{
+ SendPointerEvent(cl, _x, _y, _buttonMask);
+}
+
+void KeyEvent::fire(rfbClient* cl)
+{
+ SendKeyEvent(cl, _key, _pressed);
+}
+
+void VNCClientThread::mouseEvent(int x, int y, int buttonMask)
+{
+ //QMutexLocker lock(&mutex);
+ if (terminate)
+ return;
+
+ _eventQueue.enqueue(new PointerEvent(x, y, buttonMask));
+}
+
+void VNCClientThread::keyEvent(int key, bool pressed)
+{
+ //QMutexLocker lock(&mutex);
+ if (terminate)
+ return;
+
+ _eventQueue.enqueue(new KeyEvent(key, pressed));
+}
diff --git a/src/util/vncClientThread.h b/src/util/vncClientThread.h
new file mode 100644
index 0000000..10980b8
--- /dev/null
+++ b/src/util/vncClientThread.h
@@ -0,0 +1,114 @@
+/*
+ # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of
+ # Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ */
+
+#ifndef VNCCLIENTTHREAD_H_
+#define VNCCLIENTTHREAD_H_
+
+#include <QtCore>
+#include <QtGui/QImage>
+
+extern "C"
+{
+#include <rfb/rfbclient.h>
+}
+
+class SomeEvent
+{
+public:
+ virtual ~SomeEvent();
+
+ virtual void fire(rfbClient*) = 0;
+};
+
+class KeyEvent : public SomeEvent
+{
+public:
+ KeyEvent(int key, int pressed)
+ : _key(key), _pressed(pressed) {}
+
+ void fire(rfbClient*);
+
+private:
+ int _key;
+ int _pressed;
+};
+
+class PointerEvent : public SomeEvent
+{
+public:
+ PointerEvent(int x, int y, int buttonMask)
+ : _x(x), _y(y), _buttonMask(buttonMask) {}
+
+ void fire(rfbClient*);
+
+private:
+ int _x;
+ int _y;
+ int _buttonMask;
+};
+
+class VNCClientThread: public QThread
+{
+ Q_OBJECT
+
+public:
+ VNCClientThread(QString host, int port, QString passwd, int quality, int updatefreq = 0);
+ ~VNCClientThread();
+
+ void run();
+ QImage getImage();
+ QSize getSize();
+ int getUpdatefreq();
+ void setUpdatefreq(int updatefreq);
+ QString getDesktopName();
+ void mouseEvent(int x, int y, int buttonMask);
+ void keyEvent(int key, bool pressed);
+ bool isConnected()
+ {
+ return _connected;
+ }
+
+
+ static void updateImage(rfbClient *client, int x, int y, int w, int h);
+ static char* passwdHandler(rfbClient *client);
+ static rfbBool frameBufferHandler(rfbClient *client);
+ //rfbClient* getRfbClient();
+
+ bool terminate;
+
+ int const static HIGH = 0;
+ int const static MEDIUM = 1;
+ int const static LOW = 2;
+
+Q_SIGNALS:
+ void imageUpdated(int x, int y, int w, int h);
+
+private:
+ rfbClient *_client;
+ uint8_t *_frameBuffer;
+
+ QString _host;
+ int _port;
+ QString _passwd;
+ int _quality;
+ int _updatefreq;
+ QQueue<SomeEvent* > _eventQueue;
+
+ QImage _img;
+ QSize _clientSize;
+
+ bool _connected;
+
+};
+
+#endif /* VNCCLIENTTHREAD_H_ */
diff --git a/src/version.h b/src/version.h
new file mode 100644
index 0000000..c217c07
--- /dev/null
+++ b/src/version.h
@@ -0,0 +1,2 @@
+#define VERSION_STRING "1.9.8.0"
+#define VERSION_NUMBER 1980