Changeset 73948 in vbox
- Timestamp:
- Aug 29, 2018 12:31:13 PM (6 years ago)
- Location:
- trunk/src/VBox/Frontends/VirtualBox/src/manager/chooser
- Files:
-
- 3 edited
-
UIChooserItem.h (modified) (3 diffs)
-
UIChooserItemGroup.cpp (modified) (20 diffs)
-
UIChooserItemGroup.h (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/src/manager/chooser/UIChooserItem.h
r73927 r73948 82 82 signals: 83 83 84 /** @name Basicstuff.84 /** @name Item stuff. 85 85 * @{ */ 86 86 /** Notifies listeners about hover enter. */ … … 190 190 void updateGeometry(); 191 191 192 /** Updates layout. */192 /** Updates layout. */ 193 193 virtual void updateLayout() = 0; 194 194 … … 227 227 protected: 228 228 229 /** @name Event- processing stuff.229 /** @name Event-handling stuff. 230 230 * @{ */ 231 231 /** Handles hover enter @a event. */ 232 v oid hoverMoveEvent(QGraphicsSceneHoverEvent *pEvent);232 virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *pEvent) /* override */; 233 233 /** Handles hover leave @a event. */ 234 v oid hoverLeaveEvent(QGraphicsSceneHoverEvent *pEvent);234 virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *pEvent) /* override */; 235 235 236 236 /** Handles mouse press @a event. */ 237 v oid mousePressEvent(QGraphicsSceneMouseEvent *pEvent);237 virtual void mousePressEvent(QGraphicsSceneMouseEvent *pEvent) /* override */; 238 238 /** Handles mouse move @a event. */ 239 v oid mouseMoveEvent(QGraphicsSceneMouseEvent *pEvent);239 virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *pEvent) /* override */; 240 240 241 241 /** Handles drag move @a event. */ 242 v oid dragMoveEvent(QGraphicsSceneDragDropEvent *pEvent);242 virtual void dragMoveEvent(QGraphicsSceneDragDropEvent *pEvent) /* override */; 243 243 /** Handles drag leave @a event. */ 244 v oid dragLeaveEvent(QGraphicsSceneDragDropEvent *pEvent);244 virtual void dragLeaveEvent(QGraphicsSceneDragDropEvent *pEvent) /* override */; 245 245 /** Handles drop @a event. */ 246 v oid dropEvent(QGraphicsSceneDragDropEvent *pEvent);246 virtual void dropEvent(QGraphicsSceneDragDropEvent *pEvent) /* override */; 247 247 /** @} */ 248 248 -
trunk/src/VBox/Frontends/VirtualBox/src/manager/chooser/UIChooserItemGroup.cpp
r73927 r73948 5 5 6 6 /* 7 * Copyright (C) 2012-201 7Oracle Corporation7 * Copyright (C) 2012-2018 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 21 21 22 22 /* Qt includes: */ 23 # include <QGraphicsScene> 24 # include <QGraphicsSceneDragDropEvent> 25 # include <QHBoxLayout> 26 # include <QLineEdit> 27 # include <QMenu> 23 28 # include <QPainter> 24 29 # include <QStyleOptionGraphicsItem> 25 # include <QGraphicsSceneDragDropEvent>26 # include <QLineEdit>27 # include <QGraphicsScene>28 # include <QHBoxLayout>29 # include <QMenu>30 30 31 31 /* GUI includes: */ … … 44 44 45 45 46 /* static */ 47 QString UIChooserItemGroup::className() { return "UIChooserItemGroup"; } 46 /********************************************************************************************************************************* 47 * Class UIChooserItemGroup implementation. * 48 *********************************************************************************************************************************/ 48 49 49 50 UIChooserItemGroup::UIChooserItemGroup(QGraphicsScene *pScene) 50 51 : UIChooserItem(0, false /* temporary? */) 52 , m_fMainRoot(true) 51 53 , m_fClosed(false) 52 , m_fMainRoot(true) 54 , m_iAdditionalHeight(0) 55 , m_iCornerRadius(0) 56 , m_iBlackoutDarkness(0) 57 , m_pToggleButton(0) 58 , m_pEnterButton(0) 59 , m_pExitButton(0) 60 , m_pNameEditorWidget(0) 61 , m_pNameEditor(0) 53 62 { 54 63 /* Prepare: */ … … 62 71 retranslateUi(); 63 72 64 /* Prepare main-root-itemconnections: */65 connect(this, SIGNAL(sigMinimumWidthHintChanged(int)),66 model(), SIGNAL(sigRootItemMinimumWidthHintChanged(int)));67 connect(this, SIGNAL(sigMinimumHeightHintChanged(int)),68 model(), SIGNAL(sigRootItemMinimumHeightHintChanged(int)));73 /* Prepare connections: */ 74 connect(this, &UIChooserItemGroup::sigMinimumWidthHintChanged, 75 model(), &UIChooserModel::sigRootItemMinimumWidthHintChanged); 76 connect(this, &UIChooserItemGroup::sigMinimumHeightHintChanged, 77 model(), &UIChooserModel::sigRootItemMinimumHeightHintChanged); 69 78 } 70 79 71 80 UIChooserItemGroup::UIChooserItemGroup(QGraphicsScene *pScene, 72 UIChooserItemGroup *pCopyFrom,73 bool fMainRoot)81 UIChooserItemGroup *pCopyFrom, 82 bool fMainRoot) 74 83 : UIChooserItem(0, true /* temporary? */) 84 , m_fMainRoot(fMainRoot) 75 85 , m_fClosed(pCopyFrom->isClosed()) 76 , m_fMainRoot(fMainRoot) 86 , m_iAdditionalHeight(0) 87 , m_iCornerRadius(0) 88 , m_iBlackoutDarkness(0) 77 89 , m_strName(pCopyFrom->name()) 90 , m_pToggleButton(0) 91 , m_pEnterButton(0) 92 , m_pExitButton(0) 93 , m_pNameEditorWidget(0) 94 , m_pNameEditor(0) 78 95 { 79 96 /* Prepare: */ … … 97 114 98 115 UIChooserItemGroup::UIChooserItemGroup(UIChooserItem *pParent, 99 const QString &strName,100 bool fOpened /* = false */,101 int iPosition /* = -1 */)116 const QString &strName, 117 bool fOpened /* = false */, 118 int iPosition /* = -1 */) 102 119 : UIChooserItem(pParent, pParent->isTemporary()) 120 , m_fMainRoot(false) 103 121 , m_fClosed(!fOpened) 104 , m_fMainRoot(false) 122 , m_iAdditionalHeight(0) 123 , m_iCornerRadius(0) 124 , m_iBlackoutDarkness(0) 105 125 , m_strName(strName) 126 , m_pToggleButton(0) 127 , m_pEnterButton(0) 128 , m_pExitButton(0) 129 , m_pNameEditorWidget(0) 130 , m_pNameEditor(0) 106 131 { 107 132 /* Prepare: */ … … 112 137 parentItem()->addItem(this, iPosition); 113 138 setZValue(parentItem()->zValue() + 1); 114 connect(this, SIGNAL(sigToggleStarted()), model(), SIGNAL(sigToggleStarted())); 115 connect(this, SIGNAL(sigToggleFinished()), model(), SIGNAL(sigToggleFinished()), Qt::QueuedConnection); 139 connect(this, &UIChooserItemGroup::sigToggleStarted, 140 model(), &UIChooserModel::sigToggleStarted); 141 connect(this, &UIChooserItemGroup::sigToggleFinished, 142 model(), &UIChooserModel::sigToggleFinished, 143 Qt::QueuedConnection); 116 144 connect(gpManager, &UIVirtualBoxManager::sigWindowRemapped, 117 145 this, &UIChooserItemGroup::sltHandleWindowRemapped); … … 126 154 updateToolTip(); 127 155 128 /* Prepare root-itemconnections: */129 connect(this, SIGNAL(sigMinimumWidthHintChanged(int)),130 model(), SIGNAL(sigRootItemMinimumWidthHintChanged(int)));131 connect(this, SIGNAL(sigMinimumHeightHintChanged(int)),132 model(), SIGNAL(sigRootItemMinimumHeightHintChanged(int)));156 /* Prepare connections: */ 157 connect(this, &UIChooserItemGroup::sigMinimumWidthHintChanged, 158 model(), &UIChooserModel::sigRootItemMinimumWidthHintChanged); 159 connect(this, &UIChooserItemGroup::sigMinimumHeightHintChanged, 160 model(), &UIChooserModel::sigRootItemMinimumHeightHintChanged); 133 161 } 134 162 135 163 UIChooserItemGroup::UIChooserItemGroup(UIChooserItem *pParent, 136 UIChooserItemGroup *pCopyFrom,137 int iPosition /* = -1 */)164 UIChooserItemGroup *pCopyFrom, 165 int iPosition /* = -1 */) 138 166 : UIChooserItem(pParent, pParent->isTemporary()) 167 , m_fMainRoot(false) 139 168 , m_fClosed(pCopyFrom->isClosed()) 140 , m_fMainRoot(false) 169 , m_iAdditionalHeight(0) 170 , m_iCornerRadius(0) 171 , m_iBlackoutDarkness(0) 141 172 , m_strName(pCopyFrom->name()) 173 , m_pToggleButton(0) 174 , m_pEnterButton(0) 175 , m_pExitButton(0) 176 , m_pNameEditorWidget(0) 177 , m_pNameEditor(0) 142 178 { 143 179 /* Prepare: */ … … 148 184 parentItem()->addItem(this, iPosition); 149 185 setZValue(parentItem()->zValue() + 1); 150 connect(this, SIGNAL(sigToggleStarted()), model(), SIGNAL(sigToggleStarted())); 151 connect(this, SIGNAL(sigToggleFinished()), model(), SIGNAL(sigToggleFinished())); 186 connect(this, &UIChooserItemGroup::sigToggleStarted, 187 model(), &UIChooserModel::sigToggleStarted); 188 connect(this, &UIChooserItemGroup::sigToggleFinished, 189 model(), &UIChooserModel::sigToggleFinished); 152 190 connect(gpManager, &UIVirtualBoxManager::sigWindowRemapped, 153 191 this, &UIChooserItemGroup::sltHandleWindowRemapped); … … 193 231 if (parentItem()) 194 232 parentItem()->removeItem(this); 233 } 234 235 void UIChooserItemGroup::setName(const QString &strName) 236 { 237 /* Something changed? */ 238 if (m_strName == strName) 239 return; 240 241 /* Remember new name: */ 242 m_strName = strName; 243 244 /* Update linked values: */ 245 updateVisibleName(); 246 updateMinimumHeaderSize(); 247 } 248 249 void UIChooserItemGroup::close(bool fAnimated /* = true */) 250 { 251 AssertMsg(!isRoot(), ("Can't close root-item!")); 252 m_pToggleButton->setToggled(false, fAnimated); 253 } 254 255 bool UIChooserItemGroup::isClosed() const 256 { 257 return m_fClosed && !isRoot(); 258 } 259 260 void UIChooserItemGroup::open(bool fAnimated /* = true */) 261 { 262 AssertMsg(!isRoot(), ("Can't open root-item!")); 263 m_pToggleButton->setToggled(true, fAnimated); 264 } 265 266 bool UIChooserItemGroup::isOpened() const 267 { 268 return !m_fClosed || isRoot(); 269 } 270 271 /* static */ 272 QString UIChooserItemGroup::className() 273 { 274 return "UIChooserItemGroup"; 275 } 276 277 void UIChooserItemGroup::retranslateUi() 278 { 279 /* Update description: */ 280 m_strDescription = tr("Virtual Machine group"); 281 282 /* Update group tool-tip: */ 283 updateToolTip(); 284 285 /* Update button tool-tips: */ 286 if (m_pEnterButton) 287 m_pEnterButton->setToolTip(tr("Enter group")); 288 if (m_pExitButton) 289 m_pExitButton->setToolTip(tr("Exit group")); 290 updateToggleButtonToolTip(); 291 } 292 293 void UIChooserItemGroup::showEvent(QShowEvent *pEvent) 294 { 295 /* Call to base-class: */ 296 UIChooserItem::showEvent(pEvent); 297 298 /* Update pixmaps: */ 299 updatePixmaps(); 300 } 301 302 void UIChooserItemGroup::resizeEvent(QGraphicsSceneResizeEvent *pEvent) 303 { 304 /* Call to base-class: */ 305 UIChooserItem::resizeEvent(pEvent); 306 307 /* What is the new geometry? */ 308 const QRectF newGeometry = geometry(); 309 310 /* Should we update visible name? */ 311 if (previousGeometry().width() != newGeometry.width()) 312 updateVisibleName(); 313 314 /* Remember the new geometry: */ 315 setPreviousGeometry(newGeometry); 316 } 317 318 void UIChooserItemGroup::hoverMoveEvent(QGraphicsSceneHoverEvent *pEvent) 319 { 320 /* Skip if hovered: */ 321 if (isHovered()) 322 return; 323 324 /* Prepare variables: */ 325 const QPoint pos = pEvent->pos().toPoint(); 326 const int iMargin = data(GroupItemData_VerticalMargin).toInt(); 327 const int iHeaderHeight = m_minimumHeaderSize.height(); 328 const int iFullHeaderHeight = 2 * iMargin + iHeaderHeight; 329 /* Skip if hovered part out of the header: */ 330 if (pos.y() >= iFullHeaderHeight) 331 return; 332 333 /* Call to base-class: */ 334 UIChooserItem::hoverMoveEvent(pEvent); 335 336 /* Update linked values: */ 337 updateVisibleName(); 338 } 339 340 void UIChooserItemGroup::hoverLeaveEvent(QGraphicsSceneHoverEvent *pEvent) 341 { 342 /* Skip if not hovered: */ 343 if (!isHovered()) 344 return; 345 346 /* Call to base-class: */ 347 UIChooserItem::hoverLeaveEvent(pEvent); 348 349 /* Update linked values: */ 350 updateVisibleName(); 351 } 352 353 void UIChooserItemGroup::paint(QPainter *pPainter, const QStyleOptionGraphicsItem *pOptions, QWidget* /* pWidget = 0 */) 354 { 355 /* Setup: */ 356 pPainter->setRenderHint(QPainter::Antialiasing); 357 358 /* Paint background: */ 359 paintBackground(pPainter, pOptions->rect); 360 361 /* Paint header: */ 362 paintHeader(pPainter, pOptions->rect); 363 } 364 365 void UIChooserItemGroup::show() 366 { 367 /* Call to base-class: */ 368 UIChooserItem::show(); 369 /* Show children: */ 370 if (!isClosed()) 371 foreach (UIChooserItem *pItem, items()) 372 pItem->show(); 373 } 374 375 void UIChooserItemGroup::hide() 376 { 377 /* Call to base-class: */ 378 UIChooserItem::hide(); 379 /* Hide children: */ 380 foreach (UIChooserItem *pItem, items()) 381 pItem->hide(); 382 } 383 384 void UIChooserItemGroup::startEditing() 385 { 386 /* Not for root: */ 387 if (isRoot()) 388 return; 389 390 /* Not while saving groups: */ 391 if (model()->isGroupSavingInProgress()) 392 return; 393 394 /* Unlock name-editor: */ 395 m_pNameEditor->show(); 396 m_pNameEditorWidget->setText(name()); 397 m_pNameEditorWidget->setFocus(); 398 } 399 400 void UIChooserItemGroup::updateToolTip() 401 { 402 /* Not for main root: */ 403 if (isMainRoot()) 404 return; 405 406 /* Prepare variables: */ 407 QStringList toolTipInfo; 408 409 /* Should we add name? */ 410 if (!name().isEmpty()) 411 { 412 /* Template: */ 413 QString strTemplateForName = tr("<b>%1</b>", "Group item tool-tip / Group name"); 414 415 /* Append value: */ 416 toolTipInfo << strTemplateForName.arg(name()); 417 } 418 419 /* Should we add group info? */ 420 if (!items(UIChooserItemType_Group).isEmpty()) 421 { 422 /* Template: */ 423 QString strGroupCount = tr("%n group(s)", "Group item tool-tip / Group info", items(UIChooserItemType_Group).size()); 424 425 /* Append value: */ 426 QString strValue = tr("<nobr>%1</nobr>", "Group item tool-tip / Group info wrapper").arg(strGroupCount); 427 toolTipInfo << strValue; 428 } 429 430 /* Should we add machine info? */ 431 if (!items(UIChooserItemType_Machine).isEmpty()) 432 { 433 /* Check if 'this' group contains started VMs: */ 434 int iCountOfStartedMachineItems = 0; 435 foreach (UIChooserItem *pItem, items(UIChooserItemType_Machine)) 436 if (UIVirtualMachineItem::isItemStarted(pItem->toMachineItem())) 437 ++iCountOfStartedMachineItems; 438 /* Template: */ 439 QString strMachineCount = tr("%n machine(s)", "Group item tool-tip / Machine info", items(UIChooserItemType_Machine).size()); 440 QString strStartedMachineCount = tr("(%n running)", "Group item tool-tip / Running machine info", iCountOfStartedMachineItems); 441 442 /* Append value: */ 443 QString strValue = !iCountOfStartedMachineItems ? 444 tr("<nobr>%1</nobr>", "Group item tool-tip / Machine info wrapper").arg(strMachineCount) : 445 tr("<nobr>%1 %2</nobr>", "Group item tool-tip / Machine info wrapper, including running").arg(strMachineCount).arg(strStartedMachineCount); 446 toolTipInfo << strValue; 447 } 448 449 /* Set tool-tip: */ 450 setToolTip(toolTipInfo.join("<br>")); 195 451 } 196 452 … … 224 480 } 225 481 226 void UIChooserItemGroup::setName(const QString &strName) 227 { 228 /* Something changed? */ 229 if (m_strName == strName) 230 return; 231 232 /* Remember new name: */ 233 m_strName = strName; 482 void UIChooserItemGroup::handleRootStatusChange() 483 { 484 /* Call to base-class: */ 485 UIChooserItem::handleRootStatusChange(); 234 486 235 487 /* Update linked values: */ … … 238 490 } 239 491 240 bool UIChooserItemGroup::isClosed() const 241 { 242 return m_fClosed && !isRoot(); 243 } 244 245 bool UIChooserItemGroup::isOpened() const 246 { 247 return !m_fClosed || isRoot(); 248 } 249 250 void UIChooserItemGroup::close(bool fAnimated /* = true */) 251 { 252 AssertMsg(!isRoot(), ("Can't close root-item!")); 253 m_pToggleButton->setToggled(false, fAnimated); 254 } 255 256 void UIChooserItemGroup::open(bool fAnimated /* = true */) 257 { 258 AssertMsg(!isRoot(), ("Can't open root-item!")); 259 m_pToggleButton->setToggled(true, fAnimated); 260 } 261 262 bool UIChooserItemGroup::isContainsMachine(const QString &strId) const 263 { 264 /* Check each machine-item: */ 265 foreach (UIChooserItem *pItem, m_machineItems) 266 if (pItem->toMachineItem()->id() == strId) 267 return true; 492 void UIChooserItemGroup::addItem(UIChooserItem *pItem, int iPosition) 493 { 494 /* Check item type: */ 495 switch (pItem->type()) 496 { 497 case UIChooserItemType_Group: 498 { 499 AssertMsg(!m_groupItems.contains(pItem), ("Group-item already added!")); 500 if (iPosition < 0 || iPosition >= m_groupItems.size()) 501 m_groupItems.append(pItem); 502 else 503 m_groupItems.insert(iPosition, pItem); 504 scene()->addItem(pItem); 505 break; 506 } 507 case UIChooserItemType_Global: 508 { 509 AssertMsg(!m_globalItems.contains(pItem), ("Global-item already added!")); 510 if (iPosition < 0 || iPosition >= m_globalItems.size()) 511 m_globalItems.append(pItem); 512 else 513 m_globalItems.insert(iPosition, pItem); 514 scene()->addItem(pItem); 515 break; 516 } 517 case UIChooserItemType_Machine: 518 { 519 AssertMsg(!m_machineItems.contains(pItem), ("Machine-item already added!")); 520 if (iPosition < 0 || iPosition >= m_machineItems.size()) 521 m_machineItems.append(pItem); 522 else 523 m_machineItems.insert(iPosition, pItem); 524 scene()->addItem(pItem); 525 break; 526 } 527 default: 528 { 529 AssertMsgFailed(("Invalid item type!")); 530 break; 531 } 532 } 533 534 /* Update linked values: */ 535 updateItemCountInfo(); 536 updateToolTip(); 537 updateGeometry(); 538 } 539 540 void UIChooserItemGroup::removeItem(UIChooserItem *pItem) 541 { 542 /* Check item type: */ 543 switch (pItem->type()) 544 { 545 case UIChooserItemType_Group: 546 { 547 AssertMsg(m_groupItems.contains(pItem), ("Group-item was not found!")); 548 scene()->removeItem(pItem); 549 m_groupItems.removeAt(m_groupItems.indexOf(pItem)); 550 break; 551 } 552 case UIChooserItemType_Global: 553 { 554 AssertMsg(m_globalItems.contains(pItem), ("Global-item was not found!")); 555 scene()->removeItem(pItem); 556 m_globalItems.removeAt(m_globalItems.indexOf(pItem)); 557 break; 558 } 559 case UIChooserItemType_Machine: 560 { 561 AssertMsg(m_machineItems.contains(pItem), ("Machine-item was not found!")); 562 scene()->removeItem(pItem); 563 m_machineItems.removeAt(m_machineItems.indexOf(pItem)); 564 break; 565 } 566 default: 567 { 568 AssertMsgFailed(("Invalid item type!")); 569 break; 570 } 571 } 572 573 /* Update linked values: */ 574 updateItemCountInfo(); 575 updateToolTip(); 576 updateGeometry(); 577 } 578 579 void UIChooserItemGroup::setItems(const QList<UIChooserItem*> &items, UIChooserItemType type) 580 { 581 /* Check item type: */ 582 switch (type) 583 { 584 case UIChooserItemType_Group: m_groupItems = items; break; 585 case UIChooserItemType_Global: m_globalItems = items; break; 586 case UIChooserItemType_Machine: m_machineItems = items; break; 587 default: AssertMsgFailed(("Invalid item type!")); break; 588 } 589 590 /* Update linked values: */ 591 updateItemCountInfo(); 592 updateToolTip(); 593 updateGeometry(); 594 } 595 596 QList<UIChooserItem*> UIChooserItemGroup::items(UIChooserItemType type /* = UIChooserItemType_Any */) const 597 { 598 switch (type) 599 { 600 case UIChooserItemType_Any: return items(UIChooserItemType_Global) + items(UIChooserItemType_Group) + items(UIChooserItemType_Machine); 601 case UIChooserItemType_Group: return m_groupItems; 602 case UIChooserItemType_Global: return m_globalItems; 603 case UIChooserItemType_Machine: return m_machineItems; 604 default: break; 605 } 606 return QList<UIChooserItem*>(); 607 } 608 609 bool UIChooserItemGroup::hasItems(UIChooserItemType type /* = UIChooserItemType_Any */) const 610 { 611 switch (type) 612 { 613 case UIChooserItemType_Any: 614 return hasItems(UIChooserItemType_Global) || hasItems(UIChooserItemType_Group) || hasItems(UIChooserItemType_Machine); 615 case UIChooserItemType_Group: 616 return !m_groupItems.isEmpty(); 617 case UIChooserItemType_Global: 618 return !m_globalItems.isEmpty(); 619 case UIChooserItemType_Machine: 620 return !m_machineItems.isEmpty(); 621 } 622 return false; 623 } 624 625 void UIChooserItemGroup::clearItems(UIChooserItemType type /* = UIChooserItemType_Any */) 626 { 627 switch (type) 628 { 629 case UIChooserItemType_Any: 630 { 631 clearItems(UIChooserItemType_Group); 632 clearItems(UIChooserItemType_Global); 633 clearItems(UIChooserItemType_Machine); 634 break; 635 } 636 case UIChooserItemType_Group: 637 { 638 while (!m_groupItems.isEmpty()) { delete m_groupItems.last(); } 639 AssertMsg(m_groupItems.isEmpty(), ("Group items cleanup failed!")); 640 break; 641 } 642 case UIChooserItemType_Global: 643 { 644 while (!m_globalItems.isEmpty()) { delete m_globalItems.last(); } 645 AssertMsg(m_globalItems.isEmpty(), ("Global items cleanup failed!")); 646 break; 647 } 648 case UIChooserItemType_Machine: 649 { 650 while (!m_machineItems.isEmpty()) { delete m_machineItems.last(); } 651 AssertMsg(m_machineItems.isEmpty(), ("Machine items cleanup failed!")); 652 break; 653 } 654 } 655 656 /* Update linked values: */ 657 updateItemCountInfo(); 658 updateToolTip(); 659 updateGeometry(); 660 } 661 662 void UIChooserItemGroup::updateAllItems(const QString &strId) 663 { 664 /* Update all the required items recursively: */ 665 foreach (UIChooserItem *pItem, items()) 666 pItem->updateAllItems(strId); 667 } 668 669 void UIChooserItemGroup::removeAllItems(const QString &strId) 670 { 671 /* Remove all the required items recursively: */ 672 foreach (UIChooserItem *pItem, items()) 673 pItem->removeAllItems(strId); 674 } 675 676 UIChooserItem* UIChooserItemGroup::searchForItem(const QString &strSearchTag, int iItemSearchFlags) 677 { 678 /* Are we searching among group-items? */ 679 if (iItemSearchFlags & UIChooserItemSearchFlag_Group) 680 { 681 /* Are we searching by the exact name? */ 682 if (iItemSearchFlags & UIChooserItemSearchFlag_ExactName) 683 { 684 /* Exact name matches? */ 685 if (name() == strSearchTag) 686 return this; 687 } 688 /* Are we searching by the few first symbols? */ 689 else 690 { 691 /* Name starts with passed symbols? */ 692 if (name().startsWith(strSearchTag, Qt::CaseInsensitive)) 693 return this; 694 } 695 } 696 697 /* Search among all the children, but machines first: */ 698 foreach (UIChooserItem *pItem, items(UIChooserItemType_Machine)) 699 if (UIChooserItem *pFoundItem = pItem->searchForItem(strSearchTag, iItemSearchFlags)) 700 return pFoundItem; 701 foreach (UIChooserItem *pItem, items(UIChooserItemType_Global)) 702 if (UIChooserItem *pFoundItem = pItem->searchForItem(strSearchTag, iItemSearchFlags)) 703 return pFoundItem; 704 foreach (UIChooserItem *pItem, items(UIChooserItemType_Group)) 705 if (UIChooserItem *pFoundItem = pItem->searchForItem(strSearchTag, iItemSearchFlags)) 706 return pFoundItem; 707 268 708 /* Found nothing? */ 709 return 0; 710 } 711 712 UIChooserItem *UIChooserItemGroup::firstMachineItem() 713 { 714 /* If this group-item have at least one machine-item: */ 715 if (hasItems(UIChooserItemType_Machine)) 716 /* Return the first machine-item: */ 717 return items(UIChooserItemType_Machine).first()->firstMachineItem(); 718 /* If this group-item have at least one group-item: */ 719 else if (hasItems(UIChooserItemType_Group)) 720 /* Return the first machine-item of the first group-item: */ 721 return items(UIChooserItemType_Group).first()->firstMachineItem(); 722 /* Found nothing? */ 723 return 0; 724 } 725 726 void UIChooserItemGroup::sortItems() 727 { 728 /* Sort group-items: */ 729 QMap<QString, UIChooserItem*> sorter; 730 foreach (UIChooserItem *pItem, items(UIChooserItemType_Group)) 731 sorter.insert(pItem->name().toLower(), pItem); 732 setItems(sorter.values(), UIChooserItemType_Group); 733 734 /* Sort machine-items: */ 735 sorter.clear(); 736 foreach (UIChooserItem *pItem, items(UIChooserItemType_Machine)) 737 sorter.insert(pItem->name().toLower(), pItem); 738 setItems(sorter.values(), UIChooserItemType_Machine); 739 740 /* Update model: */ 741 model()->updateNavigation(); 742 model()->updateLayout(); 743 } 744 745 void UIChooserItemGroup::updateLayout() 746 { 747 /* Prepare variables: */ 748 int iHorizontalMargin = data(GroupItemData_HorizonalMargin).toInt(); 749 int iVerticalMargin = data(GroupItemData_VerticalMargin).toInt(); 750 int iMinorSpacing = data(GroupItemData_MinorSpacing).toInt(); 751 int iFullHeaderHeight = m_minimumHeaderSize.height(); 752 int iRootIndent = data(GroupItemData_RootIndent).toInt(); 753 int iPreviousVerticalIndent = 0; 754 755 /* Header (root-item): */ 756 if (isRoot()) 757 { 758 /* Header (main root-item): */ 759 if (isMainRoot()) 760 { 761 /* Prepare body indent: */ 762 iPreviousVerticalIndent = iRootIndent; 763 } 764 /* Header (non-main root-item): */ 765 else 766 { 767 /* Hide unnecessary buttons: */ 768 if (m_pToggleButton) 769 m_pToggleButton->hide(); 770 if (m_pEnterButton) 771 m_pEnterButton->hide(); 772 773 /* Exit-button: */ 774 if (m_pExitButton) 775 { 776 /* Prepare variables: */ 777 int iExitButtonHeight = m_exitButtonSize.height(); 778 /* Layout exit-button: */ 779 int iExitButtonX = iHorizontalMargin + iRootIndent; 780 int iExitButtonY = iExitButtonHeight == iFullHeaderHeight ? iVerticalMargin : 781 iVerticalMargin + (iFullHeaderHeight - iExitButtonHeight) / 2; 782 m_pExitButton->setPos(iExitButtonX, iExitButtonY); 783 /* Show exit-button: */ 784 m_pExitButton->show(); 785 } 786 787 /* Prepare body indent: */ 788 iPreviousVerticalIndent = iVerticalMargin + iFullHeaderHeight + iVerticalMargin + iMinorSpacing; 789 } 790 } 791 /* Header (non-root-item): */ 792 else 793 { 794 /* Hide unnecessary button: */ 795 if (m_pExitButton) 796 m_pExitButton->hide(); 797 798 /* Toggle-button: */ 799 if (m_pToggleButton) 800 { 801 /* Prepare variables: */ 802 int iToggleButtonHeight = m_toggleButtonSize.height(); 803 /* Layout toggle-button: */ 804 int iToggleButtonX = iHorizontalMargin; 805 int iToggleButtonY = iToggleButtonHeight == iFullHeaderHeight ? iVerticalMargin : 806 iVerticalMargin + (iFullHeaderHeight - iToggleButtonHeight) / 2; 807 m_pToggleButton->setPos(iToggleButtonX, iToggleButtonY); 808 /* Show toggle-button: */ 809 m_pToggleButton->show(); 810 } 811 812 /* Enter-button: */ 813 if (m_pEnterButton) 814 { 815 /* Prepare variables: */ 816 int iFullWidth = (int)geometry().width(); 817 int iEnterButtonWidth = m_enterButtonSize.width(); 818 int iEnterButtonHeight = m_enterButtonSize.height(); 819 /* Layout enter-button: */ 820 int iEnterButtonX = iFullWidth - iHorizontalMargin - iEnterButtonWidth; 821 int iEnterButtonY = iEnterButtonHeight == iFullHeaderHeight ? iVerticalMargin : 822 iVerticalMargin + (iFullHeaderHeight - iEnterButtonHeight) / 2; 823 m_pEnterButton->setPos(iEnterButtonX, iEnterButtonY); 824 } 825 826 /* Name-editor: */ 827 if (m_pNameEditor && m_pNameEditorWidget) 828 { 829 /* Prepare variables: */ 830 int iMajorSpacing = data(GroupItemData_MajorSpacing).toInt(); 831 int iToggleButtonWidth = m_toggleButtonSize.width(); 832 /* Layout name-editor: */ 833 int iNameEditorX = iHorizontalMargin + iToggleButtonWidth + iMajorSpacing; 834 int iNameEditorY = 1; 835 m_pNameEditor->setPos(iNameEditorX, iNameEditorY); 836 m_pNameEditorWidget->resize((int)(geometry().width() - iNameEditorX - iHorizontalMargin), m_pNameEditorWidget->height()); 837 } 838 839 /* Prepare body indent: */ 840 iPreviousVerticalIndent = 3 * iVerticalMargin + iFullHeaderHeight; 841 } 842 843 /* No body for closed group: */ 844 if (isClosed()) 845 { 846 /* Hide all the items: */ 847 foreach (UIChooserItem *pItem, items()) 848 pItem->hide(); 849 } 850 /* Body for opened group: */ 851 else 852 { 853 /* Prepare variables: */ 854 int iHorizontalIndent = isRoot() ? iRootIndent : iHorizontalMargin; 855 QRect geo = geometry().toRect(); 856 int iX = geo.x(); 857 int iY = geo.y(); 858 int iWidth = geo.width(); 859 860 /* Layout all the items: */ 861 foreach (UIChooserItem *pItem, items()) 862 { 863 /* Show if hidden: */ 864 pItem->show(); 865 /* Get item height-hint: */ 866 int iMinimumHeight = pItem->minimumHeightHint(); 867 /* Set item position: */ 868 pItem->setPos(iX + iHorizontalIndent, iY + iPreviousVerticalIndent); 869 /* Set item size: */ 870 pItem->resize(iWidth - 2 * iHorizontalIndent, iMinimumHeight); 871 /* Relayout group: */ 872 pItem->updateLayout(); 873 /* Update indent for next items: */ 874 iPreviousVerticalIndent += (iMinimumHeight + iMinorSpacing); 875 } 876 } 877 } 878 879 int UIChooserItemGroup::minimumWidthHint() const 880 { 881 return minimumWidthHintForGroup(isOpened()); 882 } 883 884 int UIChooserItemGroup::minimumHeightHint() const 885 { 886 return minimumHeightHintForGroup(isOpened()); 887 } 888 889 QSizeF UIChooserItemGroup::sizeHint(Qt::SizeHint enmWhich, const QSizeF &constraint /* = QSizeF() */) const 890 { 891 /* If Qt::MinimumSize requested: */ 892 if (enmWhich == Qt::MinimumSize) 893 return minimumSizeHintForProup(isOpened()); 894 /* Else call to base-class: */ 895 return UIChooserItem::sizeHint(enmWhich, constraint); 896 } 897 898 QPixmap UIChooserItemGroup::toPixmap() 899 { 900 /* Ask item to paint itself into pixmap: */ 901 QSize minimumSize = minimumSizeHintForProup(false).toSize(); 902 QPixmap pixmap(minimumSize); 903 pixmap.fill(Qt::transparent); 904 QPainter painter(&pixmap); 905 painter.setRenderHint(QPainter::Antialiasing); 906 QStyleOptionGraphicsItem options; 907 options.rect = QRect(QPoint(0, 0), minimumSize); 908 paint(&painter, &options); 909 return pixmap; 910 } 911 912 bool UIChooserItemGroup::isDropAllowed(QGraphicsSceneDragDropEvent *pEvent, DragToken where) const 913 { 914 /* No drops while saving groups: */ 915 if (model()->isGroupSavingInProgress()) 916 return false; 917 /* Get mime: */ 918 const QMimeData *pMimeData = pEvent->mimeData(); 919 /* If drag token is shown, its up to parent to decide: */ 920 if (where != DragToken_Off) 921 return parentItem()->isDropAllowed(pEvent); 922 /* Else we should check mime format: */ 923 if (pMimeData->hasFormat(UIChooserItemGroup::className())) 924 { 925 /* Get passed group-item: */ 926 const UIChooserItemMimeData *pCastedMimeData = qobject_cast<const UIChooserItemMimeData*>(pMimeData); 927 AssertMsg(pCastedMimeData, ("Can't cast passed mime-data to UIChooserItemMimeData!")); 928 UIChooserItem *pItem = pCastedMimeData->item(); 929 /* Make sure passed group is mutable within this group: */ 930 if (pItem->toGroupItem()->isContainsLockedMachine() && 931 !items(UIChooserItemType_Group).contains(pItem)) 932 return false; 933 /* Make sure passed group is not 'this': */ 934 if (pItem == this) 935 return false; 936 /* Make sure passed group is not among our parents: */ 937 const UIChooserItem *pTestedWidget = this; 938 while (UIChooserItem *pParentOfTestedWidget = pTestedWidget->parentItem()) 939 { 940 if (pItem == pParentOfTestedWidget) 941 return false; 942 pTestedWidget = pParentOfTestedWidget; 943 } 944 return true; 945 } 946 else if (pMimeData->hasFormat(UIChooserItemMachine::className())) 947 { 948 /* Get passed machine-item: */ 949 const UIChooserItemMimeData *pCastedMimeData = qobject_cast<const UIChooserItemMimeData*>(pMimeData); 950 AssertMsg(pCastedMimeData, ("Can't cast passed mime-data to UIChooserItemMimeData!")); 951 UIChooserItem *pItem = pCastedMimeData->item(); 952 /* Make sure passed machine is mutable within this group: */ 953 if (pItem->toMachineItem()->isLockedMachine() && 954 !items(UIChooserItemType_Machine).contains(pItem)) 955 return false; 956 switch (pEvent->proposedAction()) 957 { 958 case Qt::MoveAction: 959 { 960 /* Make sure passed item is ours or there is no other item with such id: */ 961 return m_machineItems.contains(pItem) || !isContainsMachine(pItem->toMachineItem()->id()); 962 } 963 case Qt::CopyAction: 964 { 965 /* Make sure there is no other item with such id: */ 966 return !isContainsMachine(pItem->toMachineItem()->id()); 967 } 968 default: break; /* Shut up, MSC! */ 969 } 970 } 971 /* That was invalid mime: */ 269 972 return false; 270 973 } 271 974 272 bool UIChooserItemGroup::isContainsLockedMachine() 273 { 274 /* Check each machine-item: */ 275 foreach (UIChooserItem *pItem, items(UIChooserItemType_Machine)) 276 if (pItem->toMachineItem()->isLockedMachine()) 277 return true; 278 /* Check each group-item: */ 279 foreach (UIChooserItem *pItem, items(UIChooserItemType_Group)) 280 if (pItem->toGroupItem()->isContainsLockedMachine()) 281 return true; 282 /* Found nothing? */ 283 return false; 975 void UIChooserItemGroup::processDrop(QGraphicsSceneDragDropEvent *pEvent, UIChooserItem *pFromWho, DragToken where) 976 { 977 /* Get mime: */ 978 const QMimeData *pMime = pEvent->mimeData(); 979 /* Check mime format: */ 980 if (pMime->hasFormat(UIChooserItemGroup::className())) 981 { 982 switch (pEvent->proposedAction()) 983 { 984 case Qt::MoveAction: 985 case Qt::CopyAction: 986 { 987 /* Remember scene: */ 988 UIChooserModel *pModel = model(); 989 990 /* Get passed group-item: */ 991 const UIChooserItemMimeData *pCastedMime = qobject_cast<const UIChooserItemMimeData*>(pMime); 992 AssertMsg(pCastedMime, ("Can't cast passed mime-data to UIChooserItemMimeData!")); 993 UIChooserItem *pItem = pCastedMime->item(); 994 995 /* Check if we have position information: */ 996 int iPosition = m_groupItems.size(); 997 if (pFromWho && where != DragToken_Off) 998 { 999 /* Make sure sender item if our child: */ 1000 AssertMsg(m_groupItems.contains(pFromWho), ("Sender item is NOT our child!")); 1001 if (m_groupItems.contains(pFromWho)) 1002 { 1003 iPosition = m_groupItems.indexOf(pFromWho); 1004 if (where == DragToken_Down) 1005 ++iPosition; 1006 } 1007 } 1008 1009 /* Copy passed item into this group: */ 1010 UIChooserItem *pNewGroupItem = new UIChooserItemGroup(this, pItem->toGroupItem(), iPosition); 1011 if (isClosed()) 1012 open(false); 1013 1014 /* If proposed action is 'move': */ 1015 if (pEvent->proposedAction() == Qt::MoveAction) 1016 { 1017 /* Delete passed item: */ 1018 delete pItem; 1019 } 1020 1021 /* Update model: */ 1022 pModel->cleanupGroupTree(); 1023 pModel->updateNavigation(); 1024 pModel->updateLayout(); 1025 pModel->setCurrentItem(pNewGroupItem); 1026 pModel->saveGroupSettings(); 1027 break; 1028 } 1029 default: 1030 break; 1031 } 1032 } 1033 else if (pMime->hasFormat(UIChooserItemMachine::className())) 1034 { 1035 switch (pEvent->proposedAction()) 1036 { 1037 case Qt::MoveAction: 1038 case Qt::CopyAction: 1039 { 1040 /* Remember scene: */ 1041 UIChooserModel *pModel = model(); 1042 1043 /* Get passed item: */ 1044 const UIChooserItemMimeData *pCastedMime = qobject_cast<const UIChooserItemMimeData*>(pMime); 1045 AssertMsg(pCastedMime, ("Can't cast passed mime-data to UIChooserItemMimeData!")); 1046 UIChooserItem *pItem = pCastedMime->item(); 1047 1048 /* Check if we have position information: */ 1049 int iPosition = m_machineItems.size(); 1050 if (pFromWho && where != DragToken_Off) 1051 { 1052 /* Make sure sender item if our child: */ 1053 AssertMsg(m_machineItems.contains(pFromWho), ("Sender item is NOT our child!")); 1054 if (m_machineItems.contains(pFromWho)) 1055 { 1056 iPosition = m_machineItems.indexOf(pFromWho); 1057 if (where == DragToken_Down) 1058 ++iPosition; 1059 } 1060 } 1061 1062 /* Copy passed machine-item into this group: */ 1063 UIChooserItem *pNewMachineItem = new UIChooserItemMachine(this, pItem->toMachineItem(), iPosition); 1064 if (isClosed()) 1065 open(false); 1066 1067 /* If proposed action is 'move': */ 1068 if (pEvent->proposedAction() == Qt::MoveAction) 1069 { 1070 /* Delete passed item: */ 1071 delete pItem; 1072 } 1073 1074 /* Update model: */ 1075 pModel->cleanupGroupTree(); 1076 pModel->updateNavigation(); 1077 pModel->updateLayout(); 1078 pModel->setCurrentItem(pNewMachineItem); 1079 pModel->saveGroupSettings(); 1080 break; 1081 } 1082 default: 1083 break; 1084 } 1085 } 1086 } 1087 1088 void UIChooserItemGroup::resetDragToken() 1089 { 1090 /* Reset drag token for this item: */ 1091 if (dragTokenPlace() != DragToken_Off) 1092 { 1093 setDragTokenPlace(DragToken_Off); 1094 update(); 1095 } 1096 /* Reset drag tokens for all the items: */ 1097 foreach (UIChooserItem *pItem, items()) 1098 pItem->resetDragToken(); 1099 } 1100 1101 QMimeData* UIChooserItemGroup::createMimeData() 1102 { 1103 return new UIChooserItemMimeData(this); 284 1104 } 285 1105 … … 388 1208 /* Unindent to previous root: */ 389 1209 model()->unindentRoot(); 390 }391 392 QVariant UIChooserItemGroup::data(int iKey) const393 {394 /* Provide other members with required data: */395 switch (iKey)396 {397 /* Layout hints: */398 case GroupItemData_HorizonalMargin: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 4;399 case GroupItemData_VerticalMargin: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 4;400 case GroupItemData_MajorSpacing: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 2;401 case GroupItemData_MinorSpacing: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 5;402 case GroupItemData_RootIndent: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 6;403 404 /* Default: */405 default: break;406 }407 return QVariant();408 1210 } 409 1211 … … 431 1233 /* Setup toggle-button: */ 432 1234 m_pToggleButton = new UIGraphicsRotatorButton(this, "additionalHeight", isOpened()); 433 connect(m_pToggleButton, SIGNAL(sigRotationStart()), this, SLOT(sltGroupToggleStart())); 434 connect(m_pToggleButton, SIGNAL(sigRotationFinish(bool)), this, SLOT(sltGroupToggleFinish(bool))); 1235 connect(m_pToggleButton, &UIGraphicsRotatorButton::sigRotationStart, 1236 this, &UIChooserItemGroup::sltGroupToggleStart); 1237 connect(m_pToggleButton, &UIGraphicsRotatorButton::sigRotationFinish, 1238 this, &UIChooserItemGroup::sltGroupToggleFinish); 435 1239 m_pToggleButton->hide(); 436 1240 437 1241 /* Setup enter-button: */ 438 1242 m_pEnterButton = new UIGraphicsButton(this, UIIconPool::iconSet(":/next_16px.png")); 439 connect(m_pEnterButton, SIGNAL(sigButtonClicked()), this, SLOT(sltIndentRoot())); 1243 connect(m_pEnterButton, &UIGraphicsButton::sigButtonClicked, 1244 this, &UIChooserItemGroup::sltIndentRoot); 440 1245 m_pEnterButton->hide(); 441 1246 … … 443 1248 m_pNameEditorWidget = new UIEditorGroupRename(name(), this); 444 1249 m_pNameEditorWidget->setFont(m_nameFont); 445 connect(m_pNameEditorWidget, SIGNAL(sigEditingFinished()), this, SLOT(sltNameEditingFinished())); 1250 connect(m_pNameEditorWidget, &UIEditorGroupRename::sigEditingFinished, 1251 this, &UIChooserItemGroup::sltNameEditingFinished); 446 1252 m_pNameEditor = new QGraphicsProxyWidget(this); 447 1253 m_pNameEditor->setWidget(m_pNameEditorWidget); … … 453 1259 /* Setup exit-button: */ 454 1260 m_pExitButton = new UIGraphicsButton(this, UIIconPool::iconSet(":/previous_16px.png")); 455 connect(m_pExitButton, SIGNAL(sigButtonClicked()), this, SLOT(sltUnindentRoot())); 1261 connect(m_pExitButton, &UIGraphicsButton::sigButtonClicked, 1262 this, &UIChooserItemGroup::sltUnindentRoot); 456 1263 QSizeF sh = m_pExitButton->minimumSizeHint(); 457 1264 m_pExitButton->setTransformOriginPoint(sh.width() / 2, sh.height() / 2); … … 479 1286 } 480 1287 481 void UIChooserItemGroup::handleRootStatusChange() 482 { 483 /* Call to base-class: */ 484 UIChooserItem::handleRootStatusChange(); 1288 QVariant UIChooserItemGroup::data(int iKey) const 1289 { 1290 /* Provide other members with required data: */ 1291 switch (iKey) 1292 { 1293 /* Layout hints: */ 1294 case GroupItemData_HorizonalMargin: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 4; 1295 case GroupItemData_VerticalMargin: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 4; 1296 case GroupItemData_MajorSpacing: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 2; 1297 case GroupItemData_MinorSpacing: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 5; 1298 case GroupItemData_RootIndent: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 6; 1299 1300 /* Default: */ 1301 default: break; 1302 } 1303 return QVariant(); 1304 } 1305 1306 void UIChooserItemGroup::setAdditionalHeight(int iAdditionalHeight) 1307 { 1308 m_iAdditionalHeight = iAdditionalHeight; 1309 updateGeometry(); 1310 model()->updateLayout(); 1311 } 1312 1313 int UIChooserItemGroup::additionalHeight() const 1314 { 1315 return m_iAdditionalHeight; 1316 } 1317 1318 void UIChooserItemGroup::updateAnimationParameters() 1319 { 1320 /* Only for item with button: */ 1321 if (!m_pToggleButton) 1322 return; 1323 1324 /* Recalculate animation parameters: */ 1325 QSizeF openedSize = minimumSizeHintForProup(true); 1326 QSizeF closedSize = minimumSizeHintForProup(false); 1327 int iAdditionalHeight = (int)(openedSize.height() - closedSize.height()); 1328 m_pToggleButton->setAnimationRange(0, iAdditionalHeight); 1329 } 1330 1331 void UIChooserItemGroup::updateToggleButtonToolTip() 1332 { 1333 /* Only for item with button: */ 1334 if (!m_pToggleButton) 1335 return; 1336 1337 /* Update toggle-button tool-tip: */ 1338 m_pToggleButton->setToolTip(isOpened() ? tr("Collapse group") : tr("Expand group")); 1339 } 1340 1341 bool UIChooserItemGroup::isContainsMachine(const QString &strId) const 1342 { 1343 /* Check each machine-item: */ 1344 foreach (UIChooserItem *pItem, m_machineItems) 1345 if (pItem->toMachineItem()->id() == strId) 1346 return true; 1347 /* Found nothing? */ 1348 return false; 1349 } 1350 1351 bool UIChooserItemGroup::isContainsLockedMachine() 1352 { 1353 /* Check each machine-item: */ 1354 foreach (UIChooserItem *pItem, items(UIChooserItemType_Machine)) 1355 if (pItem->toMachineItem()->isLockedMachine()) 1356 return true; 1357 /* Check each group-item: */ 1358 foreach (UIChooserItem *pItem, items(UIChooserItemType_Group)) 1359 if (pItem->toGroupItem()->isContainsLockedMachine()) 1360 return true; 1361 /* Found nothing? */ 1362 return false; 1363 } 1364 1365 void UIChooserItemGroup::updateItemCountInfo() 1366 { 1367 /* Not for main root: */ 1368 if (isMainRoot()) 1369 return; 1370 1371 /* Update item info attributes: */ 1372 QPaintDevice *pPaintDevice = model()->paintDevice(); 1373 QString strInfoGroups = m_groupItems.isEmpty() ? QString() : QString::number(m_groupItems.size()); 1374 QString strInfoMachines = m_machineItems.isEmpty() ? QString() : QString::number(m_machineItems.size()); 1375 QSize infoSizeGroups = textSize(m_infoFont, pPaintDevice, strInfoGroups); 1376 QSize infoSizeMachines = textSize(m_infoFont, pPaintDevice, strInfoMachines); 485 1377 486 1378 /* Update linked values: */ 487 updateVisibleName(); 488 updateMinimumHeaderSize(); 1379 bool fSomethingChanged = false; 1380 if (m_strInfoGroups != strInfoGroups) 1381 { 1382 m_strInfoGroups = strInfoGroups; 1383 fSomethingChanged = true; 1384 } 1385 if (m_strInfoMachines != strInfoMachines) 1386 { 1387 m_strInfoMachines = strInfoMachines; 1388 fSomethingChanged = true; 1389 } 1390 if (m_infoSizeGroups != infoSizeGroups) 1391 { 1392 m_infoSizeGroups = infoSizeGroups; 1393 fSomethingChanged = true; 1394 } 1395 if (m_infoSizeMachines != infoSizeMachines) 1396 { 1397 m_infoSizeMachines = infoSizeMachines; 1398 fSomethingChanged = true; 1399 } 1400 if (fSomethingChanged) 1401 { 1402 updateVisibleName(); 1403 updateMinimumHeaderSize(); 1404 } 1405 } 1406 1407 int UIChooserItemGroup::minimumWidthHintForGroup(bool fGroupOpened) const 1408 { 1409 /* Calculating proposed width: */ 1410 int iProposedWidth = 0; 1411 1412 /* Main root-item: */ 1413 if (isMainRoot()) 1414 { 1415 /* Main root-item always takes body into account: */ 1416 if (hasItems()) 1417 { 1418 /* Prepare variables: */ 1419 int iRootIndent = data(GroupItemData_RootIndent).toInt(); 1420 1421 /* We have to take every child width into account: */ 1422 int iMaximumChildWidth = 0; 1423 foreach (UIChooserItem *pItem, items()) 1424 iMaximumChildWidth = qMax(iMaximumChildWidth, pItem->minimumWidthHint()); 1425 iProposedWidth += iMaximumChildWidth; 1426 1427 /* And 2 indents at last - left and right: */ 1428 iProposedWidth += 2 * iRootIndent; 1429 } 1430 } 1431 /* Other items, including temporary roots: */ 1432 else 1433 { 1434 /* Prepare variables: */ 1435 int iHorizontalMargin = data(GroupItemData_HorizonalMargin).toInt(); 1436 1437 /* Basically we have to take header width into account: */ 1438 iProposedWidth += m_minimumHeaderSize.width(); 1439 1440 /* But if group-item is opened: */ 1441 if (fGroupOpened) 1442 { 1443 /* We have to take every child width into account: */ 1444 int iMaximumChildWidth = 0; 1445 foreach (UIChooserItem *pItem, items()) 1446 iMaximumChildWidth = qMax(iMaximumChildWidth, pItem->minimumWidthHint()); 1447 iProposedWidth = qMax(iProposedWidth, iMaximumChildWidth); 1448 } 1449 1450 /* And 2 margins at last - left and right: */ 1451 iProposedWidth += 2 * iHorizontalMargin; 1452 } 1453 1454 /* Return result: */ 1455 return iProposedWidth; 1456 } 1457 1458 int UIChooserItemGroup::minimumHeightHintForGroup(bool fGroupOpened) const 1459 { 1460 /* Prepare variables: */ 1461 int iMinorSpacing = data(GroupItemData_MinorSpacing).toInt(); 1462 1463 /* Calculating proposed height: */ 1464 int iProposedHeight = 0; 1465 1466 /* Main root-item: */ 1467 if (isMainRoot()) 1468 { 1469 /* Main root-item always takes body into account: */ 1470 if (hasItems()) 1471 { 1472 /* Prepare variables: */ 1473 int iRootIndent = data(GroupItemData_RootIndent).toInt(); 1474 1475 /* Main root-item have 2 indents - top and bottom: */ 1476 iProposedHeight += 2 * iRootIndent; 1477 /* And every existing: */ 1478 foreach (UIChooserItem *pItem, items()) 1479 { 1480 /* Child height: */ 1481 iProposedHeight += pItem->minimumHeightHint(); 1482 /* And interline spacing: */ 1483 iProposedHeight += iMinorSpacing; 1484 } 1485 /* Excpect the last one spacing: */ 1486 iProposedHeight -= iMinorSpacing; 1487 } 1488 } 1489 /* Other items, including temporary roots: */ 1490 else 1491 { 1492 /* Prepare variables: */ 1493 int iVerticalMargin = data(GroupItemData_VerticalMargin).toInt(); 1494 1495 /* Group-item header have 2 margins - top and bottom: */ 1496 iProposedHeight += 2 * iVerticalMargin; 1497 /* And header content height to take into account: */ 1498 iProposedHeight += m_minimumHeaderSize.height(); 1499 1500 /* But if group-item is opened: */ 1501 if (fGroupOpened) 1502 { 1503 /* Prepare variables: */ 1504 int iHorizontalMargin = data(GroupItemData_HorizonalMargin).toInt(); 1505 1506 /* We should take into spacing between header and body: */ 1507 iProposedHeight += iVerticalMargin; 1508 /* Every existing: */ 1509 foreach (UIChooserItem *pItem, items()) 1510 { 1511 /* Child height: */ 1512 iProposedHeight += pItem->minimumHeightHint(); 1513 /* And interline spacing: */ 1514 iProposedHeight += iMinorSpacing; 1515 } 1516 /* Excpect the last one spacing: */ 1517 iProposedHeight -= iMinorSpacing; 1518 /* And bottom margin at last: */ 1519 iProposedHeight += iHorizontalMargin; 1520 } 1521 1522 /* Finally, additional height during animation: */ 1523 if (!fGroupOpened && m_pToggleButton && m_pToggleButton->isAnimationRunning()) 1524 iProposedHeight += m_iAdditionalHeight; 1525 } 1526 1527 /* Return result: */ 1528 return iProposedHeight; 1529 } 1530 1531 QSizeF UIChooserItemGroup::minimumSizeHintForProup(bool fGroupOpened) const 1532 { 1533 return QSizeF(minimumWidthHintForGroup(fGroupOpened), minimumHeightHintForGroup(fGroupOpened)); 489 1534 } 490 1535 … … 565 1610 m_pixmapSizeGroups = m_groupsPixmap.size() / m_groupsPixmap.devicePixelRatio(); 566 1611 m_pixmapSizeMachines = m_machinesPixmap.size() / m_machinesPixmap.devicePixelRatio(); 567 }568 569 void UIChooserItemGroup::updateItemCountInfo()570 {571 /* Not for main root: */572 if (isMainRoot())573 return;574 575 /* Update item info attributes: */576 QPaintDevice *pPaintDevice = model()->paintDevice();577 QString strInfoGroups = m_groupItems.isEmpty() ? QString() : QString::number(m_groupItems.size());578 QString strInfoMachines = m_machineItems.isEmpty() ? QString() : QString::number(m_machineItems.size());579 QSize infoSizeGroups = textSize(m_infoFont, pPaintDevice, strInfoGroups);580 QSize infoSizeMachines = textSize(m_infoFont, pPaintDevice, strInfoMachines);581 582 /* Update linked values: */583 bool fSomethingChanged = false;584 if (m_strInfoGroups != strInfoGroups)585 {586 m_strInfoGroups = strInfoGroups;587 fSomethingChanged = true;588 }589 if (m_strInfoMachines != strInfoMachines)590 {591 m_strInfoMachines = strInfoMachines;592 fSomethingChanged = true;593 }594 if (m_infoSizeGroups != infoSizeGroups)595 {596 m_infoSizeGroups = infoSizeGroups;597 fSomethingChanged = true;598 }599 if (m_infoSizeMachines != infoSizeMachines)600 {601 m_infoSizeMachines = infoSizeMachines;602 fSomethingChanged = true;603 }604 if (fSomethingChanged)605 {606 updateVisibleName();607 updateMinimumHeaderSize();608 }609 1612 } 610 1613 … … 682 1685 } 683 1686 684 void UIChooserItemGroup::updateToolTip()685 {686 /* Not for main root: */687 if (isMainRoot())688 return;689 690 /* Prepare variables: */691 QStringList toolTipInfo;692 693 /* Should we add name? */694 if (!name().isEmpty())695 {696 /* Template: */697 QString strTemplateForName = tr("<b>%1</b>", "Group item tool-tip / Group name");698 699 /* Append value: */700 toolTipInfo << strTemplateForName.arg(name());701 }702 703 /* Should we add group info? */704 if (!items(UIChooserItemType_Group).isEmpty())705 {706 /* Template: */707 QString strGroupCount = tr("%n group(s)", "Group item tool-tip / Group info", items(UIChooserItemType_Group).size());708 709 /* Append value: */710 QString strValue = tr("<nobr>%1</nobr>", "Group item tool-tip / Group info wrapper").arg(strGroupCount);711 toolTipInfo << strValue;712 }713 714 /* Should we add machine info? */715 if (!items(UIChooserItemType_Machine).isEmpty())716 {717 /* Check if 'this' group contains started VMs: */718 int iCountOfStartedMachineItems = 0;719 foreach (UIChooserItem *pItem, items(UIChooserItemType_Machine))720 if (UIVirtualMachineItem::isItemStarted(pItem->toMachineItem()))721 ++iCountOfStartedMachineItems;722 /* Template: */723 QString strMachineCount = tr("%n machine(s)", "Group item tool-tip / Machine info", items(UIChooserItemType_Machine).size());724 QString strStartedMachineCount = tr("(%n running)", "Group item tool-tip / Running machine info", iCountOfStartedMachineItems);725 726 /* Append value: */727 QString strValue = !iCountOfStartedMachineItems ?728 tr("<nobr>%1</nobr>", "Group item tool-tip / Machine info wrapper").arg(strMachineCount) :729 tr("<nobr>%1 %2</nobr>", "Group item tool-tip / Machine info wrapper, including running").arg(strMachineCount).arg(strStartedMachineCount);730 toolTipInfo << strValue;731 }732 733 /* Set tool-tip: */734 setToolTip(toolTipInfo.join("<br>"));735 }736 737 void UIChooserItemGroup::updateToggleButtonToolTip()738 {739 /* Is toggle-button created? */740 if (!m_pToggleButton)741 return;742 743 /* Update toggle-button tool-tip: */744 m_pToggleButton->setToolTip(isOpened() ? tr("Collapse group") : tr("Expand group"));745 }746 747 void UIChooserItemGroup::retranslateUi()748 {749 /* Update description: */750 m_strDescription = tr("Virtual Machine group");751 752 /* Update group tool-tip: */753 updateToolTip();754 755 /* Update button tool-tips: */756 if (m_pEnterButton)757 m_pEnterButton->setToolTip(tr("Enter group"));758 if (m_pExitButton)759 m_pExitButton->setToolTip(tr("Exit group"));760 updateToggleButtonToolTip();761 }762 763 void UIChooserItemGroup::show()764 {765 /* Call to base-class: */766 UIChooserItem::show();767 /* Show children: */768 if (!isClosed())769 foreach (UIChooserItem *pItem, items())770 pItem->show();771 }772 773 void UIChooserItemGroup::hide()774 {775 /* Call to base-class: */776 UIChooserItem::hide();777 /* Hide children: */778 foreach (UIChooserItem *pItem, items())779 pItem->hide();780 }781 782 void UIChooserItemGroup::startEditing()783 {784 /* Not for root: */785 if (isRoot())786 return;787 788 /* Not while saving groups: */789 if (model()->isGroupSavingInProgress())790 return;791 792 /* Unlock name-editor: */793 m_pNameEditor->show();794 m_pNameEditorWidget->setText(name());795 m_pNameEditorWidget->setFocus();796 }797 798 void UIChooserItemGroup::addItem(UIChooserItem *pItem, int iPosition)799 {800 /* Check item type: */801 switch (pItem->type())802 {803 case UIChooserItemType_Group:804 {805 AssertMsg(!m_groupItems.contains(pItem), ("Group-item already added!"));806 if (iPosition < 0 || iPosition >= m_groupItems.size())807 m_groupItems.append(pItem);808 else809 m_groupItems.insert(iPosition, pItem);810 scene()->addItem(pItem);811 break;812 }813 case UIChooserItemType_Global:814 {815 AssertMsg(!m_globalItems.contains(pItem), ("Global-item already added!"));816 if (iPosition < 0 || iPosition >= m_globalItems.size())817 m_globalItems.append(pItem);818 else819 m_globalItems.insert(iPosition, pItem);820 scene()->addItem(pItem);821 break;822 }823 case UIChooserItemType_Machine:824 {825 AssertMsg(!m_machineItems.contains(pItem), ("Machine-item already added!"));826 if (iPosition < 0 || iPosition >= m_machineItems.size())827 m_machineItems.append(pItem);828 else829 m_machineItems.insert(iPosition, pItem);830 scene()->addItem(pItem);831 break;832 }833 default:834 {835 AssertMsgFailed(("Invalid item type!"));836 break;837 }838 }839 840 /* Update linked values: */841 updateItemCountInfo();842 updateToolTip();843 updateGeometry();844 }845 846 void UIChooserItemGroup::removeItem(UIChooserItem *pItem)847 {848 /* Check item type: */849 switch (pItem->type())850 {851 case UIChooserItemType_Group:852 {853 AssertMsg(m_groupItems.contains(pItem), ("Group-item was not found!"));854 scene()->removeItem(pItem);855 m_groupItems.removeAt(m_groupItems.indexOf(pItem));856 break;857 }858 case UIChooserItemType_Global:859 {860 AssertMsg(m_globalItems.contains(pItem), ("Global-item was not found!"));861 scene()->removeItem(pItem);862 m_globalItems.removeAt(m_globalItems.indexOf(pItem));863 break;864 }865 case UIChooserItemType_Machine:866 {867 AssertMsg(m_machineItems.contains(pItem), ("Machine-item was not found!"));868 scene()->removeItem(pItem);869 m_machineItems.removeAt(m_machineItems.indexOf(pItem));870 break;871 }872 default:873 {874 AssertMsgFailed(("Invalid item type!"));875 break;876 }877 }878 879 /* Update linked values: */880 updateItemCountInfo();881 updateToolTip();882 updateGeometry();883 }884 885 void UIChooserItemGroup::setItems(const QList<UIChooserItem*> &items, UIChooserItemType type)886 {887 /* Check item type: */888 switch (type)889 {890 case UIChooserItemType_Group: m_groupItems = items; break;891 case UIChooserItemType_Global: m_globalItems = items; break;892 case UIChooserItemType_Machine: m_machineItems = items; break;893 default: AssertMsgFailed(("Invalid item type!")); break;894 }895 896 /* Update linked values: */897 updateItemCountInfo();898 updateToolTip();899 updateGeometry();900 }901 902 QList<UIChooserItem*> UIChooserItemGroup::items(UIChooserItemType type /* = UIChooserItemType_Any */) const903 {904 switch (type)905 {906 case UIChooserItemType_Any: return items(UIChooserItemType_Global) + items(UIChooserItemType_Group) + items(UIChooserItemType_Machine);907 case UIChooserItemType_Group: return m_groupItems;908 case UIChooserItemType_Global: return m_globalItems;909 case UIChooserItemType_Machine: return m_machineItems;910 default: break;911 }912 return QList<UIChooserItem*>();913 }914 915 bool UIChooserItemGroup::hasItems(UIChooserItemType type /* = UIChooserItemType_Any */) const916 {917 switch (type)918 {919 case UIChooserItemType_Any:920 return hasItems(UIChooserItemType_Global) || hasItems(UIChooserItemType_Group) || hasItems(UIChooserItemType_Machine);921 case UIChooserItemType_Group:922 return !m_groupItems.isEmpty();923 case UIChooserItemType_Global:924 return !m_globalItems.isEmpty();925 case UIChooserItemType_Machine:926 return !m_machineItems.isEmpty();927 }928 return false;929 }930 931 void UIChooserItemGroup::clearItems(UIChooserItemType type /* = UIChooserItemType_Any */)932 {933 switch (type)934 {935 case UIChooserItemType_Any:936 {937 clearItems(UIChooserItemType_Group);938 clearItems(UIChooserItemType_Global);939 clearItems(UIChooserItemType_Machine);940 break;941 }942 case UIChooserItemType_Group:943 {944 while (!m_groupItems.isEmpty()) { delete m_groupItems.last(); }945 AssertMsg(m_groupItems.isEmpty(), ("Group items cleanup failed!"));946 break;947 }948 case UIChooserItemType_Global:949 {950 while (!m_globalItems.isEmpty()) { delete m_globalItems.last(); }951 AssertMsg(m_globalItems.isEmpty(), ("Global items cleanup failed!"));952 break;953 }954 case UIChooserItemType_Machine:955 {956 while (!m_machineItems.isEmpty()) { delete m_machineItems.last(); }957 AssertMsg(m_machineItems.isEmpty(), ("Machine items cleanup failed!"));958 break;959 }960 }961 962 /* Update linked values: */963 updateItemCountInfo();964 updateToolTip();965 updateGeometry();966 }967 968 void UIChooserItemGroup::updateAllItems(const QString &strId)969 {970 /* Update all the required items recursively: */971 foreach (UIChooserItem *pItem, items())972 pItem->updateAllItems(strId);973 }974 975 void UIChooserItemGroup::removeAllItems(const QString &strId)976 {977 /* Remove all the required items recursively: */978 foreach (UIChooserItem *pItem, items())979 pItem->removeAllItems(strId);980 }981 982 UIChooserItem* UIChooserItemGroup::searchForItem(const QString &strSearchTag, int iItemSearchFlags)983 {984 /* Are we searching among group-items? */985 if (iItemSearchFlags & UIChooserItemSearchFlag_Group)986 {987 /* Are we searching by the exact name? */988 if (iItemSearchFlags & UIChooserItemSearchFlag_ExactName)989 {990 /* Exact name matches? */991 if (name() == strSearchTag)992 return this;993 }994 /* Are we searching by the few first symbols? */995 else996 {997 /* Name starts with passed symbols? */998 if (name().startsWith(strSearchTag, Qt::CaseInsensitive))999 return this;1000 }1001 }1002 1003 /* Search among all the children, but machines first: */1004 foreach (UIChooserItem *pItem, items(UIChooserItemType_Machine))1005 if (UIChooserItem *pFoundItem = pItem->searchForItem(strSearchTag, iItemSearchFlags))1006 return pFoundItem;1007 foreach (UIChooserItem *pItem, items(UIChooserItemType_Global))1008 if (UIChooserItem *pFoundItem = pItem->searchForItem(strSearchTag, iItemSearchFlags))1009 return pFoundItem;1010 foreach (UIChooserItem *pItem, items(UIChooserItemType_Group))1011 if (UIChooserItem *pFoundItem = pItem->searchForItem(strSearchTag, iItemSearchFlags))1012 return pFoundItem;1013 1014 /* Found nothing? */1015 return 0;1016 }1017 1018 UIChooserItem *UIChooserItemGroup::firstMachineItem()1019 {1020 /* If this group-item have at least one machine-item: */1021 if (hasItems(UIChooserItemType_Machine))1022 /* Return the first machine-item: */1023 return items(UIChooserItemType_Machine).first()->firstMachineItem();1024 /* If this group-item have at least one group-item: */1025 else if (hasItems(UIChooserItemType_Group))1026 /* Return the first machine-item of the first group-item: */1027 return items(UIChooserItemType_Group).first()->firstMachineItem();1028 /* Found nothing? */1029 return 0;1030 }1031 1032 void UIChooserItemGroup::sortItems()1033 {1034 /* Sort group-items: */1035 QMap<QString, UIChooserItem*> sorter;1036 foreach (UIChooserItem *pItem, items(UIChooserItemType_Group))1037 sorter.insert(pItem->name().toLower(), pItem);1038 setItems(sorter.values(), UIChooserItemType_Group);1039 1040 /* Sort machine-items: */1041 sorter.clear();1042 foreach (UIChooserItem *pItem, items(UIChooserItemType_Machine))1043 sorter.insert(pItem->name().toLower(), pItem);1044 setItems(sorter.values(), UIChooserItemType_Machine);1045 1046 /* Update model: */1047 model()->updateNavigation();1048 model()->updateLayout();1049 }1050 1051 void UIChooserItemGroup::updateLayout()1052 {1053 /* Prepare variables: */1054 int iHorizontalMargin = data(GroupItemData_HorizonalMargin).toInt();1055 int iVerticalMargin = data(GroupItemData_VerticalMargin).toInt();1056 int iMinorSpacing = data(GroupItemData_MinorSpacing).toInt();1057 int iFullHeaderHeight = m_minimumHeaderSize.height();1058 int iRootIndent = data(GroupItemData_RootIndent).toInt();1059 int iPreviousVerticalIndent = 0;1060 1061 /* Header (root-item): */1062 if (isRoot())1063 {1064 /* Header (main root-item): */1065 if (isMainRoot())1066 {1067 /* Prepare body indent: */1068 iPreviousVerticalIndent = iRootIndent;1069 }1070 /* Header (non-main root-item): */1071 else1072 {1073 /* Hide unnecessary buttons: */1074 if (m_pToggleButton)1075 m_pToggleButton->hide();1076 if (m_pEnterButton)1077 m_pEnterButton->hide();1078 1079 /* Exit-button: */1080 if (m_pExitButton)1081 {1082 /* Prepare variables: */1083 int iExitButtonHeight = m_exitButtonSize.height();1084 /* Layout exit-button: */1085 int iExitButtonX = iHorizontalMargin + iRootIndent;1086 int iExitButtonY = iExitButtonHeight == iFullHeaderHeight ? iVerticalMargin :1087 iVerticalMargin + (iFullHeaderHeight - iExitButtonHeight) / 2;1088 m_pExitButton->setPos(iExitButtonX, iExitButtonY);1089 /* Show exit-button: */1090 m_pExitButton->show();1091 }1092 1093 /* Prepare body indent: */1094 iPreviousVerticalIndent = iVerticalMargin + iFullHeaderHeight + iVerticalMargin + iMinorSpacing;1095 }1096 }1097 /* Header (non-root-item): */1098 else1099 {1100 /* Hide unnecessary button: */1101 if (m_pExitButton)1102 m_pExitButton->hide();1103 1104 /* Toggle-button: */1105 if (m_pToggleButton)1106 {1107 /* Prepare variables: */1108 int iToggleButtonHeight = m_toggleButtonSize.height();1109 /* Layout toggle-button: */1110 int iToggleButtonX = iHorizontalMargin;1111 int iToggleButtonY = iToggleButtonHeight == iFullHeaderHeight ? iVerticalMargin :1112 iVerticalMargin + (iFullHeaderHeight - iToggleButtonHeight) / 2;1113 m_pToggleButton->setPos(iToggleButtonX, iToggleButtonY);1114 /* Show toggle-button: */1115 m_pToggleButton->show();1116 }1117 1118 /* Enter-button: */1119 if (m_pEnterButton)1120 {1121 /* Prepare variables: */1122 int iFullWidth = (int)geometry().width();1123 int iEnterButtonWidth = m_enterButtonSize.width();1124 int iEnterButtonHeight = m_enterButtonSize.height();1125 /* Layout enter-button: */1126 int iEnterButtonX = iFullWidth - iHorizontalMargin - iEnterButtonWidth;1127 int iEnterButtonY = iEnterButtonHeight == iFullHeaderHeight ? iVerticalMargin :1128 iVerticalMargin + (iFullHeaderHeight - iEnterButtonHeight) / 2;1129 m_pEnterButton->setPos(iEnterButtonX, iEnterButtonY);1130 }1131 1132 /* Name-editor: */1133 if (m_pNameEditor && m_pNameEditorWidget)1134 {1135 /* Prepare variables: */1136 int iMajorSpacing = data(GroupItemData_MajorSpacing).toInt();1137 int iToggleButtonWidth = m_toggleButtonSize.width();1138 /* Layout name-editor: */1139 int iNameEditorX = iHorizontalMargin + iToggleButtonWidth + iMajorSpacing;1140 int iNameEditorY = 1;1141 m_pNameEditor->setPos(iNameEditorX, iNameEditorY);1142 m_pNameEditorWidget->resize((int)(geometry().width() - iNameEditorX - iHorizontalMargin), m_pNameEditorWidget->height());1143 }1144 1145 /* Prepare body indent: */1146 iPreviousVerticalIndent = 3 * iVerticalMargin + iFullHeaderHeight;1147 }1148 1149 /* No body for closed group: */1150 if (isClosed())1151 {1152 /* Hide all the items: */1153 foreach (UIChooserItem *pItem, items())1154 pItem->hide();1155 }1156 /* Body for opened group: */1157 else1158 {1159 /* Prepare variables: */1160 int iHorizontalIndent = isRoot() ? iRootIndent : iHorizontalMargin;1161 QRect geo = geometry().toRect();1162 int iX = geo.x();1163 int iY = geo.y();1164 int iWidth = geo.width();1165 1166 /* Layout all the items: */1167 foreach (UIChooserItem *pItem, items())1168 {1169 /* Show if hidden: */1170 pItem->show();1171 /* Get item height-hint: */1172 int iMinimumHeight = pItem->minimumHeightHint();1173 /* Set item position: */1174 pItem->setPos(iX + iHorizontalIndent, iY + iPreviousVerticalIndent);1175 /* Set item size: */1176 pItem->resize(iWidth - 2 * iHorizontalIndent, iMinimumHeight);1177 /* Relayout group: */1178 pItem->updateLayout();1179 /* Update indent for next items: */1180 iPreviousVerticalIndent += (iMinimumHeight + iMinorSpacing);1181 }1182 }1183 }1184 1185 int UIChooserItemGroup::minimumWidthHint(bool fOpenedGroup) const1186 {1187 /* Calculating proposed width: */1188 int iProposedWidth = 0;1189 1190 /* Main root-item: */1191 if (isMainRoot())1192 {1193 /* Main root-item always takes body into account: */1194 if (hasItems())1195 {1196 /* Prepare variables: */1197 int iRootIndent = data(GroupItemData_RootIndent).toInt();1198 1199 /* We have to take every child width into account: */1200 int iMaximumChildWidth = 0;1201 foreach (UIChooserItem *pItem, items())1202 iMaximumChildWidth = qMax(iMaximumChildWidth, pItem->minimumWidthHint());1203 iProposedWidth += iMaximumChildWidth;1204 1205 /* And 2 indents at last - left and right: */1206 iProposedWidth += 2 * iRootIndent;1207 }1208 }1209 /* Other items, including temporary roots: */1210 else1211 {1212 /* Prepare variables: */1213 int iHorizontalMargin = data(GroupItemData_HorizonalMargin).toInt();1214 1215 /* Basically we have to take header width into account: */1216 iProposedWidth += m_minimumHeaderSize.width();1217 1218 /* But if group-item is opened: */1219 if (fOpenedGroup)1220 {1221 /* We have to take every child width into account: */1222 int iMaximumChildWidth = 0;1223 foreach (UIChooserItem *pItem, items())1224 iMaximumChildWidth = qMax(iMaximumChildWidth, pItem->minimumWidthHint());1225 iProposedWidth = qMax(iProposedWidth, iMaximumChildWidth);1226 }1227 1228 /* And 2 margins at last - left and right: */1229 iProposedWidth += 2 * iHorizontalMargin;1230 }1231 1232 /* Return result: */1233 return iProposedWidth;1234 }1235 1236 int UIChooserItemGroup::minimumHeightHint(bool fOpenedGroup) const1237 {1238 /* Prepare variables: */1239 int iMinorSpacing = data(GroupItemData_MinorSpacing).toInt();1240 1241 /* Calculating proposed height: */1242 int iProposedHeight = 0;1243 1244 /* Main root-item: */1245 if (isMainRoot())1246 {1247 /* Main root-item always takes body into account: */1248 if (hasItems())1249 {1250 /* Prepare variables: */1251 int iRootIndent = data(GroupItemData_RootIndent).toInt();1252 1253 /* Main root-item have 2 indents - top and bottom: */1254 iProposedHeight += 2 * iRootIndent;1255 /* And every existing: */1256 foreach (UIChooserItem *pItem, items())1257 {1258 /* Child height: */1259 iProposedHeight += pItem->minimumHeightHint();1260 /* And interline spacing: */1261 iProposedHeight += iMinorSpacing;1262 }1263 /* Excpect the last one spacing: */1264 iProposedHeight -= iMinorSpacing;1265 }1266 }1267 /* Other items, including temporary roots: */1268 else1269 {1270 /* Prepare variables: */1271 int iVerticalMargin = data(GroupItemData_VerticalMargin).toInt();1272 1273 /* Group-item header have 2 margins - top and bottom: */1274 iProposedHeight += 2 * iVerticalMargin;1275 /* And header content height to take into account: */1276 iProposedHeight += m_minimumHeaderSize.height();1277 1278 /* But if group-item is opened: */1279 if (fOpenedGroup)1280 {1281 /* Prepare variables: */1282 int iHorizontalMargin = data(GroupItemData_HorizonalMargin).toInt();1283 1284 /* We should take into spacing between header and body: */1285 iProposedHeight += iVerticalMargin;1286 /* Every existing: */1287 foreach (UIChooserItem *pItem, items())1288 {1289 /* Child height: */1290 iProposedHeight += pItem->minimumHeightHint();1291 /* And interline spacing: */1292 iProposedHeight += iMinorSpacing;1293 }1294 /* Excpect the last one spacing: */1295 iProposedHeight -= iMinorSpacing;1296 /* And bottom margin at last: */1297 iProposedHeight += iHorizontalMargin;1298 }1299 1300 /* Finally, additional height during animation: */1301 if (!fOpenedGroup && m_pToggleButton && m_pToggleButton->isAnimationRunning())1302 iProposedHeight += m_iAdditionalHeight;1303 }1304 1305 /* Return result: */1306 return iProposedHeight;1307 }1308 1309 int UIChooserItemGroup::minimumWidthHint() const1310 {1311 return minimumWidthHint(isOpened());1312 }1313 1314 int UIChooserItemGroup::minimumHeightHint() const1315 {1316 return minimumHeightHint(isOpened());1317 }1318 1319 QSizeF UIChooserItemGroup::minimumSizeHint(bool fOpenedGroup) const1320 {1321 return QSizeF(minimumWidthHint(fOpenedGroup), minimumHeightHint(fOpenedGroup));1322 }1323 1324 QSizeF UIChooserItemGroup::sizeHint(Qt::SizeHint which, const QSizeF &constraint /* = QSizeF() */) const1325 {1326 /* If Qt::MinimumSize requested: */1327 if (which == Qt::MinimumSize)1328 return minimumSizeHint(isOpened());1329 /* Else call to base-class: */1330 return UIChooserItem::sizeHint(which, constraint);1331 }1332 1333 QPixmap UIChooserItemGroup::toPixmap()1334 {1335 /* Ask item to paint itself into pixmap: */1336 QSize minimumSize = minimumSizeHint(false).toSize();1337 QPixmap pixmap(minimumSize);1338 pixmap.fill(Qt::transparent);1339 QPainter painter(&pixmap);1340 painter.setRenderHint(QPainter::Antialiasing);1341 QStyleOptionGraphicsItem options;1342 options.rect = QRect(QPoint(0, 0), minimumSize);1343 paint(&painter, &options);1344 return pixmap;1345 }1346 1347 bool UIChooserItemGroup::isDropAllowed(QGraphicsSceneDragDropEvent *pEvent, DragToken where) const1348 {1349 /* No drops while saving groups: */1350 if (model()->isGroupSavingInProgress())1351 return false;1352 /* Get mime: */1353 const QMimeData *pMimeData = pEvent->mimeData();1354 /* If drag token is shown, its up to parent to decide: */1355 if (where != DragToken_Off)1356 return parentItem()->isDropAllowed(pEvent);1357 /* Else we should check mime format: */1358 if (pMimeData->hasFormat(UIChooserItemGroup::className()))1359 {1360 /* Get passed group-item: */1361 const UIChooserItemMimeData *pCastedMimeData = qobject_cast<const UIChooserItemMimeData*>(pMimeData);1362 AssertMsg(pCastedMimeData, ("Can't cast passed mime-data to UIChooserItemMimeData!"));1363 UIChooserItem *pItem = pCastedMimeData->item();1364 /* Make sure passed group is mutable within this group: */1365 if (pItem->toGroupItem()->isContainsLockedMachine() &&1366 !items(UIChooserItemType_Group).contains(pItem))1367 return false;1368 /* Make sure passed group is not 'this': */1369 if (pItem == this)1370 return false;1371 /* Make sure passed group is not among our parents: */1372 const UIChooserItem *pTestedWidget = this;1373 while (UIChooserItem *pParentOfTestedWidget = pTestedWidget->parentItem())1374 {1375 if (pItem == pParentOfTestedWidget)1376 return false;1377 pTestedWidget = pParentOfTestedWidget;1378 }1379 return true;1380 }1381 else if (pMimeData->hasFormat(UIChooserItemMachine::className()))1382 {1383 /* Get passed machine-item: */1384 const UIChooserItemMimeData *pCastedMimeData = qobject_cast<const UIChooserItemMimeData*>(pMimeData);1385 AssertMsg(pCastedMimeData, ("Can't cast passed mime-data to UIChooserItemMimeData!"));1386 UIChooserItem *pItem = pCastedMimeData->item();1387 /* Make sure passed machine is mutable within this group: */1388 if (pItem->toMachineItem()->isLockedMachine() &&1389 !items(UIChooserItemType_Machine).contains(pItem))1390 return false;1391 switch (pEvent->proposedAction())1392 {1393 case Qt::MoveAction:1394 {1395 /* Make sure passed item is ours or there is no other item with such id: */1396 return m_machineItems.contains(pItem) || !isContainsMachine(pItem->toMachineItem()->id());1397 }1398 case Qt::CopyAction:1399 {1400 /* Make sure there is no other item with such id: */1401 return !isContainsMachine(pItem->toMachineItem()->id());1402 }1403 default: break; /* Shut up, MSC! */1404 }1405 }1406 /* That was invalid mime: */1407 return false;1408 }1409 1410 void UIChooserItemGroup::processDrop(QGraphicsSceneDragDropEvent *pEvent, UIChooserItem *pFromWho, DragToken where)1411 {1412 /* Get mime: */1413 const QMimeData *pMime = pEvent->mimeData();1414 /* Check mime format: */1415 if (pMime->hasFormat(UIChooserItemGroup::className()))1416 {1417 switch (pEvent->proposedAction())1418 {1419 case Qt::MoveAction:1420 case Qt::CopyAction:1421 {1422 /* Remember scene: */1423 UIChooserModel *pModel = model();1424 1425 /* Get passed group-item: */1426 const UIChooserItemMimeData *pCastedMime = qobject_cast<const UIChooserItemMimeData*>(pMime);1427 AssertMsg(pCastedMime, ("Can't cast passed mime-data to UIChooserItemMimeData!"));1428 UIChooserItem *pItem = pCastedMime->item();1429 1430 /* Check if we have position information: */1431 int iPosition = m_groupItems.size();1432 if (pFromWho && where != DragToken_Off)1433 {1434 /* Make sure sender item if our child: */1435 AssertMsg(m_groupItems.contains(pFromWho), ("Sender item is NOT our child!"));1436 if (m_groupItems.contains(pFromWho))1437 {1438 iPosition = m_groupItems.indexOf(pFromWho);1439 if (where == DragToken_Down)1440 ++iPosition;1441 }1442 }1443 1444 /* Copy passed item into this group: */1445 UIChooserItem *pNewGroupItem = new UIChooserItemGroup(this, pItem->toGroupItem(), iPosition);1446 if (isClosed())1447 open(false);1448 1449 /* If proposed action is 'move': */1450 if (pEvent->proposedAction() == Qt::MoveAction)1451 {1452 /* Delete passed item: */1453 delete pItem;1454 }1455 1456 /* Update model: */1457 pModel->cleanupGroupTree();1458 pModel->updateNavigation();1459 pModel->updateLayout();1460 pModel->setCurrentItem(pNewGroupItem);1461 pModel->saveGroupSettings();1462 break;1463 }1464 default:1465 break;1466 }1467 }1468 else if (pMime->hasFormat(UIChooserItemMachine::className()))1469 {1470 switch (pEvent->proposedAction())1471 {1472 case Qt::MoveAction:1473 case Qt::CopyAction:1474 {1475 /* Remember scene: */1476 UIChooserModel *pModel = model();1477 1478 /* Get passed item: */1479 const UIChooserItemMimeData *pCastedMime = qobject_cast<const UIChooserItemMimeData*>(pMime);1480 AssertMsg(pCastedMime, ("Can't cast passed mime-data to UIChooserItemMimeData!"));1481 UIChooserItem *pItem = pCastedMime->item();1482 1483 /* Check if we have position information: */1484 int iPosition = m_machineItems.size();1485 if (pFromWho && where != DragToken_Off)1486 {1487 /* Make sure sender item if our child: */1488 AssertMsg(m_machineItems.contains(pFromWho), ("Sender item is NOT our child!"));1489 if (m_machineItems.contains(pFromWho))1490 {1491 iPosition = m_machineItems.indexOf(pFromWho);1492 if (where == DragToken_Down)1493 ++iPosition;1494 }1495 }1496 1497 /* Copy passed machine-item into this group: */1498 UIChooserItem *pNewMachineItem = new UIChooserItemMachine(this, pItem->toMachineItem(), iPosition);1499 if (isClosed())1500 open(false);1501 1502 /* If proposed action is 'move': */1503 if (pEvent->proposedAction() == Qt::MoveAction)1504 {1505 /* Delete passed item: */1506 delete pItem;1507 }1508 1509 /* Update model: */1510 pModel->cleanupGroupTree();1511 pModel->updateNavigation();1512 pModel->updateLayout();1513 pModel->setCurrentItem(pNewMachineItem);1514 pModel->saveGroupSettings();1515 break;1516 }1517 default:1518 break;1519 }1520 }1521 }1522 1523 void UIChooserItemGroup::resetDragToken()1524 {1525 /* Reset drag token for this item: */1526 if (dragTokenPlace() != DragToken_Off)1527 {1528 setDragTokenPlace(DragToken_Off);1529 update();1530 }1531 /* Reset drag tokens for all the items: */1532 foreach (UIChooserItem *pItem, items())1533 pItem->resetDragToken();1534 }1535 1536 QMimeData* UIChooserItemGroup::createMimeData()1537 {1538 return new UIChooserItemMimeData(this);1539 }1540 1541 void UIChooserItemGroup::showEvent(QShowEvent *pEvent)1542 {1543 /* Call to base-class: */1544 UIChooserItem::showEvent(pEvent);1545 1546 /* Update pixmaps: */1547 updatePixmaps();1548 }1549 1550 void UIChooserItemGroup::resizeEvent(QGraphicsSceneResizeEvent *pEvent)1551 {1552 /* Call to base-class: */1553 UIChooserItem::resizeEvent(pEvent);1554 1555 /* What is the new geometry? */1556 QRectF newGeometry = geometry();1557 1558 /* Should we update visible name? */1559 if (previousGeometry().width() != newGeometry.width())1560 updateVisibleName();1561 1562 /* Remember the new geometry: */1563 setPreviousGeometry(newGeometry);1564 }1565 1566 void UIChooserItemGroup::hoverMoveEvent(QGraphicsSceneHoverEvent *pEvent)1567 {1568 /* Skip if hovered: */1569 if (isHovered())1570 return;1571 1572 /* Prepare variables: */1573 QPoint pos = pEvent->pos().toPoint();1574 int iMargin = data(GroupItemData_VerticalMargin).toInt();1575 int iHeaderHeight = m_minimumHeaderSize.height();1576 int iFullHeaderHeight = 2 * iMargin + iHeaderHeight;1577 /* Skip if hovered part out of the header: */1578 if (pos.y() >= iFullHeaderHeight)1579 return;1580 1581 /* Call to base-class: */1582 UIChooserItem::hoverMoveEvent(pEvent);1583 1584 /* Update linked values: */1585 updateVisibleName();1586 }1587 1588 void UIChooserItemGroup::hoverLeaveEvent(QGraphicsSceneHoverEvent *pEvent)1589 {1590 /* Skip if not hovered: */1591 if (!isHovered())1592 return;1593 1594 /* Call to base-class: */1595 UIChooserItem::hoverLeaveEvent(pEvent);1596 1597 /* Update linked values: */1598 updateVisibleName();1599 }1600 1601 void UIChooserItemGroup::paint(QPainter *pPainter, const QStyleOptionGraphicsItem *pOption, QWidget* /* pWidget = 0 */)1602 {1603 /* Setup: */1604 pPainter->setRenderHint(QPainter::Antialiasing);1605 1606 /* Paint background: */1607 paintBackground(pPainter, pOption->rect);1608 1609 /* Paint header: */1610 paintHeader(pPainter, pOption->rect);1611 }1612 1613 1687 void UIChooserItemGroup::paintBackground(QPainter *pPainter, const QRect &rect) 1614 1688 { … … 1873 1947 } 1874 1948 1875 void UIChooserItemGroup::updateAnimationParameters() 1876 { 1877 /* Only for item with button: */ 1878 if (!m_pToggleButton) 1879 return; 1880 1881 /* Recalculate animation parameters: */ 1882 QSizeF openedSize = minimumSizeHint(true); 1883 QSizeF closedSize = minimumSizeHint(false); 1884 int iAdditionalHeight = (int)(openedSize.height() - closedSize.height()); 1885 m_pToggleButton->setAnimationRange(0, iAdditionalHeight); 1886 } 1887 1888 void UIChooserItemGroup::setAdditionalHeight(int iAdditionalHeight) 1889 { 1890 m_iAdditionalHeight = iAdditionalHeight; 1891 updateGeometry(); 1892 model()->updateLayout(); 1893 } 1894 1895 int UIChooserItemGroup::additionalHeight() const 1896 { 1897 return m_iAdditionalHeight; 1898 } 1949 1950 /********************************************************************************************************************************* 1951 * Class UIEditorGroupRename implementation. * 1952 *********************************************************************************************************************************/ 1899 1953 1900 1954 UIEditorGroupRename::UIEditorGroupRename(const QString &strName, UIChooserItem *pParent) … … 1903 1957 , m_pTemporaryMenu(0) 1904 1958 { 1905 /* Create line-edit: */ 1906 m_pLineEdit = new QLineEdit(strName, this); 1907 m_pLineEdit->setTextMargins(0, 0, 0, 0); 1908 connect(m_pLineEdit, SIGNAL(returnPressed()), this, SIGNAL(sigEditingFinished())); 1909 /* Create main-layout: */ 1959 /* Create layout: */ 1910 1960 QHBoxLayout *pLayout = new QHBoxLayout(this); 1911 pLayout->setContentsMargins(0, 0, 0, 0); 1912 /* Add line-edit into main-layout: */ 1913 pLayout->addWidget(m_pLineEdit); 1961 if (pLayout) 1962 { 1963 /* Configure layout: */ 1964 pLayout->setContentsMargins(0, 0, 0, 0); 1965 1966 /* Create line-edit: */ 1967 m_pLineEdit = new QLineEdit(strName); 1968 if (m_pLineEdit) 1969 { 1970 m_pLineEdit->setTextMargins(0, 0, 0, 0); 1971 connect(m_pLineEdit, &QLineEdit::returnPressed, 1972 this, &UIEditorGroupRename::sigEditingFinished); 1973 } 1974 1975 /* Add into layout: */ 1976 pLayout->addWidget(m_pLineEdit); 1977 } 1978 1914 1979 /* Install event-filter: */ 1915 1980 m_pLineEdit->installEventFilter(this); 1916 1981 } 1917 1982 1983 void UIEditorGroupRename::setText(const QString &strText) 1984 { 1985 m_pLineEdit->setText(strText); 1986 } 1987 1918 1988 QString UIEditorGroupRename::text() const 1919 1989 { 1920 1990 return m_pLineEdit->text(); 1921 }1922 1923 void UIEditorGroupRename::setText(const QString &strText)1924 {1925 m_pLineEdit->setText(strText);1926 1991 } 1927 1992 -
trunk/src/VBox/Frontends/VirtualBox/src/manager/chooser/UIChooserItemGroup.h
r73927 r73948 5 5 6 6 /* 7 * Copyright (C) 2012-201 7Oracle Corporation7 * Copyright (C) 2012-2018 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 16 16 */ 17 17 18 #ifndef __ UIChooserItemGroup_h__19 #define __ UIChooserItemGroup_h__18 #ifndef ___UIChooserItemGroup_h___ 19 #define ___UIChooserItemGroup_h___ 20 20 21 21 /* Qt includes: */ 22 #include <QPixmap> 23 #include <QString> 22 24 #include <QWidget> 23 #include <QPixmap>24 25 25 26 /* GUI includes: */ … … 27 28 28 29 /* Forward declarations: */ 30 class QGraphicsProxyWidget; 29 31 class QGraphicsScene; 30 class QGraphicsProxyWidget;31 32 class QLineEdit; 33 class QMenu; 34 class QMimeData; 35 class QPainter; 36 class QStyleOptionGraphicsItem; 37 class UIEditorGroupRename; 32 38 class UIGraphicsButton; 33 39 class UIGraphicsRotatorButton; 34 class UIEditorGroupRename; 35 36 /* Graphics group-item 37 * for graphics selector model/view architecture: */ 40 41 42 /** UIChooserItem extension implementing group item. */ 38 43 class UIChooserItemGroup : public UIChooserItem 39 44 { … … 43 48 signals: 44 49 45 /* Notifiers: Toggle stuff: */ 46 void sigToggleStarted(); 47 void sigToggleFinished(); 50 /** @name Item stuff. 51 * @{ */ 52 /** Notifies listeners about toggle start. */ 53 void sigToggleStarted(); 54 /** Notifies listeners about toggle finish. */ 55 void sigToggleFinished(); 56 /** @} */ 48 57 49 58 public: 50 59 51 /* Class-name used for drag&drop mime-data format: */ 52 static QString className(); 53 54 /* Graphics-item type: */ 60 /** RTTI item type. */ 55 61 enum { Type = UIChooserItemType_Group }; 56 int type() const { return Type; } 57 58 /* Constructor (main-root-item): */ 62 63 /** Constructs main-root item passing pScene to the base-class. */ 59 64 UIChooserItemGroup(QGraphicsScene *pScene); 60 /* Constructor (temporary main-root-item/root-item copy):*/65 /** Constructs temporary @a fMainRoot item as a @a pCopyFrom passing pScene to the base-class. */ 61 66 UIChooserItemGroup(QGraphicsScene *pScene, UIChooserItemGroup *pCopyFrom, bool fMainRoot); 62 /* Constructor (new non-root-item):*/67 /** Constructs non-root item with specified @a strName and @a iPosition, @a fOpened if requested. */ 63 68 UIChooserItemGroup(UIChooserItem *pParent, const QString &strName, bool fOpened = false, int iPosition = -1); 64 /* Constructor (new non-root-item copy):*/69 /** Constructs temporary non-root item with specified @a iPosition as a @a pCopyFrom. */ 65 70 UIChooserItemGroup(UIChooserItem *pParent, UIChooserItemGroup *pCopyFrom, int iPosition = -1); 66 /* Destructor:*/71 /** Destructs group item. */ 67 72 ~UIChooserItemGroup(); 68 73 69 /* API: Basic stuff: */ 70 QString name() const; 71 QString description() const; 72 QString fullName() const; 73 QString definition() const; 74 void setName(const QString &strName); 75 bool isClosed() const; 76 bool isOpened() const; 77 void close(bool fAnimated = true); 78 void open(bool fAnimated = true); 79 80 /* API: Children stuff: */ 81 bool isContainsMachine(const QString &strId) const; 82 bool isContainsLockedMachine(); 74 /** @name Item stuff. 75 * @{ */ 76 /** Defines group @a strName. */ 77 void setName(const QString &strName); 78 79 /** Closes group in @a fAnimated way if requested. */ 80 void close(bool fAnimated = true); 81 /** Returns whether group is closed. */ 82 bool isClosed() const; 83 84 /** Opens group in @a fAnimated way if requested. */ 85 void open(bool fAnimated = true); 86 /** Returns whether group is opened. */ 87 bool isOpened() const; 88 /** @} */ 89 90 /** @name Navigation stuff. 91 * @{ */ 92 /** Class-name used for drag&drop mime-data format. */ 93 static QString className(); 94 /** @} */ 95 96 protected: 97 98 /** @name Event-handling stuff. 99 * @{ */ 100 /** Handles translation event. */ 101 virtual void retranslateUi() /* override */; 102 103 /** Handles show @a pEvent. */ 104 virtual void showEvent(QShowEvent *pEvent) /* override */; 105 106 /** Handles resize @a pEvent. */ 107 virtual void resizeEvent(QGraphicsSceneResizeEvent *pEvent) /* override */; 108 109 /** Handles hover enter @a event. */ 110 virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *pEvent) /* override */; 111 /** Handles hover leave @a event. */ 112 virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *pEvent) /* override */; 113 114 /** Performs painting using passed @a pPainter, @a pOptions and optionally specified @a pWidget. */ 115 virtual void paint(QPainter *pPainter, const QStyleOptionGraphicsItem *pOptions, QWidget *pWidget = 0) /* override */; 116 /** @} */ 117 118 /** @name Item stuff. 119 * @{ */ 120 /** Returns RTTI item type. */ 121 virtual int type() const /* override */ { return Type; } 122 123 /** Shows item. */ 124 virtual void show() /* override */; 125 /** Hides item. */ 126 virtual void hide() /* override */; 127 128 /** Starts item editing. */ 129 virtual void startEditing() /* override */; 130 131 /** Updates item tool-tip. */ 132 virtual void updateToolTip() /* override */; 133 134 /** Returns item name. */ 135 virtual QString name() const /* override */; 136 /** Returns item description. */ 137 virtual QString description() const /* override */; 138 /** Returns item full-name. */ 139 virtual QString fullName() const /* override */; 140 /** Returns item definition. */ 141 virtual QString definition() const /* override */; 142 143 /** Handles root status change. */ 144 virtual void handleRootStatusChange() /* override */; 145 /** @} */ 146 147 /** @name Children stuff. 148 * @{ */ 149 /** Adds child @a pItem to certain @a iPosition. */ 150 virtual void addItem(UIChooserItem *pItem, int iPosition) /* override */; 151 /** Removes child @a pItem. */ 152 virtual void removeItem(UIChooserItem *pItem) /* override */; 153 154 /** Replaces children @a items of certain @a enmType. */ 155 virtual void setItems(const QList<UIChooserItem*> &items, UIChooserItemType enmType) /* override */; 156 /** Returns children items of certain @a enmType. */ 157 virtual QList<UIChooserItem*> items(UIChooserItemType enmType = UIChooserItemType_Any) const /* override */; 158 /** Returns whether there are children items of certain @a enmType. */ 159 virtual bool hasItems(UIChooserItemType enmType = UIChooserItemType_Any) const /* override */; 160 /** Clears children items of certain @a enmType. */ 161 virtual void clearItems(UIChooserItemType enmType = UIChooserItemType_Any) /* override */; 162 163 /** Updates all children items with specified @a strId. */ 164 virtual void updateAllItems(const QString &strId) /* override */; 165 /** Removes all children items with specified @a strId. */ 166 virtual void removeAllItems(const QString &strId) /* override */; 167 168 /** Searches for a first child item answering to specified @a strSearchTag and @a iItemSearchFlags. */ 169 virtual UIChooserItem *searchForItem(const QString &strSearchTag, int iItemSearchFlags) /* override */; 170 171 /** Searches for a first machine child item. */ 172 virtual UIChooserItem *firstMachineItem() /* override */; 173 174 /** Sorts children items. */ 175 virtual void sortItems() /* override */; 176 /** @} */ 177 178 /** @name Layout stuff. 179 * @{ */ 180 /** Updates layout. */ 181 virtual void updateLayout() /* override */; 182 183 /** Returns minimum width-hint. */ 184 virtual int minimumWidthHint() const /* override */; 185 /** Returns minimum height-hint. */ 186 virtual int minimumHeightHint() const /* override */; 187 188 /** Returns size-hint. 189 * @param enmWhich Brings size-hint type. 190 * @param constraint Brings size constraint. */ 191 virtual QSizeF sizeHint(Qt::SizeHint enmWhich, const QSizeF &constraint = QSizeF()) const /* override */; 192 /** @} */ 193 194 /** @name Navigation stuff. 195 * @{ */ 196 /** Returns pixmap item representation. */ 197 virtual QPixmap toPixmap() /* override */; 198 199 /** Returns whether item drop is allowed. 200 * @param pEvent Brings information about drop event. 201 * @param enmPlace Brings the place of drag token to the drop moment. */ 202 virtual bool isDropAllowed(QGraphicsSceneDragDropEvent *pEvent, DragToken where) const /* override */; 203 /** Processes item drop. 204 * @param pEvent Brings information about drop event. 205 * @param pFromWho Brings the item according to which we choose drop position. 206 * @param enmPlace Brings the place of drag token to the drop moment (according to item mentioned above). */ 207 virtual void processDrop(QGraphicsSceneDragDropEvent *pEvent, UIChooserItem *pFromWho, DragToken where) /* override */; 208 /** Reset drag token. */ 209 virtual void resetDragToken() /* override */; 210 211 /** Returns D&D mime data. */ 212 virtual QMimeData *createMimeData() /* override */; 213 /** @} */ 83 214 84 215 private slots: 85 216 86 /** Handles top-level window remaps. */ 87 void sltHandleWindowRemapped(); 88 89 /* Handler: Name editing stuff: */ 90 void sltNameEditingFinished(); 91 92 /* Handler: Toggle stuff: */ 93 void sltGroupToggleStart(); 94 void sltGroupToggleFinish(bool fToggled); 95 96 /* Handlers: Indent root stuff: */ 97 void sltIndentRoot(); 98 void sltUnindentRoot(); 217 /** @name Item stuff. 218 * @{ */ 219 /** Handles top-level window remaps. */ 220 void sltHandleWindowRemapped(); 221 222 /** Handles name editing trigger. */ 223 void sltNameEditingFinished(); 224 225 /** Handles group toggle start. */ 226 void sltGroupToggleStart(); 227 /** Handles group toggle finish for group finally @a fToggled. */ 228 void sltGroupToggleFinish(bool fToggled); 229 230 /** Handles root indentation. */ 231 void sltIndentRoot(); 232 /** Handles root unindentation. */ 233 void sltUnindentRoot(); 234 /** @} */ 99 235 100 236 private: 101 237 102 /* Data enumerator:*/238 /** Data field types. */ 103 239 enum GroupItemData 104 240 { … … 111 247 }; 112 248 113 /* Data provider: */ 114 QVariant data(int iKey) const; 115 116 /* Helpers: Prepare stuff: */ 117 void prepare(); 118 static void copyContent(UIChooserItemGroup *pFrom, UIChooserItemGroup *pTo); 119 120 /* Helpers: Update stuff: */ 121 void handleRootStatusChange(); 122 void updateVisibleName(); 123 void updatePixmaps(); 124 void updateItemCountInfo(); 125 void updateMinimumHeaderSize(); 126 void updateToolTip(); 127 void updateToggleButtonToolTip(); 128 129 /* Helper: Translate stuff: */ 130 void retranslateUi(); 131 132 /* Helpers: Basic stuff: */ 133 void show(); 134 void hide(); 135 void startEditing(); 136 bool isMainRoot() const { return m_fMainRoot; } 137 138 /* Helpers: Children stuff: */ 139 void addItem(UIChooserItem *pItem, int iPosition); 140 void removeItem(UIChooserItem *pItem); 141 void setItems(const QList<UIChooserItem*> &items, UIChooserItemType type); 142 QList<UIChooserItem*> items(UIChooserItemType type = UIChooserItemType_Any) const; 143 bool hasItems(UIChooserItemType type = UIChooserItemType_Any) const; 144 void clearItems(UIChooserItemType type = UIChooserItemType_Any); 145 void updateAllItems(const QString &strId); 146 void removeAllItems(const QString &strId); 147 UIChooserItem *searchForItem(const QString &strSearchTag, int iItemSearchFlags); 148 UIChooserItem *firstMachineItem(); 149 void sortItems(); 150 151 /* Helpers: Layout stuff: */ 152 void updateLayout(); 153 int minimumWidthHint(bool fOpenedGroup) const; 154 int minimumHeightHint(bool fOpenedGroup) const; 155 int minimumWidthHint() const; 156 int minimumHeightHint() const; 157 #ifdef VBOX_WS_MAC 158 # pragma clang diagnostic push 159 # pragma clang diagnostic ignored "-Woverloaded-virtual" 160 #endif 161 QSizeF minimumSizeHint(bool fOpenedGroup) const; 162 #ifdef VBOX_WS_MAC 163 # pragma clang diagnostic pop 164 #endif 165 QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const; 166 167 /* Helpers: Drag&drop stuff: */ 168 QPixmap toPixmap(); 169 bool isDropAllowed(QGraphicsSceneDragDropEvent *pEvent, DragToken where) const; 170 void processDrop(QGraphicsSceneDragDropEvent *pEvent, UIChooserItem *pFromWho, DragToken where); 171 void resetDragToken(); 172 QMimeData* createMimeData(); 173 174 /** Handles show @a pEvent. */ 175 virtual void showEvent(QShowEvent *pEvent) /* override */; 176 177 /* Handler: Resize handling stuff: */ 178 void resizeEvent(QGraphicsSceneResizeEvent *pEvent); 179 180 /* Handlers: Hover handling stuff: */ 181 void hoverMoveEvent(QGraphicsSceneHoverEvent *pEvent); 182 void hoverLeaveEvent(QGraphicsSceneHoverEvent *pEvent); 183 184 /* Helpers: Paint stuff: */ 185 void paint(QPainter *pPainter, const QStyleOptionGraphicsItem *pOption, QWidget *pWidget = 0); 186 void paintBackground(QPainter *pPainter, const QRect &rect); 187 void paintHeader(QPainter *pPainter, const QRect &rect); 188 189 /* Helpers: Animation stuff: */ 190 void updateAnimationParameters(); 191 void setAdditionalHeight(int iAdditionalHeight); 192 int additionalHeight() const; 193 194 /* Helper: Color stuff: */ 195 int blackoutDarkness() const { return m_iBlackoutDarkness; } 196 197 /* Variables: */ 198 bool m_fClosed; 199 UIGraphicsRotatorButton *m_pToggleButton; 200 UIGraphicsButton *m_pEnterButton; 201 UIGraphicsButton *m_pExitButton; 202 UIEditorGroupRename *m_pNameEditorWidget; 203 QGraphicsProxyWidget *m_pNameEditor; 204 QList<UIChooserItem*> m_groupItems; 205 QList<UIChooserItem*> m_globalItems; 206 QList<UIChooserItem*> m_machineItems; 207 int m_iAdditionalHeight; 208 int m_iCornerRadius; 209 bool m_fMainRoot; 210 int m_iBlackoutDarkness; 211 /* Cached values: */ 212 QString m_strName; 213 QString m_strDescription; 214 QString m_strVisibleName; 215 QString m_strInfoGroups; 216 QString m_strInfoMachines; 217 QSize m_visibleNameSize; 218 QSize m_infoSizeGroups; 219 QSize m_infoSizeMachines; 220 QSize m_pixmapSizeGroups; 221 QSize m_pixmapSizeMachines; 222 QSize m_minimumHeaderSize; 223 QSize m_toggleButtonSize; 224 QSize m_enterButtonSize; 225 QSize m_exitButtonSize; 226 QFont m_nameFont; 227 QFont m_infoFont; 228 QPixmap m_groupsPixmap; 229 QPixmap m_machinesPixmap; 249 /** @name Prepare/cleanup cascade. 250 * @{ */ 251 /** Prepares all. */ 252 void prepare(); 253 254 /** Copies group contents @a pFrom one item @a pTo another. */ 255 static void copyContent(UIChooserItemGroup *pFrom, UIChooserItemGroup *pTo); 256 /** @} */ 257 258 /** @name Item stuff. 259 * @{ */ 260 /** Returns abstractly stored data value for certain @a iKey. */ 261 QVariant data(int iKey) const; 262 263 /** Returns whether group is main-root. */ 264 bool isMainRoot() const { return m_fMainRoot; } 265 266 /** Returns blackout item darkness. */ 267 int blackoutDarkness() const { return m_iBlackoutDarkness; } 268 269 /** Defines @a iAdditionalHeight. */ 270 void setAdditionalHeight(int iAdditionalHeight); 271 /** Returns additional height. */ 272 int additionalHeight() const; 273 274 /** Updates animation parameters. */ 275 void updateAnimationParameters(); 276 /** Updates toggle-button tool-tip. */ 277 void updateToggleButtonToolTip(); 278 /** @} */ 279 280 /** @name Children stuff. 281 * @{ */ 282 /** Returns whether group contains machine with @a strId. */ 283 bool isContainsMachine(const QString &strId) const; 284 /** Returns whether group contains locked machine. */ 285 bool isContainsLockedMachine(); 286 287 /** Updates user count info. */ 288 void updateItemCountInfo(); 289 /** @} */ 290 291 /** @name Layout stuff. 292 * @{ */ 293 /** Returns minimum width-hint depending on whether @a fGroupOpened. */ 294 int minimumWidthHintForGroup(bool fGroupOpened) const; 295 /** Returns minimum height-hint depending on whether @a fGroupOpened. */ 296 int minimumHeightHintForGroup(bool fGroupOpened) const; 297 /** Returns minimum size-hint depending on whether @a fGroupOpened. */ 298 QSizeF minimumSizeHintForProup(bool fGroupOpened) const; 299 300 /** Updates visible name. */ 301 void updateVisibleName(); 302 /** Updates pixmaps. */ 303 void updatePixmaps(); 304 /** Updates minimum header size. */ 305 void updateMinimumHeaderSize(); 306 /** @} */ 307 308 /** @name Painting stuff. 309 * @{ */ 310 /** Paints background using specified @a pPainter and certain @a rect. */ 311 void paintBackground(QPainter *pPainter, const QRect &rect); 312 /** Paints header using specified @a pPainter and certain @a rect. */ 313 void paintHeader(QPainter *pPainter, const QRect &rect); 314 /** @} */ 315 316 /** @name Item stuff. 317 * @{ */ 318 /** Holds whether group is main-root. */ 319 bool m_fMainRoot; 320 /** Holds whether group is closed. */ 321 bool m_fClosed; 322 323 /** Holds aditional height. */ 324 int m_iAdditionalHeight; 325 /** Holds corner radious. */ 326 int m_iCornerRadius; 327 /** Holds blackout item darkness. */ 328 int m_iBlackoutDarkness; 329 330 /** Holds the cached name. */ 331 QString m_strName; 332 /** Holds the cached description. */ 333 QString m_strDescription; 334 /** Holds the cached visible name. */ 335 QString m_strVisibleName; 336 337 /** Holds the name font. */ 338 QFont m_nameFont; 339 340 /** Holds the group toggle button instance. */ 341 UIGraphicsRotatorButton *m_pToggleButton; 342 /** Holds the group enter button instance. */ 343 UIGraphicsButton *m_pEnterButton; 344 /** Holds the group exit button instance. */ 345 UIGraphicsButton *m_pExitButton; 346 347 /** Holds the group name editor instance. */ 348 UIEditorGroupRename *m_pNameEditorWidget; 349 /** Holds the group name editor proxy instance. */ 350 QGraphicsProxyWidget *m_pNameEditor; 351 /** @} */ 352 353 /** @name Children stuff. 354 * @{ */ 355 /** Holds the group children list. */ 356 QList<UIChooserItem*> m_groupItems; 357 /** Holds the global children list. */ 358 QList<UIChooserItem*> m_globalItems; 359 /** Holds the machine children list. */ 360 QList<UIChooserItem*> m_machineItems; 361 362 /** Holds group children pixmap. */ 363 QPixmap m_groupsPixmap; 364 /** Holds machine children pixmap. */ 365 QPixmap m_machinesPixmap; 366 367 /** Holds the cached group children info. */ 368 QString m_strInfoGroups; 369 /** Holds the cached machine children info. */ 370 QString m_strInfoMachines; 371 372 /** Holds the children info font. */ 373 QFont m_infoFont; 374 /** @} */ 375 376 /** @name Layout stuff. 377 * @{ */ 378 /** Holds cached visible name size. */ 379 QSize m_visibleNameSize; 380 /** Holds cached group children pixmap size. */ 381 QSize m_pixmapSizeGroups; 382 /** Holds cached machine children pixmap size. */ 383 QSize m_pixmapSizeMachines; 384 /** Holds cached group children info size. */ 385 QSize m_infoSizeGroups; 386 /** Holds cached machine children info size. */ 387 QSize m_infoSizeMachines; 388 /** Holds cached minimum header size. */ 389 QSize m_minimumHeaderSize; 390 /** Holds cached toggle button size. */ 391 QSize m_toggleButtonSize; 392 /** Holds cached enter button size. */ 393 QSize m_enterButtonSize; 394 /** Holds cached exit button size. */ 395 QSize m_exitButtonSize; 396 /** @} */ 230 397 }; 231 398 399 400 /** QWidget extension to use as group name editor. */ 232 401 class UIEditorGroupRename : public QWidget 233 402 { … … 236 405 signals: 237 406 238 /* Notifier: Editing stuff:*/407 /** Notifies about group editing finished. */ 239 408 void sigEditingFinished(); 240 409 241 410 public: 242 411 243 /* Constructor:*/412 /** Constructs group editor with initial @a strName passing @a pParent to the base-class. */ 244 413 UIEditorGroupRename(const QString &strName, UIChooserItem *pParent); 245 414 246 /* API: Text stuff: */ 415 /** Defines editor @a strText. */ 416 void setText(const QString &strText); 417 /** Returns editor text. */ 247 418 QString text() const; 248 void setText(const QString &strText); 249 250 /* API: Font stuff: */ 419 420 /** Defines editor @a font. */ 251 421 void setFont(const QFont &font); 252 422 253 423 public slots: 254 424 255 /* API/Handler: Focus stuff:*/425 /** ACquires keyboard focus. */ 256 426 void setFocus(); 257 427 428 protected: 429 430 /** Preprocesses any Qt @a pEvent for passed @a pObject. */ 431 virtual bool eventFilter(QObject *pObject, QEvent *pEvent) /* override */; 432 258 433 private: 259 434 260 /* Handler: Event-filter: */ 261 bool eventFilter(QObject *pWatched, QEvent *pEvent); 262 263 /* Helper: Context-menu stuff: */ 264 void handleContextMenuEvent(QContextMenuEvent *pContextMenuEvent); 265 266 /* Variables: */ 435 /** Handles context-menu @a pEvent. */ 436 void handleContextMenuEvent(QContextMenuEvent *pEvent); 437 438 /** Holds the parent reference. */ 267 439 UIChooserItem *m_pParent; 440 441 /** Holds the line-edit instance. */ 268 442 QLineEdit *m_pLineEdit; 269 QMenu *m_pTemporaryMenu; 443 /** Holds the conect-menu instance. */ 444 QMenu *m_pTemporaryMenu; 270 445 }; 271 446 272 #endif /* __UIChooserItemGroup_h__ */ 273 447 448 #endif /* !___UIChooserItemGroup_h___ */
Note:
See TracChangeset
for help on using the changeset viewer.

