From a5a15d32f4f7407687177756b2361e4274e07b73 Mon Sep 17 00:00:00 2001
From: Friedemann Kleint <Friedemann.Kleint@qt.io>
Date: Wed, 19 Jun 2019 13:00:11 +0200
Subject: [PATCH 2/3] WIP: Extract QGuiAction(Group) from QAction(Group) into
 QtGui

Simply moving QAction to QtGui was not deemed possible since it
operates on a set of controls of some kind. The approach to extract a
base class was taken instead, named QGuiAction following the
QGuiApplication scheme. QAction remains in widgets, but changes base
class.

For QActionGroup, the functions addAction(text/icon), which create an
action, cannot be implemented in QtGui, hence a base class is needed,
too (unless they are deprecated and removed).

- Extract base classes providing functionality not based on
  QtWidgets, using virtuals in QGuiActionPrivate to
  provide customization points

- Change QActionEvent to take QGuiAction, removing
  the need to forward declare QAction in QtGui

- Notes
   * Introduces some ugly casts to widgets

TODO : split tests

Task-number: QTBUG-69478
Change-Id: Ic490a5e3470939ee8af612d46ff41d4c8c91fbdf
---
 src/gui/kernel/kernel.pri                     |    6 +
 src/gui/kernel/qevent.cpp                     |   10 +-
 src/gui/kernel/qevent.h                       |   10 +-
 src/gui/kernel/qguiaction.cpp                 | 1214 +++++++++++++++++
 src/gui/kernel/qguiaction.h                   |  199 +++
 src/gui/kernel/qguiaction_p.h                 |  127 ++
 src/gui/kernel/qguiactiongroup.cpp            |  349 +++++
 src/gui/kernel/qguiactiongroup.h              |  107 ++
 src/gui/kernel/qguiactiongroup_p.h            |   91 ++
 src/widgets/graphicsview/qgraphicswidget.h    |    1 +
 src/widgets/kernel/qaction.cpp                | 1064 +--------------
 src/widgets/kernel/qaction.h                  |  124 +-
 src/widgets/kernel/qaction_p.h                |   47 +-
 src/widgets/kernel/qactiongroup.cpp           |  304 +----
 src/widgets/kernel/qactiongroup.h             |   37 +-
 src/widgets/styles/qstyleoption.cpp           |    2 +-
 src/widgets/widgets/qlineedit_p.cpp           |    6 +-
 src/widgets/widgets/qlineedit_p.h             |    4 +-
 src/widgets/widgets/qmenu.cpp                 |   12 +-
 src/widgets/widgets/qmenubar.cpp              |   17 +-
 src/widgets/widgets/qtoolbar.cpp              |    2 +-
 src/widgets/widgets/qtoolbarlayout.cpp        |    2 +-
 src/widgets/widgets/qtoolbarlayout_p.h        |    2 +-
 src/widgets/widgets/qtoolbutton.cpp           |    2 +-
 .../widgets/kernel/qaction/tst_qaction.cpp    |    2 +-
 .../kernel/qactiongroup/tst_qactiongroup.cpp  |    2 +-
 26 files changed, 2200 insertions(+), 1543 deletions(-)
 create mode 100644 src/gui/kernel/qguiaction.cpp
 create mode 100644 src/gui/kernel/qguiaction.h
 create mode 100644 src/gui/kernel/qguiaction_p.h
 create mode 100644 src/gui/kernel/qguiactiongroup.cpp
 create mode 100644 src/gui/kernel/qguiactiongroup.h
 create mode 100644 src/gui/kernel/qguiactiongroup_p.h

diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri
index 9c80f1e2cc..d70b1ea13b 100644
--- a/src/gui/kernel/kernel.pri
+++ b/src/gui/kernel/kernel.pri
@@ -33,6 +33,10 @@ HEADERS += \
         kernel/qplatformnativeinterface.h \
         kernel/qplatformmenu.h \
         kernel/qsurfaceformat.h \
+        kernel/qguiaction.h \
+        kernel/qguiaction_p.h \
+        kernel/qguiactiongroup.h \
+        kernel/qguiactiongroup_p.h \
         kernel/qguiapplication.h \
         kernel/qguiapplication_p.h \
         kernel/qwindow_p.h \
@@ -98,6 +102,8 @@ SOURCES += \
         kernel/qplatformnativeinterface.cpp \
         kernel/qsessionmanager.cpp \
         kernel/qsurfaceformat.cpp \
+        kernel/qguiactiongroup.cpp \
+        kernel/qguiaction.cpp \
         kernel/qguiapplication.cpp \
         kernel/qwindow.cpp \
         kernel/qoffscreensurface.cpp \
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index e1d685b1b0..d116ec0855 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -3470,18 +3470,18 @@ QWhatsThisClickedEvent::~QWhatsThisClickedEvent()
 /*!
     \class QActionEvent
     \brief The QActionEvent class provides an event that is generated
-    when a QAction is added, removed, or changed.
+    when a QGuiAction is added, removed, or changed.
 
     \ingroup events
     \inmodule QtGui
 
-    Actions can be added to widgets using QWidget::addAction(). This
-    generates an \l ActionAdded event, which you can handle to provide
+    Actions can be added to controls, for example by using QWidget::addAction().
+    This generates an \l ActionAdded event, which you can handle to provide
     custom behavior. For example, QToolBar reimplements
     QWidget::actionEvent() to create \l{QToolButton}s for the
     actions.
 
-    \sa QAction, QWidget::addAction(), QWidget::removeAction(), QWidget::actions()
+    \sa QGuiAction, QWidget::addAction(), QWidget::removeAction(), QWidget::actions()
 */
 
 /*!
@@ -3492,7 +3492,7 @@ QWhatsThisClickedEvent::~QWhatsThisClickedEvent()
     type is ActionAdded, the action is to be inserted before the
     action \a before. If \a before is 0, the action is appended.
 */
-QActionEvent::QActionEvent(int type, QAction *action, QAction *before)
+QActionEvent::QActionEvent(int type, QGuiAction *action, QGuiAction *before)
     : QEvent(static_cast<QEvent::Type>(type)), act(action), bef(before)
 {}
 
diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h
index eb0a6208a9..bd0632ef3f 100644
--- a/src/gui/kernel/qevent.h
+++ b/src/gui/kernel/qevent.h
@@ -59,7 +59,7 @@
 QT_BEGIN_NAMESPACE
 
 
-class QAction;
+class QGuiAction;
 #ifndef QT_NO_GESTURES
 class QGesture;
 #endif
@@ -727,13 +727,13 @@ private:
 #ifndef QT_NO_ACTION
 class Q_GUI_EXPORT QActionEvent : public QEvent
 {
-    QAction *act, *bef;
+    QGuiAction *act, *bef;
 public:
-    QActionEvent(int type, QAction *action, QAction *before = nullptr);
+    QActionEvent(int type, QGuiAction *action, QGuiAction *before = nullptr);
     ~QActionEvent();
 
-    inline QAction *action() const { return act; }
-    inline QAction *before() const { return bef; }
+    inline QGuiAction *action() const { return act; }
+    inline QGuiAction *before() const { return bef; }
 };
 #endif
 
