mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-02-07 15:08:24 +00:00
feat(ui/modules/Common/Menus/DropDownDynamicMenu): use Popup component
This commit is contained in:
parent
78de78982e
commit
b0fc92164d
11 changed files with 107 additions and 211 deletions
|
|
@ -223,14 +223,13 @@
|
|||
<file>ui/modules/Common/Indicators/VuMeter.qml</file>
|
||||
<file>ui/modules/Common/Menus/ActionMenuEntry.qml</file>
|
||||
<file>ui/modules/Common/Menus/ActionMenu.qml</file>
|
||||
<file>ui/modules/Common/Menus/DropDownDynamicMenu.qml</file>
|
||||
<file>ui/modules/Common/Menus/Menu.qml</file>
|
||||
<file>ui/modules/Common/Misc/Borders.qml</file>
|
||||
<file>ui/modules/Common/Misc/Collapse.qml</file>
|
||||
<file>ui/modules/Common/Misc/ForceScrollBar.qml</file>
|
||||
<file>ui/modules/Common/Misc/Paned.qml</file>
|
||||
<file>ui/modules/Common/Popup/AbstractDropDownMenu.qml</file>
|
||||
<file>ui/modules/Common/Popup/DesktopPopup.qml</file>
|
||||
<file>ui/modules/Common/Popup/DropDownDynamicMenu.qml</file>
|
||||
<file>ui/modules/Common/Popup/Popup.qml</file>
|
||||
<file>ui/modules/Common/Popup/PopupShadow.qml</file>
|
||||
<file>ui/modules/Common/qmldir</file>
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
#include <QtDebug>
|
||||
#include <QTimer>
|
||||
|
||||
#include "gitversion.h"
|
||||
|
||||
#include "../components/Components.hpp"
|
||||
#include "../Utils.hpp"
|
||||
|
||||
|
|
@ -37,7 +39,6 @@
|
|||
#include "translator/DefaultTranslator.hpp"
|
||||
|
||||
#include "App.hpp"
|
||||
#include "gitversion.h"
|
||||
|
||||
#define DEFAULT_LOCALE "en"
|
||||
|
||||
|
|
@ -51,7 +52,7 @@
|
|||
|
||||
#define QML_VIEW_SPLASH_SCREEN "qrc:/ui/views/App/SplashScreen/SplashScreen.qml"
|
||||
|
||||
#define SELF_TEST_DELAY 60000
|
||||
#define SELF_TEST_DELAY 300000
|
||||
|
||||
#ifndef LINPHONE_QT_GIT_VERSION
|
||||
#define LINPHONE_QT_GIT_VERSION "unknown"
|
||||
|
|
@ -153,10 +154,10 @@ void App::initContentApp () {
|
|||
|
||||
// Init engine content.
|
||||
mEngine = new QQmlApplicationEngine();
|
||||
qInfo() << QStringLiteral("Activated selectors:") << QQmlFileSelector::get(mEngine)->selector()->allSelectors();
|
||||
|
||||
// Provide `+custom` folders for custom components.
|
||||
(new QQmlFileSelector(mEngine, mEngine))->setExtraSelectors(QStringList("custom"));
|
||||
qInfo() << QStringLiteral("Activated selectors:") << QQmlFileSelector::get(mEngine)->selector()->allSelectors();
|
||||
|
||||
// Set modules paths.
|
||||
mEngine->addImportPath(":/ui/modules");
|
||||
|
|
|
|||
|
|
@ -89,10 +89,8 @@ Item {
|
|||
DropDownDynamicMenu {
|
||||
id: menu
|
||||
|
||||
launcher: searchField
|
||||
relativeTo: searchField
|
||||
relativeY: searchField.height
|
||||
width: searchField.width
|
||||
|
||||
// If the menu is focused, the main window loses the active status.
|
||||
// So It's necessary to map the keys events.
|
||||
|
|
@ -103,8 +101,8 @@ Item {
|
|||
ScrollableListView {
|
||||
id: list
|
||||
|
||||
anchors.fill: parent
|
||||
headerPositioning: header ? ListView.OverlayHeader : ListView.InlineFooter
|
||||
width: searchField.width
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -123,7 +121,7 @@ Item {
|
|||
|
||||
ScriptAction {
|
||||
script: {
|
||||
menu.showMenu()
|
||||
menu.show()
|
||||
|
||||
searchBox.menuOpened()
|
||||
}
|
||||
|
|
@ -136,7 +134,7 @@ Item {
|
|||
|
||||
ScriptAction {
|
||||
script: {
|
||||
menu.hideMenu()
|
||||
menu.hide()
|
||||
searchField.focus = false
|
||||
|
||||
searchBox.menuClosed()
|
||||
|
|
|
|||
|
|
@ -123,9 +123,6 @@ Item {
|
|||
DropDownDynamicMenu {
|
||||
id: menu
|
||||
|
||||
launcher: searchField
|
||||
width: searchField.width
|
||||
|
||||
// If the menu is focused, the main window loses the active status.
|
||||
// So It's necessary to map the keys events.
|
||||
Keys.forwardTo: searchField
|
||||
|
|
@ -135,8 +132,8 @@ Item {
|
|||
ScrollableListView {
|
||||
id: list
|
||||
|
||||
anchors.fill: parent
|
||||
headerPositioning: header ? ListView.OverlayHeader : ListView.InlineFooter
|
||||
width: searchField.width
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -156,7 +153,7 @@ Item {
|
|||
|
||||
ScriptAction {
|
||||
script: {
|
||||
menu.showMenu()
|
||||
menu.show()
|
||||
desktopPopup.show()
|
||||
|
||||
searchBox.menuOpened()
|
||||
|
|
@ -170,7 +167,7 @@ Item {
|
|||
|
||||
ScriptAction {
|
||||
script: {
|
||||
menu.hideMenu()
|
||||
menu.hide()
|
||||
searchField.focus = false
|
||||
desktopPopup.hide()
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
import QtQuick 2.7
|
||||
|
||||
import Common 1.0
|
||||
import Utils 1.0
|
||||
|
||||
// =============================================================================
|
||||
|
||||
Item {
|
||||
id: menu
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
property alias relativeTo: popup.relativeTo
|
||||
property alias relativeX: popup.relativeX
|
||||
property alias relativeY: popup.relativeY
|
||||
|
||||
// Can be computed, but for performance usage, it must be given in attribute.
|
||||
property int entryHeight
|
||||
property int maxMenuHeight
|
||||
|
||||
default property alias _content: menuContent.data
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
signal menuClosed
|
||||
signal menuOpened
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function show () {
|
||||
popup.show()
|
||||
}
|
||||
|
||||
function hide () {
|
||||
popup.hide()
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function _computeHeight () {
|
||||
Utils.assert(_content != null && _content.length > 0, '`_content` cannot be null and must exists.')
|
||||
|
||||
var list = _content[0]
|
||||
Utils.assert(list != null, 'No list found.')
|
||||
Utils.assert(
|
||||
Utils.qmlTypeof(list, 'QQuickListView') || Utils.qmlTypeof(list, 'ScrollableListView'),
|
||||
'No list view parameter.'
|
||||
)
|
||||
|
||||
var height = list.count * entryHeight
|
||||
|
||||
if (list.headerPositioning === ListView.OverlayHeader) {
|
||||
// Workaround to force header layout.
|
||||
list.headerItem.z = Constants.zMax
|
||||
|
||||
height += list.headerItem.height
|
||||
}
|
||||
|
||||
return (maxMenuHeight !== undefined && height > maxMenuHeight)
|
||||
? maxMenuHeight
|
||||
: height
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Popup {
|
||||
id: popup
|
||||
|
||||
onShown: menu.menuOpened()
|
||||
onHidden: menu.menuClosed()
|
||||
|
||||
Item {
|
||||
id: menuContent
|
||||
|
||||
height: menu._computeHeight()
|
||||
width: menu._content[0].width
|
||||
}
|
||||
}
|
||||
|
||||
Binding {
|
||||
property: 'height'
|
||||
target: menu._content[0]
|
||||
value: menuContent.height
|
||||
}
|
||||
}
|
||||
|
|
@ -1,154 +0,0 @@
|
|||
import QtQuick 2.7
|
||||
|
||||
import Common 1.0
|
||||
import Common.Styles 1.0
|
||||
import Utils 1.0
|
||||
|
||||
// =============================================================================
|
||||
// Low component to display a list/menu in a popup.
|
||||
// =============================================================================
|
||||
|
||||
Item {
|
||||
id: menu
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Optionnal parameter, if defined and if a click is detected
|
||||
// on it, menu is not closed.
|
||||
property var launcher
|
||||
|
||||
// Optionnal parameters, set the position of Menu relative
|
||||
// to this item.
|
||||
property var relativeTo
|
||||
property int relativeX: 0
|
||||
property int relativeY: 0
|
||||
|
||||
default property alias _content: content.data
|
||||
property bool _isOpen: false
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
signal menuClosed
|
||||
signal menuOpened
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function isOpen () {
|
||||
return _isOpen
|
||||
}
|
||||
|
||||
function showMenu () {
|
||||
if (_isOpen) {
|
||||
return
|
||||
}
|
||||
|
||||
if (relativeTo != null) {
|
||||
this.x = relativeTo.mapToItem(null, relativeX, relativeY).x
|
||||
this.y = relativeTo.mapToItem(null, relativeX, relativeY).y
|
||||
}
|
||||
|
||||
_isOpen = true
|
||||
}
|
||||
|
||||
function hideMenu () {
|
||||
if (!_isOpen) {
|
||||
return
|
||||
}
|
||||
|
||||
_isOpen = false
|
||||
}
|
||||
|
||||
function _computeHeight () {
|
||||
throw new Error('Virtual method must be implemented.')
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
implicitHeight: 0
|
||||
opacity: 0
|
||||
visible: false
|
||||
z: Constants.zPopup
|
||||
|
||||
Keys.onEscapePressed: hideMenu()
|
||||
|
||||
// Set parent menu to root.
|
||||
Component.onCompleted: {
|
||||
if (relativeTo != null) {
|
||||
parent = Utils.getTopParent(this)
|
||||
}
|
||||
}
|
||||
|
||||
// Handle clicks, wheel... below menu.
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onWheel: {}
|
||||
}
|
||||
|
||||
// Menu content.
|
||||
Rectangle {
|
||||
id: content
|
||||
|
||||
anchors.fill: parent
|
||||
color: PopupStyle.backgroundColor
|
||||
|
||||
layer {
|
||||
enabled: true
|
||||
effect: PopupShadow {}
|
||||
}
|
||||
}
|
||||
|
||||
// Inverted mouse area to detect click outside menu.
|
||||
InvertedMouseArea {
|
||||
anchors.fill: parent
|
||||
enabled: parent.visible
|
||||
|
||||
onPressed: {
|
||||
if (launcher == null || !pointIsInItem(launcher)) {
|
||||
hideMenu()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
states: State {
|
||||
name: 'opened'
|
||||
when: _isOpen
|
||||
|
||||
PropertyChanges {
|
||||
focus: true // Necessary to use `Keys.onEscapePressed`.
|
||||
implicitHeight: _computeHeight()
|
||||
opacity: 1.0
|
||||
target: menu
|
||||
}
|
||||
}
|
||||
|
||||
transitions: [
|
||||
Transition {
|
||||
from: ''
|
||||
to: 'opened'
|
||||
|
||||
ScriptAction {
|
||||
script: {
|
||||
menu.visible = true
|
||||
menuOpened()
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Transition {
|
||||
from: 'opened'
|
||||
to: ''
|
||||
|
||||
SequentialAnimation {
|
||||
ScriptAction {
|
||||
script: {
|
||||
menuClosed()
|
||||
visible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
import QtQuick 2.7
|
||||
|
||||
import Common 1.0
|
||||
import Utils 1.0
|
||||
|
||||
// =============================================================================
|
||||
// Menu which supports `ListView`.
|
||||
// =============================================================================
|
||||
|
||||
AbstractDropDownMenu {
|
||||
// Can be computed, but for performance usage, it must be given in attribute.
|
||||
property int entryHeight
|
||||
property int maxMenuHeight
|
||||
|
||||
function _computeHeight () {
|
||||
Utils.assert(_content != null && _content.length > 0, '`_content` cannot be null and must exists.')
|
||||
|
||||
var list = _content[0]
|
||||
Utils.assert(list != null, 'No list found.')
|
||||
Utils.assert(
|
||||
Utils.qmlTypeof(list, 'QQuickListView') || Utils.qmlTypeof(list, 'ScrollableListView'),
|
||||
'No list view parameter.'
|
||||
)
|
||||
|
||||
var height = list.count * entryHeight
|
||||
|
||||
if (list.headerPositioning === ListView.OverlayHeader) {
|
||||
// Workaround to force header layout.
|
||||
list.headerItem.z = Constants.zMax
|
||||
|
||||
height += list.headerItem.height
|
||||
}
|
||||
|
||||
return (maxMenuHeight !== undefined && height > maxMenuHeight)
|
||||
? maxMenuHeight
|
||||
: height
|
||||
}
|
||||
}
|
||||
|
|
@ -18,6 +18,11 @@ Item {
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
signal hidden
|
||||
signal shown
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
visible: false
|
||||
|
||||
function show () {
|
||||
|
|
@ -79,5 +84,8 @@ Item {
|
|||
padding: 0
|
||||
|
||||
Component.onCompleted: parent = Utils.getTopParent(this)
|
||||
|
||||
onClosed: wrapper.hidden()
|
||||
onOpened: wrapper.shown()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ VuMeter 1.0 Indicators/VuMeter.qml
|
|||
|
||||
ActionMenu 1.0 Menus/ActionMenu.qml
|
||||
ActionMenuEntry 1.0 Menus/ActionMenuEntry.qml
|
||||
DropDownDynamicMenu 1.0 Menus/DropDownDynamicMenu.qml
|
||||
Menu 1.0 Menus/Menu.qml
|
||||
|
||||
Borders 1.0 Misc/Borders.qml
|
||||
|
|
@ -71,7 +72,6 @@ ForceScrollBar 1.0 Misc/ForceScrollBar.qml
|
|||
Paned 1.0 Misc/Paned.qml
|
||||
|
||||
DesktopPopup 1.0 Popup/DesktopPopup.qml
|
||||
DropDownDynamicMenu 1.0 Popup/DropDownDynamicMenu.qml
|
||||
Popup 1.0 Popup/Popup.qml
|
||||
PopupShadow 1.0 Popup/PopupShadow.qml
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
.pragma library
|
||||
|
||||
.import QtQuick 2.0 as QtQuick
|
||||
.import QtQuick 2.7 as QtQuick
|
||||
|
||||
.import 'port-tools.js' as PortTools
|
||||
.import 'uri-tools.js' as UriTools
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.0
|
||||
import QtQuick.Controls 2.1
|
||||
import QtQuick.Window 2.2
|
||||
|
||||
import Utils 1.0
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue