From 8dc0e39b03a01d2521bda9c06132b7c9f5888085 Mon Sep 17 00:00:00 2001 From: Barry <870709864@qq.com> Date: Sun, 20 Jan 2019 20:14:07 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A3=81=E6=80=A7=E5=B7=A5=E5=85=B7=E7=AA=97?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- QtScrcpy/QtScrcpy.pro | 12 +- QtScrcpy/dialog.cpp | 3 +- QtScrcpy/toolform.cpp | 38 ++++++ QtScrcpy/toolform.h | 30 +++++ QtScrcpy/toolform.ui | 19 +++ QtScrcpy/uibase/magneticwidget.cpp | 196 +++++++++++++++++++++++++++++ QtScrcpy/uibase/magneticwidget.h | 50 ++++++++ QtScrcpy/uibase/magneticwidget.ui | 32 +++++ QtScrcpy/uibase/uibase.pri | 8 ++ QtScrcpy/videoform.cpp | 7 +- 10 files changed, 390 insertions(+), 5 deletions(-) create mode 100644 QtScrcpy/toolform.cpp create mode 100644 QtScrcpy/toolform.h create mode 100644 QtScrcpy/toolform.ui create mode 100644 QtScrcpy/uibase/magneticwidget.cpp create mode 100644 QtScrcpy/uibase/magneticwidget.h create mode 100644 QtScrcpy/uibase/magneticwidget.ui create mode 100644 QtScrcpy/uibase/uibase.pri diff --git a/QtScrcpy/QtScrcpy.pro b/QtScrcpy/QtScrcpy.pro index 5bc3cef..ada28c1 100644 --- a/QtScrcpy/QtScrcpy.pro +++ b/QtScrcpy/QtScrcpy.pro @@ -29,15 +29,18 @@ DEFINES += QT_DEPRECATED_WARNINGS SOURCES += \ main.cpp \ dialog.cpp \ - videoform.cpp + videoform.cpp \ + toolform.cpp HEADERS += \ dialog.h \ - videoform.h + videoform.h \ + toolform.h FORMS += \ dialog.ui \ - videoform.ui + videoform.ui \ + toolform.ui # 子工程 include ($$PWD/common/common.pri) @@ -47,8 +50,10 @@ include ($$PWD/decoder/decoder.pri) include ($$PWD/render/render.pri) include ($$PWD/android/android.pri) include ($$PWD/inputcontrol/inputcontrol.pri) +include ($$PWD/uibase/uibase.pri) include ($$PWD/fontawesome/fontawesome.pri) + # 附加包含路径 INCLUDEPATH += \ $$PWD/../third_party/ffmpeg/include \ @@ -59,6 +64,7 @@ INCLUDEPATH += \ $$PWD/render \ $$PWD/android \ $$PWD/inputcontrol \ + $$PWD/uibase \ $$PWD/fontawesome diff --git a/QtScrcpy/dialog.cpp b/QtScrcpy/dialog.cpp index 53369a6..2046f38 100644 --- a/QtScrcpy/dialog.cpp +++ b/QtScrcpy/dialog.cpp @@ -8,8 +8,9 @@ Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) -{ +{ ui->setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); setWindowFlags(windowFlags() | Qt::WindowMinimizeButtonHint); diff --git a/QtScrcpy/toolform.cpp b/QtScrcpy/toolform.cpp new file mode 100644 index 0000000..1650d21 --- /dev/null +++ b/QtScrcpy/toolform.cpp @@ -0,0 +1,38 @@ +#include + +#include "toolform.h" +#include "ui_toolform.h" + +ToolForm::ToolForm(QWidget* adsorbWidget, AdsorbPositions adsorbPos) + : MagneticWidget(adsorbWidget, adsorbPos) + , ui(new Ui::ToolForm) +{ + ui->setupUi(this); + setWindowFlags(Qt::FramelessWindowHint); +} + +ToolForm::~ToolForm() +{ + delete ui; +} + +void ToolForm::mousePressEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) { + m_dragPosition = event->globalPos() - frameGeometry().topLeft(); + event->accept(); + } +} + +void ToolForm::mouseReleaseEvent(QMouseEvent *event) +{ + +} + +void ToolForm::mouseMoveEvent(QMouseEvent *event) +{ + if (event->buttons() & Qt::LeftButton) { + move(event->globalPos() - m_dragPosition); + event->accept(); + } +} diff --git a/QtScrcpy/toolform.h b/QtScrcpy/toolform.h new file mode 100644 index 0000000..5d72b01 --- /dev/null +++ b/QtScrcpy/toolform.h @@ -0,0 +1,30 @@ +#ifndef TOOLFORM_H +#define TOOLFORM_H + +#include + +#include "magneticwidget.h" + +namespace Ui { +class ToolForm; +} + +class ToolForm : public MagneticWidget +{ + Q_OBJECT + +public: + explicit ToolForm(QWidget* adsorbWidget, AdsorbPositions adsorbPos); + ~ToolForm(); + +protected: + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + +private: + Ui::ToolForm *ui; + QPoint m_dragPosition; +}; + +#endif // TOOLFORM_H diff --git a/QtScrcpy/toolform.ui b/QtScrcpy/toolform.ui new file mode 100644 index 0000000..fa542b9 --- /dev/null +++ b/QtScrcpy/toolform.ui @@ -0,0 +1,19 @@ + + + ToolForm + + + + 0 + 0 + 118 + 497 + + + + Form + + + + + diff --git a/QtScrcpy/uibase/magneticwidget.cpp b/QtScrcpy/uibase/magneticwidget.cpp new file mode 100644 index 0000000..390a14c --- /dev/null +++ b/QtScrcpy/uibase/magneticwidget.cpp @@ -0,0 +1,196 @@ +#include +#include +#include + +#include "magneticwidget.h" +#include "ui_magneticwidget.h" + +MagneticWidget::MagneticWidget(QWidget* adsorbWidget, AdsorbPositions adsorbPos) + : QWidget(Q_NULLPTR) + , m_adsorbPos(adsorbPos) + , m_adsorbWidget(adsorbWidget) +{ + Q_ASSERT(m_adsorbWidget); + setAttribute(Qt::WA_DeleteOnClose); + + connect(m_adsorbWidget, &QWidget::destroyed, this, &QWidget::close); + m_adsorbWidget->installEventFilter(this); + +} + +MagneticWidget::~MagneticWidget() +{ + if (m_adsorbWidget) { + m_adsorbWidget->removeEventFilter(this); + } +} + +bool MagneticWidget::eventFilter(QObject *watched, QEvent *event) +{ + if (watched != m_adsorbWidget || !event) { + return false; + } + if (m_adsorbed && QEvent::Move == event->type()) { + move(m_adsorbWidget->pos() - m_relativePos); + } + if (m_adsorbed && QEvent::Resize == event->type()) { + QRect parentRect; + QRect targetRect; + getGeometry(parentRect, targetRect); + QPoint pos(parentRect.left(), parentRect.top()); + switch (m_curAdsorbPosition) { + case AP_OUTSIDE_LEFT: + pos.setX(pos.x() - width()); + pos.setY(pos.y() - m_relativePos.y()); + break; + case AP_OUTSIDE_RIGHT: + pos.setX(pos.x() + m_adsorbWidget->width()); + pos.setY(pos.y() - m_relativePos.y()); + break; + case AP_OUTSIDE_TOP: + pos.setX(pos.x() - m_relativePos.x()); + pos.setY(pos.y() - targetRect.height()); + break; + case AP_OUTSIDE_BOTTOM: + pos.setX(pos.x() - m_relativePos.x()); + pos.setY(pos.y() + parentRect.height()); + break; + case AP_INSIDE_LEFT: + pos.setY(pos.y() - m_relativePos.y()); + break; + case AP_INSIDE_RIGHT: + pos.setX(parentRect.right() - targetRect.width()); + pos.setY(pos.y() - m_relativePos.y()); + break; + case AP_INSIDE_TOP: + pos.setX(pos.x() - m_relativePos.x()); + break; + case AP_INSIDE_BOTTOM: + pos.setX(pos.x() - m_relativePos.x()); + pos.setY(parentRect.bottom() - targetRect.height()); + break; + default: + break; + } + move(pos); + } + return false; +} + +void MagneticWidget::moveEvent(QMoveEvent *event) +{ + if (!m_adsorbWidget) { + return; + } + + QRect parentRect; + QRect targetRect; + getGeometry(parentRect, targetRect); + + int parentLeft = parentRect.left(); + int parentRight = parentRect.right(); + int parentTop = parentRect.top(); + int parentBottom = parentRect.bottom(); + int targetLeft = targetRect.left(); + int targetRight = targetRect.right(); + int targetTop = targetRect.top(); + int targetBottom = targetRect.bottom(); + + QPoint finalPosition = pos(); + int adsorbDistance = 30; + + m_adsorbed = false; + + if (m_adsorbPos & AP_INSIDE_LEFT + && parentRect.intersects(targetRect) + && qAbs(parentLeft - targetLeft) < adsorbDistance) { + finalPosition.setX(parentLeft); + m_adsorbed |= true; + m_curAdsorbPosition = AP_INSIDE_LEFT; + } + + if (m_adsorbPos & AP_OUTSIDE_RIGHT + && parentRect.intersects(targetRect.translated(-adsorbDistance, 0)) + && qAbs(parentRight - targetLeft) < adsorbDistance) { + finalPosition.setX(parentRight); + m_adsorbed |= true; + m_curAdsorbPosition = AP_OUTSIDE_RIGHT; + } + + if (m_adsorbPos & AP_OUTSIDE_LEFT + && parentRect.intersects(targetRect.translated(adsorbDistance, 0)) + && qAbs(parentLeft - targetRight) < adsorbDistance) { + finalPosition.setX(parentLeft - targetRect.width()); + m_adsorbed |= true; + m_curAdsorbPosition = AP_OUTSIDE_LEFT; + } + + if (m_adsorbPos & AP_INSIDE_RIGHT + && parentRect.intersects(targetRect) + && qAbs(parentRight - targetRight) < adsorbDistance) { + finalPosition.setX(parentRight - targetRect.width()); + m_adsorbed |= true; + m_curAdsorbPosition = AP_INSIDE_RIGHT; + } + + if (m_adsorbPos & AP_INSIDE_TOP + && parentRect.intersects(targetRect) + && qAbs(parentTop - targetTop) < adsorbDistance) { + finalPosition.setY(parentTop); + m_adsorbed |= true; + m_curAdsorbPosition = AP_INSIDE_TOP; + } + + if (m_adsorbPos & AP_OUTSIDE_TOP + && parentRect.intersects(targetRect.translated(0, adsorbDistance)) + && qAbs(parentTop - targetBottom) < adsorbDistance) { + finalPosition.setY(parentTop - targetRect.height()); + m_adsorbed |= true; + m_curAdsorbPosition = AP_OUTSIDE_TOP; + } + + if (m_adsorbPos & AP_OUTSIDE_BOTTOM + && parentRect.intersects(targetRect.translated(0, -adsorbDistance)) + && qAbs(parentBottom - targetTop) < adsorbDistance) { + finalPosition.setY(parentBottom); + m_adsorbed |= true; + m_curAdsorbPosition = AP_OUTSIDE_BOTTOM; + } + + if (m_adsorbPos & AP_INSIDE_BOTTOM + && parentRect.intersects(targetRect) + && qAbs(parentBottom - targetBottom) < adsorbDistance) { + finalPosition.setY(parentBottom - targetRect.height()); + m_adsorbed |= true; + m_curAdsorbPosition = AP_INSIDE_BOTTOM; + } + + if (m_adsorbed) { + m_relativePos = m_adsorbWidget->pos() - pos(); + } + + move(finalPosition); +} + +void MagneticWidget::getGeometry(QRect &relativeWidgetRect, QRect &targetWidgetRect) +{ + QRect parentRect = m_adsorbWidget->geometry(); + QRect targetRect = geometry(); + + if (!m_adsorbWidget->windowFlags().testFlag(Qt::FramelessWindowHint)) { + // title bar height + int titleBarHeight = m_adsorbWidget->style()->pixelMetric(QStyle::PM_TitleBarHeight); + parentRect.translate(0, -titleBarHeight); + parentRect.setHeight(parentRect.height() + titleBarHeight); + } + + if (!windowFlags().testFlag(Qt::FramelessWindowHint)) { + // title bar height + int titleBarHeight = style()->pixelMetric(QStyle::PM_TitleBarHeight); + targetRect.translate(0, -titleBarHeight); + targetRect.setHeight(targetRect.height() + titleBarHeight); + } + relativeWidgetRect = parentRect; + targetWidgetRect = targetRect; +} + diff --git a/QtScrcpy/uibase/magneticwidget.h b/QtScrcpy/uibase/magneticwidget.h new file mode 100644 index 0000000..07ef267 --- /dev/null +++ b/QtScrcpy/uibase/magneticwidget.h @@ -0,0 +1,50 @@ +#ifndef MAGNETICWIDGET_H +#define MAGNETICWIDGET_H + +#include +#include + +/* + * a magnetic widget + * window title bar support not good +*/ + +class MagneticWidget : public QWidget +{ + Q_OBJECT + +public: + enum AdsorbPosition { + AP_OUTSIDE_LEFT = 0x01, // 吸附外部左边框 + AP_OUTSIDE_TOP = 0x02, // 吸附外部上边框 + AP_OUTSIDE_RIGHT = 0x04, // 吸附外部右边框 + AP_OUTSIDE_BOTTOM = 0x08, // 吸附外部下边框 + AP_INSIDE_LEFT = 0x10, // 吸附内部左边框 + AP_INSIDE_TOP = 0x20, // 吸附内部上边框 + AP_INSIDE_RIGHT = 0x40, // 吸附内部右边框 + AP_INSIDE_BOTTOM = 0x80, // 吸附内部下边框 + AP_ALL = 0xFF, // 全吸附 + }; + Q_DECLARE_FLAGS(AdsorbPositions, AdsorbPosition) + +public: + explicit MagneticWidget(QWidget* adsorbWidget, AdsorbPositions adsorbPos = AP_ALL); + ~MagneticWidget(); + +protected: + bool eventFilter(QObject *watched, QEvent *event) override; + void moveEvent(QMoveEvent *event) override; + +private: + void getGeometry(QRect& relativeWidgetRect, QRect& targetWidgetRect); + +private: + AdsorbPositions m_adsorbPos = AP_ALL; + QPoint m_relativePos; + bool m_adsorbed = false; + QPointer m_adsorbWidget; + AdsorbPosition m_curAdsorbPosition; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(MagneticWidget::AdsorbPositions) +#endif // MAGNETICWIDGET_H diff --git a/QtScrcpy/uibase/magneticwidget.ui b/QtScrcpy/uibase/magneticwidget.ui new file mode 100644 index 0000000..c600e01 --- /dev/null +++ b/QtScrcpy/uibase/magneticwidget.ui @@ -0,0 +1,32 @@ + + + MagneticWidget + + + + 0 + 0 + 400 + 300 + + + + Form + + + + + 80 + 110 + 93 + 28 + + + + PushButton + + + + + + diff --git a/QtScrcpy/uibase/uibase.pri b/QtScrcpy/uibase/uibase.pri new file mode 100644 index 0000000..75c0643 --- /dev/null +++ b/QtScrcpy/uibase/uibase.pri @@ -0,0 +1,8 @@ +FORMS += \ + $$PWD/magneticwidget.ui + +HEADERS += \ + $$PWD/magneticwidget.h + +SOURCES += \ + $$PWD/magneticwidget.cpp diff --git a/QtScrcpy/videoform.cpp b/QtScrcpy/videoform.cpp index e4ac962..a8b08d6 100644 --- a/QtScrcpy/videoform.cpp +++ b/QtScrcpy/videoform.cpp @@ -11,6 +11,7 @@ #include "videoform.h" #include "ui_videoform.h" #include "iconhelper.h" +#include "toolform.h" VideoForm::VideoForm(const QString& serial, QWidget *parent) : QWidget(parent), @@ -18,7 +19,7 @@ VideoForm::VideoForm(const QString& serial, QWidget *parent) : m_serial(serial) { ui->setupUi(this); - setAttribute(Qt::WA_DeleteOnClose); + setAttribute(Qt::WA_DeleteOnClose); QPixmap phone; if (phone.load(":/res/phone.png")) { @@ -114,6 +115,10 @@ VideoForm::VideoForm(const QString& serial, QWidget *parent) : bool vertical = size().height() > size().width(); updateStyleSheet(vertical); + + ToolForm* mw = new ToolForm(this, ToolForm::AP_OUTSIDE_RIGHT); + mw->move(pos().x() + geometry().width(), pos().y() + 30); + mw->show(); } VideoForm::~VideoForm()