diff --git a/src/gui/kernel/qguiaction.cpp b/src/gui/kernel/qguiaction.cpp
new file mode 100644
index 0000000000..43158a58d5
--- /dev/null
+++ b/src/gui/kernel/qguiaction.cpp
@@ -0,0 +1,1214 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWidgets module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qguiaction.h"
+#include "qguiactiongroup.h"
+
+#ifndef QT_NO_ACTION
+#include "qguiaction_p.h"
+#include "qguiapplication.h"
+#include "qevent.h"
+#include "qlist.h"
+#include "qstylehints.h"
+#include <private/qshortcutmap_p.h>
+#include <private/qguiapplication_p.h>
+#include <private/qdebug_p.h>
+
+#define QAPP_CHECK(functionName) \
+    if (Q_UNLIKELY(!QCoreApplication::instance())) { \
+        qWarning("QAction: Initialize Q(Gui)Application before calling '" functionName "'."); \
+        return; \
+    }
+
+QT_BEGIN_NAMESPACE
+
+/*
+  internal: guesses a descriptive text from a text suited for a menu entry
+ */
+static QString qt_strippedText(QString s)
+{
+    s.remove(QLatin1String("..."));
+    for (int i = 0; i < s.size(); ++i) {
+        if (s.at(i) == QLatin1Char('&'))
+            s.remove(i, 1);
+    }
+    return s.trimmed();
+}
+
+QGuiActionPrivate::QGuiActionPrivate() :
+#if QT_CONFIG(shortcut)
+    autorepeat(1),
+#endif
+    enabled(1), forceDisabled(0), visible(1), forceInvisible(0), checkable(0),
+    checked(0), separator(0), fontSet(false),
+    iconVisibleInMenu(-1), shortcutVisibleInContextMenu(-1)
+{
+}
+
+static bool dummy(QObject *, Qt::ShortcutContext) { return false; } // only for GUI testing.
+
+QShortcutMap::ContextMatcher QGuiActionPrivate::contextMatcher() const
+{
+    return dummy;
+}
+
+QGuiActionPrivate::~QGuiActionPrivate() = default;
+
+void QGuiActionPrivate::sendDataChanged()
+{
+    Q_Q(QGuiAction);
+    QActionEvent e(QEvent::ActionChanged, q);
+    QCoreApplication::sendEvent(q, &e);
+
+    emit q->changed();
+}
+
+#if QT_CONFIG(shortcut)
+void QGuiActionPrivate::redoGrab(QShortcutMap &map)
+{
+    Q_Q(QGuiAction);
+    if (shortcutId)
+        map.removeShortcut(shortcutId, q);
+    if (shortcut.isEmpty())
+        return;
+    shortcutId = map.addShortcut(q, shortcut, shortcutContext, contextMatcher());
+    if (!enabled)
+        map.setShortcutEnabled(false, shortcutId, q);
+    if (!autorepeat)
+        map.setShortcutAutoRepeat(false, shortcutId, q);
+}
+
+void QGuiActionPrivate::redoGrabAlternate(QShortcutMap &map)
+{
+    Q_Q(QGuiAction);
+    for(int i = 0; i < alternateShortcutIds.count(); ++i) {
+        if (const int id = alternateShortcutIds.at(i))
+            map.removeShortcut(id, q);
+    }
+    alternateShortcutIds.clear();
+    if (alternateShortcuts.isEmpty())
+        return;
+    for(int i = 0; i < alternateShortcuts.count(); ++i) {
+        const QKeySequence& alternate = alternateShortcuts.at(i);
+        if (!alternate.isEmpty())
+            alternateShortcutIds.append(map.addShortcut(q, alternate, shortcutContext, contextMatcher()));
+        else
+            alternateShortcutIds.append(0);
+    }
+    if (!enabled) {
+        for(int i = 0; i < alternateShortcutIds.count(); ++i) {
+            const int id = alternateShortcutIds.at(i);
+            map.setShortcutEnabled(false, id, q);
+        }
+    }
+    if (!autorepeat) {
+        for(int i = 0; i < alternateShortcutIds.count(); ++i) {
+            const int id = alternateShortcutIds.at(i);
+            map.setShortcutAutoRepeat(false, id, q);
+        }
+    }
+}
+
+void QGuiActionPrivate::setShortcutEnabled(bool enable, QShortcutMap &map)
+{
+    Q_Q(QGuiAction);
+    if (shortcutId)
+        map.setShortcutEnabled(enable, shortcutId, q);
+    for(int i = 0; i < alternateShortcutIds.count(); ++i) {
+        if (const int id = alternateShortcutIds.at(i))
+            map.setShortcutEnabled(enable, id, q);
+    }
+}
+#endif // QT_NO_SHORTCUT
+
+
+/*!
+    \class QGuiAction
+    \brief QGuiAction is the base class for actions, an abstract user interface
+    action that can be inserted into widgets.
+    \since 6.0
+
+    \ingroup TDB
+    \inmodule QtGui
+
+    In applications many common commands can be invoked via menus,
+    toolbar buttons, and keyboard shortcuts. Since the user expects
+    each command to be performed in the same way, regardless of the
+    user interface used, it is useful to represent each command as
+    an \e action.
+
+    Actions can be added to menus and toolbars, and will
+    automatically keep them in sync. For example, in a word processor,
+    if the user presses a Bold toolbar button, the Bold menu item
+    will automatically be checked.
+
+    Actions can be created as independent objects, but they may
+    also be created during the construction of menus; the QMenu class
+    contains convenience functions for creating actions suitable for
+    use as menu items.
+
+    A QGuiAction may contain an icon, menu text, a shortcut, status text,
+    "What's This?" text, and a tooltip. Most of these can be set in
+    the constructor. They can also be set independently with
+    setIcon(), setText(), setIconText(), setShortcut(),
+    setStatusTip(), setWhatsThis(), and setToolTip(). For menu items,
+    it is possible to set an individual font with setFont().
+
+    We recommend that actions are created as children of the window
+    they are used in. In most cases actions will be children of
+    the application's main window.
+
+    \sa QMenu, QToolBar, {Application Example}
+*/
+
+/*!
+    \fn void QGuiAction::trigger()
+
+    This is a convenience slot that calls activate(Trigger).
+*/
+
+/*!
+    \fn void QGuiAction::hover()
+
+    This is a convenience slot that calls activate(Hover).
+*/
+
+/*!
+    \enum QGuiAction::MenuRole
+
+    This enum describes how an action should be moved into the application menu on \macos.
+
+    \value NoRole This action should not be put into the application menu
+    \value TextHeuristicRole This action should be put in the application menu based on the action's text
+           as described in the QMenuBar documentation.
+    \value ApplicationSpecificRole This action should be put in the application menu with an application specific role
+    \value AboutQtRole This action handles the "About Qt" menu item.
+    \value AboutRole This action should be placed where the "About" menu item is in the application menu. The text of
+           the menu item will be set to "About <application name>". The application name is fetched from the
+           \c{Info.plist} file in the application's bundle (See \l{Qt for macOS - Deployment}).
+    \value PreferencesRole This action should be placed where the  "Preferences..." menu item is in the application menu.
+    \value QuitRole This action should be placed where the Quit menu item is in the application menu.
+
+    Setting this value only has effect on items that are in the immediate menus
+    of the menubar, not the submenus of those menus. For example, if you have
+    File menu in your menubar and the File menu has a submenu, setting the
+    MenuRole for the actions in that submenu have no effect. They will never be moved.
+*/
+
+/*!
+    Constructs an action with \a parent. If \a parent is an action
+    group the action will be automatically inserted into the group.
+
+    \note The \a parent argument is optional since Qt 5.7.
+*/
+QGuiAction::QGuiAction(QObject* parent)
+    : QGuiAction(*new QGuiActionPrivate, parent)
+{
+}
+
+/*!
+    Constructs an action with some \a text and \a parent. If \a
+    parent is an action group the action will be automatically
+    inserted into the group.
+
+    The action uses a stripped version of \a text (e.g. "\&Menu
+    Option..." becomes "Menu Option") as descriptive text for
+    tool buttons. You can override this by setting a specific
+    description with setText(). The same text will be used for
+    tooltips unless you specify a different text using
+    setToolTip().
+
+*/
+QGuiAction::QGuiAction(const QString &text, QObject* parent)
+    : QGuiAction(parent)
+{
+    Q_D(QGuiAction);
+    d->text = text;
+}
+
+/*!
+    Constructs an action with an \a icon and some \a text and \a
+    parent. If \a parent is an action group the action will be
+    automatically inserted into the group.
+
+    The action uses a stripped version of \a text (e.g. "\&Menu
+    Option..." becomes "Menu Option") as descriptive text for
+    tool buttons. You can override this by setting a specific
+    description with setText(). The same text will be used for
+    tooltips unless you specify a different text using
+    setToolTip().
+*/
+QGuiAction::QGuiAction(const QIcon &icon, const QString &text, QObject* parent)
+    : QGuiAction(text, parent)
+{
+    Q_D(QGuiAction);
+    d->icon = icon;
+}
+
+/*!
+    \internal
+*/
+QGuiAction::QGuiAction(QGuiActionPrivate &dd, QObject *parent)
+    : QObject(dd, parent)
+{
+    Q_D(QGuiAction);
+    d->group = qobject_cast<QGuiActionGroup *>(parent);
+    if (d->group)
+        d->group->addAction(this);
+}
+
+#if QT_CONFIG(shortcut)
+/*!
+    \property QGuiAction::shortcut
+    \brief the action's primary shortcut key
+
+    Valid keycodes for this property can be found in \l Qt::Key and
+    \l Qt::Modifier. There is no default shortcut key.
+*/
+void QGuiAction::setShortcut(const QKeySequence &shortcut)
+{
+    QAPP_CHECK("setShortcut");
+
+    Q_D(QGuiAction);
+    if (d->shortcut == shortcut)
+        return;
+
+    d->shortcut = shortcut;
+    d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap);
+    d->sendDataChanged();
+}
+
+/*!
+    Sets \a shortcuts as the list of shortcuts that trigger the
+    action. The first element of the list is the primary shortcut.
+
+    \sa shortcut
+*/
+void QGuiAction::setShortcuts(const QList<QKeySequence> &shortcuts)
+{
+    Q_D(QGuiAction);
+
+    QList <QKeySequence> listCopy = shortcuts;
+
+    QKeySequence primary;
+    if (!listCopy.isEmpty())
+        primary = listCopy.takeFirst();
+
+    if (d->shortcut == primary && d->alternateShortcuts == listCopy)
+        return;
+
+    QAPP_CHECK("setShortcuts");
+
+    d->shortcut = primary;
+    d->alternateShortcuts = listCopy;
+    d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap);
+    d->redoGrabAlternate(QGuiApplicationPrivate::instance()->shortcutMap);
+    d->sendDataChanged();
+}
+
+/*!
+    Sets a platform dependent list of shortcuts based on the \a key.
+    The result of calling this function will depend on the currently running platform.
+    Note that more than one shortcut can assigned by this action.
+    If only the primary shortcut is required, use setShortcut instead.
+
+    \sa QKeySequence::keyBindings()
+*/
+void QGuiAction::setShortcuts(QKeySequence::StandardKey key)
+{
+    QList <QKeySequence> list = QKeySequence::keyBindings(key);
+    setShortcuts(list);
+}
+
+/*!
+    Returns the primary shortcut.
+
+    \sa setShortcuts()
+*/
+QKeySequence QGuiAction::shortcut() const
+{
+    Q_D(const QGuiAction);
+    return d->shortcut;
+}
+
+/*!
+    Returns the list of shortcuts, with the primary shortcut as
+    the first element of the list.
+
+    \sa setShortcuts()
+*/
+QList<QKeySequence> QGuiAction::shortcuts() const
+{
+    Q_D(const QGuiAction);
+    QList <QKeySequence> shortcuts;
+    if (!d->shortcut.isEmpty())
+        shortcuts << d->shortcut;
+    if (!d->alternateShortcuts.isEmpty())
+        shortcuts << d->alternateShortcuts;
+    return shortcuts;
+}
+
+/*!
+    \property QGuiAction::shortcutContext
+    \brief the context for the action's shortcut
+
+    Valid values for this property can be found in \l Qt::ShortcutContext.
+    The default value is Qt::WindowShortcut.
+*/
+void QGuiAction::setShortcutContext(Qt::ShortcutContext context)
+{
+    Q_D(QGuiAction);
+    if (d->shortcutContext == context)
+        return;
+    QAPP_CHECK("setShortcutContext");
+    d->shortcutContext = context;
+    d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap);
+    d->redoGrabAlternate(QGuiApplicationPrivate::instance()->shortcutMap);
+    d->sendDataChanged();
+}
+
+Qt::ShortcutContext QGuiAction::shortcutContext() const
+{
+    Q_D(const QGuiAction);
+    return d->shortcutContext;
+}
+
+/*!
+    \property QGuiAction::autoRepeat
+    \brief whether the action can auto repeat
+
+    If true, the action will auto repeat when the keyboard shortcut
+    combination is held down, provided that keyboard auto repeat is
+    enabled on the system.
+    The default value is true.
+*/
+void QGuiAction::setAutoRepeat(bool on)
+{
+    Q_D(QGuiAction);
+    if (d->autorepeat == on)
+        return;
+    QAPP_CHECK("setAutoRepeat");
+    d->autorepeat = on;
+    d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap);
+    d->redoGrabAlternate(QGuiApplicationPrivate::instance()->shortcutMap);
+    d->sendDataChanged();
+}
+
+bool QGuiAction::autoRepeat() const
+{
+    Q_D(const QGuiAction);
+    return d->autorepeat;
+}
+#endif // QT_NO_SHORTCUT
+
+/*!
+    \property QGuiAction::font
+    \brief the action's font
+
+    The font property is used to render the text set on the
+    QAction. The font will can be considered a hint as it will not be
+    consulted in all cases based upon application and style.
+
+    By default, this property contains the application's default font.
+
+    \sa setText()
+*/
+void QGuiAction::setFont(const QFont &font)
+{
+    Q_D(QGuiAction);
+    if (d->font == font)
+        return;
+
+    d->fontSet = true;
+    d->font = font;
+    d->sendDataChanged();
+}
+
+QFont QGuiAction::font() const
+{
+    Q_D(const QGuiAction);
+    return d->font;
+}
+
+
+/*!
+    Destroys the object and frees allocated resources.
+*/
+QGuiAction::~QGuiAction()
+{
+    Q_D(QGuiAction);
+    if (d->group)
+        d->group->removeAction(this);
+#if QT_CONFIG(shortcut)
+    if (d->shortcutId && qApp) {
+        QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(d->shortcutId, this);
+        for (int id : qAsConst(d->alternateShortcutIds))
+            QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(id, this);
+    }
+#endif
+}
+
+/*!
+  Sets this action group to \a group. The action will be automatically
+  added to the group's list of actions.
+
+  Actions within the group will be mutually exclusive.
+
+  \sa QGuiActionGroup, guiActionGroup()
+*/
+void QGuiAction::setActionGroup(QGuiActionGroup *group)
+{
+    Q_D(QGuiAction);
+    if(group == d->group)
+        return;
+
+    if(d->group)
+        d->group->removeAction(this);
+    d->group = group;
+    if(group)
+        group->addAction(this);
+    d->sendDataChanged();
+}
+
+/*!
+  Returns the action group for this action. If no action group manages
+  this action, then \nullptr will be returned.
+
+  \sa QGuiActionGroup, setActionGroup()
+*/
+QGuiActionGroup *QGuiAction::guiActionGroup() const
+{
+    Q_D(const QGuiAction);
+    return d->group;
+}
+
+
+/*!
+    \property QGuiAction::icon
+    \brief the action's icon
+
+    In toolbars, the icon is used as the tool button icon; in menus,
+    it is displayed to the left of the menu text. There is no default
+    icon.
+
+    If a null icon (QIcon::isNull()) is passed into this function,
+    the icon of the action is cleared.
+*/
+void QGuiAction::setIcon(const QIcon &icon)
+{
+    Q_D(QGuiAction);
+    d->icon = icon;
+    d->sendDataChanged();
+}
+
+QIcon QGuiAction::icon() const
+{
+    Q_D(const QGuiAction);
+    return d->icon;
+}
+
+/*!
+  If \a b is true then this action will be considered a separator.
+
+  How a separator is represented depends on the widget it is inserted
+  into. Under most circumstances the text, submenu, and icon will be
+  ignored for separator actions.
+
+  \sa isSeparator()
+*/
+void QGuiAction::setSeparator(bool b)
+{
+    Q_D(QGuiAction);
+    if (d->separator == b)
+        return;
+
+    d->separator = b;
+    d->sendDataChanged();
+}
+
+/*!
+  Returns \c true if this action is a separator action; otherwise it
+  returns \c false.
+
+  \sa setSeparator()
+*/
+bool QGuiAction::isSeparator() const
+{
+    Q_D(const QGuiAction);
+    return d->separator;
+}
+
+/*!
+    \property QGuiAction::text
+    \brief the action's descriptive text
+
+    If the action is added to a menu, the menu option will consist of
+    the icon (if there is one), the text, and the shortcut (if there
+    is one). If the text is not explicitly set in the constructor, or
+    by using setText(), the action's description icon text will be
+    used as text. There is no default text.
+
+    \sa iconText
+*/
+void QGuiAction::setText(const QString &text)
+{
+    Q_D(QGuiAction);
+    if (d->text == text)
+        return;
+
+    d->text = text;
+    d->sendDataChanged();
+}
+
+QString QGuiAction::text() const
+{
+    Q_D(const QGuiAction);
+    QString s = d->text;
+    if(s.isEmpty()) {
+        s = d->iconText;
+        s.replace(QLatin1Char('&'), QLatin1String("&&"));
+    }
+    return s;
+}
+
+/*!
+    \property QGuiAction::iconText
+    \brief the action's descriptive icon text
+
+    If QToolBar::toolButtonStyle is set to a value that permits text to
+    be displayed, the text defined held in this property appears as a
+    label in the relevant tool button.
+
+    It also serves as the default text in menus and tooltips if the action
+    has not been defined with setText() or setToolTip(), and will
+    also be used in toolbar buttons if no icon has been defined using setIcon().
+
+    If the icon text is not explicitly set, the action's normal text will be
+    used for the icon text.
+
+    By default, this property contains an empty string.
+
+    \sa setToolTip(), setStatusTip()
+*/
+void QGuiAction::setIconText(const QString &text)
+{
+    Q_D(QGuiAction);
+    if (d->iconText == text)
+        return;
+
+    d->iconText = text;
+    d->sendDataChanged();
+}
+
+QString QGuiAction::iconText() const
+{
+    Q_D(const QGuiAction);
+    if (d->iconText.isEmpty())
+        return qt_strippedText(d->text);
+    return d->iconText;
+}
+
+/*!
+    \property QGuiAction::toolTip
+    \brief the action's tooltip
+
+    This text is used for the tooltip. If no tooltip is specified,
+    the action's text is used.
+
+    By default, this property contains the action's text.
+
+    \sa setStatusTip(), setShortcut()
+*/
+void QGuiAction::setToolTip(const QString &tooltip)
+{
+    Q_D(QGuiAction);
+    if (d->tooltip == tooltip)
+        return;
+
+    d->tooltip = tooltip;
+    d->sendDataChanged();
+}
+
+QString QGuiAction::toolTip() const
+{
+    Q_D(const QGuiAction);
+    if (d->tooltip.isEmpty()) {
+        if (!d->text.isEmpty())
+            return qt_strippedText(d->text);
+        return qt_strippedText(d->iconText);
+    }
+    return d->tooltip;
+}
+
+/*!
+    \property QGuiAction::statusTip
+    \brief the action's status tip
+
+    The status tip is displayed on all status bars provided by the
+    action's top-level parent widget.
+
+    By default, this property contains an empty string.
+
+    \sa setToolTip(), showStatusText()
+*/
+void QGuiAction::setStatusTip(const QString &statustip)
+{
+    Q_D(QGuiAction);
+    if (d->statustip == statustip)
+        return;
+
+    d->statustip = statustip;
+    d->sendDataChanged();
+}
+
+QString QGuiAction::statusTip() const
+{
+    Q_D(const QGuiAction);
+    return d->statustip;
+}
+
+/*!
+    \property QGuiAction::whatsThis
+    \brief the action's "What's This?" help text
+
+    The "What's This?" text is used to provide a brief description of
+    the action. The text may contain rich text. There is no default
+    "What's This?" text.
+
+    \sa QWhatsThis
+*/
+void QGuiAction::setWhatsThis(const QString &whatsthis)
+{
+    Q_D(QGuiAction);
+    if (d->whatsthis == whatsthis)
+        return;
+
+    d->whatsthis = whatsthis;
+    d->sendDataChanged();
+}
+
+QString QGuiAction::whatsThis() const
+{
+    Q_D(const QGuiAction);
+    return d->whatsthis;
+}
+
+/*!
+    \enum QGuiAction::Priority
+
+    This enum defines priorities for actions in user interface.
+
+    \value LowPriority The action should not be prioritized in
+    the user interface.
+
+    \value NormalPriority
+
+    \value HighPriority The action should be prioritized in
+    the user interface.
+
+    \sa priority
+*/
+
+
+/*!
+    \property QGuiAction::priority
+
+    \brief the actions's priority in the user interface.
+
+    This property can be set to indicate how the action should be prioritized
+    in the user interface.
+
+    For instance, when toolbars have the Qt::ToolButtonTextBesideIcon
+    mode set, then actions with LowPriority will not show the text
+    labels.
+*/
+void QGuiAction::setPriority(Priority priority)
+{
+    Q_D(QGuiAction);
+    if (d->priority == priority)
+        return;
+
+    d->priority = priority;
+    d->sendDataChanged();
+}
+
+QGuiAction::Priority QGuiAction::priority() const
+{
+    Q_D(const QGuiAction);
+    return d->priority;
+}
+
+/*!
+    \property QGuiAction::checkable
+    \brief whether the action is a checkable action
+
+    A checkable action is one which has an on/off state. For example,
+    in a word processor, a Bold toolbar button may be either on or
+    off. An action which is not a toggle action is a command action;
+    a command action is simply executed, e.g. file save.
+    By default, this property is \c false.
+
+    In some situations, the state of one toggle action should depend
+    on the state of others. For example, "Left Align", "Center" and
+    "Right Align" toggle actions are mutually exclusive. To achieve
+    exclusive toggling, add the relevant toggle actions to a
+    QGuiActionGroup with the QGuiActionGroup::exclusive property set to
+    true.
+
+    \sa setChecked()
+*/
+void QGuiAction::setCheckable(bool b)
+{
+    Q_D(QGuiAction);
+    if (d->checkable == b)
+        return;
+
+    d->checkable = b;
+    d->checked = false;
+    d->sendDataChanged();
+}
+
+bool QGuiAction::isCheckable() const
+{
+    Q_D(const QGuiAction);
+    return d->checkable;
+}
+
+/*!
+    \fn void QGuiAction::toggle()
+
+    This is a convenience function for the \l checked property.
+    Connect to it to change the checked state to its opposite state.
+*/
+void QGuiAction::toggle()
+{
+    Q_D(QGuiAction);
+    setChecked(!d->checked);
+}
+
+/*!
+    \property QGuiAction::checked
+    \brief whether the action is checked.
+
+    Only checkable actions can be checked.  By default, this is false
+    (the action is unchecked).
+
+    \note The notifier signal for this property is toggled(). As toggling
+    a QAction changes its state, it will also emit a changed() signal.
+
+    \sa checkable, toggled()
+*/
+void QGuiAction::setChecked(bool b)
+{
+    Q_D(QGuiAction);
+    if (!d->checkable || d->checked == b)
+        return;
+
+    QPointer<QGuiAction> guard(this);
+    d->checked = b;
+    d->sendDataChanged();
+    if (guard)
+        emit toggled(b);
+}
+
+bool QGuiAction::isChecked() const
+{
+    Q_D(const QGuiAction);
+    return d->checked;
+}
+
+/*!
+    \fn void QGuiAction::setDisabled(bool b)
+
+    This is a convenience function for the \l enabled property, that
+    is useful for signals--slots connections. If \a b is true the
+    action is disabled; otherwise it is enabled.
+*/
+
+/*!
+    \property QGuiAction::enabled
+    \brief whether the action is enabled
+
+    Disabled actions cannot be chosen by the user. They do not
+    disappear from menus or toolbars, but they are displayed in a way
+    which indicates that they are unavailable. For example, they might
+    be displayed using only shades of gray.
+
+    \uicontrol{What's This?} help on disabled actions is still available, provided
+    that the QAction::whatsThis property is set.
+
+    An action will be disabled when all widgets to which it is added
+    (with QWidget::addAction()) are disabled or not visible. When an
+    action is disabled, it is not possible to trigger it through its
+    shortcut.
+
+    By default, this property is \c true (actions are enabled).
+
+    \sa text
+*/
+void QGuiAction::setEnabled(bool b)
+{
+    Q_D(QGuiAction);
+    if (b == d->enabled && b != d->forceDisabled)
+        return;
+    d->forceDisabled = !b;
+    if (b && (!d->visible || (d->group && !d->group->isEnabled())))
+        return;
+    QAPP_CHECK("setEnabled");
+    d->enabled = b;
+#if QT_CONFIG(shortcut)
+    d->setShortcutEnabled(b, QGuiApplicationPrivate::instance()->shortcutMap);
+#endif
+    d->sendDataChanged();
+}
+
+bool QGuiAction::isEnabled() const
+{
+    Q_D(const QGuiAction);
+    return d->enabled;
+}
+
+/*!
+    \property QGuiAction::visible
+    \brief whether the action can be seen (e.g. in menus and toolbars)
+
+    If \e visible is true the action can be seen (e.g. in menus and
+    toolbars) and chosen by the user; if \e visible is false the
+    action cannot be seen or chosen by the user.
+
+    Actions which are not visible are \e not grayed out; they do not
+    appear at all.
+
+    By default, this property is \c true (actions are visible).
+*/
+void QGuiAction::setVisible(bool b)
+{
+    Q_D(QGuiAction);
+    if (b == d->visible && b != d->forceInvisible)
+        return;
+    QAPP_CHECK("setVisible");
+    d->forceInvisible = !b;
+    d->visible = b;
+    d->enabled = b && !d->forceDisabled && (!d->group || d->group->isEnabled()) ;
+#if QT_CONFIG(shortcut)
+    d->setShortcutEnabled(d->enabled, QGuiApplicationPrivate::instance()->shortcutMap);
+#endif
+    d->sendDataChanged();
+}
+
+
+bool QGuiAction::isVisible() const
+{
+    Q_D(const QGuiAction);
+    return d->visible;
+}
+
+/*!
+  \reimp
+*/
+bool QGuiAction::event(QEvent *e)
+{
+#if QT_CONFIG(shortcut)
+    if (e->type() == QEvent::Shortcut) {
+        QShortcutEvent *se = static_cast<QShortcutEvent *>(e);
+        Q_ASSERT_X(se->key() == d_func()->shortcut || d_func()->alternateShortcuts.contains(se->key()),
+                   "QAction::event",
+                   "Received shortcut event from incorrect shortcut");
+        if (se->isAmbiguous())
+            qWarning("QAction::event: Ambiguous shortcut overload: %s", se->key().toString(QKeySequence::NativeText).toLatin1().constData());
+        else
+            activate(Trigger);
+        return true;
+    }
+#endif
+    return QObject::event(e);
+}
+
+/*!
+  Returns the user data as set in QAction::setData.
+
+  \sa setData()
+*/
+QVariant QGuiAction::data() const
+{
+    Q_D(const QGuiAction);
+    return d->userData;
+}
+
+/*!
+  Sets the action's internal data to the given \a userData.
+
+  \sa data()
+*/
+void QGuiAction::setData(const QVariant &data)
+{
+    Q_D(QGuiAction);
+    if (d->userData == data)
+        return;
+    d->userData = data;
+    d->sendDataChanged();
+}
+
+/*!
+  Sends the relevant signals for ActionEvent \a event.
+
+  Action based widgets use this API to cause the QAction
+  to emit signals as well as emitting their own.
+*/
+void QGuiAction::activate(ActionEvent event)
+{
+    Q_D(QGuiAction);
+    if(event == Trigger) {
+        QPointer<QObject> guard = this;
+        if(d->checkable) {
+            // the checked action of an exclusive group may not be unchecked
+            if (d->checked && (d->group
+                               && d->group->exclusionPolicy() == QGuiActionGroup::ExclusionPolicy::Exclusive
+                               && d->group->checkedGuiAction() == this)) {
+                if (!guard.isNull())
+                    emit triggered(true);
+                return;
+            }
+            setChecked(!d->checked);
+        }
+        if (!guard.isNull())
+            emit triggered(d->checked);
+    } else if(event == Hover) {
+        emit hovered();
+    }
+}
+
+/*!
+    \fn void QGuiAction::triggered(bool checked)
+
+    This signal is emitted when an action is activated by the user;
+    for example, when the user clicks a menu option, toolbar button,
+    or presses an action's shortcut key combination, or when trigger()
+    was called. Notably, it is \e not emitted when setChecked() or
+    toggle() is called.
+
+    If the action is checkable, \a checked is true if the action is
+    checked, or false if the action is unchecked.
+
+    \sa activate(), toggled(), checked
+*/
+
+/*!
+    \fn void QGuiAction::toggled(bool checked)
+
+    This signal is emitted whenever a checkable action changes its
+    isChecked() status. This can be the result of a user interaction,
+    or because setChecked() was called. As setChecked() changes the
+    QAction, it emits changed() in addition to toggled().
+
+    \a checked is true if the action is checked, or false if the
+    action is unchecked.
+
+    \sa activate(), triggered(), checked
+*/
+
+/*!
+    \fn void QGuiAction::hovered()
+
+    This signal is emitted when an action is highlighted by the user;
+    for example, when the user pauses with the cursor over a menu option,
+    toolbar button, or presses an action's shortcut key combination.
+
+    \sa activate()
+*/
+
+/*!
+    \fn void QGuiAction::changed()
+
+    This signal is emitted when an action has changed. If you
+    are only interested in actions in a given widget, you can
+    watch for QWidget::actionEvent() sent with an
+    QEvent::ActionChanged.
+
+    \sa QWidget::actionEvent()
+*/
+
+/*!
+    \enum QGuiAction::ActionEvent
+
+    This enum type is used when calling QAction::activate()
+
+    \value Trigger this will cause the QAction::triggered() signal to be emitted.
+
+    \value Hover this will cause the QAction::hovered() signal to be emitted.
+*/
+
+/*!
+    \property QGuiAction::menuRole
+    \brief the action's menu role
+
+    This indicates what role the action serves in the application menu on
+    \macos. By default all actions have the TextHeuristicRole, which means that
+    the action is added based on its text (see QMenuBar for more information).
+
+    The menu role can only be changed before the actions are put into the menu
+    bar in \macos (usually just before the first application window is
+    shown).
+*/
+void QGuiAction::setMenuRole(MenuRole menuRole)
+{
+    Q_D(QGuiAction);
+    if (d->menuRole == menuRole)
+        return;
+
+    d->menuRole = menuRole;
+    d->sendDataChanged();
+}
+
+QGuiAction::MenuRole QGuiAction::menuRole() const
+{
+    Q_D(const QGuiAction);
+    return d->menuRole;
+}
+
+/*!
+    \property QGuiAction::iconVisibleInMenu
+    \brief Whether or not an action should show an icon in a menu
+
+    In some applications, it may make sense to have actions with icons in the
+    toolbar, but not in menus. If true, the icon (if valid) is shown in the menu, when it
+    is false, it is not shown.
+
+    The default is to follow whether the Qt::AA_DontShowIconsInMenus attribute
+    is set for the application. Explicitly settings this property overrides
+    the presence (or abscence) of the attribute.
+
+    For example:
+    \snippet code/src_gui_kernel_qaction.cpp 0
+
+    \sa icon, QCoreApplication::setAttribute()
+*/
+void QGuiAction::setIconVisibleInMenu(bool visible)
+{
+    Q_D(QGuiAction);
+    if (d->iconVisibleInMenu == -1 || visible != bool(d->iconVisibleInMenu)) {
+        int oldValue = d->iconVisibleInMenu;
+        d->iconVisibleInMenu = visible;
+        // Only send data changed if we really need to.
+        if (oldValue != -1
+            || visible == !QCoreApplication::testAttribute(Qt::AA_DontShowIconsInMenus)) {
+            d->sendDataChanged();
+        }
+    }
+}
+
+bool QGuiAction::isIconVisibleInMenu() const
+{
+    Q_D(const QGuiAction);
+    if (d->iconVisibleInMenu == -1) {
+        return !QCoreApplication::testAttribute(Qt::AA_DontShowIconsInMenus);
+    }
+    return d->iconVisibleInMenu;
+}
+
+/*!
+    \property QGuiAction::shortcutVisibleInContextMenu
+    \brief Whether or not an action should show a shortcut in a context menu
+
+    In some applications, it may make sense to have actions with shortcuts in
+    context menus. If true, the shortcut (if valid) is shown when the action is
+    shown via a context menu, when it is false, it is not shown.
+
+    The default is to follow whether the Qt::AA_DontShowShortcutsInContextMenus attribute
+    is set for the application, falling back to the widget style hint.
+    Explicitly setting this property overrides the presence (or abscence) of the attribute.
+
+    \sa shortcut, QCoreApplication::setAttribute()
+*/
+void QGuiAction::setShortcutVisibleInContextMenu(bool visible)
+{
+    Q_D(QGuiAction);
+    if (d->shortcutVisibleInContextMenu == -1 || visible != bool(d->shortcutVisibleInContextMenu)) {
+        int oldValue = d->shortcutVisibleInContextMenu;
+        d->shortcutVisibleInContextMenu = visible;
+        // Only send data changed if we really need to.
+        if (oldValue != -1
+            || visible == !QCoreApplication::testAttribute(Qt::AA_DontShowShortcutsInContextMenus)) {
+            d->sendDataChanged();
+        }
+    }
+}
+
+bool QGuiAction::isShortcutVisibleInContextMenu() const
+{
+    Q_D(const QGuiAction);
+    if (d->shortcutVisibleInContextMenu == -1) {
+        return !QCoreApplication::testAttribute(Qt::AA_DontShowShortcutsInContextMenus)
+            && QGuiApplication::styleHints()->showShortcutsInContextMenus();
+    }
+    return d->shortcutVisibleInContextMenu;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug d, const QGuiAction *action)
+{
+    QDebugStateSaver saver(d);
+    d.nospace();
+    d << "QAction(" << static_cast<const void *>(action);
+    if (action) {
+        d << " text=" << action->text();
+        if (!action->toolTip().isEmpty())
+            d << " toolTip=" << action->toolTip();
+        if (action->isCheckable())
+            d << " checked=" << action->isChecked();
+#if QT_CONFIG(shortcut)
+        if (!action->shortcut().isEmpty())
+            d << " shortcut=" << action->shortcut();
+#endif
+        d << " menuRole=";
+        QtDebugUtils::formatQEnum(d, action->menuRole());
+        d << " visible=" << action->isVisible();
+    } else {
+        d << '0';
+    }
+    d << ')';
+    return d;
+}
+#endif // QT_NO_DEBUG_STREAM
+
+QT_END_NAMESPACE
+
+#include "moc_qguiaction.cpp"
+
+#endif // QT_NO_ACTION
diff --git a/src/gui/kernel/qguiaction.h b/src/gui/kernel/qguiaction.h
new file mode 100644
index 0000000000..7672b312da
--- /dev/null
+++ b/src/gui/kernel/qguiaction.h
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWidgets module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGUIACTION_H
+#define QGUIACTION_H
+
+#include <QtGui/qtguiglobal.h>
+#include <QtGui/qkeysequence.h>
+#include <QtGui/qicon.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_NAMESPACE
+
+
+#ifndef QT_NO_ACTION
+
+class QActionEvent;
+class QGuiActionGroup;
+class QGuiActionPrivate;
+
+class Q_GUI_EXPORT QGuiAction : public QObject
+{
+    Q_OBJECT
+    Q_DECLARE_PRIVATE(QGuiAction)
+
+    Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable NOTIFY changed)
+    Q_PROPERTY(bool checked READ isChecked WRITE setChecked DESIGNABLE isCheckable NOTIFY toggled)
+    Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY changed)
+    Q_PROPERTY(QIcon icon READ icon WRITE setIcon NOTIFY changed)
+    Q_PROPERTY(QString text READ text WRITE setText NOTIFY changed)
+    Q_PROPERTY(QString iconText READ iconText WRITE setIconText NOTIFY changed)
+    Q_PROPERTY(QString toolTip READ toolTip WRITE setToolTip NOTIFY changed)
+    Q_PROPERTY(QString statusTip READ statusTip WRITE setStatusTip NOTIFY changed)
+    Q_PROPERTY(QString whatsThis READ whatsThis WRITE setWhatsThis NOTIFY changed)
+    Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY changed)
+#if QT_CONFIG(shortcut)
+    Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut NOTIFY changed)
+    Q_PROPERTY(Qt::ShortcutContext shortcutContext READ shortcutContext WRITE setShortcutContext NOTIFY changed)
+    Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat NOTIFY changed)
+#endif
+    Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY changed)
+    Q_PROPERTY(MenuRole menuRole READ menuRole WRITE setMenuRole NOTIFY changed)
+    Q_PROPERTY(bool iconVisibleInMenu READ isIconVisibleInMenu WRITE setIconVisibleInMenu NOTIFY changed)
+    Q_PROPERTY(bool shortcutVisibleInContextMenu READ isShortcutVisibleInContextMenu WRITE setShortcutVisibleInContextMenu NOTIFY changed)
+    Q_PROPERTY(Priority priority READ priority WRITE setPriority)
+
+public:
+    // note this is copied into qplatformmenu.h, which must stay in sync
+    enum MenuRole { NoRole = 0, TextHeuristicRole, ApplicationSpecificRole, AboutQtRole,
+                    AboutRole, PreferencesRole, QuitRole };
+    Q_ENUM(MenuRole)
+    enum Priority { LowPriority = 0,
+                    NormalPriority = 128,
+                    HighPriority = 256};
+    Q_ENUM(Priority)
+    explicit QGuiAction(QObject *parent = nullptr);
+    explicit QGuiAction(const QString &text, QObject *parent = nullptr);
+    explicit QGuiAction(const QIcon &icon, const QString &text, QObject *parent = nullptr);
+
+    ~QGuiAction();
+
+    void setActionGroup(QGuiActionGroup *group);
+    QGuiActionGroup *guiActionGroup() const;
+    void setIcon(const QIcon &icon);
+    QIcon icon() const;
+
+    void setText(const QString &text);
+    QString text() const;
+
+    void setIconText(const QString &text);
+    QString iconText() const;
+
+    void setToolTip(const QString &tip);
+    QString toolTip() const;
+
+    void setStatusTip(const QString &statusTip);
+    QString statusTip() const;
+
+    void setWhatsThis(const QString &what);
+    QString whatsThis() const;
+
+    void setPriority(Priority priority);
+    Priority priority() const;
+
+    void setSeparator(bool b);
+    bool isSeparator() const;
+
+#if QT_CONFIG(shortcut)
+    void setShortcut(const QKeySequence &shortcut);
+    QKeySequence shortcut() const;
+
+    void setShortcuts(const QList<QKeySequence> &shortcuts);
+    void setShortcuts(QKeySequence::StandardKey);
+    QList<QKeySequence> shortcuts() const;
+
+    void setShortcutContext(Qt::ShortcutContext context);
+    Qt::ShortcutContext shortcutContext() const;
+
+    void setAutoRepeat(bool);
+    bool autoRepeat() const;
+#endif
+
+    void setFont(const QFont &font);
+    QFont font() const;
+
+    void setCheckable(bool);
+    bool isCheckable() const;
+
+    QVariant data() const;
+    void setData(const QVariant &var);
+
+    bool isChecked() const;
+
+    bool isEnabled() const;
+
+    bool isVisible() const;
+
+    enum ActionEvent { Trigger, Hover };
+    void activate(ActionEvent event);
+
+    void setMenuRole(MenuRole menuRole);
+    MenuRole menuRole() const;
+
+    void setIconVisibleInMenu(bool visible);
+    bool isIconVisibleInMenu() const;
+
+    void setShortcutVisibleInContextMenu(bool show);
+    bool isShortcutVisibleInContextMenu() const;
+
+protected:
+    bool event(QEvent *) override;
+    QGuiAction(QGuiActionPrivate &dd, QObject *parent);
+
+public Q_SLOTS:
+    void trigger() { activate(Trigger); }
+    void hover() { activate(Hover); }
+    void setChecked(bool);
+    void toggle();
+    void setEnabled(bool);
+    inline void setDisabled(bool b) { setEnabled(!b); }
+    void setVisible(bool);
+
+Q_SIGNALS:
+    void changed();
+    void triggered(bool checked = false);
+    void hovered();
+    void toggled(bool);
+
+private:
+    Q_DISABLE_COPY(QGuiAction)
+    friend class QGuiActionGroup;
+};
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QGuiAction *);
+#endif
+
+#endif // QT_NO_ACTION
+
+QT_END_NAMESPACE
+
+#endif // QGUIACTION_H
diff --git a/src/gui/kernel/qguiaction_p.h b/src/gui/kernel/qguiaction_p.h
new file mode 100644
index 0000000000..850656a4af
--- /dev/null
+++ b/src/gui/kernel/qguiaction_p.h
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWidgets module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGUIACTION_P_H
+#define QGUIACTION_P_H
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists for the convenience
+// of other Qt classes.  This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qtguiglobal_p.h>
+#include <QtGui/qguiaction.h>
+#include <QtGui/qfont.h>
+#include <QtGui/private/qshortcutmap_p.h>
+#include "private/qobject_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_ACTION
+
+
+class QShortcutMap;
+
+class Q_GUI_EXPORT QGuiActionPrivate : public QObjectPrivate
+{
+    Q_DECLARE_PUBLIC(QGuiAction)
+public:
+    QGuiActionPrivate();
+    ~QGuiActionPrivate();
+
+    virtual QShortcutMap::ContextMatcher contextMatcher() const;
+
+    static QGuiActionPrivate *get(QGuiAction *q)
+    {
+        return q->d_func();
+    }
+
+
+    QPointer<QGuiActionGroup> group;
+    QString text;
+    QString iconText;
+    QIcon icon;
+    QString tooltip;
+    QString statustip;
+    QString whatsthis;
+#if QT_CONFIG(shortcut)
+    QKeySequence shortcut;
+    QList<QKeySequence> alternateShortcuts;
+#endif
+    QVariant userData;
+#if QT_CONFIG(shortcut)
+    int shortcutId = 0;
+    QVector<int> alternateShortcutIds;
+    Qt::ShortcutContext shortcutContext = Qt::WindowShortcut;
+    uint autorepeat : 1;
+#endif
+    QFont font;
+    uint enabled : 1, forceDisabled : 1;
+    uint visible : 1, forceInvisible : 1;
+    uint checkable : 1;
+    uint checked : 1;
+    uint separator : 1;
+    uint fontSet : 1;
+
+    int iconVisibleInMenu : 2;  // Only has values -1, 0, and 1
+    int shortcutVisibleInContextMenu : 2; // Only has values -1, 0, and 1
+
+    QGuiAction::MenuRole menuRole = QGuiAction::TextHeuristicRole;
+    QGuiAction::Priority priority = QGuiAction::NormalPriority;
+
+#if QT_CONFIG(shortcut)
+    void redoGrab(QShortcutMap &map);
+    void redoGrabAlternate(QShortcutMap &map);
+    void setShortcutEnabled(bool enable, QShortcutMap &map);
+#endif // QT_NO_SHORTCUT
+
+    void sendDataChanged();
+};
+
+#endif // QT_NO_ACTION
+
+QT_END_NAMESPACE
+
+#endif // QACTION_P_H
diff --git a/src/gui/kernel/qguiactiongroup.cpp b/src/gui/kernel/qguiactiongroup.cpp
new file mode 100644
index 0000000000..3bfcb63238
--- /dev/null
+++ b/src/gui/kernel/qguiactiongroup.cpp
@@ -0,0 +1,349 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWidgets module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qguiactiongroup.h"
+
+#ifndef QT_NO_ACTION
+#include "qguiaction.h"
+#include "qguiaction_p.h"
+#include "qguiactiongroup_p.h"
+#include "qevent.h"
+#include "qlist.h"
+
+QT_BEGIN_NAMESPACE
+
+QGuiActionGroupPrivate::QGuiActionGroupPrivate() :
+    enabled(1), visible(1)
+{
+}
+
+QGuiActionGroupPrivate::~QGuiActionGroupPrivate() = default;
+
+void QGuiActionGroup::_q_actionChanged()
+{
+    Q_D(QGuiActionGroup);
+    auto action = qobject_cast<QGuiAction*>(sender());
+    Q_ASSERT_X(action != nullptr, "QGuiActionGroup::_q_actionChanged", "internal error");
+    if (d->exclusionPolicy != QGuiActionGroup::ExclusionPolicy::None) {
+        if (action->isChecked()) {
+            if (action != d->current) {
+                if (!d->current.isNull())
+                    d->current->setChecked(false);
+                d->current = action;
+            }
+        } else if (action == d->current) {
+            d->current = nullptr;
+        }
+    }
+}
+
+void QGuiActionGroup::_q_actionTriggered()
+{
+    Q_D(QGuiActionGroup);
+    auto action = qobject_cast<QGuiAction*>(sender());
+    Q_ASSERT_X(action != nullptr, "QGuiActionGroup::_q_actionTriggered", "internal error");
+    d->emitSignal(QGuiActionGroupPrivate::Triggered, action);
+}
+
+void QGuiActionGroup::_q_actionHovered()
+{
+    Q_D(QGuiActionGroup);
+    auto action = qobject_cast<QGuiAction*>(sender());
+    Q_ASSERT_X(action != nullptr, "QGuiActionGroup::_q_actionHovered", "internal error");
+    d->emitSignal(QGuiActionGroupPrivate::Hovered, action);
+}
+
+/*!
+    \class QGuiActionGroup
+    \brief The QGuiActionGroup class groups actions together.
+    \since 6.0
+
+    \ingroup TBD
+    \inmodule QtGui
+
+    QGuiActionGroup is a base class for classes grouping
+    classes inhheriting QGuiAction objects together.
+
+    In some situations it is useful to group QGuiAction objects together.
+    For example, if you have a \uicontrol{Left Align} action, a \uicontrol{Right
+    Align} action, a \uicontrol{Justify} action, and a \uicontrol{Center} action,
+    only one of these actions should be active at any one time. One
+    simple way of achieving this is to group the actions together in
+    an action group, inheriting QGuiActionGroup.
+
+    \sa QGuiAction
+*/
+
+/*!
+    \enum QGuiActionGroup::ExclusionPolicy
+
+    This enum specifies the different policies that can be used to
+    control how the group performs exclusive checking on checkable actions.
+
+    \value None
+           The actions in the group can be checked independently of each other.
+
+    \value Exclusive
+           Exactly one action can be checked at any one time.
+           This is the default policy.
+
+    \value ExclusiveOptional
+           At most one action can be checked at any one time. The actions
+           can also be all unchecked.
+
+    \sa exclusionPolicy
+*/
+
+/*!
+    Constructs an action group for the \a parent object.
+
+    The action group is exclusive by default. Call setExclusive(false)
+    to make the action group non-exclusive. To make the group exclusive
+    but allow unchecking the active action call instead
+    setExclusionPolicy(QGuiActionGroup::ExclusionPolicy::ExclusiveOptional)
+*/
+QGuiActionGroup::QGuiActionGroup(QObject* parent) :
+    QGuiActionGroup(*new QGuiActionGroupPrivate, parent)
+{
+}
+
+QGuiActionGroup::QGuiActionGroup(QGuiActionGroupPrivate &dd, QObject *parent) :
+    QObject(dd, parent)
+{
+}
+
+/*!
+    Destroys the action group.
+*/
+QGuiActionGroup::~QGuiActionGroup() = default;
+
+/*!
+    \fn QGuiAction *QGuiActionGroup::addAction(QGuiAction *action)
+
+    Adds the \a action to this group, and returns it.
+
+    Normally an action is added to a group by creating it with the
+    group as its parent, so this function is not usually used.
+
+    \sa QGuiAction::setActionGroup()
+*/
+QGuiAction *QGuiActionGroup::addAction(QGuiAction* a)
+{
+    Q_D(QGuiActionGroup);
+    if (!d->actions.contains(a)) {
+        d->actions.append(a);
+        QObject::connect(a, &QGuiAction::triggered, this, &QGuiActionGroup::_q_actionTriggered);
+        QObject::connect(a, &QGuiAction::changed, this, &QGuiActionGroup::_q_actionChanged);
+        QObject::connect(a, &QGuiAction::hovered, this, &QGuiActionGroup::_q_actionHovered);
+    }
+    if (!a->d_func()->forceDisabled) {
+        a->setEnabled(d->enabled);
+        a->d_func()->forceDisabled = false;
+    }
+    if (!a->d_func()->forceInvisible) {
+        a->setVisible(d->visible);
+        a->d_func()->forceInvisible = false;
+    }
+    if (a->isChecked())
+        d->current = a;
+    QGuiActionGroup *oldGroup = a->d_func()->group;
+    if (oldGroup != this) {
+        if (oldGroup)
+            oldGroup->removeAction(a);
+        a->d_func()->group = this;
+        a->d_func()->sendDataChanged();
+    }
+    return a;
+}
+
+/*!
+  Removes the \a action from this group. The action will have no
+  parent as a result.
+
+  \sa QGuiAction::setActionGroup()
+*/
+void QGuiActionGroup::removeAction(QGuiAction *action)
+{
+    Q_D(QGuiActionGroup);
+    if (d->actions.removeAll(action)) {
+        if (action == d->current)
+            d->current = nullptr;
+        QObject::disconnect(action, &QGuiAction::triggered, this, &QGuiActionGroup::_q_actionTriggered);
+        QObject::disconnect(action, &QGuiAction::changed, this, &QGuiActionGroup::_q_actionChanged);
+        QObject::disconnect(action, &QGuiAction::hovered, this, &QGuiActionGroup::_q_actionHovered);
+        action->d_func()->group = nullptr;
+    }
+}
+
+/*!
+    Returns the list of this groups's actions. This may be empty.
+*/
+QList<QGuiAction*> QGuiActionGroup::guiActions() const
+{
+    Q_D(const QGuiActionGroup);
+    return d->actions;
+}
+
+/*!
+    \brief Enable or disable the group exclusion checking
+
+    This is a convenience method that calls
+    setExclusionPolicy(ExclusionPolicy::Exclusive).
+
+    \sa QGuiActionGroup::exclusionPolicy
+*/
+void QGuiActionGroup::setExclusive(bool b)
+{
+    setExclusionPolicy(b ? QGuiActionGroup::ExclusionPolicy::Exclusive
+                         : QGuiActionGroup::ExclusionPolicy::None);
+}
+
+/*!
+    \brief Returs true if the group is exclusive
+
+    The group is exclusive if the ExclusionPolicy is either Exclusive
+    or ExclusionOptional.
+
+*/
+bool QGuiActionGroup::isExclusive() const
+{
+    return exclusionPolicy() != QGuiActionGroup::ExclusionPolicy::None;
+}
+
+/*!
+    \property QGuiActionGroup::exclusionPolicy
+    \brief This property holds the group exclusive checking policy
+
+    If exclusionPolicy is set to Exclusive, only one checkable
+    action in the action group can ever be active at any time. If the user
+    chooses another checkable action in the group, the one they chose becomes
+    active and the one that was active becomes inactive. If exclusionPolicy is
+    set to ExclusionOptional the group is exclusive but the active checkable
+    action in the group can be unchecked leaving the group with no actions
+    checked.
+
+    \sa QGuiAction::checkable
+*/
+void QGuiActionGroup::setExclusionPolicy(QGuiActionGroup::ExclusionPolicy policy)
+{
+    Q_D(QGuiActionGroup);
+    d->exclusionPolicy = policy;
+}
+
+QGuiActionGroup::ExclusionPolicy QGuiActionGroup::exclusionPolicy() const
+{
+    Q_D(const QGuiActionGroup);
+    return d->exclusionPolicy;
+}
+
+/*!
+    \fn void QGuiActionGroup::setDisabled(bool b)
+
+    This is a convenience function for the \l enabled property, that
+    is useful for signals--slots connections. If \a b is true the
+    action group is disabled; otherwise it is enabled.
+*/
+
+/*!
+    \property QGuiActionGroup::enabled
+    \brief whether the action group is enabled
+
+    Each action in the group will be enabled or disabled unless it
+    has been explicitly disabled.
+
+    \sa QGuiAction::setEnabled()
+*/
+void QGuiActionGroup::setEnabled(bool b)
+{
+    Q_D(QGuiActionGroup);
+    d->enabled = b;
+    for (auto action : qAsConst(d->actions)) {
+        if (!action->d_func()->forceDisabled) {
+            action->setEnabled(b);
+            action->d_func()->forceDisabled = false;
+        }
+    }
+}
+
+bool QGuiActionGroup::isEnabled() const
+{
+    Q_D(const QGuiActionGroup);
+    return d->enabled;
+}
+
+/*!
+  Returns the currently checked action in the group, or \nullptr if
+  none are checked.
+*/
+QGuiAction *QGuiActionGroup::checkedGuiAction() const
+{
+    Q_D(const QGuiActionGroup);
+    return d->current.data();
+}
+
+/*!
+    \property QGuiActionGroup::visible
+    \brief whether the action group is visible
+
+    Each action in the action group will match the visible state of
+    this group unless it has been explicitly hidden.
+
+    \sa QGuiAction::setEnabled()
+*/
+void QGuiActionGroup::setVisible(bool b)
+{
+    Q_D(QGuiActionGroup);
+    d->visible = b;
+    for (auto action : qAsConst(d->actions)) {
+        if (!action->d_func()->forceInvisible) {
+            action->setVisible(b);
+            action->d_func()->forceInvisible = false;
+        }
+    }
+}
+
+bool QGuiActionGroup::isVisible() const
+{
+    Q_D(const QGuiActionGroup);
+    return d->visible;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACTION
diff --git a/src/gui/kernel/qguiactiongroup.h b/src/gui/kernel/qguiactiongroup.h
new file mode 100644
index 0000000000..ae25c2e768
--- /dev/null
+++ b/src/gui/kernel/qguiactiongroup.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWidgets module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGUIACTIONGROUP_H
+#define QGUIACTIONGROUP_H
+
+#include <QtGui/qtguiglobal.h>
+#include <QtGui/qguiaction.h>
+
+QT_BEGIN_NAMESPACE
+
+
+#ifndef QT_NO_ACTION
+
+class QGuiActionGroupPrivate;
+
+class Q_GUI_EXPORT QGuiActionGroup : public QObject
+{
+    Q_OBJECT
+    Q_DECLARE_PRIVATE(QGuiActionGroup)
+
+    Q_PROPERTY(QGuiActionGroup::ExclusionPolicy exclusionPolicy READ exclusionPolicy WRITE setExclusionPolicy)
+    Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
+    Q_PROPERTY(bool visible READ isVisible WRITE setVisible)
+
+public:
+    enum class ExclusionPolicy {
+        None,
+        Exclusive,
+        ExclusiveOptional
+    };
+    Q_ENUM(ExclusionPolicy)
+
+    explicit QGuiActionGroup(QObject *parent);
+    ~QGuiActionGroup();
+
+    QGuiAction *addAction(QGuiAction *a);
+    void removeAction(QGuiAction *a);
+    QList<QGuiAction*> guiActions() const;
+    QGuiAction *checkedGuiAction() const;
+
+    bool isExclusive() const;
+    bool isEnabled() const;
+    bool isVisible() const;
+    ExclusionPolicy exclusionPolicy() const;
+
+
+public Q_SLOTS:
+    void setEnabled(bool);
+    inline void setDisabled(bool b) { setEnabled(!b); }
+    void setVisible(bool);
+    void setExclusive(bool);
+    void setExclusionPolicy(ExclusionPolicy policy);
+
+private Q_SLOTS:
+    void _q_actionTriggered();
+    void _q_actionHovered();
+    void _q_actionChanged();
+
+protected:
+     QGuiActionGroup(QGuiActionGroupPrivate &dd, QObject *parent);
+
+private:
+    Q_DISABLE_COPY(QGuiActionGroup)
+};
+
+#endif // QT_NO_ACTION
+
+QT_END_NAMESPACE
+
+#endif // QGUIACTIONGROUP_H
diff --git a/src/gui/kernel/qguiactiongroup_p.h b/src/gui/kernel/qguiactiongroup_p.h
new file mode 100644
index 0000000000..d2f41f26c4
--- /dev/null
+++ b/src/gui/kernel/qguiactiongroup_p.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWidgets module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGUIACTIONGROUP_P_H
+#define QGUIACTIONGROUP_P_H
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qtguiglobal_p.h>
+#include <QtGui/qguiactiongroup.h>
+#include <QtGui/qfont.h>
+#include <QtGui/private/qshortcutmap_p.h>
+#include "private/qobject_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_ACTION
+
+class Q_GUI_EXPORT QGuiActionGroupPrivate : public QObjectPrivate
+{
+    Q_DECLARE_PUBLIC(QGuiActionGroup)
+public:
+    enum Signal { Triggered, Hovered };
+
+    QGuiActionGroupPrivate();
+    ~QGuiActionGroupPrivate();
+
+    virtual void emitSignal(Signal, QGuiAction *) {}
+
+    QList<QGuiAction *> actions;
+    QPointer<QGuiAction> current;
+    uint enabled : 1;
+    uint visible : 1;
+    QGuiActionGroup::ExclusionPolicy exclusionPolicy = QGuiActionGroup::ExclusionPolicy::Exclusive;
+
+private:
+    void _q_actionTriggered();  //private slot
+    void _q_actionChanged();    //private slot
+    void _q_actionHovered();    //private slot
+};
+
+#endif // QT_NO_ACTION
+
+QT_END_NAMESPACE
+
+#endif // QACTIONGROUP_P_H
diff --git a/src/widgets/graphicsview/qgraphicswidget.h b/src/widgets/graphicsview/qgraphicswidget.h
index 8223b921c9..b757af5c0e 100644
--- a/src/widgets/graphicsview/qgraphicswidget.h
+++ b/src/widgets/graphicsview/qgraphicswidget.h
@@ -42,6 +42,7 @@
 
 #include <QtWidgets/qtwidgetsglobal.h>
 #include <QtGui/qfont.h>
+#include <QtWidgets/qaction.h>
 #include <QtWidgets/qgraphicslayoutitem.h>
 #include <QtWidgets/qgraphicsitem.h>
 #include <QtGui/qpalette.h>
diff --git a/src/widgets/kernel/qaction.cpp b/src/widgets/kernel/qaction.cpp
index 19ad65692b..e6082ab1c5 100644
--- a/src/widgets/kernel/qaction.cpp
+++ b/src/widgets/kernel/qaction.cpp
@@ -53,40 +53,14 @@
 #endif
 #include <private/qdebug_p.h>
 
-#define QAPP_CHECK(functionName) \
-    if (Q_UNLIKELY(!QCoreApplication::instance())) { \
-        qWarning("QAction: Initialize Q(Gui)Application before calling '" functionName "'."); \
-        return; \
-    }
 
 QT_BEGIN_NAMESPACE
 
-/*
-  internal: guesses a descriptive text from a text suited for a menu entry
- */
-static QString qt_strippedText(QString s)
-{
-    s.remove(QLatin1String("..."));
-    for (int i = 0; i < s.size(); ++i) {
-        if (s.at(i) == QLatin1Char('&'))
-            s.remove(i, 1);
-    }
-    return s.trimmed();
-}
-
-
-QActionPrivate::QActionPrivate() :
-#if QT_CONFIG(shortcut)
-    autorepeat(1),
-#endif
-    enabled(1), forceDisabled(0), visible(1), forceInvisible(0), checkable(0),
-    checked(0), separator(0), fontSet(false),
-    iconVisibleInMenu(-1), shortcutVisibleInContextMenu(-1)
+QShortcutMap::ContextMatcher QActionPrivate::contextMatcher() const
 {
+    return qWidgetShortcutContextMatcher;
 }
 
-QActionPrivate::~QActionPrivate() = default;
-
 bool QActionPrivate::showStatusText(QWidget *widget, const QString &str)
 {
 #if !QT_CONFIG(statustip)
@@ -102,84 +76,6 @@ bool QActionPrivate::showStatusText(QWidget *widget, const QString &str)
     return false;
 }
 
-void QActionPrivate::sendDataChanged()
-{
-    Q_Q(QAction);
-    QActionEvent e(QEvent::ActionChanged, q);
-    for (int i = 0; i < widgets.size(); ++i) {
-        QWidget *w = widgets.at(i);
-        QCoreApplication::sendEvent(w, &e);
-    }
-#if QT_CONFIG(graphicsview)
-    for (int i = 0; i < graphicsWidgets.size(); ++i) {
-        QGraphicsWidget *w = graphicsWidgets.at(i);
-        QCoreApplication::sendEvent(w, &e);
-    }
-#endif
-    QCoreApplication::sendEvent(q, &e);
-
-    emit q->changed();
-}
-
-#if QT_CONFIG(shortcut)
-void QActionPrivate::redoGrab(QShortcutMap &map)
-{
-    Q_Q(QAction);
-    if (shortcutId)
-        map.removeShortcut(shortcutId, q);
-    if (shortcut.isEmpty())
-        return;
-    shortcutId = map.addShortcut(q, shortcut, shortcutContext, qWidgetShortcutContextMatcher);
-    if (!enabled)
-        map.setShortcutEnabled(false, shortcutId, q);
-    if (!autorepeat)
-        map.setShortcutAutoRepeat(false, shortcutId, q);
-}
-
-void QActionPrivate::redoGrabAlternate(QShortcutMap &map)
-{
-    Q_Q(QAction);
-    for(int i = 0; i < alternateShortcutIds.count(); ++i) {
-        if (const int id = alternateShortcutIds.at(i))
-            map.removeShortcut(id, q);
-    }
-    alternateShortcutIds.clear();
-    if (alternateShortcuts.isEmpty())
-        return;
-    for(int i = 0; i < alternateShortcuts.count(); ++i) {
-        const QKeySequence& alternate = alternateShortcuts.at(i);
-        if (!alternate.isEmpty())
-            alternateShortcutIds.append(map.addShortcut(q, alternate, shortcutContext, qWidgetShortcutContextMatcher));
-        else
-            alternateShortcutIds.append(0);
-    }
-    if (!enabled) {
-        for(int i = 0; i < alternateShortcutIds.count(); ++i) {
-            const int id = alternateShortcutIds.at(i);
-            map.setShortcutEnabled(false, id, q);
-        }
-    }
-    if (!autorepeat) {
-        for(int i = 0; i < alternateShortcutIds.count(); ++i) {
-            const int id = alternateShortcutIds.at(i);
-            map.setShortcutAutoRepeat(false, id, q);
-        }
-    }
-}
-
-void QActionPrivate::setShortcutEnabled(bool enable, QShortcutMap &map)
-{
-    Q_Q(QAction);
-    if (shortcutId)
-        map.setShortcutEnabled(enable, shortcutId, q);
-    for(int i = 0; i < alternateShortcutIds.count(); ++i) {
-        if (const int id = alternateShortcutIds.at(i))
-            map.setShortcutEnabled(enable, id, q);
-    }
-}
-#endif // QT_NO_SHORTCUT
-
-
 /*!
     \class QAction
     \brief The QAction class provides an abstract user interface
@@ -323,12 +219,26 @@ QAction::QAction(const QIcon &icon, const QString &text, QObject* parent)
     \internal
 */
 QAction::QAction(QActionPrivate &dd, QObject *parent)
-    : QObject(dd, parent)
+    : QGuiAction(dd, parent)
+{
+}
+
+/*!
+  \reimp
+*/
+
+bool QAction::event(QEvent *e)
 {
     Q_D(QAction);
-    d->group = qobject_cast<QActionGroup *>(parent);
-    if (d->group)
-        d->group->addAction(this);
+    if (e->type() == QEvent::ActionChanged) {
+        for (auto w : qAsConst(d->widgets))
+            QCoreApplication::sendEvent(w, e);
+#if QT_CONFIG(graphicsview)
+        for (auto gw :  qAsConst(d->graphicsWidgets))
+            QCoreApplication::sendEvent(gw, e);
+#endif
+    }
+    return QGuiAction::event(e);
 }
 
 /*!
@@ -368,190 +278,6 @@ QList<QGraphicsWidget *> QAction::associatedGraphicsWidgets() const
 }
 #endif
 
-#if QT_CONFIG(shortcut)
-/*!
-    \property QAction::shortcut
-    \brief the action's primary shortcut key
-
-    Valid keycodes for this property can be found in \l Qt::Key and
-    \l Qt::Modifier. There is no default shortcut key.
-*/
-void QAction::setShortcut(const QKeySequence &shortcut)
-{
-    QAPP_CHECK("setShortcut");
-
-    Q_D(QAction);
-    if (d->shortcut == shortcut)
-        return;
-
-    d->shortcut = shortcut;
-    d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap);
-    d->sendDataChanged();
-}
-
-/*!
-    \since 4.2
-
-    Sets \a shortcuts as the list of shortcuts that trigger the
-    action. The first element of the list is the primary shortcut.
-
-    \sa shortcut
-*/
-void QAction::setShortcuts(const QList<QKeySequence> &shortcuts)
-{
-    Q_D(QAction);
-
-    QList <QKeySequence> listCopy = shortcuts;
-
-    QKeySequence primary;
-    if (!listCopy.isEmpty())
-        primary = listCopy.takeFirst();
-
-    if (d->shortcut == primary && d->alternateShortcuts == listCopy)
-        return;
-
-    QAPP_CHECK("setShortcuts");
-
-    d->shortcut = primary;
-    d->alternateShortcuts = listCopy;
-    d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap);
-    d->redoGrabAlternate(QGuiApplicationPrivate::instance()->shortcutMap);
-    d->sendDataChanged();
-}
-
-/*!
-    \since 4.2
-
-    Sets a platform dependent list of shortcuts based on the \a key.
-    The result of calling this function will depend on the currently running platform.
-    Note that more than one shortcut can assigned by this action.
-    If only the primary shortcut is required, use setShortcut instead.
-
-    \sa QKeySequence::keyBindings()
-*/
-void QAction::setShortcuts(QKeySequence::StandardKey key)
-{
-    QList <QKeySequence> list = QKeySequence::keyBindings(key);
-    setShortcuts(list);
-}
-
-/*!
-    Returns the primary shortcut.
-
-    \sa setShortcuts()
-*/
-QKeySequence QAction::shortcut() const
-{
-    Q_D(const QAction);
-    return d->shortcut;
-}
-
-/*!
-    \since 4.2
-
-    Returns the list of shortcuts, with the primary shortcut as
-    the first element of the list.
-
-    \sa setShortcuts()
-*/
-QList<QKeySequence> QAction::shortcuts() const
-{
-    Q_D(const QAction);
-    QList <QKeySequence> shortcuts;
-    if (!d->shortcut.isEmpty())
-        shortcuts << d->shortcut;
-    if (!d->alternateShortcuts.isEmpty())
-        shortcuts << d->alternateShortcuts;
-    return shortcuts;
-}
-
-/*!
-    \property QAction::shortcutContext
-    \brief the context for the action's shortcut
-
-    Valid values for this property can be found in \l Qt::ShortcutContext.
-    The default value is Qt::WindowShortcut.
-*/
-void QAction::setShortcutContext(Qt::ShortcutContext context)
-{
-    Q_D(QAction);
-    if (d->shortcutContext == context)
-        return;
-    QAPP_CHECK("setShortcutContext");
-    d->shortcutContext = context;
-    d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap);
-    d->redoGrabAlternate(QGuiApplicationPrivate::instance()->shortcutMap);
-    d->sendDataChanged();
-}
-
-Qt::ShortcutContext QAction::shortcutContext() const
-{
-    Q_D(const QAction);
-    return d->shortcutContext;
-}
-
-/*!
-    \property QAction::autoRepeat
-    \brief whether the action can auto repeat
-    \since 4.2
-
-    If true, the action will auto repeat when the keyboard shortcut
-    combination is held down, provided that keyboard auto repeat is
-    enabled on the system.
-    The default value is true.
-*/
-void QAction::setAutoRepeat(bool on)
-{
-    Q_D(QAction);
-    if (d->autorepeat == on)
-        return;
-    QAPP_CHECK("setAutoRepeat");
-    d->autorepeat = on;
-    d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap);
-    d->redoGrabAlternate(QGuiApplicationPrivate::instance()->shortcutMap);
-    d->sendDataChanged();
-}
-
-bool QAction::autoRepeat() const
-{
-    Q_D(const QAction);
-    return d->autorepeat;
-}
-#endif // QT_NO_SHORTCUT
-
-/*!
-    \property QAction::font
-    \brief the action's font
-
-    The font property is used to render the text set on the
-    QAction. The font will can be considered a hint as it will not be
-    consulted in all cases based upon application and style.
-
-    By default, this property contains the application's default font.
-
-    \sa QAction::setText(), QStyle
-*/
-void QAction::setFont(const QFont &font)
-{
-    Q_D(QAction);
-    if (d->font == font)
-        return;
-
-    d->fontSet = true;
-    d->font = font;
-    d->sendDataChanged();
-}
-
-QFont QAction::font() const
-{
-    Q_D(const QAction);
-    return d->font;
-}
-
-
-/*!
-    Destroys the object and frees allocated resources.
-*/
 QAction::~QAction()
 {
     Q_D(QAction);
@@ -565,76 +291,17 @@ QAction::~QAction()
         w->removeAction(this);
     }
 #endif
-    if (d->group)
-        d->group->removeAction(this);
-#if QT_CONFIG(shortcut)
-    if (d->shortcutId && qApp) {
-        QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(d->shortcutId, this);
-        for(int i = 0; i < d->alternateShortcutIds.count(); ++i) {
-            const int id = d->alternateShortcutIds.at(i);
-            QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(id, this);
-        }
-    }
-#endif
-}
-
-/*!
-  Sets this action group to \a group. The action will be automatically
-  added to the group's list of actions.
-
-  Actions within the group will be mutually exclusive.
-
-  \sa QActionGroup, QAction::actionGroup()
-*/
-void QAction::setActionGroup(QActionGroup *group)
-{
-    Q_D(QAction);
-    if(group == d->group)
-        return;
-
-    if(d->group)
-        d->group->removeAction(this);
-    d->group = group;
-    if(group)
-        group->addAction(this);
-    d->sendDataChanged();
 }
 
 /*!
-  Returns the action group for this action. If no action group manages
-  this action then 0 will be returned.
+   Returns the action group for this action. If no action group manages
+   this action then \nullptr will be returned.
 
-  \sa QActionGroup, QAction::setActionGroup()
-*/
+   \sa QActionGroup, QAction::setActionGroup()
+ */
 QActionGroup *QAction::actionGroup() const
 {
-    Q_D(const QAction);
-    return d->group;
-}
-
-
-/*!
-    \property QAction::icon
-    \brief the action's icon
-
-    In toolbars, the icon is used as the tool button icon; in menus,
-    it is displayed to the left of the menu text. There is no default
-    icon.
-
-    If a null icon (QIcon::isNull()) is passed into this function,
-    the icon of the action is cleared.
-*/
-void QAction::setIcon(const QIcon &icon)
-{
-    Q_D(QAction);
-    d->icon = icon;
-    d->sendDataChanged();
-}
-
-QIcon QAction::icon() const
-{
-    Q_D(const QAction);
-    return d->icon;
+    return static_cast<QActionGroup *>(guiActionGroup());
 }
 
 #if QT_CONFIG(menu)
