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 }