/** * Insert a new widget * @param widget :: An MdiSubWindow to add. * @param row :: A row index at which to place the new tile. * @param col :: A column index at which to place the new tile. */ void TiledWindow::insertWidget(MdiSubWindow *widget, int row, int col) { int index = calcFlatIndex( row, col ); int lastRow = rowCount() - 1; int lastCol = columnCount() - 1; // if the last tile has a widget append a row if ( getWidget( lastRow, lastCol ) != NULL ) { ++lastRow; Tile *tile = getOrAddTile( lastRow, lastCol ); (void) tile; } // shift widgets towards the bottom int lastIndex = calcFlatIndex( lastRow, lastCol ); int rowTo(0), colTo(0), rowFrom(0), colFrom(0); for(int i = lastIndex; i > index; --i) { calcTilePosition( i, rowTo, colTo ); calcTilePosition( i - 1, rowFrom, colFrom ); if ( hasWidget( rowFrom, colFrom ) ) { MdiSubWindow *w = removeTile( rowFrom, colFrom ); addWidget( w, rowTo, colTo ); } } addWidget( widget, row, col ); }
/** * Add a new sub-window at a given position in the layout. * The row and column indices do not have to be within the current shape - * it will change accordingly. * @param widget :: An MdiSubWindow to add. * @param row :: A row index at which to place the new tile. * @param col :: A column index at which to place the new tile. */ void TiledWindow::addWidget(MdiSubWindow *widget, int row, int col) { try { Tile *tile = getOrAddTile(row, col); // prepare the cell m_layout->setColumnMinimumWidth(col, minimumTileWidth); m_layout->setRowMinimumHeight(row, minimumTileHeight); m_layout->setColumnStretch(col, 1); // detach the widget from ApplicationWindow widget->detach(); // widget must have it's parent widget->setParent(this); // disable mouse events widget->setAttribute(Qt::WA_TransparentForMouseEvents, true); // attach it to this window tile->setWidget(widget); connect(widget, SIGNAL(detachFromParent(MdiSubWindow *)), this, SLOT(removeWidget(MdiSubWindow *))); connect(widget, SIGNAL(closedWindow(MdiSubWindow *)), this, SLOT(removeWidget(MdiSubWindow *))); // fill possible empty spaces with Tiles tileEmptyCells(); } catch (std::invalid_argument &ex) { QMessageBox::critical(this, "MantidPlot- Error", "Cannot add a widget to a TiledWindow:\n\n" + QString::fromStdString(ex.what())); sendWidgetTo(widget, Default); } }
/** * Re-arrange the tiles according to a new layout shape. * @param newColumnCount :: A new number of columns in the layout. */ void TiledWindow::reshape(int newColumnCount) { if ( newColumnCount < 1 ) { throw std::invalid_argument("Number of columns in a TiledWindow cannot be less than 1."); } clearSelection(); int nrows = rowCount(); int ncols = columnCount(); // remove all widgets and store their pointers QList<MdiSubWindow*> widgets; for(int row = 0; row < nrows; ++row) { for(int col = 0; col < ncols; ++col) { Tile *tile = getTile(row,col); MdiSubWindow *widget = tile->widget(); if ( widget != NULL ) { tile->removeWidget(); widgets.append( widget ); } } } int nWidgets = widgets.size(); if ( nWidgets < newColumnCount ) { newColumnCount = nWidgets; } if ( newColumnCount == 0 ) return; // clear the layout init(1,1); // make sure new dimensions will fit all widgets int newRowCount = nWidgets / newColumnCount; if ( newRowCount * newColumnCount != nWidgets ) { newRowCount += 1; } // set up the new layout by putting in an empty tile at the top-right corner // m_layout now knows its rowCount and columnCount and calcTilePosition can be used Tile *tile = getOrAddTile(newRowCount - 1, newColumnCount - 1); (void) tile; // re-insert the widgets for(int i = 0; i < nWidgets; ++i) { int row(0), col(0); calcTilePosition( i, row, col ); addWidget( widgets[i], row, col ); } }