#####################################################################
# #
# settings.py #
# #
# Copyright 2013, Monash University #
# #
# This file is part of the labscript suite (see #
# http://labscriptsuite.org) and is licensed under the Simplified #
# BSD License. See the license.txt file in the root of the project #
# for the full license. #
# #
#####################################################################
from qtutils.qt.QtCore import *
from qtutils.qt.QtGui import *
from qtutils.qt.QtWidgets import *
import labscript_utils.h5_lock, h5py
from labscript_utils.qtwidgets.fingertab import FingerTabWidget
# Create a generic interface for displaying pages of settings
[docs]class Settings(object):
[docs] def __init__(self,storage='hdf5',file=None,parent = None,page_classes = []):
self.pages = {}
self.instantiated_pages = {}
self.dialog_open = False
self.parent = parent
self.storage = storage
self.file = file
self.callback_list = []
if not self.file:
raise Exception('You must specify a file to load/save preferences from')
for c in page_classes:
self.add_settings_interface(c)
# This function can be called to add a interface
# Each one of these will display as a seperate page in the settings window
# You can not add a class more than once!
# Classes must have unique Class.name attributes! (This might change later...)
[docs] def add_settings_interface(self,setting_class):
if setting_class.name in self.pages:
return False
self.pages[setting_class.name] = setting_class(self.load(setting_class.name))
return True
[docs] def load(self,name):
if self.storage == 'hdf5':
with h5py.File(self.file,'r+') as h5file:
# does the settings group exist?
if 'preferences' not in h5file:
h5file['/'].create_group('preferences')
# is there an entry for this preference type?
group = h5file['/preferences']
if name not in group.attrs:
group.attrs[name] = repr({})
try:
data = eval(group.attrs[name])
except Exception:
# TODO: log this properly
print('Could not load settings data for %s. It may contain data that could not be evaluated. All settings have now been lost'%name)
data = {}
return data
else:
raise Exception("the Settings module cannot handle the storage type: %s"%str(self.storage))
# A simple interface for accessing values in the settings interface
[docs] def get_value(self,settings_class,value_name):
return self.pages[settings_class.name].get_value(value_name)
# goto_page should be the CLASS which you wish to go to!
[docs] def create_dialog(self,goto_page=None):
if not self.dialog_open:
self.instantiated_pages = {}
# Create the dialog
self.dialog = QDialog(self.parent)
self.dialog.setModal(True)
self.dialog.accepted.connect(self.on_save)
self.dialog.rejected.connect(self.on_cancel)
self.dialog.setMinimumSize(800,600)
self.dialog.setWindowTitle("Preferences")
# Remove the help flag next to the [X] close button
self.dialog.setWindowFlags(self.dialog.windowFlags() & ~Qt.WindowContextHelpButtonHint)
# Create the layout
layout = QVBoxLayout(self.dialog)
#Create the Notebook
self.notebook = FingerTabWidget(self.dialog)
self.notebook.setTabPosition(QTabWidget.West)
self.notebook.show()
layout.addWidget(self.notebook)
# Create the button box
widget = QWidget()
hlayout = QHBoxLayout(widget)
button_box = QDialogButtonBox()
button_box.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
button_box.accepted.connect(self.dialog.accept)
button_box.rejected.connect(self.dialog.reject)
hlayout.addItem(QSpacerItem(0,0,QSizePolicy.MinimumExpanding,QSizePolicy.Minimum))
hlayout.addWidget(button_box)
layout.addWidget(widget)
#sorted(a.items(),key=lambda x: x[1])
set_page = None
#self.temp_pages = []
for name, c in sorted(self.pages.items()):
page,icon = c.create_dialog(self.notebook)
# save page
self.instantiated_pages[c.__class__] = page
# Create label
#if isinstance(icon,gtk.Image):
# use their icon
# pass
#else:
# use default icon
# pass
self.notebook.addTab(page,c.name)
if goto_page and isinstance(c,goto_page):
# this is the page we want to go to!
set_page = page
# We do this here in case one of the settings pages specifically inserts itself in an out of order place (eg first)
# We hope that everything will be in alphabetical order, but maybe not!
if set_page:
self.notebook.tabBar().setCurrentIndex(self.notebook.indexOf(set_page))
pass
self.dialog.show()
self.dialog_open = True
else:
if goto_page and goto_page in self.instantiated_pages:
self.notebook.tabBar().setCurrentIndex(self.notebook.indexOf(self.instantiated_pages[goto_page]))
[docs] def register_callback(self,callback):
self.callback_list.append(callback)
[docs] def remove_callback(self,callback):
self.callback_list.remove(callback)
[docs] def on_save(self,*args,**kwargs):
# Save the settings
if self.storage == 'hdf5':
with h5py.File(self.file,'r+') as h5file:
group = h5file['/preferences']
for page in self.pages.values():
group.attrs[page.__class__.name] = repr(page.save())
else:
# this should never happen as the exception will have been raised on load!
pass
# run callback functions!
# Notifies other areas of the program that settings have changed
for callback in self.callback_list:
callback()
self.close()
[docs] def on_cancel(self,*args,**kwargs):
self.close()
[docs] def close(self,*args,**kwargs):
if self.dialog_open:
# Close the setting classes
for page in self.pages.values():
page.close()
self.dialog_open = False
self.dialog.deleteLater()
self.dialog = None