Add ActionItem to allow sharing Action objects between MenuBar, ToolBar and Widgets
authorTobias Koenig <tobias.koenig@kdab.com>
Fri, 19 Oct 2012 12:09:57 +0000 (14:09 +0200)
committerTobias Koenig <tobias.koenig@kdab.com>
Sun, 28 Oct 2012 06:53:10 +0000 (07:53 +0100)
declarativeobjects.cpp
declarativeobjects_p.h
declarativewidgetdocument.cpp
editor.qml
objectadaptors.cpp
objectadaptors_p.h

index a6771db..88ea6e2 100644 (file)
@@ -154,6 +154,14 @@ DeclarativeAction::DeclarativeAction(QObject *parent) : DeclarativeObjectProxy<Q
 
 CUSTOM_METAOBJECT(DeclarativeAction, QAction)
 
+// DeclarativeActionItem
+DeclarativeActionItem::DeclarativeActionItem(QObject *parent) : DeclarativeObjectProxy<ActionItem>(parent)
+{
+  connectAllSignals(m_proxiedObject, this);
+}
+
+CUSTOM_METAOBJECT(DeclarativeActionItem, ActionItem)
+
 // DeclarativeSeparator
 DeclarativeSeparator::DeclarativeSeparator(QObject *parent) : DeclarativeObjectProxy<QAction>(parent)
 {
index 8f80f8d..f7a3b36 100644 (file)
 #include <QtDeclarative/qdeclarativeinfo.h>
 #include <qdeclarative.h>
 
+#include "objectadaptors_p.h"
+
+Q_DECLARE_METATYPE(QAction*)
+
 #define DECLARATIVE_OBJECT \
   public: \
     Q_OBJECT_CHECK \
@@ -99,6 +103,14 @@ class DeclarativeObjectProxy : public AbstractDeclarativeObject
     QVector<QObject*> m_children;
 };
 
+class DeclarativeActionItem : public DeclarativeObjectProxy<ActionItem>
+{
+  DECLARATIVE_OBJECT
+
+  public:
+    DeclarativeActionItem(QObject *parent = 0);
+};
+
 template <class T>
 class DeclarativeWidgetProxy : public DeclarativeObjectProxy<T>
 {
@@ -129,6 +141,12 @@ class DeclarativeWidgetProxy : public DeclarativeObjectProxy<T>
             return;
           }
 
+          DeclarativeActionItem *declarativeActionItem = dynamic_cast<DeclarativeActionItem*>(object);
+          if (declarativeActionItem) {
+            addAction(qobject_cast<ActionItem*>(declarativeActionItem->object())->action(), declarativeObject);
+            return;
+          }
+
           QAction *action = qobject_cast<QAction*>(declarativeObject->object());
           if (action) {
             addAction(action, declarativeObject);
@@ -212,6 +230,7 @@ class DeclarativeAction : public DeclarativeObjectProxy<QAction>
   public:
     DeclarativeAction(QObject *parent = 0);
 };
