summaryrefslogtreecommitdiffstats
path: root/src/server/mainwindow/mainwindow.cpp
diff options
context:
space:
mode:
authorSimon Rettberg2016-11-02 19:24:07 +0100
committerSimon Rettberg2016-11-02 19:24:07 +0100
commit9d73e385153656ef998cc8f6378bb01ff36b2090 (patch)
treee73108ab31a56bd310af25b9e0623378480fb2bd /src/server/mainwindow/mainwindow.cpp
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
Diffstat (limited to 'src/server/mainwindow/mainwindow.cpp')
-rw-r--r--src/server/mainwindow/mainwindow.cpp162
1 files changed, 89 insertions, 73 deletions
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;
}
}