#include "topwin8desktopgroup.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "topwin8desktopitem.h" #include "topdesktopitemabs.h" enum WndSize { WndSize_CellWidth = 64, // Cell是一个单元格 WndSize_CellHeight = 64, WndSize_ItemsMargin = 6, WndSize_ItemsSpace = 10, WndSize_ItemCalcSpace = 15, // 拖拽时判断位置距离topleft,大概1/3处 }; class TopWin8DesktopGroupPrivate { Q_DECLARE_PUBLIC(TopWin8DesktopGroup) public: TopWin8DesktopGroupPrivate(TopWin8DesktopGroup *qptr); TScrollArea *mScrollArea; QWidget *mCenterWidget; QGridLayout *mGridLayout; QHBoxLayout *mHcenterLayout; QMap mModuleRightMap; TopDesktopItemAbs::State state; TopDesktopItemAbs::ClickType clickType; QVariantMap mConfigDataVarMap; QList mItemsLst; QMenu *mGroupMenu; bool startDragBol; bool drawCurPosiRectBol; QRect curDroppableRect; QPoint pressPos; Qt::Orientation mItemPrivority; static QMap i18NMap; const QString defaultBackground = "transparent"; const QString defaultTitleColor = "white"; protected: TopWin8DesktopGroup * const q_ptr; }; QMap TopWin8DesktopGroupPrivate::i18NMap = { {"GroupName", QObject::tr("GroupName")}, {"GroupName(English)", QObject::tr("GroupName(English)")}, {"GroupName(Chinese Simplified)", QObject::tr("GroupName(Chinese Simplified)")}, {"GroupName(Chinese Tranditional)", QObject::tr("GroupName(Chinese Tranditional)")}, {"Icon Name", QObject::tr("Icon Name")}, {"Title Color", QObject::tr("Title Color")}, {"Background Color", QObject::tr("Background Color")}, {"Size", QObject::tr("Size")}, {"Top Left", QObject::tr("Top Left")}, {"Top", QObject::tr("Top")}, {"Top Right", QObject::tr("Top Right")}, {"Left", QObject::tr("Left")}, {"Center", QObject::tr("Center")}, {"Right", QObject::tr("Right")}, {"Bottom Left", QObject::tr("Bottom Left")}, {"Bottom", QObject::tr("Bottom")}, {"Bottom Right", QObject::tr("Bottom Right")}, {"Absolute Position", QObject::tr("Absolute Position")}, {"Dock Area", QObject::tr("Dock Area")}, {"Dock Sequence", QObject::tr("Dock Sequence")} }; TopWin8DesktopGroupPrivate::TopWin8DesktopGroupPrivate(TopWin8DesktopGroup *qptr) : mScrollArea(NULL), mCenterWidget(NULL), mGridLayout(NULL), mGroupMenu(NULL), startDragBol(false), drawCurPosiRectBol(false), mItemPrivority(Qt::Horizontal), q_ptr(qptr) { } TopWin8DesktopGroup::TopWin8DesktopGroup(QWidget *iParent) : QGroupBox(iParent), d_ptr(new TopWin8DesktopGroupPrivate(this)) { Q_D(TopWin8DesktopGroup); this->setProperty("SS", "DESKTOPGROUP"); d->mScrollArea = new TScrollArea(this); d->mCenterWidget = new QWidget(d->mScrollArea); d->mCenterWidget->setObjectName("CENTERWIDGET"); d->mScrollArea->setWidget(d->mCenterWidget); d->mScrollArea->setWidgetResizable(true); d->mScrollArea->setStyleSheet(QString(".TScrollArea{background:transparent; border-width:0px;}" ".QWidget#CENTERWIDGET{background:%1;}").arg(d->defaultBackground)); QHBoxLayout *hLayout = new QHBoxLayout(this); hLayout->setMargin(0); hLayout->setSpacing(0); hLayout->addWidget(d->mScrollArea, 1); d->mGridLayout = new QGridLayout(0); d->mGridLayout->setMargin(WndSize_ItemsMargin); d->mGridLayout->setSpacing(0); QHBoxLayout *hCenterLayout = new QHBoxLayout(d->mCenterWidget); hCenterLayout->setMargin(0); hCenterLayout->setSpacing(0); hCenterLayout->addLayout(d->mGridLayout); d->mHcenterLayout = hCenterLayout; setAcceptDrops(true); this->setStyleSheet(QString("QGroupBox[SS=\"DESKTOPGROUP\"]{border:none;font-size:18px;margin-top: 24px;} " "QGroupBox[SS=\"DESKTOPGROUP\"]::title { subcontrol-origin: margin;subcontrol-position:top left;padding-left: 5px;color:%1;}") .arg(d->defaultTitleColor)); } TopWin8DesktopGroup::~TopWin8DesktopGroup() { Q_D(TopWin8DesktopGroup); delete d->mGridLayout; } void TopWin8DesktopGroup::doLayout() { Q_D(TopWin8DesktopGroup); // 1.检查初值 int colSpanInt = colSpan(); int rowSpanInt = rowSpan(); if (colSpanInt <= 0) colSpanInt = 1; if (rowSpanInt <= 0) rowSpanInt = 1; int cellWidthInt = WndSize_CellWidth; setCellWidth(cellWidthInt); int cellHeightInt = WndSize_CellHeight; setCellHeight(cellHeightInt); // 2.对分组大小和布局调整 while (d->mGridLayout->count() > 0) { d->mGridLayout->removeItem(d->mGridLayout->itemAt(0)); } d->mScrollArea->setFixedSize(cellWidthInt * colSpanInt + d->mGridLayout->spacing() * (colSpanInt - 1) + 2 * d->mGridLayout->margin() + 3, cellHeightInt * rowSpanInt + d->mGridLayout->spacing() * (rowSpanInt - 1) + 2 * d->mGridLayout->margin()+ 3); // 3.计算item位置 QPoint itemRowColPoint; QRect itemRect; QPoint layoutedItemRowColPoint; QList layoutedItemsLst; layoutedItemsLst.clear(); QList itemsLst = d->mItemsLst; foreach (TopDesktopItemAbs *item, itemsLst) { // point: x表示行,y表示列 itemRowColPoint = posStr2Point(item->config("position").toString()); // rect : x表示列(左边距离),y表示行 itemRect = QRect(QPoint(itemRowColPoint.y(), itemRowColPoint.x()), QSize(item->colSpan(), item->rowSpan())); item->blockSignals(true); // 3.1 是否超出最大宽度 if (isBeyondPlacedArea(itemRect, colSpanInt) && itemRect.x() != 0) { // 下移一行 itemRect.moveTo(0, itemRect.y() + 1); } // 3.2 检测QRect是否和已经布局的Item碰撞 bool isPreviousCollisionBol = false; while (isCollisionWithLayoutedItems(itemRect, layoutedItemsLst, &isPreviousCollisionBol)) { // 后面的位置Item下移一格 if (isPreviousCollisionBol) { itemRect.moveTo(itemRect.x(), itemRect.y() + 1); isPreviousCollisionBol = false; } foreach (TopDesktopItemAbs *layoutedItem, layoutedItemsLst) { layoutedItemRowColPoint = posStr2Point(layoutedItem->config("position").toString()); if (layoutedItemRowColPoint.x() > itemRect.y() || (layoutedItemRowColPoint.x() == itemRect.y() && layoutedItemRowColPoint.y() >= itemRect.x())) { layoutedItemRowColPoint.setX(layoutedItemRowColPoint.x() + 1); layoutedItem->setConfig("position", point2PosStr(layoutedItemRowColPoint)); } } } item->setConfig("position", point2PosStr(QPoint(itemRect.y(), itemRect.x()))); item->blockSignals(false); layoutedItemsLst.push_back(item); } // 4. 放置 int itemColSpan = 0; int itemRowSpan = 0; foreach (TopDesktopItemAbs *item, layoutedItemsLst) { itemRowColPoint = posStr2Point(item->config("position").toString()); itemColSpan = item->colSpan(); itemRowSpan = item->rowSpan(); item->setFixedSize(cellWidthInt * itemColSpan + d->mGridLayout->spacing() * (itemColSpan - 1), cellHeightInt * itemRowSpan + d->mGridLayout->spacing() * (itemRowSpan - 1)); item->setMargin(3); item->doLayout(); item->setHidden(!item->property("VISIBLE").toBool()); d->mGridLayout->addWidget(item, itemRowColPoint.x(), itemRowColPoint.y(), itemRowSpan, itemColSpan, Qt::AlignLeft | Qt::AlignTop ); } for (int i = 0; i < rowSpanInt - 1; ++i) { d->mGridLayout->setRowMinimumHeight(i, cellHeightInt); if (d->mGridLayout->itemAtPosition(i, 0) == 0) { d->mGridLayout->addItem(new QSpacerItem(cellWidthInt, cellHeightInt), i, 0, 1, 1); } } d->mGridLayout->setRowStretch(rowSpanInt - 1, 1); d->mGridLayout->setRowStretch(rowSpanInt, 1); for (int i = 0; i < colSpanInt - 1; ++i) { d->mGridLayout->setColumnMinimumWidth(i, cellWidthInt); if (d->mGridLayout->itemAtPosition(0, i)) { d->mGridLayout->addItem(new QSpacerItem(cellWidthInt, cellHeightInt), 0, i, 1, 1); } } d->mGridLayout->setColumnStretch(colSpanInt - 1, 1); d->mGridLayout->setSizeConstraint(QLayout::SetMinimumSize); adjustSize(); d->mItemsLst = itemOrder(d->mItemPrivority, d->mItemsLst); // 5. 设置stylesheet updateStyleSheet(); } void TopWin8DesktopGroup::setModuleRight(const QMap &iModuleRightMap) { Q_D(TopWin8DesktopGroup); d->mModuleRightMap = iModuleRightMap; } QList TopWin8DesktopGroup::desktopItems(Qt::Orientation iPriorityOrder) { Q_D(TopWin8DesktopGroup); if (iPriorityOrder != d->mItemPrivority) { d->mItemsLst = itemOrder(iPriorityOrder, d->mItemsLst); } return d->mItemsLst; } void TopWin8DesktopGroup::setColorList(TComboBox *iBackgroundCombox) { QString colorsStr = "[" "\"transparent\"," "\"rgba(0, 0, 0, 0.9)\"," "\"rgba(255, 255, 255, 0.9)\"," "\"rgba(42, 105, 238, 0.9)\"," "\"rgba(239, 59, 5, 0.9)\"," "\"rgba(255, 153, 0, 0.9)\"," "\"rgba(27, 117, 27, 0.9)\"," "\"rgba(110, 9, 189, 0.9)\"," "\"rgba(0, 204, 204, 0.9)\"," "\"rgba(51, 153, 51, 0.9)\"," "\"rgba(250, 123, 56, 0.9)\"," "\"rgba(86, 97, 153, 0.9)\"," "\"rgba(173, 86, 94, 0.9)\"," "\"rgba(128,128,255,0.9)\"," "\"rgba(164,99,255,0.9)\"," "\"rgba(0,128,128,0.9)\"," "\"rgba(204,51,51,0.9)\"," "\"rgba(255, 191, 24, 0.9)\"" "]"; QVariantList btnBkgColorVarLst = TDataParse::jsonStr2Variant(colorsStr).toList(); //1. 下拉框添加颜色字符 QVariantList colorVarLst; foreach(QVariant itemVar, btnBkgColorVarLst) { QString colorStr = itemVar.toString(); QVariantMap comboVarMap; comboVarMap.insert("name", colorStr); comboVarMap.insert("text", colorStr); colorVarLst << comboVarMap; } iBackgroundCombox->setItemList(colorVarLst); //2. 设置颜色图标 for(int n = 0; n < colorVarLst.count(); n++) { QVariantMap itemVarMap = colorVarLst.at(n).toMap(); QString colorStr = itemVarMap.value("text").toString(); int rInt = 0, gInt = 0, bInt = 0; QRegExp rx("(\\d+)\\s*\\,\\s*(\\d+)\\s*\\,\\s*(\\d+)"); if (rx.indexIn(colorStr) != -1) { rInt = rx.cap(1).toInt(); gInt = rx.cap(2).toInt(); bInt = rx.cap(3).toInt(); } //创建pixmap const int widthInt = 80; const int heightInt = 20; QPixmap pixColor(widthInt, heightInt); pixColor.fill(QColor(rInt, gInt, bInt, 210)); iBackgroundCombox->setItemIcon(n, QIcon(pixColor)); iBackgroundCombox->setIconSize(QSize(widthInt, heightInt)); } } void TopWin8DesktopGroup::setTitleColorList(TComboBox *iTitleCombox) { QString colorsStr = "[" "\"rgba(0, 0, 0, 0.9)\"," "\"rgba(255, 255, 255, 0.9)\"" "]"; QVariantList btnBkgColorVarLst = TDataParse::jsonStr2Variant(colorsStr).toList(); //1. 下拉框添加颜色字符 QVariantList colorVarLst; foreach(QVariant itemVar, btnBkgColorVarLst) { QString colorStr = itemVar.toString(); QVariantMap comboVarMap; comboVarMap.insert("name", colorStr); comboVarMap.insert("text", colorStr); colorVarLst << comboVarMap; } iTitleCombox->setItemList(colorVarLst); //2. 设置颜色图标 for(int n = 0; n < colorVarLst.count(); n++) { QVariantMap itemVarMap = colorVarLst.at(n).toMap(); QString colorStr = itemVarMap.value("text").toString(); int rInt = 0, gInt = 0, bInt = 0; QRegExp rx("(\\d+)\\s*\\,\\s*(\\d+)\\s*\\,\\s*(\\d+)"); if (rx.indexIn(colorStr) != -1) { rInt = rx.cap(1).toInt(); gInt = rx.cap(2).toInt(); bInt = rx.cap(3).toInt(); } //创建pixmap const int widthInt = 80; const int heightInt = 20; QPixmap pixColor(widthInt, heightInt); pixColor.fill(QColor(rInt, gInt, bInt, 210)); iTitleCombox->setItemIcon(n, QIcon(pixColor)); iTitleCombox->setIconSize(QSize(widthInt, heightInt)); } } void TopWin8DesktopGroup::showDockSequence(QFormLayout *iLayout, QSpinBox *iObj, bool iShowBol) { iLayout->labelForField(iObj)->setHidden(!iShowBol); iObj->setHidden(!iShowBol); } void TopWin8DesktopGroup::setLabelAdjustSize(QLabel *label) { label->adjustSize(); label->setFixedWidth(20); label->setWordWrap(true); label->setAlignment(Qt::AlignCenter); } TopDesktopItemAbs::State TopWin8DesktopGroup::state() const { Q_D(const TopWin8DesktopGroup); return d->state; } void TopWin8DesktopGroup::setState(TopDesktopItemAbs::State iState) { Q_D(TopWin8DesktopGroup); d->state = iState; foreach (TopDesktopItemAbs *item, d->mItemsLst) { item->setState(iState); } } void TopWin8DesktopGroup::setModuleClickType(TopDesktopItemAbs::ClickType iClickType) { Q_D(TopWin8DesktopGroup); d->clickType = iClickType; foreach (TopDesktopItemAbs *item, d->mItemsLst) { item->setClickType(iClickType); } } TopDesktopItemAbs::ClickType TopWin8DesktopGroup::moduleClickType() const { Q_D(const TopWin8DesktopGroup); return d->clickType; } void TopWin8DesktopGroup::setConfigData(const QVariantMap &iConfigDataVarMap) { Q_D(TopWin8DesktopGroup); d->mConfigDataVarMap = iConfigDataVarMap; QString titleStr = iConfigDataVarMap.value(QString("title_%1").arg(APP->language())).toString(); if (titleStr.isEmpty()) titleStr = iConfigDataVarMap.value("title").toString(); this->setTitle(titleStr); if (iConfigDataVarMap.contains("items")) { d->mItemsLst = createItems(iConfigDataVarMap.value("items").toList()); } emit configChanged(); } QVariantMap TopWin8DesktopGroup::configData() { Q_D(TopWin8DesktopGroup); QVariantList itemsVarLst; foreach (TopDesktopItemAbs *dskItem, d->mItemsLst) { // 返回数据删除不需要的字段 QVariantMap itemDataVarMap = dskItem->configData(); itemDataVarMap.remove("uuid"); itemsVarLst.push_back(dskItem->configData()); } QVariantMap dataVarMap = d->mConfigDataVarMap; dataVarMap.insert("size", rowColStr2SizeStr(QString::number(rowSpan()), QString::number(colSpan()))); dataVarMap.insert("items", itemsVarLst); return dataVarMap; } void TopWin8DesktopGroup::setConfig(const QString &iKeyStr, const QVariant &iValueVar) { Q_D(TopWin8DesktopGroup); d->mConfigDataVarMap.insert(iKeyStr, iValueVar); dataChanged(); } QVariant TopWin8DesktopGroup::config(const QString &iKeyStr) const { Q_D(const TopWin8DesktopGroup); return d->mConfigDataVarMap.value(iKeyStr); } QPoint TopWin8DesktopGroup::position() { return posStr2Point(config("position").toString()); } void TopWin8DesktopGroup::setPosition(QPoint iPoint) { setConfig("position", point2PosStr(iPoint)); } void TopWin8DesktopGroup::setRowSpan(int iRowSpanInt) { setConfig("rowSpan", iRowSpanInt); } int TopWin8DesktopGroup::rowSpan() const { return config("rowSpan").toInt(); } void TopWin8DesktopGroup::setColSpan(int iColSpanInt) { setConfig("colSpan", iColSpanInt); } int TopWin8DesktopGroup::colSpan() const { return config("colSpan").toInt(); } void TopWin8DesktopGroup::setCellWidth(int iCellWidthInt) { setConfig("cellWidth", iCellWidthInt); } int TopWin8DesktopGroup::cellWidth() const { return config("cellWidth").toInt(); } void TopWin8DesktopGroup::setCellHeight(int iCellHeight) { setConfig("cellHeight", iCellHeight); } int TopWin8DesktopGroup::cellHeight() const { return config("cellHeight").toInt(); } QString TopWin8DesktopGroup::dockArea() { return config("dockArea").toString(); } void TopWin8DesktopGroup::setDockArea(const QString &iDockAreaStr) { setConfig("dockArea", iDockAreaStr); } int TopWin8DesktopGroup::dockSequence() { return config("dockSequence").toInt(); } void TopWin8DesktopGroup::setDockSequence(int iSequenceInt) { setConfig("dockSequence", iSequenceInt); } bool TopWin8DesktopGroup::removeOne(TopDesktopItemAbs *iDesktopItem) { Q_D(TopWin8DesktopGroup); return d->mItemsLst.removeOne(iDesktopItem); } void TopWin8DesktopGroup::appendOne(TopDesktopItemAbs *iDesktopItem) { Q_D(TopWin8DesktopGroup); if (iDesktopItem) d->mItemsLst.prepend(iDesktopItem); } void TopWin8DesktopGroup::clear() { Q_D(TopWin8DesktopGroup); foreach (TopDesktopItemAbs *item, d->mItemsLst) { delete item; } d->mItemsLst.clear(); } QPoint TopWin8DesktopGroup::posStr2Point(const QString &iPosStr) { QString posRegStr("[0-9]{1,20},[0-9]{1,20}"); QRegExp rx(posRegStr); if (!rx.exactMatch(iPosStr)) return QPoint(0, 0); QString posStr = iPosStr; QStringList posStrLst = posStr.split(','); return QPoint(posStrLst.at(0).toInt(), posStrLst.at(1).toInt()); } QString TopWin8DesktopGroup::point2PosStr(QPoint iPoint) { return QString("%1,%2").arg(iPoint.x()).arg(iPoint.y()); } QSize TopWin8DesktopGroup::sizeStr2QSize(const QString &iSizeStr) { QString rowStr; QString colStr; QString sizeStr = iSizeStr; if (sizeStr.contains('x')) { QStringList sizeStrLst = sizeStr.split('x'); rowStr = sizeStrLst.at(0); colStr = sizeStrLst.at(1); } if (rowStr.isEmpty()) rowStr = "0"; if (colStr.isEmpty()) colStr = "0"; QSize size(rowStr.toInt(), colStr.toInt()); return size; } QString TopWin8DesktopGroup::rowColStr2SizeStr(const QString &iRowStr, const QString &iColStr) { return QString("%1x%2").arg(iRowStr).arg(iColStr); } bool TopWin8DesktopGroup::showConfigDialog(bool iIsNewBol) { TUiloaderDialog dialog; QString uimStr = TFileIo::readFileString(":/topclass/topdesktop/GroupInfo.ui.js"); QString dockAreaStr = dockArea(); int sequenceStr = dockSequence(); int colSpanInt = colSpan(); int rowSpanInt = rowSpan(); QString itemTextStr = config("title_" + APP->language()).toString(); if (itemTextStr.isEmpty()) { itemTextStr = config("title").toString(); } if (!iIsNewBol) { dialog.setTitle(tr("Edit - %1").arg(itemTextStr)); dialog.setIcon("setting2.white"); } else { dialog.setTitle(tr("New Group")); dialog.setIcon("add.white"); } dialog.setSelf(this); dialog.setScriptEngine(APP->scriptEngine()); dialog.resize(700, 600); dialog.setUiStr(uimStr); if (iIsNewBol) { this->setDockArea("top"); this->setConfig("background", "transparent"); this->setRowSpan(6); this->setColSpan(4); } QVariantMap dataVarMap = this->configData(); dialog.loadValues(dataVarMap); QVariantMap retVarMap = dialog.run(true); dialog.close(); if (retVarMap.isEmpty()) return false; setConfigData(retVarMap); updateStyleSheet(); if (dockArea() != dockAreaStr || sequenceStr != dockSequence() || colSpan() != colSpanInt || rowSpanInt != rowSpan()) { emit layoutedRequest(); } return true; } void TopWin8DesktopGroup::deleteGroup() { if (TMessageBox::msgbox(this, tr("Are you sure to delete category group %1?").arg(this->title()), "", "Question", tr("Delete"), QStringList() << tr("Yes") + ":Yes:Accept" << tr("No") + ":No:Reject", "No") == "Yes") { emit groupDeleted(this); } } void TopWin8DesktopGroup::addModuleItem() { Q_D(TopWin8DesktopGroup); TopDesktopItemAbs *win8item = createDesktopItem(); if (win8item->showConfigDialog()) { QPoint clickPosition = mapClassPos2WidgetPos(d->mGroupMenu->property("POSITION").toPoint()); win8item->setStartRow(rowAtWidget(clickPosition)); win8item->setStartCol(colAtWidget(clickPosition)); win8item->setConfig("position", point2PosStr(QPoint(rowAtWidget(clickPosition), colAtWidget(clickPosition)))); d->mItemsLst.append(win8item); this->doLayout(); } else { delete win8item; } } QString TopWin8DesktopGroup::ttr(const QString &iStr) { return TopWin8DesktopGroupPrivate::i18NMap.value(iStr, iStr); } TopDesktopItemAbs *TopWin8DesktopGroup::createDesktopItem(const QVariant &iParsVar) { QVariantMap itemVarMap = iParsVar.toMap(); TopDesktopItemAbs *deskitem = new TopWin8DesktopItem(); deskitem->setParent(this); deskitem->setState(this->state()); deskitem->setClickType(this->moduleClickType()); deskitem->setConfigData(itemVarMap); deskitem->setProperty("MODULE", this->property("MODULE").toString()); // 根据url->moduleName->right bool hasRightBol = hasOpenItemRight(deskitem->urlAddress()); deskitem->setHasOpenRight(hasRightBol); deskitem->setProperty("VISIBLE", hasRightBol); deskitem->doLayout(); connect(deskitem, SIGNAL(clicked(QString, QVariant)), this, SIGNAL(urlRequested(QString, QVariant))); connect(deskitem, SIGNAL(doubleClicked(QString, QVariant)), this, SIGNAL(urlRequested(QString, QVariant))); connect(deskitem, SIGNAL(configChanged()), this, SLOT(dataChanged())); connect(deskitem, SIGNAL(layoutDone()), this, SLOT(doLayout())); connect(deskitem, SIGNAL(itemDeleted(TopDesktopItemAbs*)), this, SLOT(deleteItem(TopDesktopItemAbs*))); connect(deskitem, SIGNAL(itemTryDeleted(TopDesktopItemAbs*)), this, SLOT(tryDeleteItem(TopDesktopItemAbs*))); return deskitem; } QMenu *TopWin8DesktopGroup::createContextMenu() { Q_D(TopWin8DesktopGroup); // 分组Menu if (!d->mGroupMenu) { QMenu *mGroupMenu = new QMenu(this); mGroupMenu->addAction(TRES->icon(""), tr("Setting Group"), this, SLOT(showConfigDialog())); mGroupMenu->addAction(TRES->icon(""), tr("Delete Group"), this, SLOT(deleteGroup())); mGroupMenu->addAction(TRES->icon(""), tr("Add Module"), this, SLOT(addModuleItem())); return mGroupMenu; } return d->mGroupMenu; } void TopWin8DesktopGroup::deleteItem(TopDesktopItemAbs *iItem) { Q_D(TopWin8DesktopGroup); if (iItem) { if (d->mItemsLst.removeOne(iItem)) iItem->deleteLater(); else iItem->close(); dataChanged(); } } void TopWin8DesktopGroup::tryDeleteItem(TopDesktopItemAbs *iItem) { Q_D(TopWin8DesktopGroup); d->mItemsLst.removeOne(iItem); } void TopWin8DesktopGroup::dataChanged() { emit configChanged(); } void TopWin8DesktopGroup::mousePressEvent(QMouseEvent *iEvent) { Q_D(TopWin8DesktopGroup); if (state() == TopDesktopItemAbs::State_Editing && iEvent->button() == Qt::LeftButton) { d->startDragBol = true; d->pressPos = iEvent->pos(); } } void TopWin8DesktopGroup::mouseReleaseEvent(QMouseEvent *iEvent) { Q_D(TopWin8DesktopGroup); if (iEvent->button() == Qt::RightButton) { if (d->state == TopDesktopItemAbs::State_Editing) { if (d->mGroupMenu == NULL) { d->mGroupMenu = createContextMenu(); } d->mGroupMenu->setProperty("POSITION", iEvent->pos()); d->mGroupMenu->popup(QCursor::pos()); } } d->startDragBol = false; d->drawCurPosiRectBol = false; } void TopWin8DesktopGroup::mouseMoveEvent(QMouseEvent *iEvent) { Q_D(TopWin8DesktopGroup); if (d->startDragBol && (qAbs(iEvent->pos().x() - d->pressPos.x()) > 7 || qAbs(iEvent->pos().y() - d->pressPos.y()) > 7)) { QByteArray groupBytLst; QDataStream dataStream(&groupBytLst, QIODevice::WriteOnly); dataStream << QPoint(iEvent->pos()) << this->title() << this->size() << QSize(cellWidth(), cellHeight()) << TDataParse::variant2JsonStr(this->configData()); QMimeData *mimeData = new QMimeData; mimeData->setData("application/desktop-groupdata", groupBytLst); QPixmap pixmap(this->size()); this->render(&pixmap); QDrag *drag = new QDrag(this); drag->setMimeData(mimeData); drag->setPixmap(pixmap); QPoint point(iEvent->pos()); drag->setHotSpot(point); this->setAttribute(Qt::WA_DeleteOnClose); Qt::DropAction dropAction = drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::CopyAction); if (dropAction == Qt::MoveAction) { this->close(); } } } void TopWin8DesktopGroup::dragMoveEvent(QDragMoveEvent *iEvent) { if (iEvent->mimeData()->hasFormat("application/desktop-itemdata") && !isCollisionLayoutedItems(iEvent)) { if (QString(iEvent->source()->property("MODULE").toString()) == QString(this->property("MODULE").toString())) { iEvent->setDropAction(Qt::MoveAction); iEvent->accept(); } else { iEvent->acceptProposedAction(); } } else { iEvent->ignore(); } } void TopWin8DesktopGroup::dragEnterEvent(QDragEnterEvent *iEvent) { if (iEvent->mimeData()->hasFormat("application/desktop-itemdata")) { if (QString(iEvent->source()->property("MODULE").toString()) == QString(this->property("MODULE").toString())) { iEvent->setDropAction(Qt::MoveAction); iEvent->accept(); } else { iEvent->acceptProposedAction(); } } else { iEvent->ignore(); } } void TopWin8DesktopGroup::dropEvent(QDropEvent *iEvent) { Q_D(TopWin8DesktopGroup); d->drawCurPosiRectBol = false; if (iEvent->mimeData()->hasFormat("application/desktop-itemdata") && !isCollisionLayoutedItems(iEvent)) { QByteArray itemDataBytLst = iEvent->mimeData()->data("application/desktop-itemdata"); QDataStream dataStream(&itemDataBytLst, QIODevice::ReadOnly); QPoint offsetPoint; QString itemDataStr; bool hasOpenrightBol = false; QSize itemSize; dataStream >> offsetPoint >> itemSize >> hasOpenrightBol >> itemDataStr; TopDesktopItemAbs *newItem = createDesktopItem(TDataParse::jsonStr2Variant(itemDataStr)); if (!newItem) return; newItem->setHasOpenRight(hasOpenrightBol); newItem->move(iEvent->pos() - offsetPoint); newItem->setAttribute(Qt::WA_DeleteOnClose); d->mItemsLst.removeOne(qobject_cast(iEvent->source())); iEvent->setDropAction(Qt::MoveAction); iEvent->accept(); // 根据放下的位置计算item应该在的位置,将item加入到mItemLst中 QPoint movePosi = mapClassPos2WidgetPos(iEvent->pos()) - offsetPoint; QPoint centerPosi = QPoint(movePosi.x() + itemSize.width() / 2, movePosi.y() + itemSize.height() / 2) ; QPoint calcPosi = movePosi; if (newItem->colSpan() == 1 && newItem->rowSpan() == 1) { calcPosi = centerPosi; } else { calcPosi = movePosi + QPoint(WndSize_ItemCalcSpace, WndSize_ItemCalcSpace); } insertItem(calcPosi, newItem); } else { iEvent->ignore(); } } void TopWin8DesktopGroup::paintEvent(QPaintEvent *iEvent) { Q_D(TopWin8DesktopGroup); if (d->drawCurPosiRectBol && state() == TopDesktopItemAbs::State_Editing) { QPainter painter(this); QColor color(QColor(TTHEME->value("TITLE").toString())); QBrush brush(color); QPen pen(brush, 2, Qt::DashDotLine, Qt::RoundCap, Qt::RoundJoin); painter.setPen(pen); } QGroupBox::paintEvent(iEvent); } void TopWin8DesktopGroup::mouseDoubleClickEvent(QMouseEvent *iEvent) { if (iEvent->button() == Qt::LeftButton && state() == TopDesktopItemAbs::State_Editing) { showConfigDialog(); } QGroupBox::mouseDoubleClickEvent(iEvent); } QList TopWin8DesktopGroup::createItems(const QVariantList &iItemsVarLst) { QList mItemsLst; foreach (QVariant itemVar, iItemsVarLst) { mItemsLst.push_back(createDesktopItem(itemVar)); } return mItemsLst; } // 说明: mapClassPos2WidgetPos // 参数: iPoint: QPoint 是相对于Class的点位置 // 返回值 :是相对于CenterWidget的位置 // 见:布局框架 // - mScrollArea.pos() 目的是算出Class Event 发出的点Point在mScrollArea中位置 // 同理 -mCenterWidget->pos() 目的是算出在mscrollArea中位置 在 CenterWidget中的位置 QPoint TopWin8DesktopGroup::mapClassPos2WidgetPos(QPoint iPoint) { Q_D(TopWin8DesktopGroup); return iPoint - d->mScrollArea->pos() - d->mCenterWidget->pos(); } int TopWin8DesktopGroup::rowAtWidget(QPoint iAtWidgetPoint) { Q_D(TopWin8DesktopGroup); int atRowInt = 0; for (int rowInt = 0; ; ++rowInt) { int yInt = 0; if (rowInt > 0) { yInt = cellHeight() * rowInt + d->mGridLayout->spacing() * rowInt + d->mGridLayout->margin(); } else { yInt = cellHeight() * rowInt + d->mGridLayout->margin(); } if (yInt < iAtWidgetPoint.y()) { atRowInt = rowInt; } else { break; } } return atRowInt; } int TopWin8DesktopGroup::colAtWidget(QPoint iAtWidgetPoint) { Q_D(TopWin8DesktopGroup); int atColInt = 0; for (int colInt = 0; ; ++colInt) { int xInt = 0; if (colInt > 0) { xInt = cellWidth() * colInt + d->mGridLayout->spacing() * colInt + d->mGridLayout->margin(); } else { xInt = cellWidth() * colInt + d->mGridLayout->margin(); } if (xInt < iAtWidgetPoint.x()) { atColInt = colInt; } else { break; } } return atColInt; } void TopWin8DesktopGroup::insertItem(QPoint iDropPoint, TopDesktopItemAbs *iInsetedItem) { Q_D(TopWin8DesktopGroup); // 放下点的行 int rowInt = rowAtWidget(iDropPoint); int colInt = colAtWidget(iDropPoint); // 放下的行列 d->mItemsLst.append(iInsetedItem); iInsetedItem->setConfig("position", point2PosStr(QPoint(rowInt, colInt))); doLayout(); } bool TopWin8DesktopGroup::isBeyondPlacedArea(QRect iRect, int iPlacedWidthInt) { return (iRect.x() + iRect.width() > iPlacedWidthInt) ? true : false; } bool TopWin8DesktopGroup::isCollisionWithLayoutedItems(QRect iRect, const QList iLayoutedItemsLst, bool *oIsPreviousCollisionBol) { QRect layoutedItemRect; QPoint layoutedItemPoint; foreach (TopDesktopItemAbs *item, iLayoutedItemsLst) { layoutedItemPoint = posStr2Point(item->config("position").toString()); layoutedItemRect = QRect(QPoint(layoutedItemPoint.y(), layoutedItemPoint.x()), QSize(item->colSpan(), item->rowSpan())); if (layoutedItemRect.intersects(iRect)) { if (oIsPreviousCollisionBol) { if (layoutedItemRect.y() < iRect.y() || (layoutedItemRect.y() == iRect.y() && layoutedItemRect.x() < iRect.x())) { *oIsPreviousCollisionBol = true; } else { *oIsPreviousCollisionBol = false; } } return true; } } return false; } bool TopWin8DesktopGroup::isCollisionLayoutedItems(QDropEvent *iEvent) { Q_D(TopWin8DesktopGroup); QByteArray itemDataBytLst = iEvent->mimeData()->data("application/desktop-itemdata"); QDataStream dataStream(&itemDataBytLst, QIODevice::ReadOnly); QPoint offsetPoint; QString itemDataStr; bool hasOpenrightBol = false; QSize itemSize; dataStream >> offsetPoint >> itemSize >> hasOpenrightBol >> itemDataStr; TopDesktopItemAbs *newItem = createDesktopItem(TDataParse::jsonStr2Variant(itemDataStr)); QPoint movePosition = mapClassPos2WidgetPos(iEvent->pos()) - offsetPoint; QPoint centerPosi = QPoint(movePosition.x() + itemSize.width() / 2, movePosition.y() + itemSize.height() / 2) ; QPoint calcPosi; if (newItem->colSpan() == 1 && newItem->rowSpan() == 1) { calcPosi = centerPosi; } else { calcPosi = movePosition + QPoint(WndSize_ItemCalcSpace, WndSize_ItemCalcSpace); } QRect rect = QRect(QPoint(colAtWidget(calcPosi), rowAtWidget(calcPosi)), QSize(newItem->colSpan(), newItem->rowSpan())); delete newItem; return isCollisionWithLayoutedItems(rect, d->mItemsLst); } void TopWin8DesktopGroup::updateStyleSheet() { Q_D(TopWin8DesktopGroup); QString background = config("background").toString(); if (background != d->defaultBackground) { d->mScrollArea->setStyleSheet(QString(".TScrollArea{background:transparent; border-width:0px;}" ".QWidget#CENTERWIDGET{background:%1;}") .arg(config("background").toString())); } QString titleColor = config("titleColor").toString(); if (titleColor != d->defaultTitleColor) { this->setStyleSheet(QString("QGroupBox[SS=\"DESKTOPGROUP\"]{border:none;font-size:18px;margin-top: 24px;} " "QGroupBox[SS=\"DESKTOPGROUP\"]::title { subcontrol-origin: margin;subcontrol-position:top left;padding-left: 5px;color:%1;}") .arg(config("titleColor").toString())); } } bool TopWin8DesktopGroup::hasOpenItemRight(const QString &iUrlStr) { Q_D(TopWin8DesktopGroup); QVariantMap dataMap = TDataParse::commandStr2Map(iUrlStr); QString moduleNameStr = dataMap.value("COM").toString().toUpper(); if (d->mModuleRightMap.contains(moduleNameStr)) { return APP->hasRight(d->mModuleRightMap.value(moduleNameStr)); } return true; } QList TopWin8DesktopGroup::itemOrder(Qt::Orientation iPriorityOrder, const QList& iItemLst) { QList itemLst = iItemLst; if (iItemLst.isEmpty()) return itemLst; QMap rowItemMap; QMap colItemMap; foreach (TopDesktopItemAbs *item, iItemLst) { QString relativePosStr = item->config("position").toString().trimmed(); QPoint relativePos = posStr2Point(relativePosStr.isEmpty() ? QString("0,0") : relativePosStr); rowItemMap.insert(item, relativePos.x()); colItemMap.insert(item, relativePos.y()); } if (iPriorityOrder == Qt::Horizontal) { qSort(itemLst.begin(), itemLst.end(), [=](const TopDesktopItemAbs*item1, const TopDesktopItemAbs*item2) { int y1 = rowItemMap.value(item1); int y2 = rowItemMap.value(item2); int x1 = colItemMap.value(item1); int x2 = colItemMap.value(item2); return y1 < y2 || (y1 == y2 && x1 < x2); }); } else { qSort(itemLst.begin(), itemLst.end(), [=](const TopDesktopItemAbs*item1, const TopDesktopItemAbs*item2) { int y1 = rowItemMap.value(item1); int y2 = rowItemMap.value(item2); int x1 = colItemMap.value(item1); int x2 = colItemMap.value(item2); return x1 < x2 || (x1 == x2 && y1 < y2); }); } return itemLst; }