+Q_DECLARE_METATYPE(DeclarativeAction*)
 
 class DeclarativeSeparator : public DeclarativeObjectProxy<QAction>
 {
index 1955afb..fd2648a 100644 (file)
@@ -32,6 +32,7 @@ DeclarativeWidgetDocument::DeclarativeWidgetDocument(const QUrl &url, QObject *p
   // objects
   qmlRegisterType<QAction>();
   qmlRegisterType<DeclarativeAction>("QtGui", 1, 0, "Action");
+  qmlRegisterType<DeclarativeActionItem>("QtGui", 1, 0, "ActionItem");
   qmlRegisterType<DeclarativeSeparator>("QtGui", 1, 0, "Separator");
 
   // layouts
index 1fd14cf..43f29ad 100644 (file)
@@ -49,7 +49,7 @@ MainWindow {
       Separator {}
 
       Action {
-        text: "Close"
+        text: qsTr("Close")
         onTriggered: Qt.quit()
       }
     }
@@ -70,16 +70,19 @@ MainWindow {
       Separator {}
 
       Action {
+        id: cutAction
         text: qsTr("Cut")
         onTriggered: textEdit.cut()
       }
 
       Action {
+        id: copyAction
         text: qsTr("Copy")
         onTriggered: textEdit.copy()
       }
 
       Action {
+        id: pasteAction
         text: qsTr("Paste")
         onTriggered: textEdit.paste()
       }
@@ -139,19 +142,16 @@ MainWindow {
 
     contextMenuPolicy: Qt.ActionsContextMenu
 
-    Action {
-      text: qsTr("Cut")
-      onTriggered: textEdit.cut()
+    ActionItem {
+      action: cutAction
     }
 
-    Action {
-      text: qsTr("Copy")
-      onTriggered: textEdit.copy()
+    ActionItem {
+      action: copyAction
     }
 
-    Action {
-      text: qsTr("Paste")
-      onTriggered: textEdit.paste()
+    ActionItem {
+      action: pasteAction
     }
   }
 
index d3f44b6..8862f24 100644 (file)
@@ -1,5 +1,7 @@
 #include "objectadaptors_p.h"
 
+#include "declarativeobjects_p.h"
+
 FileDialog::FileDialog(QWidget *parent)
   : QFileDialog(parent)
 {
@@ -23,3 +25,55 @@ bool TextEdit::modified() const
 {
   return document()->isModified();
 }
+
+ActionItem::ActionItem(QObject *parent)
+  : QObject(parent)
+  , m_placeholderAction(new QAction(this))
+  , m_qAction(m_placeholderAction)
+{
+}
+
+QAction* ActionItem::action()
+{
+  return m_qAction;
+}
+
+void ActionItem::setAction(const QVariant &action)
+{
+  if (m_action == action)
+    return;
+
+  m_action = action;
+
+  QObject *object = m_action.value<QObject*>();
+
+  // Is the passed action a QAction ...
+  QAction *newAction = qobject_cast<QAction*>(object);
+
+  // ... or a DeclarativeAction
+  DeclarativeAction *declarativeAction = dynamic_cast<DeclarativeAction*>(object);
+  if (declarativeAction) {
+    newAction = qobject_cast<QAction*>(declarativeAction->object());
+  }
+
+  // Check if the placeholder must be replaced with the actual action
+  if (m_qAction == m_placeholderAction) {
+    const QList<QWidget*> widgets = m_placeholderAction->associatedWidgets();
+    if (!widgets.isEmpty()) {
+      Q_ASSERT(widgets.count() == 1); // The placeholder action can only be plugged into one widget
+
+      // Replace the placeholder action with the new one
+      widgets.first()->insertAction(m_placeholderAction, newAction);
+      widgets.first()->removeAction(m_placeholderAction);
+
+      m_qAction = newAction;
+    }
+  }
+
+  emit actionChanged();
+}
+
+QVariant ActionItem::qmlAction() const
+{
+  return m_action;
+}
index 11e22f7..cc2f32f 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef OBJECTADAPTORS_P_H
 #define OBJECTADAPTORS_P_H
 
+#include <QtGui/QAction>
 #include <QtGui/QFileDialog>
 #include <QtGui/QInputDialog>
 #include <QtGui/QTextEdit>
@@ -65,4 +66,27 @@ class TextEdit : public QTextEdit
     bool modified() const;
 };
 
+class ActionItem : public QObject
+{
+  Q_OBJECT
+
+  Q_PROPERTY(QVariant action READ qmlAction WRITE setAction NOTIFY actionChanged)
+
+  public:
+    ActionItem(QObject *parent = 0);
+
+    QAction* action();
+
+  Q_SIGNALS:
+    void actionChanged();
+
+  private:
+    void setAction(const QVariant &action);
+    QVariant qmlAction() const;
+
+    QVariant m_action;
+    QAction* m_placeholderAction;
+    QAction* m_qAction;
+};
+
 #endif