diff --git a/.buildinfo b/.buildinfo
new file mode 100644
index 0000000..190bd04
--- /dev/null
+++ b/.buildinfo
@@ -0,0 +1,4 @@
+# Sphinx build info version 1
+# This file records the configuration used when building these files. When it is not found, a full rebuild will be done.
+config: 36f547f5292569554477c28b3dfa67d6
+tags: 645f666f9bcd5a90fca523b33c5a78b7
diff --git a/.doctrees/api.doctree b/.doctrees/api.doctree
new file mode 100644
index 0000000..054a954
Binary files /dev/null and b/.doctrees/api.doctree differ
diff --git a/.doctrees/api/iblqt.core.ColoredDataFrameTableModel.doctree b/.doctrees/api/iblqt.core.ColoredDataFrameTableModel.doctree
new file mode 100644
index 0000000..ee3f492
Binary files /dev/null and b/.doctrees/api/iblqt.core.ColoredDataFrameTableModel.doctree differ
diff --git a/.doctrees/api/iblqt.core.DataFrameTableModel.doctree b/.doctrees/api/iblqt.core.DataFrameTableModel.doctree
new file mode 100644
index 0000000..314bda0
Binary files /dev/null and b/.doctrees/api/iblqt.core.DataFrameTableModel.doctree differ
diff --git a/.doctrees/api/iblqt.core.PathWatcher.doctree b/.doctrees/api/iblqt.core.PathWatcher.doctree
new file mode 100644
index 0000000..ef25cc3
Binary files /dev/null and b/.doctrees/api/iblqt.core.PathWatcher.doctree differ
diff --git a/.doctrees/api/iblqt.core.doctree b/.doctrees/api/iblqt.core.doctree
new file mode 100644
index 0000000..4573126
Binary files /dev/null and b/.doctrees/api/iblqt.core.doctree differ
diff --git a/.doctrees/api/iblqt.doctree b/.doctrees/api/iblqt.doctree
new file mode 100644
index 0000000..3ccb377
Binary files /dev/null and b/.doctrees/api/iblqt.doctree differ
diff --git a/.doctrees/api/iblqt.widgets.CheckBoxDelegate.doctree b/.doctrees/api/iblqt.widgets.CheckBoxDelegate.doctree
new file mode 100644
index 0000000..ba2c4a7
Binary files /dev/null and b/.doctrees/api/iblqt.widgets.CheckBoxDelegate.doctree differ
diff --git a/.doctrees/api/iblqt.widgets.StatefulButton.doctree b/.doctrees/api/iblqt.widgets.StatefulButton.doctree
new file mode 100644
index 0000000..f49ef55
Binary files /dev/null and b/.doctrees/api/iblqt.widgets.StatefulButton.doctree differ
diff --git a/.doctrees/api/iblqt.widgets.doctree b/.doctrees/api/iblqt.widgets.doctree
new file mode 100644
index 0000000..a7bda54
Binary files /dev/null and b/.doctrees/api/iblqt.widgets.doctree differ
diff --git a/.doctrees/changelog.doctree b/.doctrees/changelog.doctree
new file mode 100644
index 0000000..d0d0637
Binary files /dev/null and b/.doctrees/changelog.doctree differ
diff --git a/.doctrees/dev_guide.doctree b/.doctrees/dev_guide.doctree
new file mode 100644
index 0000000..e089b90
Binary files /dev/null and b/.doctrees/dev_guide.doctree differ
diff --git a/.doctrees/environment.pickle b/.doctrees/environment.pickle
new file mode 100644
index 0000000..78346dd
Binary files /dev/null and b/.doctrees/environment.pickle differ
diff --git a/.doctrees/index.doctree b/.doctrees/index.doctree
new file mode 100644
index 0000000..ab3a657
Binary files /dev/null and b/.doctrees/index.doctree differ
diff --git a/.nojekyll b/.nojekyll
new file mode 100644
index 0000000..e69de29
diff --git a/_modules/iblqt/core.html b/_modules/iblqt/core.html
new file mode 100644
index 0000000..9cfec55
--- /dev/null
+++ b/_modules/iblqt/core.html
@@ -0,0 +1,800 @@
+
+
+
+
+
+[docs]
+classDataFrameTableModel(QAbstractTableModel):
+"""
+ A Qt TableModel for Pandas DataFrames.
+
+ Attributes
+ ----------
+ dataFrame : Property
+ The DataFrame containing the models data.
+ """
+
+
+[docs]
+ def__init__(
+ self,
+ parent:QObject|None=None,
+ dataFrame:DataFrame|None=None,
+ *args,
+ **kwargs,
+ ):
+"""
+ Initialize the DataFrameTableModel.
+
+ Parameters
+ ----------
+ parent : QObject, optional
+ The parent object.
+ dataFrame : DataFrame, optional
+ The Pandas DataFrame to be represented by the model.
+ *args : tuple
+ Positional arguments passed to the parent class.
+ **kwargs : dict
+ Keyword arguments passed to the parent class.
+ """
+ super().__init__(parent,*args,**kwargs)
+ self._dataFrame=DataFrame()ifdataFrameisNoneelsedataFrame.copy()
+
+
+
+[docs]
+ defgetDataFrame(self)->DataFrame:
+"""
+ Get the underlying DataFrame.
+
+ Returns
+ -------
+ DataFrame
+ The DataFrame represented by the model.
+ """
+ returnself._dataFrame
+
+
+
+[docs]
+ defsetDataFrame(self,dataFrame:DataFrame):
+"""
+ Set a new DataFrame.
+
+ Parameters
+ ----------
+ dataFrame : DataFrame
+ The new DataFrame to be set.
+ """
+ self.beginResetModel()
+ self._dataFrame=dataFrame.copy()
+ self.endResetModel()
+[docs]
+ defheaderData(
+ self,
+ section:int,
+ orientation:Qt.Orientation=Qt.Orientation.Horizontal,
+ role:int=Qt.ItemDataRole.DisplayRole,
+ )->Any|None:
+"""
+ Get the header data for the specified section.
+
+ Parameters
+ ----------
+ section : int
+ The section index.
+ orientation : Qt.Orientation, optional
+ The orientation of the header. Defaults to Horizontal.
+ role : int, optional
+ The role of the header data. Only DisplayRole is supported at this time.
+
+ Returns
+ -------
+ Any or None
+ The header data.
+ """
+ ifrole==Qt.ItemDataRole.DisplayRole:
+ if(
+ orientation==Qt.Orientation.Horizontal
+ and0<=section<self.columnCount()
+ ):
+ returnself._dataFrame.columns[section]
+ elif(
+ orientation==Qt.Orientation.Vertical
+ and0<=section<self.rowCount()
+ ):
+ returnself._dataFrame.index[section]
+ returnNone
+
+
+
+[docs]
+ defrowCount(self,parent:QModelIndex|None=None)->int:
+"""
+ Get the number of rows in the model.
+
+ Parameters
+ ----------
+ parent : QModelIndex, optional
+ The parent index.
+
+ Returns
+ -------
+ int
+ The number of rows.
+ """
+ ifisinstance(parent,QModelIndex)andparent.isValid():
+ return0
+ returnlen(self._dataFrame.index)
+
+
+
+[docs]
+ defcolumnCount(self,parent:QModelIndex|None=None)->int:
+"""
+ Get the number of columns in the model.
+
+ Parameters
+ ----------
+ parent : QModelIndex, optional
+ The parent index.
+
+ Returns
+ -------
+ int
+ The number of columns.
+ """
+ ifisinstance(parent,QModelIndex)andparent.isValid():
+ return0
+ returnself._dataFrame.columns.size
+
+
+
+[docs]
+ defdata(
+ self,index:QModelIndex,role:int=Qt.ItemDataRole.DisplayRole
+ )->Any|None:
+"""
+ Get the data for the specified index.
+
+ Parameters
+ ----------
+ index : QModelIndex
+ The index of the data.
+ role : int, optional
+ The role of the data.
+
+ Returns
+ -------
+ Any or None
+ The data for the specified index.
+ """
+ ifindex.isValid()androle==Qt.ItemDataRole.DisplayRole:
+ data=self._dataFrame.iloc[index.row(),index.column()]
+ ifisinstance(data,np.generic):
+ returndata.item()
+ returndata
+ returnNone
+
+
+
+[docs]
+ defsetData(
+ self,index:QModelIndex,value:Any,role:int=Qt.ItemDataRole.DisplayRole
+ )->bool:
+"""
+ Set data at the specified index with the given value.
+
+ Parameters
+ ----------
+ index : QModelIndex
+ The index where the data will be set.
+ value : Any
+ The new value to be set at the specified index.
+ role : int, optional
+ The role of the data. Only DisplayRole is supported at this time.
+
+ Returns
+ -------
+ bool
+ Returns true if successful; otherwise returns false.
+ """
+ ifindex.isValid()androle==Qt.ItemDataRole.DisplayRole:
+ self._dataFrame.iloc[index.row(),index.column()]=value
+ self.dataChanged.emit(index,index,[role])
+ returnTrue
+ returnFalse
+
+
+
+[docs]
+ defsort(self,column:int,order:Qt.SortOrder=Qt.SortOrder.AscendingOrder):
+"""
+ Sort the data based on the specified column and order.
+
+ Parameters
+ ----------
+ column : int
+ The column index to sort by.
+ order : Qt.SortOrder, optional
+ The sort order. Defaults to Ascending order.
+ """
+ ifself.columnCount()==0:
+ return
+ columnName=self._dataFrame.columns[column]
+ self.layoutAboutToBeChanged.emit()
+ self._dataFrame.sort_values(
+ by=columnName,ascending=order==Qt.SortOrder.AscendingOrder,inplace=True
+ )
+ self.layoutChanged.emit()
+
+
+
+
+
+[docs]
+classColoredDataFrameTableModel(DataFrameTableModel):
+"""Extension of DataFrameTableModel providing color-mapped numerical data."""
+
+ colormapChanged=Signal(str)# type: Signal
+"""Emitted when the colormap has been changed."""
+
+ alphaChanged=Signal(int)# type: Signal
+"""Emitted when the alpha value has been changed."""
+
+ _normData=DataFrame()
+ _background:npt.NDArray[np.int_]
+ _foreground:npt.NDArray[np.int_]
+ _cmap:ColorMap=colormap.get('plasma')
+ _alpha:int
+
+
+[docs]
+ def__init__(
+ self,
+ parent:QObject|None=None,
+ dataFrame:DataFrame|None=None,
+ colormap:str='plasma',
+ alpha:int=255,
+ ):
+"""
+ Initialize the ColoredDataFrameTableModel.
+
+ Parameters
+ ----------
+ parent : QObject, optional
+ The parent object.
+ dataFrame : DataFrame, optional
+ The Pandas DataFrame to be represented by the model.
+ colormap : str
+ The colormap to be used. Can be the name of a valid colormap from matplotlib or colorcet.
+ alpha : int
+ The alpha value of the colormap. Must be between 0 and 255.
+ *args : tuple
+ Positional arguments passed to the parent class.
+ **kwargs : dict
+ Keyword arguments passed to the parent class.
+
+ """
+ super().__init__(parent=parent)
+ self.modelReset.connect(self._normalizeData)
+ self.dataChanged.connect(self._normalizeData)
+ self.colormapChanged.connect(self._defineColors)
+ self.setProperty('colormap',colormap)
+ self.setProperty('alpha',alpha)
+ ifdataFrameisnotNone:
+ self.setDataFrame(dataFrame)
+
+
+
+[docs]
+ defgetColormap(self)->str:
+"""
+ Return the name of the current colormap.
+
+ Returns
+ -------
+ str
+ The name of the current colormap
+ """
+ returnself._cmap.name
+
+
+
+[docs]
+ @Slot(str)
+ defsetColormap(self,name:str):
+"""
+ Set the colormap.
+
+ Parameters
+ ----------
+ name : str
+ Name of the colormap to be used. Can be the name of a valid colormap from matplotlib or colorcet.
+ """
+ forsourcein[None,'matplotlib','colorcet']:
+ ifnameincolormap.listMaps(source):
+ self._cmap=colormap.get(name,source)
+ self.colormapChanged.emit(name)
+ return
+ log.warning(f'No such colormap: "{name}"')
+
+
+ colormap=Property(str,fget=getColormap,fset=setColormap,notify=colormapChanged)# type: Property
+"""The name of the colormap."""
+
+
+[docs]
+ defgetAlpha(self)->int:
+"""
+ Return the alpha value of the colormap.
+
+ Returns
+ -------
+ int
+ The alpha value of the colormap.
+ """
+ returnself._alpha
+
+
+
+[docs]
+ @Slot(int)
+ defsetAlpha(self,alpha:int=255):
+"""
+ Set the alpha value of the colormap.
+
+ Parameters
+ ----------
+ alpha : int
+ The alpha value of the colormap. Must be between 0 and 255.
+ """
+ _,self._alpha,_=sorted([0,alpha,255])
+ self.alphaChanged.emit(self._alpha)
+ self.layoutChanged.emit()
+
+
+ alpha=Property(int,fget=getAlpha,fset=setAlpha,notify=alphaChanged)# type: Property
+"""The alpha value of the colormap."""
+
+ def_normalizeData(self)->None:
+"""Normalize the Data for mapping to a colormap."""
+ df=self._dataFrame.copy()
+
+ # coerce non-bool / non-numeric values to numeric
+ cols=df.select_dtypes(exclude=['bool','number']).columns
+ df[cols]=df[cols].apply(pd.to_numeric,errors='coerce')
+
+ # normalize numeric values, avoiding inf values and division by zero
+ cols=df.select_dtypes(include=['number']).columns
+ df[cols].replace([np.inf,-np.inf],np.nan)
+ m=df[cols].nunique()<=1# boolean mask for columns with only 1 unique value
+ df[cols[m]]=df[cols[m]].where(df[cols[m]].isna(),other=0.0)
+ cols=cols[~m]
+ df[cols]=(df[cols]-df[cols].min())/(df[cols].max()-df[cols].min())
+
+ # convert boolean values
+ cols=df.select_dtypes(include=['bool']).columns
+ df[cols]=df[cols].astype(float)
+
+ # store as property & call _defineColors()
+ self._normData=df
+ self._defineColors()
+
+ def_defineColors(self)->None:
+"""
+ Define the background and foreground colors according to the table's data.
+
+ The background color is set to the colormap-mapped values of the normalized
+ data, and the foreground color is set to the inverse of the background's
+ approximated luminosity.
+
+ The `layoutChanged` signal is emitted after the colors are defined.
+ """
+ ifself._normData.empty:
+ self._background=np.zeros((0,0,3),dtype=int)
+ self._foreground=np.zeros((0,0),dtype=int)
+ else:
+ m=np.isfinite(self._normData)# binary mask for finite values
+ self._background=np.ones((*self._normData.shape,3),dtype=int)*255
+ self._background[m]=self._cmap.mapToByte(self._normData.values[m])[:,:3]
+ self._foreground=255-(
+ self._background*np.array([[[0.21,0.72,0.07]]])
+ ).sum(axis=2).astype(int)
+ self.layoutChanged.emit()
+
+
+[docs]
+ defdata(self,index:QModelIndex,role:int=Qt.ItemDataRole.DisplayRole)->Any:
+"""
+ Get the data for the specified index.
+
+ Parameters
+ ----------
+ index : QModelIndex
+ The index of the data.
+ role : int, optional
+ The role of the data.
+
+ Returns
+ -------
+ Any
+ The data for the specified index.
+ """
+ if(
+ rolein(Qt.ItemDataRole.BackgroundRole,Qt.ItemDataRole.ForegroundRole)
+ andindex.isValid()
+ ):
+ row=self._dataFrame.index[index.row()]
+ col=index.column()
+ ifrole==Qt.ItemDataRole.BackgroundRole:
+ r,g,b=self._background[row][col]
+ returnQColor.fromRgb(r,g,b,self._alpha)
+ ifrole==Qt.ItemDataRole.ForegroundRole:
+ lum=self._foreground[row][col]
+ returnQColor('black'if(lum*self._alpha)<32512else'white')
+ returnsuper().data(index,role)
+
+
+
+
+
+[docs]
+classPathWatcher(QObject):
+"""Watch paths for changes.
+
+ Identical to :class:`~PyQt5.QtCore.QFileSystemWatcher` but using
+ :class:`~pathlib.Path` instead of :class:`str` for arguments and signals.
+
+ Call :meth:`~iblqt.core.PathWatcher.addPath` to watch a particular file or
+ directory. Multiple paths can be added using the
+ :meth:`~iblqt.core.PathWatcher.addPaths` function. Existing paths can be removed by
+ using the :meth:`~iblqt.core.PathWatcher.removePath` and
+ :meth:`~iblqt.core.PathWatcher.removePaths` functions.
+
+ PathWatcher examines each path added to it. Files that have been added to the
+ PathWatcher can be accessed using the :meth:`~iblqt.core.PathWatcher.files`
+ function, and directories using the :meth:`~iblqt.core.PathWatcher.directories`
+ function.
+
+ The :meth:`~iblqt.core.PathWatcher.fileChanged` signal is emitted when a file has
+ been modified, renamed or removed from disk. Similarly, the
+ :meth:`~iblqt.core.PathWatcher.directoryChanged` signal is emitted when a
+ directory or its contents is modified or removed. Note that PathWatcher stops
+ monitoring files once they have been renamed or removed from disk, and directories
+ once they have been removed from disk.
+
+ Notes
+ -----
+ - On systems running a Linux kernel without inotify support, file systems that
+ contain watched paths cannot be unmounted.
+ - The act of monitoring files and directories for modifications consumes system
+ resources. This implies there is a limit to the number of files and directories
+ your process can monitor simultaneously. On all BSD variants, for example,
+ an open file descriptor is required for each monitored file. Some system limits
+ the number of open file descriptors to 256 by default. This means that
+ :meth:`~iblqt.core.PathWatcher.addPath` and
+ :meth:`~iblqt.core.PathWatcher.addPaths` will fail if your process tries to add
+ more than 256 files or directories to the PathWatcher. Also note that your
+ process may have other file descriptors open in addition to the ones for files
+ being monitored, and these other open descriptors also count in the total. macOS
+ uses a different backend and does not suffer from this issue.
+ """
+
+ fileChanged=Signal(Path)# type: Signal
+"""Emitted when a file has been modified, renamed or removed from disk."""
+
+ directoryChanged=Signal(Path)# type: Signal
+"""Emitted when a directory or its contents is modified or removed."""
+
+
+[docs]
+ def__init__(self,parent:QObject,paths:list[Path]|list[str]):
+"""Initialize the PathWatcher.
+
+ Parameters
+ ----------
+ parent : QObject
+ The parent object.
+ paths : list[Path] or list[str]
+ Paths or directories to be watched.
+ """
+ super().__init__(parent)
+ self._watcher=QFileSystemWatcher([],parent=self)
+ self.addPaths(paths)
+ self._watcher.fileChanged.connect(lambdaf:self.fileChanged.emit(Path(f)))
+ self._watcher.directoryChanged.connect(
+ lambdad:self.directoryChanged.emit(Path(d))
+ )
+
+
+
+[docs]
+ deffiles(self)->list[Path]:
+"""Return a list of paths to files that are being watched.
+
+ Returns
+ -------
+ list[Path]
+ List of paths to files that are being watched.
+ """
+ return[Path(f)forfinself._watcher.files()]
+
+
+
+[docs]
+ defdirectories(self)->list[Path]:
+"""Return a list of paths to directories that are being watched.
+
+ Returns
+ -------
+ list[Path]
+ List of paths to directories that are being watched.
+ """
+ return[Path(f)forfinself._watcher.directories()]
+
+
+
+[docs]
+ defaddPath(self,path:Path|str)->bool:
+"""
+ Add path to the PathWatcher.
+
+ The path is not added if it does not exist, or if it is already being monitored
+ by the PathWatcher.
+
+ If path specifies a directory, the directoryChanged() signal will be emitted
+ when path is modified or removed from disk; otherwise the fileChanged() signal
+ is emitted when path is modified, renamed or removed.
+
+ If the watch was successful, true is returned.
+
+ Reasons for a watch failure are generally system-dependent, but may include the
+ resource not existing, access failures, or the total watch count limit, if the
+ platform has one.
+
+ Note
+ ----
+ There may be a system dependent limit to the number of files and directories
+ that can be monitored simultaneously. If this limit is been reached, path will
+ not be monitored, and false is returned.
+
+ Parameters
+ ----------
+ path : Path or str
+ Path or directory to be watched.
+
+ Returns
+ -------
+ bool
+ True if the watch was successful, otherwise False.
+ """
+ returnself._watcher.addPath(str(path))
+
+
+
+[docs]
+ defaddPaths(self,paths:list[Path]|list[str])->list[Path]:
+"""
+ Add each path in paths to the PathWatcher.
+
+ Paths are not added if they do not exist, or if they are already being monitored
+ by the PathWatcher.
+
+ If a path specifies a directory, the directoryChanged() signal will be emitted
+ when the path is modified or removed from disk; otherwise the fileChanged()
+ signal is emitted when the path is modified, renamed, or removed.
+
+ The return value is a list of paths that could not be watched.
+
+ Reasons for a watch failure are generally system-dependent, but may include the
+ resource not existing, access failures, or the total watch count limit, if the
+ platform has one.
+
+ Note
+ ----
+ There may be a system dependent limit to the number of files and directories
+ that can be monitored simultaneously. If this limit has been reached, the excess
+ paths will not be monitored, and they will be added to the returned list.
+
+ Parameters
+ ----------
+ paths : list[Path] or list[str]
+ Paths or directories to be watched.
+
+ Returns
+ -------
+ list[Path]
+ List of paths that could not be watched.
+ """
+ out=self._watcher.addPaths([str(p)forpinpaths])
+ return[Path(x)forxinout]
+
+
+
+[docs]
+ defremovePath(self,path:Path|str)->bool:
+"""
+ Remove the specified path from the PathWatcher.
+
+ If the watch is successfully removed, true is returned.
+
+ Reasons for watch removal failing are generally system-dependent, but may be due
+ to the path having already been deleted, for example.
+
+ Parameters
+ ----------
+ path : list[Path] or list[str]
+ Path or directory to be removed from the PathWatcher.
+
+ Returns
+ -------
+ bool
+ True if the watch was successful, otherwise False.
+ """
+ returnself._watcher.removePath(str(path))
+
+
+
+[docs]
+ defremovePaths(self,paths:list[Path|str])->list[Path]:
+"""
+ Remove the specified paths from the PathWatcher.
+
+ The return value is a list of paths which were not able to be unwatched
+ successfully.
+
+ Reasons for watch removal failing are generally system-dependent, but may be due
+ to the path having already been deleted, for example.
+
+ Parameters
+ ----------
+ paths : list[Path] or list[str]
+ Paths or directories to be unwatched.
+
+ Returns
+ -------
+ list[Path]
+ List of paths which were not able to be unwatched successfully.
+ """
+ out=self._watcher.removePaths([str(p)forpinpaths])
+ return[Path(x)forxinout]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_modules/iblqt/widgets.html b/_modules/iblqt/widgets.html
new file mode 100644
index 0000000..92acd4b
--- /dev/null
+++ b/_modules/iblqt/widgets.html
@@ -0,0 +1,310 @@
+
+
+
+
+
+
+
+ iblqt.widgets — iblqt 0.3.2 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[docs]
+classCheckBoxDelegate(QStyledItemDelegate):
+"""
+ A custom delegate for rendering checkboxes in a QTableView or similar widget.
+
+ This delegate allows for the display and interaction with boolean data as checkboxes.
+ """
+
+
+[docs]
+ defpaint(
+ self,painter:QPainter,option:QStyleOptionViewItem,index:QModelIndex
+ )->None:
+"""
+ Paints the checkbox in the view.
+
+ Parameters
+ ----------
+ painter : QPainter
+ The painter used to draw the checkbox.
+ option : QStyleOptionButton
+ The style option containing the information needed for painting.
+ index : QModelIndex
+ The index of the item in the model.
+ """
+ super().paint(painter,option,index)
+ control=QStyleOptionButton()
+ control.rect=QRect(option.rect.topLeft(),QCheckBox().sizeHint())
+ control.rect.moveCenter(option.rect.center())
+ control.state=QStyle.State_Onifindex.data()isTrueelseQStyle.State_Off
+ QApplication.style().drawControl(
+ QStyle.ControlElement.CE_CheckBox,control,painter
+ )
+
+
+
+[docs]
+ defdisplayText(self,value:Any,locale:Any)->str:
+"""
+ Return an empty string to hide the text representation of the data.
+
+ Parameters
+ ----------
+ value : Any
+ The value to be displayed (not used).
+ locale : Any
+ The locale to be used (not used).
+
+ Returns
+ -------
+ str
+ An empty string.
+ """
+ return''
+
+
+
+[docs]
+ defeditorEvent(
+ self,
+ event:QEvent,
+ model:QAbstractItemModel,
+ option:QStyleOptionViewItem,
+ index:QModelIndex,
+ )->bool:
+"""
+ Handle user interaction with the checkbox.
+
+ Parameters
+ ----------
+ event : QEvent
+ The event that occurred (e.g., mouse click).
+ model : QAbstractItemModel
+ The model associated with the view.
+ option : QStyleOptionViewItem
+ The style option containing the information needed for handling the event.
+ index : QModelIndex
+ The index of the item in the model.
+
+ Returns
+ -------
+ bool
+ True if the event was handled, False otherwise.
+ """
+ ifisinstance(event,QMouseEvent)andevent.type()==QEvent.MouseButtonRelease:
+ checkbox_rect=QRect(option.rect.topLeft(),QCheckBox().sizeHint())
+ checkbox_rect.moveCenter(option.rect.center())
+ ifcheckbox_rect.contains(event.pos()):
+ model.setData(index,notmodel.data(index))
+ event.accept()
+ returnTrue
+ returnsuper().editorEvent(event,model,option,index)
+
+
+
+
+
+[docs]
+classStatefulButton(QPushButton):
+"""A QPushButton that maintains an active/inactive state."""
+
+ clickedWhileActive=Signal()# type: Signal
+"""Emitted when the button is clicked while it is in the active state."""
+
+ clickedWhileInactive=Signal()# type: Signal
+"""Emitted when the button is clicked while it is in the inactive state."""
+
+ stateChanged=Signal(bool)# type: Signal
+"""Emitted when the button's state has changed. The signal carries the new state
+ (True for active, False for inactive)."""
+
+
+[docs]
+ def__init__(self,*args,active:bool=False,**kwargs):
+"""Initialize the StatefulButton with the specified active state.
+
+ Parameters
+ ----------
+ *args : tuple
+ Positional arguments passed to QPushButton constructor.
+ active : bool, optional
+ Initial state of the button (default is False).
+ **kwargs : dict
+ Keyword arguments passed to QPushButton constructor.
+ """
+ super().__init__(*args,**kwargs)
+ self._isActive=active
+ self.clicked.connect(self._onClick)
+
+
+
+[docs]
+ defgetActive(self)->bool:
+"""Get the active state of the button.
+
+ Returns
+ -------
+ bool
+ True if the button is active, False otherwise.
+ """
+ returnself._isActive
+
+
+
+[docs]
+ @Slot(bool)
+ defsetActive(self,value:bool):
+"""Set the active state of the button.
+
+ Emits `stateChanged` if the state has changed.
+
+ Parameters
+ ----------
+ value : bool
+ The new active state of the button.
+ """
+ ifself._isActive!=value:
+ self._isActive=value
+ self.stateChanged.emit(self._isActive)
+
+
+ active=Property(bool,fget=getActive,fset=setActive,notify=stateChanged)# type: Property
+"""The active state of the button."""
+
+ @Slot()
+ def_onClick(self):
+"""Handle the button click event.
+
+ Emits `clickedWhileActive` if the button is active,
+ otherwise emits `clickedWhileInactive`.
+ """
+ ifself._isActive:
+ self.clickedWhileActive.emit()
+ else:
+ self.clickedWhileInactive.emit()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_modules/index.html b/_modules/index.html
new file mode 100644
index 0000000..733f305
--- /dev/null
+++ b/_modules/index.html
@@ -0,0 +1,110 @@
+
+
+
+
+
+
+
+ Overview: module code — iblqt 0.3.2 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Call addPath() to watch a particular file or
+directory. Multiple paths can be added using the
+addPaths() function. Existing paths can be removed by
+using the removePath() and
+removePaths() functions.
+
PathWatcher examines each path added to it. Files that have been added to the
+PathWatcher can be accessed using the files()
+function, and directories using the directories()
+function.
+
The fileChanged() signal is emitted when a file has
+been modified, renamed or removed from disk. Similarly, the
+directoryChanged() signal is emitted when a
+directory or its contents is modified or removed. Note that PathWatcher stops
+monitoring files once they have been renamed or removed from disk, and directories
+once they have been removed from disk.
+
+
Notes
+
+
On systems running a Linux kernel without inotify support, file systems that
+contain watched paths cannot be unmounted.
+
The act of monitoring files and directories for modifications consumes system
+resources. This implies there is a limit to the number of files and directories
+your process can monitor simultaneously. On all BSD variants, for example,
+an open file descriptor is required for each monitored file. Some system limits
+the number of open file descriptors to 256 by default. This means that
+addPath() and
+addPaths() will fail if your process tries to add
+more than 256 files or directories to the PathWatcher. Also note that your
+process may have other file descriptors open in addition to the ones for files
+being monitored, and these other open descriptors also count in the total. macOS
+uses a different backend and does not suffer from this issue.
The path is not added if it does not exist, or if it is already being monitored
+by the PathWatcher.
+
If path specifies a directory, the directoryChanged() signal will be emitted
+when path is modified or removed from disk; otherwise the fileChanged() signal
+is emitted when path is modified, renamed or removed.
+
If the watch was successful, true is returned.
+
Reasons for a watch failure are generally system-dependent, but may include the
+resource not existing, access failures, or the total watch count limit, if the
+platform has one.
+
+
Note
+
There may be a system dependent limit to the number of files and directories
+that can be monitored simultaneously. If this limit is been reached, path will
+not be monitored, and false is returned.
+
+
+
Parameters:
+
path (Path or str) – Path or directory to be watched.
+
+
Returns:
+
True if the watch was successful, otherwise False.
Paths are not added if they do not exist, or if they are already being monitored
+by the PathWatcher.
+
If a path specifies a directory, the directoryChanged() signal will be emitted
+when the path is modified or removed from disk; otherwise the fileChanged()
+signal is emitted when the path is modified, renamed, or removed.
+
The return value is a list of paths that could not be watched.
+
Reasons for a watch failure are generally system-dependent, but may include the
+resource not existing, access failures, or the total watch count limit, if the
+platform has one.
+
+
Note
+
There may be a system dependent limit to the number of files and directories
+that can be monitored simultaneously. If this limit has been reached, the excess
+paths will not be monitored, and they will be added to the returned list.
+
+
+
Parameters:
+
paths (list[Path] or list[str]) – Paths or directories to be watched.
This project is utilizing PDM as its package manager for managing dependencies and ensuring consistent and reproducible environments.
+See PDM’s documentation for details on installing PDM.