vdat.gui.treeview_model – A Custom Model for the Treeview Widget

Model and Tree view implementations to show and navigate the directory tree used by VDAT. The code has being written following this tutorial.

To represent the following structure

+- 20150622
    +-- cal
        +-- time_stamp_1
        +-- time_stamp_2
    +-- sci
        +-- object_1
        +-- object_2
    +-- zro
        +-- time_stamp_3
        +-- time_stamp_4

we first create a ReductionTreeviewModel instance and create a root node as a ReductionNode:

>>>  model = ReductionTreeviewModel()
>>>  nights = ReductionNode("Nights", '/path/to/redux', model)
>>>  model.rootnode = nights

Then we need to create the node for the night:

>>>  night1 = ReductionNode("20150622", '/path/to/redux/20150622',
...                         model, parent=nights)
>>>  nights.add_subnode(night1)

and below it the nodes for the types. E.g. the calibration node would be:

>>>  cal = ReductionNode("cal", '/path/to/redux/20150622/cal',
...                      model, parent=night1)
>>>  night1.add_subnode(cal)

Finally we can add the final directories with, e.g.:

>>>  cal_1 = ReductionNode('time_stamp_1',  '/path/to/redux/20150622/cal',
...                        model, parent=cal, selectable=True, checkable=True,
...                        tooltip='all relevant info go here')
>>>  cal.add_subnode(cal_1)

The model must then been added to the ReductionQTreeView using the ReductionQTreeView.setModel() method as done in ReductionQTreeView.set_model()

class vdat.gui.treeview_model.ReductionNode(name, path, model, type_='', selectable=False, checkable=False, parent=None, tooltip=None)[source]

Bases: object

A class to store nodes in the custom treeview model.

Parameters:
name : String

a label for the node to appear in the treeview

path : string

path associated with the name

model : ReductionTreeviewModel instance

the model to attach the node to

type_ : string

type of the shot in the node

selectable : bool, optional

where the current node is selectable or not

checkable : bool, optional

where the current node can have a check box associated

parent : ReductionNode instance, optional

parent of the current node

tooltip :

if not None converted to a string with pprint.pformat()

Attributes:
name, model, parent : as in the parameters
column : int

column index

subnodes : list

sub-nodes of the current node

_stringify(value)[source]

Unless None or a string, convert value to a string using pprint.

Parameters:
value :

value to stringify

Returns:
string or None

None if value == None, string otherwise

index()[source]

Return the index of the node

Returns:
index : PyQt5.QtCore.QModelIndex instance

the index to this node

add_subnode(node)[source]

Add a subnode to the current node

Parameters:
node : ReductionNode instance

the subnode to add

subnode(row)[source]

Get the child at row

Parameters:
row : int

index of the child

Returns:
:class:`ReductionNode` instance

required child

class vdat.gui.treeview_model.ReductionTreeviewModel(parent=None, column_title='Reduction Browser')[source]

Bases: PyQt5.QtCore.QAbstractItemModel

A model that stores the tree structure for the treeview widget

Parameters:
parent : PyQt5.QtWidgets.QWidget or derivate

parent object of the tree view model

column_title : string, optional

title of the column

rootnode

Get the rootnode of this tree

Returns:
node : ReductionNode instance

the index of the node you want to be root node

checked_nodes

Return the checked nodes.

setData() makes sure that at most one node per type is selected

Returns:
dictionary

key: type (str) of the node (‘sci’, ‘cal’) value: corresponding node instance

columnCount(parentIndex)[source]

Return number of columns, for us this is always 1

Parameters:
parentIndex : PyQt5.QtCore.QModelIndex

index to the parent node

Returns:
int

the number of columns under parent: always 1

rowCount(parentIndex)[source]

Return the number of subnodes under a parent node

Parameters:
parentIndex : PyQt5.QtCore.QModelIndex

index to the parent node

Returns:
nrows : int

the number of rows under parent

headerData(section, orientation, role)[source]

Return information about the header items

Parameters:
section : int

the section for which this is the header

orientation : int

flag indicating whether the header is horizontal or vertical

role : int

flag specifying the type of info requested (i.e. a title for the header, or an icon etc.)

Returns:
string
data(index, role)[source]

Return information about the specified node.

Parameters:
index : PyQt5.QtCore.QModelIndex instance

the index of the node you want data for

role : int

flag specifying the type of info requested (i.e. a title or an icon etc.)

Returns:
string or int

depending of the input role:

  • PyQt5.QtCore.Qt.DisplayRole: return the name of the node associated with the index
  • PyQt5.QtCore.Qt.CheckStateRole: returns PyQt5.QtCore.Qt.Checked: PyQt5.QtCore.Qt.Unchecked whether the check-box is checked or not
  • PyQt5.QtCore.Qt.ToolTipRole: if available, returns the string to put in the tooltip
setData(index, value, role)[source]

If the role is PyQt5.QtCore.Qt.CheckStateRole, change the check status of the index, making sure that at most one element per checkable node type is selected.

Parameters:
index : QModelIndex instance

the index of the node you want data for

value :

value to set (ignored)

role : int

flag specifying the type of info requested (i.e. a title or an icon etc.)

Returns:
success : Bool

True if the operation worked

flags(index)[source]

Set the flag for every index according to the selectable/checkable status of the corresponding node

Parameters:
index : QModelIndex instance

the index of the node you want data for

Returns:
int

flags for the index as defined here

index(row, column, parentIndex)[source]

Return the index of the node with row, column and parent