@@ -666,460 +333,6 @@ void QAction::setMenu(QMenu *menu)
 }
 #endif // QT_CONFIG(menu)
 
-/*!
-  If \a b is true then this action will be considered a separator.
-
-  How a separator is represented depends on the widget it is inserted
-  into. Under most circumstances the text, submenu, and icon will be
-  ignored for separator actions.
-
-  \sa QAction::isSeparator()
-*/
-void QAction::setSeparator(bool b)
-{
-    Q_D(QAction);
-    if (d->separator == b)
-        return;
-
-    d->separator = b;
-    d->sendDataChanged();
-}
-
-/*!
-  Returns \c true if this action is a separator action; otherwise it
-  returns \c false.
-
-  \sa QAction::setSeparator()
-*/
-bool QAction::isSeparator() const
-{
-    Q_D(const QAction);
-    return d->separator;
-}
-
-/*!
-    \property QAction::text
-    \brief the action's descriptive text
-
-    If the action is added to a menu, the menu option will consist of
-    the icon (if there is one), the text, and the shortcut (if there
-    is one). If the text is not explicitly set in the constructor, or
-    by using setText(), the action's description icon text will be
-    used as text. There is no default text.
-
-    \sa iconText
-*/
-void QAction::setText(const QString &text)
-{
-    Q_D(QAction);
-    if (d->text == text)
-        return;
-
-    d->text = text;
-    d->sendDataChanged();
-}
-
-QString QAction::text() const
-{
-    Q_D(const QAction);
-    QString s = d->text;
-    if(s.isEmpty()) {
-        s = d->iconText;
-        s.replace(QLatin1Char('&'), QLatin1String("&&"));
-    }
-    return s;
-}
-
-
-
-
-
-/*!
-    \property QAction::iconText
-    \brief the action's descriptive icon text
-
-    If QToolBar::toolButtonStyle is set to a value that permits text to
-    be displayed, the text defined held in this property appears as a
-    label in the relevant tool button.
-
-    It also serves as the default text in menus and tooltips if the action
-    has not been defined with setText() or setToolTip(), and will
-    also be used in toolbar buttons if no icon has been defined using setIcon().
-
-    If the icon text is not explicitly set, the action's normal text will be
-    used for the icon text.
-
-    By default, this property contains an empty string.
-
-    \sa setToolTip(), setStatusTip()
-*/
-void QAction::setIconText(const QString &text)
-{
-    Q_D(QAction);
-    if (d->iconText == text)
-        return;
-
-    d->iconText = text;
-    d->sendDataChanged();
-}
-
-QString QAction::iconText() const
-{
-    Q_D(const QAction);
-    if (d->iconText.isEmpty())
-        return qt_strippedText(d->text);
-    return d->iconText;
-}
-
-/*!
-    \property QAction::toolTip
-    \brief the action's tooltip
-
-    This text is used for the tooltip. If no tooltip is specified,
-    the action's text is used.
-
-    By default, this property contains the action's text.
-
-    \sa setStatusTip(), setShortcut()
-*/
-void QAction::setToolTip(const QString &tooltip)
-{
-    Q_D(QAction);
-    if (d->tooltip == tooltip)
-        return;
-
-    d->tooltip = tooltip;
-    d->sendDataChanged();
-}
-
-QString QAction::toolTip() const
-{
-    Q_D(const QAction);
-    if (d->tooltip.isEmpty()) {
-        if (!d->text.isEmpty())
-            return qt_strippedText(d->text);
-        return qt_strippedText(d->iconText);
-    }
-    return d->tooltip;
-}
-
-/*!
-    \property QAction::statusTip
-    \brief the action's status tip
-
-    The status tip is displayed on all status bars provided by the
-    action's top-level parent widget.
-
-    By default, this property contains an empty string.
-
-    \sa setToolTip(), showStatusText()
-*/
-void QAction::setStatusTip(const QString &statustip)
-{
-    Q_D(QAction);
-    if (d->statustip == statustip)
-        return;
-
-    d->statustip = statustip;
-    d->sendDataChanged();
-}
-
-QString QAction::statusTip() const
-{
-    Q_D(const QAction);
-    return d->statustip;
-}
-
-/*!
-    \property QAction::whatsThis
-    \brief the action's "What's This?" help text
-
-    The "What's This?" text is used to provide a brief description of
-    the action. The text may contain rich text. There is no default
-    "What's This?" text.
-
-    \sa QWhatsThis
-*/
-void QAction::setWhatsThis(const QString &whatsthis)
-{
-    Q_D(QAction);
-    if (d->whatsthis == whatsthis)
-        return;
-
-    d->whatsthis = whatsthis;
-    d->sendDataChanged();
-}
-
-QString QAction::whatsThis() const
-{
-    Q_D(const QAction);
-    return d->whatsthis;
-}
-
-/*!
-    \enum QAction::Priority
-    \since 4.6
-
-    This enum defines priorities for actions in user interface.
-
-    \value LowPriority The action should not be prioritized in
-    the user interface.
-
-    \value NormalPriority
-
-    \value HighPriority The action should be prioritized in
-    the user interface.
-
-    \sa priority
-*/
-
-
-/*!
-    \property QAction::priority
-    \since 4.6
-
-    \brief the actions's priority in the user interface.
-
-    This property can be set to indicate how the action should be prioritized
-    in the user interface.
-
-    For instance, when toolbars have the Qt::ToolButtonTextBesideIcon
-    mode set, then actions with LowPriority will not show the text
-    labels.
-*/
-void QAction::setPriority(Priority priority)
-{
-    Q_D(QAction);
-    if (d->priority == priority)
-        return;
-
-    d->priority = priority;
-    d->sendDataChanged();
-}
-
-QAction::Priority QAction::priority() const
-{
-    Q_D(const QAction);
-    return d->priority;
-}
-
-/*!
-    \property QAction::checkable
-    \brief whether the action is a checkable action
-
-    A checkable action is one which has an on/off state. For example,
-    in a word processor, a Bold toolbar button may be either on or
-    off. An action which is not a toggle action is a command action;
-    a command action is simply executed, e.g. file save.
-    By default, this property is \c false.
-
-    In some situations, the state of one toggle action should depend
-    on the state of others. For example, "Left Align", "Center" and
-    "Right Align" toggle actions are mutually exclusive. To achieve
-    exclusive toggling, add the relevant toggle actions to a
-    QActionGroup with the QActionGroup::exclusive property set to
-    true.
-
-    \sa QAction::setChecked()
-*/
-void QAction::setCheckable(bool b)
-{
-    Q_D(QAction);
-    if (d->checkable == b)
-        return;
-
-    d->checkable = b;
-    d->checked = false;
-    d->sendDataChanged();
-}
-
-bool QAction::isCheckable() const
-{
-    Q_D(const QAction);
-    return d->checkable;
-}
-
-/*!
-    \fn void QAction::toggle()
-
-    This is a convenience function for the \l checked property.
-    Connect to it to change the checked state to its opposite state.
-*/
-void QAction::toggle()
-{
-    Q_D(QAction);
-    setChecked(!d->checked);
-}
-
-/*!
-    \property QAction::checked
-    \brief whether the action is checked.
-
-    Only checkable actions can be checked.  By default, this is false
-    (the action is unchecked).
-
-    \note The notifier signal for this property is toggled(). As toggling
-    a QAction changes its state, it will also emit a changed() signal.
-
-    \sa checkable, toggled()
-*/
-void QAction::setChecked(bool b)
-{
-    Q_D(QAction);
-    if (!d->checkable || d->checked == b)
-        return;
-
-    QPointer<QAction> guard(this);
-    d->checked = b;
-    d->sendDataChanged();
-    if (guard)
-        emit toggled(b);
-}
-
-bool QAction::isChecked() const
-{
-    Q_D(const QAction);
-    return d->checked;
-}
-
-/*!
-    \fn void QAction::setDisabled(bool b)
-
-    This is a convenience function for the \l enabled property, that
-    is useful for signals--slots connections. If \a b is true the
-    action is disabled; otherwise it is enabled.
-*/
-
-/*!
-    \property QAction::enabled
-    \brief whether the action is enabled
-
-    Disabled actions cannot be chosen by the user. They do not
-    disappear from menus or toolbars, but they are displayed in a way
-    which indicates that they are unavailable. For example, they might
-    be displayed using only shades of gray.
-
-    \uicontrol{What's This?} help on disabled actions is still available, provided
-    that the QAction::whatsThis property is set.
-
-    An action will be disabled when all widgets to which it is added
-    (with QWidget::addAction()) are disabled or not visible. When an
-    action is disabled, it is not possible to trigger it through its
-    shortcut.
-
-    By default, this property is \c true (actions are enabled).
-
-    \sa text
-*/
-void QAction::setEnabled(bool b)
-{
-    Q_D(QAction);
-    if (b == d->enabled && b != d->forceDisabled)
-        return;
-    d->forceDisabled = !b;
-    if (b && (!d->visible || (d->group && !d->group->isEnabled())))
-        return;
-    QAPP_CHECK("setEnabled");
-    d->enabled = b;
-#if QT_CONFIG(shortcut)
-    d->setShortcutEnabled(b, QGuiApplicationPrivate::instance()->shortcutMap);
-#endif
-    d->sendDataChanged();
-}
-
-bool QAction::isEnabled() const
-{
-    Q_D(const QAction);
-    return d->enabled;
-}
-
-/*!
-    \property QAction::visible
-    \brief whether the action can be seen (e.g. in menus and toolbars)
-
-    If \e visible is true the action can be seen (e.g. in menus and
-    toolbars) and chosen by the user; if \e visible is false the
-    action cannot be seen or chosen by the user.
-
-    Actions which are not visible are \e not grayed out; they do not
-    appear at all.
-
-    By default, this property is \c true (actions are visible).
-*/
-void QAction::setVisible(bool b)
-{
-    Q_D(QAction);
-    if (b == d->visible && b != d->forceInvisible)
-        return;
-    QAPP_CHECK("setVisible");
-    d->forceInvisible = !b;
-    d->visible = b;
-    d->enabled = b && !d->forceDisabled && (!d->group || d->group->isEnabled()) ;
-#if QT_CONFIG(shortcut)
-    d->setShortcutEnabled(d->enabled, QGuiApplicationPrivate::instance()->shortcutMap);
-#endif
-    d->sendDataChanged();
-}
-
-
-bool QAction::isVisible() const
-{
-    Q_D(const QAction);
-    return d->visible;
-}
-
-/*!
-  \reimp
-*/
-bool
-QAction::event(QEvent *e)
-{
-#if QT_CONFIG(shortcut)
-    if (e->type() == QEvent::Shortcut) {
-        QShortcutEvent *se = static_cast<QShortcutEvent *>(e);
-        Q_ASSERT_X(se->key() == d_func()->shortcut || d_func()->alternateShortcuts.contains(se->key()),
-                   "QAction::event",
-                   "Received shortcut event from incorrect shortcut");
-        if (se->isAmbiguous())
-            qWarning("QAction::event: Ambiguous shortcut overload: %s", se->key().toString(QKeySequence::NativeText).toLatin1().constData());
-        else
-            activate(Trigger);
-        return true;
-    }
-#endif
-    return QObject::event(e);
-}
-
-/*!
-  Returns the user data as set in QAction::setData.
-
-  \sa setData()
-*/
-QVariant
-QAction::data() const
-{
-    Q_D(const QAction);
-    return d->userData;
-}
-
-/*!
-  \fn void QAction::setData(const QVariant &userData)
-
-  Sets the action's internal data to the given \a userData.
-
-  \sa data()
-*/
-void
-QAction::setData(const QVariant &data)
-{
-    Q_D(QAction);
-    if (d->userData == data)
-        return;
-    d->userData = data;
-    d->sendDataChanged();
-}
-
-
 /*!
   Updates the relevant status bar for the \a widget specified by sending a
   QStatusTipEvent to its parent widget. Returns \c true if an event was sent;
@@ -1135,233 +348,6 @@ QAction::showStatusText(QWidget *widget)
     return d_func()->showStatusText(widget, statusTip());
 }
 
-/*!
-  Sends the relevant signals for ActionEvent \a event.
-
-  Action based widgets use this API to cause the QAction
-  to emit signals as well as emitting their own.
-*/
-void QAction::activate(ActionEvent event)
-{
-    Q_D(QAction);
-    if(event == Trigger) {
-        QPointer<QObject> guard = this;
-        if(d->checkable) {
-            // the checked action of an exclusive group may not be unchecked
-            if (d->checked && (d->group
-                               && d->group->exclusionPolicy() == QActionGroup::ExclusionPolicy::Exclusive
-                               && d->group->checkedAction() == this)) {
-                if (!guard.isNull())
-                    emit triggered(true);
-                return;
-            }
-            setChecked(!d->checked);
-        }
-        if (!guard.isNull())
-            emit triggered(d->checked);
-    } else if(event == Hover) {
-        emit hovered();
-    }
-}
-
-/*!
-    \fn void QAction::triggered(bool checked)
-
-    This signal is emitted when an action is activated by the user;
-    for example, when the user clicks a menu option, toolbar button,
-    or presses an action's shortcut key combination, or when trigger()
-    was called. Notably, it is \e not emitted when setChecked() or
-    toggle() is called.
-
-    If the action is checkable, \a checked is true if the action is
-    checked, or false if the action is unchecked.
-
-    \sa QAction::activate(), QAction::toggled(), checked
-*/
-
-/*!
-    \fn void QAction::toggled(bool checked)
-
-    This signal is emitted whenever a checkable action changes its
-    isChecked() status. This can be the result of a user interaction,
-    or because setChecked() was called. As setChecked() changes the
-    QAction, it emits changed() in addition to toggled().
-
-    \a checked is true if the action is checked, or false if the
-    action is unchecked.
-
-    \sa QAction::activate(), QAction::triggered(), checked
-*/
-
-/*!
-    \fn void QAction::hovered()
-
-    This signal is emitted when an action is highlighted by the user;
-    for example, when the user pauses with the cursor over a menu option,
-    toolbar button, or presses an action's shortcut key combination.
-
-    \sa QAction::activate()
-*/
-
-/*!
-    \fn void QAction::changed()
-
-    This signal is emitted when an action has changed. If you
-    are only interested in actions in a given widget, you can
-    watch for QWidget::actionEvent() sent with an
-    QEvent::ActionChanged.
-
-    \sa QWidget::actionEvent()
-*/
-
-/*!
-    \enum QAction::ActionEvent
-
-    This enum type is used when calling QAction::activate()
-
-    \value Trigger this will cause the QAction::triggered() signal to be emitted.
-
-    \value Hover this will cause the QAction::hovered() signal to be emitted.
-*/
-
-/*!
-    \property QAction::menuRole
-    \brief the action's menu role
-    \since 4.2
-
-    This indicates what role the action serves in the application menu on
-    \macos. By default all actions have the TextHeuristicRole, which means that
-    the action is added based on its text (see QMenuBar for more information).
-
-    The menu role can only be changed before the actions are put into the menu
-    bar in \macos (usually just before the first application window is
-    shown).
-*/
-void QAction::setMenuRole(MenuRole menuRole)
-{
-    Q_D(QAction);
-    if (d->menuRole == menuRole)
-        return;
-
-    d->menuRole = menuRole;
-    d->sendDataChanged();
-}
-
-QAction::MenuRole QAction::menuRole() const
-{
-    Q_D(const QAction);
-    return d->menuRole;
-}
-
-/*!
-    \property QAction::iconVisibleInMenu
-    \brief Whether or not an action should show an icon in a menu
-    \since 4.4
-
-    In some applications, it may make sense to have actions with icons in the
-    toolbar, but not in menus. If true, the icon (if valid) is shown in the menu, when it
-    is false, it is not shown.
-
-    The default is to follow whether the Qt::AA_DontShowIconsInMenus attribute
-    is set for the application. Explicitly settings this property overrides
-    the presence (or abscence) of the attribute.
-
-    For example:
-    \snippet code/src_gui_kernel_qaction.cpp 0
-
-    \sa QAction::icon, QCoreApplication::setAttribute()
-*/
-void QAction::setIconVisibleInMenu(bool visible)
-{
-    Q_D(QAction);
-    if (d->iconVisibleInMenu == -1 || visible != bool(d->iconVisibleInMenu)) {
-        int oldValue = d->iconVisibleInMenu;
-        d->iconVisibleInMenu = visible;
-        // Only send data changed if we really need to.
-        if (oldValue != -1
-            || visible == !QCoreApplication::testAttribute(Qt::AA_DontShowIconsInMenus)) {
-            d->sendDataChanged();
-        }
-    }
-}
-
-bool QAction::isIconVisibleInMenu() const
-{
-    Q_D(const QAction);
-    if (d->iconVisibleInMenu == -1) {
-        return !QCoreApplication::testAttribute(Qt::AA_DontShowIconsInMenus);
-    }
-    return d->iconVisibleInMenu;
-}
-
-/*!
-    \property QAction::shortcutVisibleInContextMenu
-    \brief Whether or not an action should show a shortcut in a context menu
-    \since 5.10
-
-    In some applications, it may make sense to have actions with shortcuts in
-    context menus. If true, the shortcut (if valid) is shown when the action is
-    shown via a context menu, when it is false, it is not shown.
-
-    The default is to follow whether the Qt::AA_DontShowShortcutsInContextMenus attribute
-    is set for the application, falling back to the widget style hint.
-    Explicitly setting this property overrides the presence (or abscence) of the attribute.
-
-    \sa QAction::shortcut, QCoreApplication::setAttribute()
-*/
-void QAction::setShortcutVisibleInContextMenu(bool visible)
-{
-    Q_D(QAction);
-    if (d->shortcutVisibleInContextMenu == -1 || visible != bool(d->shortcutVisibleInContextMenu)) {
-        int oldValue = d->shortcutVisibleInContextMenu;
-        d->shortcutVisibleInContextMenu = visible;
-        // Only send data changed if we really need to.
-        if (oldValue != -1
-            || visible == !QCoreApplication::testAttribute(Qt::AA_DontShowShortcutsInContextMenus)) {
-            d->sendDataChanged();
-        }
-    }
-}
-
-bool QAction::isShortcutVisibleInContextMenu() const
-{
-    Q_D(const QAction);
-    if (d->shortcutVisibleInContextMenu == -1) {
-        return !QCoreApplication::testAttribute(Qt::AA_DontShowShortcutsInContextMenus)
-            && QGuiApplication::styleHints()->showShortcutsInContextMenus();
-    }
-    return d->shortcutVisibleInContextMenu;
-}
-
-#ifndef QT_NO_DEBUG_STREAM
-Q_WIDGETS_EXPORT QDebug operator<<(QDebug d, const QAction *action)
-{
-    QDebugStateSaver saver(d);
-    d.nospace();
-    d << "QAction(" << static_cast<const void *>(action);
-    if (action) {
-        d << " text=" << action->text();
-        if (!action->toolTip().isEmpty())
-            d << " toolTip=" << action->toolTip();
-        if (action->isCheckable())
-            d << " checked=" << action->isChecked();
-#if QT_CONFIG(shortcut)
-        if (!action->shortcut().isEmpty())
-            d << " shortcut=" << action->shortcut();
-#endif
-        d << " menuRole=";
-        QtDebugUtils::formatQEnum(d, action->menuRole());
-        d << " visible=" << action->isVisible();
-    } else {
-        d << '0';
-    }
-    d << ')';
-    return d;
-}
-#endif // QT_NO_DEBUG_STREAM
-
 QT_END_NAMESPACE
 
