From 401d7c2847d9dc1bd1e12d0b3a610fb37f241c6d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= <manuq@laptop.org>
Date: Tue, 9 Oct 2012 15:36:23 -0300
Subject: [PATCH shell] Improve search in views normalizing the strings - SL
#3588
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Mail-Followup-To: <sugar-devel@lists.sugarlabs.org>
The strings returned by Gtk have to be converted to Unicode because we
use Python 2. In Python 3 this will not be needed [1] [2] .
[1] http://python-gtk-3-tutorial.readthedocs.org/en/latest/unicode.html
[2] https://mail.gnome.org/archives/python-hackers-list/2012-June/msg00012.html
Signed-off-by: Manuel Quiñones <manuq@laptop.org>
---
src/jarabe/desktop/Makefile.am | 3 ++-
src/jarabe/desktop/activitieslist.py | 6 ++++--
src/jarabe/desktop/favoritesview.py | 6 ++++--
src/jarabe/desktop/groupbox.py | 3 ++-
src/jarabe/desktop/homebox.py | 3 ++-
src/jarabe/desktop/meshbox.py | 5 +++--
src/jarabe/desktop/networkviews.py | 4 +++-
src/jarabe/desktop/tools.py | 30 ++++++++++++++++++++++++++++++
src/jarabe/view/buddyicon.py | 5 ++++-
9 files changed, 54 insertions(+), 11 deletions(-)
create mode 100644 src/jarabe/desktop/tools.py
diff --git a/src/jarabe/desktop/Makefile.am b/src/jarabe/desktop/Makefile.am
index e27bc9c..8150db8 100644
a
|
b
|
sugar_PYTHON = \ |
16 | 16 | snowflakelayout.py \ |
17 | 17 | transitionbox.py \ |
18 | 18 | viewcontainer.py \ |
19 | | viewtoolbar.py |
| 19 | viewtoolbar.py \ |
| 20 | tools.py |
diff --git a/src/jarabe/desktop/activitieslist.py b/src/jarabe/desktop/activitieslist.py
index 3b07e87..1eb7199 100644
a
|
b
|
from sugar3.graphics.alert import Alert |
36 | 36 | from jarabe.model import bundleregistry |
37 | 37 | from jarabe.view.palettes import ActivityPalette |
38 | 38 | from jarabe.journal import misc |
| 39 | from jarabe.desktop.tools import normalize_string |
39 | 40 | |
40 | 41 | |
41 | 42 | class ActivitiesTreeView(Gtk.TreeView): |
… |
… |
class ActivitiesTreeView(Gtk.TreeView): |
153 | 154 | of matching activities. |
154 | 155 | |
155 | 156 | """ |
156 | | self._query = query.lower() |
| 157 | self._query = normalize_string(query.decode('utf-8')) |
157 | 158 | self.get_model().refilter() |
158 | 159 | matches = self.get_model().iter_n_children(None) |
159 | 160 | return matches |
160 | 161 | |
161 | 162 | def __model_visible_cb(self, model, tree_iter, data): |
162 | 163 | title = model[tree_iter][ListModel.COLUMN_TITLE] |
163 | | return title is not None and title.lower().find(self._query) > -1 |
| 164 | title = normalize_string(title.decode('utf-8')) |
| 165 | return title is not None and title.find(self._query) > -1 |
164 | 166 | |
165 | 167 | |
166 | 168 | class ListModel(Gtk.TreeModelSort): |
diff --git a/src/jarabe/desktop/favoritesview.py b/src/jarabe/desktop/favoritesview.py
index aae745a..3848f5f 100644
a
|
b
|
from jarabe.desktop import schoolserver |
50 | 50 | from jarabe.desktop.schoolserver import RegisterError |
51 | 51 | from jarabe.desktop import favoriteslayout |
52 | 52 | from jarabe.desktop.viewcontainer import ViewContainer |
| 53 | from jarabe.desktop.tools import normalize_string |
53 | 54 | |
54 | 55 | |
55 | 56 | _logger = logging.getLogger('FavoritesView') |
… |
… |
class FavoritesView(ViewContainer): |
312 | 313 | query = query.strip() |
313 | 314 | for icon in self.get_children(): |
314 | 315 | if icon not in [self._owner_icon, self._activity_icon]: |
315 | | activity_name = icon.get_activity_name().lower() |
316 | | if activity_name.find(query) > -1: |
| 316 | activity_name = icon.get_activity_name().decode('utf-8') |
| 317 | normalized_name = normalize_string(activity_name) |
| 318 | if normalized_name.find(query) > -1: |
317 | 319 | icon.alpha = 1.0 |
318 | 320 | else: |
319 | 321 | icon.alpha = 0.33 |
diff --git a/src/jarabe/desktop/groupbox.py b/src/jarabe/desktop/groupbox.py
index f916f62..e1f3ae7 100644
a
|
b
|
from jarabe.model import friends |
24 | 24 | from jarabe.desktop.friendview import FriendView |
25 | 25 | from jarabe.desktop.viewcontainer import ViewContainer |
26 | 26 | from jarabe.desktop.favoriteslayout import SpreadLayout |
| 27 | from jarabe.desktop.tools import normalize_string |
27 | 28 | |
28 | 29 | |
29 | 30 | class GroupBox(ViewContainer): |
… |
… |
class GroupBox(ViewContainer): |
69 | 70 | icon.destroy() |
70 | 71 | |
71 | 72 | def _toolbar_query_changed_cb(self, toolbar, query): |
72 | | self._query = query.lower() |
| 73 | self._query = normalize_string(query.decode('utf-8')) |
73 | 74 | for icon in self.get_children(): |
74 | 75 | if hasattr(icon, 'set_filter'): |
75 | 76 | icon.set_filter(self._query) |
diff --git a/src/jarabe/desktop/homebox.py b/src/jarabe/desktop/homebox.py
index ed5144b..f39e3e0 100644
a
|
b
|
from sugar3.graphics.icon import Icon |
27 | 27 | |
28 | 28 | from jarabe.desktop import favoritesview |
29 | 29 | from jarabe.desktop.activitieslist import ActivitiesList |
| 30 | from jarabe.desktop.tools import normalize_string |
30 | 31 | |
31 | 32 | _FAVORITES_VIEW = 0 |
32 | 33 | _LIST_VIEW = 1 |
… |
… |
class HomeBox(Gtk.VBox): |
100 | 101 | panel.set_section_view_auto_close() |
101 | 102 | |
102 | 103 | def __toolbar_query_changed_cb(self, toolbar, query): |
103 | | self._query = query.lower() |
| 104 | self._query = normalize_string(query.decode('utf-8')) |
104 | 105 | self._list_view.set_filter(self._query) |
105 | 106 | self._favorites_box.set_filter(self._query) |
106 | 107 | |
diff --git a/src/jarabe/desktop/meshbox.py b/src/jarabe/desktop/meshbox.py
index e1c8381..a1adb87 100644
a
|
b
|
from sugar3.graphics import style |
32 | 32 | from sugar3.graphics import palette |
33 | 33 | from sugar3.graphics.menuitem import MenuItem |
34 | 34 | |
35 | | from jarabe.desktop.snowflakelayout import SnowflakeLayout |
36 | 35 | from jarabe.model import neighborhood |
37 | 36 | from jarabe.model.buddy import get_owner_instance |
38 | 37 | from jarabe.view.buddyicon import BuddyIcon |
| 38 | from jarabe.desktop.snowflakelayout import SnowflakeLayout |
39 | 39 | from jarabe.desktop.networkviews import WirelessNetworkView |
40 | 40 | from jarabe.desktop.networkviews import OlpcMeshView |
41 | 41 | from jarabe.desktop.networkviews import SugarAdhocView |
42 | 42 | from jarabe.desktop.viewcontainer import ViewContainer |
43 | 43 | from jarabe.desktop.favoriteslayout import SpreadLayout |
| 44 | from jarabe.desktop.tools import normalize_string |
44 | 45 | from jarabe.model import network |
45 | 46 | from jarabe.model.network import AccessPoint |
46 | 47 | from jarabe.model.olpcmesh import OlpcMeshManager |
… |
… |
class MeshBox(ViewContainer): |
588 | 589 | net.props.paused = False |
589 | 590 | |
590 | 591 | def _toolbar_query_changed_cb(self, toolbar, query): |
591 | | self._query = query.lower() |
| 592 | self._query = normalize_string(query.decode('utf-8')) |
592 | 593 | for icon in self.get_children(): |
593 | 594 | if hasattr(icon, 'set_filter'): |
594 | 595 | icon.set_filter(self._query) |
diff --git a/src/jarabe/desktop/networkviews.py b/src/jarabe/desktop/networkviews.py
index c949b7e..1adba94 100644
a
|
b
|
from sugar3 import profile |
35 | 35 | |
36 | 36 | from jarabe.view.pulsingicon import EventPulsingIcon |
37 | 37 | from jarabe.desktop import keydialog |
| 38 | from jarabe.desktop.tools import normalize_string |
38 | 39 | from jarabe.model import network |
39 | 40 | from jarabe.model.network import Settings |
40 | 41 | from jarabe.model.network import IP4Config |
… |
… |
class WirelessNetworkView(EventPulsingIcon): |
369 | 370 | self.get_first_ap().model) |
370 | 371 | |
371 | 372 | def set_filter(self, query): |
372 | | self._filtered = self._display_name.lower().find(query) == -1 |
| 373 | normalized_name = normalize_string(self._display_name.decode('utf-8')) |
| 374 | self._filtered = normalized_name.find(query) == -1 |
373 | 375 | self._update_icon() |
374 | 376 | self._update_color() |
375 | 377 | |
diff --git a/src/jarabe/desktop/tools.py b/src/jarabe/desktop/tools.py
new file mode 100644
index 0000000..f87d356
-
|
+
|
|
| 1 | # -*- coding: utf-8 -*- |
| 2 | # Copyright (C) 2012 One Laptop Per Child |
| 3 | # |
| 4 | # This program is free software; you can redistribute it and/or modify |
| 5 | # it under the terms of the GNU General Public License as published by |
| 6 | # the Free Software Foundation; either version 2 of the License, or |
| 7 | # (at your option) any later version. |
| 8 | # |
| 9 | # This program is distributed in the hope that it will be useful, |
| 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 | # GNU General Public License for more details. |
| 13 | # |
| 14 | # You should have received a copy of the GNU General Public License |
| 15 | # along with this program; if not, write to the Free Software |
| 16 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| 17 | |
| 18 | from unicodedata import normalize |
| 19 | |
| 20 | def normalize_string(unicode_string): |
| 21 | u"""Return unicode_string normalized for searching. |
| 22 | |
| 23 | >>> normalize_string(u'Mónica Viñao') |
| 24 | 'monica vinao' |
| 25 | |
| 26 | >>> normalize_string(u'Ãbaco') |
| 27 | 'abaco' |
| 28 | |
| 29 | """ |
| 30 | return normalize('NFKD', unicode_string).encode('ASCII', 'ignore').lower() |
diff --git a/src/jarabe/view/buddyicon.py b/src/jarabe/view/buddyicon.py
index 59c3690..f80ac54 100644
a
|
b
|
from sugar3.graphics.palette import Palette |
19 | 19 | from sugar3.graphics.icon import EventIcon |
20 | 20 | |
21 | 21 | from jarabe.view.buddymenu import BuddyMenu |
| 22 | from jarabe.desktop.tools import normalize_string |
22 | 23 | |
23 | 24 | |
24 | 25 | _FILTERED_ALPHA = 0.33 |
… |
… |
class BuddyIcon(EventIcon): |
68 | 69 | palette.props.icon.props.xo_color = self._buddy.get_color() |
69 | 70 | |
70 | 71 | def set_filter(self, query): |
71 | | self._filtered = (self._buddy.get_nick().lower().find(query) == -1) \ |
| 72 | normalized_name = normalize_string( |
| 73 | self._buddy.get_nick().decode('utf-8')) |
| 74 | self._filtered = (normalized_name.find(query) == -1) \ |
72 | 75 | and not self._buddy.is_owner() |
73 | 76 | self._update_color() |