Unity 8
 All Classes Functions
dash.py
1 # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2 #
3 # Unity Autopilot Test Suite
4 # Copyright (C) 2012, 2013, 2014 Canonical
5 #
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #
19 
20 import logging
21 import ubuntuuitoolkit
22 
23 from unity8.shell import emulators
24 
25 from autopilot import logging as autopilot_logging
26 from autopilot.introspection import dbus
27 from ubuntuuitoolkit import emulators as toolkit_emulators
28 
29 
30 logger = logging.getLogger(__name__)
31 
32 
33 class DashApp(object):
34 
35  """Autopilot helper for the Dash app."""
36 
37  def __init__(self, app_proxy):
38  self.app_proxy = app_proxy
39  self.main_view = self.app_proxy.select_single(
40  toolkit_emulators.MainView)
41  self.dash = self.main_view.select_single(Dash)
42 
43 
45  """An emulator that understands the Dash."""
46 
47  def __init__(self, *args):
48  super(Dash, self).__init__(*args)
49  self.dash_content_list = self.wait_select_single(
50  'QQuickListView', objectName='dashContentList')
51 
52  def get_applications_grid(self):
53  get_grid = self.get_scope('clickscope').wait_select_single(
54  'CardGrid', objectName='local')
55  return get_grid
56 
57  def get_application_icon(self, text):
58  """Returns a 'Tile' icon that has the text 'text' from the application
59  grid.
60 
61  :param text: String containing the text of the icon to search for.
62 
63  """
64  app_grid = self.get_applications_grid()
65  resp_grid = app_grid.wait_select_single('ResponsiveGridView')
66  return resp_grid.select_single('Tile', text=text)
67 
68  def get_scope(self, scope_name='clickscope'):
69  return self.dash_content_list.select_single(
70  'QQuickLoader', scopeId=scope_name)
71 
72  @autopilot_logging.log_action(logger.info)
73  def open_scope(self, scope_id):
74  """Open a dash scope.
75 
76  :parameter scope_id: The id of the scope.
77  :return: The scope.
78 
79  """
80  scope_loader = self._get_scope_loader(scope_id)
81  if scope_loader.isCurrent:
82  logger.info('The scope is already open.')
83  return self._get_scope_from_loader(scope_loader)
84  else:
85  return self._open_scope_scrolling(scope_loader)
86 
87  def _get_scope_loader(self, scope_id):
88  try:
89  return self.dash_content_list.select_single(
90  'QQuickLoader', scopeId=scope_id)
91  except dbus.StateNotFoundError:
93  'No scope found with id {0}'.format(scope_id))
94 
95  def _get_scope_from_loader(self, loader):
96  return loader.get_children()[0]
97 
98  def _open_scope_scrolling(self, scope_loader):
99  scroll = self._get_scroll_direction(scope_loader)
100 
101  while not scope_loader.isCurrent:
102  scroll()
103  self.dash_content_list.moving.wait_for(False)
104 
105  scope = self._get_scope_from_loader(scope_loader)
106  scope.isCurrent.wait_for(True)
107  return scope
108 
109  def _get_scroll_direction(self, scope_loader):
110  current_scope_loader = self.dash_content_list.select_single(
111  'QQuickLoader', isCurrent=True)
112  if scope_loader.globalRect.x < current_scope_loader.globalRect.x:
113  return self._scroll_to_left_scope
114  elif scope_loader.globalRect.x > current_scope_loader.globalRect.x:
115  return self._scroll_to_right_scope
116  else:
117  raise emulators.UnityEmulatorException('The scope is already open')
118 
119  @autopilot_logging.log_action(logger.info)
120  def _scroll_to_left_scope(self):
121  original_index = self.dash_content_list.currentIndex
122  dash_content = self.select_single(objectName="dashContent")
123  x, y, width, height = dash_content.globalRect
124  start_x = x + width / 3
125  stop_x = x + width / 3 * 2
126  start_y = stop_y = y + 1
127  self.pointing_device.drag(start_x, start_y, stop_x, stop_y)
128  self.dash_content_list.currentIndex.wait_for(original_index - 1)
129 
130  @autopilot_logging.log_action(logger.info)
131  def _scroll_to_right_scope(self):
132  original_index = self.dash_content_list.currentIndex
133  dash_content = self.select_single(objectName="dashContent")
134  x, y, width, height = dash_content.globalRect
135  start_x = x + width / 3 * 2
136  stop_x = x + width / 3
137  start_y = stop_y = y + 1
138  self.pointing_device.drag(start_x, start_y, stop_x, stop_y)
139  self.dash_content_list.currentIndex.wait_for(original_index + 1)
140 
141  def enter_search_query(self, query):
142  current_header = self._get_current_page_header()
143  search_button = current_header.select_single(objectName="search_header_button")
144  self.pointing_device.move(search_button.globalRect.x + search_button.width / 2,
145  search_button.globalRect.y + search_button.height / 2)
146  self.pointing_device.click()
147  headerContainer = current_header.select_single(
148  objectName="headerContainer")
149  headerContainer.contentY.wait_for(0)
150  search_text_field = self._get_search_text_field()
151  search_text_field.write(query)
152  self.select_single(objectName="processingIndicator").visible.wait_for(False)
153 
154  def _get_search_text_field(self):
155  page_header = self._get_current_page_header()
156  return page_header.select_single(objectName='searchTextField')
157 
158  def _get_current_page_header(self):
159  dashContentList = self.select_single(objectName="dashContentList")
160  all_headers = dashContentList.select_many("QQuickLoader")
161  for i in all_headers:
162  if i.isCurrent:
163  return i.select_single(objectName="scopePageHeader")
164  return None
165 
166 
167 class ListViewWithPageHeader(ubuntuuitoolkit.QQuickFlickable):
168  pass
169 
170 
171 class GenericScopeView(emulators.UnityEmulatorBase):
172  """Autopilot emulator for generic scopes."""
173 
174  @autopilot_logging.log_action(logger.info)
175  def open_preview(self, category, app_name):
176  """Open the preview of an application.
177 
178  :parameter category: The name of the category where the application is.
179  :parameter app_name: The name of the application.
180  :return: The opened preview.
181 
182  """
183  # FIXME some categories need a long press in order to see the preview.
184  # Some categories do not show previews, like recent apps.
185  # --elopio - 2014-1-14
186  self.click_scope_item(category, app_name)
187  preview_list = self.wait_select_single(
188  'QQuickLoader', objectName='subPageLoader')
189  preview_list.subPageShown.wait_for(True)
190  preview_list.x.wait_for(0)
191  return preview_list.select_single(
192  Preview, objectName='preview{}'.format(preview_list.currentIndex))
193 
194  @autopilot_logging.log_action(logger.debug)
195  def click_scope_item(self, category, title):
196  """Click an item from the scope.
197 
198  :parameter category: The name of the category where the item is.
199  :parameter title: The title of the item.
200 
201  """
202  category_element = self._get_category_element(category)
203  icon = category_element.select_single('AbstractButton', title=title)
204  self.pointing_device.click_object(icon)
205 
206  def _get_category_element(self, category):
207  try:
208  return self.wait_select_single(
209  'Base', objectName='dashCategory{}'.format(category))
210  except dbus.StateNotFoundError:
212  'No category found with name {}'.format(category))
213 
214  def get_applications(self, category):
215  """Return the list of applications on a category.
216 
217  :parameter category: The name of the category.
218 
219  """
220  category_element = self._get_category_element(category)
221  see_all = category_element.select_single(objectName='seeAll')
222  application_cards = category_element.select_many('AbstractButton')
223 
224  application_cards = sorted(
225  (card for card in application_cards
226  if card.globalRect.y < see_all.globalRect.y),
227  key=lambda card: (card.globalRect.y, card.globalRect.x))
228 
229  result = []
230  for card in application_cards:
231  if card.objectName not in ('cardToolCard', 'seeAll'):
232  result.append(card.title)
233  return result
234 
235 
237  """Autopilot custom proxy object for generic previews."""