Improve capture shortcuts and sticky image controls

This commit is contained in:
easyz committed 2026-03-29 18:45:30 +08:00
1 parent 0f9ea684eb
commit bb9a7d907d
5 files changed
+139 -12

No files matched your search

+16
View File
@@ -613,6 +613,20 @@ void CaptureOverlayWidget::mouseReleaseEvent(QMouseEvent *event)
setCursor(m_selection.cursorShape());
if (m_selection.hasSelection()) {
refreshCanvasForSelection(false);
if (m_defaultAction == CaptureAction::Sticky || m_defaultAction == CaptureAction::Save) {
const CaptureAction action = m_defaultAction;
if (m_magnifier) {
m_magnifier->hide();
}
update();
event->accept();
QTimer::singleShot(0, this, [this, action]() {
if (isVisible() && m_selection.hasSelection()) {
performAction(action);
}
});
return;
}
updateToolbarGeometry();
m_toolbar->show();
m_toolbar->raise();
@@ -1162,3 +1176,5 @@ QString CaptureOverlayWidget::defaultSaveFilePath() const
.arg(QDateTime::currentDateTime().toString(QStringLiteral("yyyyMMdd_HHmmss")));
return QDir(baseDir).filePath(fileName);
}
+15 -1
View File
@@ -51,6 +51,16 @@ void StickyCanvasWidget::setViewScale(qreal scale)
update();
}
void StickyCanvasWidget::setContentOpacity(qreal opacity)
{
const qreal next = qBound<qreal>(0.05, opacity, 1.0);
if (qFuzzyCompare(m_contentOpacity, next)) {
return;
}
m_contentOpacity = next;
update();
}
void StickyCanvasWidget::setActiveShapeType(Shapeype type)
{
m_shapeType = type;
@@ -180,6 +190,9 @@ void StickyCanvasWidget::paintEvent(QPaintEvent *event)
Q_UNUSED(event);
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);
painter.save();
painter.setOpacity(m_contentOpacity);
if (m_backgroundVisible) {
painter.fillRect(rect(), Qt::white);
}
@@ -188,7 +201,6 @@ void StickyCanvasWidget::paintEvent(QPaintEvent *event)
painter.drawImage(rect(), m_backgroundImage);
}
painter.save();
painter.scale(m_viewScale, m_viewScale);
for (Shape *shape : m_shapes) {
if (shape) {
@@ -311,3 +323,5 @@ void StickyCanvasWidget::clearShapes()
qDeleteAll(m_shapes);
m_shapes.clear();
}
+3
View File
@@ -21,6 +21,7 @@ public:
void setBackgroundImage(const QImage &image);
void setBackgroundVisible(bool visible);
void setViewScale(qreal scale);
void setContentOpacity(qreal opacity);
void setActiveShapeType(Shapeype type);
void setPenColor(const QColor &color);
void setPenSize(int size);
@@ -67,7 +68,9 @@ private:
bool m_drawingEnabled = false;
bool m_draggingShape = false;
qreal m_viewScale = 1.0;
qreal m_contentOpacity = 1.0;
QPoint m_startPoint;
};
#endif // STICKY_CANVAS_WIDGET_H
+99 -11
View File
@@ -10,6 +10,7 @@
#include <QCloseEvent>
#include <QFile>
#include <QContextMenuEvent>
#include <QEvent>
#include <QFileDialog>
#include <QFrame>
#include <QHBoxLayout>
@@ -28,6 +29,7 @@
#include <QStyle>
#include <QTimer>
#include <QToolButton>
#include <QToolTip>
#include <QVector>
#include <QVBoxLayout>
#include <QWindow>
@@ -73,6 +75,18 @@ qreal monitorScaleForPoint(const QPoint &physicalPoint)
return 1.0;
}
bool isAltWheelActive(const QWheelEvent *event)
{
if (event && event->modifiers().testFlag(Qt::AltModifier)) {
return true;
}
#ifdef Q_OS_WIN
return (GetAsyncKeyState(VK_MENU) & 0x8000) != 0;
#else
return QGuiApplication::keyboardModifiers().testFlag(Qt::AltModifier);
#endif
}
QPoint physicalOffsetForLogicalPoint(const QPoint &logicalPoint, const QPoint &referencePhysicalPoint)
{
#ifdef Q_OS_WIN
@@ -280,6 +294,7 @@ StickyPinWidget::StickyPinWidget(const QString &imageUrl,
m_canvas = new StickyCanvasWidget(this);
m_canvas->setBackgroundImage(m_image);
m_canvas->setViewScale(m_zoomFactor);
m_canvas->setContentOpacity(m_contentOpacity);
m_canvas->setPenColor(m_currentPenColor);
m_canvas->setPenSize(m_currentPenSize);
m_canvas->setActiveShapeType(PEN);
@@ -494,7 +509,7 @@ StickyPinWidget::StickyPinWidget(const QString &imageUrl,
connect(m_aiLoadingTimer, &QTimer::timeout, this, [this]() {
m_aiLoadingFrame = (m_aiLoadingFrame + 1) % 12;
updateAiLoadingIcon();
update(contentRect());
update();
});
auto setupButton = [](QToolButton *button, const QString &tooltip) {
@@ -607,6 +622,20 @@ StickyPinWidget::StickyPinWidget(const QString &imageUrl,
});
connect(m_closeButton, &QToolButton::clicked, this, &QWidget::close);
const auto wheelAwareWidgets = findChildren<QWidget*>();
for (QWidget *child : wheelAwareWidgets) {
if (!child) {
continue;
}
if (child == m_visionResultWidget) {
continue;
}
if (m_visionResultWidget && m_visionResultWidget->isAncestorOf(child)) {
continue;
}
child->installEventFilter(this);
}
updateLayoutAndSize();
if (!m_colorButtons.isEmpty()) {
m_colorButtons.first()->setChecked(true);
@@ -639,17 +668,18 @@ void StickyPinWidget::paintEvent(QPaintEvent *event)
painter.fillRect(rect(), Qt::transparent);
const QRect imageRect = contentRect();
const qreal contentOpacity = qBound<qreal>(0.05, m_contentOpacity, 1.0);
if (m_shadowVisible) {
for (int i = 10; i >= 1; --i) {
const int alpha = 3 + i * 2;
const int alpha = qRound((3 + i * 2) * contentOpacity);
painter.setPen(Qt::NoPen);
painter.setBrush(QColor(47, 143, 255, alpha));
painter.drawRoundedRect(imageRect.adjusted(-i, -i, i, i), 8, 8);
}
}
painter.setPen(QPen(QColor(120, 182, 255, 80), 1));
painter.setBrush(Qt::white);
painter.setPen(QPen(QColor(120, 182, 255, qRound(80 * contentOpacity)), 1));
painter.setBrush(QColor(255, 255, 255, qRound(255 * contentOpacity)));
painter.drawRoundedRect(imageRect, 4, 4);
painter.setBrush(Qt::NoBrush);
@@ -870,17 +900,72 @@ void StickyPinWidget::mousePressEvent(QMouseEvent *event)
QWidget::mousePressEvent(event);
}
bool StickyPinWidget::eventFilter(QObject *watched, QEvent *event)
{
if (watched && event && event->type() == QEvent::Wheel) {
auto *wheelEvent = static_cast<QWheelEvent *>(event);
if (isAltOpacityAdjustActive(wheelEvent) && handleWheelInteraction(wheelEvent)) {
return true;
}
}
return QWidget::eventFilter(watched, event);
}
void StickyPinWidget::wheelEvent(QWheelEvent *event)
{
if (handleWheelInteraction(event)) {
return;
}
QWidget::wheelEvent(event);
}
bool StickyPinWidget::handleWheelInteraction(QWheelEvent *event)
{
if (!event) {
return false;
}
const QPoint angleDelta = event->angleDelta();
if (angleDelta.y() == 0) {
QWidget::wheelEvent(event);
const int primaryDelta = (angleDelta.y() != 0) ? angleDelta.y() : angleDelta.x();
const bool altActive = isAltOpacityAdjustActive(event);
if (primaryDelta == 0) {
return false;
}
if (altActive) {
const qreal delta = primaryDelta > 0 ? 0.05 : -0.05;
const qreal nextOpacity = qBound<qreal>(0.05, m_contentOpacity + delta, 1.0);
setContentOpacity(nextOpacity);
QToolTip::showText(event->globalPosition().toPoint(),
tr("透明度 %1%").arg(qRound(nextOpacity * 100)),
this);
event->accept();
return true;
}
const qreal step = primaryDelta > 0 ? 1.1 : 0.9;
setZoomFactor(m_zoomFactor * step);
event->accept();
return true;
}
bool StickyPinWidget::isAltOpacityAdjustActive(const QWheelEvent *event) const
{
return isAltWheelActive(event);
}
void StickyPinWidget::setContentOpacity(qreal value)
{
const qreal next = qBound<qreal>(0.05, value, 1.0);
if (qFuzzyCompare(m_contentOpacity, next)) {
return;
}
const qreal step = angleDelta.y() > 0 ? 1.1 : 0.9;
setZoomFactor(m_zoomFactor * step);
event->accept();
m_contentOpacity = next;
if (m_canvas) {
m_canvas->setContentOpacity(next);
}
update();
}
void StickyPinWidget::setZoomFactor(qreal value)
@@ -896,6 +981,7 @@ void StickyPinWidget::setZoomFactor(qreal value)
if (m_canvas) {
m_canvas->setViewScale(m_zoomFactor);
m_canvas->setBackgroundImage(m_image);
m_canvas->setContentOpacity(m_contentOpacity);
}
updateLayoutAndSize();
update();
@@ -1003,7 +1089,7 @@ void StickyPinWidget::setAiLoading(bool loading)
if (m_aiLoadingTimer) {
m_aiLoadingTimer->start();
}
update(contentRect());
update();
return;
}
@@ -1013,7 +1099,7 @@ void StickyPinWidget::setAiLoading(bool loading)
if (m_aiButton) {
m_aiButton->setIcon(QIcon(QStringLiteral(":/resource/img/lc_chat.svg")));
}
update(contentRect());
update();
}
void StickyPinWidget::updateAiLoadingIcon()
@@ -1264,3 +1350,5 @@ int StickyPinWidget::toolbarWidth() const
{
return 32 * 16 + 52 + 2 * 16 + 12;
}
+6
View File
@@ -42,6 +42,7 @@ protected:
void contextMenuEvent(QContextMenuEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void wheelEvent(QWheelEvent *event) override;
bool eventFilter(QObject *watched, QEvent *event) override;
private:
void setActiveTool(Shapeype type, QToolButton *activeButton);
@@ -49,6 +50,9 @@ private:
void updateToolOptionsPanel();
void updateLayoutAndSize();
QToolButton *currentActiveToolButton() const;
bool handleWheelInteraction(QWheelEvent *event);
bool isAltOpacityAdjustActive(const QWheelEvent *event) const;
void setContentOpacity(qreal value);
void setZoomFactor(qreal value);
void openAiEditor();
void openVisionWindow();
@@ -122,8 +126,10 @@ private:
bool m_aiLoading = false;
int m_aiLoadingFrame = 0;
qreal m_zoomFactor = 1.0;
qreal m_contentOpacity = 1.0;
QTimer *m_aiLoadingTimer = nullptr;
bool m_released = false;
};
#endif // STICKY_PIN_WIDGET_H