Add standardized OverlayMessage

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>
This commit is contained in:
Haris Gušić
2021-10-08 15:23:48 +02:00
parent 5ee85ed5c0
commit 1f2afebaa5
8 changed files with 82 additions and 53 deletions

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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();

View File

@@ -106,6 +106,7 @@ private:
void initSelection();
void initShortcuts();
void initButtons();
void initHelpMessage();
void updateSizeIndicator();
void updateCursor();
void updateSelectionState();

View File

@@ -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\">&nbsp;&nbsp;%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;

View File

@@ -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();
};

View File

@@ -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");
}