Metadata-Version: 2.1
Name: recent_items_list
Version: 1.2.1
Summary: RecentItemsList behaves both like a list, and like a LRU (Last Recently Used)
Author-email: Leon Dionne <ldionne@dridesign.sh.cn>
Description-Content-Type: text/markdown
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3.10
Classifier: Intended Audience :: Developers
Requires-Dist: pytest ; extra == "devel"
Project-URL: Home, https://github.com/Zen-Master-SoSo/recent_items_list
Provides-Extra: devel

# recent_items_list

Provides finite length Last Recently Used (LRU) caches.

## RecentItemsList

A class which stores any type of object.

Appending or "bump"-ing items adds them to the beginning of the list. If the
"maxlen" number of items already exist, the last item is dropped from the list.

By default, only the last 10 items are kept in the list. You can change this by
setting the "maxlen" property. Setting the "maxlen" property to < 1 makes for
an infinite length list, constrained only by system resourecs.

### bump

Bump the given item to the beginning of the list. If the given item is not in
the list, inserts it at the beginning.

```python
recent_items.bump(thing)
```

### append

Alias of "bump"

### remove

Removes the given item *if it is in the list*. Does nothing if the item is not
in the list.

```python
recent_items.remove(thing)
```

### on_change

Registers a callback which is run every time the list changes.
The callback must have the signature:

```python
def item_list_changed(self, items: list):
```

...where "item_list_changed" is an example function name.

### clear

Removes all items from the list


## RecentFilesList

This class extends RecentItemsList, providing a "prune" function to clear the
list only of files which don't exist.

### prune

Removes files which no longer exist.

## Example:

This is a simple implementation of a "Recent Files" menu in PyQt.

Instantiation:

```python
def __init__(self):
	self.recent_files = RecentFilesList(
		self.settings.value("RecentFiles", defaultValue = []))
	self.menuOpen_Recent.aboutToShow.connect(self.fill_recent_file_menu)
```

Filling the Qt menu:

```python
@pyqtSlot()
def fill_recent_file_menu(self):
	self.menuOpen_Recent.clear()
	actions = []
	for filename in self.recent_files:
		action = QAction(filename, self)
		action.triggered.connect(partial(self.load_file, filename))
		actions.append(action)
	self.menuOpen_Recent.addActions(actions)
```

Opening a file:

```python
def open(self, filename):
	self.recent_files.bump(filename)
	[...]
```

Saving to a QSettings instance:

```python
self.settings.setValue("RecentFiles", self.recent_files.items)
```

"RecentFiles" above is the setting key. It's just a string value. It could be
anything.

### on_change callback

An alternate method of saving the most recent file list without having to
explicitly save the changes, is to provide a callback which will be called
whenever the list changes, which saves the list to QSettings:

```python
self.recent_files = RecentFilesList(
	self.settings.value("RecentFiles", defaultValue = []))
self.recent_files.on_change(self.save_recent_files)

def save_recent_files(self, items):
	self.settings.setValue("RecentFiles", items)
```

## Another complete example:

```python
from functools import partial
from qt_extras.settings import init_settings, get_setting, set_setting
from recent_items_list import RecentFilesList

def recent_files():
	def sync(items):
		set_setting("RecentFiles", items)
	if not hasattr(recent_files, "list"):
		recent_files.list = RecentFilesList(get_setting("RecentFiles", []))
		recent_files.list.on_change(sync)
	return recent_files.list

class Window(QMainWindow):

	def __init__(self):
		super().__init__()
		settings.init("ZenSoSo", __package__)
		self.menuOpen_Recent.aboutToShow.connect(self.fill_recent_file_menu)

	@pyqtSlot()
	def fill_recent_file_menu(self):
		self.menuOpen_Recent.clear()
		actions = []
		for filename in recent_files().prune():
			action = QAction(filename, self)
			action.triggered.connect(partial(self.load_file, filename))
			actions.append(action)
		self.menuOpen_Recent.addActions(actions)

	def load_file(self, filename):
		self.recent_files.bump(filename)

```

