Allow custom context menus on labels.

This commit is contained in:
John Preston 2022-11-29 13:41:12 +04:00
parent e6064719df
commit 0937ac0ad0
2 changed files with 57 additions and 28 deletions

View file

@ -403,6 +403,10 @@ void FlatLabel::overrideLinkClickHandler(Fn<void(QString url)> handler) {
});
}
void FlatLabel::setContextMenuHook(Fn<void(ContextMenuRequest)> hook) {
_contextMenuHook = std::move(hook);
}
void FlatLabel::mouseMoveEvent(QMouseEvent *e) {
_lastMousePos = e->globalPos();
dragActionUpdate();
@ -579,7 +583,7 @@ void FlatLabel::keyPressEvent(QKeyEvent *e) {
}
void FlatLabel::contextMenuEvent(QContextMenuEvent *e) {
if (!_selectable && !_text.hasLinks()) {
if (!_contextMenuHook && !_selectable && !_text.hasLinks()) {
return;
}
@ -661,42 +665,27 @@ void FlatLabel::showContextMenu(QContextMenuEvent *e, ContextMenuReason reason)
} else {
_lastMousePos = QCursor::pos();
}
auto state = dragActionUpdate();
const auto state = dragActionUpdate();
const auto hasSelection = _selectable && !_selection.empty();
const auto uponSelection = _selectable
&& ((reason == ContextMenuReason::FromTouch && hasSelection)
|| (state.uponSymbol
&& (state.symbol >= _selection.from)
&& (state.symbol < _selection.to)));
const auto fullSelection = _selectable
&& _text.isFullSelection(_selection);
_contextMenu = base::make_unique_q<PopupMenu>(this, _stMenu);
const auto request = ContextMenuRequest{
.menu = _contextMenu.get(),
.link = ClickHandler::getActive(),
.hasSelection = hasSelection,
.uponSelection = uponSelection,
.fullSelection = _selectable && _text.isFullSelection(_selection),
};
if (fullSelection && !_contextCopyText.isEmpty()) {
_contextMenu->addAction(
_contextCopyText,
[=] { copyContextText(); });
} else if (uponSelection && !fullSelection) {
_contextMenu->addAction(
Integration::Instance().phraseContextCopySelected(),
[=] { copySelectedText(); });
} else if (_selectable && !hasSelection && !_contextCopyText.isEmpty()) {
_contextMenu->addAction(
_contextCopyText,
[=] { copyContextText(); });
}
if (const auto link = ClickHandler::getActive()) {
const auto actionText = link->copyToClipboardContextItemText();
if (!actionText.isEmpty()) {
_contextMenu->addAction(
actionText,
[text = link->copyToClipboardText()] {
QGuiApplication::clipboard()->setText(text);
});
}
if (_contextMenuHook) {
_contextMenuHook(request);
} else {
fillContextMenu(request);
}
if (_contextMenu->empty()) {
@ -707,6 +696,35 @@ void FlatLabel::showContextMenu(QContextMenuEvent *e, ContextMenuReason reason)
}
}
void FlatLabel::fillContextMenu(ContextMenuRequest request) {
if (request.fullSelection && !_contextCopyText.isEmpty()) {
request.menu->addAction(
_contextCopyText,
[=] { copyContextText(); });
} else if (request.uponSelection && !request.fullSelection) {
request.menu->addAction(
Integration::Instance().phraseContextCopySelected(),
[=] { copySelectedText(); });
} else if (_selectable
&& !request.hasSelection
&& !_contextCopyText.isEmpty()) {
request.menu->addAction(
_contextCopyText,
[=] { copyContextText(); });
}
if (request.link) {
const auto label = request.link->copyToClipboardContextItemText();
if (!label.isEmpty()) {
request.menu->addAction(
label,
[text = request.link->copyToClipboardText()] {
QGuiApplication::clipboard()->setText(text);
});
}
}
}
void FlatLabel::copySelectedText() {
const auto selection = _selection.empty() ? (_contextMenu ? _savedSelection : _selection) : _selection;
if (!selection.empty()) {

View file

@ -142,6 +142,15 @@ public:
void overrideLinkClickHandler(Fn<void()> handler);
void overrideLinkClickHandler(Fn<void(QString url)> handler);
struct ContextMenuRequest {
not_null<PopupMenu*> menu;
ClickHandlerPtr link;
bool hasSelection = false;
bool uponSelection = false;
bool fullSelection = false;
};
void setContextMenuHook(Fn<void(ContextMenuRequest)> hook);
// ClickHandlerHost interface
void clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) override;
void clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) override;
@ -201,6 +210,7 @@ private:
FromTouch,
};
void showContextMenu(QContextMenuEvent *e, ContextMenuReason reason);
void fillContextMenu(ContextMenuRequest request);
Text::String _text;
const style::FlatLabel &_st;
@ -237,6 +247,7 @@ private:
base::Timer _trippleClickTimer;
base::unique_qptr<PopupMenu> _contextMenu;
Fn<void(ContextMenuRequest)> _contextMenuHook;
QString _contextCopyText;
ClickHandlerFilter _clickHandlerFilter;