diff --git a/tests/resources.qrc b/tests/resources.qrc
index 7682af02b..427e93006 100644
--- a/tests/resources.qrc
+++ b/tests/resources.qrc
@@ -31,6 +31,7 @@
ui/components/form/TransparentComboBox.qml
ui/components/form/SmallButton.qml
ui/components/form/DarkButton.qml
+ ui/components/invertedMouseArea/InvertedMouseArea.qml
ui/scripts/utils.js
ui/views/newCall.qml
ui/views/manageAccounts.qml
diff --git a/tests/ui/components/collapse/Collapse.qml b/tests/ui/components/collapse/Collapse.qml
index c514ce280..def381519 100644
--- a/tests/ui/components/collapse/Collapse.qml
+++ b/tests/ui/components/collapse/Collapse.qml
@@ -1,5 +1,6 @@
import QtQuick 2.7
+import 'qrc:/ui/components/form'
import 'qrc:/ui/components/image'
// ===================================================================
@@ -9,21 +10,21 @@ Item {
signal collapsed (bool collapsed)
- function updateCollapse () {
+ function collapse () {
isCollapsed = !isCollapsed
collapsed(isCollapsed)
rotate.start()
}
- Icon {
- anchors.fill: parent
- id: backgroundImage
- icon: 'collapse'
-
- MouseArea {
- anchors.fill: parent
- onClicked: updateCollapse()
+ ActionButton {
+ anchors.centerIn: parent
+ background: Rectangle {
+ color: 'transparent'
}
+ icon: 'collapse'
+ iconSize: 32
+ id: button
+ onClicked: collapse()
}
RotationAnimation {
@@ -32,7 +33,7 @@ Item {
from: isCollapsed ? 0 : 180
id: rotate
property: 'rotation'
- target: backgroundImage
+ target: button
to: isCollapsed ? 180 : 0
}
}
diff --git a/tests/ui/components/invertedMouseArea/InvertedMouseArea.qml b/tests/ui/components/invertedMouseArea/InvertedMouseArea.qml
new file mode 100644
index 000000000..211f999e0
--- /dev/null
+++ b/tests/ui/components/invertedMouseArea/InvertedMouseArea.qml
@@ -0,0 +1,86 @@
+import QtQuick 2.0
+
+// ===================================================================
+// Helper to handle button click outside a component.
+// ===================================================================
+
+Item {
+ property var mouseArea
+
+ signal pressed
+
+ function createMouseArea () {
+ if (mouseArea == null) {
+ mouseArea = builder.createObject(this)
+ }
+
+ mouseArea.parent = (function () {
+ // Search root.
+ var p = item
+
+ while (p.parent != null) {
+ p = p.parent
+ }
+
+ return p
+ })()
+ }
+
+ function deleteMouseArea () {
+ if (mouseArea != null) {
+ mouseArea.destroy()
+ mouseArea = null
+ }
+ }
+
+ function isInItem (point) {
+ return (
+ point.x >= item.x &&
+ point.y >= item.y &&
+ point.x <= item.x + item.width &&
+ point.y <= item.y + item.height
+ )
+ }
+
+ id: item
+
+ onEnabledChanged: {
+ deleteMouseArea()
+
+ if (enabled) {
+ createMouseArea()
+ }
+ }
+
+ Component {
+ id: builder
+
+ MouseArea {
+ anchors.fill: parent
+ propagateComposedEvents: true
+ z: 9999999999 // Ugly! But it's necessary in some cases...
+
+ onPressed: {
+ // Propagate event.
+ mouse.accepted = false
+
+ if (!isInItem(
+ mapToItem(item.parent, mouse.x, mouse.y)
+ )) {
+ // Outside!!!
+ item.pressed()
+ }
+ }
+ }
+ }
+
+ // It's necessary to use a `enabled` variable.
+ // See: http://doc.qt.io/qt-5/qml-qtqml-component.html#completed-signal
+ //
+ // The creation order of components in a view is undefined,
+ // so the mouse area mustt be created only when `enabled == true`.
+ //
+ // In the first view render, `enabled` must equal false.
+ Component.onCompleted: enabled && createMouseArea()
+ Component.onDestruction: deleteMouseArea()
+}
diff --git a/tests/ui/components/searchBox/SearchBox.qml b/tests/ui/components/searchBox/SearchBox.qml
index 9012246ff..d0150a199 100644
--- a/tests/ui/components/searchBox/SearchBox.qml
+++ b/tests/ui/components/searchBox/SearchBox.qml
@@ -2,6 +2,7 @@ import QtGraphicalEffects 1.0
import QtQuick 2.7
import QtQuick.Controls 2.0
+import 'qrc:/ui/components/invertedMouseArea'
import 'qrc:/ui/components/popup'
// ===================================================================
@@ -10,68 +11,70 @@ Item {
property alias placeholderText: searchField.placeholderText
property alias maxMenuHeight: menu.maxMenuHeight
+ signal menuClosed ()
+ signal menuOpened ()
+ signal searchTextChanged (string text)
+
implicitHeight: searchField.height
function hideMenu () {
menu.hide()
shadow.visible = false
+ searchField.focus = false
+ menuClosed()
}
function showMenu () {
menu.show()
shadow.visible = true
+ menuOpened()
}
- TextField {
- signal searchTextChanged (string text)
+ Item {
+ implicitHeight: searchField.height + menu.height
+ width: parent.width
- anchors.fill: parent
- background: Rectangle {
- implicitHeight: 30
- }
- id: searchField
-
- Keys.onEscapePressed: focus = false
-
- onActiveFocusChanged: {
- // Menu is hidden if `TextField` AND `FocusScope` focus
- // are lost.
- if (activeFocus) {
- showMenu()
- } else if (!scope.activeFocus) {
- hideMenu()
+ TextField {
+ background: Rectangle {
+ implicitHeight: 30
}
+ id: searchField
+ width: parent.width
+
+ Keys.onEscapePressed: hideMenu()
+
+ onActiveFocusChanged: activeFocus && showMenu()
+ onTextChanged: searchTextChanged(text)
}
- onTextChanged: searchTextChanged(text)
- }
-
- // Handle focus from content. (Buttons...)
- FocusScope {
- anchors.top: searchField.bottom
- id: scope
- z: 999 // Menu must be above any component.
-
- Keys.onEscapePressed: focus = false
-
- onActiveFocusChanged: !searchField.activeFocus &&
- !activeFocus &&
- hideMenu()
DropDownMenu {
+ anchors.top: searchField.bottom
id: menu
width: searchField.width
+ z: 999 // Menu must be above any component.
+
+ Keys.onEscapePressed: hideMenu()
+ }
+
+ DropShadow {
+ anchors.fill: searchField
+ color: "#80000000"
+ horizontalOffset: 2
+ id: shadow
+ radius: 8.0
+ samples: 15
+ source: searchField
+ verticalOffset: 2
+ visible: false
+ }
+
+ InvertedMouseArea {
+ enabled: menu.visible
+ height: parent.height
+ parent: parent
+ width: parent.width
+
+ onPressed: hideMenu()
}
}
-
- DropShadow {
- anchors.fill: searchField
- color: "#80000000"
- horizontalOffset: 2
- id: shadow
- radius: 8.0
- samples: 15
- source: searchField
- verticalOffset: 2
- visible: false
- }
}
diff --git a/tests/ui/views/mainWindow/mainWindow.qml b/tests/ui/views/mainWindow/mainWindow.qml
index 7a9a5933c..751dac15f 100644
--- a/tests/ui/views/mainWindow/mainWindow.qml
+++ b/tests/ui/views/mainWindow/mainWindow.qml
@@ -15,7 +15,7 @@ ApplicationWindow {
id: mainWindow
maximumHeight: 70
minimumHeight: 70
- minimumWidth: 700
+ minimumWidth: 780
title: 'Linphone'
visible: true
@@ -64,8 +64,17 @@ ApplicationWindow {
// Search.
SearchBox {
Layout.fillWidth: true
- maxMenuHeight: mainWindow.height - 100
+ maxMenuHeight: 300 // See Hick's law for good choice.
placeholderText: qsTr('mainSearchBarPlaceholder')
+
+ onMenuClosed: content.enabled = true
+
+ onMenuOpened: {
+ if (!collapse.isCollapsed) {
+ collapse.collapse()
+ }
+ content.enabled = false
+ }
}
// Start conference.
@@ -79,6 +88,7 @@ ApplicationWindow {
RowLayout {
anchors.fill: parent
+ id: content
spacing: 0
// Main menu.