Extra Window: added auto hide text after timeout

This commit is contained in:
Blu3train 2022-04-19 23:01:33 +02:00
parent f732f488e6
commit d0d454df24
2 changed files with 100 additions and 14 deletions

View File

@ -15,6 +15,7 @@
#include <QWheelEvent> #include <QWheelEvent>
#include <QScrollArea> #include <QScrollArea>
#include <QAbstractNativeEventFilter> #include <QAbstractNativeEventFilter>
#include <QTimer>
extern const char* EXTRA_WINDOW_INFO; extern const char* EXTRA_WINDOW_INFO;
extern const char* TOPMOST; extern const char* TOPMOST;
@ -27,6 +28,7 @@ extern const char* CENTERED_TEXT;
extern const char* AUTO_RESIZE_WINDOW_HEIGHT; extern const char* AUTO_RESIZE_WINDOW_HEIGHT;
extern const char* CLICK_THROUGH; extern const char* CLICK_THROUGH;
extern const char* HIDE_MOUSEOVER; extern const char* HIDE_MOUSEOVER;
extern const char* HIDE_TEXT;
extern const char* DICTIONARY; extern const char* DICTIONARY;
extern const char* DICTIONARY_INSTRUCTIONS; extern const char* DICTIONARY_INSTRUCTIONS;
extern const char* BG_COLOR; extern const char* BG_COLOR;
@ -36,9 +38,16 @@ extern const char* OUTLINE_COLOR;
extern const char* OUTLINE_SIZE; extern const char* OUTLINE_SIZE;
extern const char* OUTLINE_SIZE_INFO; extern const char* OUTLINE_SIZE_INFO;
extern const char* FONT; extern const char* FONT;
extern const char* TIMER_HIDE_TEXT;
extern const char* TEXT_TIMEOUT;
extern const char* TEXT_TIMEOUT_ADD_PER_CHAR;
constexpr auto DICTIONARY_SAVE_FILE = u8"SavedDictionary.txt"; constexpr auto DICTIONARY_SAVE_FILE = u8"SavedDictionary.txt";
constexpr int CLICK_THROUGH_HOTKEY = 0xc0d0; constexpr int CLICK_THROUGH_HOTKEY = 0xc0d0;
constexpr int HIDE_TEXT_HOTKEY = 0xc0d1;
const qreal COLOR_ALFAF_HIDE_WINDOW = 0.05;
const int TEXT_TIMEOUT_DEF = 2000;
const int TEXT_TIMEOUT_ADD_PER_CHAR_DEF = 40;
QColor colorPrompt(QWidget* parent, QColor default, const QString& title, bool customOpacity = true) QColor colorPrompt(QWidget* parent, QColor default, const QString& title, bool customOpacity = true)
{ {
@ -49,6 +58,10 @@ QColor colorPrompt(QWidget* parent, QColor default, const QString& title, bool c
struct PrettyWindow : QDialog, Localizer struct PrettyWindow : QDialog, Localizer
{ {
QAction *hideTextAction;
QTimer *timerHideText = new QTimer(this);
int text_timeout, text_timeout_per_char;
PrettyWindow(const char* name) PrettyWindow(const char* name)
{ {
ui.setupUi(this); ui.setupUi(this);
@ -64,18 +77,24 @@ struct PrettyWindow : QDialog, Localizer
outliner->color = settings.value(OUTLINE_COLOR, outliner->color).value<QColor>(); outliner->color = settings.value(OUTLINE_COLOR, outliner->color).value<QColor>();
outliner->size = settings.value(OUTLINE_SIZE, outliner->size).toDouble(); outliner->size = settings.value(OUTLINE_SIZE, outliner->size).toDouble();
autoHide = settings.value(HIDE_MOUSEOVER, autoHide).toBool(); autoHide = settings.value(HIDE_MOUSEOVER, autoHide).toBool();
text_timeout = settings.value(TEXT_TIMEOUT, TEXT_TIMEOUT_DEF).toInt();
text_timeout_per_char = settings.value(TEXT_TIMEOUT_ADD_PER_CHAR, TEXT_TIMEOUT_ADD_PER_CHAR_DEF).toInt();
menu.addAction(FONT, this, &PrettyWindow::RequestFont); menu.addAction(FONT, this, &PrettyWindow::RequestFont);
menu.addAction(BG_COLOR, [this] { SetBackgroundColor(colorPrompt(this, backgroundColor, BG_COLOR)); }); menu.addAction(BG_COLOR, [this] { if (hideText) ToggleHideText(); SetBackgroundColor(colorPrompt(this, backgroundColor, BG_COLOR)); });
menu.addAction(TEXT_COLOR, [this] { SetTextColor(colorPrompt(this, TextColor(), TEXT_COLOR)); }); menu.addAction(TEXT_COLOR, [this] { if (hideText) ToggleHideText(); SetTextColor(colorPrompt(this, TextColor(), TEXT_COLOR)); });
QAction* outlineAction = menu.addAction(TEXT_OUTLINE, this, &PrettyWindow::SetOutline); QAction* outlineAction = menu.addAction(TEXT_OUTLINE, this, &PrettyWindow::SetOutline);
outlineAction->setCheckable(true); outlineAction->setCheckable(true);
outlineAction->setChecked(outliner->size >= 0); outlineAction->setChecked(outliner->size >= 0);
QAction* autoHideAction = menu.addAction(HIDE_MOUSEOVER, this, [this](bool autoHide) { settings.setValue(HIDE_MOUSEOVER, this->autoHide = autoHide); }); menu.addAction(TIMER_HIDE_TEXT, this, &PrettyWindow::SetTimerHideText);
QAction* autoHideAction = menu.addAction(HIDE_MOUSEOVER, this, &PrettyWindow::SetHideMouseover);
autoHideAction->setCheckable(true); autoHideAction->setCheckable(true);
autoHideAction->setChecked(autoHide); autoHideAction->setChecked(autoHide);
connect(this, &QDialog::customContextMenuRequested, [this](QPoint point) { menu.exec(mapToGlobal(point)); }); connect(this, &QDialog::customContextMenuRequested, [this](QPoint point) { menu.exec(mapToGlobal(point)); });
connect(ui.display, &QLabel::customContextMenuRequested, [this](QPoint point) { menu.exec(ui.display->mapToGlobal(point)); }); connect(ui.display, &QLabel::customContextMenuRequested, [this](QPoint point) { menu.exec(ui.display->mapToGlobal(point)); });
startTimer(50); startTimer(50);
timerHideText->setSingleShot(true);
connect(timerHideText, &QTimer::timeout, [=]() {on_timeoutHideText();});
} }
~PrettyWindow() ~PrettyWindow()
@ -85,29 +104,55 @@ struct PrettyWindow : QDialog, Localizer
Ui::ExtraWindow ui; Ui::ExtraWindow ui;
protected: protected:
bool hidden = false, autoHide = false, hideText=false;
qreal backgroundColorAlphaF = COLOR_ALFAF_HIDE_WINDOW;
void SetBackgroundColorHideText(bool hideText)
{
if (hideText)
{
if (settings.value(BG_COLOR).value<QColor>().alpha() > backgroundColorAlphaF) backgroundColor.setAlphaF(backgroundColorAlphaF);
if (settings.value(OUTLINE_COLOR).value<QColor>().alpha() > backgroundColorAlphaF) outliner->color.setAlphaF(backgroundColorAlphaF);
QColor hiddenTextColor = TextColor();
if (settings.value(TEXT_COLOR).value<QColor>().alpha() > backgroundColorAlphaF) hiddenTextColor.setAlphaF(backgroundColorAlphaF);
ui.display->setPalette(QPalette(hiddenTextColor, {}, {}, {}, {}, {}, {}));
repaint();
}
else
{
backgroundColor.setAlpha(settings.value(BG_COLOR).value<QColor>().alpha());
outliner->color.setAlpha(settings.value(OUTLINE_COLOR).value<QColor>().alpha());
ui.display->setPalette(QPalette(settings.value(TEXT_COLOR).value<QColor>(), {}, {}, {}, {}, {}, {}));
repaint();
}
}
void ToggleHideText()
{
if (!autoHide)
{
hideText = !hideText;
SetBackgroundColorHideText(hideText);
}
};
void timerEvent(QTimerEvent*) override void timerEvent(QTimerEvent*) override
{ {
if (autoHide && geometry().contains(QCursor::pos())) if (autoHide && geometry().contains(QCursor::pos()))
{ {
if (!hidden) if (!hidden)
{ {
if (backgroundColor.alphaF() > 0.05) backgroundColor.setAlphaF(0.05);
if (outliner->color.alphaF() > 0.05) outliner->color.setAlphaF(0.05);
QColor hiddenTextColor = TextColor();
if (hiddenTextColor.alphaF() > 0.05) hiddenTextColor.setAlphaF(0.05);
ui.display->setPalette(QPalette(hiddenTextColor, {}, {}, {}, {}, {}, {}));
hidden = true; hidden = true;
repaint(); SetBackgroundColorHideText(true);
} }
} }
else if (hidden) else if (hidden)
{ {
backgroundColor.setAlpha(settings.value(BG_COLOR).value<QColor>().alpha());
outliner->color.setAlpha(settings.value(OUTLINE_COLOR).value<QColor>().alpha());
ui.display->setPalette(QPalette(settings.value(TEXT_COLOR).value<QColor>(), {}, {}, {}, {}, {}, {}));
hidden = false; hidden = false;
repaint(); SetBackgroundColorHideText(false);
} }
} }
@ -115,6 +160,12 @@ protected:
Settings settings{ this }; Settings settings{ this };
private: private:
void on_timeoutHideText()
{
if (!hideText)
ToggleHideText();
}
void RequestFont() void RequestFont()
{ {
if (QFont font = QFontDialog::getFont(&ok, ui.display->font(), this, FONT); ok) if (QFont font = QFontDialog::getFont(&ok, ui.display->font(), this, FONT); ok)
@ -147,6 +198,8 @@ private:
void SetOutline(bool enable) void SetOutline(bool enable)
{ {
if (hideText)
ToggleHideText();
if (enable) if (enable)
{ {
QColor color = colorPrompt(this, outliner->color, OUTLINE_COLOR); QColor color = colorPrompt(this, outliner->color, OUTLINE_COLOR);
@ -158,12 +211,28 @@ private:
settings.setValue(OUTLINE_SIZE, outliner->size); settings.setValue(OUTLINE_SIZE, outliner->size);
} }
void SetHideMouseover(bool autoHide)
{
if (hideText)
ToggleHideText();
settings.setValue(HIDE_MOUSEOVER, this->autoHide = autoHide);
hideTextAction->setDisabled(autoHide);
};
void SetTimerHideText()
{
text_timeout = QInputDialog::getInt(this, TIMER_HIDE_TEXT, TEXT_TIMEOUT, text_timeout, 0, INT_MAX, 2, nullptr, Qt::WindowCloseButtonHint);
text_timeout_per_char = QInputDialog::getInt(this, TIMER_HIDE_TEXT, TEXT_TIMEOUT_ADD_PER_CHAR, text_timeout_per_char, 0, INT_MAX, 2, nullptr, Qt::WindowCloseButtonHint);
settings.setValue(TEXT_TIMEOUT, text_timeout);
settings.setValue(TEXT_TIMEOUT_ADD_PER_CHAR, text_timeout_per_char);
};
void paintEvent(QPaintEvent*) override void paintEvent(QPaintEvent*) override
{ {
QPainter(this).fillRect(rect(), backgroundColor); QPainter(this).fillRect(rect(), backgroundColor);
} }
bool autoHide = false, hidden = false;
QColor backgroundColor{ palette().window().color() }; QColor backgroundColor{ palette().window().color() };
struct Outliner : QGraphicsEffect struct Outliner : QGraphicsEffect
{ {
@ -214,6 +283,7 @@ public:
action->setChecked(default); action->setChecked(default);
} }
hideTextAction = menu.addAction(HIDE_TEXT, this, &ExtraWindow::ToggleHideText);
menu.addAction(CLICK_THROUGH, this, &ExtraWindow::ToggleClickThrough); menu.addAction(CLICK_THROUGH, this, &ExtraWindow::ToggleClickThrough);
ui.display->installEventFilter(this); ui.display->installEventFilter(this);
@ -221,6 +291,7 @@ public:
QMetaObject::invokeMethod(this, [this] QMetaObject::invokeMethod(this, [this]
{ {
RegisterHotKey((HWND)winId(), HIDE_TEXT_HOTKEY, MOD_ALT | MOD_NOREPEAT, 0x54);
RegisterHotKey((HWND)winId(), CLICK_THROUGH_HOTKEY, MOD_ALT | MOD_NOREPEAT, 0x58); RegisterHotKey((HWND)winId(), CLICK_THROUGH_HOTKEY, MOD_ALT | MOD_NOREPEAT, 0x58);
show(); show();
AddSentence(EXTRA_WINDOW_INFO); AddSentence(EXTRA_WINDOW_INFO);
@ -273,6 +344,10 @@ private:
resize(width(), height() - ui.display->height() + resize(width(), height() - ui.display->height() +
QFontMetrics(ui.display->font(), ui.display).boundingRect(0, 0, ui.display->width(), INT_MAX, Qt::TextWordWrap, sentence).height() QFontMetrics(ui.display->font(), ui.display).boundingRect(0, 0, ui.display->width(), INT_MAX, Qt::TextWordWrap, sentence).height()
); );
if (hideText)
ToggleHideText();
if (text_timeout > 0 && !autoHide)
timerHideText->start(text_timeout+sentence.size()*text_timeout_per_char);
} }
void SetTopmost(bool topmost) void SetTopmost(bool topmost)
@ -341,6 +416,8 @@ private:
else exStyle &= ~WS_EX_TRANSPARENT; else exStyle &= ~WS_EX_TRANSPARENT;
SetWindowLongPtrW((HWND)window, GWL_EXSTYLE, exStyle); SetWindowLongPtrW((HWND)window, GWL_EXSTYLE, exStyle);
} }
backgroundColorAlphaF = clickThrough ? 0.0 : COLOR_ALFAF_HIDE_WINDOW;
SetBackgroundColorHideText(hidden || hideText);
}; };
void ShowDictionary(QPoint mouse) void ShowDictionary(QPoint mouse)
@ -385,6 +462,7 @@ private:
{ {
auto msg = (MSG*)message; auto msg = (MSG*)message;
if (msg->message == WM_HOTKEY) if (msg->message == WM_HOTKEY)
if (msg->wParam == HIDE_TEXT_HOTKEY) return ToggleHideText(), true;
if (msg->wParam == CLICK_THROUGH_HOTKEY) return ToggleClickThrough(), true; if (msg->wParam == CLICK_THROUGH_HOTKEY) return ToggleClickThrough(), true;
return false; return false;
} }

View File

@ -184,6 +184,7 @@ const char* CENTERED_TEXT = u8"Centered text";
const char* AUTO_RESIZE_WINDOW_HEIGHT = u8"Auto resize window height"; const char* AUTO_RESIZE_WINDOW_HEIGHT = u8"Auto resize window height";
const char* CLICK_THROUGH = u8"Click through\tAlt+X"; const char* CLICK_THROUGH = u8"Click through\tAlt+X";
const char* HIDE_MOUSEOVER = u8"Hide while mouse on top"; const char* HIDE_MOUSEOVER = u8"Hide while mouse on top";
const char* HIDE_TEXT = u8"Hide/Show text\tAlt+T";
const char* OPACITY = u8"Opacity"; const char* OPACITY = u8"Opacity";
const char* BG_COLOR = u8"Background color"; const char* BG_COLOR = u8"Background color";
const char* TEXT_COLOR = u8"Text color"; const char* TEXT_COLOR = u8"Text color";
@ -192,6 +193,9 @@ const char* OUTLINE_COLOR = u8"Outline color";
const char* OUTLINE_SIZE = u8"Outline size"; const char* OUTLINE_SIZE = u8"Outline size";
const char* OUTLINE_SIZE_INFO = u8"Size in pixels (recommended to stay below 20% of the font size)"; const char* OUTLINE_SIZE_INFO = u8"Size in pixels (recommended to stay below 20% of the font size)";
const char* FONT = u8"Font"; const char* FONT = u8"Font";
const char* TIMER_HIDE_TEXT = u8"Timer hide text";
const char* TEXT_TIMEOUT = u8"Timeout (msec, 0=disabled)";
const char* TEXT_TIMEOUT_ADD_PER_CHAR = u8"Additional timeout per char (msec)";
const char* LUA_INTRO = u8R"(--[[ const char* LUA_INTRO = u8R"(--[[
ProcessSentence is called each time Textractor receives a sentence of text. ProcessSentence is called each time Textractor receives a sentence of text.
@ -903,6 +907,7 @@ Funziona solo se questa estenzione è usata direttamente dopo un'estensione di t
AUTO_RESIZE_WINDOW_HEIGHT = u8"Auto resize altezza finestra"; AUTO_RESIZE_WINDOW_HEIGHT = u8"Auto resize altezza finestra";
CLICK_THROUGH = u8"Clicca attraverso\tAlt+X"; CLICK_THROUGH = u8"Clicca attraverso\tAlt+X";
HIDE_MOUSEOVER = u8"Nascondi testo mouseover"; HIDE_MOUSEOVER = u8"Nascondi testo mouseover";
HIDE_TEXT = u8"Nascondi/Mostra testo\tAlt+T";
OPACITY = u8"Opacità"; OPACITY = u8"Opacità";
BG_COLOR = u8"Colore dello sfondo"; BG_COLOR = u8"Colore dello sfondo";
TEXT_COLOR = u8"Colore del testo"; TEXT_COLOR = u8"Colore del testo";
@ -911,6 +916,9 @@ Funziona solo se questa estenzione è usata direttamente dopo un'estensione di t
OUTLINE_SIZE = u8"Dimensione del contorno"; OUTLINE_SIZE = u8"Dimensione del contorno";
OUTLINE_SIZE_INFO = u8"Dimensione in pixel (consigliato di rimanere sotto il 20% della dimensione del font)"; OUTLINE_SIZE_INFO = u8"Dimensione in pixel (consigliato di rimanere sotto il 20% della dimensione del font)";
FONT = u8"Font"; FONT = u8"Font";
TIMER_HIDE_TEXT = u8"Timer nascondi testo";
TEXT_TIMEOUT = u8"Timeout (msec, 0=disattivato)";
TEXT_TIMEOUT_ADD_PER_CHAR = u8"Timeout aggiuntivo per carattere (msec)";
LUA_INTRO = u8R"(--[[ LUA_INTRO = u8R"(--[[
ProcessSentence è chiamato ogni volta che Textractor riceva una sentenza di testo. ProcessSentence è chiamato ogni volta che Textractor riceva una sentenza di testo.