Co-authored-by: Rasmus Karlsson <rasmus.karlsson@pajlada.com> Co-authored-by: nerix <nerixdev@outlook.de>
This commit is contained in:
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
## Unversioned
|
## Unversioned
|
||||||
|
|
||||||
- Minor: Added an option to allow multiple user-selected extensions to interact with Chatterino. (#5997)
|
- Minor: Added an option to allow multiple user-selected extensions to interact with Chatterino. (#5997)
|
||||||
- Minor: Add `Set highlight sounds` and `Open subscription page` split hotkeys. (#5856)
|
- Minor: Add `Set highlight sounds` and `Open subscription page` split hotkeys. (#5856, #6030)
|
||||||
- Minor: `/clear` messages are now stacked like timeouts. (#5806)
|
- Minor: `/clear` messages are now stacked like timeouts. (#5806)
|
||||||
- Minor: Treat all browsers starting with `firefox` as a Firefox browser. (#5805)
|
- Minor: Treat all browsers starting with `firefox` as a Firefox browser. (#5805)
|
||||||
- Minor: Remove incognito browser support for `opera/launcher` (this should no longer be a thing). (#5805)
|
- Minor: Remove incognito browser support for `opera/launcher` (this should no longer be a thing). (#5805)
|
||||||
|
|||||||
@@ -464,32 +464,32 @@ void Split::addShortcuts()
|
|||||||
{
|
{
|
||||||
HotkeyController::HotkeyMap actions{
|
HotkeyController::HotkeyMap actions{
|
||||||
{"delete",
|
{"delete",
|
||||||
[this](std::vector<QString>) -> QString {
|
[this](const std::vector<QString> &) -> QString {
|
||||||
this->deleteFromContainer();
|
this->deleteFromContainer();
|
||||||
return "";
|
return "";
|
||||||
}},
|
}},
|
||||||
{"changeChannel",
|
{"changeChannel",
|
||||||
[this](std::vector<QString>) -> QString {
|
[this](const std::vector<QString> &) -> QString {
|
||||||
this->changeChannel();
|
this->changeChannel();
|
||||||
return "";
|
return "";
|
||||||
}},
|
}},
|
||||||
{"showSearch",
|
{"showSearch",
|
||||||
[this](std::vector<QString>) -> QString {
|
[this](const std::vector<QString> &) -> QString {
|
||||||
this->showSearch(true);
|
this->showSearch(true);
|
||||||
return "";
|
return "";
|
||||||
}},
|
}},
|
||||||
{"showGlobalSearch",
|
{"showGlobalSearch",
|
||||||
[this](std::vector<QString>) -> QString {
|
[this](const std::vector<QString> &) -> QString {
|
||||||
this->showSearch(false);
|
this->showSearch(false);
|
||||||
return "";
|
return "";
|
||||||
}},
|
}},
|
||||||
{"reconnect",
|
{"reconnect",
|
||||||
[this](std::vector<QString>) -> QString {
|
[this](const std::vector<QString> &) -> QString {
|
||||||
this->reconnect();
|
this->reconnect();
|
||||||
return "";
|
return "";
|
||||||
}},
|
}},
|
||||||
{"debug",
|
{"debug",
|
||||||
[](std::vector<QString>) -> QString {
|
[](const std::vector<QString> &) -> QString {
|
||||||
auto *popup = new DebugPopup;
|
auto *popup = new DebugPopup;
|
||||||
popup->setAttribute(Qt::WA_DeleteOnClose);
|
popup->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
popup->setWindowTitle("Chatterino - Debug popup");
|
popup->setWindowTitle("Chatterino - Debug popup");
|
||||||
@@ -497,8 +497,8 @@ void Split::addShortcuts()
|
|||||||
return "";
|
return "";
|
||||||
}},
|
}},
|
||||||
{"focus",
|
{"focus",
|
||||||
[this](std::vector<QString> arguments) -> QString {
|
[this](const std::vector<QString> &arguments) -> QString {
|
||||||
if (arguments.size() == 0)
|
if (arguments.empty())
|
||||||
{
|
{
|
||||||
return "focus action requires only one argument: the "
|
return "focus action requires only one argument: the "
|
||||||
"focus direction Use \"up\", \"above\", \"down\", "
|
"focus direction Use \"up\", \"above\", \"down\", "
|
||||||
@@ -530,20 +530,20 @@ void Split::addShortcuts()
|
|||||||
return "";
|
return "";
|
||||||
}},
|
}},
|
||||||
{"scrollToBottom",
|
{"scrollToBottom",
|
||||||
[this](std::vector<QString>) -> QString {
|
[this](const std::vector<QString> &) -> QString {
|
||||||
this->getChannelView().getScrollBar().scrollToBottom(
|
this->getChannelView().getScrollBar().scrollToBottom(
|
||||||
getSettings()->enableSmoothScrollingNewMessages.getValue());
|
getSettings()->enableSmoothScrollingNewMessages.getValue());
|
||||||
return "";
|
return "";
|
||||||
}},
|
}},
|
||||||
{"scrollToTop",
|
{"scrollToTop",
|
||||||
[this](std::vector<QString>) -> QString {
|
[this](const std::vector<QString> &) -> QString {
|
||||||
this->getChannelView().getScrollBar().scrollToTop(
|
this->getChannelView().getScrollBar().scrollToTop(
|
||||||
getSettings()->enableSmoothScrollingNewMessages.getValue());
|
getSettings()->enableSmoothScrollingNewMessages.getValue());
|
||||||
return "";
|
return "";
|
||||||
}},
|
}},
|
||||||
{"scrollPage",
|
{"scrollPage",
|
||||||
[this](std::vector<QString> arguments) -> QString {
|
[this](const std::vector<QString> &arguments) -> QString {
|
||||||
if (arguments.size() == 0)
|
if (arguments.empty())
|
||||||
{
|
{
|
||||||
qCWarning(chatterinoHotkeys)
|
qCWarning(chatterinoHotkeys)
|
||||||
<< "scrollPage hotkey called without arguments!";
|
<< "scrollPage hotkey called without arguments!";
|
||||||
@@ -567,12 +567,12 @@ void Split::addShortcuts()
|
|||||||
return "";
|
return "";
|
||||||
}},
|
}},
|
||||||
{"pickFilters",
|
{"pickFilters",
|
||||||
[this](std::vector<QString>) -> QString {
|
[this](const std::vector<QString> &) -> QString {
|
||||||
this->setFiltersDialog();
|
this->setFiltersDialog();
|
||||||
return "";
|
return "";
|
||||||
}},
|
}},
|
||||||
{"openInBrowser",
|
{"openInBrowser",
|
||||||
[this](std::vector<QString>) -> QString {
|
[this](const std::vector<QString> &) -> QString {
|
||||||
if (this->getChannel()->getType() == Channel::Type::TwitchWhispers)
|
if (this->getChannel()->getType() == Channel::Type::TwitchWhispers)
|
||||||
{
|
{
|
||||||
this->openWhispersInBrowser();
|
this->openWhispersInBrowser();
|
||||||
@@ -585,27 +585,27 @@ void Split::addShortcuts()
|
|||||||
return "";
|
return "";
|
||||||
}},
|
}},
|
||||||
{"openInStreamlink",
|
{"openInStreamlink",
|
||||||
[this](std::vector<QString>) -> QString {
|
[this](const std::vector<QString> &) -> QString {
|
||||||
this->openInStreamlink();
|
this->openInStreamlink();
|
||||||
return "";
|
return "";
|
||||||
}},
|
}},
|
||||||
{"openInCustomPlayer",
|
{"openInCustomPlayer",
|
||||||
[this](std::vector<QString>) -> QString {
|
[this](const std::vector<QString> &) -> QString {
|
||||||
this->openWithCustomScheme();
|
this->openWithCustomScheme();
|
||||||
return "";
|
return "";
|
||||||
}},
|
}},
|
||||||
{"openPlayerInBrowser",
|
{"openPlayerInBrowser",
|
||||||
[this](std::vector<QString>) -> QString {
|
[this](const std::vector<QString> &) -> QString {
|
||||||
this->openBrowserPlayer();
|
this->openBrowserPlayer();
|
||||||
return "";
|
return "";
|
||||||
}},
|
}},
|
||||||
{"openModView",
|
{"openModView",
|
||||||
[this](std::vector<QString>) -> QString {
|
[this](const std::vector<QString> &) -> QString {
|
||||||
this->openModViewInBrowser();
|
this->openModViewInBrowser();
|
||||||
return "";
|
return "";
|
||||||
}},
|
}},
|
||||||
{"createClip",
|
{"createClip",
|
||||||
[this](std::vector<QString>) -> QString {
|
[this](const std::vector<QString> &) -> QString {
|
||||||
// Alt+X: create clip LUL
|
// Alt+X: create clip LUL
|
||||||
if (const auto type = this->getChannel()->getType();
|
if (const auto type = this->getChannel()->getType();
|
||||||
type != Channel::Type::Twitch &&
|
type != Channel::Type::Twitch &&
|
||||||
@@ -621,10 +621,10 @@ void Split::addShortcuts()
|
|||||||
return "";
|
return "";
|
||||||
}},
|
}},
|
||||||
{"reloadEmotes",
|
{"reloadEmotes",
|
||||||
[this](std::vector<QString> arguments) -> QString {
|
[this](const std::vector<QString> &arguments) -> QString {
|
||||||
auto reloadChannel = true;
|
auto reloadChannel = true;
|
||||||
auto reloadSubscriber = true;
|
auto reloadSubscriber = true;
|
||||||
if (arguments.size() != 0)
|
if (!arguments.empty())
|
||||||
{
|
{
|
||||||
auto arg = arguments.at(0);
|
auto arg = arguments.at(0);
|
||||||
if (arg == "channel")
|
if (arg == "channel")
|
||||||
@@ -648,7 +648,7 @@ void Split::addShortcuts()
|
|||||||
return "";
|
return "";
|
||||||
}},
|
}},
|
||||||
{"setModerationMode",
|
{"setModerationMode",
|
||||||
[this](std::vector<QString> arguments) -> QString {
|
[this](const std::vector<QString> &arguments) -> QString {
|
||||||
if (!this->getChannel()->isTwitchChannel())
|
if (!this->getChannel()->isTwitchChannel())
|
||||||
{
|
{
|
||||||
return "Cannot set moderation mode in a non-Twitch "
|
return "Cannot set moderation mode in a non-Twitch "
|
||||||
@@ -658,7 +658,7 @@ void Split::addShortcuts()
|
|||||||
// 0 is off
|
// 0 is off
|
||||||
// 1 is on
|
// 1 is on
|
||||||
// 2 is toggle
|
// 2 is toggle
|
||||||
if (arguments.size() != 0)
|
if (!arguments.empty())
|
||||||
{
|
{
|
||||||
auto arg = arguments.at(0);
|
auto arg = arguments.at(0);
|
||||||
if (arg == "off")
|
if (arg == "off")
|
||||||
@@ -669,45 +669,41 @@ void Split::addShortcuts()
|
|||||||
{
|
{
|
||||||
mode = 1;
|
mode = 1;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
mode = 2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode == 0)
|
switch (mode)
|
||||||
{
|
{
|
||||||
this->setModerationMode(false);
|
case 0:
|
||||||
}
|
this->setModerationMode(false);
|
||||||
else if (mode == 1)
|
break;
|
||||||
{
|
case 1:
|
||||||
this->setModerationMode(true);
|
this->setModerationMode(true);
|
||||||
}
|
break;
|
||||||
else
|
default:
|
||||||
{
|
this->setModerationMode(!this->getModerationMode());
|
||||||
this->setModerationMode(!this->getModerationMode());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
}},
|
}},
|
||||||
{"openViewerList",
|
{"openViewerList",
|
||||||
[this](std::vector<QString>) -> QString {
|
[this](const std::vector<QString> &) -> QString {
|
||||||
this->showChatterList();
|
this->showChatterList();
|
||||||
return "";
|
return "";
|
||||||
}},
|
}},
|
||||||
{"clearMessages",
|
{"clearMessages",
|
||||||
[this](std::vector<QString>) -> QString {
|
[this](const std::vector<QString> &) -> QString {
|
||||||
this->clear();
|
this->clear();
|
||||||
return "";
|
return "";
|
||||||
}},
|
}},
|
||||||
{"runCommand",
|
{"runCommand",
|
||||||
[this](std::vector<QString> arguments) -> QString {
|
[this](const std::vector<QString> &arguments) -> QString {
|
||||||
if (arguments.empty())
|
if (arguments.empty())
|
||||||
{
|
{
|
||||||
qCWarning(chatterinoHotkeys)
|
qCWarning(chatterinoHotkeys)
|
||||||
<< "runCommand hotkey called without arguments!";
|
<< "runCommand hotkey called without arguments!";
|
||||||
return "runCommand hotkey called without arguments!";
|
return "runCommand hotkey called without arguments!";
|
||||||
}
|
}
|
||||||
QString requestedText = arguments.at(0).replace('\n', ' ');
|
QString requestedText = QString(arguments[0]).replace('\n', ' ');
|
||||||
|
|
||||||
QString inputText = this->getInput().getInputText();
|
QString inputText = this->getInput().getInputText();
|
||||||
QString message = getApp()->getCommands()->execCustomCommand(
|
QString message = getApp()->getCommands()->execCustomCommand(
|
||||||
@@ -723,7 +719,7 @@ void Split::addShortcuts()
|
|||||||
return "";
|
return "";
|
||||||
}},
|
}},
|
||||||
{"setChannelNotification",
|
{"setChannelNotification",
|
||||||
[this](std::vector<QString> arguments) -> QString {
|
[this](const std::vector<QString> &arguments) -> QString {
|
||||||
if (!this->getChannel()->isTwitchChannel())
|
if (!this->getChannel()->isTwitchChannel())
|
||||||
{
|
{
|
||||||
return "Cannot set channel notifications for a non-Twitch "
|
return "Cannot set channel notifications for a non-Twitch "
|
||||||
@@ -733,7 +729,7 @@ void Split::addShortcuts()
|
|||||||
// 0 is off
|
// 0 is off
|
||||||
// 1 is on
|
// 1 is on
|
||||||
// 2 is toggle
|
// 2 is toggle
|
||||||
if (arguments.size() != 0)
|
if (!arguments.empty())
|
||||||
{
|
{
|
||||||
auto arg = arguments.at(0);
|
auto arg = arguments.at(0);
|
||||||
if (arg == "off")
|
if (arg == "off")
|
||||||
@@ -744,26 +740,23 @@ void Split::addShortcuts()
|
|||||||
{
|
{
|
||||||
mode = 1;
|
mode = 1;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
mode = 2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode == 0)
|
auto *notifications = getApp()->getNotifications();
|
||||||
|
const QString channelName = this->getChannel()->getName();
|
||||||
|
switch (mode)
|
||||||
{
|
{
|
||||||
getApp()->getNotifications()->removeChannelNotification(
|
case 0:
|
||||||
this->getChannel()->getName(), Platform::Twitch);
|
notifications->removeChannelNotification(channelName,
|
||||||
}
|
Platform::Twitch);
|
||||||
else if (mode == 1)
|
break;
|
||||||
{
|
case 1:
|
||||||
getApp()->getNotifications()->addChannelNotification(
|
notifications->addChannelNotification(channelName,
|
||||||
this->getChannel()->getName(), Platform::Twitch);
|
Platform::Twitch);
|
||||||
}
|
break;
|
||||||
else
|
default:
|
||||||
{
|
notifications->updateChannelNotification(channelName,
|
||||||
getApp()->getNotifications()->updateChannelNotification(
|
Platform::Twitch);
|
||||||
this->getChannel()->getName(), Platform::Twitch);
|
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}},
|
}},
|
||||||
@@ -809,7 +802,7 @@ void Split::addShortcuts()
|
|||||||
return {};
|
return {};
|
||||||
}},
|
}},
|
||||||
{"setHighlightSounds",
|
{"setHighlightSounds",
|
||||||
[this](std::vector<QString> arguments) -> QString {
|
[this](const std::vector<QString> &arguments) -> QString {
|
||||||
if (!this->getChannel()->isTwitchChannel())
|
if (!this->getChannel()->isTwitchChannel())
|
||||||
{
|
{
|
||||||
return "Cannot set highlight sounds in a non-Twitch "
|
return "Cannot set highlight sounds in a non-Twitch "
|
||||||
@@ -934,7 +927,7 @@ void Split::openChannelInBrowserPlayer(ChannelPtr channel)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Split::openChannelInStreamlink(QString channelName)
|
void Split::openChannelInStreamlink(const QString channelName)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -1518,7 +1511,7 @@ void Split::showChatterList()
|
|||||||
|
|
||||||
HotkeyController::HotkeyMap actions{
|
HotkeyController::HotkeyMap actions{
|
||||||
{"delete",
|
{"delete",
|
||||||
[chatterDock](std::vector<QString>) -> QString {
|
[chatterDock](const std::vector<QString> &) -> QString {
|
||||||
chatterDock->close();
|
chatterDock->close();
|
||||||
return "";
|
return "";
|
||||||
}},
|
}},
|
||||||
@@ -1527,7 +1520,7 @@ void Split::showChatterList()
|
|||||||
{"scrollPage", nullptr},
|
{"scrollPage", nullptr},
|
||||||
{"openTab", nullptr},
|
{"openTab", nullptr},
|
||||||
{"search",
|
{"search",
|
||||||
[searchBar](std::vector<QString>) -> QString {
|
[searchBar](const std::vector<QString> &) -> QString {
|
||||||
searchBar->setFocus();
|
searchBar->setFocus();
|
||||||
searchBar->selectAll();
|
searchBar->selectAll();
|
||||||
return "";
|
return "";
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ private:
|
|||||||
/**
|
/**
|
||||||
* @brief Opens Twitch channel stream in streamlink app (if stream is live and streamlink is installed)
|
* @brief Opens Twitch channel stream in streamlink app (if stream is live and streamlink is installed)
|
||||||
*/
|
*/
|
||||||
void openChannelInStreamlink(QString channelName);
|
void openChannelInStreamlink(const QString channelName);
|
||||||
/**
|
/**
|
||||||
* @brief Opens Twitch channel chat in a new Chatterino tab
|
* @brief Opens Twitch channel chat in a new Chatterino tab
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -541,59 +541,64 @@ std::unique_ptr<QMenu> SplitHeader::createMainMenu()
|
|||||||
h->getDisplaySequence(HotkeyCategory::Split,
|
h->getDisplaySequence(HotkeyCategory::Split,
|
||||||
"openSubscriptionPage"));
|
"openSubscriptionPage"));
|
||||||
|
|
||||||
auto *action = new QAction(this);
|
|
||||||
action->setText("Notify when live");
|
|
||||||
action->setCheckable(true);
|
|
||||||
|
|
||||||
auto notifySeq = h->getDisplaySequence(
|
|
||||||
HotkeyCategory::Split, "setChannelNotification", {{"toggle"}});
|
|
||||||
if (notifySeq.isEmpty())
|
|
||||||
{
|
{
|
||||||
notifySeq = h->getDisplaySequence(HotkeyCategory::Split,
|
auto *action = new QAction(this);
|
||||||
"setChannelNotification",
|
action->setText("Notify when live");
|
||||||
{std::vector<QString>()});
|
action->setCheckable(true);
|
||||||
// this makes a full std::optional<> with an empty vector inside
|
|
||||||
|
auto notifySeq = h->getDisplaySequence(
|
||||||
|
HotkeyCategory::Split, "setChannelNotification", {{"toggle"}});
|
||||||
|
if (notifySeq.isEmpty())
|
||||||
|
{
|
||||||
|
notifySeq = h->getDisplaySequence(HotkeyCategory::Split,
|
||||||
|
"setChannelNotification",
|
||||||
|
{std::vector<QString>()});
|
||||||
|
// this makes a full std::optional<> with an empty vector inside
|
||||||
|
}
|
||||||
|
action->setShortcut(notifySeq);
|
||||||
|
|
||||||
|
QObject::connect(
|
||||||
|
moreMenu, &QMenu::aboutToShow, this, [action, this]() {
|
||||||
|
action->setChecked(
|
||||||
|
getApp()->getNotifications()->isChannelNotified(
|
||||||
|
this->split_->getChannel()->getName(),
|
||||||
|
Platform::Twitch));
|
||||||
|
});
|
||||||
|
QObject::connect(action, &QAction::triggered, this, [this]() {
|
||||||
|
getApp()->getNotifications()->updateChannelNotification(
|
||||||
|
this->split_->getChannel()->getName(), Platform::Twitch);
|
||||||
|
});
|
||||||
|
|
||||||
|
moreMenu->addAction(action);
|
||||||
}
|
}
|
||||||
action->setShortcut(notifySeq);
|
|
||||||
|
|
||||||
QObject::connect(moreMenu, &QMenu::aboutToShow, this, [action, this]() {
|
|
||||||
action->setChecked(getApp()->getNotifications()->isChannelNotified(
|
|
||||||
this->split_->getChannel()->getName(), Platform::Twitch));
|
|
||||||
});
|
|
||||||
QObject::connect(action, &QAction::triggered, this, [this]() {
|
|
||||||
getApp()->getNotifications()->updateChannelNotification(
|
|
||||||
this->split_->getChannel()->getName(), Platform::Twitch);
|
|
||||||
});
|
|
||||||
|
|
||||||
moreMenu->addAction(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (twitchChannel)
|
|
||||||
{
|
|
||||||
auto *action = new QAction(this);
|
|
||||||
action->setText("Mute highlight sounds");
|
|
||||||
action->setCheckable(true);
|
|
||||||
|
|
||||||
auto notifySeq = h->getDisplaySequence(
|
|
||||||
HotkeyCategory::Split, "setHighlightSounds", {{"toggle"}});
|
|
||||||
if (notifySeq.isEmpty())
|
|
||||||
{
|
{
|
||||||
notifySeq = h->getDisplaySequence(HotkeyCategory::Split,
|
auto *action = new QAction(this);
|
||||||
"setHighlightSounds",
|
action->setText("Mute highlight sounds");
|
||||||
{std::vector<QString>()});
|
action->setCheckable(true);
|
||||||
|
|
||||||
|
auto notifySeq = h->getDisplaySequence(
|
||||||
|
HotkeyCategory::Split, "setHighlightSounds", {{"toggle"}});
|
||||||
|
if (notifySeq.isEmpty())
|
||||||
|
{
|
||||||
|
notifySeq = h->getDisplaySequence(HotkeyCategory::Split,
|
||||||
|
"setHighlightSounds",
|
||||||
|
{std::vector<QString>()});
|
||||||
|
}
|
||||||
|
action->setShortcut(notifySeq);
|
||||||
|
|
||||||
|
QObject::connect(
|
||||||
|
moreMenu, &QMenu::aboutToShow, this, [action, this]() {
|
||||||
|
action->setChecked(getSettings()->isMutedChannel(
|
||||||
|
this->split_->getChannel()->getName()));
|
||||||
|
});
|
||||||
|
QObject::connect(action, &QAction::triggered, this, [this]() {
|
||||||
|
getSettings()->toggleMutedChannel(
|
||||||
|
this->split_->getChannel()->getName());
|
||||||
|
});
|
||||||
|
|
||||||
|
moreMenu->addAction(action);
|
||||||
}
|
}
|
||||||
action->setShortcut(notifySeq);
|
|
||||||
|
|
||||||
QObject::connect(moreMenu, &QMenu::aboutToShow, this, [action, this]() {
|
|
||||||
action->setChecked(getSettings()->isMutedChannel(
|
|
||||||
this->split_->getChannel()->getName()));
|
|
||||||
});
|
|
||||||
QObject::connect(action, &QAction::triggered, this, [this]() {
|
|
||||||
getSettings()->toggleMutedChannel(
|
|
||||||
this->split_->getChannel()->getName());
|
|
||||||
});
|
|
||||||
|
|
||||||
moreMenu->addAction(action);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
moreMenu->addSeparator();
|
moreMenu->addSeparator();
|
||||||
|
|||||||
Reference in New Issue
Block a user