-#include "moc_qaction.cpp"
-
 #endif // QT_NO_ACTION
diff --git a/src/widgets/kernel/qaction.h b/src/widgets/kernel/qaction.h
index f7693f4dde..725461f546 100644
--- a/src/widgets/kernel/qaction.h
+++ b/src/widgets/kernel/qaction.h
@@ -41,11 +41,11 @@
 #define QACTION_H
 
 #include <QtWidgets/qtwidgetsglobal.h>
+#include <QtGui/qguiaction.h>
 #include <QtGui/qkeysequence.h>
 #include <QtCore/qstring.h>
 #include <QtWidgets/qwidget.h>
 #include <QtCore/qvariant.h>
-#include <QtGui/qicon.h>
 
 QT_BEGIN_NAMESPACE
 
@@ -57,121 +57,25 @@ class QActionGroup;
 class QActionPrivate;
 class QGraphicsWidget;
 
-class Q_WIDGETS_EXPORT QAction : public QObject
+class Q_WIDGETS_EXPORT QAction : public QGuiAction
 {
     Q_OBJECT
     Q_DECLARE_PRIVATE(QAction)
-
-    Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable NOTIFY changed)
-    Q_PROPERTY(bool checked READ isChecked WRITE setChecked DESIGNABLE isCheckable NOTIFY toggled)
-    Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY changed)
-    Q_PROPERTY(QIcon icon READ icon WRITE setIcon NOTIFY changed)
-    Q_PROPERTY(QString text READ text WRITE setText NOTIFY changed)
-    Q_PROPERTY(QString iconText READ iconText WRITE setIconText NOTIFY changed)
-    Q_PROPERTY(QString toolTip READ toolTip WRITE setToolTip NOTIFY changed)
-    Q_PROPERTY(QString statusTip READ statusTip WRITE setStatusTip NOTIFY changed)
-    Q_PROPERTY(QString whatsThis READ whatsThis WRITE setWhatsThis NOTIFY changed)
-    Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY changed)
-#if QT_CONFIG(shortcut)
-    Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut NOTIFY changed)
-    Q_PROPERTY(Qt::ShortcutContext shortcutContext READ shortcutContext WRITE setShortcutContext NOTIFY changed)
-    Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat NOTIFY changed)
-#endif
-    Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY changed)
-    Q_PROPERTY(MenuRole menuRole READ menuRole WRITE setMenuRole NOTIFY changed)
-    Q_PROPERTY(bool iconVisibleInMenu READ isIconVisibleInMenu WRITE setIconVisibleInMenu NOTIFY changed)
-    Q_PROPERTY(bool shortcutVisibleInContextMenu READ isShortcutVisibleInContextMenu WRITE setShortcutVisibleInContextMenu NOTIFY changed)
-    Q_PROPERTY(Priority priority READ priority WRITE setPriority)
-
 public:
