diff --git a/src/app.cpp b/src/app.cpp index 051d457..d8bc94b 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -88,6 +88,9 @@ bool App::init(bool daemon, bool forceShow, bool showTodo, bool showChat) return; } m_dragging = true; + if (m_panel) { + m_panel->setDragging(true); + } if (!m_model->isEmpty()) { if (m_panel && m_panel->isVisible()) { m_panel->suppressPortalIfUnderCursor(); @@ -107,6 +110,7 @@ bool App::init(bool daemon, bool forceShow, bool showTodo, bool showChat) m_dragging = false; if (m_panel) { m_panel->stopPortalSuppression(); + m_panel->setDragging(false); } if (m_model->isEmpty() && m_panel && m_panel->isVisible()) { m_panel->dismiss(); diff --git a/src/chat/chatwindow.cpp b/src/chat/chatwindow.cpp index 37c8bb5..9f1831d 100644 --- a/src/chat/chatwindow.cpp +++ b/src/chat/chatwindow.cpp @@ -1281,9 +1281,6 @@ void ChatWindow::startConversationWith(const QString &text, const QStringList &f } } m_input->setFocus(); - - m_status->setText(tr("拖到左侧空白处=新对话,拖到左侧会话=追加到该会话,拖到右侧对话区=发给当前会话")); - m_status->show(); } void ChatWindow::activateForAsk() diff --git a/src/factory/contentfactory.cpp b/src/factory/contentfactory.cpp index 9ace704..3d610fd 100644 --- a/src/factory/contentfactory.cpp +++ b/src/factory/contentfactory.cpp @@ -317,6 +317,45 @@ void ContentFactory::paintEvent(QPaintEvent *event) painter.drawPath(path); } +void ContentFactory::dragEnterEvent(QDragEnterEvent *event) +{ + if (!event->mimeData() || + !(event->mimeData()->hasUrls() || event->mimeData()->hasText() || + event->mimeData()->hasImage())) { + event->ignore(); + return; + } + Q_EMIT dragContent(event->mimeData()); + Q_EMIT dragActivity(); + event->acceptProposedAction(); +} + +void ContentFactory::dragMoveEvent(QDragMoveEvent *event) +{ + if (event->mimeData() && + (event->mimeData()->hasUrls() || event->mimeData()->hasText() || + event->mimeData()->hasImage())) { + Q_EMIT dragContent(event->mimeData()); + Q_EMIT dragActivity(); + event->acceptProposedAction(); + return; + } + event->ignore(); +} + +void ContentFactory::dragLeaveEvent(QDragLeaveEvent *event) +{ + Q_UNUSED(event) + Q_EMIT dragActivity(); +} + +void ContentFactory::dropEvent(QDropEvent *event) +{ + if (event->mimeData()) { + event->acceptProposedAction(); + } +} + bool ContentFactory::eventFilter(QObject *watched, QEvent *event) { if (event->type() == QEvent::DragEnter || event->type() == QEvent::DragMove) { diff --git a/src/factory/contentfactory.h b/src/factory/contentfactory.h index 5141c5e..98c7a2a 100644 --- a/src/factory/contentfactory.h +++ b/src/factory/contentfactory.h @@ -33,6 +33,7 @@ signals: void actionRequested(const QString &id, const DropContent &content); void heightChanged(); void dragActivity(); + void dragContent(const QMimeData *mime); void askRequested(); void askDropped(const QMimeData *mime); @@ -42,6 +43,10 @@ public: protected: void paintEvent(QPaintEvent *event) override; bool eventFilter(QObject *watched, QEvent *event) override; + void dragEnterEvent(QDragEnterEvent *event) override; + void dragMoveEvent(QDragMoveEvent *event) override; + void dragLeaveEvent(QDragLeaveEvent *event) override; + void dropEvent(QDropEvent *event) override; private: void rebuild(); diff --git a/src/portal/portalclient.cpp b/src/portal/portalclient.cpp index a7ebe4c..995e83a 100644 --- a/src/portal/portalclient.cpp +++ b/src/portal/portalclient.cpp @@ -50,6 +50,9 @@ PortalClient::PortalClient(QObject *parent) bus.connect(QString::fromLatin1(kService), QString::fromLatin1(kPath), QString::fromLatin1(kInterface), QStringLiteral("PortalDropped"), this, SLOT(onDropped(QString, bool))); + bus.connect(QString::fromLatin1(kService), QString::fromLatin1(kPath), + QString::fromLatin1(kInterface), QStringLiteral("PortalClosed"), this, + SLOT(onPortalClosed())); } bool PortalClient::beginPortal(const QRect &panelRect) @@ -93,6 +96,11 @@ void PortalClient::onDragStarted(const QString &mimeTypes) Q_EMIT dragStarted(mimeTypes); } +void PortalClient::onPortalClosed() +{ + Q_EMIT portalClosed(); +} + void PortalClient::onDragEnded() { Q_EMIT dragEnded(); diff --git a/src/portal/portalclient.h b/src/portal/portalclient.h index 0223f3e..7f3892d 100644 --- a/src/portal/portalclient.h +++ b/src/portal/portalclient.h @@ -33,11 +33,13 @@ public: signals: void dragStarted(const QString &mimeTypes); void dragEnded(); + void portalClosed(); void dropped(const QString &uuid, bool accepted); private slots: void onDragStarted(const QString &mimeTypes); void onDragEnded(); + void onPortalClosed(); void onDropped(const QString &uuid, bool accepted); private: diff --git a/src/ui/portalpanel.cpp b/src/ui/portalpanel.cpp index e8eed55..34cc994 100644 --- a/src/ui/portalpanel.cpp +++ b/src/ui/portalpanel.cpp @@ -784,6 +784,7 @@ PortalPanel::PortalPanel(StagingModel *model, QWidget *parent) if (m_countLabel) { m_countLabel->setText(tr("%1 项").arg(m_model->count())); } + updateMode(); refreshLayout(); }); connect(m_model, &StagingModel::countChanged, m_view->viewport(), @@ -873,7 +874,15 @@ void PortalPanel::setupUi() connect(m_zone, &PortalZone::portalRequested, this, [this]() { PortalClient *portal = PortalClient::instance(); - if (portal->beginPortal(QRect(mapToGlobal(QPoint(0, 0)), size()))) { + QScreen *scr = screen() ? screen() : QGuiApplication::primaryScreen(); + QRect panelRect = geometry(); + if (scr) { + const QRect avail = scr->availableGeometry(); + panelRect = QRect(avail.x() + avail.width() - width() - m_rightMargin, + avail.y() + avail.height() - height() - m_bottomMargin, + width(), height()); + } + if (portal->beginPortal(panelRect)) { m_zone->setPortalActive(true); m_zone->showMessage(tr("移动到目标窗口上松手")); } else { @@ -886,6 +895,8 @@ void PortalPanel::setupUi() }); connect(PortalClient::instance(), &PortalClient::dragEnded, this, [this]() { m_zone->setPortalActive(false); }); + connect(PortalClient::instance(), &PortalClient::portalClosed, this, + [this]() { m_zone->setPortalActive(false); }); auto *right = new QVBoxLayout; right->setContentsMargins(0, 0, 0, 0); @@ -990,6 +1001,7 @@ void PortalPanel::setupUi() Q_EMIT askWithContent(text, files); }); connect(m_factory, &ContentFactory::heightChanged, this, [this]() { refreshLayout(); }); + connect(m_factory, &ContentFactory::dragContent, this, &PortalPanel::noteDragContent); connect(m_factory, &ContentFactory::dragActivity, this, [this]() { if (m_factoryTimer) { m_factoryTimer->start(); @@ -1002,6 +1014,32 @@ void PortalPanel::refreshLayout() updateGeometryForContent(); } +void PortalPanel::setDragging(bool dragging) +{ + if (m_dragging == dragging) { + return; + } + m_dragging = dragging; + updateMode(); +} + +void PortalPanel::updateMode() +{ + const bool stagingOnly = !m_dragging && m_model && m_model->count() > 0; + if (stagingOnly == m_stagingOnly) { + return; + } + m_stagingOnly = stagingOnly; + if (m_zone) { + m_zone->setVisible(!stagingOnly); + } + if (m_factory) { + m_factory->setVisible(!stagingOnly); + } + setFixedWidth(stagingOnly ? 360 : kPanelWidth); + refreshLayout(); +} + void PortalPanel::updateGeometryForContent() { QScreen *scr = screen(); @@ -1020,10 +1058,11 @@ void PortalPanel::updateGeometryForContent() const int selectionHeight = (m_selectionBar && m_selectionBar->isVisible()) ? 32 : 0; /* The factory always occupies the same strip, so neither the panel size nor * its position changes when a drag starts or ends. */ - const int factoryHeight = m_factory ? m_factory->sizeHint().height() + 6 : 0; + const int factoryHeight = + (!m_stagingOnly && m_factory) ? m_factory->sizeHint().height() + 6 : 0; const int totalHeight = kMargin * 2 + headerHeight + 6 + selectionHeight + listHeight + factoryHeight; - resize(kPanelWidth, totalHeight); + resize(m_stagingOnly ? 360 : kPanelWidth, totalHeight); } void PortalPanel::noteDragContent(const QMimeData *mime) diff --git a/src/ui/portalpanel.h b/src/ui/portalpanel.h index f3db7ad..dabcd53 100644 --- a/src/ui/portalpanel.h +++ b/src/ui/portalpanel.h @@ -34,6 +34,7 @@ public: void refreshLayout(); void popup(); void suppressPortalIfUnderCursor(); + void setDragging(bool dragging); void stopPortalSuppression(); void dismiss(); @@ -52,6 +53,7 @@ private: void setupUi(); void setupWindow(); void updateGeometryForContent(); + void updateMode(); void updateSelectionBar(); void noteDragContent(const QMimeData *mime); void noteDragFinished(); @@ -79,6 +81,8 @@ private: int m_bottomMargin = 16; int m_manualListHeight = 0; QTimer *m_suppressWatch = nullptr; + bool m_stagingOnly = false; + bool m_dragging = false; bool m_fixedPosition = true; bool m_fixedSize = false; int m_dragMode = 0; // 0 none, 1 move, 2 resize