Implementation from https://www.mail-archive.com/pyqt@riverbankcomputing.com/msg19414.html

Parameters:
row, column : int

index of the row and the column

parentIndex : PyQt5.QtCore.QModelIndex

index to the parent node

Returns:
:class:`PyQt5.QtCore.QModelIndex`

index of the node

parent(index)[source]

Return the index of the parent of the input

Parameters:
index : PyQt5.QtCore.QModelIndex instance

the index you want the parent of

Returns:
:class:`PyQt5.QtCore.QModelIndex` instance

the index of the parent (if the node has a parent)

insertRow(node, row, parent=<PyQt5.QtCore.QModelIndex object>)[source]

Insert node in a new row after the given row.

Parameters:
node : class:ReductionNode instance

node to insert

row: int

index of the row after which add the node

index : PyQt5.QtCore.QModelIndex instance

index of the parent

Returns:
bool

True if the insertion succeed, False otherwise, whatever exception is raised is logged to the main logger

removeRows(row, count, parent=<PyQt5.QtCore.QModelIndex object>)[source]

Remove count rows starting at row

Parameters:
row: int

index of the first row to remove

count: int

number of rows to remove

index : PyQt5.QtCore.QModelIndex instance

index of the parent

Returns:
bool

True if the removal succeed, False otherwise, whatever exception is raised is logged to the main logger

class vdat.gui.treeview_model.ReductionQTreeView(parent=None)[source]

Bases: PyQt5.QtWidgets.QTreeView

Custom tree view widget to display the reduction directories

Custom signals
Name Signature Description
sig_selectionChanged str, str emitted when a use select a directory; the parameters are the full path to the directory and its type (e.g. sci, cal, zro)
sig_exposure_removed str emitted when an exposure is removed; the value is the expname from the database
Custom slot
Name Signature Description
set_model()   create a model from the database and set it
on_press() PyQt5.QtCore.QModelIndex put the path of the selected node into the config file and emit sig_selectionChanged
option_menu() PyQt5.QtCore.QPoint create the actions for the right-click menu
clone_slot()   slot that triggers the cloning of the selected directory
remove_slot()   slot that triggers the removal of the selected directory
Connections between custom signals and/or slots
Signal Slot
customContextMenuRequested option_menu()
pressed on_press()
triggered signal of the “Clone” action clone_slot()
triggered signal of the “Remove” action remove_slot()
sig_exposure_removed vdat.gui.RemoveExposuresMenu.sig_exposure_removed
Parameters:
parent : PyQt5.QtWidgets.QWidget or derivate

parent object of the tree view model

sig_selectionChanged
sig_exposure_removed
set_model()[source]

Create the model and set it.

This method is a pyqt slot.

create_model()[source]

Create the redux directory structure using the information stored in the database

Returns:
model : ReductionTreeviewModel instance
keyPressEvent(event)[source]

If enter is pressed, trigger the pressed signal with the currently selected index

Parameters:
event : PyQt5.QtGui.QKeyEvent

event happened

on_press(index)[source]

Add the path of the underlying node and emit the sig_selectionChanged signal

Parameters:
index : PyQt5.QtCore.QModelIndex instance

index of the selected directory

option_menu(position)[source]

Add an action menu to the tree view

Parameters:
position : PyQt5.QtCore.QPoint instance

position of the mouse

Returns:
menu : PyQt5.QtWidgets.QMenu

menu created; mostly for testing purposes

clone_slot()[source]

Slot triggered when the clone action is clicked.

remove_slot()[source]

Slot triggered when the remove action is clicked.

_clone_dir(index, node)[source]

Clone the directory associated to node and add it to the tree view and to the database

Parameters:
index : PyQt5.QtCore.QModelIndex instance

index of the selected node

node : class:ReductionNode instance

selected node

_do_clone_dir(index, node, new_name)[source]
_new_dir_name(original_name, parent_path)[source]

Ask the user for the new directory name.

Parameters:
original_name : string

name of the directory we are about to copy

parent_path : string

path of the parent directory of original_name

Returns:
new_name : string

name of the new directory

_clone_dialog(default_text, label_prefix='')[source]

Create a text dialog with the default text.

Parameters:
default_text : string

text set by default in the dialog

label_prefix : string

if not empty added in the line before the standard label

Returns:
string

text from the dialog

_copy_dir(parent_path, src, dst, db_entry)[source]

Copy the directory src to dst. Both are children of parent_path.

Also set to true the is_clone entry in the shot file

Parameters:
parent_path : string

path where the original and new directories live

src, dst : string

copy src into dst

db_entry : vdat.database.models.VDATDir

database entry for the new directory

_insert_row(index, new_name)[source]

Clone node, update it and insert it

Parameters:
index : PyQt5.QtCore.QModelIndex instance

index of the selected node

new_name : string

name of the new entry

Returns:
bool

whether the insertion is successful or not

_remove_dir(index, node)[source]

Remove the directory associated to node and remove it from the tree view and from the database.

Parameters:
index : PyQt5.QtCore.QModelIndex instance

index of the selected node

node : class:ReductionNode instance

selected node

_confirm_remove_dialog(dir_name)[source]

Create the dialog to ask if you are sure

Parameters:
dir_name : string

name of the directory

Returns:
bool

where the directory can be removed

showEvent(event)[source]

When the ReductionQTreeView becomes visible, this method is triggered by Qt.

Parameters:
event : PyQt5.QtGui.QShowEvent

the tab is show