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