Skip to content

Commit

Permalink
Add a filter to the plugin menu (#277)
Browse files Browse the repository at this point in the history
Signed-off-by: Louise Poubel <[email protected]>
  • Loading branch information
chapulina authored Sep 2, 2021
1 parent cdc6eac commit 242dd40
Show file tree
Hide file tree
Showing 5 changed files with 230 additions and 14 deletions.
86 changes: 86 additions & 0 deletions include/ignition/gui/qml/IgnSortFilterModel.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright (C) 2021 Open Source Robotics Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

// Borrowed from
// https://martin.rpdev.net/2019/01/15/using-delegatemodel-in-qml-for-sorting-and-filtering.html

import QtQuick 2.9
import QtQml.Models 2.3

DelegateModel {
/**
* Used by sorting. Override it to create custom sort behaviour.
*/
property var lessThan: function(_left, _right)
{
return true;
}

/**
* Override this function to define what items should be accepted or not.
*/
property var filterAcceptsItem: function(_item)
{
return true;
}

/**
* Update the item list
*/
function update() {
if (items.count > 0) {
items.setGroups(0, items.count, "items");
}

// Step 1: Filter items
var visible = [];
for (var i = 0; i < items.count; ++i) {
var item = items.get(i);
if (filterAcceptsItem(item.model)) {
visible.push(item);
}
}

// Step 2: Sort the list of visible items
visible.sort(function(_a, _b) {
return lessThan(_a.model, _b.model) ? -1 : 1;
});

// Step 3: Add all items to the visible group:
for (i = 0; i < visible.length; ++i) {
item = visible[i];
item.inVisible = true;
if (item.visibleIndex !== i) {
visibleItems.move(item.visibleIndex, i, 1);
}
}
}

items.onChanged: update()
onLessThanChanged: update()
onFilterAcceptsItemChanged: update()

groups: DelegateModelGroup {
id: visibleItems

name: "visible"
includeByDefault: false
}

filterOnGroup: "visible"
}

3 changes: 2 additions & 1 deletion include/ignition/gui/qml/Main.qml
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,10 @@ ApplicationWindow

PluginMenu {
id: pluginMenu
width: 200
x: parent.width - width
height: window.height * 0.3
transformOrigin: Menu.TopRight
transformOrigin: Popup.TopRight
}
}
}
Expand Down
90 changes: 77 additions & 13 deletions include/ignition/gui/qml/PluginMenu.qml
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,92 @@
*/
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.2
import QtQuick.Controls.Material.impl 2.2
import QtQuick.Layouts 1.3

Menu {
Popup {
id: pluginMenu
padding: 0

Connections {
target: MainWindow
onConfigChanged: {
pluginMenuListView.model = MainWindow.PluginListModel()
filteredModel.model = MainWindow.PluginListModel()
}
}

ListView {
id: pluginMenuListView
height: pluginMenu.height
/**
* Color for search bar
*/
property color searchColor: (Material.theme == Material.Light) ?
Material.color(Material.Grey, Material.Shade200):
Material.color(Material.Grey, Material.Shade900);

onOpened: searchField.forceActiveFocus()

ColumnLayout {
anchors.fill: parent
spacing: 0

Rectangle {
id: searchSortBar
color: searchColor
height: 50
width: parent.width
RowLayout {
id: rowLayout
anchors.fill: parent
spacing: 0
Rectangle {
color: "transparent"
height: 25
width: 25
Layout.leftMargin: 5
Image {
id: searchIcon
source: "images/search.svg"
anchors.verticalCenter: parent.verticalCenter
}
}
TextField {
id: searchField
Layout.fillHeight: true
Layout.preferredWidth: parent.width - 50
selectByMouse: true
onTextEdited: {
filteredModel.update();
}
}
}
}

ListView {
id: pluginMenuListView
Layout.fillHeight: true
width: parent.width
clip: true

model: filteredModel

ScrollBar.vertical: ScrollBar {
active: true
width: 8
policy: ScrollBar.AlwaysOn
}
}
}

IgnSortFilterModel {
id: filteredModel

filterAcceptsItem: function(item) {
var itemStr = item.modelData.toLowerCase();
var filterStr = searchField.text.toLowerCase();
return itemStr.includes(filterStr);
}

model: MainWindow.PluginListModel()

delegate: ItemDelegate {
width: parent.width
Expand All @@ -41,14 +113,6 @@ Menu {
pluginMenu.close()
}
}

model: MainWindow.PluginListModel()

ScrollBar.vertical: ScrollBar {
active: true
width: 8
policy: ScrollBar.AlwaysOn
}
}
}

63 changes: 63 additions & 0 deletions include/ignition/gui/qml/images/search.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions include/ignition/gui/resources.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<file>qml/IgnCardSettings.qml</file>
<file>qml/IgnHelpers.qml</file>
<file>qml/IgnRulers.qml</file>
<file>qml/IgnSortFilterModel.qml</file>
<file>qml/IgnSpinBox.qml</file>
<file>qml/IgnSplit.qml</file>
<file>qml/Main.qml</file>
Expand All @@ -17,5 +18,6 @@
<file>qml/images/ignition_logo_50x50.png</file>
<file>qml/images/drawer.png</file>
<file>qml/images/menu.png</file>
<file>qml/images/search.svg</file>
</qresource>
</RCC>

0 comments on commit 242dd40

Please sign in to comment.