summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2016-11-02 19:24:07 +0100
committerSimon Rettberg2016-11-02 19:24:07 +0100
commit9d73e385153656ef998cc8f6378bb01ff36b2090 (patch)
treee73108ab31a56bd310af25b9e0623378480fb2bd
parent[server] Run "manager only" logic before creating main window (diff)
downloadpvs2-9d73e385153656ef998cc8f6378bb01ff36b2090.tar.gz
pvs2-9d73e385153656ef998cc8f6378bb01ff36b2090.tar.xz
pvs2-9d73e385153656ef998cc8f6378bb01ff36b2090.zip
[server] Rewrite positioning logic of connection frames
This fixes sevceral bugs: * Frames moved into virtually expanded area (for keeping aspect ratio) could be out of bounds after a window resize before * Finding a free slot to place a frame was slightly sped up * Finding a free slot is not used when loading a room layout, as it was (still is) pretty sluggish for the user * Snap to grid worked incorrectly, did not pick closest grid position
-rw-r--r--src/server/connectionframe/connectionframe.cpp45
-rw-r--r--src/server/connectionframe/connectionframe.h26
-rw-r--r--src/server/mainwindow/mainwindow.cpp162
-rw-r--r--src/server/mainwindow/mainwindow.h8
4 files changed, 137 insertions, 104 deletions
diff --git a/src/server/connectionframe/connectionframe.cpp b/src/server/connectionframe/connectionframe.cpp
index 90d72da..205433b 100644
--- a/src/server/connectionframe/connectionframe.cpp
+++ b/src/server/connectionframe/connectionframe.cpp
@@ -15,6 +15,7 @@
#include "connectionframe.h"
+#include "../mainwindow/mainwindow.h"
#include "../net/client.h"
#include <QPixmap>
#include <QImage>
@@ -59,14 +60,17 @@ static QString style_disconnected(
static QIcon *term = NULL, *cam = NULL, *eye = NULL, *lock = NULL;
+bool ConnectionFrame::paintDisabled = false;
+
/**
* 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), _isSelected(false), _isTutor(false)
+ConnectionFrame::ConnectionFrame(MainWindow* main, QWidget *parent) :
+ QGroupBox(parent), _client(NULL), _timerId(0), _timerCounter(0), _isSelected(false), _isTutor(false),
+ _mainWindow(main)
{
//defines the ui-stuff
@@ -116,7 +120,6 @@ ConnectionFrame::ConnectionFrame(QWidget *parent, int width, int height) :
_mainLayout->addWidget(_lblUserName);
_mainLayout->addWidget(_lblHostName);
this->setLayout(_mainLayout);
- this->setSize(width, height);
this->updateAppearance();
this->updateLabels();
}
@@ -129,6 +132,25 @@ ConnectionFrame::~ConnectionFrame()
_iconLayout->deleteLater();
}
+void ConnectionFrame::setGridPosition(const QPoint& pos)
+{
+ _gridPosition = pos;
+ updateGeometry();
+}
+
+void ConnectionFrame::setGridPosition(int x, int y)
+{
+ setGridPosition(QPoint(x, y));
+}
+
+void ConnectionFrame::updateGeometry()
+{
+ const QRect rect = _mainWindow->calcFrameGeometry(this);
+ setGeometry(rect);
+ if (this->_client == NULL)
+ showDefaultThumb();
+}
+
/**
* Add icon to connection frame.
* @param icon
@@ -145,18 +167,6 @@ QLabel* ConnectionFrame::addIcon(const QIcon* icon)
}
/**
- * 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
@@ -216,7 +226,7 @@ void ConnectionFrame::mouseReleaseEvent(QMouseEvent* event)
QApplication::setOverrideCursor(QCursor(Qt::OpenHandCursor));
// Only recognize a move if the distance is larger than _startDragDistance
if ((this->pos() - _previousPosition).manhattanLength() > _startDragDistance ) {
- emit frameMoved(true, this);
+ emit frameMoved(this);
} else {
qDebug("Clicked");
move(_previousPosition);
@@ -292,6 +302,9 @@ void ConnectionFrame::mouseDoubleClickEvent(QMouseEvent* event)
*/
void ConnectionFrame::paintEvent(QPaintEvent *event)
{
+ if (ConnectionFrame::paintDisabled) {
+ return;
+ }
QGroupBox::paintEvent(event);
if (_remoteScreen.isNull()) {
return;
diff --git a/src/server/connectionframe/connectionframe.h b/src/server/connectionframe/connectionframe.h
index 9d86c70..2549ae8 100644
--- a/src/server/connectionframe/connectionframe.h
+++ b/src/server/connectionframe/connectionframe.h
@@ -3,6 +3,8 @@
#include <QtGui>
#include "../net/client.h"
+class MainWindow;
+
/**
* Class for representing the clients of current session, with a specific frame
* displaying username and hostname for each one.
@@ -29,11 +31,8 @@ private:
QPoint _clickPoint;
QPoint _previousPosition;
- QPoint _currentPosition;
-
QPoint _gridPosition;
-
Client *_client;
int _timerId, _timerCounter;
@@ -45,22 +44,25 @@ private:
void showDefaultThumb();
QLabel* addIcon(const QIcon* icon);
+ MainWindow *_mainWindow;
+
public:
- ConnectionFrame(QWidget* parent, int width, int height);
+
+ static bool paintDisabled;
+
+ ConnectionFrame(MainWindow* main, QWidget* parent);
virtual ~ConnectionFrame();
+ const inline QPoint getGridPosition() const { return _gridPosition; }
+ void setGridPosition(int x, int y);
+ void setGridPosition(const QPoint& pos);
+ void updateGeometry();
+
const QPixmap& getFramePixmap() const { return _remoteScreen; }
- void setSize(int width, int height);
- const inline QPoint& getPreviousPosition() const { return _previousPosition; }
void assignClient(Client *client);
void setSelection(bool selected);
const inline bool isSelected() const { return _isSelected; }
- inline void setGridPosition(QPoint pos) { _gridPosition = pos; }
- inline QPoint getGridPosition() const { return _gridPosition; };
- const inline void setCurrentPosition(QPoint position) { _currentPosition = position; }
- const inline QPoint& getCurrentPosition() const { return _currentPosition; }
-
const QString& computerId() const { return _computerId; }
void setComputerId(QString computerId) { if (_client != NULL) return; _computerId = computerId; updateLabels(); }
Client* client() const { return _client; }
@@ -79,7 +81,7 @@ protected:
void timerEvent(QTimerEvent* event);
signals:
- void frameMoved(bool activateTrash, ConnectionFrame* frame);
+ void frameMoved(ConnectionFrame* frame);
void doubleClicked(ConnectionFrame* frame);
void clicked(ConnectionFrame* frame);
diff --git a/src/server/mainwindow/mainwindow.cpp b/src/server/mainwindow/mainwindow.cpp
index cb2e4da..87ecca4 100644
--- a/src/server/mainwindow/mainwindow.cpp
+++ b/src/server/mainwindow/mainwindow.cpp
@@ -217,25 +217,23 @@ MainWindow::~MainWindow()
delete ui;
}
-/** Euclidean distance (why is this not implemented in QPoint?) */
-float distance(QPoint a, QPoint b)
+/** Squared euclidean distance (why is this not implemented in QPoint?) */
+int distance(QPoint a, QPoint b)
{
- int dx = a.x() - b.x();
- int dy = a.y() - b.y();
- int sum = dx * dx + dy * dy;
- return sqrt((float) sum);
+ const int dx = a.x() - b.x();
+ const int dy = a.y() - b.y();
+ const int sum = dx * dx + dy * dy;
+ return sum;
}
-float distance(QPointF a, QPointF b)
+int distance(QPointF a, QPointF b)
{
- int dx = a.x() - b.x();
- int dy = a.y() - b.y();
- int sum = dx * dx + dy * dy;
- return sqrt(sum);
+ const int dx = a.x() - b.x();
+ const int dy = a.y() - b.y();
+ const int sum = dx * dx + dy * dy;
+ return sum;
}
-
-
/***************************************************************************//**
* \brief: find the closest available frame.
*
@@ -251,6 +249,14 @@ float distance(QPointF a, QPointF b)
*/
QPoint MainWindow::closestFreeSlot(QPoint preferredPixels, ConnectionFrame* toIgnore)
{
+ const bool pickFirstOne = ( preferredPixels == QPoint(-1, -1) );
+ if (!pickFirstOne && toIgnore != NULL) {
+ // Check if we're already in the desired location and skip all the checks
+ QPoint desired = QPoint(preferredPixels.x() / getTileWidthPx(), preferredPixels.y() / getTileHeightPx());
+ if (desired == toIgnore->getGridPosition()) {
+ return desired;
+ }
+ }
const QSize& clientSize = serverApp->getCurrentRoom()->clientSize;
bool grid[_tilesX][_tilesY];
memset(grid, 0, sizeof(bool) * _tilesX * _tilesY); /* set everything to false */
@@ -260,7 +266,7 @@ QPoint MainWindow::closestFreeSlot(QPoint preferredPixels, ConnectionFrame* toIg
if (*it == toIgnore) { continue; }
- const QPoint& p = (*it)->getGridPosition();
+ const QPoint p = (*it)->getGridPosition();
for (int x = p.x(); x < p.x() + clientSize.width(); x++) {
for (int y = p.y(); y < p.y() + clientSize.height(); y++) {
@@ -283,18 +289,23 @@ QPoint MainWindow::closestFreeSlot(QPoint preferredPixels, ConnectionFrame* toIg
}
}
}
-endLoop:
- if (isFree) { freePositions << QPoint(x, y); }
+endLoop: ;
+ if (isFree) {
+ freePositions << QPoint(x, y);
+ if (pickFirstOne) {
+ goto endSearch;
+ }
+ }
}
}
+endSearch: ;
/* among all the free positions, find the closest */
- float min_distance = 10000;
- QPoint bestPosition = QPoint(-1, -1);
+ float min_distance = 1000000;
+ QPoint bestPosition = QPoint(0, 0);
for (QPoint freePos : freePositions) {
- QPoint freePosCenter( freePos.x() * getTileWidthPx() + getTileWidthPx() * clientSize.width() / 2,
- freePos.y() * getTileHeightPx() + getTileHeightPx() * clientSize.height() / 2);
- float dist = distance(freePosCenter, preferredPixels);
+ const QPoint freePosPx( freePos.x() * getTileWidthPx(), freePos.y() * getTileHeightPx() );
+ const float dist = distance(freePosPx, preferredPixels);
if (dist < min_distance) {
min_distance = dist;
bestPosition = freePos;
@@ -307,10 +318,7 @@ endLoop:
void MainWindow::placeFrameInFreeSlot(ConnectionFrame* frame, QPoint preferredPixels)
{
QPoint bestPosition = closestFreeSlot(preferredPixels, frame);
-
frame->setGridPosition(bestPosition);
- QPoint freePosPx(bestPosition.x() * getTileWidthPx(), bestPosition.y() * getTileHeightPx());
- frame->setCurrentPosition(freePosPx);
}
/***************************************************************************//**
@@ -321,14 +329,12 @@ void MainWindow::placeFrameInFreeSlot(ConnectionFrame* frame, QPoint preferredPi
*/
ConnectionFrame* MainWindow::createFrame()
{
- // Allocate and resize
- int width = getTileWidthPx() * serverApp->getCurrentRoom()->clientSize.width();
- int height = getTileHeightPx() * serverApp->getCurrentRoom()->clientSize.height();
-
- ConnectionFrame *cf = new ConnectionFrame(ui->frmRoom, width, height);
+ ConnectionFrame *cf = new ConnectionFrame(this, ui->frmRoom);
+ // Move to any free tile
+ placeFrameInFreeSlot(cf);
_clientFrames.append(cf);
cf->show();
- connect(cf, SIGNAL(frameMoved(bool, ConnectionFrame *)), this, SLOT(onPlaceFrame(bool, ConnectionFrame *)));
+ connect(cf, SIGNAL(frameMoved(ConnectionFrame *)), this, SLOT(onPlaceFrame(ConnectionFrame *)));
connect(cf, SIGNAL(clicked(ConnectionFrame *)), this, SLOT(onFrameClicked(ConnectionFrame *)));
return cf;
}
@@ -339,20 +345,14 @@ ConnectionFrame* MainWindow::createFrame()
* Also connect signals frameMoved() and clicked() with slots.
* @return ConnectionFrame*
*/
-ConnectionFrame* MainWindow::createFrame(QString computerId, QPoint pxCoord, QPoint gridPosition)
+ConnectionFrame* MainWindow::createFrame(QString computerId, QPoint gridPosition)
{
- // Allocate and resize
- const Room* room = serverApp->getCurrentRoom();
- int width = getTileWidthPx() * (room == NULL ? 1 : room->clientSize.width());
- int height = getTileHeightPx() * (room == NULL ? 1 : room->clientSize.height());
-
- ConnectionFrame *cf = new ConnectionFrame(ui->frmRoom, width, height);
+ ConnectionFrame *cf = new ConnectionFrame(this, ui->frmRoom);
cf->setComputerId(computerId);
- cf->setCurrentPosition(pxCoord);
cf->setGridPosition(gridPosition);
_clientFrames.append(cf);
cf->show();
- connect(cf, SIGNAL(frameMoved(bool, ConnectionFrame *)), this, SLOT(onPlaceFrame(bool, ConnectionFrame *)));
+ connect(cf, SIGNAL(frameMoved(ConnectionFrame *)), this, SLOT(onPlaceFrame(ConnectionFrame *)));
connect(cf, SIGNAL(clicked(ConnectionFrame *)), this, SLOT(onFrameClicked(ConnectionFrame *)));
return cf;
}
@@ -480,41 +480,54 @@ AspectStatus checkAspectRatio(const QSize& frameSize, const QSize& gridSize)
*/
void MainWindow::resizeEvent(QResizeEvent* e)
{
- const Room* room = serverApp->getCurrentRoom();
- const QSize& clientSize = room->clientSize;
-
- if (ui->frmRoom->size().width() < 100 || ui->frmRoom->size().height() < 100 || _tilesX <= 0 || _tilesY <= 0) { return; }
+ if (ui->frmRoom->size().width() < 100 || ui->frmRoom->size().height() < 100) {
+ return;
+ }
+ const Room* room = serverApp->getCurrentRoom();
QSize newGridSize = room->gridSize;
+ const QSize& clientSize = room->clientSize;
- /* do we have to add virtual columns? */
- while (checkAspectRatio(ui->frmRoom->size(), newGridSize) == GRID_TOO_WIDE) {
- /* add row */
- newGridSize.setHeight(newGridSize.height() + 1);
- }
- while (checkAspectRatio(ui->frmRoom->size(), newGridSize) == GRID_TOO_TALL) {
- /* add column */
- newGridSize.setWidth(newGridSize.width() + 1);
+ // Check if any frames have been moved beyond the room dimensions
+ for (auto it = _clientFrames.begin(); it != _clientFrames.end(); ++it) {
+ QPoint bounds = (*it)->getGridPosition();
+ while (bounds.x() + clientSize.width() > newGridSize.width()) {
+ newGridSize += QSize(1, 0);
+ }
+ while (bounds.y() + clientSize.height() > newGridSize.height()) {
+ newGridSize += QSize(0, 1);
+ }
}
+
+ /* do we have to add virtual columns or rows? */
+ AspectStatus status;
+ do {
+ status = checkAspectRatio(ui->frmRoom->size(), newGridSize);
+ if (status == GRID_TOO_WIDE) {
+ /* add row */
+ newGridSize += QSize(0, 1);
+ }
+ if (status == GRID_TOO_TALL) {
+ /* add column */
+ newGridSize += QSize(1, 0);
+ }
+ } while (status != GRID_OK);
this->_tilesX = newGridSize.width();
this->_tilesY = newGridSize.height();
+ const int maxX = _tilesX - clientSize.width();
+ const int maxY = _tilesY - clientSize.height();
/* Bring back frames which are now out of the screen */
for (auto it = _clientFrames.begin(); it != _clientFrames.end(); ++it) {
const QPoint gp = (*it)->getGridPosition();
- if ( gp.x() >= _tilesX || gp.y() >= _tilesY ) {
- placeFrameInFreeSlot(*it, (*it)->getCurrentPosition());
+ if ( gp.x() > maxX || gp.y() > maxY ) {
+ placeFrameInFreeSlot(*it, (*it)->pos());
}
}
/* Resize all connection windows */
for (auto it = _clientFrames.begin(); it != _clientFrames.end(); ++it) {
- int newPosX = (*it)->getGridPosition().x() * getTileWidthPx();
- int newPosY = (*it)->getGridPosition().y() * getTileHeightPx();
- QPoint newPos(newPosX, newPosY);
-
- (*it)->setSize(getTileWidthPx() * clientSize.width(), getTileHeightPx() * clientSize.height());
- (*it)->move(newPos);
+ (*it)->updateGeometry();
}
/* update background image label */
@@ -607,13 +620,13 @@ void MainWindow::reset()
* Place frame to from user specified position. Should be called when a
* connectionFrame is dropped during the "drag-n-drop".
*/
-void MainWindow::onPlaceFrame(bool activateTrash, ConnectionFrame* connectionFrame)
+void MainWindow::onPlaceFrame(ConnectionFrame* connectionFrame)
{
// if (_tilesX <= 0 || _tilesY <= 0) return;
- const QPoint &preferredPixels = connectionFrame->frameGeometry().center();
+ const QPoint preferredPixels = connectionFrame->pos();
placeFrameInFreeSlot(connectionFrame, preferredPixels);
- resizeEvent(NULL);
+ //resizeEvent(NULL);
}
/***************************************************************************//**
@@ -737,11 +750,9 @@ void MainWindow::reloadCurrentRoom()
for (auto it = room->clientPositions.begin(); it != room->clientPositions.end(); ++it) {
QString computerId = it.key();
QPoint pos = it.value();
- QPoint pxPos(pos.x() * getTileWidthPx(), pos.y() * getTileHeightPx());
- ConnectionFrame *cf = createFrame(computerId, pxPos, pos);
- cf->move(cf->getCurrentPosition());
- onPlaceFrame(false, cf);
+ ConnectionFrame *cf = createFrame(computerId, pos);
+ onPlaceFrame(cf);
if (computerId == room->tutorIP) {
qDebug() << "set computer with id " << computerId << " as tutor per configuration";
if (getTutorFrame() != NULL) {
@@ -808,13 +819,24 @@ void MainWindow::onReloadRoomOk()
int MainWindow::getTileWidthPx() const
{
+
return ui->frmRoom->size().width() / _tilesX;
}
+
int MainWindow::getTileHeightPx() const
{
return ui->frmRoom->size().height() / _tilesY;
}
+QRect MainWindow::calcFrameGeometry(ConnectionFrame* frame) const
+{
+ const QPoint pos = frame->getGridPosition();
+ const QSize& clientSize = serverApp->getCurrentRoom()->clientSize;
+ const int w = getTileWidthPx();
+ const int h = getTileHeightPx();
+ return QRect(pos.x() * w, pos.y() * h, w * clientSize.width(), h * clientSize.height());
+}
+
/***************************************************************************//**
* Display popup which explains possible actions about the buttons.
*/
@@ -1133,12 +1155,10 @@ void MainWindow::onClientAuthenticated(Client* client)
// New one, create
ConnectionFrame *cf = createFrame();
- // Move to any free tile
- placeFrameInFreeSlot(cf);
// Assign client instance
cf->assignClient(client);
- resizeEvent(NULL); // This is where all the positioning should be
+ //resizeEvent(NULL); // This is where all the positioning should be
tellClientCurrentSituation(client);
updateExamMode();
@@ -1276,10 +1296,6 @@ void MainWindow::onDeleteClient()
lockContextButtons();
updateExamMode();
return;
- } else {
- frame->move(frame->getPreviousPosition());
- updateExamMode();
- return;
}
}
diff --git a/src/server/mainwindow/mainwindow.h b/src/server/mainwindow/mainwindow.h
index b0ad498..988ac50 100644
--- a/src/server/mainwindow/mainwindow.h
+++ b/src/server/mainwindow/mainwindow.h
@@ -30,6 +30,8 @@ public:
MainWindow(QWidget *parent = 0);
~MainWindow();
+ QRect calcFrameGeometry(ConnectionFrame* frame) const;
+
private:
// Ui stuff
@@ -75,9 +77,9 @@ private:
DiscoveryListener *_discoveryListener;
QPoint closestFreeSlot(QPoint preferredPixels, ConnectionFrame* toIgnore);
- void placeFrameInFreeSlot(ConnectionFrame* frame, QPoint preferred = QPoint(0, 0));
+ void placeFrameInFreeSlot(ConnectionFrame* frame, QPoint preferred = QPoint(-1, -1));
ConnectionFrame* createFrame();
- ConnectionFrame* createFrame(QString computerId, QPoint position, QPoint gridPosition);
+ ConnectionFrame* createFrame(QString computerId, QPoint gridPosition);
void savePosition(ConnectionFrame *cf);
void startVncServerIfNecessary(int from);
void tellClientCurrentSituation(Client* client);
@@ -122,7 +124,7 @@ protected slots:
void DisableButtons();
void EnableButtons();
// connection frame
- void onPlaceFrame(bool activateTrash, ConnectionFrame* frame);
+ void onPlaceFrame(ConnectionFrame* frame);
void onFrameClicked(ConnectionFrame* frame);
// Net
void onClientConnected(Client* client);