34 from python_qt_binding
import loadUi
35 from python_qt_binding.QtCore
import QByteArray, qDebug, QObject, QSignalMapper, Signal, Slot
36 from python_qt_binding.QtGui
import QIcon, QValidator
37 from python_qt_binding.QtWidgets
import QAction, QFileDialog, QInputDialog, QMessageBox
45 """Check if the argument is a string which works for both Python 2 and 3.""" 47 return isinstance(s, basestring)
49 return isinstance(s, str)
53 """Manager for perspectives associated with specific sets of `Settings`.""" 55 perspective_changed_signal = Signal(str)
56 save_settings_signal = Signal(Settings, Settings)
57 restore_settings_signal = Signal(Settings, Settings)
58 restore_settings_without_plugin_changes_signal = Signal(Settings, Settings)
62 def __init__(self, settings, application_context):
63 super(PerspectiveManager, self).
__init__()
64 self.setObjectName(
'PerspectiveManager')
77 self.
perspectives = self._settings_proxy.value(
'',
'perspectives', [])
89 if application_context.provide_app_dbus_interfaces:
91 self.
_dbus_server = PerspectiveManagerDBusInterface(self, application_context)
99 create_action = QAction(
'&Create perspective...', self._menu_manager.menu)
100 create_action.setIcon(QIcon.fromTheme(
'list-add'))
102 self._menu_manager.add_suffix(create_action)
104 self.
_remove_action = QAction(
'&Remove perspective...', self._menu_manager.menu)
105 self._remove_action.setEnabled(
False)
106 self._remove_action.setIcon(QIcon.fromTheme(
'list-remove'))
110 self._menu_manager.add_suffix(
None)
112 import_action = QAction(
'&Import...', self._menu_manager.menu)
113 import_action.setIcon(QIcon.fromTheme(
'document-open'))
115 self._menu_manager.add_suffix(import_action)
117 export_action = QAction(
'&Export...', self._menu_manager.menu)
118 export_action.setIcon(QIcon.fromTheme(
'document-save-as'))
120 self._menu_manager.add_suffix(export_action)
129 name = self._settings_proxy.value(
'',
'current-perspective',
'Default')
130 elif hide_and_without_plugin_changes:
133 without_plugin_changes=hide_and_without_plugin_changes)
137 @Slot(str, bool, bool)
139 self, name, settings_changed=
True, save_before=
True, without_plugin_changes=
False):
150 self, name, settings_changed, save_before, without_plugin_changes=
False):
152 name = str(name.replace(
'/',
'__'))
154 qDebug(
'PerspectiveManager.switch_perspective() switching to perspective "%s"' % name)
168 if not self._current_perspective.startswith(self.
HIDDEN_PREFIX):
173 self.perspective_changed_signal.emit(self._current_perspective.lstrip(self.
HIDDEN_PREFIX))
175 if not without_plugin_changes:
176 self.restore_settings_signal.emit(
179 self.restore_settings_without_plugin_changes_signal.emit(
188 callback(*callback_args)
196 clone_perspective = self._create_perspective_dialog.clone_checkbox.isChecked()
199 name, settings_changed=
not clone_perspective, save_before=
False)
204 ui_file = os.path.join(self.
_qtgui_path,
'resource',
'perspective_create.ui')
208 class CustomValidator(QValidator):
211 super(CustomValidator, self).
__init__(parent)
213 def fixup(self, value):
214 value = value.replace(
'/',
'')
216 def validate(self, value, pos):
217 if value.find(
'/') != -1:
218 pos = value.find(
'/')
219 return (QValidator.Invalid, value, pos)
221 return (QValidator.Intermediate, value, pos)
222 return (QValidator.Acceptable, value, pos)
223 self._create_perspective_dialog.perspective_name_edit.setValidator(CustomValidator())
226 self._create_perspective_dialog.perspective_name_edit.setText(
'')
227 self._create_perspective_dialog.clone_checkbox.setChecked(
True)
228 self._create_perspective_dialog.clone_checkbox.setVisible(show_cloning)
231 return_value = self._create_perspective_dialog.exec_()
232 if return_value == self._create_perspective_dialog.Rejected:
235 name = str(self._create_perspective_dialog.perspective_name_edit.text()).lstrip(
239 self._menu_manager.menu,
240 self.tr(
'Empty perspective name'),
241 self.tr(
'The name of the perspective must be non-empty.'))
245 self._menu_manager.menu,
246 self.tr(
'Duplicate perspective name'),
247 self.tr(
'A perspective with the same name already exists.'))
254 if name.find(
'/') != -1:
256 'PerspectiveManager._create_perspective() name cannot contain forward slashes (/)')
258 qDebug(
'PerspectiveManager._create_perspective(%s, %s)' % (name, clone_perspective))
260 self.perspectives.append(name)
261 self._settings_proxy.set_value(
'',
'perspectives', self.
perspectives)
273 if clone_perspective:
275 keys = self._perspective_settings.all_keys()
277 value = self._perspective_settings.value(key)
278 new_settings.set_value(key, value)
287 action = QAction(name, self._menu_manager.menu)
288 action.setCheckable(
True)
289 self._perspective_mapper.setMapping(action, name)
290 action.triggered.connect(self._perspective_mapper.map)
293 self._menu_manager.add_item(action)
295 if self._menu_manager.count_items() > 1:
296 self._remove_action.setEnabled(
True)
302 name, return_value = QInputDialog.getItem(
303 self._menu_manager.menu, self._menu_manager.tr(
'Remove perspective'),
304 self._menu_manager.tr(
'Select the perspective'), names, 0,
False)
307 if return_value == QInputDialog.Rejected:
313 raise UserWarning(
'unknown perspective: %s' % name)
314 qDebug(
'PerspectiveManager._remove_perspective(%s)' % str(name))
317 self.perspectives.remove(name)
318 self._settings_proxy.set_value(
'',
'perspectives', self.
perspectives)
325 self._menu_manager.remove_item(name)
328 if self._menu_manager.count_items() < 2:
329 self._remove_action.setEnabled(
False)
332 file_name, _ = QFileDialog.getOpenFileName(
333 self._menu_manager.menu, self.tr(
'Import perspective from file'),
334 self.
_file_path, self.tr(
'Perspectives (*.perspective)'))
335 if file_name
is None or file_name ==
'':
338 perspective_name = os.path.basename(file_name)
339 suffix =
'.perspective' 340 if perspective_name.endswith(suffix):
341 perspective_name = perspective_name[:-len(suffix)]
344 if perspective_name
is None:
357 file_handle = open(path,
'r') 359 data = json.loads(file_handle.read())
368 """Set dictionary key-value pairs on Settings instance.""" 369 keys = data.get(
'keys', {})
371 settings.set_value(key, keys[key])
372 groups = data.get(
'groups', {})
374 sub = settings.get_settings(group)
378 save_file_name = os.path.join(
380 suffix =
'.perspective' 381 if not save_file_name.endswith(suffix):
382 save_file_name += suffix
383 file_name, _ = QFileDialog.getSaveFileName(
384 self._menu_manager.menu, self.tr(
'Export perspective to file'),
385 save_file_name, self.tr(
'Perspectives (*.perspective)'))
386 if file_name
is None or file_name ==
'':
401 file_handle = open(file_name,
'w')
402 file_handle.write(json.dumps(data, indent=2, separators=(
',',
': ')))
406 """Convert data of Settings instance to dictionary.""" 408 for key
in settings.child_keys():
409 keys[str(key)] = settings.value(key)
411 for group
in settings.child_groups():
412 sub = settings.get_settings(group)
414 return {
'keys': keys,
'groups': groups}
417 keys = data.get(
'keys', {})
419 keys[key] = convert_function(keys[key])
420 groups = data.get(
'groups', {})
426 if value[
'type'] ==
'repr':
427 return eval(value[
'repr'])
428 elif value[
'type'] ==
'repr(QByteArray.hex)':
429 return QByteArray.fromHex(eval(value[
'repr(QByteArray.hex)']))
431 'PerspectiveManager._import_value() unknown serialization type (%s)' % value[
'type'])
435 if value.__class__.__name__ ==
'QByteArray':
436 hex_value = value.toHex()
437 data[
'repr(QByteArray.hex)'] = \
439 data[
'type'] =
'repr(QByteArray.hex)' 443 for i
in range(1, value.size(), 2):
445 character = value.at(i)
447 if character >=
' ' and character <=
'~':
448 characters += character
451 except UnicodeDecodeError:
453 data[
'pretty-print'] = characters
457 data[
'type'] =
'repr' 461 if reimported != value:
463 'PerspectiveManager._export_value() stored value can not be restored (%s)' %
469 """Strip binding specific prefix from type string.""" 470 parts = obj.__class__.__module__.split(
'.')
471 if len(parts) > 1
and parts[1] ==
'QtCore':
472 prefix =
'.'.join(parts[:2])
473 data = data.replace(prefix,
'QtCore', 1)
_create_perspective_dialog
def _get_dict_from_settings(self, settings)
def _on_remove_perspective(self)
def __init__(self, settings, application_context)
def _create_perspective(self, name, clone_perspective=True)
def _switch_perspective(self, name, settings_changed, save_before, without_plugin_changes=False)
def _on_create_perspective(self)
def _add_perspective_action(self, name)
def _remove_perspective(self, name)
def _set_dict_on_settings(self, data, settings)
def _create_perspective_continued(self, name, clone_perspective)
def _choose_new_perspective_name(self, show_cloning=True)
def switch_perspective(self, name, settings_changed=True, save_before=True, without_plugin_changes=False)
def set_perspective(self, name, hide_and_without_plugin_changes=False)
def _on_import_perspective(self)
def _strip_qt_binding_prefix(self, obj, data)
def _import_value(self, value)
def _on_export_perspective_continued(self, file_name)
def _get_perspective_settings(self, perspective_name)
def save_settings_completed(self)
def _on_export_perspective(self)
def import_perspective_from_file(self, path, perspective_name)
def _convert_values(self, data, convert_function)
def _export_value(self, value)