2017-07-19, 15:47
I'm trying to implement pagination for my add-on in the following fashion:
Add-on setting links_per_page is set to 10
1. Add-on scrapes page 1 of source (for example sake, say it returns 15 links)
2. Displays the first 10 links on the first page of the add-on
3. Stores the excess (5) links in the paging.p pickle
4. Adds a Next Page directory item at the bottom of the list of links in kodi
5. User selected the Next Page directory item
6. The excess (5) links from the pickle are added to the beginning of the list for the next page
7. Add-on scrapes page 2 of source (returns 15 links)
8. Displays the excess (5) links, followed by the first 5 links from page 2
9. Store the excess (5) links from source's page 2 in the paging.p pickle
10. Adds a Next Page directory item at the bottom of the list of links in kodi
And continues like that.
I'm able to successfully accomplish the above flow with the following code in most cases.
The case where this fails to function properly is when a single page returns more than 2x the links_per_page variable (ex: 30 links returned when links_per_page set to 10). In that case I get the Next Page directory item for the first page, but once I click it the second page of results is loaded, but the Next Page directory item isn't placed at the bottom of the directory.
Even in the event that that issue is resolved I'm still faced with the confusing dilemma of keeping track of pages for sources
Example:
Add-on Page 1 (10 links - taken from source)| Source Page 1 (20 links) | Pickle (10 links)
Add-on Page 2 (10 links - taken from pickle) | Source Page 1 | Pickle (back to 0)
Add-on Page 3 (10 links - taken from source)| Source Page 2 (20 links) | Pickle (10 links)
Add-on Page 4 (10 links - taken from pickle) | Source Page 2 | Pickle (back to 0)
and so on
Also, in general, I feel like my paginating implementation is really messy/hack-y. Can anyone show me a better way to implement this sort of feature?
Add-on setting links_per_page is set to 10
1. Add-on scrapes page 1 of source (for example sake, say it returns 15 links)
2. Displays the first 10 links on the first page of the add-on
3. Stores the excess (5) links in the paging.p pickle
4. Adds a Next Page directory item at the bottom of the list of links in kodi
5. User selected the Next Page directory item
6. The excess (5) links from the pickle are added to the beginning of the list for the next page
7. Add-on scrapes page 2 of source (returns 15 links)
8. Displays the excess (5) links, followed by the first 5 links from page 2
9. Store the excess (5) links from source's page 2 in the paging.p pickle
10. Adds a Next Page directory item at the bottom of the list of links in kodi
And continues like that.
I'm able to successfully accomplish the above flow with the following code in most cases.
Code:
def get_listing(self, source, page=1):
import importlib
import cPickle
if '[' in source: #Remove Status Label
source = source[:source.find('[')]
source_str = source.lower()
source = importlib.import_module('.'+source_str, package='resources.lib.sources')
#Stored here: C:\Users\mhill\Desktop\Portable Apps\Kodi Portable\Kodi
try:
f = open('paging.p', 'rb')
paging = cPickle.load(f)
except:
f = open('paging.p', 'wb')
paging = {source_str:{}}
cPickle.dump(paging, f, -1)
f.close()
#Issue with current method:
#If one page has over 2x per_page it causes Next Page option
#to not be displayed after first time it's selected
per_page = int(data.addon.getSetting('links_per_page'))
if source_str in paging and 'excess' in paging[source_str]:
display_these_now = paging[source_str]['excess']
else:
display_these_now = []
i=1
links = source.Site().scrape(page)
while (len(display_these_now) < per_page and len(links) != 0):
display_these_now = display_these_now + links
i += 1
links = source.Site().scrape(int(page)+i)
if len(display_these_now) > per_page:
paging[source_str] = {'excess': display_these_now[per_page:]}
display_these_now = display_these_now[:per_page]
f = open('paging.p', 'wb')
cPickle.dump(paging, f, -1)
f.close()
print list(display_these_now)
for i, (title, image, link) in enumerate(display_these_now):
list_item = xbmcgui.ListItem(label=title)
list_item.setProperty('IsPlayable','true')
list_item.setArt({'poster': image, 'banner': image})
url = get_url(action='play', video=link)
xbmcplugin.addDirectoryItem(data._handle, url, list_item, False)
if len(links) != 0:
list_item = xbmcgui.ListItem(label='NEXT PAGE >>>')
#list_item.setArt({'poster': image, 'banner': image})
url = get_url(action='listing', source=source_str, page=int(page)+i)
xbmcplugin.addDirectoryItem(data._handle, url, list_item, True)
xbmcplugin.addSortMethod(data._handle, xbmcplugin.SORT_METHOD_NONE)
xbmcplugin.endOfDirectory(data._handle)
The case where this fails to function properly is when a single page returns more than 2x the links_per_page variable (ex: 30 links returned when links_per_page set to 10). In that case I get the Next Page directory item for the first page, but once I click it the second page of results is loaded, but the Next Page directory item isn't placed at the bottom of the directory.
Even in the event that that issue is resolved I'm still faced with the confusing dilemma of keeping track of pages for sources
Example:
Add-on Page 1 (10 links - taken from source)| Source Page 1 (20 links) | Pickle (10 links)
Add-on Page 2 (10 links - taken from pickle) | Source Page 1 | Pickle (back to 0)
Add-on Page 3 (10 links - taken from source)| Source Page 2 (20 links) | Pickle (10 links)
Add-on Page 4 (10 links - taken from pickle) | Source Page 2 | Pickle (back to 0)
and so on
Also, in general, I feel like my paginating implementation is really messy/hack-y. Can anyone show me a better way to implement this sort of feature?