-    // note this is copied into qplatformmenu.h, which must stay in sync
-    enum MenuRole { NoRole = 0, TextHeuristicRole, ApplicationSpecificRole, AboutQtRole,
-                    AboutRole, PreferencesRole, QuitRole };
-    Q_ENUM(MenuRole)
-    enum Priority { LowPriority = 0,
-                    NormalPriority = 128,
-                    HighPriority = 256};
-    Q_ENUM(Priority)
-    explicit QAction(QObject *parent = nullptr);
-    explicit QAction(const QString &text, QObject *parent = nullptr);
-    explicit QAction(const QIcon &icon, const QString &text, QObject *parent = nullptr);
-
+    QAction(QObject* parent = nullptr);
+    QAction(const QString &text, QObject* parent = nullptr);
+    QAction(const QIcon &icon, const QString &text, QObject* parent);
     ~QAction();
 
-    void setActionGroup(QActionGroup *group);
     QActionGroup *actionGroup() const;
-    void setIcon(const QIcon &icon);
-    QIcon icon() const;
-
-    void setText(const QString &text);
-    QString text() const;
-
-    void setIconText(const QString &text);
-    QString iconText() const;
-
-    void setToolTip(const QString &tip);
-    QString toolTip() const;
-
-    void setStatusTip(const QString &statusTip);
-    QString statusTip() const;
-
-    void setWhatsThis(const QString &what);
-    QString whatsThis() const;
-
-    void setPriority(Priority priority);
-    Priority priority() const;
 
 #if QT_CONFIG(menu)
     QMenu *menu() const;
     void setMenu(QMenu *menu);
 #endif
 
