Skip to content

Commit

Permalink
Implemented pagination
Browse files Browse the repository at this point in the history
Implemented async call for remaining time query + spinner for wait
  • Loading branch information
ggalan87 committed Dec 10, 2018
1 parent f330196 commit 7ffb551
Show file tree
Hide file tree
Showing 8 changed files with 240 additions and 29 deletions.
8 changes: 5 additions & 3 deletions dashboard/remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import math
import json


class Store:

sample_descr = lorem.paragraph()
Expand Down Expand Up @@ -53,11 +54,12 @@ def get_metadata():

return data, (duration - elapsed)


import time
# TODO: make it async
def query_autopilot_remaining():
data, next = get_metadata()
print(data)
time.sleep(3)
return next


Expand All @@ -68,5 +70,5 @@ def fetch_sample_messages(page_length, page_number):
all = c.fetchall()

len_all = len(all)
data_slice = slice(len_all - page_length * page_number, len_all - page_length * (page_number - 1))
return all[data_slice]
data_slice = slice(max(0, len_all - page_length * page_number), len_all - page_length * (page_number - 1))
return all[data_slice][::-1], len_all
71 changes: 71 additions & 0 deletions dashboard/utilities.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import math


class PaginationState:
def __init__(self, total_items, items_per_page=20):
self._sensitivities = None
self._current_page = 1
self._total_items = total_items
self._items_per_page = items_per_page

self._n_pages = self._calculate_n_pages()
self._assign_sensitivities()

def _assign_sensitivities(self):
# Single page
if self._total_items <= self._items_per_page:
self._sensitivities = (False, False, False, False)
# First page
elif self._current_page == 1:
self._sensitivities = (False, False, True, True)
# Last page
elif self._current_page == self._n_pages:
self._sensitivities = (True, True, False, False)
# Middle page
else:
self._sensitivities = (True, True, True, True)

def _get_shown_range(self):
first = (self._current_page - 1) * self._items_per_page + 1
last = min(self._total_items, first + self._items_per_page - 1)

return first, last

def _calculate_n_pages(self):
return math.ceil(self._total_items / self._items_per_page)

def goto_next_page(self):
if self._current_page < self._n_pages:
self._current_page += 1
self._assign_sensitivities()

return self._current_page, self._sensitivities, self._get_shown_range()

def goto_previous_page(self):
if self._current_page > 1:
self._current_page -= 1
self._assign_sensitivities()

return self._current_page, self._sensitivities, self._get_shown_range()

def goto_first_page(self):
if self._current_page != 1:
self._current_page = 1
self._assign_sensitivities()

return self._current_page, self._sensitivities, self._get_shown_range()

def goto_last_page(self):
if self._current_page != self._n_pages:
self._current_page = self._n_pages
self._assign_sensitivities()

return self._current_page, self._sensitivities, self._get_shown_range()

@property
def total_items(self):
return self._total_items

@total_items.setter
def total_items(self, value):
self._total_items = value
11 changes: 9 additions & 2 deletions dashboard/views/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,15 @@ def setup_shows_listbox(lb, shows):
lb.bind_model(ls, lambda model, data: show.Show(model.title, model.subtitle, model.logo_path), None)


def setup_inbox_listbox(lb, messages):
ls = Gio.ListStore()
def setup_inbox_listbox(lb, ls, messages):
ls.remove_all()
for m in messages:
ls.append(MessageObject(html.unescape(m[5]), m[2], m[1]))
lb.bind_model(ls, lambda model, data: Message(model.message, model.sender, model.timestamp), None)
return ls


def update_inbox_model(ls, messages):
ls.remove_all()
for m in messages:
ls.append(MessageObject(html.unescape(m[5]), m[2], m[1]))
38 changes: 38 additions & 0 deletions dashboard/widgets/livepage.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ class LivePage(Gtk.Notebook):
__gsignals__ = \
{
'live-page-shown': (GObject.SignalFlags.RUN_FIRST, None, ()),
'goto-next-clicked': (GObject.SignalFlags.RUN_FIRST, None, ()),
'goto-previous-clicked': (GObject.SignalFlags.RUN_FIRST, None, ()),
'goto-first-clicked': (GObject.SignalFlags.RUN_FIRST, None, ()),
'goto-last-clicked': (GObject.SignalFlags.RUN_FIRST, None, ()),
}

