OpenShot Video Editor  2.0.0
ui_util.py
Go to the documentation of this file.
1 ##
2 #
3 # @file
4 # @brief This file contains PyQt help functions, to translate the interface, load icons, and connect signals
5 # @author Noah Figg <eggmunkee@hotmail.com>
6 # @author Jonathan Thomas <jonathan@openshot.org>
7 # @author Olivier Girard <eolinwen@gmail.com>
8 #
9 # @section LICENSE
10 #
11 # Copyright (c) 2008-2016 OpenShot Studios, LLC
12 # (http://www.openshotstudios.com). This file is part of
13 # OpenShot Video Editor (http://www.openshot.org), an open-source project
14 # dedicated to delivering high quality video editing and animation solutions
15 # to the world.
16 #
17 # OpenShot Video Editor is free software: you can redistribute it and/or modify
18 # it under the terms of the GNU General Public License as published by
19 # the Free Software Foundation, either version 3 of the License, or
20 # (at your option) any later version.
21 #
22 # OpenShot Video Editor is distributed in the hope that it will be useful,
23 # but WITHOUT ANY WARRANTY; without even the implied warranty of
24 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 # GNU General Public License for more details.
26 #
27 # You should have received a copy of the GNU General Public License
28 # along with OpenShot Library. If not, see <http://www.gnu.org/licenses/>.
29 #
30 
31 import os
32 import xml.etree.ElementTree
33 
34 from PyQt5.QtCore import QDir, QLocale
35 from PyQt5.QtGui import QIcon
36 from PyQt5.QtWidgets import *
37 from PyQt5 import uic
38 
39 from classes.logger import log
40 from classes import settings
41 
42 DEFAULT_THEME_NAME = "Humanity"
43 
44 
45 ##
46 # Load the current OS theme, or fallback to a default one
47 def load_theme():
48 
50 
51  # If theme not reported by OS
52  if QIcon.themeName() == '' and not s.get("theme") == "No Theme":
53 
54  # Address known Ubuntu bug of not reporting configured theme name, use default ubuntu theme
55  if os.getenv('DESKTOP_SESSION') == 'ubuntu':
56  QIcon.setThemeName('unity-icon-theme')
57 
58  # Windows/Mac use packaged theme
59  else:
60  QIcon.setThemeName(DEFAULT_THEME_NAME)
61 
62 
63 ##
64 # Load a Qt *.ui file, and also load an XML parsed version
65 def load_ui(window, path):
66 
67  # Load ui from configured path
68  uic.loadUi(path, window)
69 
70  # Save xml tree for ui
71  window.uiTree = xml.etree.ElementTree.parse(path)
72 
73 
74 ##
75 # Get a QIcon, and fallback to default theme if OS does not support themes.
76 def get_default_icon(theme_name):
77 
78  # Default path to backup icons
79  start_path = ":/icons/" + DEFAULT_THEME_NAME + "/"
80  icon_path = search_dir(start_path, theme_name)
81  return QIcon(icon_path), icon_path
82 
83 
84 ##
85 # Search for theme name
86 def search_dir(base_path, theme_name):
87 
88  # Search each entry in this directory
89  base_dir = QDir(base_path)
90  for e in base_dir.entryList():
91  # Path to current item
92  path = base_dir.path() + "/" + e
93  base_filename = e.split('.')[0]
94 
95  # If file matches theme name, return
96  if base_filename == theme_name:
97  return path
98 
99  # If this is a directory, search within it
100  dir = QDir(path)
101  if dir.exists():
102  # If found below, return it
103  res = search_dir(path, theme_name)
104  if res:
105  return res
106 
107  # If no match found in dir, return None
108  return None
109 
110 
111 ##
112 # Get either the current theme icon or fallback to default theme (for custom icons). Returns None if none
113 # found or empty name.
114 def get_icon(theme_name):
115 
116  if theme_name:
117  has_icon = QIcon.hasThemeIcon(theme_name)
118  if not has_icon:
119  log.warn('Icon theme {} not found. Will use backup icon.'.format(theme_name))
120  fallback_icon, fallback_path = get_default_icon(theme_name)
121  # log.info('Fallback icon path for {} is {}'.format(theme_name, fallback_path))
122  if has_icon or fallback_icon:
123  return QIcon.fromTheme(theme_name, fallback_icon)
124  return None
125 
126 
127 ##
128 # Using the window xml, set the icon on the given element, or if theme_name passed load that icon.
129 def setup_icon(window, elem, name, theme_name=None):
130 
131  type_filter = 'action'
132  if isinstance(elem, QWidget): # Search for widget with name instead
133  type_filter = 'widget'
134  # Find iconset in tree (if any)
135  iconset = window.uiTree.find('.//' + type_filter + '[@name="' + name + '"]/property[@name="icon"]/iconset')
136  if iconset != None or theme_name: # For some reason "if iconset:" doesn't work the same as "!= None"
137  if not theme_name:
138  theme_name = iconset.get('theme', '')
139  # Get Icon (either current theme or fallback)
140  icon = get_icon(theme_name)
141  if icon:
142  elem.setIcon(icon)
143 
144 
145 ##
146 # Initialize language and icons of the given element
147 def init_element(window, elem):
148 
149  _translate = QApplication.instance().translate
150 
151  name = ''
152  if hasattr(elem, 'objectName'):
153  name = elem.objectName()
154  connect_auto_events(window, elem, name)
155 
156  # Handle generic translatable properties
157  if hasattr(elem, 'setText') and hasattr(elem, 'text') and elem.text() != "":
158  elem.setText(_translate("", elem.text()))
159  if hasattr(elem, 'setToolTip') and hasattr(elem, 'toolTip') and elem.toolTip() != "":
160  elem.setToolTip(_translate("", elem.toolTip()))
161  if hasattr(elem, 'setWindowTitle') and hasattr(elem, 'windowTitle') and elem.windowTitle() != "":
162  elem.setWindowTitle(_translate("", elem.windowTitle()))
163  if hasattr(elem, 'setTitle') and hasattr(elem, 'title') and elem.title() != "":
164  elem.setTitle(_translate("", elem.title()))
165  if hasattr(elem, 'setPlaceholderText') and hasattr(elem, 'placeholderText') and elem.placeholderText() != "":
166  elem.setPlaceholderText(_translate("", elem.placeholderText()))
167  if hasattr(elem, 'setLocale'):
168  elem.setLocale(QLocale().system())
169  # Handle tabs differently
170  if isinstance(elem, QTabWidget):
171  for i in range(elem.count()):
172  elem.setTabText(i, _translate("", elem.tabText(i)))
173  elem.setTabToolTip(i, _translate("", elem.tabToolTip(i)))
174  # Set icon if possible
175  if hasattr(elem, 'setIcon') and name != '': # Has ability to set its icon
176  setup_icon(window, elem, name)
177 
178 
179 ##
180 # Connect any events in a *.ui file with matching Python method names
181 def connect_auto_events(window, elem, name):
182 
183  # If trigger slot available check it
184  if hasattr(elem, 'trigger'):
185  func_name = name + "_trigger"
186  if hasattr(window, func_name) and callable(getattr(window, func_name)):
187  func = getattr(window, func_name)
188  log.info("Binding event {}:{}".format(window.objectName(), func_name))
189  elem.triggered.connect(getattr(window, func_name))
190  if hasattr(elem, 'click'):
191  func_name = name + "_click"
192  if hasattr(window, func_name) and callable(getattr(window, func_name)):
193  func = getattr(window, func_name)
194  log.info("Binding event {}:{}".format(window.objectName(), func_name))
195  elem.clicked.connect(getattr(window, func_name))
196 
197 
198 ##
199 # Initialize all child widgets and action of a window or dialog
200 def init_ui(window):
201  log.info('Initializing UI for {}'.format(window.objectName()))
202 
203  try:
204  # Set locale & window title on the window object
205  if hasattr(window, 'setWindowTitle') and window.windowTitle() != "":
206  _translate = QApplication.instance().translate
207  window.setWindowTitle(_translate("", window.windowTitle()))
208 
209  # Loop through all widgets
210  for widget in window.findChildren(QWidget):
211  init_element(window, widget)
212 
213  # Loop through all actions
214  for action in window.findChildren(QAction):
215  # log.info('Initializing element: {}'.format(action))
216  init_element(window, action)
217  except:
218  log.info('Failed to initialize an element on {}'.format(window.objectName()))
219 
220 
221 def transfer_children(from_widget, to_widget):
222  log.info("Transferring children from '{}' to '{}'".format(from_widget.objectName(), to_widget.objectName()))
def setup_icon(window, elem, name, theme_name=None)
Using the window xml, set the icon on the given element, or if theme_name passed load that icon...
Definition: ui_util.py:129
def get_icon(theme_name)
Get either the current theme icon or fallback to default theme (for custom icons).
Definition: ui_util.py:114
def get_default_icon(theme_name)
Get a QIcon, and fallback to default theme if OS does not support themes.
Definition: ui_util.py:76
def transfer_children(from_widget, to_widget)
Definition: ui_util.py:221
def get_settings()
Get the current QApplication&#39;s settings instance.
Definition: settings.py:43
def connect_auto_events(window, elem, name)
Connect any events in a *.ui file with matching Python method names.
Definition: ui_util.py:181
def load_theme()
Load the current OS theme, or fallback to a default one.
Definition: ui_util.py:47
def search_dir(base_path, theme_name)
Search for theme name.
Definition: ui_util.py:86
def init_ui(window)
Initialize all child widgets and action of a window or dialog.
Definition: ui_util.py:200
def init_element(window, elem)
Initialize language and icons of the given element.
Definition: ui_util.py:147
def load_ui(window, path)
Load a Qt *.ui file, and also load an XML parsed version.
Definition: ui_util.py:65