-    void setSeparator(bool b);
-    bool isSeparator() const;
-
-#if QT_CONFIG(shortcut)
-    void setShortcut(const QKeySequence &shortcut);
-    QKeySequence shortcut() const;
-
-    void setShortcuts(const QList<QKeySequence> &shortcuts);
-    void setShortcuts(QKeySequence::StandardKey);
-    QList<QKeySequence> shortcuts() const;
-
-    void setShortcutContext(Qt::ShortcutContext context);
-    Qt::ShortcutContext shortcutContext() const;
-
-    void setAutoRepeat(bool);
-    bool autoRepeat() const;
-#endif
-
-    void setFont(const QFont &font);
-    QFont font() const;
-
-    void setCheckable(bool);
-    bool isCheckable() const;
-
-    QVariant data() const;
-    void setData(const QVariant &var);
-
-    bool isChecked() const;
-
-    bool isEnabled() const;
-
-    bool isVisible() const;
-
-    enum ActionEvent { Trigger, Hover };
-    void activate(ActionEvent event);
     bool showStatusText(QWidget *widget = nullptr);
 
-    void setMenuRole(MenuRole menuRole);
-    MenuRole menuRole() const;
-
-    void setIconVisibleInMenu(bool visible);
-    bool isIconVisibleInMenu() const;
-
-    void setShortcutVisibleInContextMenu(bool show);
-    bool isShortcutVisibleInContextMenu() const;
-
     QWidget *parentWidget() const;
 
     QList<QWidget *> associatedWidgets() const;
@@ -180,30 +84,14 @@ public:
 #endif
 
 protected:
-    bool event(QEvent *) override;
     QAction(QActionPrivate &dd, QObject *parent);
-
-public Q_SLOTS:
-    void trigger() { activate(Trigger); }
-    void hover() { activate(Hover); }
-    void setChecked(bool);
-    void toggle();
-    void setEnabled(bool);
-    inline void setDisabled(bool b) { setEnabled(!b); }
-    void setVisible(bool);
-
-Q_SIGNALS:
-    void changed();
-    void triggered(bool checked = false);
-    void hovered();
-    void toggled(bool);
+    bool event(QEvent *) override;
 
 private:
     Q_DISABLE_COPY(QAction)
 
     friend class QGraphicsWidget;
     friend class QWidget;
-    friend class QActionGroup;
     friend class QMenu;
     friend class QMenuPrivate;
     friend class QMenuBar;
diff --git a/src/widgets/kernel/qaction_p.h b/src/widgets/kernel/qaction_p.h
index 6b6ca8076f..2583607e75 100644
--- a/src/widgets/kernel/qaction_p.h
+++ b/src/widgets/kernel/qaction_p.h
@@ -52,6 +52,7 @@
 //
 
 #include <QtWidgets/private/qtwidgetsglobal_p.h>
+#include <QtGui/private/qguiaction_p.h>
 #include "QtWidgets/qaction.h"
 #if QT_CONFIG(menu)
 #include "QtWidgets/qmenu.h"
@@ -68,12 +69,13 @@ QT_BEGIN_NAMESPACE
 
 class QShortcutMap;
 
