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')
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'))
112 import_action = QAction(
'&Import...', self.
_menu_manager.menu)
113 import_action.setIcon(QIcon.fromTheme(
'document-open'))
117 export_action = QAction(
'&Export...', self.
_menu_manager.menu)
118 export_action.setIcon(QIcon.fromTheme(
'document-save-as'))
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)
175 if not without_plugin_changes:
188 callback(*callback_args)
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)
240 self.tr(
'Empty perspective name'),
241 self.tr(
'The name of the perspective must be non-empty.'))
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))
273 if clone_perspective:
278 new_settings.set_value(key, value)
288 action.setCheckable(
True)
302 name, return_value = QInputDialog.getItem(
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))
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)
446 if isinstance(character, bytes):
447 character = character.decode(
'utf-8')
449 if character >=
' ' and character <=
'~':
450 characters += character
453 except UnicodeDecodeError:
455 data[
'pretty-print'] = characters
459 data[
'type'] =
'repr'
463 if reimported != value:
465 'PerspectiveManager._export_value() stored value can not be restored (%s)' %
471 """Strip binding specific prefix from type string."""
472 parts = obj.__class__.__module__.split(
'.')
473 if len(parts) > 1
and parts[1] ==
'QtCore':
474 prefix =
'.'.join(parts[:2])
475 data = data.replace(prefix,
'QtCore', 1)