From 1a1a19f74e7f55388da043ae1e2e34e334d5f740 Mon Sep 17 00:00:00 2001
From: Richard Moe Gustavsen <richard.gustavsen@digia.com>
Date: Tue, 23 Sep 2014 15:53:49 +0200
Subject: [PATCH] EditMenu: let menu property be a component to lazy load it

Since all input fields have a menu assigned to it by
default (which in most cases never will be shown), it should
be an optimization to await creating it until needed.

Change-Id: I5777bbdae42103981e9b2f5ddfdfd763acea07ae
Reviewed-by: J-P Nurmi <jpnurmi@digia.com>
---
 examples/quick/controls/gallery/main.qml | 36 +++++++-------
 src/controls/ComboBox.qml                |  5 +-
 src/controls/Private/EditMenu.qml        | 22 ++++++++-
 src/controls/Private/EditMenu_base.qml   | 63 +++++++++++++-----------
 src/controls/Private/EditMenu_ios.qml    | 10 ++--
 src/controls/SpinBox.qml                 |  5 +-
 src/controls/TextArea.qml                |  7 +--
 src/controls/TextField.qml               |  5 +-
 8 files changed, 90 insertions(+), 63 deletions(-)

diff --git a/examples/quick/controls/gallery/main.qml b/examples/quick/controls/gallery/main.qml
index 0a385a1bd..a6f4ce390 100644
--- a/examples/quick/controls/gallery/main.qml
+++ b/examples/quick/controls/gallery/main.qml
@@ -140,25 +140,27 @@ ApplicationWindow {
 
     ChildWindow { id: window1 }
 
-    Menu {
+    Component {
         id: editmenu
-        MenuItem { action: cutAction }
-        MenuItem { action: copyAction }
-        MenuItem { action: pasteAction }
-        MenuSeparator {}
         Menu {
-            title: "Text &Format"
-            MenuItem { action: a1 }
-            MenuItem { action: a2 }
-            MenuItem { action: a3 }
-            MenuSeparator { }
-            MenuItem { text: "Allow &Hyphenation"; checkable: true }
-        }
-        Menu {
-            title: "Font &Style"
-            MenuItem { text: "&Bold"; checkable: true }
-            MenuItem { text: "&Italic"; checkable: true }
-            MenuItem { text: "&Underline"; checkable: true }
+            MenuItem { action: cutAction }
+            MenuItem { action: copyAction }
+            MenuItem { action: pasteAction }
+            MenuSeparator {}
+            Menu {
+                title: "Text &Format"
+                MenuItem { action: a1 }
+                MenuItem { action: a2 }
+                MenuItem { action: a3 }
+                MenuSeparator { }
+                MenuItem { text: "Allow &Hyphenation"; checkable: true }
+            }
+            Menu {
+                title: "Font &Style"
+                MenuItem { text: "&Bold"; checkable: true }
+                MenuItem { text: "&Italic"; checkable: true }
+                MenuItem { text: "&Underline"; checkable: true }
+            }
         }
     }
 
diff --git a/src/controls/ComboBox.qml b/src/controls/ComboBox.qml
index 1dba6b7e7..55161d398 100644
--- a/src/controls/ComboBox.qml
+++ b/src/controls/ComboBox.qml
@@ -222,16 +222,15 @@ Control {
     property alias validator: input.validator
 
     /*!
-        \qmlproperty Menu ComboBox::menu
         \since QtQuick.Controls 1.3
 
-        This property contains the edit menu for working
+        This property contains the edit \l Menu for working
         with text selection. Set it to \c null if no menu
         is wanted.
 
         \note The menu is only in use when \l editable is \c true
     */
-    property Menu menu: input.editMenu.defaultMenu
+    property Component menu: input.editMenu.defaultMenu
 
     /*!
         \qmlproperty bool ComboBox::acceptableInput
diff --git a/src/controls/Private/EditMenu.qml b/src/controls/Private/EditMenu.qml
index c0faf9ff3..f4d80bd5f 100644
--- a/src/controls/Private/EditMenu.qml
+++ b/src/controls/Private/EditMenu.qml
@@ -47,7 +47,27 @@ Loader {
     property Item cursorHandle
     property Item selectionHandle
     property Flickable flickable
-    property Menu defaultMenu: item && item.defaultMenu ? item.defaultMenu : null
+    property Component defaultMenu: item && item.defaultMenu ? item.defaultMenu : null
+    property Menu menuInstance: null
+
+    Connections {
+        target: control
+        onMenuChanged: {
+            if (menuInstance !== null) {
+                menuInstance.destroy()
+                menuInstance = null
+            }
+        }
+    }
+
+    function getMenuInstance()
+    {
+        // Lazy load menu when first requested
+        if (!menuInstance && control.menu) {
+            menuInstance = control.menu.createObject(input);
+        }
+        return menuInstance;
+    }
 
     source: Qt.resolvedUrl("EditMenu_" + (Qt.platform.os === "ios"  ? "ios" : "base") + ".qml")
 }
diff --git a/src/controls/Private/EditMenu_base.qml b/src/controls/Private/EditMenu_base.qml
index 88cef62ad..aed4e4647 100644
--- a/src/controls/Private/EditMenu_base.qml
+++ b/src/controls/Private/EditMenu_base.qml
@@ -42,45 +42,52 @@ import QtQuick.Controls 1.2
 import QtQuick.Controls.Private 1.0
 
 Item {
+    id: editMenuBase
     anchors.fill: parent
 
-    Action {
+    Component {
         id: cutAction
-        text: "Cu&t"
-        shortcut: StandardKey.Cut
-        iconName: "edit-cut"
-        enabled: !input.readOnly && selectionStart !== selectionEnd
-        onTriggered: {
-            input.cut();
-            input.select(input.cursorPosition, input.cursorPosition);
+        Action {
+            text: "Cu&t"
+            shortcut: StandardKey.Cut
+            iconName: "edit-cut"
+            enabled: !input.readOnly && selectionStart !== selectionEnd
+            onTriggered: {
+                input.cut();
+                input.select(input.cursorPosition, input.cursorPosition);
+            }
         }
     }
 
-    Action {
+    Component {
         id: copyAction
-        text: "&Copy"
-        shortcut: StandardKey.Copy
-        iconName: "edit-copy"
-        enabled: input.selectionStart !== input.selectionEnd
-        onTriggered: {
-            input.copy();
-            input.select(input.cursorPosition, input.cursorPosition);
+        Action {
+            text: "&Copy"
+            shortcut: StandardKey.Copy
+            iconName: "edit-copy"
+            enabled: input.selectionStart !== input.selectionEnd
+            onTriggered: {
+                input.copy();
+                input.select(input.cursorPosition, input.cursorPosition);
+            }
         }
     }
 
-    Action {
+    Component {
         id: pasteAction
-        text: "&Paste"
-        shortcut: StandardKey.Paste
-        iconName: "edit-paste"
-        enabled: input.canPaste
-        onTriggered: input.paste()
+        Action {
+            text: "&Paste"
+            shortcut: StandardKey.Paste
+            iconName: "edit-paste"
+            enabled: input.canPaste
+            onTriggered: input.paste()
+        }
     }
 
-    property Menu defaultMenu: Menu {
-        MenuItem { action: cutAction }
-        MenuItem { action: copyAction }
-        MenuItem { action: pasteAction }
+    property Component defaultMenu: Menu {
+        MenuItem { action: cutAction.createObject(editMenuBase) }
+        MenuItem { action: copyAction.createObject(editMenuBase) }
+        MenuItem { action: pasteAction.createObject(editMenuBase) }
     }
 
     MouseArea {
@@ -97,9 +104,9 @@ Item {
             input.activate()
 
             if (control.menu) {
-                control.menu.__dismissMenu();
+                getMenuInstance().__dismissMenu();
                 var menuPos = mapToItem(null, mouse.x, mouse.y)
-                control.menu.__popup(menuPos.x, menuPos.y, -1, MenuPrivate.EditMenu);
+                getMenuInstance().__popup(menuPos.x, menuPos.y, -1, MenuPrivate.EditMenu);
             }
         }
     }
diff --git a/src/controls/Private/EditMenu_ios.qml b/src/controls/Private/EditMenu_ios.qml
index e41e0cb67..1fe92e46d 100644
--- a/src/controls/Private/EditMenu_ios.qml
+++ b/src/controls/Private/EditMenu_ios.qml
@@ -46,7 +46,7 @@ Item {
     anchors.fill: parent
     property bool __showMenuFromTouchAndHold: false
 
-    property Menu defaultMenu: Menu {
+    property Component defaultMenu: Menu {
         MenuItem {
             text: "cut"
             visible: !input.readOnly && selectionStart !== selectionEnd
@@ -99,7 +99,7 @@ Item {
         }
 
         onClicked: {
-            if (control.menu && control.menu.__popupVisible) {
+            if (control.menu && getMenuInstance().__popupVisible) {
                 select(input.cursorPosition, input.cursorPosition);
             } else {
                 input.activate();
@@ -180,10 +180,10 @@ Item {
                 var xMax = Math.max(r1.x, r2.x);
                 var centerX = xMin + ((xMax - xMin) / 2);
                 var popupPos = input.mapToItem(null, centerX, r1.y);
-                control.menu.__dismissMenu();
-                control.menu.__popup(popupPos.x, popupPos.y, -1, MenuPrivate.EditMenu);
+                getMenuInstance().__dismissMenu();
+                getMenuInstance().__popup(popupPos.x, popupPos.y, -1, MenuPrivate.EditMenu);
             } else {
-                control.menu.__dismissMenu();
+                getMenuInstance().__dismissMenu();
             }
         }
     }
diff --git a/src/controls/SpinBox.qml b/src/controls/SpinBox.qml
index f4b89ae60..f13e81dc4 100644
--- a/src/controls/SpinBox.qml
+++ b/src/controls/SpinBox.qml
@@ -204,14 +204,13 @@ Control {
     readonly property bool inputMethodComposing: !!input.inputMethodComposing
 
     /*!
-        \qmlproperty Menu SpinBox::menu
         \since QtQuick.Controls 1.3
 
-        This property contains the edit menu for working
+        This property contains the edit \l Menu for working
         with text selection. Set it to \c null if no menu
         is wanted.
     */
-    property Menu menu: input.editMenu.defaultMenu
+    property Component menu: input.editMenu.defaultMenu
 
     style: Qt.createComponent(Settings.style + "/SpinBoxStyle.qml", spinbox)
 
diff --git a/src/controls/TextArea.qml b/src/controls/TextArea.qml
index d8181ab93..d2663e17e 100644
--- a/src/controls/TextArea.qml
+++ b/src/controls/TextArea.qml
@@ -436,14 +436,15 @@ ScrollView {
     readonly property alias hoveredLink: edit.hoveredLink
 
     /*!
-        \qmlproperty Menu TextArea::menu
         \since QtQuick.Controls 1.3
 
-        This property contains the edit menu for working
+        This property contains the edit \l Menu for working
         with text selection. Set it to \c null if no menu
         is wanted.
+
+        \sa Menu
     */
-    property Menu menu: editMenu.defaultMenu
+    property Component menu: editMenu.defaultMenu
 
     /*!
         \qmlmethod TextArea::append(string)
diff --git a/src/controls/TextField.qml b/src/controls/TextField.qml
index 7417beb8c..4d31e9b88 100644
--- a/src/controls/TextField.qml
+++ b/src/controls/TextField.qml
@@ -434,14 +434,13 @@ Control {
     property alias validator: textInput.validator
 
     /*!
-        \qmlproperty Menu TextField::menu
         \since QtQuick.Controls 1.3
 
-        This property contains the edit menu for working
+        This property contains the edit \l Menu for working
         with text selection. Set it to \c null if no menu
         is wanted.
     */
-    property Menu menu: textInput.editMenu.defaultMenu
+    property Component menu: textInput.editMenu.defaultMenu
 
     /*!
         \qmlsignal TextField::accepted()
-- 
GitLab