summaryrefslogblamecommitdiffstats
path: root/src/gui/frame.cpp
blob: cb79643d369b7ee43e5a46de117f19c302add978 (plain) (tree)











































































































































































































































































































































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