File indexing completed on 2025-02-09 06:04:33

0001 /***************************************************************************
0002  * SPDX-FileCopyrightText: 2022 S. MANKOWSKI stephane@mankowski.fr
0003  * SPDX-FileCopyrightText: 2022 G. DE BURE support@mankowski.fr
0004  * SPDX-License-Identifier: GPL-3.0-or-later
0005  ***************************************************************************/
0006 /** @file
0007  * A dashboard widget
0008  *
0009  * @author Stephane MANKOWSKI
0010  */
0011 #include "skgdashboardwidget.h"
0012 
0013 #include <kaboutdata.h>
0014 #include <kservice.h>
0015 #include <ktitlewidget.h>
0016 
0017 #include <qdom.h>
0018 #include <qdrag.h>
0019 #include <qevent.h>
0020 #include <qmenu.h>
0021 #include <qmimedata.h>
0022 #include <qgridlayout.h>
0023 
0024 #include "skgboardwidget.h"
0025 #include "skgdocument.h"
0026 #include "skgflowlayout.h"
0027 #include "skginterfaceplugin.h"
0028 #include "skgmainpanel.h"
0029 #include "skgservices.h"
0030 #include "skgtraces.h"
0031 #include "skgzoomselector.h"
0032 #include "skgdashboardplugin.h"
0033 
0034 SKGDashboardWidget::SKGDashboardWidget(QWidget* iParent, SKGDocument* iDocument, QMenu* iMenu)
0035     : SKGWidget(iParent, iDocument), m_flowLayout(nullptr), m_menu(nullptr), m_addMenu(nullptr),
0036       m_layoutF(nullptr), m_layout1(nullptr), m_layout2(nullptr), m_layout3(nullptr), m_layout4(nullptr), m_content(nullptr), m_layout(0)
0037 {
0038     SKGTRACEINFUNC(1)
0039     if (iDocument == nullptr) {
0040         return;
0041     }
0042 
0043     if (iMenu) {
0044         m_addMenu = iMenu;
0045     } else {
0046         // Create a context menu for adding widgets
0047         setContextMenuPolicy(Qt::CustomContextMenu);
0048 
0049         m_menu = new QMenu(this);
0050         setContextMenuPolicy(Qt::CustomContextMenu);
0051         m_menu = new QMenu(this);
0052 
0053         connect(this, &SKGDashboardWidget::customContextMenuRequested, this, &SKGDashboardWidget::showHeaderMenu);
0054         m_addMenu = m_menu->addMenu(SKGServices::fromTheme(QStringLiteral("configure")),  i18nc("Verb", "Configure the dashboard"));
0055     }
0056 
0057     auto verticalLayout = new QVBoxLayout(this);
0058     verticalLayout->setSpacing(2);
0059 
0060     if (!iMenu) {
0061         auto horizontalLayout = new QHBoxLayout();
0062         horizontalLayout->setSpacing(2);
0063 
0064         auto kTitle = new KTitleWidget(this);
0065         kTitle->setIcon(QApplication::windowIcon(), KTitleWidget::ImageLeft);
0066 #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
0067         kTitle->setIconSize(QSize(32, 32));
0068 #endif
0069 
0070         kTitle->setText(i18nc("Message", "Welcome to %1", KAboutData::applicationData().displayName()));
0071         kTitle->setLevel(1);
0072 
0073         horizontalLayout->addWidget(kTitle);
0074 
0075         auto kAddWidget = new QToolButton(this);
0076         QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
0077         sizePolicy.setHorizontalStretch(0);
0078         sizePolicy.setVerticalStretch(0);
0079         sizePolicy.setHeightForWidth(kAddWidget->sizePolicy().hasHeightForWidth());
0080         kAddWidget->setSizePolicy(sizePolicy);
0081         kAddWidget->setFocusPolicy(Qt::NoFocus);
0082         kAddWidget->setCheckable(false);
0083         kAddWidget->setChecked(false);
0084         kAddWidget->setAutoRaise(true);
0085 
0086         horizontalLayout->addWidget(kAddWidget);
0087 
0088         verticalLayout->addLayout(horizontalLayout);
0089 
0090         auto kContainer = new QScrollArea(this);
0091         kContainer->setFrameShape(QFrame::NoFrame);
0092         kContainer->setWidgetResizable(true);
0093         kContainer->setAlignment(Qt::AlignLeading | Qt::AlignLeft | Qt::AlignTop);
0094         m_content = new QWidget();
0095         m_content->setGeometry(QRect(0, 0, 601, 237));
0096         kContainer->setWidget(m_content);
0097 
0098         verticalLayout->addWidget(kContainer);
0099 
0100         // Plug buttons with menus
0101         if ((m_addMenu != nullptr) && (kAddWidget != nullptr)) {
0102             kAddWidget->setIcon(m_addMenu->icon());
0103             kAddWidget->setMenu(m_addMenu);
0104             kAddWidget->setPopupMode(QToolButton::InstantPopup);
0105         }
0106     } else {
0107         m_content = new QWidget();
0108         m_content->setGeometry(QRect(0, 0, 601, 237));
0109 
0110         verticalLayout->addWidget(m_content);
0111     }
0112 
0113     // Drag and drop
0114     m_clickedPoint = QPoint(-1, -1);
0115 
0116     // Build menu
0117     if (m_addMenu != nullptr) {
0118         // Add layouts sub menu
0119         auto layoutMenu = m_addMenu->addMenu(SKGServices::fromTheme(QStringLiteral("labplot-editbreaklayout")),  i18nc("Verb", "Choose layout …"));
0120         auto alignmentGroup = new QActionGroup(this);
0121         {
0122             m_layoutF = layoutMenu->addAction(i18nc("Verb", "Flow"));
0123             if (m_layoutF != nullptr) {
0124                 m_layoutF->setIcon(SKGServices::fromTheme(QStringLiteral("text-flow-into-frame")));
0125                 m_layoutF->setCheckable(true);
0126                 m_layoutF->setData(0);
0127                 connect(m_layoutF, &QAction::triggered, this, &SKGDashboardWidget::onChangeLayout);
0128 
0129                 alignmentGroup->addAction(m_layoutF);
0130             }
0131         }
0132         {
0133             m_layout1 = layoutMenu->addAction(i18nc("Verb", "1 column"));
0134             if (m_layout1 != nullptr) {
0135                 m_layout1->setIcon(SKGServices::fromTheme(QStringLiteral("object-columns")));
0136                 m_layout1->setCheckable(true);
0137                 m_layout1->setData(1);
0138                 connect(m_layout1, &QAction::triggered, this, &SKGDashboardWidget::onChangeLayout);
0139 
0140                 alignmentGroup->addAction(m_layout1);
0141             }
0142         }
0143         {
0144             m_layout2 = layoutMenu->addAction(i18nc("Verb", "2 columns"));
0145             if (m_layout2 != nullptr) {
0146                 m_layout2->setIcon(SKGServices::fromTheme(QStringLiteral("object-columns")));
0147                 m_layout2->setCheckable(true);
0148                 m_layout2->setData(2);
0149                 connect(m_layout2, &QAction::triggered, this, &SKGDashboardWidget::onChangeLayout);
0150 
0151                 alignmentGroup->addAction(m_layout2);
0152             }
0153         }
0154         {
0155             m_layout3 = layoutMenu->addAction(i18nc("Verb", "3 columns"));
0156             if (m_layout3 != nullptr) {
0157                 m_layout3->setIcon(SKGServices::fromTheme(QStringLiteral("object-columns")));
0158                 m_layout3->setCheckable(true);
0159                 m_layout3->setData(3);
0160                 connect(m_layout3, &QAction::triggered, this, &SKGDashboardWidget::onChangeLayout);
0161 
0162                 alignmentGroup->addAction(m_layout3);
0163             }
0164         }
0165         {
0166             m_layout4 = layoutMenu->addAction(i18nc("Verb", "4 columns"));
0167             if (m_layout4 != nullptr) {
0168                 m_layout4->setIcon(SKGServices::fromTheme(QStringLiteral("object-columns")));
0169                 m_layout4->setCheckable(true);
0170                 m_layout4->setData(4);
0171                 connect(m_layout4, &QAction::triggered, this, &SKGDashboardWidget::onChangeLayout);
0172 
0173                 alignmentGroup->addAction(m_layout4);
0174             }
0175         }
0176         if (m_layoutF) {
0177             m_layoutF->setChecked(true);
0178         }
0179         auto sep = new QAction(m_addMenu);
0180         sep->setSeparator(true);
0181         m_addMenu->addAction(sep);
0182 
0183         int index = 0;
0184         int added = 0;
0185         auto currentMenu = m_addMenu;
0186         while (index >= 0) {
0187             SKGInterfacePlugin* plugin = SKGMainPanel::getMainPanel()->getPluginByIndex(index);
0188             if (plugin != nullptr) {
0189                 int nbdbw = plugin->getNbDashboardWidgets();
0190                 for (int j = 0; j < nbdbw; ++j) {
0191                     added++;
0192                     if (added % 10 == 0) {
0193                         currentMenu = currentMenu->addMenu(SKGServices::fromTheme(QStringLiteral("list-add")),  i18nc("Verb", "More …"));
0194                     }
0195 
0196                     // Create menu
0197                     QAction* act = currentMenu->addAction(plugin->getDashboardWidgetTitle(j));
0198                     if (act != nullptr) {
0199                         act->setIcon(SKGServices::fromTheme(plugin->icon()));
0200                         act->setData(QString(plugin->objectName() % '-' % SKGServices::intToString(j)));
0201 
0202                         connect(act, &QAction::triggered, this, &SKGDashboardWidget::onAddWidget);
0203                     }
0204                 }
0205             } else {
0206                 index = -2;
0207             }
0208             ++index;
0209         }
0210     }
0211 
0212     // Build layout
0213     m_flowLayout = new SKGFlowLayout(m_content, 0, 0, 0);
0214 }
0215 
0216 SKGDashboardWidget::~SKGDashboardWidget()
0217 {
0218     SKGTRACEINFUNC(1)
0219     m_menu = nullptr;
0220     m_addMenu = nullptr;
0221     m_flowLayout = nullptr;
0222     m_layoutF = nullptr;
0223     m_layout1 = nullptr;
0224     m_layout2 = nullptr;
0225     m_layout3 = nullptr;
0226     m_layout4 = nullptr;
0227     m_content = nullptr;
0228 }
0229 
0230 QString SKGDashboardWidget::getState()
0231 {
0232     SKGTRACEINFUNC(10)
0233     QDomDocument doc(QStringLiteral("SKGML"));
0234     QDomElement root = doc.createElement(QStringLiteral("parameters"));
0235     doc.appendChild(root);
0236     root.setAttribute(QStringLiteral("layout"), m_layout);
0237 
0238     int nb = m_items.count();
0239     for (int i = 0; i < nb; ++i) {
0240         QDomElement element = doc.createElement("ITEM-" % SKGServices::intToString(i + 1));
0241         root.appendChild(element);
0242 
0243         QStringList param = SKGServices::splitCSVLine(m_items.at(i), '-');
0244         SKGBoardWidget* item = m_itemsPointers.at(i);
0245         if (item != nullptr) {
0246             element.setAttribute(QStringLiteral("name"), param.at(0));
0247             element.setAttribute(QStringLiteral("index"), param.at(1));
0248             element.setAttribute(QStringLiteral("state"), item->getState());
0249             element.setAttribute(QStringLiteral("zoom"), SKGServices::intToString(item->getZoomRatio() * 5 - 15));
0250         }
0251     }
0252     return doc.toString();
0253 }
0254 
0255 void SKGDashboardWidget::setState(const QString& iState)
0256 {
0257     SKGTRACEINFUNC(10)
0258 
0259     QDomDocument doc(QStringLiteral("SKGML"));
0260     doc.setContent(iState);
0261     QDomElement root = doc.documentElement();
0262 
0263     QString layout = root.attribute(QStringLiteral("layout"));
0264     if (!layout.isEmpty()) {
0265         m_layout = SKGServices::stringToInt(layout);
0266     }
0267 
0268     // Initialisation
0269     int nb = (m_flowLayout != nullptr ? m_flowLayout->count() : 0);
0270     for (int i = 0; i < nb; ++i) {
0271         SKGBoardWidget* item = m_itemsPointers.at(0);
0272         if (item != nullptr) {
0273             m_flowLayout->removeWidget(item);
0274             item->hide();
0275 
0276             m_items.removeAt(0);
0277             m_itemsPointers.removeAt(0);
0278 
0279             item->deleteLater();
0280         }
0281     }
0282 
0283     // Create new layout
0284     if (m_flowLayout) {
0285         delete m_flowLayout;
0286     }
0287     if (m_layout == 0) {
0288         m_flowLayout = new SKGFlowLayout(m_content, 0, 0, 0);
0289     } else {
0290         m_flowLayout = new QGridLayout(m_content);
0291     }
0292     m_content->setLayout(m_flowLayout);
0293 
0294     int index = 1;
0295     while (index > 0) {
0296         QDomElement element = root.firstChildElement("ITEM-" % SKGServices::intToString(index));
0297         if (!element.isNull()) {
0298             SKGInterfacePlugin* plugin = SKGMainPanel::getMainPanel()->getPluginByName(element.attribute(QStringLiteral("name")));
0299             QString indexString = element.attribute(QStringLiteral("index"));
0300             if (indexString.isEmpty()) {
0301                 indexString = '0';
0302             }
0303             QString zoom = element.attribute(QStringLiteral("zoom"));
0304             if (zoom.isEmpty()) {
0305                 zoom = '0';
0306             }
0307             if (plugin != nullptr) {
0308                 addItem(plugin, SKGServices::stringToInt(indexString), SKGServices::stringToInt(zoom), element.attribute(QStringLiteral("state")));
0309             }
0310         } else {
0311             index = -1;
0312         }
0313         ++index;
0314     }
0315 
0316     // In case of reset
0317     if (m_items.isEmpty() && root.attribute(QStringLiteral("zoomPosition")).isEmpty()) {
0318         int index2 = 0;
0319         while (index2 >= 0) {
0320             SKGInterfacePlugin* plugin = SKGMainPanel::getMainPanel()->getPluginByIndex(index2);
0321             if (plugin != nullptr && dynamic_cast<SKGDashboardPlugin*>(plugin) == nullptr) {
0322                 int nb2 = plugin->getNbDashboardWidgets();
0323                 for (int j = 0; j < nb2; ++j) {
0324                     addItem(plugin, j);
0325                 }
0326             } else {
0327                 index2 = -2;
0328             }
0329             ++index2;
0330         }
0331     }
0332 }
0333 
0334 QList< QWidget* > SKGDashboardWidget::printableWidgets()
0335 {
0336     QList< QWidget* > output;
0337     output.reserve(m_itemsPointers.count());
0338     for (auto w : qAsConst(m_itemsPointers)) {
0339         output.push_back(w);
0340     }
0341 
0342     return output;
0343 }
0344 
0345 bool SKGDashboardWidget::eventFilter(QObject* iObject, QEvent* iEvent)
0346 {
0347     if ((iEvent != nullptr) && iEvent->type() == QEvent::HoverLeave) {
0348         // Leave widget
0349         m_timer.stop();
0350         return true;
0351     }
0352 
0353     if ((iEvent != nullptr) && (iObject != nullptr) &&
0354         (iEvent->type() == QEvent::MouseButtonPress ||
0355          iEvent->type() == QEvent::MouseButtonRelease ||
0356          iEvent->type() == QEvent::MouseMove ||
0357          iEvent->type() == QEvent::DragEnter ||
0358          iEvent->type() == QEvent::DragMove ||
0359          iEvent->type() == QEvent::Drop ||
0360          iEvent->type() == QEvent::HoverMove)) {
0361         // Search SKGBoardWidget corresponding to this widget
0362         SKGBoardWidget* toMove = nullptr;
0363         int toMoveIndex = -1;
0364         int nb = m_itemsPointers.count();
0365         for (int i = 0; toMove == nullptr && i < nb; ++i) {
0366             SKGBoardWidget* w = m_itemsPointers.at(i);
0367             if ((w != nullptr) && w->getDragWidget() == iObject) {
0368                 toMove = w;
0369                 toMoveIndex = i;
0370             }
0371         }
0372 
0373         if (iEvent->type() == QEvent::MouseButtonPress) {
0374             // Drag
0375             auto* mevent = dynamic_cast<QMouseEvent*>(iEvent);
0376             if (mevent && mevent->button() == Qt::LeftButton) {
0377                 m_clickedPoint = mevent->pos();
0378                 m_timer.stop();
0379             }
0380         } else if (iEvent->type() == QEvent::MouseButtonRelease) {
0381             // Drag
0382             auto* mevent = dynamic_cast<QMouseEvent*>(iEvent);
0383             if (mevent && mevent->button() == Qt::LeftButton) {
0384                 m_clickedPoint = QPoint(-1, -1);
0385             }
0386         } else if (iEvent->type() == QEvent::MouseMove) {
0387             // Drag
0388             if (m_clickedPoint != QPoint(-1, -1) && toMoveIndex != -1) {
0389                 auto* mevent = dynamic_cast<QMouseEvent*>(iEvent);
0390                 if (mevent) {
0391                     int distance = (mevent->pos() - m_clickedPoint).manhattanLength();
0392                     if (distance >= QApplication::startDragDistance()) {
0393                         auto mimeData = new QMimeData;
0394                         mimeData->setData(QStringLiteral("application/x-SKGDashboardWidget"), SKGServices::intToString(toMoveIndex).toLatin1());
0395 
0396                         auto drag = new QDrag(this);
0397                         drag->setMimeData(mimeData);
0398                         drag->exec();  // krazy:exclude=crashy
0399 
0400                         return true;
0401                     }
0402                 }
0403             }
0404         } else if (iEvent->type() == QEvent::DragEnter) {
0405             // Drop move
0406             auto* devent = dynamic_cast<QDragEnterEvent*>(iEvent);
0407             if (devent && devent->mimeData()->hasFormat(QStringLiteral("application/x-SKGDashboardWidget"))) {
0408                 devent->accept();
0409 
0410                 return true;
0411             }
0412         } else if (iEvent->type() == QEvent::DragMove) {
0413             // Drop move
0414             auto* devent = dynamic_cast<QDragMoveEvent*>(iEvent);
0415             if (devent && devent->mimeData()->hasFormat(QStringLiteral("application/x-SKGDashboardWidget"))) {
0416                 int oldPos = SKGServices::stringToInt(devent->mimeData()->data(QStringLiteral("application/x-SKGDashboardWidget")));
0417                 if (oldPos != toMoveIndex) {
0418                     devent->accept();
0419                 } else {
0420                     devent->ignore();
0421                 }
0422 
0423                 return true;
0424             }
0425         } else if (iEvent->type() == QEvent::Drop) {
0426             // Drop
0427             auto* devent = dynamic_cast<QDropEvent*>(iEvent);
0428             if (devent && devent->mimeData()->hasFormat(QStringLiteral("application/x-SKGDashboardWidget"))) {
0429                 int oldPos = SKGServices::stringToInt(devent->mimeData()->data(QStringLiteral("application/x-SKGDashboardWidget")));
0430 
0431                 if (oldPos + 1 == toMoveIndex) {
0432                     ++toMoveIndex;
0433                 }
0434 
0435                 // Move item
0436                 if (toMoveIndex > oldPos) {
0437                     --toMoveIndex;
0438                 }
0439                 moveItem(oldPos, toMoveIndex);
0440 
0441                 return true;
0442             }
0443         }
0444     }
0445     return SKGWidget::eventFilter(iObject, iEvent);
0446 }
0447 
0448 void SKGDashboardWidget::showHeaderMenu(const QPoint iPos)
0449 {
0450     // Display menu
0451     if (m_menu != nullptr) {
0452         m_menu->popup(mapToGlobal(iPos));
0453     }
0454 }
0455 
0456 void SKGDashboardWidget::onAddWidget()
0457 {
0458     auto* send = qobject_cast<QAction*>(this->sender());
0459     if (send != nullptr) {
0460         QString id = send->data().toString();
0461         QStringList param = SKGServices::splitCSVLine(id, '-');
0462 
0463         SKGInterfacePlugin* db = SKGMainPanel::getMainPanel()->getPluginByName(param.at(0));
0464         if (db != nullptr) {
0465             addItem(db, SKGServices::stringToInt(param.at(1)));
0466         }
0467     }
0468 }
0469 
0470 void SKGDashboardWidget::onChangeLayout()
0471 {
0472     auto* send = qobject_cast<QAction*>(this->sender());
0473     if (send != nullptr) {
0474         m_layout = send->data().toInt();
0475         setState(getState());
0476     }
0477 }
0478 
0479 void SKGDashboardWidget::onMoveWidget(int iMove)
0480 {
0481     // Get current position
0482     QWidget* send = qobject_cast<QWidget*>(this->sender());
0483     if (send != nullptr) {
0484         int currentPos = m_itemsPointers.indexOf(parentBoardWidget(send));
0485         int newPos = currentPos + iMove;
0486         if (newPos < 0) {
0487             newPos = 0;
0488         } else if (newPos > m_items.count() - 1) {
0489             newPos = m_items.count() - 1;
0490         }
0491 
0492         moveItem(currentPos, newPos);
0493     }
0494 }
0495 
0496 void SKGDashboardWidget::moveItem(int iFrom, int iTo)
0497 {
0498     // Compute new position
0499     if (iTo != iFrom) {
0500         // Move item
0501         m_items.move(iFrom, iTo);
0502         m_itemsPointers.move(iFrom, iTo);
0503 
0504         // Build list of items in the right order
0505         QList<SKGBoardWidget*> listWidgets;
0506         int nb = m_itemsPointers.count();
0507         listWidgets.reserve(nb);
0508         for (int i = 0; i < nb; ++i) {
0509             SKGBoardWidget* wgt2 = m_itemsPointers.at(i);
0510             m_flowLayout->removeWidget(wgt2);
0511             listWidgets.push_back(wgt2);
0512         }
0513 
0514         // Add items
0515         nb = listWidgets.count();
0516         for (int i = 0; i < nb; ++i) {
0517             SKGBoardWidget* dbw = listWidgets.at(i);
0518             dbw->setParent(m_content);
0519             m_flowLayout->addWidget(dbw);
0520         }
0521     }
0522 }
0523 
0524 SKGBoardWidget* SKGDashboardWidget::parentBoardWidget(QWidget* iWidget)
0525 {
0526     auto* output = qobject_cast< SKGBoardWidget* >(iWidget);
0527     if ((output == nullptr) && (iWidget != nullptr)) {
0528         QWidget* iParent = iWidget->parentWidget();
0529         if (iParent != nullptr) {
0530             output = SKGDashboardWidget::parentBoardWidget(iParent);
0531         }
0532     }
0533 
0534     return output;
0535 }
0536 
0537 void SKGDashboardWidget::onRemoveWidget()
0538 {
0539     int p = -1;
0540     QWidget* send = qobject_cast<QWidget*>(this->sender());
0541     if (send != nullptr) {
0542         p = m_itemsPointers.indexOf(parentBoardWidget(send));
0543     }
0544     if (p >= 0) {
0545         // Get item
0546         SKGBoardWidget* wgt = m_itemsPointers.at(p);
0547 
0548         // Delete widget
0549         m_flowLayout->removeWidget(wgt);
0550         wgt->hide();
0551         wgt->deleteLater();
0552 
0553         // Remove item
0554         m_items.removeAt(p);
0555         m_itemsPointers.removeAt(p);
0556     }
0557 }
0558 
0559 void SKGDashboardWidget::addItem(SKGInterfacePlugin* iDashboard, int iIndex, int iZoom, const QString& iState)
0560 {
0561     if ((iDashboard != nullptr) && (m_flowLayout != nullptr)) {
0562         SKGBoardWidget* dbw = iDashboard->getDashboardWidget(iIndex);
0563         if (dbw != nullptr) {
0564             // Add widget
0565             dbw->setParent(m_content);
0566             dbw->setState(iState);
0567             if (m_layout == 0) {
0568                 m_flowLayout->addWidget(dbw);
0569             } else {
0570                 auto* grid = qobject_cast< QGridLayout* >(m_flowLayout);
0571                 if (grid) {
0572                     int nbItem = grid->count();
0573                     int row = nbItem / m_layout;
0574                     int col = nbItem % m_layout;
0575                     grid->addWidget(dbw, row, col);
0576                 }
0577             }
0578 
0579             // Install filter
0580             QWidget* drag = dbw->getDragWidget();
0581             if (drag != nullptr) {
0582                 drag->installEventFilter(this);
0583                 drag->setAcceptDrops(true);
0584                 drag->setAttribute(Qt::WA_Hover);
0585             }
0586 
0587             // Connect widget
0588             connect(dbw, &SKGBoardWidget::requestRemove, this, &SKGDashboardWidget::onRemoveWidget, Qt::QueuedConnection);
0589             connect(dbw, &SKGBoardWidget::requestMove, this, &SKGDashboardWidget::onMoveWidget, Qt::QueuedConnection);
0590 
0591             // Set size
0592             dbw->setZoomRatio((iZoom + 15.0) / 5.0);
0593 
0594             QString id = iDashboard->objectName() % '-' % SKGServices::intToString(iIndex);
0595             m_items.push_back(id);
0596             m_itemsPointers.push_back(dbw);
0597         }
0598     }
0599 }