/*
# 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 "connectionframe.h"
#include "../net/client.h"
#include <QPixmap>
#include <QImage>
#include <cassert>
static QString style_student(
"QLabel{ background-color: #FFF; border-radius: 2px; color: black;} \
QGroupBox { background-color: #AAA; margin: 2px; border-radius: 4px}"
);
static QString style_tutor(
"QLabel{ background-color: #FFF; border-radius: 2px; color: black;} \
QGroupBox { background-color: #70C670; margin: 2px; border-radius: 4px}"
);
static QString style_selectedStudent(
"QLabel{ background-color: #FFF; border-radius: 2px; color: black; } \
QGroupBox { background-color: #AAA; margin: 0px; border-radius: 4px; border: 2px solid #6C8CD5;}"
);
static QString style_selectedTutor(
"QLabel{ background-color: #FFF; border-radius: 2px; color: black;} \
QGroupBox { background-color: #70C670; margin: 0px; border-radius: 4px; border: 2px solid #6C8CD5;}"
);
static QString style_disconnected(
"QLabel{ background-color: #919191; color: black; } \
QGroupBox { background-color: #7F7F7F; margin: 1px; border-radius: 4px}"
);
static QIcon *term = NULL, *cam = NULL, *eye = NULL, *lock = NULL;
/**
* Initialize frame for connected client.
* @param parent
* @param width
* @param height
*/
ConnectionFrame::ConnectionFrame(QWidget *parent, int width, int height) :
QGroupBox(parent), _client(NULL), _timerId(0), _timerCounter(0), _selected(false), _isTutor(false)
{
//defines the ui-stuff
// load icons first
if (term == NULL)
{
term = new QIcon(":terminal");
cam = new QIcon(":cf_cam");
eye = new QIcon(":cf_eye");
lock = new QIcon(":cf_lock");
}
//this->setAttribute(Qt::WA_OpaquePaintEvent);
_mainLayout = new QBoxLayout(QBoxLayout::TopToBottom, this);
_mainLayout->setSpacing(1);
_mainLayout->setMargin(3);
_mainLayout->setAlignment(Qt::AlignHCenter);
this->setStyleSheet(style_student);
_iconLayout = new QBoxLayout(QBoxLayout::RightToLeft, NULL);
_iconLayout->setSpacing(1);
_iconLayout->setMargin(3);
_lblUserName = new QLabel("Test", this);
_lblUserName->setAlignment(Qt::AlignHCenter);
_lblHostName = new QLabel("PC", this);
_lblHostName->setAlignment(Qt::AlignHCenter);
_icoCam = addIcon(cam);
_icoEye = addIcon(eye);
_icoLock = addIcon(lock);
_iconLayout->addWidget(_icoCam);
_iconLayout->addWidget(_icoEye);
_iconLayout->addWidget(_icoLock);
_iconLayout->addStretch();
_mainLayout->addLayout(_iconLayout);
_mainLayout->addStretch();
_mainLayout->addWidget(_lblUserName);
_mainLayout->addWidget(_lblHostName);
this->setLayout(_mainLayout);
this->setSize(width, height);
this->updateAppearance();
}
ConnectionFrame::~ConnectionFrame()
{
//
}
/**
* Add icon to connection frame.
* @param icon
* @return Pointer to new Icon.
*/
QLabel* ConnectionFrame::addIcon(const QIcon* icon)
{
QLabel *label = new QLabel(this);
label->setPixmap(icon->pixmap(24, 24, QIcon::Normal, QIcon::On));
label->setAttribute(Qt::WA_TranslucentBackground);
label->hide();
_icons.append(label);
return label;
}
/**
* Set size of connectionFrame.
* @param width
* @param height
*/
void ConnectionFrame::setSize(int width, int height)
{
this->resize(width, height);
if (this->_client == NULL)
showDefaultThumb();
}
/**
* Assign client to connectionFrame.
* Set hostName, userName and tutor status to display.
* @param client
*/
void ConnectionFrame::assignClient(Client* client)
{
assert(_client == NULL);
connect( client, SIGNAL(disconnected()), this, SLOT(onClientDisconnected()) );
connect( client, SIGNAL(thumbUpdated(Client*, const QPixmap&)), this, SLOT(onThumbUpdated(Client*, const QPixmap&)) );
connect( client, SIGNAL(vncServerStateChange(Client*)), this, SLOT(updateAppearance()));
connect( client, SIGNAL(vncClientStateChange(Client*)), this, SLOT(updateAppearance()));
connect( client, SIGNAL(stateChanged()), this, SLOT(updateAppearance()));
_client = client;
_computerId = client->ip();
_lblHostName->setText(client->ip());
_lblHostName->setToolTip(client->host());
_lblUserName->setText(client->name());
_lblUserName->show();
showDefaultThumb();
if (_timerId == 0)
_timerId = startTimer(1000 + qrand() % 150);
this->updateAppearance();
_client->setTutor(_isTutor);
}
/**
* Show default thumg instead of remote screen in connectionFrame.
*/
void ConnectionFrame::showDefaultThumb()
{
const int width = this->width() - 6;
const int height = this->height() - 8 - _lblHostName->height() - _lblUserName->height();
_remoteScreen = term->pixmap(width, height, QIcon::Normal, QIcon::On);
this->repaint();
//_imgScreen->setPixmap(_remoteScreen);
}
/**
* Handle mouse release event on frame.
* Check if frame was clicked or moved, if not moved enough, the event is handled as click.
* @param event
*/
void ConnectionFrame::mouseReleaseEvent(QMouseEvent* event)
{
event->accept();
if (event->button() == Qt::LeftButton)
{
QApplication::setOverrideCursor(QCursor(Qt::OpenHandCursor));
// Only recognize a move if the distance is larger than _startDragDistance
if ((this->pos() - _previousPosition).manhattanLength() > _startDragDistance )
{
qDebug("Moved");
emit frameMoved(this);
}
else
{
qDebug("Clicked");
move(_previousPosition);
emit clicked(this);
}
}
}
/**
* Handle if mouse reaches frame.
* @param event
*/
void ConnectionFrame::enterEvent(QEvent* event)
{
QApplication::setOverrideCursor(QCursor(Qt::OpenHandCursor));
event->accept();
}
/**
* Handle mouse leaves frame.
* @param event
*/
void ConnectionFrame::leaveEvent(QEvent* event)
{
QApplication::setOverrideCursor(QCursor(Qt::ArrowCursor));
event->accept();
}
/**
* Handle mouse press on frame.
* @param event
*/
void ConnectionFrame::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::RightButton)
{
// Menu...
}
else
{
_clickPoint = event->pos();
_previousPosition = this->pos();
QApplication::setOverrideCursor(QCursor(Qt::ClosedHandCursor));
}
// On click, the window has to be on the top-level.
activateWindow();
raise();
update();
event->accept();
}
/**
* Hanle mouse movement over frame.
* @param event
*/
void ConnectionFrame::mouseMoveEvent(QMouseEvent *event)
{
QApplication::setOverrideCursor(QCursor(Qt::ClosedHandCursor));
move(mapToParent(event->pos()-_clickPoint));
event->accept();
}
/**
* Handle double click event on frame.
* @param event
*/
void ConnectionFrame::mouseDoubleClickEvent(QMouseEvent* event)
{
emit doubleClicked(this);
event->accept();
}
/**
* Draw remote screen in frame.
* @param event
*/
void ConnectionFrame::paintEvent(QPaintEvent *event)
{
QGroupBox::paintEvent(event);
if (_remoteScreen.isNull())
return;
QPainter painter(this);
painter.drawPixmap((this->width() - _remoteScreen.width()) / 2, 4, _remoteScreen);
event->accept();
}
/**
* Handle timer event.
* @param event
*/
void ConnectionFrame::timerEvent(QTimerEvent* event)
{
if (_client == NULL)
return;
++_timerCounter;
if (_client->isActiveVncServer() && _timerCounter % 5 != 0)
return;
const int width = this->width() - 8;
const int height = this->height() - 9 - _lblHostName->height() - _lblUserName->height();
_client->requestThumb(width, height);
}
/**
* Set frame as selected or not.
* @param selected
*/
void ConnectionFrame::setSelection(bool selected)
{
if (_selected == selected)
return;
_selected = selected;
this->updateAppearance();
}
/**
* Set tutor status of frame.
* @param b
*/
void ConnectionFrame::setTutor(bool b)
{
if (_isTutor != b && _client != NULL)
_client->setTutor(b);
_isTutor = b;
this->updateAppearance();
}
/**
* Update appearence of frame.
* Check tutor status, vnc status and set background or icon.
*/
void ConnectionFrame::updateAppearance()
{
if (_client == NULL)
{
// Unconnected Frame
if (_selected)
this->setStyleSheet(style_selectedStudent);
else
this->setStyleSheet(style_disconnected);
for (QList<QLabel*>::iterator it(_icons.begin()); it != _icons.end(); ++it)
(**it).hide();
return;
}
_icoCam->setVisible(_client->isActiveVncServer());
_icoEye->setVisible(_client->isActiveVncClient());
_icoLock->setVisible(_client->isLocked());
// Normal client, no special stuff active
if (_selected && _isTutor){
this->setStyleSheet(style_selectedTutor);
}
else if (_isTutor){
this->setStyleSheet(style_tutor);
}
else if (_selected){
this->setStyleSheet(style_selectedStudent);
}
else{
this->setStyleSheet(style_student);
}
}
/*
* Slots
*/
/**
* Handle if client was disconnected.
* Kill timer and set appearence to default.
*/
void ConnectionFrame::onClientDisconnected()
{
if (_timerId != 0)
{
killTimer(_timerId);
_timerId = 0;
}
_client = NULL;
_lblUserName->setText(QString());
_lblUserName->hide();
showDefaultThumb();
this->updateAppearance();
}
/**
* Update thumb of specific client.
* @param client
* @param thumb
*/
void ConnectionFrame::onThumbUpdated(Client* client, const QPixmap& thumb)
{
assert(client == _client);
_remoteScreen = thumb;
//_imgScreen->setPixmap(_remoteScreen);
this->repaint();
}