Back to index

unity  6.0.0
dash.py
Go to the documentation of this file.
00001 # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
00002 # Copyright 2012 Canonical
00003 # Author: Thomi Richards
00004 #
00005 # This program is free software: you can redistribute it and/or modify it
00006 # under the terms of the GNU General Public License version 3, as published
00007 # by the Free Software Foundation.
00008 #
00009 
00010 from __future__ import absolute_import
00011 
00012 from autopilot.introspection.dbus import make_introspection_object
00013 from autopilot.emulators.X11 import Keyboard, Mouse
00014 from autopilot.keybindings import KeybindingsHelper
00015 
00016 from unity.emulators import UnityIntrospectionObject
00017 import logging
00018 
00019 
00020 logger = logging.getLogger(__name__)
00021 
00022 
00023 class Dash(KeybindingsHelper):
00024     """
00025     An emulator class that makes it easier to interact with the unity dash.
00026     """
00027 
00028     def __init__(self):
00029         super(Dash, self).__init__()
00030         controllers = DashController.get_all_instances()
00031         assert(len(controllers) == 1)
00032         self.controller = controllers[0]
00033         self._keyboard = Keyboard()
00034 
00035     @property
00036     def view(self):
00037         return self.controller.get_dash_view()
00038 
00039     def toggle_reveal(self):
00040         """
00041         Reveals the dash if it's currently hidden, hides it otherwise.
00042         """
00043         old_state = self.visible
00044         logger.debug("Toggling dash visibility with Super key.")
00045         self.keybinding("dash/reveal", 0.1)
00046         self.visible.wait_for(not old_state)
00047 
00048     def ensure_visible(self, clear_search=True):
00049         """
00050         Ensures the dash is visible.
00051         """
00052         if not self.visible:
00053             self.toggle_reveal()
00054             self.visible.wait_for(True)
00055             if clear_search:
00056                 self.clear_search()
00057 
00058     def ensure_hidden(self):
00059         """
00060         Ensures the dash is hidden.
00061         """
00062         if self.visible:
00063             self.toggle_reveal()
00064             self.visible.wait_for(False)
00065 
00066     @property
00067     def visible(self):
00068         """Returns if the dash is currently visible"""
00069         return self.controller.visible
00070 
00071     @property
00072     def monitor(self):
00073         """The monitor where the dash is"""
00074         return self.controller.monitor
00075 
00076     @property
00077     def search_string(self):
00078         return self.searchbar.search_string
00079 
00080     @property
00081     def searchbar(self):
00082         """Returns the searchbar attached to the dash."""
00083         return self.view.get_searchbar()
00084 
00085     def get_num_rows(self):
00086         """Returns the number of displayed rows in the dash."""
00087         return self.view.num_rows
00088 
00089     def clear_search(self):
00090         """Clear the contents of the search bar.
00091 
00092         Assumes dash is already visible, and search bar has keyboard focus.
00093 
00094         """
00095         self._keyboard.press_and_release("Ctrl+a")
00096         self._keyboard.press_and_release("Delete")
00097         self.search_string.wait_for("")
00098 
00099     def reveal_application_lens(self, clear_search=True):
00100         """Reveal the application lense."""
00101         logger.debug("Revealing application lens with Super+a.")
00102         self._reveal_lens("lens_reveal/apps", clear_search)
00103         return self.view.get_lensview_by_name("applications.lens")
00104 
00105     def reveal_music_lens(self, clear_search=True):
00106         """Reveal the music lense."""
00107         logger.debug("Revealing music lens with Super+m.")
00108         self._reveal_lens("lens_reveal/music", clear_search)
00109         return self.view.get_lensview_by_name("music.lens")
00110 
00111     def reveal_file_lens(self, clear_search=True):
00112         """Reveal the file lense."""
00113         logger.debug("Revealing file lens with Super+f.")
00114         self._reveal_lens("lens_reveal/files", clear_search)
00115         return self.view.get_lensview_by_name("files.lens")
00116 
00117     def reveal_command_lens(self, clear_search=True):
00118         """Reveal the 'run command' lens."""
00119         logger.debug("Revealing command lens with Alt+F2.")
00120         self._reveal_lens("lens_reveal/command", clear_search)
00121         return self.view.get_lensview_by_name("commands.lens")
00122 
00123     def _reveal_lens(self, binding_name, clear_search):
00124         self.keybinding_hold(binding_name)
00125         self.keybinding_tap(binding_name)
00126         self.keybinding_release(binding_name)
00127         self.visible.wait_for(True)
00128         if clear_search:
00129             self.clear_search()
00130 
00131     @property
00132     def active_lens(self):
00133         return self.view.get_lensbar().active_lens
00134 
00135     def get_current_lens(self):
00136         """Get the currently-active LensView object."""
00137         active_lens_name = self.view.get_lensbar().active_lens
00138         return self.view.get_lensview_by_name(active_lens_name)
00139 
00140 
00141 class DashController(UnityIntrospectionObject):
00142     """The main dash controller object."""
00143 
00144     def get_dash_view(self):
00145         """Get the dash view that's attached to this controller."""
00146         return self.get_children_by_type(DashView)[0]
00147 
00148 
00149 class DashView(UnityIntrospectionObject):
00150     """The dash view."""
00151 
00152     def get_searchbar(self):
00153         """Get the search bar attached to this dash view."""
00154         return self.get_children_by_type(SearchBar)[0]
00155 
00156     def get_lensbar(self):
00157         """Get the lensbar attached to this dash view."""
00158         return self.get_children_by_type(LensBar)[0]
00159 
00160     def get_lensview_by_name(self, lens_name):
00161         """Get a LensView child object by it's name. For example, "home.lens"."""
00162         lenses = self.get_children_by_type(LensView)
00163         for lens in lenses:
00164             if lens.name == lens_name:
00165                 return lens
00166 
00167 
00168 class SearchBar(UnityIntrospectionObject):
00169     """The search bar for the dash view."""
00170 
00171 
00172 class LensBar(UnityIntrospectionObject):
00173     """The bar of lens icons at the bottom of the dash."""
00174     def get_icon_by_name(self, name):
00175         """Get a LensBarIcon child object by it's name. For example, 'home.lens'."""
00176         icons = self.get_children_by_type(LensBarIcon)
00177         for icon in icons:
00178             if icon.name == name:
00179                 return icon
00180 
00181 class LensBarIcon(UnityIntrospectionObject):
00182     """A lens icon at the bottom of the dash."""
00183 
00184 
00185 class LensView(UnityIntrospectionObject):
00186     """A Lens View."""
00187 
00188     def get_groups(self):
00189         """Get a list of all groups within this lensview. May return an empty list."""
00190         groups = self.get_children_by_type(PlacesGroup)
00191         return groups
00192 
00193     def get_focused_category(self):
00194         """Return a PlacesGroup instance for the category whose header has keyboard focus.
00195 
00196         Returns None if no category headers have keyboard focus.
00197 
00198         """
00199         categories = self.get_children_by_type(PlacesGroup)
00200         matches = [m for m in categories if m.header_has_keyfocus]
00201         if matches:
00202             return matches[0]
00203         return None
00204 
00205     def get_category_by_name(self, category_name):
00206         """Return a PlacesGroup instance with the given name, or None."""
00207         categories = self.get_children_by_type(PlacesGroup)
00208         matches = [m for m in categories if m.name == category_name]
00209         if matches:
00210             return matches[0]
00211         return None
00212 
00213     def get_num_visible_categories(self):
00214         """Get the number of visible categories in this lens."""
00215         return len([c for c in self.get_children_by_type(PlacesGroup) if c.is_visible])
00216 
00217     def get_filterbar(self):
00218         """Get the filter bar for the current lense, or None if it doesn't have one."""
00219         bars = self.get_children_by_type(FilterBar)
00220         if bars:
00221             return bars[0]
00222         return None
00223 
00224 
00225 class PlacesGroup(UnityIntrospectionObject):
00226     """A category in the lense view."""
00227 
00228     def get_results(self):
00229         """Get a list of all results within this category. May return an empty list."""
00230         result_view = self.get_children_by_type(ResultView)[0]
00231         return result_view.get_children_by_type(Result)
00232 
00233 
00234 class ResultView(UnityIntrospectionObject):
00235     """Contains a list of Result objects."""
00236 
00237 
00238 class Result(UnityIntrospectionObject):
00239     """A single result in the dash."""
00240 
00241 
00242 class FilterBar(UnityIntrospectionObject):
00243     """A filterbar, as shown inside a lens."""
00244 
00245     def get_num_filters(self):
00246         """Get the number of filters in this filter bar."""
00247         filters = self.get_children_by_type(FilterExpanderLabel)
00248         return len(filters)
00249 
00250     def get_focused_filter(self):
00251         """Returns the id of the focused filter widget."""
00252         filters = self.get_children_by_type(FilterExpanderLabel)
00253         for filter_label in filters:
00254             if filter_label.expander_has_focus:
00255                 return filter_label
00256         return None
00257 
00258     @property
00259     def expanded(self):
00260         """Return True if the filterbar on this lens is expanded, False otherwise.
00261         """
00262         searchbar = self._get_searchbar()
00263         return searchbar.showing_filters
00264 
00265     def ensure_expanded(self):
00266         """Expand the filter bar, if it's not already."""
00267         if not self.expanded:
00268             searchbar = self._get_searchbar()
00269             tx = searchbar.filter_label_x + (searchbar.filter_label_width / 2)
00270             ty = searchbar.filter_label_y + (searchbar.filter_label_height / 2)
00271             m = Mouse()
00272             m.move(tx, ty)
00273             m.click()
00274             self.expanded.wait_for(True)
00275 
00276     def ensure_collapsed(self):
00277         """Collapse the filter bar, if it's not already."""
00278         if self.expanded:
00279             searchbar = self._get_searchbar()
00280             tx = searchbar.filter_label_x + (searchbar.filter_label_width / 2)
00281             ty = searchbar.filter_label_y + (searchbar.filter_label_height / 2)
00282             m = Mouse()
00283             m.move(tx, ty)
00284             m.click()
00285             self.expanded.wait_for(False)
00286 
00287     def _get_searchbar(self):
00288         """Get the searchbar.
00289 
00290         This hack exists because there's now more than one SearchBar in Unity,
00291         and for some reason the FilterBar stuff is bundled in the SearchBar.
00292 
00293         """
00294         searchbar_state = self.get_state_by_path("//DashView/SearchBar")
00295         assert(len(searchbar_state) == 1)
00296         return make_introspection_object(searchbar_state[0])
00297 
00298 
00299 class FilterExpanderLabel(UnityIntrospectionObject):
00300     """A label that expands into a filter within a filter bar."""