instrumentserver.gui.base_instrument#
Quick Introduction#
This module contains all the base classes necessaries to display different properties dictionaries of instruments. The goal is to have a base design such that implementing further GUIS is simplified and can be done without repeating much code. To implement your own GUI you just need to inherit any particular part you want to customize.
The assembled widget uses a TreeView to display some attribute of the passed instrument. It will go through the submodules contained in it and display them accordingly.
All the classes here assume that arguments present in them will exist in inherited ones. E.g.: all classes assume that the items used have a property star and trash. If your implementation of ItemBase deletes those properties unexpected things might break.
You should be careful when using Signals: I tried keeping signals and direct interaction between classes to a minimum, however, there still is a need for inter object signal connection. This is the responsibility of the InstrumentDisplayBase (or whatever your specific widget implementation is). If you are adding more connections that happen between signals it is recommended to overload the connectSignals function, call the super version and add whatever new signals you need. The exception is with the toolbar actions themselves, those are handled by the makeToolBar function.
Full Description#
The following is a more through and linear guide on how to implement your own custom instrument widgets.
The goal of any widget implementation of the following classes is to display some attribute of a Qcodes instrument. Following this design will allow you to display items similarly to how the generic gui for instruments looks like. It is recommended to understand the basic of model/view in Qt to more easily understand this guide, but I would do my best to guide you through.
Classes#
ItemBase#
This is based of the QStandardItem. It does not do much other than hold the individual data of each item. The actual object that you are interested in displaying is stored in the variable element.
InstrumentModelBase#
Based on a QStandardItemModel, it stores all the items in the correct structure. It is in charge of keeping its data up to date (if needed). All the information of the model is contained in the column 0, this includes any hierarchical (items inside of items representing submodules) or any other information that should be shown in other columns. When adding items to the model, use the addItem method, this will take care of hierarchical things for you. don’t use insertItemTo This should just be used to insert the correct number of items to the correct place.
Things to pay attention when implementing your own:
If your model is going to display more than one column (this is usually the case) you need to set the correct number of columns and set the horizontal headers.
Implement the function insertItemTo: This is the only function that actually adds items to the model. When the model contains more than one column this function creates QStandardItems and adds them to the correct columns. don’t forget to emit the newItem signal if you are going to implement a view that utilizes delegates.
InstrumentSortFilterProxyModel#
This class is in charge of filtering and sorting of the model. For most things, you should not have to care about this class.
It might be helpful to know, before a new filtering happens, the proxy model emits the signal filterIncoming, when the filtering is done it will emit the signal filterFinished. These signals are used to set delegates and collapsed states in the view.
InstrumentTreeViewBase#
The view is in charge of displaying the model data. It uses the ProxyModel to filter and sort the items for it. The main thing you need to implement for this class is its delegate. Delegates are classes in charge of creating the widgets that are shown for each row of the view. Usually they are the way we represent the information we want to show and allows us to interact with it.
When creating your own delegate, you need to inherit from the class QStyledItemDelegate. Other than the constructor, the only class that your delegate should have implemented is the createEditor class. This class is responsible to return an already created widget for a specific item. If any signal needs to be connected from or to this widget, it should happen in the createEditor function.
- Things to pay attention when implementing the constructor:
You can add any extra action that you want in the context menu here.
- When calling the super, don’t forget to pass the delegateColumns argument to the base model indicating
what columns utilize delegates.
Don’t forget to call the setItemDelegateForColumn for all the columns that utilize delegates.
- Don’t forget to end the constructor by calling the function setAllDelegatesPersistent,
if not, the delegates will not be shown.
InstrumentDisplayBase#
This is the class that brings everything together. It is the widget that should be added to a layout. When calling the constructor, you can pass any of the 4 previous classes to it to utilize your version of it, instead of the base one.
All items connect their own signals with their own slots, but if any class needs to connect to a slot of a different class, that happens in the connectSignal method If you need to implement any of your own signals, override this method and after calling the super version of it, connect your signals.
To add more items to the toolbar for any extra functionality, you can do so by overriding the makeToolbar method.
Classes
The parent of the delegate should be the view. |
|
|
Basic widget. |
|
Base model used to display information of an instrument (like parameters or methods). |
|
|
|
|
|
Base item for instrument models. |
- class instrumentserver.gui.base_instrument.DelegateBase[source]#
Bases:
QStyledItemDelegateThe parent of the delegate should be the view. The signals should go through the view too.
- class instrumentserver.gui.base_instrument.InstrumentDisplayBase(instrument: Any, attr: str, itemType: type = <class 'instrumentserver.gui.base_instrument.ItemBase'>, modelType: type = <class 'instrumentserver.gui.base_instrument.InstrumentModelBase'>, proxyModelType: type = <class 'instrumentserver.gui.base_instrument.InstrumentSortFilterProxyModel'>, viewType: type = <class 'instrumentserver.gui.base_instrument.InstrumentTreeViewBase'>, callSignals: bool = True, shortcutManager: KeyboardShortcutManager | None = None, parent: QWidget | None = None, **modelKwargs: Any)[source]#
Bases:
QWidgetBasic widget. To implement new toolbars overload the makeToolBar function. To connect any extra signals overload the connectSignals function.
All the type variables, require the class type and not an initialized object of the variables.
- Parameters:
instrument – The instrument we want to display the attribute from.
attr – string of the name of the dictionary we want to display, like ‘parameters’ or ‘function’
itemType – The type of item the model should use.
modelType – The type of model that should be used.
proxyModelType – The type of proxy model that should be used.
viewType – The type of view that should be used.
callSignals – If False, the constructor will not call the method connectSignals
shortcutManager – Manager shared across the application so actions can be registered to shortcuts
- class instrumentserver.gui.base_instrument.InstrumentModelBase(instrument: Any, attr: str, itemClass: type[ItemBase] = <class 'instrumentserver.gui.base_instrument.ItemBase'>, itemsStar: List[str] | None = [], itemsTrash: List[str] | None = [], itemsHide: List[str] | None = [], parent: QObject | None = None)[source]#
Bases:
QStandardItemModelBase model used to display information of an instrument (like parameters or methods).
In the constructor of the implemented model, you should specify how many columns it has and set the header labels
If you are implementing the addChildTo function it is very important that you emit the newItem signal in the end. Delegates will not work properly unless you do so. This is because the integrated signal that Qt has, is emitted at the beginning of the insertion process and not in the end, not allowing the delegates to be properly set
The attribute you are trying to display must be a dictionary.
- Parameters:
instrument – The instrument we are trying to show.
attr – The string name of the dictionary of the items we want to show (“parameters”, for example)
itemClass – The item class the model should use.
itemsStar – List of items that will start being starred.
itemsTrash – List of items that will start trashed.
itemsHide – List of items that will not be loaded. If the user adds the same parameters to the model manually, they will be shown.
- addItem(fullName: str, **kwargs: Any) ItemBase[source]#
Adds an item to the model. The
*argsand**kwargsare whatever the specific item needs for a new item.- Parameters:
fullName – The name of the parameter
- insertItemTo(parent: QStandardItem, item: QStandardItem) None[source]#
This is the only function that actually inserts items into the model. Overload for models that utilize more columns. Don’t call directly
If you are using delegates, this function should emit the newItem signal
- loadItems(module: Any = None, prefix: str | None = None) None[source]#
The argument for either submodules or the instrument itself.
- Parameters:
module – A proxy instrument from which we want to add all of its attributes and submodules. If None, self.instrument will be used.
prefix – any submodule name that should be added before the name of a parameter.
- modelRefreshed#
Signal() Emitted when the model refreshes.
- newItem#
Signal(ItemBase) Gets emitted after a new item has been added. The user is in charge of emitting it in their implementation of addChildTo
- class instrumentserver.gui.base_instrument.InstrumentSortFilterProxyModel(sourceModel: InstrumentModelBase, parent: QObject | None = None)[source]#
Bases:
QSortFilterProxyModel- filterAcceptsRow(source_row: int, source_parent: QModelIndex) bool[source]#
Calls for the super() unless trash is active and the item or one of its parent is trash.
- filterFinished#
Signal() Emitted after a filter has occurred.
- filterIncoming#
Signal() Emitted before a filter occurs
- class instrumentserver.gui.base_instrument.InstrumentTreeViewBase(model: QAbstractItemModel, delegateColumns: List[int] | None = None, parent: QWidget | None = None)[source]#
Bases:
QTreeView- fillCollapsedDict(parentItem: ItemBase | None = None) None[source]#
Fills the collapsed state dictionary to be recovered after a filter event occured.
- itemStarToggle#
Signal(ItemBase) emitted when this item got its star action triggered.
- itemTrashToggle#
Signal(ItemBase) emitted when this item got its trashed action triggered.
- onCheckDelegate(item: ItemBase | None) None[source]#
Makes sure that the delegates are shown if needed.
- Parameters:
item – The item whose row the delegates need to be activated
- class instrumentserver.gui.base_instrument.ItemBase(name: str, star: bool = False, trash: bool = False, showDelegate: bool = True, element: Any = None)[source]#
Bases:
QStandardItemBase item for instrument models.
- Parameters:
name – The name. This should include all of the submodules.
star – indicates if the item is starred.
trash – indicates if the item is trashed.
showDelegate – If true, the delegate for that item will be shown.
element – The object we want to store here, this can be a parameter or a method at the moment. If this is None, it means that the item is a submodule and should only be there to store the children.