/*
# 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);
}
}