Improve Ui::Menu interface.

This commit is contained in:
John Preston 2019-04-19 11:35:35 +04:00
parent 9acdc4eac1
commit 607655941d
11 changed files with 60 additions and 55 deletions

View File

@ -1616,8 +1616,12 @@ void DialogsInner::contextMenuEvent(QContextMenuEvent *e) {
selectByMouse(globalPosition);
}
});
_menu->popup(e->globalPos());
e->accept();
if (_menu->actions().empty()) {
_menu = nullptr;
} else {
_menu->popup(e->globalPos());
e->accept();
}
}
void DialogsInner::onParentGeometryChanged() {

View File

@ -1065,7 +1065,7 @@ void InnerWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
}
}
if (_menu->actions().isEmpty()) {
if (_menu->actions().empty()) {
_menu = nullptr;
} else {
_menu->popup(e->globalPos());

View File

@ -1782,7 +1782,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
}
}
if (_menu->actions().isEmpty()) {
if (_menu->actions().empty()) {
_menu = nullptr;
} else {
_menu->popup(e->globalPos());

View File

@ -1614,7 +1614,7 @@ void ListWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
_overState));
_menu = FillContextMenu(this, request);
if (_menu && !_menu->actions().isEmpty()) {
if (_menu && !_menu->actions().empty()) {
_menu->popup(e->globalPos());
e->accept();
} else if (_menu) {

View File

@ -51,15 +51,15 @@ void DropdownMenu::init() {
hide();
}
QAction *DropdownMenu::addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon, const style::icon *iconOver) {
not_null<QAction*> DropdownMenu::addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon, const style::icon *iconOver) {
return _menu->addAction(text, receiver, member, icon, iconOver);
}
QAction *DropdownMenu::addAction(const QString &text, Fn<void()> callback, const style::icon *icon, const style::icon *iconOver) {
not_null<QAction*> DropdownMenu::addAction(const QString &text, Fn<void()> callback, const style::icon *icon, const style::icon *iconOver) {
return _menu->addAction(text, std::move(callback), icon, iconOver);
}
QAction *DropdownMenu::addSeparator() {
not_null<QAction*> DropdownMenu::addSeparator() {
return _menu->addSeparator();
}
@ -70,7 +70,7 @@ void DropdownMenu::clearActions() {
return _menu->clearActions();
}
DropdownMenu::Actions &DropdownMenu::actions() {
const std::vector<not_null<QAction*>> &DropdownMenu::actions() const {
return _menu->actions();
}

View File

@ -19,17 +19,16 @@ class DropdownMenu : public InnerDropdown {
public:
DropdownMenu(QWidget *parent, const style::DropdownMenu &st = st::defaultDropdownMenu);
QAction *addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr);
QAction *addAction(const QString &text, Fn<void()> callback, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr);
QAction *addSeparator();
not_null<QAction*> addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr);
not_null<QAction*> addAction(const QString &text, Fn<void()> callback, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr);
not_null<QAction*> addSeparator();
void clearActions();
void setHiddenCallback(Fn<void()> callback) {
_hiddenCallback = std::move(callback);
}
using Actions = Ui::Menu::Actions;
Actions &actions();
const std::vector<not_null<QAction*>> &actions() const;
~DropdownMenu();

View File

@ -557,7 +557,7 @@ void FlatLabel::showContextMenu(QContextMenuEvent *e, ContextMenuReason reason)
}
}
if (_contextMenu->actions().isEmpty()) {
if (_contextMenu->actions().empty()) {
delete _contextMenu;
_contextMenu = nullptr;
} else {

View File

@ -43,30 +43,28 @@ void Menu::init() {
setAttribute(Qt::WA_OpaquePaintEvent);
}
QAction *Menu::addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon, const style::icon *iconOver) {
auto action = addAction(new QAction(text, this), icon, iconOver);
not_null<QAction*> Menu::addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon, const style::icon *iconOver) {
const auto action = addAction(new QAction(text, this), icon, iconOver);
connect(action, SIGNAL(triggered(bool)), receiver, member, Qt::QueuedConnection);
return action;
}
QAction *Menu::addAction(const QString &text, Fn<void()> callback, const style::icon *icon, const style::icon *iconOver) {
auto action = addAction(new QAction(text, this), icon, iconOver);
not_null<QAction*> Menu::addAction(const QString &text, Fn<void()> callback, const style::icon *icon, const style::icon *iconOver) {
const auto action = addAction(new QAction(text, this), icon, iconOver);
connect(action, &QAction::triggered, action, std::move(callback), Qt::QueuedConnection);
return action;
}
QAction *Menu::addAction(QAction *action, const style::icon *icon, const style::icon *iconOver) {
not_null<QAction*> Menu::addAction(not_null<QAction*> action, const style::icon *icon, const style::icon *iconOver) {
connect(action, SIGNAL(changed()), this, SLOT(actionChanged()));
_actions.push_back(action);
auto createData = [icon, iconOver, action] {
_actions.emplace_back(action);
_actionsData.push_back([&] {
auto data = ActionData();
data.icon = icon;
data.iconOver = iconOver ? iconOver : icon;
data.hasSubmenu = (action->menu() != nullptr);
return data;
};
_actionsData.push_back(createData());
}());
auto newWidth = qMax(width(), _st.widthMin);
newWidth = processAction(action, _actions.size() - 1, newWidth);
@ -81,8 +79,8 @@ QAction *Menu::addAction(QAction *action, const style::icon *icon, const style::
return action;
}
QAction *Menu::addSeparator() {
auto separator = new QAction(this);
not_null<QAction*> Menu::addSeparator() {
const auto separator = new QAction(this);
separator->setSeparator(true);
return addAction(separator);
}
@ -113,7 +111,7 @@ void Menu::finishAnimating() {
}
}
int Menu::processAction(QAction *action, int index, int width) {
int Menu::processAction(not_null<QAction*> action, int index, int width) {
auto &data = _actionsData[index];
if (action->isSeparator() || action->text().isEmpty()) {
data.text = data.shortcut = QString();
@ -149,10 +147,10 @@ int Menu::processAction(QAction *action, int index, int width) {
void Menu::setShowSource(TriggeredSource source) {
_mouseSelection = (source == TriggeredSource::Mouse);
setSelected((source == TriggeredSource::Mouse || _actions.isEmpty()) ? -1 : 0);
setSelected((source == TriggeredSource::Mouse || _actions.empty()) ? -1 : 0);
}
Menu::Actions &Menu::actions() {
const std::vector<not_null<QAction*>> &Menu::actions() const {
return _actions;
}
@ -163,8 +161,9 @@ void Menu::setForceWidth(int forceWidth) {
void Menu::actionChanged() {
auto newWidth = _st.widthMin;
for (auto i = 0, count = _actions.size(); i != count; ++i) {
newWidth = processAction(_actions[i], i, newWidth);
auto index = 0;
for (const auto action : _actions) {
newWidth = processAction(action, index++, newWidth);
}
if (newWidth != width() && !_forceWidth) {
resize(newWidth, height());
@ -188,10 +187,10 @@ void Menu::paintEvent(QPaintEvent *e) {
int top = _st.skip;
p.translate(0, top);
p.setFont(_st.itemFont);
for (int i = 0, count = _actions.size(); i != count; ++i) {
for (int i = 0, count = int(_actions.size()); i != count; ++i) {
if (clip.top() + clip.height() <= top) break;
auto action = _actions[i];
const auto action = _actions[i];
auto &data = _actionsData[i];
auto actionHeight = action->isSeparator() ? _separatorHeight : _itemHeight;
top += actionHeight;
@ -300,12 +299,14 @@ void Menu::handleKeyPress(int key) {
if (_selected >= 0 && _actionsData[_selected].hasSubmenu) {
itemPressed(TriggeredSource::Keyboard);
return;
} else if (_selected < 0 && !_actions.isEmpty()) {
} else if (_selected < 0 && !_actions.empty()) {
_mouseSelection = false;
setSelected(0);
}
}
if ((key != Qt::Key_Up && key != Qt::Key_Down) || _actions.size() < 1) return;
if ((key != Qt::Key_Up && key != Qt::Key_Down) || _actions.empty()) {
return;
}
auto delta = (key == Qt::Key_Down ? 1 : -1), start = _selected;
if (start < 0 || start >= _actions.size()) {
@ -367,7 +368,10 @@ void Menu::setSelected(int selected) {
updateSelectedItem();
if (_activatedCallback) {
auto source = _mouseSelection ? TriggeredSource::Mouse : TriggeredSource::Keyboard;
_activatedCallback((_selected >= 0) ? _actions[_selected] : nullptr, itemTop(_selected), source);
_activatedCallback(
(_selected >= 0) ? _actions[_selected].get() : nullptr,
itemTop(_selected),
source);
}
}
}

View File

@ -21,9 +21,9 @@ public:
Menu(QWidget *parent, const style::Menu &st = st::defaultMenu);
Menu(QWidget *parent, QMenu *menu, const style::Menu &st = st::defaultMenu);
QAction *addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr);
QAction *addAction(const QString &text, Fn<void()> callback, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr);
QAction *addSeparator();
not_null<QAction*> addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr);
not_null<QAction*> addAction(const QString &text, Fn<void()> callback, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr);
not_null<QAction*> addSeparator();
void clearActions();
void finishAnimating();
@ -39,8 +39,7 @@ public:
void setShowSource(TriggeredSource source);
void setForceWidth(int forceWidth);
using Actions = QList<QAction*>;
Actions &actions();
const std::vector<not_null<QAction*>> &actions() const;
void setResizedCallback(Fn<void()> callback) {
_resizedCallback = std::move(callback);
@ -107,8 +106,8 @@ private:
void init();
// Returns the new width.
int processAction(QAction *action, int index, int width);
QAction *addAction(QAction *a, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr);
int processAction(not_null<QAction*> action, int index, int width);
not_null<QAction*> addAction(not_null<QAction*> action, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr);
void setSelected(int selected);
void setPressed(int pressed);
@ -131,7 +130,7 @@ private:
Fn<void(QPoint globalPosition)> _mouseReleaseDelegate;
QMenu *_wappedMenu = nullptr;
Actions _actions;
std::vector<not_null<QAction*>> _actions;
std::vector<ActionData> _actionsData;
int _forceWidth = 0;

View File

@ -91,26 +91,26 @@ void PopupMenu::handleMenuResize() {
_inner = rect().marginsRemoved(_padding);
}
QAction *PopupMenu::addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon, const style::icon *iconOver) {
not_null<QAction*> PopupMenu::addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon, const style::icon *iconOver) {
return _menu->addAction(text, receiver, member, icon, iconOver);
}
QAction *PopupMenu::addAction(const QString &text, Fn<void()> callback, const style::icon *icon, const style::icon *iconOver) {
not_null<QAction*> PopupMenu::addAction(const QString &text, Fn<void()> callback, const style::icon *icon, const style::icon *iconOver) {
return _menu->addAction(text, std::move(callback), icon, iconOver);
}
QAction *PopupMenu::addSeparator() {
not_null<QAction*> PopupMenu::addSeparator() {
return _menu->addSeparator();
}
void PopupMenu::clearActions() {
for (auto submenu : base::take(_submenus)) {
for (const auto &submenu : base::take(_submenus)) {
delete submenu;
}
return _menu->clearActions();
}
PopupMenu::Actions &PopupMenu::actions() {
const std::vector<not_null<QAction*>> &PopupMenu::actions() const {
return _menu->actions();
}

View File

@ -20,13 +20,12 @@ public:
PopupMenu(QWidget *parent, const style::PopupMenu &st = st::defaultPopupMenu);
PopupMenu(QWidget *parent, QMenu *menu, const style::PopupMenu &st = st::defaultPopupMenu);
QAction *addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr);
QAction *addAction(const QString &text, Fn<void()> callback, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr);
QAction *addSeparator();
not_null<QAction*> addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr);
not_null<QAction*> addAction(const QString &text, Fn<void()> callback, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr);
not_null<QAction*> addSeparator();
void clearActions();
using Actions = Ui::Menu::Actions;
Actions &actions();
const std::vector<not_null<QAction*>> &actions() const;
void deleteOnHide(bool del);
void popup(const QPoint &p);