def __repr__(self):
Expand All @@ -23,10 +27,44 @@ def __init__(self):
super().__init__()
self._message = utils.get_descendant(self, 'message_textview', 0)

self._pagination_info = utils.get_descendant(self, 'pagination_info', 0)
self._goto_first_button = utils.get_descendant(self, 'goto_first_button', 0)
self._goto_previous_button = utils.get_descendant(self, 'goto_previous_button', 0)
self._goto_next_button = utils.get_descendant(self, 'goto_next_button', 0)
self._goto_last_button = utils.get_descendant(self, 'goto_last_button', 0)

@Gtk.Template.Callback()
@log
def on_LivePage_map(self, widget):
self.emit('live-page-shown')

@Gtk.Template.Callback()
@log
def on_goto_first_button_clicked(self, widget):
self.emit('goto-first-clicked')

@Gtk.Template.Callback()
@log
def on_goto_previous_button_clicked(self, widget):
self.emit('goto-previous-clicked')

@Gtk.Template.Callback()
@log
def on_goto_next_button_clicked(self, widget):
self.emit('goto-next-clicked')

@Gtk.Template.Callback()
@log
def on_goto_last_button_clicked(self, widget):
self.emit('goto-last-clicked')

def set_buffer(self, text_buffer: Gtk.TextBuffer):
self._message.set_buffer(text_buffer)

def update_pagination(self, info, sensitivities):
self._pagination_info.set_text(info)

self._goto_first_button.set_sensitive(sensitivities[0])
self._goto_previous_button.set_sensitive(sensitivities[1])
self._goto_next_button.set_sensitive(sensitivities[2])
self._goto_last_button.set_sensitive(sensitivities[3])
16 changes: 14 additions & 2 deletions dashboard/widgets/waitpage.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class WaitPage(Gtk.Box):

__gsignals__ = \
{
'wait-page-shown': (GObject.SignalFlags.RUN_FIRST, None, (Gtk.Label, Gtk.TextView, Gtk.Label)),
'wait-page-shown': (GObject.SignalFlags.RUN_FIRST, None, ()),
'instant-attempted': (GObject.SignalFlags.RUN_FIRST, None, ()),
'cancel-attempted': (GObject.SignalFlags.RUN_FIRST, None, ()),
}
Expand All @@ -26,11 +26,12 @@ def __init__(self):
self._show_title = utils.get_descendant(self, 'showtitle_label', 0)
self._message = utils.get_descendant(self, 'message_textview', 0)
self._remaining = utils.get_descendant(self, 'remaining_label', 0)
self._remaining_stack = utils.get_descendant(self, 'remaining_stack', 0)

@Gtk.Template.Callback()
@log
def on_WaitPage_map(self, widget):
self.emit('wait-page-shown', self._show_title, self._message, self._remaining)
self.emit('wait-page-shown')

@Gtk.Template.Callback()
@log
Expand All @@ -44,3 +45,14 @@ def on_cancel_button_clicked(self, widget):

def set_buffer(self, text_buffer: Gtk.TextBuffer):
self._message.set_buffer(text_buffer)

def set_title(self, txt):
self._show_title.set_text(txt)

def set_wait(self):
self._remaining_stack.set_visible_child_name('wait_spinner')

def set_remaining(self, txt):
self._remaining.set_text(txt)
self._remaining_stack.set_visible_child_name('remaining_label')

81 changes: 68 additions & 13 deletions dashboard/window.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from gi.repository import Gtk, Gdk, Gio, GLib, GObject
from gettext import gettext as _

import sys
import math
from multiprocessing.pool import ThreadPool
from dashboard import log
from dashboard.widgets.headerbar import HeaderBar

Expand All @@ -13,6 +16,7 @@

from dashboard.remote import *
from dashboard.views import views, utils
from dashboard.utilities import PaginationState

from enum import IntEnum

Expand Down Expand Up @@ -46,9 +50,15 @@ def __init__(self, app):
self.timer_id = None
self.time_for_live = None

self.pagination_state = None

# Keep a single TextBuffer for all pages
self.message_buffer = Gtk.TextBuffer()
self.messages_model = None

self.inbox_messages_model = Gio.ListStore()

self.pool = ThreadPool(processes=1)

# </State>

self.prev_view = None
Expand Down Expand Up @@ -122,7 +132,10 @@ def _setup_view(self):
self._pages['wait_page'].connect('cancel-attempted', self._on_cancel_attempted)

