summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorFabian Schillinger2010-11-01 17:35:27 +0100
committerFabian Schillinger2010-11-01 17:35:27 +0100
commitea3fb17345e5f82db9f2e98a8062e95797700ace (patch)
tree1da0d1a8ec9455364386af78762d0f6fed187824 /src/gui
parentProcess start/stop/view functionality (diff)
parent[PVSGUI] No X required for --help and --version (diff)
downloadpvs-ea3fb17345e5f82db9f2e98a8062e95797700ace.tar.gz
pvs-ea3fb17345e5f82db9f2e98a8062e95797700ace.tar.xz
pvs-ea3fb17345e5f82db9f2e98a8062e95797700ace.zip
Merge branch 'master' of openslx.org:pvs
Conflicts: CMakeLists.txt src/core/pvsConnectionManager.cpp src/pvs.cpp src/pvs.h
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/clientConfigDialog.cpp28
-rw-r--r--src/gui/clientConfigDialog.h3
-rw-r--r--src/gui/clientFileReceiveDialog.cpp95
-rw-r--r--src/gui/clientFileReceiveDialog.h14
-rw-r--r--src/gui/clientFileSendDialog.cpp201
-rw-r--r--src/gui/clientFileSendDialog.h21
-rw-r--r--src/gui/connectionWindow.h3
-rw-r--r--src/gui/frame.cpp304
-rw-r--r--src/gui/frame.h29
-rw-r--r--src/gui/mainWindow.cpp54
-rw-r--r--src/gui/mainWindow.h1
-rw-r--r--src/gui/multicastConfigDialog.cpp170
-rw-r--r--src/gui/multicastConfigDialog.h38
-rw-r--r--src/gui/ui/clientConfigDialog.ui64
-rw-r--r--src/gui/ui/clientFileReceiveDialog.ui11
-rw-r--r--src/gui/ui/clientFileSendDialog.ui15
-rw-r--r--src/gui/ui/clientNicklistDialog.ui7
-rw-r--r--src/gui/ui/mainwindow.ui15
-rw-r--r--src/gui/ui/mainwindowtouch.ui11
-rw-r--r--src/gui/ui/multicastConfigDialog.ui156
20 files changed, 1174 insertions, 66 deletions
diff --git a/src/gui/clientConfigDialog.cpp b/src/gui/clientConfigDialog.cpp
index 0ee5908..b7ba407 100644
--- a/src/gui/clientConfigDialog.cpp
+++ b/src/gui/clientConfigDialog.cpp
@@ -16,20 +16,33 @@
# -----------------------------------------------------------------------------
*/
+#include <QtDebug>
+#include <QNetworkInterface>
+#include <QStandardItemModel>
#include "clientConfigDialog.h"
+#include <cerrno>
+#include <cstdlib>
+#include <cstring>
+#include <src/net/pvsNetworkInterfaceListModel.h>
+
+using namespace std;
ClientConfigDialog::ClientConfigDialog(QWidget *parent) :
- QDialog(parent)
+ QDialog(parent),
+ _interfaceListModel(0)
{
setupUi(this);
connect(this, SIGNAL(accepted()), this, SLOT(writeSettings()));
connect(radioButtonOtherRO, SIGNAL(clicked()), this,
SLOT(checkPermissions()));
+ _interfaceListModel = new PVSNetworkInterfaceListModel(this);
+ interfaceList->setModel(_interfaceListModel);
+ interfaceList->setModelColumn(0);
+ connect(reloadInterfaceListButton, SIGNAL(clicked()), _interfaceListModel, SLOT(reloadInterfaceList()));
// connect to D-Bus and get interface
QDBusConnection dbus = QDBusConnection::sessionBus();
_ifaceDBus = new OrgOpenslxPvsInterface("org.openslx.pvs", "/", dbus, this);
-
}
ClientConfigDialog::~ClientConfigDialog()
@@ -53,7 +66,14 @@ void ClientConfigDialog::readSettings()
else
comboBox->setCurrentIndex(_settings.value("Display/location").toInt());
- QDBusPendingReply<QString> reply = _ifaceDBus->getConfigValue("Permissions/vnc_lecturer");
+ QDBusPendingReply<QString> reply = _ifaceDBus->getConfigValue("multicast/interface");
+ reply.waitForFinished();
+ if (reply.isValid())
+ {
+ interfaceList->setEditText(reply.value());
+ }
+
+ reply = _ifaceDBus->getConfigValue("Permissions/vnc_lecturer");
reply.waitForFinished();
if (reply.isValid())
{
@@ -86,7 +106,6 @@ void ClientConfigDialog::readSettings()
reply.waitForFinished();
if (reply.isValid())
checkBoxAllowFiletransfer->setChecked(reply.value() == "T");
-
}
void ClientConfigDialog::writeSettings()
@@ -110,6 +129,7 @@ void ClientConfigDialog::writeSettings()
QString(checkBoxAllowChat->isChecked() ? "T" : "F"));
_ifaceDBus->setConfigValue("Permissions/allow_filetransfer",
QString(checkBoxAllowFiletransfer->isChecked() ? "T" : "F"));
+ _ifaceDBus->setConfigValue("multicast/interface", interfaceList->currentText());
_settings.sync();
emit configChanged();
diff --git a/src/gui/clientConfigDialog.h b/src/gui/clientConfigDialog.h
index 98da54f..fd7529e 100644
--- a/src/gui/clientConfigDialog.h
+++ b/src/gui/clientConfigDialog.h
@@ -18,6 +18,8 @@
#include "pvsinterface.h"
#include "ui_clientConfigDialog.h"
+class QAbstractItemModel;
+
class ClientConfigDialog: public QDialog, private Ui::ClientConfigDialogClass
{
Q_OBJECT
@@ -40,6 +42,7 @@ private Q_SLOTS:
private:
OrgOpenslxPvsInterface *_ifaceDBus;
QSettings _settings;
+ QAbstractItemModel* _interfaceListModel;
};
diff --git a/src/gui/clientFileReceiveDialog.cpp b/src/gui/clientFileReceiveDialog.cpp
index 669ca81..fc6a1a3 100644
--- a/src/gui/clientFileReceiveDialog.cpp
+++ b/src/gui/clientFileReceiveDialog.cpp
@@ -16,6 +16,9 @@
*/
#include "clientFileReceiveDialog.h"
+#include <pvsinterface.h>
+#include <QFileInfo>
+#include <limits.h>
ClientFileReceiveDialog::ClientFileReceiveDialog(QTcpSocket *socket, QWidget *parent) :
QDialog(parent)
@@ -37,9 +40,44 @@ ClientFileReceiveDialog::ClientFileReceiveDialog(QTcpSocket *socket, QWidget *pa
connect(this, SIGNAL(finished(int)), this, SLOT(deleteLater()));
}
+ClientFileReceiveDialog::ClientFileReceiveDialog(QString const& sender, qulonglong transferID,
+ QString const& filename, qulonglong size, OrgOpenslxPvsInterface* ifaceDBus, QWidget* parent)
+{
+ setupUi(this);
+
+ _transferID = transferID;
+ _filename = filename;
+ _ifaceDBus = ifaceDBus;
+ _bytesToRead = size;
+ _socket = 0;
+ _file = 0;
+ div = 1;
+ while((size / div) > INT_MAX)
+ {
+ div <<= 1;
+ }
+
+ connect(ifaceDBus, SIGNAL(incomingMulticastTransferStarted(qulonglong)), SLOT(mcastTransferStarted(qulonglong)));
+ connect(ifaceDBus, SIGNAL(incomingMulticastTransferProgress(qulonglong, qulonglong, qulonglong)),
+ SLOT(mcastTransferProgress(qulonglong, qulonglong, qulonglong)));
+ connect(ifaceDBus, SIGNAL(incomingMulticastTransferFinished(qulonglong)), SLOT(mcastTransferFinished(qulonglong)));
+ connect(ifaceDBus, SIGNAL(incomingMulticastTransferFailed(qulonglong, QString)), SLOT(mcastTransferFailed(qulonglong, QString)));
+ connect(cancelButton, SIGNAL(clicked()), SLOT(cancelTransfer()));
+
+ qDebug("[%s] New multicast incoming transfer: %s from %s", metaObject()->className(),
+ filename.toLocal8Bit().constData(), sender.toLocal8Bit().constData());
+
+
+ filenameLabel->setText(QFileInfo(filename).baseName());
+ labelNick->setText(sender);
+ progressBar->setRange(0, 0);
+}
+
+
ClientFileReceiveDialog::~ClientFileReceiveDialog()
{
- _socket->deleteLater();
+ if(_socket)
+ _socket->deleteLater();
qDebug("[%s] Deleted!", metaObject()->className());
}
@@ -168,6 +206,61 @@ void ClientFileReceiveDialog::error(QAbstractSocket::SocketError error)
close();
}
+void ClientFileReceiveDialog::mcastTransferStarted(qulonglong transferID)
+{
+ if(transferID != _transferID)
+ return;
+}
+
+void ClientFileReceiveDialog::mcastTransferProgress(qulonglong transferID, qulonglong bytes, qulonglong of)
+{
+ if(transferID != _transferID)
+ return;
+
+ progressBar->setRange(0, of);
+ progressBar->setValue(bytes);
+
+ labelA->setText(formatSize(bytes));
+ labelB->setText(formatSize(of));
+}
+
+void ClientFileReceiveDialog::mcastTransferFinished(qulonglong transferID)
+{
+ if(transferID != _transferID)
+ return;
+
+ QString filename = QFileDialog::getSaveFileName(this, tr("Where should I save %1?").arg(_filename), _filename);
+ QFile* file = new QFile(_filename);
+ if(filename.isNull() || filename.isEmpty())
+ {
+ file->remove();
+ }
+ else
+ {
+ if(!file->rename(filename))
+ {
+ QMessageBox::warning(this, tr("Could not rename file"), tr("Failed to rename %1 to %2").arg(_filename).arg(filename));
+ }
+ }
+ accept();
+ deleteLater();
+}
+
+void ClientFileReceiveDialog::mcastTransferFailed(qulonglong transferID, QString reason)
+{
+ if(transferID != _transferID)
+ return;
+
+ QMessageBox::warning(this, tr("File transfer failed"), tr("File transfer failed for the following reason:\n%1").arg(reason));
+ reject();
+ deleteLater();
+}
+
+void ClientFileReceiveDialog::cancelTransfer()
+{
+ _ifaceDBus->cancelIncomingMulticastTransfer(_transferID);
+}
+
QString ClientFileReceiveDialog::formatSize(qint64 size)
{
if (size >= 1000000000) // GB
diff --git a/src/gui/clientFileReceiveDialog.h b/src/gui/clientFileReceiveDialog.h
index c13d7b7..c9ed220 100644
--- a/src/gui/clientFileReceiveDialog.h
+++ b/src/gui/clientFileReceiveDialog.h
@@ -18,6 +18,8 @@
#include <QtNetwork>
#include "ui_clientFileReceiveDialog.h"
+class OrgOpenslxPvsInterface;
+
class ClientFileReceiveDialog: public QDialog,
private Ui::ClientFileReceiveDialogClass
{
@@ -25,6 +27,7 @@ Q_OBJECT
public:
ClientFileReceiveDialog(QTcpSocket *socket, QWidget *parent = 0);
+ ClientFileReceiveDialog(QString const& sender, qulonglong transferID, QString const& basename, qulonglong size, OrgOpenslxPvsInterface* ifaceDBus, QWidget* parent = 0);
~ClientFileReceiveDialog();
private Q_SLOTS:
@@ -33,6 +36,13 @@ private Q_SLOTS:
void close();
void error(QAbstractSocket::SocketError error);
+ // multicast:
+ void mcastTransferStarted(qulonglong transferID);
+ void mcastTransferProgress(qulonglong transferID, qulonglong bytes, qulonglong of);
+ void mcastTransferFinished(qulonglong transferID);
+ void mcastTransferFailed(qulonglong transferID, QString reason);
+ void cancelTransfer();
+
private:
void sendAck(bool b);
QString formatSize(qint64 size);
@@ -42,6 +52,10 @@ private:
qint64 _bytesToRead;
int div;
+ // multicast:
+ OrgOpenslxPvsInterface* _ifaceDBus;
+ QString _filename;
+ qulonglong _transferID;
};
#endif /* CLIENTFILERECEIVEDIALOG_H_ */
diff --git a/src/gui/clientFileSendDialog.cpp b/src/gui/clientFileSendDialog.cpp
index b4512c0..93da725 100644
--- a/src/gui/clientFileSendDialog.cpp
+++ b/src/gui/clientFileSendDialog.cpp
@@ -22,6 +22,10 @@ ClientFileSendDialog::ClientFileSendDialog(QWidget *parent) :
{
setupUi(this);
+ _transferID = 0;
+ _error = false;
+ _isMulticast = false;
+
_file = NULL;
_socket = NULL;
_clientNicklistDialog = new ClientNicklistDialog(this);
@@ -58,7 +62,15 @@ void ClientFileSendDialog::open()
reject();
return;
}
- open(_clientNicklistDialog->getNick());
+
+ if (_clientNicklistDialog->isSendToAll())
+ {
+ sendToAll();
+ }
+ else
+ {
+ open(_clientNicklistDialog->getNick());
+ }
}
void ClientFileSendDialog::open(QString nick)
@@ -73,6 +85,70 @@ void ClientFileSendDialog::open(QString nick)
open(nick, filename);
}
+void ClientFileSendDialog::sendToAll()
+{
+ QString filename = QFileDialog::getOpenFileName(this, tr("Send File"), QDir::homePath(), "");
+ if (filename == "")
+ {
+ reject();
+ return;
+ }
+ sendToAll(filename);
+}
+
+void ClientFileSendDialog::sendToAll(QString filename)
+{
+ _isMulticast = true;
+
+ connect(_ifaceDBus, SIGNAL(outgoingMulticastTransferStarted(qulonglong)), SLOT(multicastTransferStarted(qulonglong)));
+ connect(_ifaceDBus, SIGNAL(outgoingMulticastTransferProgress(qulonglong,qulonglong,qulonglong)), SLOT(multicastTransferProgress(qulonglong, qulonglong, qulonglong)));
+ connect(_ifaceDBus, SIGNAL(outgoingMulticastTransferFinished(qulonglong)), SLOT(multicastTransferFinished(qulonglong)));
+ connect(_ifaceDBus, SIGNAL(outgoingMulticastTransferFailed(qulonglong, QString const&)), SLOT(multicastTransferFailed(qulonglong, QString const&)));
+
+ filenameLabel->setText(filename);
+ progressBar->setRange(0, 0);
+ labelNick->setText(tr("all"));
+ labelStatus->setText(tr("Waiting to start"));
+
+ QString errorMessage("Backend error");
+
+ // We need to jump through a lot of hoops because this call is prone to time out, and
+ // QtDBus does not support specifying timeouts in generated interfaces.
+ QDBusMessage call = QDBusMessage::createMethodCall("org.openslx.pvs", "/", "org.openslx.pvs", "createMulticastTransfer");
+ call << filename;
+
+ QDBusMessage reply = _ifaceDBus->connection().call(call, QDBus::Block, 5000);
+ if (reply.type() == QDBusMessage::ErrorMessage)
+ {
+ QMessageBox::critical(this, tr("File Send error"), tr("Error communicating with backend: %1: %2").arg(reply.errorName()).arg(reply.errorMessage()));
+ reject();
+ return;
+ }
+ else if (reply.type() == QDBusMessage::InvalidMessage)
+ {
+ QMessageBox::critical(this, tr("File Send error"), tr("Something went wrong while communicating with backend, but I don't know what."));
+ reject();
+ return;
+ }
+ else if (reply.type() == QDBusMessage::ReplyMessage)
+ {
+ QList<QVariant> args = reply.arguments();
+ bool created = args.at(0).toBool();
+ _transferID = args.at(1).toULongLong();
+ QString errorMessage = args.at(2).toString();
+ if (!created)
+ {
+ QMessageBox::critical(this, tr("File Send error"), tr("Could not create a multicast transfer: %1").arg(errorMessage));
+ reject();
+ return;
+ }
+ }
+
+ connect(cancelButton, SIGNAL(clicked()), SLOT(canceled()));
+
+ show();
+}
+
void ClientFileSendDialog::open(QString nick, QString filename)
{
// open file
@@ -127,6 +203,8 @@ void ClientFileSendDialog::receiveAck()
QString ack = QString::fromUtf8(_socket->readLine());
if (ack != "ok\n")
{
+ _error = true;
+ _reason = tr("Receiver declined");
qDebug("[%s] Received nack!", metaObject()->className());
close();
return;
@@ -158,27 +236,30 @@ void ClientFileSendDialog::sendFile()
void ClientFileSendDialog::close()
{
- if (_file && _file->isOpen())
- {
- _file->close();
- qDebug("[%s] File closed.", metaObject()->className());
- }
-
- if (_socket && _socket->isOpen())
+ if (!_isMulticast)
{
- 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());
+ 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()));
+ disconnect(cancelButton, SIGNAL(clicked()), this, SLOT(canceled()));
- if (_bytesToWrite == 0)
+ if (!_error)
{
accept();
QMessageBox::information(0, tr("PVS - File Transfer"),
@@ -188,12 +269,26 @@ void ClientFileSendDialog::close()
{
reject();
QMessageBox::warning(0, tr("PVS - File Transfer"),
- tr("File Transfer canceled!"));
+ tr("File Transfer canceled: %1").arg(_reason));
}
}
+void ClientFileSendDialog::canceled()
+{
+ if(_isMulticast)
+ {
+ _ifaceDBus->cancelOutgoingMulticastTransfer(_transferID);
+ }
+
+ _error = true;
+ _reason = tr("You clicked 'Cancel'");
+ close();
+}
+
void ClientFileSendDialog::error(QAbstractSocket::SocketError error)
{
+ _error = true;
+ _reason = tr("Socket Error");
qDebug("[%s] Socket error: %i", metaObject()->className(), error);
close();
}
@@ -210,6 +305,55 @@ QString ClientFileSendDialog::formatSize(qint64 size)
return QString("%1B").arg((qreal)size, 0, 'f',1);
}
+void ClientFileSendDialog::multicastTransferStarted(qulonglong transferID)
+{
+ qDebug() << "multicastTransferStarted(" << transferID << ")";
+ if (transferID != _transferID)
+ {
+ return;
+ }
+ labelStatus->setText("Started");
+}
+
+void ClientFileSendDialog::multicastTransferProgress(qulonglong transferID, qulonglong bytes, qulonglong of)
+{
+ qDebug() << "multicastTransferProgress(" << transferID << bytes << of << ")";
+ if (transferID != _transferID)
+ {
+ return;
+ }
+
+ if(bytes < of)
+ {
+ labelStatus->setText("Transferring");
+ progressBar->setRange(0, of);
+ progressBar->setValue(bytes);
+ }
+ else
+ {
+ labelStatus->setText("Waiting to finish");
+ progressBar->setRange(0, 0);
+ }
+
+ labelA->setText(formatSize(bytes));
+ labelB->setText(formatSize(of));
+}
+
+void ClientFileSendDialog::multicastTransferFinished(quint64 transferID)
+{
+ qDebug() << "multicastTransferFinished(" << transferID << ")";
+ qDebug("[%s] MulticastTransfer finished", metaObject()->className());
+ close();
+}
+
+void ClientFileSendDialog::multicastTransferFailed(quint64 transferID, QString const& reason)
+{
+ qDebug() << "multicastTransferFailed(" << transferID << reason << ")";
+ _error = true;
+ _reason = reason;
+ close();
+}
+
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
@@ -233,6 +377,25 @@ ClientNicklistDialog::ClientNicklistDialog(QWidget *parent) :
listWidget->addItems(nicknames);
listWidget->setCurrentRow(0);
+
+ connect(sendToAllCheckBox, SIGNAL(stateChanged(int)), SLOT(sendToAllStateChanged(int)));
+
+ sendToAllCheckBox->setCheckState(Qt::Unchecked);
+ _isSendToAll = false;
+}
+
+void ClientNicklistDialog::sendToAllStateChanged(int state)
+{
+ if (state)
+ {
+ listWidget->setEnabled(false);
+ _isSendToAll = true;
+ }
+ else
+ {
+ listWidget->setEnabled(true);
+ _isSendToAll = false;
+ }
}
ClientNicklistDialog::~ClientNicklistDialog()
diff --git a/src/gui/clientFileSendDialog.h b/src/gui/clientFileSendDialog.h
index d8afc3a..7abdcc7 100644
--- a/src/gui/clientFileSendDialog.h
+++ b/src/gui/clientFileSendDialog.h
@@ -30,9 +30,17 @@ public:
~ClientNicklistDialog();
QString getNick();
+ bool isSendToAll() const
+ {
+ return _isSendToAll;
+ }
+
+private Q_SLOTS:
+ void sendToAllStateChanged(int state);
private:
OrgOpenslxPvsInterface *_ifaceDBus;
+ bool _isSendToAll;
};
@@ -51,14 +59,22 @@ public:
void open();
void open(QString nick);
void open(QString nick, QString filename);
+ void sendToAll();
+ void sendToAll(QString filename);
private Q_SLOTS:
void sendHeader();
void receiveAck();
void sendFile();
void close();
+ void canceled();
void error(QAbstractSocket::SocketError error);
+ void multicastTransferStarted(qulonglong transferID);
+ void multicastTransferProgress(qulonglong transferID, qulonglong bytes, qulonglong of);
+ void multicastTransferFinished(qulonglong transferID);
+ void multicastTransferFailed(qulonglong transferID, QString const& reason);
+
private:
QString formatSize(qint64 size);
@@ -71,6 +87,11 @@ private:
OrgOpenslxPvsInterface *_ifaceDBus;
QString _nickname;
+ quint64 _transferID;
+ bool _error;
+ QString _reason;
+ bool _isMulticast;
+
};
#endif /* CLIENTFILESENDDIALOG_H_ */
diff --git a/src/gui/connectionWindow.h b/src/gui/connectionWindow.h
index e7d0177..55442db 100644
--- a/src/gui/connectionWindow.h
+++ b/src/gui/connectionWindow.h
@@ -9,6 +9,7 @@
#include <iostream>
#include <math.h>
#include <QSettings>
+#include <QPointer>
#define FRAME_DELAY 1000 // to comply with the standard value in the gui
@@ -110,7 +111,7 @@ protected:
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;
+ QPointer<ConnectionFrame> _closeupFrame;
QPoint currentPosition (ConnectionFrame* cF);
QMenu *menu;
QAction *newDummy;
diff --git a/src/gui/frame.cpp b/src/gui/frame.cpp
index cb79643..1b80c3d 100644
--- a/src/gui/frame.cpp
+++ b/src/gui/frame.cpp
@@ -18,11 +18,16 @@
# -----------------------------------------------------------------------------
*/
+#include <src/input/inputEvent.h>
+#include <src/input/inputHandlerChain.h>
#include "frame.h"
#include <src/gui/mainWindow.h>
#include <iostream>
#include <QPixmap>
+#define MOUSE_MOTION_SEND_INTERVAL 100 /* msecs */
+#define SPECIAL_EVENT_WAIT_TIME 5000 /* msecs */
+
Frame::Frame(const QString & text, QWidget * parent) :
QLabel(parent), _clientVNCThread(0)
{
@@ -51,10 +56,30 @@ Frame::Frame(const QString & text, QWidget * parent) :
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()));
+ button_control = createToolButton(tr("Enable Remote Control"), QIcon(":/remotecontrol"), SLOT(remoteControlClicked()));
+ button_control->setCheckable(true);
+ button_control_all = createToolButton(tr("Remote Control All Clients"), QIcon(":/remotecontrolall"), SLOT(remoteControlAllClicked()));
+ button_control_all->setCheckable(true);
connect(this, SIGNAL(clicked()), this, SLOT(slotClicked()));
ip = "";
setToolButtonListVisible(false);
+
+ _remoteControlEnabled = false;
+ _remoteControlToAll = false;
+
+ _mouseMotionEventTimer = new QTimer(this);
+ _mouseMotionEventTimer->setInterval(MOUSE_MOTION_SEND_INTERVAL);
+ _mouseMotionEventTimer->setSingleShot(false);
+ connect(_mouseMotionEventTimer, SIGNAL(timeout()), this, SLOT(sendMouseMotionEvent()));
+
+ _mousePositionChanged = true;
+
+ _specialEventTimer = new QTimer(this);
+ _specialEventTimer->setInterval(SPECIAL_EVENT_WAIT_TIME);
+ _specialEventTimer->setSingleShot(true);
+ connect(_specialEventTimer, SIGNAL(timeout()), this, SLOT(showSpecialEventMenu()));
+
}
Frame::~Frame()
@@ -216,23 +241,45 @@ void Frame::slotClicked()
void Frame::mousePressEvent(QMouseEvent* event)
{
- emit clicked();
- if (event->button() == Qt::RightButton)
- {
- /*if (!_dummy)
- DelDummy->setDisabled(true);
- menu->exec(QCursor::pos());*/
- }
- else
- {
+ if(!_remoteControlEnabled)
+ {
+ emit clicked();
+ if (event->button() == Qt::RightButton)
+ {
+ /*if (!_dummy)
+ DelDummy->setDisabled(true);
+ menu->exec(QCursor::pos());*/
+ }
+ else
+ {
- }
- QLabel::mousePressEvent(event);
+ }
+ QLabel::mousePressEvent(event);
+ }
+ else
+ {
+ event->accept();
+ ConsoleLog writeLine("Captured remote control mousePressEvent");
+
+ updateMousePosition(event);
+ sendInputEvent(InputEvent::mousePressRelease(event->button(), event->buttons()));
+ }
}
void Frame::mouseReleaseEvent ( QMouseEvent * event )
{
- QLabel::mouseReleaseEvent(event);
+ if(!_remoteControlEnabled)
+ {
+ QLabel::mouseReleaseEvent(event);
+ }
+ else
+ {
+ event->accept();
+ ConsoleLog writeLine("Captured remote control mouseReleaseEvent");
+
+ updateMousePosition(event);
+ sendInputEvent(InputEvent::mousePressRelease(event->button(), event->buttons()));
+ }
}
QToolButton* Frame::createToolButton(const QString &toolTip, const QIcon &icon, const char *member)
@@ -330,3 +377,236 @@ void Frame::setDozent()
getConFrame()->setDozent(true);
}
}
+
+void Frame::remoteControlClicked()
+{
+ if(_remoteControlEnabled)
+ {
+ setMouseTracking(false);
+ _mouseMotionEventTimer->stop();
+ button_control->setToolTip(tr("Enable Remote Control"));
+ _remoteControlEnabled = false;
+ button_control->setChecked(false);
+ releaseKeyboard();
+ }
+ else
+ {
+ button_control->setToolTip(tr("Disable Remote Control"));
+ _remoteControlEnabled = true;
+ button_control->setChecked(true);
+ _mouseMotionEventTimer->start();
+ setMouseTracking(true);
+ if(_mouseOver)
+ grabKeyboard();
+ }
+}
+
+void Frame::remoteControlAllClicked()
+{
+ if(_remoteControlToAll)
+ {
+ button_control_all->setToolTip(tr("Remote Control only this Client"));
+ button_control_all->setChecked(false);
+ _remoteControlToAll = false;
+ }
+ else
+ {
+ button_control_all->setToolTip(tr("Remote Control All Clients"));
+ button_control_all->setChecked(true);
+ _remoteControlToAll = true;
+ }
+}
+
+
+
+void Frame::sendMouseMotionEvent()
+{
+ InputEvent evt = InputEvent::mouseMotion(_lastRecordedMousePosition.x(), _lastRecordedMousePosition.y());
+
+ if(!_mousePositionChanged)
+ return;
+
+ _mousePositionChanged = false;
+ sendInputEvent(evt);
+}
+
+void Frame::sendInputEvent(InputEvent const& evt)
+{
+ QString str;
+ eventToString(evt, str);
+ std::string evtStr = evt.toString();
+ PVSMsg msg(PVSCOMMAND, "INPUTEVENT", str);
+
+ if(_remoteControlEnabled)
+ {
+ if(_remoteControlToAll)
+ {
+ ConsoleLog writeLine(QString("sendInputEvent(%1) to one").arg(evtStr.c_str()));
+ PVSConnectionManager::getManager()->getServer()->sendToAll(msg);
+ }
+ else
+ {
+ ConsoleLog writeLine(QString("sendInputEvent(%1) to all").arg(evtStr.c_str()));
+ _cFrame->getConnection()->sendMessage(msg);
+ }
+ }
+ else
+ {
+ ConsoleLog writeLine("sendMouseMotionEvent() disabled");
+ }
+}
+
+void Frame::mouseMoveEvent(QMouseEvent* event)
+{
+ QPoint newPosition = rescalePosition(event->posF());
+ if(newPosition != _lastRecordedMousePosition) {
+ _lastRecordedMousePosition = newPosition;
+ _mousePositionChanged = true;
+ ConsoleLog writeLine(QString("Mouse moved to (%1,%2)").arg(_lastRecordedMousePosition.x()).arg(_lastRecordedMousePosition.y()));
+ }
+}
+
+QPoint Frame::rescalePosition(QPointF guipos)
+{
+ if(!_clientVNCThread)
+ return QPoint();
+
+ QSize s = size();
+ QSize t = _clientVNCThread->getSize();
+ qreal px, py;
+ px = guipos.x() * t.width() / (qreal)s.width();
+ py = guipos.y() * t.height() / (qreal)s.height();
+ return QPoint((int)px, (int)py);
+}
+
+void Frame::updateMousePosition(QMouseEvent* event)
+{
+ QPoint oldPosition = _lastRecordedMousePosition;
+ _lastRecordedMousePosition = rescalePosition(event->posF());
+ _mousePositionChanged = oldPosition != _lastRecordedMousePosition;
+ sendMouseMotionEvent();
+}
+
+void Frame::enterEvent(QEvent* event)
+{
+ _mouseOver = true;
+ if(_remoteControlEnabled)
+ {
+ grabKeyboard();
+ }
+}
+
+void Frame::leaveEvent(QEvent* event)
+{
+ _mouseOver = false;
+ if(_remoteControlEnabled)
+ {
+ releaseKeyboard();
+ }
+}
+
+void Frame::keyPressEvent(QKeyEvent* event)
+{
+ if(_remoteControlEnabled)
+ {
+ if(event->key() == Qt::Key_Menu)
+ {
+ qDebug("Menu has been pressed");
+ if(!event->isAutoRepeat())
+ _specialEventTimer->start();
+ }
+ else
+ {
+ // The action of the keyboard may depend on the position of the pointer
+ sendMouseMotionEvent();
+ sendInputEvent(InputEvent::keyboardPress(event->key(), event->modifiers()));
+ }
+ }
+ else
+ {
+ QLabel::keyPressEvent(event);
+ }
+}
+
+void Frame::keyReleaseEvent(QKeyEvent* event)
+{
+ if(_remoteControlEnabled)
+ {
+ sendMouseMotionEvent();
+ if(event->key() == Qt::Key_Menu)
+ {
+ if(!event->isAutoRepeat())
+ {
+ qDebug("Menu has been released");
+ if(_specialEventTimer->isActive())
+ {
+ qDebug("Pressing key on client");
+ // Pressing the key has been deferred, so do it now:
+ sendInputEvent(InputEvent::keyboardPress(event->key(), event->modifiers()));
+ }
+ sendInputEvent(InputEvent::keyboardRelease(event->key(), event->modifiers()));
+ _specialEventTimer->stop();
+ }
+ }
+ else
+ {
+ // The action of the keyboard may depend on the position of the pointer
+ sendInputEvent(InputEvent::keyboardRelease(event->key(), event->modifiers()));
+ }
+ }
+ else
+ {
+ QLabel::keyReleaseEvent(event);
+ }
+}
+
+bool Frame::event(QEvent* event)
+{
+ if(_remoteControlEnabled)
+ {
+ bool recognized;
+ switch(event->type())
+ {
+ case QEvent::ShortcutOverride:
+ recognized = true;
+ event->accept();
+ break;
+ case QEvent::KeyPress:
+ recognized = true;
+ keyPressEvent(static_cast<QKeyEvent*>(event));
+ break;
+ case QEvent::KeyRelease:
+ recognized = true;
+ keyReleaseEvent(static_cast<QKeyEvent*>(event));
+ break;
+ default:
+ recognized = false;
+ }
+ if(recognized && event->isAccepted())
+ return true;
+ }
+ return QLabel::event(event);
+}
+
+void Frame::showSpecialEventMenu()
+{
+ qDebug("Trying to show menu...");
+ QMenu* menu = new QMenu(this);
+ QList<SpecialInputEventDescription> specialEvents = privileged_handler_chain::describe();
+ QList<SpecialInputEventDescription>::iterator iter;
+ int i;
+ for(i = 0, iter = specialEvents.begin();
+ iter != specialEvents.end();
+ iter++, i++)
+ {
+ QAction* act = menu->addAction((*iter).descriptionString);
+ act->setData(i);
+ }
+ QAction* selected = menu->exec(QCursor::pos());
+ if(selected)
+ {
+ int index = selected->data().toInt();
+ sendInputEvent(specialEvents.at(index).toEvent());
+ }
+ delete menu;
+}
diff --git a/src/gui/frame.h b/src/gui/frame.h
index 3004e0c..8271670 100644
--- a/src/gui/frame.h
+++ b/src/gui/frame.h
@@ -8,6 +8,7 @@ class VNCClientThread;
class ConnectionWindow;
class ConnectionFrame;
class MainWindow;
+class InputEvent;
class Frame: public QLabel
{
@@ -48,8 +49,13 @@ public:
QToolButton* button_lock;
QToolButton* button_unlock;
QToolButton* button_dozent;
+ QToolButton* button_control;
+ QToolButton* button_control_all;
QList<QToolButton*> toolButtonList;
+ bool _remoteControlEnabled;
+ bool _remoteControlToAll;
+
public Q_SLOTS:
void updateImage(int x, int y, int w, int h);
void iamDown();
@@ -68,13 +74,24 @@ public Q_SLOTS:
void setLock();
//void unlock();
void setDozent();
+private Q_SLOTS:
+ void remoteControlClicked();
+ void remoteControlAllClicked();
+ void sendMouseMotionEvent();
+ void showSpecialEventMenu();
signals:
- void clicked();
+ void clicked();
protected:
void paintEvent(QPaintEvent *event);
void mousePressEvent ( QMouseEvent * event );
void mouseReleaseEvent ( QMouseEvent * event );
+ void mouseMoveEvent ( QMouseEvent * event );
+ void enterEvent(QEvent* event);
+ void leaveEvent(QEvent* event);
+ void keyPressEvent(QKeyEvent* event);
+ void keyReleaseEvent(QKeyEvent* event);
+ bool event(QEvent* event);
private:
QToolButton* createToolButton(const QString &toolTip, const QIcon &icon, const char *member);
@@ -85,6 +102,16 @@ private:
bool _isLocked;
bool _dozent;
int _ux, _uy;
+
+ // for remote control:
+ QPoint _lastRecordedMousePosition;
+ bool _mousePositionChanged;
+ QTimer* _mouseMotionEventTimer;
+ bool _mouseOver;
+ QTimer* _specialEventTimer;
+ QPoint rescalePosition(QPointF guiPosition);
+ void updateMousePosition(QMouseEvent* event);
+ void sendInputEvent(InputEvent const&);
};
#endif /* FRAME_H_ */
diff --git a/src/gui/mainWindow.cpp b/src/gui/mainWindow.cpp
index 815f001..b6878e8 100644
--- a/src/gui/mainWindow.cpp
+++ b/src/gui/mainWindow.cpp
@@ -16,7 +16,10 @@
#include <QtGui>
#include <QFileDialog>
+#include <QBuffer>
+#include <QDataStream>
#include <src/gui/mainWindow.h>
+#include <src/net/mcast/McastConfiguration.h>
using namespace std;
// setting the IF-DEF Block for the touchgui and the normal gui, for later use
@@ -35,6 +38,7 @@ using namespace std;
#include <src/gui/processesDialog.h>
//#include <src/gui/dialog.h>
#include <src/core/pvsConnectionManager.h>
+#include <src/gui/multicastConfigDialog.h>
#include <iostream>
MainWindow::MainWindow(QWidget *parent) :
@@ -133,6 +137,7 @@ MainWindow::MainWindow(QWidget *parent) :
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->actionConfigure_Network, SIGNAL(triggered()), this, SLOT(configureNetwork()));
connect(ui->actionShowProcesses, SIGNAL(triggered()), this, SLOT(showProcesses()));
ui->actionShowProcesses->setStatusTip(tr("Show Processes of the selected Client"));
connect(ui->actionStartProcess, SIGNAL(triggered()), this, SLOT(startProcess()));
@@ -163,7 +168,6 @@ MainWindow::MainWindow(QWidget *parent) :
_serverSocket = new QTcpServer();
_serverSocket->listen(QHostAddress::Any, 29481);
connect(_serverSocket, SIGNAL(newConnection()), this, SLOT(incomingFile()));
-
}
MainWindow::~MainWindow()
@@ -270,24 +274,24 @@ void MainWindow::loadSettings()
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);
+// 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);
@@ -1277,6 +1281,18 @@ void MainWindow::startChatDialog()
sChatDialog.raise();//show the chat dialog on top level
}
+void MainWindow::configureNetwork()
+{
+ PVSServer* server = PVSConnectionManager::getManager()->getServer();
+ McastConfiguration mc(*(server->getMulticastConfiguration()));
+ MulticastConfigDialog* mcd = new MulticastConfigDialog(&mc, this);
+ int result = mcd->exec();
+ if(result == QDialog::Accepted)
+ {
+ server->multicastReconfigure(&mc);
+ }
+}
+
MainWindow* MainWindow::myself = NULL;
ConnectionList* MainWindow::conList = NULL;
ConnectionWindow* MainWindow::conWin = NULL;
diff --git a/src/gui/mainWindow.h b/src/gui/mainWindow.h
index 2ab62f8..28f82f7 100644
--- a/src/gui/mainWindow.h
+++ b/src/gui/mainWindow.h
@@ -204,6 +204,7 @@ private slots:
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
+ void configureNetwork();
};
diff --git a/src/gui/multicastConfigDialog.cpp b/src/gui/multicastConfigDialog.cpp
new file mode 100644
index 0000000..ff370c7
--- /dev/null
+++ b/src/gui/multicastConfigDialog.cpp
@@ -0,0 +1,170 @@
+#include <QValidator>
+#include <QIntValidator>
+#include <QHostAddress>
+#include <QPushButton>
+#include "multicastConfigDialog.h"
+#include <src/net/mcast/McastConfiguration.h>
+// #include "multicastValidators.h"
+
+MulticastConfigDialog::MulticastConfigDialog(QWidget* parent) :
+ QDialog(parent)
+{
+ setupUi();
+}
+
+MulticastConfigDialog::MulticastConfigDialog(McastConfiguration* config,
+ QWidget *parent) :
+ QDialog(parent)
+{
+ setupUi();
+ _config = config;
+
+ _ui.groupAddressEdit->setText(config->multicastAddress());
+ _ui.dataPortEdit->setText(QString::number(config->multicastUDPPortBase()));
+
+ connect(_ui.buttonBox, SIGNAL(accepted()), this, SLOT(dialogAccepted()));
+ connect(_ui.buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
+}
+
+void MulticastConfigDialog::setupUi()
+{
+ _ui.setupUi(this);
+
+ QIntValidator* portValidator = new QIntValidator(1024, 65535, this);
+ _ui.dataPortEdit->setValidator(portValidator);
+
+ connect(_ui.groupAddressEdit, SIGNAL(textChanged(QString const&)), this,
+ SLOT(validateGroupAddress(QString const&)));
+ connect(_ui.dataPortEdit, SIGNAL(textChanged(QString const&)), this,
+ SLOT(validateDataPort(QString const&)));
+
+ connect(_ui.buttonBox, SIGNAL(accepted()), this, SLOT(dialogAccepted()));
+ connect(_ui.buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
+
+ validateGroupAddress(_ui.groupAddressEdit->text());
+ validateDataPort(_ui.dataPortEdit->text());
+}
+
+MulticastConfigDialog::~MulticastConfigDialog()
+{
+}
+
+void MulticastConfigDialog::dialogAccepted()
+{
+ QHostAddress addr;
+ bool addressParses = addr.setAddress(_ui.groupAddressEdit->text());
+ _config->multicastAddress(_ui.groupAddressEdit->text());
+ quint16 port = _ui.dataPortEdit->text().toInt();
+ _config->multicastUDPPortBase(port);
+ _config->multicastDPort(port + 1);
+ _config->multicastSPort(port + 2);
+ _config->multicastRate(_ui.rateSpinbox->value() * 1024);
+ accept();
+}
+
+void MulticastConfigDialog::setError(QWidget* widget,
+ QLabel* errorMessageLabel, QString text)
+{
+ if (errorMessageLabel)
+ errorMessageLabel->setText(QString(
+ "<span style=\"font-weight: 600; color: #880000;\">") + text
+ + "</span>");
+ if (widget)
+ widget->setStyleSheet("background-color: #ffcccc;");
+}
+
+void MulticastConfigDialog::setOK(QWidget* widget, QLabel* errorMessageLabel)
+{
+ if (errorMessageLabel)
+ errorMessageLabel->setText(QString(
+ "<span style=\"font-weight: 600; color: #008800;\">")
+ + tr("OK") + "</span>");
+ if (widget)
+ widget->setStyleSheet("background-color: #ccffcc;");
+}
+
+void MulticastConfigDialog::validateGroupAddress(QString const& input)
+{
+ QHostAddress a;
+
+ _isAddressValid = false;
+
+ if (!a.setAddress(input))
+ {
+ setError(_ui.groupAddressEdit, _ui.groupAddressMessage, tr(
+ "Not a valid IP Address"));
+ revalidateButtons();
+ return;
+ }
+
+ // check if it is IPv4
+ if (a.protocol() != QAbstractSocket::IPv4Protocol)
+ {
+ setError(_ui.groupAddressEdit, _ui.groupAddressMessage, tr(
+ "Not a valid IPv4 Address"));
+ revalidateButtons();
+ return;
+ }
+
+ // check if it is a valid multicast address
+ quint32 addr = a.toIPv4Address();
+ if ((addr & 0xf0000000) != 0xe0000000)
+ {
+ setError(_ui.groupAddressEdit, _ui.groupAddressMessage, tr(
+ "Not an IPv4 multicast address"));
+ revalidateButtons();
+ return;
+ }
+
+ _isAddressValid = true;
+ setOK(_ui.groupAddressEdit, _ui.groupAddressMessage);
+ revalidateButtons();
+}
+
+void MulticastConfigDialog::validateDataPort(QString const& input)
+{
+ bool ok;
+ int p = input.toInt(&ok, 0);
+
+ _isPortValid = false;
+
+ if (!ok)
+ {
+ setError(_ui.dataPortEdit, _ui.dataPortMessage, tr("Not a number"));
+ revalidateButtons();
+ return;
+ }
+
+ if (p < 0)
+ {
+ setError(_ui.dataPortEdit, _ui.dataPortMessage, tr("Must be positive"));
+ revalidateButtons();
+ return;
+ }
+
+ if (p < 1024)
+ {
+ setError(_ui.dataPortEdit, _ui.dataPortMessage, tr(
+ "Must not be a privileged port"));
+ revalidateButtons();
+ return;
+ }
+
+ if (p > 65535)
+ {
+ setError(_ui.dataPortEdit, _ui.dataPortMessage, tr(
+ "Port number too large"));
+ revalidateButtons();
+ return;
+ }
+
+ _isPortValid = true;
+ setOK(_ui.dataPortEdit, _ui.dataPortMessage);
+ revalidateButtons();
+}
+
+void MulticastConfigDialog::revalidateButtons()
+{
+ _ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(_isAddressValid
+ && _isPortValid);
+}
diff --git a/src/gui/multicastConfigDialog.h b/src/gui/multicastConfigDialog.h
new file mode 100644
index 0000000..6421813
--- /dev/null
+++ b/src/gui/multicastConfigDialog.h
@@ -0,0 +1,38 @@
+#ifndef MULTICASTCONFIGDIALOG_H
+#define MULTICASTCONFIGDIALOG_H
+
+#include <QtGui/QDialog>
+#include <QPointer>
+#include "ui_multicastConfigDialog.h"
+#include <pvsinterface.h>
+
+class McastConfiguration;
+
+class MulticastConfigDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ MulticastConfigDialog(QWidget* parent = 0);
+ MulticastConfigDialog(McastConfiguration* dbusIface, QWidget *parent = 0);
+ ~MulticastConfigDialog();
+
+private:
+ Ui::MulticastConfigDialogClass _ui;
+ McastConfiguration* _config;
+ bool _isAddressValid;
+ bool _isPortValid;
+
+ void setupUi();
+
+ void setError(QWidget* input, QLabel* messageLabel, QString text);
+ void setOK(QWidget* input, QLabel* messageLabel);
+ void revalidateButtons();
+
+private slots:
+ void dialogAccepted();
+ void validateGroupAddress(QString const&);
+ void validateDataPort(QString const&);
+};
+
+#endif // MULTICASTCONFIGDIALOG_H
diff --git a/src/gui/ui/clientConfigDialog.ui b/src/gui/ui/clientConfigDialog.ui
index 3262b6b..bb4bdc9 100644
--- a/src/gui/ui/clientConfigDialog.ui
+++ b/src/gui/ui/clientConfigDialog.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>438</width>
- <height>257</height>
+ <width>445</width>
+ <height>266</height>
</rect>
</property>
<property name="windowTitle">
@@ -27,7 +27,7 @@
<enum>QTabWidget::North</enum>
</property>
<property name="currentIndex">
- <number>0</number>
+ <number>2</number>
</property>
<widget class="QWidget" name="tabPermissions">
<attribute name="title">
@@ -197,6 +197,64 @@
</item>
</layout>
</widget>
+ <widget class="QWidget" name="networkTab">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <attribute name="title">
+ <string>Network</string>
+ </attribute>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="2" column="1">
+ <widget class="QComboBox" name="interfaceList">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ <property name="insertPolicy">
+ <enum>QComboBox::NoInsert</enum>
+ </property>
+ <property name="frame">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Network Interface</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QPushButton" name="reloadInterfaceListButton">
+ <property name="text">
+ <string>Reload List</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
</widget>
</item>
<item>
diff --git a/src/gui/ui/clientFileReceiveDialog.ui b/src/gui/ui/clientFileReceiveDialog.ui
index af3a135..a137def 100644
--- a/src/gui/ui/clientFileReceiveDialog.ui
+++ b/src/gui/ui/clientFileReceiveDialog.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>208</width>
- <height>108</height>
+ <width>528</width>
+ <height>117</height>
</rect>
</property>
<property name="windowTitle">
@@ -61,6 +61,13 @@
</property>
</spacer>
</item>
+ <item>
+ <widget class="QLabel" name="labelStatus">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
</layout>
</item>
<item>
diff --git a/src/gui/ui/clientFileSendDialog.ui b/src/gui/ui/clientFileSendDialog.ui
index d2d9c75..85462ba 100644
--- a/src/gui/ui/clientFileSendDialog.ui
+++ b/src/gui/ui/clientFileSendDialog.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>186</width>
- <height>108</height>
+ <width>528</width>
+ <height>144</height>
</rect>
</property>
<property name="windowTitle">
@@ -33,7 +33,7 @@
</widget>
</item>
<item>
- <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
@@ -61,10 +61,17 @@
</property>
</spacer>
</item>
+ <item>
+ <widget class="QLabel" name="labelStatus">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
</layout>
</item>
<item>
- <layout class="QHBoxLayout" name="horizontalLayout">
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="labelA">
<property name="text">
diff --git a/src/gui/ui/clientNicklistDialog.ui b/src/gui/ui/clientNicklistDialog.ui
index afd84f1..3679b55 100644
--- a/src/gui/ui/clientNicklistDialog.ui
+++ b/src/gui/ui/clientNicklistDialog.ui
@@ -29,6 +29,13 @@
<widget class="QListWidget" name="listWidget"/>
</item>
<item>
+ <widget class="QCheckBox" name="sendToAllCheckBox">
+ <property name="text">
+ <string>Send to &amp;all</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
diff --git a/src/gui/ui/mainwindow.ui b/src/gui/ui/mainwindow.ui
index 285d0f2..d444092 100644
--- a/src/gui/ui/mainwindow.ui
+++ b/src/gui/ui/mainwindow.ui
@@ -243,9 +243,16 @@
</property>
<addaction name="actionAbout_pvs"/>
</widget>
+ <widget class="QMenu" name="menuNetwork">
+ <property name="title">
+ <string>Network</string>
+ </property>
+ <addaction name="actionConfigure_Network"/>
+ </widget>
<addaction name="menu_File"/>
<addaction name="menuClients"/>
<addaction name="menuLogging"/>
+ <addaction name="menuNetwork"/>
<addaction name="menu_Help"/>
</widget>
<widget class="QStatusBar" name="statusBar"/>
@@ -533,6 +540,14 @@
<string>-</string>
</property>
</action>
+ <action name="actionConfigure_Network">
+ <property name="text">
+ <string>&amp;Configure...</string>
+ </property>
+ <property name="toolTip">
+ <string>Configure Network Parameters</string>
+ </property>
+ </action>
<action name="actionShowProcesses">
<property name="icon">
<iconset resource="../../../pvsmgr.qrc">
diff --git a/src/gui/ui/mainwindowtouch.ui b/src/gui/ui/mainwindowtouch.ui
index ae1d0cf..ea6f01e 100644
--- a/src/gui/ui/mainwindowtouch.ui
+++ b/src/gui/ui/mainwindowtouch.ui
@@ -365,6 +365,8 @@
<addaction name="actionresetall"/>
<addaction name="separator"/>
<addaction name="actionDozent"/>
+ <addaction name="separator"/>
+ <addaction name="actionConfigure_Network"/>
<addaction name="actionShowProcesses"/>
<addaction name="actionStartProcess"/>
</widget>
@@ -638,6 +640,15 @@
<string>Ctrl+D</string>
</property>
</action>
+ <action name="actionConfigure_Network">
+ <property name="icon">
+ <iconset resource="../../../pvsmgr.qrc">
+ <normaloff>:/netconf</normaloff>:/netconf</iconset>
+ </property>
+ <property name="text">
+ <string>Configure Network...</string>
+ </property>
+ </action>
<action name="actionShowProcesses">
<property name="icon">
<iconset resource="../../../pvsmgr.qrc">
diff --git a/src/gui/ui/multicastConfigDialog.ui b/src/gui/ui/multicastConfigDialog.ui
new file mode 100644
index 0000000..1ddf02c
--- /dev/null
+++ b/src/gui/ui/multicastConfigDialog.ui
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MulticastConfigDialogClass</class>
+ <widget class="QDialog" name="MulticastConfigDialogClass">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>331</width>
+ <height>314</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle">
+ <string>PVS - Multicast Configuration</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <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:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;table style=&quot;-qt-table-type: root; margin-top:4px; margin-bottom:4px; margin-left:4px; margin-right:4px;&quot;&gt;
+&lt;tr&gt;
+&lt;td style=&quot;border: none;&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;You need to specify connection parameters for multicast messaging on your network. These parameters will automatically be distributed to client computers, so you need to assign them only once.&lt;/p&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;You will probably want to assign an address from the &lt;span style=&quot; text-decoration: underline;&quot;&gt;239.0.0.0/8&lt;/span&gt; &amp;quot;Administratively Scoped&amp;quot; range.&lt;/p&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-weight:600;&quot;&gt;Do not assign arbitrary numbers without checking with your network administrator!&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Multicast Group Address</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="groupAddressEdit">
+ <property name="inputMask">
+ <string notr="true">009.009.009.009; </string>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="2">
+ <widget class="QLabel" name="groupAddressMessage">
+ <property name="text">
+ <string>&lt;span style=&quot; font-weight:600; color:#008800;&quot;&gt;OK&lt;/span&gt;</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Data Port (1024-65535)</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLineEdit" name="dataPortEdit">
+ <property name="inputMask">
+ <string notr="true">00009; </string>
+ </property>
+ <property name="maxLength">
+ <number>5</number>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" colspan="2">
+ <widget class="QLabel" name="dataPortMessage">
+ <property name="text">
+ <string>&lt;span style=&quot; font-weight:600; color:#008800;&quot;&gt;OK&lt;/span&gt;</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Transmission Rate</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QSpinBox" name="rateSpinbox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="suffix">
+ <string> KiB/s</string>
+ </property>
+ <property name="maximum">
+ <number>10240</number>
+ </property>
+ <property name="singleStep">
+ <number>10</number>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources/>
+ <connections/>
+</ui>