Add standardized OverlayMessage
Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>
This commit is contained in:
@@ -31,7 +31,7 @@ CaptureTool::Type CopyTool::type() const
|
||||
|
||||
QString CopyTool::description() const
|
||||
{
|
||||
return tr("Copy the selection into the clipboard");
|
||||
return tr("Copy selection to clipboard");
|
||||
}
|
||||
|
||||
CaptureTool* CopyTool::copy(QObject* parent)
|
||||
|
||||
@@ -37,7 +37,7 @@ CaptureTool::Type SaveTool::type() const
|
||||
|
||||
QString SaveTool::description() const
|
||||
{
|
||||
return tr("Save the capture");
|
||||
return tr("Save screenshot to a file");
|
||||
}
|
||||
|
||||
CaptureTool* SaveTool::copy(QObject* parent)
|
||||
|
||||
@@ -385,7 +385,9 @@ bool ConfigHandler::setShortcut(const QString& shortcutName,
|
||||
|
||||
QString ConfigHandler::shortcut(const QString& shortcutName)
|
||||
{
|
||||
return value(QStringLiteral("Shortcuts/") + shortcutName).toString();
|
||||
QString val = value(QStringLiteral("Shortcuts/") + shortcutName).toString();
|
||||
val.replace("Return", "Enter");
|
||||
return val;
|
||||
}
|
||||
|
||||
void ConfigHandler::setValue(const QString& key, const QVariant& value)
|
||||
|
||||
@@ -220,12 +220,7 @@ CaptureWidget::CaptureWidget(uint id,
|
||||
QGuiAppCurrentScreen().currentScreen()->geometry());
|
||||
|
||||
if (m_config.showHelp()) {
|
||||
OverlayMessage::push(
|
||||
tr("Select an area with the mouse, or press Esc to exit."
|
||||
"\nPress Enter to capture the screen."
|
||||
"\nPress Right Click to show the color picker."
|
||||
"\nUse the Mouse Wheel to change the thickness of your tool."
|
||||
"\nPress Space to open the side panel."));
|
||||
initHelpMessage();
|
||||
}
|
||||
|
||||
updateCursor();
|
||||
@@ -319,6 +314,26 @@ void CaptureWidget::initButtons()
|
||||
m_buttonHandler->setButtons(vectorButtons);
|
||||
}
|
||||
|
||||
void CaptureWidget::initHelpMessage()
|
||||
{
|
||||
QList<QPair<QString, QString>> keyMap;
|
||||
keyMap << QPair("Mouse", "Select screenshot area");
|
||||
using CT = CaptureTool;
|
||||
for (auto toolType : { CT::TYPE_ACCEPT, CT::TYPE_SAVE, CT::TYPE_COPY }) {
|
||||
auto* tool = ToolFactory().CreateTool(toolType);
|
||||
QString shortcut =
|
||||
ConfigHandler().shortcut(QVariant::fromValue(toolType).toString());
|
||||
if (!shortcut.isEmpty()) {
|
||||
keyMap << QPair(shortcut, tool->description());
|
||||
}
|
||||
}
|
||||
keyMap << QPair("Mouse Wheel", "Change tool size");
|
||||
keyMap << QPair("Right Click", "Show color picker");
|
||||
keyMap << QPair("Space", "Open side panel");
|
||||
keyMap << QPair("Esc", "Exit");
|
||||
OverlayMessage::pushKeyMap(keyMap);
|
||||
}
|
||||
|
||||
QPixmap CaptureWidget::pixmap()
|
||||
{
|
||||
return m_context.selectedScreenshotArea();
|
||||
|
||||
@@ -106,6 +106,7 @@ private:
|
||||
void initSelection();
|
||||
void initShortcuts();
|
||||
void initButtons();
|
||||
void initHelpMessage();
|
||||
void updateSizeIndicator();
|
||||
void updateCursor();
|
||||
void updateSelectionState();
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#include <QLabel>
|
||||
#include <QPainter>
|
||||
#include <QPen>
|
||||
#include <QScreen>
|
||||
#include <QWidget>
|
||||
|
||||
OverlayMessage::OverlayMessage(QWidget* parent, const QRect& targetArea)
|
||||
: QWidget(parent)
|
||||
: QLabel(parent)
|
||||
, m_targetArea(targetArea)
|
||||
{
|
||||
// NOTE: do not call the static functions from the constructor
|
||||
@@ -19,6 +19,9 @@ OverlayMessage::OverlayMessage(QWidget* parent, const QRect& targetArea)
|
||||
m_messageStack.push(QString()); // Default message is empty
|
||||
setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
setAttribute(Qt::WA_AlwaysStackOnTop);
|
||||
setAlignment(Qt::AlignCenter);
|
||||
setTextFormat(Qt::RichText);
|
||||
setMargin(QApplication::fontMetrics().height() / 2);
|
||||
QWidget::hide();
|
||||
}
|
||||
|
||||
@@ -27,9 +30,14 @@ void OverlayMessage::init(QWidget* parent, const QRect& targetArea)
|
||||
new OverlayMessage(parent, targetArea);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Push a message to the message stack.
|
||||
* @param msg Message text formatted as rich text
|
||||
*/
|
||||
void OverlayMessage::push(const QString& msg)
|
||||
{
|
||||
m_instance->m_messageStack.push(msg);
|
||||
m_instance->setText(m_instance->m_messageStack.top());
|
||||
setVisibility(true);
|
||||
}
|
||||
|
||||
@@ -39,13 +47,8 @@ void OverlayMessage::pop()
|
||||
m_instance->m_messageStack.pop();
|
||||
}
|
||||
|
||||
if (m_instance->m_messageStack.size() == 1) {
|
||||
// Only empty message left (don't show it)
|
||||
m_instance->QWidget::hide();
|
||||
} else {
|
||||
// Still visible, resize for new message
|
||||
m_instance->updateGeometry();
|
||||
}
|
||||
m_instance->setText(m_instance->m_messageStack.top());
|
||||
setVisibility(m_instance->m_messageStack.size() > 1);
|
||||
}
|
||||
|
||||
void OverlayMessage::setVisibility(bool visible)
|
||||
@@ -59,13 +62,34 @@ OverlayMessage* OverlayMessage::instance()
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
void OverlayMessage::paintEvent(QPaintEvent*)
|
||||
void OverlayMessage::pushKeyMap(const QList<QPair<QString, QString>>& map)
|
||||
{
|
||||
push(compileKeyMap(map));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compile a message from a set of shortcuts and descriptions.
|
||||
* @param map List of (shortcut, description) pairs
|
||||
*/
|
||||
QString OverlayMessage::compileKeyMap(const QList<QPair<QString, QString>>& map)
|
||||
{
|
||||
QString str = QStringLiteral("<table>");
|
||||
for (const auto& pair : map) {
|
||||
str += QStringLiteral("<tr>"
|
||||
"<td align=\"right\"><b>%1 </b></td>"
|
||||
"<td align=\"left\"> %2</td>"
|
||||
"</tr>")
|
||||
.arg(pair.first)
|
||||
.arg(pair.second);
|
||||
}
|
||||
str += QStringLiteral("</table>");
|
||||
return str;
|
||||
}
|
||||
|
||||
void OverlayMessage::paintEvent(QPaintEvent* e)
|
||||
{
|
||||
QPainter painter(this);
|
||||
|
||||
QRectF bRect = boundingRect();
|
||||
bRect.moveTo(0, 0);
|
||||
|
||||
QColor rectColor(ConfigHandler().uiColor());
|
||||
rectColor.setAlpha(180);
|
||||
QColor textColor(
|
||||
@@ -73,38 +97,23 @@ void OverlayMessage::paintEvent(QPaintEvent*)
|
||||
|
||||
painter.setBrush(QBrush(rectColor, Qt::SolidPattern));
|
||||
painter.setPen(QPen(textColor));
|
||||
|
||||
float margin = painter.pen().widthF();
|
||||
painter.drawRect(bRect - QMarginsF(margin, margin, margin, margin));
|
||||
painter.drawText(bRect, Qt::AlignCenter, m_messageStack.top());
|
||||
painter.drawRect(rect() - QMarginsF(margin, margin, margin, margin));
|
||||
|
||||
return QLabel::paintEvent(e);
|
||||
}
|
||||
|
||||
void OverlayMessage::showEvent(QShowEvent*)
|
||||
QRect OverlayMessage::boundingRect() const
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
QRectF OverlayMessage::boundingRect() const
|
||||
{
|
||||
// We draw the white contrasting background for the text, using the
|
||||
// same text and options to get the boundingRect that the text will
|
||||
// have.
|
||||
QRectF bRect = QApplication::fontMetrics().boundingRect(
|
||||
m_targetArea, Qt::AlignCenter, m_messageStack.top());
|
||||
|
||||
// These four calls provide padding for the rect
|
||||
const int margin = QApplication::fontMetrics().height() / 2;
|
||||
bRect.setWidth(bRect.width() + margin);
|
||||
bRect.setHeight(bRect.height() + margin);
|
||||
bRect.setX(bRect.x() - margin);
|
||||
bRect.setY(bRect.y() - margin);
|
||||
return bRect;
|
||||
QRect geom = QRect(QPoint(), sizeHint());
|
||||
geom.moveCenter(m_targetArea.center());
|
||||
return geom;
|
||||
}
|
||||
|
||||
void OverlayMessage::updateGeometry()
|
||||
{
|
||||
m_instance->setGeometry(m_instance->boundingRect().toRect());
|
||||
QWidget::updateGeometry();
|
||||
setGeometry(boundingRect());
|
||||
QLabel::updateGeometry();
|
||||
}
|
||||
|
||||
OverlayMessage* OverlayMessage::m_instance = nullptr;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <QLabel>
|
||||
#include <QStack>
|
||||
#include <QWidget>
|
||||
|
||||
/**
|
||||
* @brief Overlay a message in capture mode.
|
||||
@@ -17,7 +17,7 @@
|
||||
* @note You have to make sure that widgets pop the messages they pushed when
|
||||
* they are closed, to avoid potential bugs and resource leaks.
|
||||
*/
|
||||
class OverlayMessage : public QWidget
|
||||
class OverlayMessage : public QLabel
|
||||
{
|
||||
public:
|
||||
OverlayMessage() = delete;
|
||||
@@ -28,6 +28,9 @@ public:
|
||||
static void setVisibility(bool visible);
|
||||
static OverlayMessage* instance();
|
||||
|
||||
static void pushKeyMap(const QList<QPair<QString, QString>>& map);
|
||||
static QString compileKeyMap(const QList<QPair<QString, QString>>& map);
|
||||
|
||||
private:
|
||||
QStack<QString> m_messageStack;
|
||||
QRect m_targetArea;
|
||||
@@ -36,8 +39,7 @@ private:
|
||||
OverlayMessage(QWidget* parent, const QRect& center);
|
||||
|
||||
void paintEvent(QPaintEvent*) override;
|
||||
void showEvent(QShowEvent*) override;
|
||||
|
||||
QRectF boundingRect() const;
|
||||
QRect boundingRect() const;
|
||||
void updateGeometry();
|
||||
};
|
||||
|
||||
@@ -51,9 +51,9 @@ void ColorGrabWidget::startGrabbing()
|
||||
qApp->setOverrideCursor(Qt::CrossCursor);
|
||||
qApp->installEventFilter(this);
|
||||
OverlayMessage::push(
|
||||
"Press Enter or Left Mouse Button to accept color\n"
|
||||
"Press and hold Left Mouse Button to precisely select color\n"
|
||||
"Press Space or Right Mouse Button to toggle magnifier\n"
|
||||
"Press Enter or Left Mouse Button to accept color<br>"
|
||||
"Press and hold Left Mouse Button to precisely select color<br>"
|
||||
"Press Space or Right Mouse Button to toggle magnifier<br>"
|
||||
"Press ESC to cancel");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user