self._pages['live_page'].connect('live-page-shown', self._on_live_page_shown)

self._pages['live_page'].connect('goto-first-clicked', self._on_goto_first_clicked)
self._pages['live_page'].connect('goto-previous-clicked', self._on_goto_previous_clicked)
self._pages['live_page'].connect('goto-next-clicked', self._on_goto_next_clicked)
self._pages['live_page'].connect('goto-last-clicked', self._on_goto_last_clicked)

# Setup title bar
self._headerbar = HeaderBar()
Expand Down Expand Up @@ -187,13 +200,19 @@ def _on_golive_attempted(self, widget):
self._views_stack.set_visible_child(self._pages['wait_page'])

@log
def _on_wait_page_shown(self, widget, show_title_label, message_textview, remaining_label):
show_title_label.set_text(self.current_show.title)
def _on_wait_page_shown(self, wait_page):
wait_page.set_title(self.current_show.title)
wait_page.set_wait()
self.pool.apply_async(self.query_autopilot_remaining, [wait_page], callback=Window.init_timer)

def query_autopilot_remaining(self, widget):
return self, query_autopilot_remaining(), widget

# initiate timer
self.time_for_live = query_autopilot_remaining()
remaining_label.set_text(str(self.time_for_live))
self.timer_id = GLib.timeout_add(1000, self._timer_callback, remaining_label)
@staticmethod
def init_timer(async_return):
async_return[0].time_for_live = async_return[1]
async_return[2].set_remaining(str(async_return[0].time_for_live))
async_return[0].timer_id = GLib.timeout_add(1000, async_return[0]._timer_callback, async_return[2])

@log
def _on_instant_attempted(self, widget):
Expand All @@ -207,28 +226,52 @@ def _on_cancel_attempted(self, widget):

@log
def _on_live_page_shown(self, widget):
messages = fetch_sample_messages(20, 1)
messages_subset, total_messages = fetch_sample_messages(20, 1)
self.pagination_state = PaginationState(total_messages)

_, sensitivities, (first, last) = self.pagination_state.goto_first_page()
info = self._get_pagination_info(first, last, total_messages)
widget.update_pagination(info, sensitivities)

lb = utils.get_descendant(widget, 'inbox_messages_view', 0)
views.setup_inbox_listbox(lb, messages)
views.setup_inbox_listbox(lb, self.inbox_messages_model, messages_subset)

@log
def _on_goto_first_clicked(self, widget):
self._handle_pagination_clicked(widget, self.pagination_state.goto_first_page)

@log
def _on_goto_previous_clicked(self, widget):
self._handle_pagination_clicked(widget, self.pagination_state.goto_previous_page)

@log
def _on_goto_next_clicked(self, widget):
self._handle_pagination_clicked(widget, self.pagination_state.goto_next_page)


@log
def _on_goto_last_clicked(self, widget):
self._handle_pagination_clicked(widget, self.pagination_state.goto_last_page)

# Helper functions

def switch_to_live(self):
self._views_stack.set_visible_child(self._pages['live_page'])

def _timer_callback(self, label):
def _timer_callback(self, widget):
self.time_for_live -= 1

if self.time_for_live == 0:
self._invalidate_timer()
self.switch_to_live()
return False
else:
label.set_text(str(self.time_for_live))
widget.set_remaining(str(self.time_for_live))
return True

def _invalidate_timer(self):
GLib.source_remove(self.timer_id)
if self.timer_id:
GLib.source_remove(self.timer_id)

def _setup_current_show(self, shows_stack):
show_option = shows_stack.get_visible_child()
Expand All @@ -244,3 +287,15 @@ def _setup_current_show(self, shows_stack):
self.current_show = Show(special_title, [self.current_user], special_nickname, '', [], '')
else:
assert False

def _get_pagination_info(self, first, last, total_messages):
return '{}-{} out of {}'.format(first, last, total_messages)

def _handle_pagination_clicked(self, live_page, pagination_func):
page_number, sensitivities, (first, last) = pagination_func()
messages_subset, _ = fetch_sample_messages(20, page_number)

info = self._get_pagination_info(first, last, self.pagination_state.total_items)
live_page.update_pagination(info, sensitivities)

views.update_inbox_model(self.inbox_messages_model, messages_subset)
Loading

0 comments on commit 7ffb551

Please sign in to comment.