1
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2
# Copyright 2012 Canonical
3
# Author: Thomi Richards
5
# This program is free software: you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License version 3, as published
7
# by the Free Software Foundation.
10
from time import sleep
12
from autopilot.emulators.unity import (
14
make_introspection_object,
15
UnityIntrospectionObject,
17
from autopilot.emulators.X11 import Keyboard, Mouse
18
from autopilot.keybindings import KeybindingsHelper
23
logger = logging.getLogger(__name__)
26
class Dash(KeybindingsHelper):
28
An emulator class that makes it easier to interact with the unity dash.
32
self.controller = DashController.get_all_instances()[0]
33
self.view = self.controller.get_dash_view()
35
self._keyboard = Keyboard()
36
super(Dash, self).__init__()
38
def toggle_reveal(self):
40
Reveals the dash if it's currently hidden, hides it otherwise.
42
logger.debug("Toggling dash visibility with Super key.")
43
self.keybinding("dash/reveal")
46
def ensure_visible(self, clear_search=True):
48
Ensures the dash is visible.
50
if not self.get_is_visible():
52
self._wait_for_visibility(expect_visible=True)
56
def ensure_hidden(self):
58
Ensures the dash is hidden.
60
if self.get_is_visible():
62
self._wait_for_visibility(expect_visible=False)
64
def _wait_for_visibility(self, expect_visible):
66
if self.get_is_visible() != expect_visible:
70
raise RuntimeError("Dash not %s after waiting for 10 seconds." %
71
("Visible" if expect_visible else "Hidden"))
73
def get_is_visible(self):
77
return self.controller.visible
79
def get_searchbar(self):
80
"""Returns the searchbar attached to the dash."""
81
return self.view.get_searchbar()
83
def get_num_rows(self):
84
"""Returns the number of displayed rows in the dash."""
85
return self.view.num_rows
87
def clear_search(self):
88
"""Clear the contents of the search bar.
90
Assumes dash is already visible, and search bar has keyboard focus.
93
self._keyboard.press_and_release("Ctrl+a")
94
self._keyboard.press_and_release("Delete")
96
def reveal_application_lens(self, clear_search=True):
97
"""Reveal the application lense."""
98
logger.debug("Revealing application lens with Super+a.")
99
self._reveal_lens("lens_reveal/apps")
103
def reveal_music_lens(self, clear_search=True):
104
"""Reveal the music lense."""
105
logger.debug("Revealing music lens with Super+m.")
106
self._reveal_lens("lens_reveal/music")
108
def reveal_file_lens(self, clear_search=True):
109
"""Reveal the file lense."""
110
logger.debug("Revealing file lens with Super+f.")
111
self._reveal_lens("lens_reveal/files")
115
def reveal_command_lens(self, clear_search=True):
116
"""Reveal the 'run command' lens."""
117
logger.debug("Revealing command lens with Alt+F2.")
118
self._reveal_lens("lens_reveal/command")
122
def _reveal_lens(self, binding_name):
123
self.keybinding_hold(binding_name)
124
self.keybinding_tap(binding_name)
125
self.keybinding_release(binding_name)
127
def get_current_lens(self):
128
"""Get the currently-active LensView object."""
129
active_lens_name = self.view.get_lensbar().active_lens
130
return self.view.get_lensview_by_name(active_lens_name)
132
def close_with_alt_f4(self):
133
"""Send ALT+F4 in order to close the dash."""
134
self._keyboard.press_and_release("Alt+F4")
137
class DashController(UnityIntrospectionObject):
138
"""The main dash controller object."""
140
def get_dash_view(self):
141
"""Get the dash view that's attached to this controller."""
142
return self.get_children_by_type(DashView)[0]
145
class DashView(UnityIntrospectionObject):
148
def get_searchbar(self):
149
"""Get the search bar attached to this dash view."""
150
return self.get_children_by_type(SearchBar)[0]
152
def get_lensbar(self):
153
"""Get the lensbar attached to this dash view."""
154
return self.get_children_by_type(LensBar)[0]
156
def get_lensview_by_name(self, lens_name):
157
"""Get a LensView child object by it's name. For example, "home.lens"."""
158
lenses = self.get_children_by_type(LensView)
160
if lens.name == lens_name:
164
class SearchBar(UnityIntrospectionObject):
165
"""The search bar for the dash view."""
168
class LensBar(UnityIntrospectionObject):
169
"""The bar of lens icons at the bottom of the dash."""
172
class LensView(UnityIntrospectionObject):
175
def get_groups(self):
176
"""Get a list of all groups within this lensview. May return an empty list."""
177
groups = self.get_children_by_type(PlacesGroup)
180
def get_focused_category(self):
181
"""Return a PlacesGroup instance for the category whose header has keyboard focus.
183
Returns None if no category headers have keyboard focus.
186
categories = self.get_children_by_type(PlacesGroup)
187
matches = [m for m in categories if m.header_has_keyfocus]
192
def get_category_by_name(self, category_name):
193
"""Return a PlacesGroup instance with the given name, or None."""
194
categories = self.get_children_by_type(PlacesGroup)
195
matches = [m for m in categories if m.name == category_name]
200
def get_num_visible_categories(self):
201
"""Get the number of visible categories in this lens."""
202
return len([c for c in self.get_children_by_type(PlacesGroup) if c.is_visible])
204
def get_filterbar(self):
205
"""Get the filter bar for the current lense, or None if it doesn't have one."""
206
bars = self.get_children_by_type(FilterBar)
212
class PlacesGroup(UnityIntrospectionObject):
213
"""A category in the lense view."""
215
def get_results(self):
216
"""Get a list of all results within this category. May return an empty list."""
217
result_view = self.get_children_by_type(ResultView)[0]
218
return result_view.get_children_by_type(Result)
221
class ResultView(UnityIntrospectionObject):
222
"""Contains a list of Result objects."""
225
class Result(UnityIntrospectionObject):
226
"""A single result in the dash."""
229
class FilterBar(UnityIntrospectionObject):
230
"""A filterbar, as shown inside a lens."""
232
def get_num_filters(self):
233
"""Get the number of filters in this filter bar."""
234
filters = self.get_children_by_type(FilterExpanderLabel)
237
def get_focused_filter(self):
238
"""Returns the id of the focused filter widget."""
239
filters = self.get_children_by_type(FilterExpanderLabel)
240
for filter_label in filters:
241
if filter_label.expander_has_focus:
245
def is_expanded(self):
246
"""Return True if the filterbar on this lens is expanded, False otherwise.
248
searchbar = self._get_searchbar()
249
return searchbar.showing_filters
251
def ensure_expanded(self):
252
"""Expand the filter bar, if it's not already."""
253
if not self.is_expanded():
254
searchbar = self._get_searchbar()
255
tx = searchbar.filter_label_x + (searchbar.filter_label_width / 2)
256
ty = searchbar.filter_label_y + (searchbar.filter_label_height / 2)
261
def ensure_collapsed(self):
262
"""Collapse the filter bar, if it's not already."""
263
if self.is_expanded():
264
searchbar = self._get_searchbar()
265
tx = searchbar.filter_label_x + (searchbar.filter_label_width / 2)
266
ty = searchbar.filter_label_y + (searchbar.filter_label_height / 2)
271
def _get_searchbar(self):
272
"""Get the searchbar.
274
This hack exists because there's now more than one SearchBar in Unity,
275
and for some reason the FilterBar stuff is bundled in the SearchBar.
278
state_info = get_state_by_path("//DashView/SearchBar")
279
assert(len(state_info) == 1)
280
return make_introspection_object(("SearchBar", state_info[0]))
283
class FilterExpanderLabel(UnityIntrospectionObject):
284
"""A label that expands into a filter within a filter bar."""