-class Q_WIDGETS_EXPORT QActionPrivate : public QObjectPrivate
+class Q_WIDGETS_EXPORT QActionPrivate : public QGuiActionPrivate
 {
     Q_DECLARE_PUBLIC(QAction)
 public:
-    QActionPrivate();
-    ~QActionPrivate();
+    QActionPrivate() = default;
+
+    QShortcutMap::ContextMatcher contextMatcher() const override;
 
     static QActionPrivate *get(QAction *q)
     {
@@ -82,50 +84,11 @@ public:
 
     bool showStatusText(QWidget *w, const QString &str);
 
-    QPointer<QActionGroup> group;
-    QString text;
-    QString iconText;
-    QIcon icon;
-    QString tooltip;
-    QString statustip;
-    QString whatsthis;
-#if QT_CONFIG(shortcut)
-    QKeySequence shortcut;
-    QList<QKeySequence> alternateShortcuts;
-#endif
-    QVariant userData;
-#if QT_CONFIG(shortcut)
-    int shortcutId = 0;
-    QVector<int> alternateShortcutIds;
-    Qt::ShortcutContext shortcutContext = Qt::WindowShortcut;
-    uint autorepeat : 1;
-#endif
-    QFont font;
     QPointer<QMenu> menu;
-    uint enabled : 1, forceDisabled : 1;
-    uint visible : 1, forceInvisible : 1;
-    uint checkable : 1;
-    uint checked : 1;
-    uint separator : 1;
-    uint fontSet : 1;
-
-    int iconVisibleInMenu : 2;  // Only has values -1, 0, and 1
-    int shortcutVisibleInContextMenu : 2; // Only has values -1, 0, and 1
-
-    QAction::MenuRole menuRole = QAction::TextHeuristicRole;
-    QAction::Priority priority = QAction::NormalPriority;
-
     QWidgetList widgets;
 #if QT_CONFIG(graphicsview)
     QList<QGraphicsWidget *> graphicsWidgets;
 #endif
-#if QT_CONFIG(shortcut)
-    void redoGrab(QShortcutMap &map);
-    void redoGrabAlternate(QShortcutMap &map);
-    void setShortcutEnabled(bool enable, QShortcutMap &map);
-#endif // QT_NO_SHORTCUT
-
-    void sendDataChanged();
 };
 
 #endif // QT_NO_ACTION
diff --git a/src/widgets/kernel/qactiongroup.cpp b/src/widgets/kernel/qactiongroup.cpp
index 1d9213de0c..56e1df6b23 100644
--- a/src/widgets/kernel/qactiongroup.cpp
+++ b/src/widgets/kernel/qactiongroup.cpp
@@ -38,70 +38,34 @@
 ****************************************************************************/
 
 #include "qactiongroup.h"
+#include <QtGui/private/qguiactiongroup_p.h>
 
 #ifndef QT_NO_ACTION
 
-#include "qaction_p.h"
-#include "qevent.h"
-#include "qlist.h"
+#include "qaction.h"
 
 QT_BEGIN_NAMESPACE
 
-class QActionGroupPrivate : public QObjectPrivate
+class QActionGroupPrivate : public QGuiActionGroupPrivate
 {
     Q_DECLARE_PUBLIC(QActionGroup)
 public:
-    QActionGroupPrivate() : enabled(1),
-                            visible(1),
-                            exclusionPolicy(QActionGroup::ExclusionPolicy::Exclusive)
-    {
-    }
-    QList<QAction *> actions;
-    QPointer<QAction> current;
-    uint enabled : 1;
-    uint visible : 1;
-    QActionGroup::ExclusionPolicy exclusionPolicy;
-
-private:
-    void _q_actionTriggered();  //private slot
-    void _q_actionChanged();    //private slot
-    void _q_actionHovered();    //private slot
+     void emitSignal(Signal, QGuiAction *) override;
 };
 
-void QActionGroupPrivate::_q_actionChanged()
+void QActionGroupPrivate::emitSignal(Signal s, QGuiAction *action)
 {
     Q_Q(QActionGroup);
-    QAction *action = qobject_cast<QAction*>(q->sender());
-    Q_ASSERT_X(action != nullptr, "QActionGroup::_q_actionChanged", "internal error");
-    if (exclusionPolicy != QActionGroup::ExclusionPolicy::None) {
-        if (action->isChecked()) {
-            if (action != current) {
-                if(current)
-                    current->setChecked(false);
-                current = action;
-            }
-        } else if (action == current) {
-            current = 0;
-        }
+    switch (s) {
+    case QGuiActionGroupPrivate::Triggered:
+        emit q->triggered(static_cast<QAction *>(action));
+        break;
+    case QGuiActionGroupPrivate::Hovered:
+        emit q->hovered(static_cast<QAction *>(action));
+        break;
     }
 }
 
-void QActionGroupPrivate::_q_actionTriggered()
-{
-    Q_Q(QActionGroup);
-    QAction *action = qobject_cast<QAction*>(q->sender());
-    Q_ASSERT_X(action != nullptr, "QActionGroup::_q_actionTriggered", "internal error");
-    emit q->triggered(action);
-}
-
-void QActionGroupPrivate::_q_actionHovered()
-{
-    Q_Q(QActionGroup);
-    QAction *action = qobject_cast<QAction*>(q->sender());
-    Q_ASSERT_X(action != nullptr, "QActionGroup::_q_actionHovered", "internal error");
-    emit q->hovered(action);
-}
-
 /*!
     \class QActionGroup
     \brief The QActionGroup class groups actions together.
@@ -153,27 +117,6 @@ void QActionGroupPrivate::_q_actionHovered()
     \sa QAction
 */
 
-/*!
-    \enum QActionGroup::ExclusionPolicy
-
-    This enum specifies the different policies that can be used to
-    control how the group performs exclusive checking on checkable actions.
-
-    \value None
-           The actions in the group can be checked independently of each other.
-
-    \value Exclusive
-           Exactly one action can be checked at any one time.
-           This is the default policy.
-
-    \value ExclusiveOptional
-           At most one action can be checked at any one time. The actions
-           can also be all unchecked.
-
-    \sa exclusionPolicy
-    \since 5.14
-*/
-
 /*!
     Constructs an action group for the \a parent object.
 
@@ -182,53 +125,24 @@ void QActionGroupPrivate::_q_actionHovered()
     but allow unchecking the active action call instead
     setExclusionPolicy(QActionGroup::ExclusionPolicy::ExclusiveOptional)
 */
-QActionGroup::QActionGroup(QObject* parent) : QObject(*new QActionGroupPrivate, parent)
+QActionGroup::QActionGroup(QObject* parent) :
+    QGuiActionGroup(*new QActionGroupPrivate, parent)
 {
 }
 
 /*!
     Destroys the action group.
 */
-QActionGroup::~QActionGroup()
+QActionGroup::~QActionGroup() = default;
+
+QAction *QActionGroup::checkedAction() const
 {
+    return static_cast<QAction *>(checkedGuiAction());
 }
 
-/*!
-    \fn QAction *QActionGroup::addAction(QAction *action)
-
-    Adds the \a action to this group, and returns it.
-
-    Normally an action is added to a group by creating it with the
-    group as its parent, so this function is not usually used.
-
-    \sa QAction::setActionGroup()
-*/
-QAction *QActionGroup::addAction(QAction* a)
+QAction *QActionGroup::addAction(QAction *a)
 {
-    Q_D(QActionGroup);
-    if(!d->actions.contains(a)) {
-        d->actions.append(a);
-        QObject::connect(a, SIGNAL(triggered()), this, SLOT(_q_actionTriggered()));
-        QObject::connect(a, SIGNAL(changed()), this, SLOT(_q_actionChanged()));
-        QObject::connect(a, SIGNAL(hovered()), this, SLOT(_q_actionHovered()));
-    }
-    if(!a->d_func()->forceDisabled) {
-        a->setEnabled(d->enabled);
-        a->d_func()->forceDisabled = false;
-    }
-    if(!a->d_func()->forceInvisible) {
-        a->setVisible(d->visible);
-        a->d_func()->forceInvisible = false;
-    }
-    if(a->isChecked())
-        d->current = a;
-    QActionGroup *oldGroup = a->d_func()->group;
-    if(oldGroup != this) {
-        if (oldGroup)
-            oldGroup->removeAction(a);
-        a->d_func()->group = this;
-        a->d_func()->sendDataChanged();
-    }
+    QGuiActionGroup::addAction(a);
     return a;
 }
 
@@ -260,185 +174,19 @@ QAction *QActionGroup::addAction(const QIcon &icon, const QString &text)
     return new QAction(icon, text, this);
 }
 
-/*!
-  Removes the \a action from this group. The action will have no
-  parent as a result.
-
-  \sa QAction::setActionGroup()
-*/
-void QActionGroup::removeAction(QAction *action)
-{
-    Q_D(QActionGroup);
-    if (d->actions.removeAll(action)) {
-        if (action == d->current)
-            d->current = 0;
-        QObject::disconnect(action, SIGNAL(triggered()), this, SLOT(_q_actionTriggered()));
-        QObject::disconnect(action, SIGNAL(changed()), this, SLOT(_q_actionChanged()));
-        QObject::disconnect(action, SIGNAL(hovered()), this, SLOT(_q_actionHovered()));
-        action->d_func()->group = 0;
-    }
-}
-
 /*!
     Returns the list of this groups's actions. This may be empty.
 */
 QList<QAction*> QActionGroup::actions() const
 {
-    Q_D(const QActionGroup);
-    return d->actions;
-}
-
-/*!
-    \brief Enable or disable the group exclusion checking
-
-    This is a convenience method that calls
-    setExclusionPolicy(ExclusionPolicy::Exclusive).
-
-    \sa QActionGroup::exclusionPolicy
-*/
-void QActionGroup::setExclusive(bool b)
-{
-    setExclusionPolicy(b ? QActionGroup::ExclusionPolicy::Exclusive
-                         : QActionGroup::ExclusionPolicy::None);
-}
-
-/*!
-    \brief Returs true if the group is exclusive
-
-    The group is exclusive if the ExclusionPolicy is either Exclusive
-    or ExclusionOptional.
-
-*/
-bool QActionGroup::isExclusive() const
-{
-    return exclusionPolicy() != QActionGroup::ExclusionPolicy::None;
+    QList<QAction*> result;
+    const auto baseActions = guiActions();
+    result.reserve(baseActions.size());
+    for (auto baseAction : baseActions)
+        result.append(static_cast<QAction*>(baseAction));
+    return result;
 }
 
-/*!
-    \property QActionGroup::exclusionPolicy
-    \brief This property holds the group exclusive checking policy
-
-    If exclusionPolicy is set to Exclusive, only one checkable
-    action in the action group can ever be active at any time. If the user
-    chooses another checkable action in the group, the one they chose becomes
-    active and the one that was active becomes inactive. If exclusionPolicy is
-    set to ExclusionOptional the group is exclusive but the active checkable
-    action in the group can be unchecked leaving the group with no actions
-    checked.
-
-    \sa QAction::checkable
-    \since 5.14
-*/
-void QActionGroup::setExclusionPolicy(QActionGroup::ExclusionPolicy policy)
-{
-    Q_D(QActionGroup);
-    d->exclusionPolicy = policy;
-}
-
-QActionGroup::ExclusionPolicy QActionGroup::exclusionPolicy() const
-{
-    Q_D(const QActionGroup);
-    return d->exclusionPolicy;
-}
-
-/*!
-    \fn void QActionGroup::setDisabled(bool b)
-
-    This is a convenience function for the \l enabled property, that
-    is useful for signals--slots connections. If \a b is true the
-    action group is disabled; otherwise it is enabled.
-*/
-
-/*!
-    \property QActionGroup::enabled
-    \brief whether the action group is enabled
-
-    Each action in the group will be enabled or disabled unless it
-    has been explicitly disabled.
-
-    \sa QAction::setEnabled()
-*/
-void QActionGroup::setEnabled(bool b)
-{
-    Q_D(QActionGroup);
-    d->enabled = b;
-    for (auto action : qAsConst(d->actions)) {
-        if (!action->d_func()->forceDisabled) {
-            action->setEnabled(b);
-            action->d_func()->forceDisabled = false;
-        }
-    }
-}
-
-bool QActionGroup::isEnabled() const
-{
-    Q_D(const QActionGroup);
-    return d->enabled;
-}
-
-/*!
-  Returns the currently checked action in the group, or \nullptr if
-  none are checked.
-*/
-QAction *QActionGroup::checkedAction() const
-{
-    Q_D(const QActionGroup);
-    return d->current;
-}
-
-/*!
-    \property QActionGroup::visible
-    \brief whether the action group is visible
-
-    Each action in the action group will match the visible state of
-    this group unless it has been explicitly hidden.
-
-    \sa QAction::setEnabled()
-*/
-void QActionGroup::setVisible(bool b)
-{
-    Q_D(QActionGroup);
-    d->visible = b;
-    for (auto action : qAsConst(d->actions)) {
-        if (!action->d_func()->forceInvisible) {
-            action->setVisible(b);
-            action->d_func()->forceInvisible = false;
-        }
-    }
-}
-
-bool QActionGroup::isVisible() const
-{
-    Q_D(const QActionGroup);
-    return d->visible;
-}
-
-/*!
-    \fn void QActionGroup::triggered(QAction *action)
-
-    This signal is emitted when the given \a action in the action
-    group is activated by the user; for example, when the user clicks
-    a menu option, toolbar button, or presses an action's shortcut key
-    combination.
-
-    Connect to this signal for command actions.
-
-    \sa QAction::activate()
-*/
-
-/*!
-    \fn void QActionGroup::hovered(QAction *action)
-
-    This signal is emitted when the given \a action in the action
-    group is highlighted by the user; for example, when the user
-    pauses with the cursor over a menu option, toolbar button, or
-    presses an action's shortcut key combination.
-
-    \sa QAction::activate()
-*/
-
 QT_END_NAMESPACE
 
-#include "moc_qactiongroup.cpp"
-
 #endif // QT_NO_ACTION
diff --git a/src/widgets/kernel/qactiongroup.h b/src/widgets/kernel/qactiongroup.h
index 90f488bedb..6ec2fc09ef 100644
--- a/src/widgets/kernel/qactiongroup.h
+++ b/src/widgets/kernel/qactiongroup.h
@@ -41,6 +41,7 @@
 #define QACTIONGROUP_H
 
 #include <QtWidgets/qtwidgetsglobal.h>
+#include <QtGui/qguiactiongroup.h>
 #include <QtWidgets/qaction.h>
 
 QT_BEGIN_NAMESPACE
@@ -50,45 +51,22 @@ QT_BEGIN_NAMESPACE
 
 class QActionGroupPrivate;
 
-class Q_WIDGETS_EXPORT QActionGroup : public QObject
+class Q_WIDGETS_EXPORT QActionGroup : public QGuiActionGroup
 {
     Q_OBJECT
     Q_DECLARE_PRIVATE(QActionGroup)
 
-    Q_PROPERTY(QActionGroup::ExclusionPolicy exclusionPolicy READ exclusionPolicy WRITE setExclusionPolicy)
-    Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
-    Q_PROPERTY(bool visible READ isVisible WRITE setVisible)
-
 public:
-    enum class ExclusionPolicy {
-        None,
-        Exclusive,
-        ExclusiveOptional
-    };
-    Q_ENUM(ExclusionPolicy)
-
     explicit QActionGroup(QObject* parent);
     ~QActionGroup();
 
-    QAction *addAction(QAction* a);
-    QAction *addAction(const QString &text);
-    QAction *addAction(const QIcon &icon, const QString &text);
-    void removeAction(QAction *a);
-    QList<QAction*> actions() const;
-
     QAction *checkedAction() const;
-    bool isExclusive() const;
-    bool isEnabled() const;
-    bool isVisible() const;
-    ExclusionPolicy exclusionPolicy() const;
 
+    QAction *addAction(QAction *a);
+    QAction *addAction(const QString &text);
+    QAction *addAction(const QIcon &icon, const QString &text);
 
-public Q_SLOTS:
-    void setEnabled(bool);
-    inline void setDisabled(bool b) { setEnabled(!b); }
-    void setVisible(bool);
-    void setExclusive(bool);
-    void setExclusionPolicy(ExclusionPolicy policy);
+    QList<QAction*> actions() const;
 
 Q_SIGNALS:
     void triggered(QAction *);
@@ -96,9 +74,6 @@ Q_SIGNALS:
 
 private:
     Q_DISABLE_COPY(QActionGroup)
-    Q_PRIVATE_SLOT(d_func(), void _q_actionTriggered())
-    Q_PRIVATE_SLOT(d_func(), void _q_actionChanged())
-    Q_PRIVATE_SLOT(d_func(), void _q_actionHovered())
 };
 
 #endif // QT_NO_ACTION
diff --git a/src/widgets/styles/qstyleoption.cpp b/src/widgets/styles/qstyleoption.cpp
index 4faf98a0a3..ec312a1ce4 100644
--- a/src/widgets/styles/qstyleoption.cpp
+++ b/src/widgets/styles/qstyleoption.cpp
@@ -1765,7 +1765,7 @@ QStyleOptionMenuItem::QStyleOptionMenuItem(int version)
     \value Exclusive The item is an exclusive check item (like a radio button).
     \value NonExclusive The item is a non-exclusive check item (like a check box).
 
-    \sa checkType, QAction::checkable, QAction::checked, QActionGroup::exclusive
+    \sa checkType, QGuiAction::checkable, QGuiAction::checked, QGuiActionGroup::exclusive
 */
 
 /*!
diff --git a/src/widgets/widgets/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp
index 7d580e50a5..d0ca0f4922 100644
--- a/src/widgets/widgets/qlineedit_p.cpp
+++ b/src/widgets/widgets/qlineedit_p.cpp
@@ -373,7 +373,7 @@ void QLineEditIconButton::actionEvent(QActionEvent *e)
 {
     switch (e->type()) {
     case QEvent::ActionChanged: {
-        const QAction *action = e->action();
+        const auto *action = e->action();
         if (isVisibleTo(parentWidget()) != action->isVisible()) {
             setVisible(action->isVisible());
             if (QLineEditPrivate *lep = lineEditPrivate())
@@ -548,7 +548,7 @@ void QLineEditPrivate::positionSideWidgets()
     }
 }
 
-QLineEditPrivate::SideWidgetLocation QLineEditPrivate::findSideWidget(const QAction *a) const
+QLineEditPrivate::SideWidgetLocation QLineEditPrivate::findSideWidget(const QGuiAction *a) const
 {
     int i = 0;
     for (const auto &e : leadingSideWidgets) {
@@ -637,7 +637,7 @@ QWidget *QLineEditPrivate::addAction(QAction *newAction, QAction *before, QLineE
     return w;
 }
 
-void QLineEditPrivate::removeAction(QAction *action)
+void QLineEditPrivate::removeAction(QGuiAction *action)
 {
 #if QT_CONFIG(action)
     Q_Q(QLineEdit);
diff --git a/src/widgets/widgets/qlineedit_p.h b/src/widgets/widgets/qlineedit_p.h
index 3f98aab901..33483254b6 100644
--- a/src/widgets/widgets/qlineedit_p.h
+++ b/src/widgets/widgets/qlineedit_p.h
@@ -241,7 +241,7 @@ public:
     QString placeholderText;
 
     QWidget *addAction(QAction *newAction, QAction *before, QLineEdit::ActionPosition, int flags = 0);
-    void removeAction(QAction *action);
+    void removeAction(QGuiAction *action);
     SideWidgetParameters sideWidgetParameters() const;
     QIcon clearButtonIcon() const;
     void setClearButtonEnabled(bool enabled);
@@ -264,7 +264,7 @@ private:
     };
     friend class QTypeInfo<SideWidgetLocation>;
 
-    SideWidgetLocation findSideWidget(const QAction *a) const;
+    SideWidgetLocation findSideWidget(const QGuiAction *a) const;
 
     SideWidgetEntryList leadingSideWidgets;
     SideWidgetEntryList trailingSideWidgets;
diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp
index 72653b377d..975f4f0e51 100644
--- a/src/widgets/widgets/qmenu.cpp
+++ b/src/widgets/widgets/qmenu.cpp
@@ -159,10 +159,11 @@ public:
         Q_D(QTornOffMenu);
         if(menu != d->causedMenu)
             return;
+        auto action = static_cast<QAction *>(act->action());
         if (act->type() == QEvent::ActionAdded) {
-            insertAction(act->before(), act->action());
+            insertAction(static_cast<QAction *>(act->before()), action);
         } else if (act->type() == QEvent::ActionRemoved)
-            removeAction(act->action());
+            removeAction(action);
     }
     void actionEvent(QActionEvent *e) override
     {
@@ -3540,15 +3541,16 @@ void QMenu::actionEvent(QActionEvent *e)
                 wa->releaseWidget(widget);
             }
         }
-        d->widgetItems.remove(e->action());
+        d->widgetItems.remove(static_cast<QAction *>(e->action()));
     }
 
     if (!d->platformMenu.isNull()) {
+        auto action = static_cast<QAction *>(e->action());
         if (e->type() == QEvent::ActionAdded) {
             QPlatformMenuItem *beforeItem = e->before()
                 ? d->platformMenu->menuItemForTag(reinterpret_cast<quintptr>(e->before()))
                 : nullptr;
-            d->insertActionInPlatformMenu(e->action(), beforeItem);
+            d->insertActionInPlatformMenu(action, beforeItem);
         } else if (e->type() == QEvent::ActionRemoved) {
             QPlatformMenuItem *menuItem = d->platformMenu->menuItemForTag(reinterpret_cast<quintptr>(e->action()));
             d->platformMenu->removeMenuItem(menuItem);
@@ -3556,7 +3558,7 @@ void QMenu::actionEvent(QActionEvent *e)
         } else if (e->type() == QEvent::ActionChanged) {
             QPlatformMenuItem *menuItem = d->platformMenu->menuItemForTag(reinterpret_cast<quintptr>(e->action()));
             if (menuItem) {
-                d->copyActionToPlatformItem(e->action(), menuItem);
+                d->copyActionToPlatformItem(action, menuItem);
                 d->platformMenu->syncMenuItem(menuItem);
             }
         }
diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp
index 3d31a3b73a..2ababac7a4 100644
--- a/src/widgets/widgets/qmenubar.cpp
+++ b/src/widgets/widgets/qmenubar.cpp
@@ -1293,21 +1293,22 @@ void QMenuBar::actionEvent(QActionEvent *e)
         if (!nativeMenuBar)
             return;
 
+        auto action = static_cast<QAction *>(e->action());
         if (e->type() == QEvent::ActionAdded) {
-            QPlatformMenu *menu = d->getPlatformMenu(e->action());
+            QPlatformMenu *menu = d->getPlatformMenu(action);
             if (menu) {
-                d->copyActionToPlatformMenu(e->action(), menu);
+                d->copyActionToPlatformMenu(action, menu);
 
-                QPlatformMenu *beforeMenu = d->findInsertionPlatformMenu(e->action());
+                QPlatformMenu *beforeMenu = d->findInsertionPlatformMenu(action);
                 d->platformMenuBar->insertMenu(menu, beforeMenu);
             }
         } else if (e->type() == QEvent::ActionRemoved) {
-            QPlatformMenu *menu = d->getPlatformMenu(e->action());
+            QPlatformMenu *menu = d->getPlatformMenu(action);
             if (menu)
                 d->platformMenuBar->removeMenu(menu);
         } else if (e->type() == QEvent::ActionChanged) {
             QPlatformMenu *cur = d->platformMenuBar->menuForTag(reinterpret_cast<quintptr>(e->action()));
-            QPlatformMenu *menu = d->getPlatformMenu(e->action());
+            QPlatformMenu *menu = d->getPlatformMenu(action);
 
             // the menu associated with the action can change, need to
             // remove and/or insert the new platform menu
@@ -1315,13 +1316,13 @@ void QMenuBar::actionEvent(QActionEvent *e)
                 if (cur)
                     d->platformMenuBar->removeMenu(cur);
                 if (menu) {
-                    d->copyActionToPlatformMenu(e->action(), menu);
+                    d->copyActionToPlatformMenu(action, menu);
 
-                    QPlatformMenu *beforeMenu = d->findInsertionPlatformMenu(e->action());
+                    QPlatformMenu *beforeMenu = d->findInsertionPlatformMenu(action);
                     d->platformMenuBar->insertMenu(menu, beforeMenu);
                 }
             } else if (menu) {
-                d->copyActionToPlatformMenu(e->action(), menu);
+                d->copyActionToPlatformMenu(action, menu);
                 d->platformMenuBar->syncMenu(menu);
             }
         }
diff --git a/src/widgets/widgets/qtoolbar.cpp b/src/widgets/widgets/qtoolbar.cpp
index fcaafbc581..aa8d2457d9 100644
--- a/src/widgets/widgets/qtoolbar.cpp
+++ b/src/widgets/widgets/qtoolbar.cpp
@@ -967,7 +967,7 @@ QAction *QToolBar::actionAt(const QPoint &p) const
 void QToolBar::actionEvent(QActionEvent *event)
 {
     Q_D(QToolBar);
-    QAction *action = event->action();
+    auto action = static_cast<QAction *>(event->action());
     QWidgetAction *widgetAction = qobject_cast<QWidgetAction *>(action);
 
     switch (event->type()) {
diff --git a/src/widgets/widgets/qtoolbarlayout.cpp b/src/widgets/widgets/qtoolbarlayout.cpp
index d50e19a5ed..31cb18efbd 100644
--- a/src/widgets/widgets/qtoolbarlayout.cpp
+++ b/src/widgets/widgets/qtoolbarlayout.cpp
@@ -207,7 +207,7 @@ void QToolBarLayout::insertAction(int index, QAction *action)
     }
 }
 
-int QToolBarLayout::indexOf(QAction *action) const
+int QToolBarLayout::indexOf(const QGuiAction *action) const
 {
     for (int i = 0; i < items.count(); ++i) {
         if (items.at(i)->action == action)
diff --git a/src/widgets/widgets/qtoolbarlayout_p.h b/src/widgets/widgets/qtoolbarlayout_p.h
index b5dc121b93..1a406a3d29 100644
--- a/src/widgets/widgets/qtoolbarlayout_p.h
+++ b/src/widgets/widgets/qtoolbarlayout_p.h
@@ -96,7 +96,7 @@ public:
     QSize sizeHint() const override;
 
     void insertAction(int index, QAction *action);
-    int indexOf(QAction *action) const;
+    int indexOf(const QGuiAction *action) const;
     using QLayout::indexOf; // bring back the hidden members
 
     bool layoutActions(const QSize &size);
diff --git a/src/widgets/widgets/qtoolbutton.cpp b/src/widgets/widgets/qtoolbutton.cpp
index b00b219386..cced36738c 100644
--- a/src/widgets/widgets/qtoolbutton.cpp
+++ b/src/widgets/widgets/qtoolbutton.cpp
@@ -466,7 +466,7 @@ void QToolButton::paintEvent(QPaintEvent *)
 void QToolButton::actionEvent(QActionEvent *event)
 {
     Q_D(QToolButton);
-    QAction *action = event->action();
+    auto action = static_cast<QAction *>(event->action());
     switch (event->type()) {
     case QEvent::ActionChanged:
         if (action == d->defaultAction)
diff --git a/tests/auto/widgets/kernel/qaction/tst_qaction.cpp b/tests/auto/widgets/kernel/qaction/tst_qaction.cpp
index 0d62c2cd4b..0d45bbc749 100644
--- a/tests/auto/widgets/kernel/qaction/tst_qaction.cpp
+++ b/tests/auto/widgets/kernel/qaction/tst_qaction.cpp
@@ -72,7 +72,7 @@ private slots:
 private:
     QEvent::Type m_lastEventType;
     const int m_keyboardScheme;
-    QAction *m_lastAction;
+    QGuiAction *m_lastAction;
 };
 
 tst_QAction::tst_QAction()
diff --git a/tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp b/tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp
index 524040d003..ae2b00c63a 100644
--- a/tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp
+++ b/tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp
@@ -259,7 +259,7 @@ void tst_QActionGroup::unCheckCurrentAction()
     action1.setChecked(true);
     QVERIFY(action1.isChecked());
     QVERIFY(!action2.isChecked());
-    QAction *current = group.checkedAction();
+    auto current = group.checkedAction();
     QCOMPARE(current, &action1);
     current->setChecked(false);
     QVERIFY(!action1.isChecked());
-- 
2.17.1

