From 541cdf60e77bfde78a46835c2cc6a34a3b3973d5 Mon Sep 17 00:00:00 2001 From: donghualin Date: Mon, 12 Dec 2022 10:30:44 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E4=BB=8E=E5=BF=AB?= =?UTF-8?q?=E6=8D=B7=E9=9D=A2=E6=9D=BF=E6=8B=96=E5=8A=A8=E5=9B=BE=E6=A0=87?= =?UTF-8?q?=E9=A9=BB=E7=95=99=E5=88=B0=E4=BB=BB=E5=8A=A1=E6=A0=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 增加从快捷面板拖动应用到任务栏的功能 Log: Influence: 从快捷面板拖动图标到任务栏,观察是否驻留在任务栏 Bug: https://pms.uniontech.com/bug-view-171517.html Change-Id: I3351be282ef8d3afbb55f227fc6ae8ce16c78a97 --- frame/CMakeLists.txt | 1 + frame/drag/quickdragcore.cpp | 147 +++++++++++++++++++ frame/drag/quickdragcore.h | 53 +++++++ frame/item/components/singlequickitem.cpp | 9 +- frame/item/quicksettingitem.cpp | 24 +--- frame/window/docktraywindow.cpp | 2 +- frame/window/quickpluginmodel.cpp | 106 ++++++++++++-- frame/window/quickpluginmodel.h | 2 + frame/window/quickpluginwindow.cpp | 168 +++++++++++++++------- frame/window/quickpluginwindow.h | 10 +- frame/window/quicksettingcontainer.cpp | 36 ++--- frame/window/quicksettingcontainer.h | 15 -- frame/window/traymanagerwindow.cpp | 2 +- 13 files changed, 435 insertions(+), 140 deletions(-) create mode 100644 frame/drag/quickdragcore.cpp create mode 100644 frame/drag/quickdragcore.h diff --git a/frame/CMakeLists.txt b/frame/CMakeLists.txt index fc38f7f11..949a9dbdf 100644 --- a/frame/CMakeLists.txt +++ b/frame/CMakeLists.txt @@ -73,6 +73,7 @@ target_include_directories(${BIN_NAME} PUBLIC window/components window/tray window/tray/widgets + drag xcb ../plugins/tray ../plugins/show-desktop diff --git a/frame/drag/quickdragcore.cpp b/frame/drag/quickdragcore.cpp new file mode 100644 index 000000000..d4325f57c --- /dev/null +++ b/frame/drag/quickdragcore.cpp @@ -0,0 +1,147 @@ +#include "quickdragcore.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QuickPluginMimeData::QuickPluginMimeData(PluginsItemInterface *item, QDrag *drag) + : QMimeData() + , m_item(item) + , m_drag(drag) +{ +} + +QuickPluginMimeData::~QuickPluginMimeData() +{ +} + +PluginsItemInterface *QuickPluginMimeData::pluginItemInterface() const +{ + return m_item; +} + +QDrag *QuickPluginMimeData::drag() const +{ + return m_drag; +} + +/** + * @brief 拖动图标的窗口,可以根据实际情况设置动态图标 + * @param dragSource + */ +QuickIconDrag::QuickIconDrag(QObject *dragSource, const QPixmap &pixmap) + : QDrag(dragSource) + , m_imageWidget(new QWidget) + , m_timer(new QTimer(this)) + , m_sourcePixmap(pixmap) + , m_hotPoint(QPoint(0, 0)) +{ + m_timer->setInterval(10); + connect(m_timer, &QTimer::timeout, this, &QuickIconDrag::onDragMove); + m_timer->start(); + + m_imageWidget->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowDoesNotAcceptFocus); + m_imageWidget->setAttribute(Qt::WA_TransparentForMouseEvents); + m_imageWidget->installEventFilter(this); + useSourcePixmap(); +} + +QuickIconDrag::~QuickIconDrag() +{ + m_imageWidget->deleteLater(); +} + +void QuickIconDrag::updatePixmap(QPixmap pixmap) +{ + if (m_sourcePixmap == pixmap) + return; + + m_pixmap = pixmap; + m_useSourcePixmap = false; + m_imageWidget->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowDoesNotAcceptFocus | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint); + m_imageWidget->setFixedSize(pixmap.size()); + m_imageWidget->show(); + m_imageWidget->raise(); + m_imageWidget->update(); +} + +void QuickIconDrag::useSourcePixmap() +{ + m_useSourcePixmap = true; + m_imageWidget->setFixedSize(m_sourcePixmap.size()); + m_imageWidget->show(); + m_imageWidget->raise(); + m_imageWidget->update(); +} + +void QuickIconDrag::setDragHotPot(QPoint point) +{ + m_hotPoint = point; + m_imageWidget->update(); +} + +bool QuickIconDrag::eventFilter(QObject *watched, QEvent *event) +{ + if (watched == m_imageWidget) { + switch (event->type()) { + case QEvent::Paint: { + QPixmap pixmap = m_useSourcePixmap ? m_sourcePixmap : m_pixmap; + QPainter painter(m_imageWidget); + painter.drawPixmap(QPoint(0, 0), pixmap); + + QPixmap pixmapMask(m_imageWidget->size()); + pixmapMask.fill(Qt::transparent); + QPainter painterMask(&pixmapMask); + QPainterPath path; + path.addRoundedRect(pixmapMask.rect(), 8, 8); + painterMask.fillPath(path, Qt::white); + painterMask.setRenderHint(QPainter::Antialiasing, true); + painterMask.setCompositionMode(QPainter::CompositionMode_Source); + painterMask.drawPixmap(0, 0, pixmap); + painterMask.setCompositionMode(QPainter::CompositionMode_DestinationIn); + QColor maskColor(Qt::black); + maskColor.setAlpha(150); + painterMask.fillRect(pixmapMask.rect(), maskColor); + painterMask.end(); + + // 绘制圆角 + QBitmap radiusMask(m_imageWidget->size()); + radiusMask.fill(); + QPainter radiusPainter(&radiusMask); + radiusPainter.setPen(Qt::NoPen); + radiusPainter.setBrush(Qt::black); + radiusPainter.setRenderHint(QPainter::Antialiasing); + radiusPainter.drawRoundedRect(radiusMask.rect(), 8, 8); + m_imageWidget->setMask(radiusMask); + + painter.end(); + break; + } + default: + break; + } + } + return QDrag::eventFilter(watched, event); +} + +QPoint QuickIconDrag::currentPoint() const +{ + QPoint mousePos = QCursor::pos(); + if (m_useSourcePixmap) + return mousePos - m_hotPoint; + + QSize pixmapSize = m_pixmap.size(); + return (mousePos - QPoint(pixmapSize.width() * (m_hotPoint.x() / m_sourcePixmap.width()) + , pixmapSize.height() * (m_hotPoint.y() / m_sourcePixmap.height()))); +} + +void QuickIconDrag::onDragMove() +{ + m_imageWidget->move(currentPoint()); +} diff --git a/frame/drag/quickdragcore.h b/frame/drag/quickdragcore.h new file mode 100644 index 000000000..0eee58dc2 --- /dev/null +++ b/frame/drag/quickdragcore.h @@ -0,0 +1,53 @@ +#ifndef QUICKDRAGCORE_H +#define QUICKDRAGCORE_H + +#include +#include +#include + +class PluginsItemInterface; +class QTimer; + +class QuickPluginMimeData : public QMimeData +{ + Q_OBJECT + +public: + explicit QuickPluginMimeData(PluginsItemInterface *item, QDrag *drag); + ~QuickPluginMimeData(); + PluginsItemInterface *pluginItemInterface() const; + QDrag *drag() const; + +private: + PluginsItemInterface *m_item; + QDrag *m_drag; +}; + +class QuickIconDrag : public QDrag +{ + Q_OBJECT + +public: + explicit QuickIconDrag(QObject *dragSource, const QPixmap &pixmap); + ~QuickIconDrag(); + void updatePixmap(QPixmap pixmap); + void useSourcePixmap(); + void setDragHotPot(QPoint point); + +protected: + bool eventFilter(QObject *watched, QEvent *event) override; + QPoint currentPoint() const; + +private Q_SLOTS: + void onDragMove(); + +private: + QWidget *m_imageWidget; + QTimer *m_timer; + QPixmap m_sourcePixmap; + QPixmap m_pixmap; + QPoint m_hotPoint; + bool m_useSourcePixmap; +}; + +#endif // QUICKDRAGCORE_H diff --git a/frame/item/components/singlequickitem.cpp b/frame/item/components/singlequickitem.cpp index 0ec6bf72e..695adf347 100644 --- a/frame/item/components/singlequickitem.cpp +++ b/frame/item/components/singlequickitem.cpp @@ -120,13 +120,8 @@ QPixmap SingleQuickItem::pixmap() const { // 如果快捷面板区域的图标为空,那么就获取itemWidget的截图 QIcon icon = pluginItem()->icon(DockPart::QuickPanel); - if (icon.isNull()) { - QWidget *itemWidget = pluginItem()->itemWidget(itemKey()); - if (itemWidget) { - itemWidget->setFixedSize(24, 24); - icon = itemWidget->grab(); - } - } + if (icon.isNull()) + return QPixmap(); int pixmapWidth = width(); int pixmapHeight = height(); diff --git a/frame/item/quicksettingitem.cpp b/frame/item/quicksettingitem.cpp index 12b93785b..cbe791138 100644 --- a/frame/item/quicksettingitem.cpp +++ b/frame/item/quicksettingitem.cpp @@ -34,6 +34,8 @@ #include #include #include +#include +#include #define ICONWIDTH 24 #define ICONHEIGHT 24 @@ -72,27 +74,7 @@ DockItem::ItemType QuickSettingItem::itemType() const const QPixmap QuickSettingItem::dragPixmap() { - QPixmap pm = m_pluginInter->icon(DockPart::QuickPanel).pixmap(ICONWIDTH, ICONHEIGHT); - - QPainter pa(&pm); - pa.setPen(foregroundColor()); - pa.setCompositionMode(QPainter::CompositionMode_SourceIn); - pa.fillRect(pm.rect(), foregroundColor()); - - QPixmap pmRet(ICONWIDTH + ICONSPACE + FONTSIZE * 2, ICONHEIGHT + ICONSPACE + FONTSIZE * 2); - pmRet.fill(Qt::transparent); - QPainter paRet(&pmRet); - paRet.drawPixmap(QPoint((ICONSPACE + FONTSIZE * 2) / 2, 0), pm); - paRet.setPen(pa.pen()); - - QFont ft; - ft.setPixelSize(FONTSIZE); - paRet.setFont(ft); - QTextOption option; - option.setAlignment(Qt::AlignTop | Qt::AlignHCenter); - paRet.drawText(QRect(QPoint(0, ICONHEIGHT + ICONSPACE), - QPoint(pmRet.width(), pmRet.height())), m_pluginInter->pluginDisplayName(), option); - return pmRet; + return grab(); } const QString QuickSettingItem::itemKey() const diff --git a/frame/window/docktraywindow.cpp b/frame/window/docktraywindow.cpp index b1cc9e55f..a70fb1e9d 100644 --- a/frame/window/docktraywindow.cpp +++ b/frame/window/docktraywindow.cpp @@ -29,6 +29,7 @@ #include "pluginsitem.h" #include "quicksettingcontainer.h" #include "expandiconwidget.h" +#include "quickdragcore.h" #include @@ -313,7 +314,6 @@ void DockTrayWindow::initConnection() connect(m_systemPuginWidget, &SystemPluginWindow::itemChanged, this, &DockTrayWindow::onUpdateComponentSize); connect(m_dateTimeWidget, &DateTimeDisplayer::requestUpdate, this, &DockTrayWindow::onUpdateComponentSize); connect(m_quickIconWidget, &QuickPluginWindow::itemCountChanged, this, &DockTrayWindow::onUpdateComponentSize); - connect(m_quickIconWidget, &QuickPluginWindow::requestDrop, this, &DockTrayWindow::onDropIcon); connect(m_systemPuginWidget, &SystemPluginWindow::requestDrop, this, &DockTrayWindow::onDropIcon); connect(m_model, &TrayModel::rowCountChanged, this, &DockTrayWindow::onUpdateComponentSize); connect(m_model, &TrayModel::rowCountChanged, m_trayView, &TrayGridView::onUpdateEditorView); diff --git a/frame/window/quickpluginmodel.cpp b/frame/window/quickpluginmodel.cpp index 052885f69..190871af5 100644 --- a/frame/window/quickpluginmodel.cpp +++ b/frame/window/quickpluginmodel.cpp @@ -25,7 +25,6 @@ #include -static QStringList fixedPluginNames { "network", "sound", "power" }; #define PLUGINNAMEKEY "Dock_Quick_Plugin_Name" QuickPluginModel *QuickPluginModel::instance() @@ -40,17 +39,15 @@ void QuickPluginModel::addPlugin(PluginsItemInterface *itemInter, int index) if (QuickSettingController::instance()->pluginAttribute(itemInter) != QuickSettingController::PluginAttribute::Quick) return; - if (index < 0) { - // 如果索引值小于0,则认为它插在最后面 - index = m_dockedPluginIndex.size(); - } - - // 如果插入的插件在原来的插件列表中存在,并且位置相同,则不做任何的处理 - int oldIndex = m_dockedPluginIndex.contains(itemInter->pluginName()); + // 获取当前插件在插件区的位置索引(所有在任务栏上显示的插件) + int oldIndex = getCurrentIndex(itemInter); + // 计算插入之前的顺序 if (oldIndex == index && m_dockedPluginsItems.contains(itemInter)) return; - m_dockedPluginIndex[itemInter->pluginName()] = index; + // 根据插件区域的位置计算新的索引值 + int newIndex = generaIndex(index, oldIndex); + m_dockedPluginIndex[itemInter->pluginName()] = newIndex; if (!m_dockedPluginsItems.contains(itemInter)) { m_dockedPluginsItems << itemInter; // 保存配置到dConfig中 @@ -83,10 +80,10 @@ QList QuickPluginModel::dockedPluginItems() const QList dockedItems; QList activedItems; for (PluginsItemInterface *itemInter : m_dockedPluginsItems) { - if (fixedPluginNames.contains(itemInter->pluginName())) - dockedItems << itemInter; - else + if (isFixed(itemInter)) activedItems << itemInter; + else + dockedItems << itemInter; } std::sort(dockedItems.begin(), dockedItems.end(), [ this ](PluginsItemInterface *item1, PluginsItemInterface *item2) { return m_dockedPluginIndex.value(item1->pluginName()) < m_dockedPluginIndex.value(item2->pluginName()); @@ -104,7 +101,7 @@ bool QuickPluginModel::isDocked(PluginsItemInterface *itemInter) const bool QuickPluginModel::isFixed(PluginsItemInterface *itemInter) const { - return fixedPluginNames.contains(itemInter->pluginName()); + return !(itemInter->flags() & PluginFlag::Attribute_CanInsert); } QuickPluginModel::QuickPluginModel(QObject *parent) @@ -206,3 +203,86 @@ void QuickPluginModel::saveConfig() }); SETTINGCONFIG->setValue(PLUGINNAMEKEY, plugins); } + +int QuickPluginModel::getCurrentIndex(PluginsItemInterface *itemInter) +{ + QList dockedPluginsItems = m_dockedPluginsItems; + std::sort(dockedPluginsItems.begin(), dockedPluginsItems.end(), [ this ](PluginsItemInterface *plugin1, PluginsItemInterface *plugin2) { + return m_dockedPluginIndex.value(plugin1->pluginName()) < m_dockedPluginIndex.value(plugin2->pluginName()); + }); + return dockedPluginItems().indexOf(itemInter); +} + +int QuickPluginModel::generaIndex(int insertIndex, int oldIndex) +{ + int newIndex = insertIndex; + if (oldIndex < 0) { + newIndex = insertIndex + 1; + // 如果该插件在列表中存在,则需要将原来的索引值加一 + if (insertIndex < 0) { + // 如果新插入的索引值为-1,则表示需要插入到末尾的位置,此时需要从索引值中找到最大值 + int lastIndex = -1; + for (PluginsItemInterface *itemInter : m_dockedPluginsItems) { + int index = m_dockedPluginIndex.value(itemInter->pluginName()); + if (lastIndex < index) + lastIndex = index; + } + newIndex = lastIndex + 1; + } + if (m_dockedPluginIndex.values().contains(newIndex)) { + // 遍历map列表,检查列表中是否存在等于新索引的插件,如果存在,将其后面的索引值向后加一 + for (auto it = m_dockedPluginIndex.begin(); it != m_dockedPluginIndex.end(); it++) { + if (it.value() < newIndex) + continue; + + m_dockedPluginIndex[it.key()] = it.value() + 1; + } + } + } else { + newIndex = insertIndex; + // 如果该插件已经存在于下面的列表中,则分两种情况 + if (insertIndex < 0) { + // 如果插入在末尾,则计算最大值 + if (m_dockedPluginIndex.size() > 0) { + int maxIndex = m_dockedPluginIndex.first(); + for (auto it = m_dockedPluginIndex.begin(); it != m_dockedPluginIndex.end(); it++) { + if (maxIndex < it.value()) + maxIndex = it.value(); + } + return maxIndex; + } + return 0; + } + if (insertIndex > oldIndex) { + int minIndex = NGROUPS_MAX; + // 新的位置的索引值大于原来位置的索引值,则认为插入在原来的任务栏的后面,将前面的插件的索引值减去1 + for (PluginsItemInterface *itemInter : m_dockedPluginsItems) { + int pluginDockIndex = getCurrentIndex(itemInter); + qInfo() << itemInter->pluginDisplayName() << m_dockedPluginIndex[itemInter->pluginName()] << pluginDockIndex; + if (pluginDockIndex > oldIndex) { + if (pluginDockIndex <= insertIndex) { + int tmpIndex = m_dockedPluginIndex[itemInter->pluginName()]; + if (tmpIndex < minIndex) + minIndex = tmpIndex; + } + m_dockedPluginIndex[itemInter->pluginName()]--; + } + qInfo() << itemInter->pluginDisplayName() << m_dockedPluginIndex[itemInter->pluginName()]; + } + + if (minIndex != NGROUPS_MAX) + newIndex = minIndex; + } else { + // 新的位置索引小于原来的索引值,则认为是插在任务栏的前面,将任务栏后面的插件的索引值加一 + for (PluginsItemInterface *itemInter : m_dockedPluginsItems) { + int pluginDockIndex = getCurrentIndex(itemInter); + if (pluginDockIndex >= insertIndex) { + m_dockedPluginIndex[itemInter->pluginName()]++; + } + qInfo() << itemInter->pluginDisplayName() << m_dockedPluginIndex[itemInter->pluginName()]; + } + } + } + + return newIndex; +} diff --git a/frame/window/quickpluginmodel.h b/frame/window/quickpluginmodel.h index f028ef7de..a9a06f886 100644 --- a/frame/window/quickpluginmodel.h +++ b/frame/window/quickpluginmodel.h @@ -60,6 +60,8 @@ private: void initConnection(); void initConfig(); void saveConfig(); + int getCurrentIndex(PluginsItemInterface *itemInter); + int generaIndex(int sourceIndex, int oldIndex); private: QList m_dockedPluginsItems; diff --git a/frame/window/quickpluginwindow.cpp b/frame/window/quickpluginwindow.cpp index a84b50b7e..bdd8f5ff1 100644 --- a/frame/window/quickpluginwindow.cpp +++ b/frame/window/quickpluginwindow.cpp @@ -26,6 +26,7 @@ #include "appdrag.h" #include "proxyplugincontroller.h" #include "quickpluginmodel.h" +#include "quickdragcore.h" #include #include @@ -39,6 +40,7 @@ #include #include #include +#include #define ITEMSIZE 22 #define ITEMSPACE 6 @@ -66,8 +68,8 @@ typedef struct DragInfo{ if (!dragPixmap()) return false; - return (qAbs(currentPoint.x() - dragPoint.x()) >= 5 || - qAbs(currentPoint.y() - dragPoint.y()) >= 5); + return (qAbs(currentPoint.x() - dragPoint.x()) >= 1 || + qAbs(currentPoint.y() - dragPoint.y()) >= 1); } QPixmap dragPixmap() const { @@ -94,10 +96,12 @@ QuickPluginWindow::QuickPluginWindow(QWidget *parent) , m_mainLayout(new QBoxLayout(QBoxLayout::RightToLeft, this)) , m_position(Dock::Position::Bottom) , m_dragInfo(new DragInfo) + , m_dragEnterMimeData(nullptr) { initUi(); initConnection(); + topLevelWidget()->installEventFilter(this); installEventFilter(this); setAcceptDrops(true); setMouseTracking(true); @@ -197,6 +201,22 @@ PluginsItemInterface *QuickPluginWindow::findQuickSettingItem(const QPoint &mous bool QuickPluginWindow::eventFilter(QObject *watched, QEvent *event) { + if (watched == topLevelWidget()) { + switch (event->type()) { + case QEvent::DragEnter: { + QDragEnterEvent *dragEvent = static_cast(event); + dragEnterEvent(dragEvent); + break; + } + case QEvent::DragLeave: { + QDragLeaveEvent *dragEvent = static_cast(event); + dragLeaveEvent(dragEvent); + break; + } + default: + break; + } + } switch (event->type()) { case QEvent::MouseButtonPress: { QMouseEvent *mouseEvent = static_cast(event); @@ -223,7 +243,7 @@ bool QuickPluginWindow::eventFilter(QObject *watched, QEvent *event) if (m_dragInfo->canDrag(mouseEvent->pos())) break; - showPopup(qobject_cast(watched)); + showPopup(m_dragInfo->dockItem); } while (false); m_dragInfo->reset(); @@ -241,7 +261,13 @@ bool QuickPluginWindow::eventFilter(QObject *watched, QEvent *event) break; } case QEvent::Drop: { - Q_EMIT requestDrop(static_cast(event)); + m_dragEnterMimeData = nullptr; + QDropEvent *dropEvent = static_cast(event); + if (qobject_cast(dropEvent->source())) { + const QuickPluginMimeData *mimeData = qobject_cast(dropEvent->mimeData()); + if (mimeData) + dragPlugin(mimeData->pluginItemInterface()); + } break; } default: @@ -250,6 +276,35 @@ bool QuickPluginWindow::eventFilter(QObject *watched, QEvent *event) return QWidget::eventFilter(watched, event); } +void QuickPluginWindow::dragEnterEvent(QDragEnterEvent *event) +{ + m_dragEnterMimeData = const_cast(qobject_cast(event->mimeData())); + if (m_dragEnterMimeData) { + QIcon icon = m_dragEnterMimeData->pluginItemInterface()->icon(DockPart::QuickShow); + QuickIconDrag *drag = qobject_cast(m_dragEnterMimeData->drag()); + if (drag && !icon.isNull()) { + QPixmap pixmap = icon.pixmap(QSize(16, 16)); + drag->updatePixmap(pixmap); + } + event->accept(); + } else { + event->ignore(); + } +} + +void QuickPluginWindow::dragLeaveEvent(QDragLeaveEvent *event) +{ + if (m_dragEnterMimeData) { + QPoint mousePos = topLevelWidget()->mapFromGlobal(QCursor::pos()); + QuickIconDrag *drag = static_cast(m_dragEnterMimeData->drag()); + if (!topLevelWidget()->rect().contains(mousePos) && drag) { + static_cast(m_dragEnterMimeData->drag())->useSourcePixmap(); + } + m_dragEnterMimeData = nullptr; + } + event->accept(); +} + void QuickPluginWindow::onRequestUpdate() { bool countChanged = false; @@ -364,24 +419,22 @@ void QuickPluginWindow::startDrag() return; PluginsItemInterface *moveItem = m_dragInfo->dockItem->pluginItem(); - AppDrag *drag = new AppDrag(this, new QuickDragWidget); - QuickPluginMimeData *mimedata = new QuickPluginMimeData(moveItem); + //AppDrag *drag = new AppDrag(this, new QuickDragWidget); + QDrag *drag = new QDrag(this); + QuickPluginMimeData *mimedata = new QuickPluginMimeData(moveItem, drag); drag->setMimeData(mimedata); - drag->appDragWidget()->setDockInfo(m_position, QRect(mapToGlobal(pos()), size())); QPixmap dragPixmap = m_dragInfo->dragPixmap(); drag->setPixmap(dragPixmap); - drag->setHotSpot(QPoint(0, 0)); + drag->setHotSpot(dragPixmap.rect().center()); + //connect(static_cast(drag->appDragWidget()), &QuickDragWidget::requestDropItem, this, &QuickPluginWindow::onPluginDropItem); + //connect(static_cast(drag->appDragWidget()), &QuickDragWidget::requestDragMove, this, &QuickPluginWindow::onPluginDragMove); - connect(drag->appDragWidget(), &AppDragWidget::requestSplitWindow, this, [ this, moveItem ] { - QuickPluginModel::instance()->removePlugin(moveItem); - Q_EMIT itemCountChanged(); - }); - - connect(static_cast(drag->appDragWidget()), &QuickDragWidget::requestDropItem, this, &QuickPluginWindow::onPluginDropItem); - connect(static_cast(drag->appDragWidget()), &QuickDragWidget::requestDragMove, this, &QuickPluginWindow::onPluginDragMove); - - drag->exec(Qt::MoveAction | Qt::CopyAction); + drag->exec(Qt::CopyAction); + // 获取当前鼠标在任务栏快捷图标区域的位置 + QPoint currentPoint = mapFromGlobal(QCursor::pos()); + // 获取区域图标插入的位置 + QuickPluginModel::instance()->addPlugin(mimedata->pluginItemInterface(), getDropIndex(currentPoint)); } QuickDockItem *QuickPluginWindow::getDockItemByPlugin(PluginsItemInterface *item) @@ -447,62 +500,69 @@ void QuickPluginWindow::showPopup(QuickDockItem *item, PluginsItemInterface *ite QuickSettingContainer *container = static_cast(popWindow->getContent()); container->showPage(childPage, itemInter, canBack); + popWindow->raise(); +} + +QList QuickPluginWindow::quickDockItems() +{ + QList dockItems; + for (int i = 0; i < m_mainLayout->count(); i++) { + QLayoutItem *layoutItem = m_mainLayout->itemAt(i); + if (!layoutItem) + continue; + + QuickDockItem *dockedItem = qobject_cast(layoutItem->widget()); + if (!dockedItem) + continue; + + dockItems << dockedItem; + } + + return dockItems; } int QuickPluginWindow::getDropIndex(QPoint point) { + QList dockedItems = quickDockItems(); QuickDockItem *targetItem = getActiveDockItem(point); if (targetItem) { - for (int i = 0; i < m_mainLayout->count(); i++) { - QLayoutItem *layoutItem = m_mainLayout->itemAt(i); - if (!layoutItem) - continue; - - if (layoutItem->widget() == targetItem) + for (int i = 0; i < dockedItems.count(); i++) { + if (dockedItems[i] == targetItem) return i; } return -1; } - // 上下方向从右向左排列 + QList dockItemInter = QuickPluginModel::instance()->dockedPluginItems(); if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) { - for (int i = 0; i < m_mainLayout->count() - 1; i++) { - QLayoutItem *layoutBefore = m_mainLayout->itemAt(i); - QLayoutItem *layoutItem = m_mainLayout->itemAt(i + 1); - if (!layoutBefore || !layoutItem) - continue; - - QuickDockItem *dockBeforeItem = qobject_cast(layoutBefore->widget()); - QuickDockItem *dockItem = qobject_cast(layoutItem->widget()); - if (dockItem->canInsert()) + // 上下方向从右向左排列 + for (int i = 0; i < dockItemInter.count() - 1; i++) { + QuickDockItem *dockBeforeItem = dockedItems[i]; + QuickDockItem *dockItem = dockedItems[i + 1]; + if (!dockItem->canInsert()) continue; if (dockBeforeItem->geometry().x() > point.x() && dockItem->geometry().right() < point.x()) return i; } - } - for (int i = 0; i < m_mainLayout->count() - 1; i++) { - QLayoutItem *layoutBefore = m_mainLayout->itemAt(i); - QLayoutItem *layoutItem = m_mainLayout->itemAt(i + 1); - if (!layoutBefore || !layoutItem) - continue; + } else { + // 左右方向从下向上排列 + for (int i = 0; i < dockItemInter.count() - 1; i++) { + QuickDockItem *dockBeforeItem = dockedItems[i]; + QuickDockItem *dockItem = dockedItems[i + 1]; + if (!dockItem->canInsert()) + continue; - QuickDockItem *dockBeforeItem = qobject_cast(layoutBefore->widget()); - if (dockBeforeItem->canInsert()) - break; - - QuickDockItem *dockItem = qobject_cast(layoutItem->widget()); - - // 从上向下排列 - if (dockBeforeItem->geometry().bottom() < point.y() && dockItem->geometry().top() > point.y()) - return i; + if (dockBeforeItem->geometry().bottom() > point.y() && dockItem->geometry().top() < point.y()) + return i; + } } // 如果都没有找到,直接插入到最后 return -1; } -void QuickPluginWindow::onPluginDropItem(QDropEvent *event) +/*void QuickPluginWindow::onPluginDropItem(QDropEvent *event) { const QuickPluginMimeData *data = qobject_cast(event->mimeData()); if (!data) @@ -512,7 +572,7 @@ void QuickPluginWindow::onPluginDropItem(QDropEvent *event) QPoint currentPoint = mapFromGlobal(QCursor::pos()); // 获取区域图标插入的位置 QuickPluginModel::instance()->addPlugin(data->pluginItemInterface(), getDropIndex(currentPoint)); -} +}*/ void QuickPluginWindow::onPluginDragMove(QDragMoveEvent *event) { @@ -549,6 +609,11 @@ void QuickPluginWindow::onPluginDragMove(QDragMoveEvent *event) event->accept(); } +void QuickPluginWindow::dragMoveEvent(QDragMoveEvent *event) +{ + event->accept(); +} + void QuickPluginWindow::initConnection() { QuickPluginModel *model = QuickPluginModel::instance(); @@ -571,7 +636,6 @@ QuickDockItem::QuickDockItem(PluginsItemInterface *pluginItem, const QString &it , m_contextMenu(new QMenu(this)) , m_tipParent(nullptr) , m_mainLayout(nullptr) - , m_canInsert(QuickSettingController::instance()->hasFlag(pluginItem, PluginFlag::Attribute_CanInsert)) , m_dockItemParent(nullptr) { initUi(); @@ -595,7 +659,7 @@ PluginsItemInterface *QuickDockItem::pluginItem() bool QuickDockItem::canInsert() const { - return m_canInsert; + return (m_pluginItem->flags() & PluginFlag::Attribute_CanInsert); } void QuickDockItem::hideToolTip() diff --git a/frame/window/quickpluginwindow.h b/frame/window/quickpluginwindow.h index f2d10e29d..563541ef9 100644 --- a/frame/window/quickpluginwindow.h +++ b/frame/window/quickpluginwindow.h @@ -36,6 +36,7 @@ class QBoxLayout; class QuickDockItem; class DockPopupWindow; class QMenu; +class QuickPluginMimeData; enum class DockPart; namespace Dtk { namespace Gui { class DRegionMonitor; } @@ -59,14 +60,16 @@ public: Q_SIGNALS: void itemCountChanged(); - void requestDrop(QDropEvent *dropEvent); protected: bool eventFilter(QObject *watched, QEvent *event) override; + void dragEnterEvent(QDragEnterEvent *event) override; + void dragLeaveEvent(QDragLeaveEvent *event) override; + void dragMoveEvent(QDragMoveEvent *event) override; private Q_SLOTS: void onRequestUpdate(); - void onPluginDropItem(QDropEvent *event); + //void onPluginDropItem(QDropEvent *event); void onPluginDragMove(QDragMoveEvent *event); void onUpdatePlugin(PluginsItemInterface *itemInter, const DockPart &dockPart); void onRequestAppletShow(PluginsItemInterface * itemInter, const QString &itemKey); @@ -81,11 +84,13 @@ private: QuickDockItem *getDockItemByPlugin(PluginsItemInterface *item); QuickDockItem *getActiveDockItem(QPoint point) const; void showPopup(QuickDockItem *item, PluginsItemInterface *itemInter = nullptr, QWidget *childPage = nullptr); + QList quickDockItems(); private: QBoxLayout *m_mainLayout; Dock::Position m_position; struct DragInfo *m_dragInfo; + QuickPluginMimeData *m_dragEnterMimeData; }; // 用于在任务栏上显示的插件 @@ -131,7 +136,6 @@ private: QMenu *m_contextMenu; QWidget *m_tipParent; QHBoxLayout *m_mainLayout; - bool m_canInsert; QWidget *m_dockItemParent; }; diff --git a/frame/window/quicksettingcontainer.cpp b/frame/window/quicksettingcontainer.cpp index 34f6b6519..0c110cea9 100644 --- a/frame/window/quicksettingcontainer.cpp +++ b/frame/window/quicksettingcontainer.cpp @@ -26,6 +26,7 @@ #include "slidercontainer.h" #include "pluginchildpage.h" #include "utils.h" +#include "quickdragcore.h" #include #include @@ -35,6 +36,9 @@ #include #include #include +#include +#include +#include DWIDGET_USE_NAMESPACE @@ -132,8 +136,7 @@ DockPopupWindow *QuickSettingContainer::popWindow() m_popWindow->setArrowHeight(10); m_popWindow->setArrowDirection(getDirection(m_position)); m_popWindow->setContent(new QuickSettingContainer(m_popWindow)); - if (Utils::IS_WAYLAND_DISPLAY) - m_popWindow->setWindowFlags(m_popWindow->windowFlags() | Qt::FramelessWindowHint); + m_popWindow->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool); return m_popWindow; } @@ -181,17 +184,6 @@ bool QuickSettingContainer::eventFilter(QObject *watched, QEvent *event) return QWidget::eventFilter(watched, event); } -QPoint QuickSettingContainer::hotSpot(const QPixmap &pixmap) -{ - if (m_position == Dock::Position::Left) - return QPoint(0, pixmap.height()); - - if (m_position == Dock::Position::Top) - return QPoint(pixmap.width(), 0); - - return QPoint(pixmap.width(), pixmap.height()); -} - void QuickSettingContainer::appendPlugin(PluginsItemInterface *itemInter, bool needLayout) { QuickSettingItem *quickItem = QuickSettingFactory::createQuickWidget(itemInter); @@ -259,24 +251,14 @@ void QuickSettingContainer::mouseMoveEvent(QMouseEvent *event) QPoint pointCurrent = event->pos(); if (qAbs(m_dragInfo->dragPosition.x() - pointCurrent.x()) > 5 || qAbs(m_dragInfo->dragPosition.y() - pointCurrent.y()) > 5) { - - QDrag *drag = new QDrag(this); QuickSettingItem *moveItem = qobject_cast(m_dragInfo->dragItem); - QuickPluginMimeData *mimedata = new QuickPluginMimeData(m_dragInfo->pluginInter); + QuickIconDrag *drag = new QuickIconDrag(this, moveItem->dragPixmap()); + QuickPluginMimeData *mimedata = new QuickPluginMimeData(m_dragInfo->pluginInter, drag); drag->setMimeData(mimedata); - if (moveItem) { - QPixmap dragPixmap = moveItem->dragPixmap(); - drag->setPixmap(dragPixmap); - drag->setHotSpot(hotSpot(dragPixmap)); - } else { - // 如果拖动的是声音等插件 - QPixmap dragPixmap = m_dragInfo->dragItem->grab(); - drag->setPixmap(dragPixmap); - drag->setHotSpot(hotSpot(dragPixmap)); - } + drag->setDragHotPot(m_dragInfo->dragPosition); m_dragInfo->reset(); - drag->exec(Qt::MoveAction | Qt::CopyAction); + drag->exec(Qt::CopyAction); } } diff --git a/frame/window/quicksettingcontainer.h b/frame/window/quicksettingcontainer.h index 149fb259d..c04941412 100644 --- a/frame/window/quicksettingcontainer.h +++ b/frame/window/quicksettingcontainer.h @@ -77,8 +77,6 @@ private: void updateItemLayout(); // 调整全列插件的位置 void updateFullItemLayout(); - // 获取拖动图标的热点 - QPoint hotSpot(const QPixmap &pixmap); // 插入插件 void appendPlugin(PluginsItemInterface *itemInter, bool needLayout = true); @@ -98,17 +96,4 @@ private: PluginsItemInterface *m_childShowPlugin; }; -class QuickPluginMimeData : public QMimeData -{ - Q_OBJECT - -public: - explicit QuickPluginMimeData(PluginsItemInterface *item) : QMimeData(), m_item(item) {} - ~QuickPluginMimeData() {} - PluginsItemInterface *pluginItemInterface() const { return m_item; } - -private: - PluginsItemInterface *m_item; -}; - #endif // PLUGINCONTAINER_H diff --git a/frame/window/traymanagerwindow.cpp b/frame/window/traymanagerwindow.cpp index 031fb166a..bce900894 100644 --- a/frame/window/traymanagerwindow.cpp +++ b/frame/window/traymanagerwindow.cpp @@ -28,6 +28,7 @@ #include "systempluginwindow.h" #include "datetimedisplayer.h" #include "expandiconwidget.h" +#include "quickdragcore.h" #include #include @@ -40,7 +41,6 @@ #include #include -#define MAXFIXEDSIZE 999999 #define CRITLCALHEIGHT 42 #define CONTENTSPACE 7 // 高度小于等于这个值的时候,间距最小值