[rigo] App Rating integration, NotificationBox Context support, a lot of other improvements

This commit is contained in:
Fabio Erculiani
2012-02-28 11:13:07 +01:00
parent 671901279a
commit 24fbdc5f56
8 changed files with 360 additions and 170 deletions

View File

@@ -1,66 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="150"
height="40"
id="svg2"
version="1.1"
inkscape:version="0.48.2 r9819"
sodipodi:docname="comment-separator.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.4"
inkscape:cx="-72.515822"
inkscape:cy="26.150743"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1280"
inkscape:window-height="744"
inkscape:window-x="0"
inkscape:window-y="26"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Livello 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1012.3622)">
<path
sodipodi:type="arc"
style="fill:#aaaaaa;fill-opacity:1;stroke:none"
id="path2985"
sodipodi:cx="64.285713"
sodipodi:cy="45"
sodipodi:rx="20"
sodipodi:ry="20"
d="m 84.285713,45 a 20,20 0 1 1 -40,0 20,20 0 1 1 40,0 z"
transform="matrix(0.76580796,0,0,0.76580796,25.769489,997.90084)" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -106,6 +106,7 @@ GtkInfoBar #message-area-error GtkLabel {
}
/* Application View Comment Box */
#comment-box-title {
color: #613056; /* purple */
}
@@ -114,4 +115,4 @@ GtkInfoBar #message-area-error GtkLabel {
}
#comment-box-author {
color: brown;
}
}

View File

@@ -26,7 +26,7 @@
<signal name="delete-event" handler="onDeleteWindow" swapped="no"/>
<child>
<object class="GtkVBox" id="appVbox">
<property name="width_request">600</property>
<property name="width_request">650</property>
<property name="height_request">400</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
@@ -264,11 +264,21 @@
</packing>
</child>
<child>
<object class="GtkVBox" id="appViewCommentsVbox">
<object class="GtkAlignment" id="appViewCommentsAlign">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="top_padding">5</property>
<property name="left_padding">25</property>
<property name="right_padding">25</property>
<child>
<placeholder/>
<object class="GtkVBox" id="appViewCommentsVbox">
<property name="width_request">300</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
<packing>
@@ -278,11 +288,21 @@
</packing>
</child>
<child>
<object class="GtkVBox" id="appViewMyCommentsVbox">
<object class="GtkAlignment" id="appViewMyCommentsAlign">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="bottom_padding">5</property>
<property name="left_padding">25</property>
<property name="right_padding">25</property>
<child>
<placeholder/>
<object class="GtkVBox" id="appViewMyCommentsVbox">
<property name="width_request">300</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
<packing>
@@ -295,20 +315,6 @@
<object class="GtkVBox" id="appViewCommentsWriteVbox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel" id="appViewCommentWriteLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">&lt;small&gt;&lt;i&gt;Comment this &lt;b&gt;Application&lt;/b&gt;&lt;/i&gt;&lt;/small&gt;</property>
<property name="use_markup">True</property>
<property name="wrap">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkAlignment" id="appViewCommentTextAlign">
<property name="visible">True</property>
@@ -332,7 +338,7 @@
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
<property name="position">0</property>
</packing>
</child>
<child>
@@ -341,13 +347,20 @@
<property name="can_focus">False</property>
<child>
<object class="GtkButton" id="appViewCommentSendButton">
<property name="label" translatable="yes">_Send</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="image">appViewCommentSendImage1</property>
<property name="use_underline">True</property>
<child>
<object class="GtkLabel" id="appViewCommentSendButtonLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_Write a &lt;b&gt;comment&lt;/b&gt;</property>
<property name="use_markup">True</property>
<property name="use_underline">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
@@ -360,7 +373,19 @@
<property name="expand">True</property>
<property name="fill">True</property>
<property name="padding">4</property>
<property name="position">3</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="appViewCommentMoreLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label">Want to see more?</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>

View File

@@ -36,12 +36,13 @@ from entropy.client.services.interfaces import ClientWebService
import entropy.tools
from rigo.enums import Icons
from rigo.utils import build_application_store_url
LOG = logging.getLogger(__name__)
class ReviewStats(object):
NO_RATING = 1
NO_RATING = 0
def __init__(self, app):
self.app = app
@@ -816,12 +817,17 @@ class Application(object):
else:
use_txt += _("No use flags")
text = "<small>%s\n%s\n%s\n%s\n%s</small>" % (
more_txt = "<a href=\"%s\"><b>%s</b></a>" % (
build_application_store_url(self, ""),
_("Click here for more details"),)
text = "<small>%s\n%s\n%s\n%s\n%s\n\n%s</small>" % (
down_size_txt,
required_space_txt,
licenses_txt,
digest_txt,
use_txt,
more_txt,
)
return text

View File

@@ -32,6 +32,27 @@ class CommentBox(Gtk.VBox):
self._is_last = is_last
def render(self):
vbox = Gtk.VBox()
ts_id = Document.DOCUMENT_TIMESTAMP_ID
user_id = DocumentFactory.DOCUMENT_USERNAME_ID
label = Gtk.Label()
time_str = entropy.tools.convert_unix_time_to_human_time(
self._comment[ts_id])
time_str = GObject.markup_escape_text(time_str)
label.set_markup(
"<small><b>%s</b>" % (self._comment[user_id],) \
+ ", <i>" + time_str + "</i>" \
+ "</small>")
label.set_line_wrap(True)
label.set_line_wrap_mode(Pango.WrapMode.WORD)
label.set_alignment(0.0, 1.0)
label.set_selectable(True)
label.set_name("comment-box-author")
label.show()
vbox.pack_start(label, False, False, 0)
# title, keywords, ddata, document_id
title = self._comment['title'].strip()
@@ -45,7 +66,7 @@ class CommentBox(Gtk.VBox):
label.set_alignment(0.0, 0.0)
label.set_selectable(True)
label.show()
self.pack_start(label, False, False, 0)
vbox.pack_start(label, False, False, 0)
data_id = Document.DOCUMENT_DATA_ID
label = Gtk.Label()
@@ -56,29 +77,13 @@ class CommentBox(Gtk.VBox):
label.set_alignment(0.0, 0.0)
label.set_selectable(True)
label.show()
self.pack_start(label, False, False, 0)
vbox.pack_start(label, False, False, 0)
ts_id = Document.DOCUMENT_TIMESTAMP_ID
user_id = DocumentFactory.DOCUMENT_USERNAME_ID
label = Gtk.Label()
time_str = entropy.tools.convert_unix_time_to_human_time(
self._comment[ts_id])
time_str = GObject.markup_escape_text(time_str)
label.set_markup(
"<small><i>" + time_str \
+ "</i>, <b>%s</b>" % (self._comment[user_id],) \
+ "</small>")
label.set_line_wrap(True)
label.set_line_wrap_mode(Pango.WrapMode.WORD)
label.set_alignment(0.98, 0.0)
label.set_selectable(True)
label.set_name("comment-box-author")
label.show()
self.pack_start(label, False, False, 0)
if not self._is_last:
image = Gtk.Image.new_from_icon_name("comment-separator",
Gtk.IconSize.BUTTON)
image.set_pixel_size(50)
self.pack_start(image, False, False, 0)
image.show()
if self._is_last:
self.pack_start(vbox, False, False, 0)
else:
align = Gtk.Alignment()
align.set_padding(0, 10, 0, 0)
align.add(vbox)
self.pack_start(align, False, False, 0)
align.show_all()

View File

@@ -1,11 +1,16 @@
import subprocess
from gi.repository import Gtk, GLib, GObject
from rigo.utils import build_register_url, open_url
from entropy.i18n import _
from entropy.services.client import WebService
from entropy.misc import ParallelTask
class NotificationBox(Gtk.HBox):
"""
@@ -14,7 +19,8 @@ class NotificationBox(Gtk.HBox):
"""
def __init__(self, message, message_widget=None,
message_type=None, tooltip=None):
message_type=None, tooltip=None,
context_id=None):
Gtk.HBox.__init__(self)
self._message = message
# if not None, it will replace Gtk.Label(self._message)
@@ -24,6 +30,7 @@ class NotificationBox(Gtk.HBox):
if self._type is None:
self._type = Gtk.MessageType.INFO
self._tooltip = tooltip
self._context_id = context_id
def add_button(self, text, clicked_callback):
"""
@@ -82,6 +89,15 @@ class NotificationBox(Gtk.HBox):
bar.get_action_area().hide()
self.pack_start(bar, True, True, 0)
def get_context_id(self):
"""
Multiple NotificationBox instances can
share the same context_id. This information
is useful when showing multiple notifications
sharing the same context is unwanted.
"""
return self._context_id
class UpdatesNotificationBox(NotificationBox):
@@ -118,7 +134,8 @@ class UpdatesNotificationBox(NotificationBox):
NotificationBox.__init__(self, msg,
tooltip=_("Updates available, how about installing them?"),
message_type=Gtk.MessageType.WARNING)
message_type=Gtk.MessageType.WARNING,
context_id="UpdatesNotificationBox")
self.add_button(_("_Update System"), self._update)
self.add_button(_("_Show"), self._show)
self.add_destroy_button(_("_Ignore"))
@@ -154,7 +171,8 @@ class RepositoriesUpdateNotificationBox(NotificationBox):
NotificationBox.__init__(self, msg,
tooltip=_("I dunno dude, I'd say Yes"),
message_type=Gtk.MessageType.ERROR)
message_type=Gtk.MessageType.ERROR,
context_id="RepositoriesUpdateNotificationBox")
self.add_button(_("_Yes, why not?"), self._update)
self.add_destroy_button(_("_No, thanks"))
@@ -185,17 +203,21 @@ class LoginNotificationBox(NotificationBox):
),
}
def __init__(self, entropy_ws, app):
def __init__(self, entropy_ws, app, context_id=None):
self._entropy_ws = entropy_ws
self._app = app
self._repository_id = app.get_details().channelname
if context_id is None:
context_id = "LoginNotificationBox"
NotificationBox.__init__(self, None,
message_widget=self._make_login_box(),
tooltip=_("You need to login to Entropy Web Services"),
message_type=Gtk.MessageType.WARNING)
message_type=Gtk.MessageType.WARNING,
context_id=context_id)
self.add_button(_("_Login"), self._login)
self.add_button(_("Register"), self._register)
def _destroy(*args):
self.emit("login-failed", self._app)
@@ -277,3 +299,8 @@ class LoginNotificationBox(NotificationBox):
task.daemon = True
task.start()
def _register(self, button):
"""
Register button click event.
"""
open_url(build_register_url())

View File

@@ -1,8 +1,10 @@
import os
import subprocess
from entropy.const import etpConst
from entropy.core.settings.base import SystemSettings
from entropy.misc import ParallelTask
def build_application_store_url(app, sub_page):
"""
@@ -33,3 +35,15 @@ def build_register_url():
Build User Account Registration Form URL.
"""
return os.path.join(etpConst['distro_website_url'], "register")
def open_url(url):
"""
Open the given URL using xdg-open
"""
def _open_url(url):
subprocess.call(["xdg-open", url])
task = ParallelTask(_open_url, url)
task.name = "UrlOpen"
task.daemon = True
task.start()

View File

@@ -169,6 +169,7 @@ class NotificationViewController(GObject.Object):
self._box = notification_box
self._updates = None
self._security_updates = None
self._context_id_map = {}
def setup(self):
GLib.timeout_add(3000, self._calculate_updates)
@@ -238,10 +239,18 @@ class NotificationViewController(GObject.Object):
"""
self._avc.set_many_safe(self._updates)
def append(self, box, timeout=None):
def append(self, box, timeout=None, context_id=None):
"""
Append a notification to the Notification area.
context_id is used to automatically drop any other
notification exposing the same context identifier.
"""
context_id = box.get_context_id()
if context_id is not None:
old_box = self._context_id_map.get(context_id)
if old_box is not None:
old_box.destroy()
self._context_id_map[context_id] = box
box.render()
self._box.pack_start(box, False, False, 0)
box.show()
@@ -263,7 +272,7 @@ class NotificationViewController(GObject.Object):
area, if there.
"""
if box in self._box.get_children():
self._box.remove(box)
self._context_id_map.pop(box.get_context_id(), None)
box.destroy()
def remove_safe(self, box):
@@ -277,8 +286,8 @@ class NotificationViewController(GObject.Object):
Clear all the notifications.
"""
for child in self._box.get_children():
self._box.remove(child)
child.destroy()
self._context_id_map.clear()
def clear_safe(self):
"""
@@ -294,6 +303,19 @@ class ApplicationViewController(GObject.Object):
TreeView.
"""
class WindowedReactiveStar(ReactiveStar):
def __init__(self, window):
self._window = window
self._hand = Gdk.Cursor.new(Gdk.CursorType.HAND2)
ReactiveStar.__init__(self)
def on_enter_notify(self, widget, event):
self._window.get_window().set_cursor(self._hand)
def on_leave_notify(self, widget, event):
self._window.get_window().set_cursor(None)
__gsignals__ = {
# Double click on application widget
"application-activated" : (GObject.SignalFlags.RUN_LAST,
@@ -325,6 +347,9 @@ class ApplicationViewController(GObject.Object):
),
}
VOTE_NOTIFICATION_CONTEXT_ID = "VoteNotificationContext"
COMMENT_NOTIFICATION_CONTEXT_ID = "CommentNotificationContext"
def __init__(self, entropy_client, entropy_ws, builder):
GObject.Object.__init__(self)
self._builder = builder
@@ -334,14 +359,21 @@ class ApplicationViewController(GObject.Object):
self._last_app = None
self._nc = None
self._window = self._builder.get_object("rigoWindow")
self._image = self._builder.get_object("appViewImage")
self._app_name_lbl = self._builder.get_object("appViewNameLabel")
self._app_info_lbl = self._builder.get_object("appViewInfoLabel")
self._app_downloaded_lbl = self._builder.get_object(
"appViewDownloadedLabel")
self._app_comments_box = self._builder.get_object("appViewCommentsVbox")
self._app_comments_box.set_name("comments-box")
self._app_comments_align = self._builder.get_object(
"appViewCommentsAlign")
self._app_my_comments_box = self._builder.get_object(
"appViewMyCommentsVbox")
self._app_my_comments_align = self._builder.get_object(
"appViewMyCommentsAlign")
self._app_my_comments_box.set_name("comments-box")
self._app_comment_send_button = self._builder.get_object(
"appViewCommentSendButton")
self._app_comment_text_view = self._builder.get_object(
@@ -349,9 +381,12 @@ class ApplicationViewController(GObject.Object):
self._app_comment_text_view.set_name("rigo-text-view")
self._app_comment_text_buffer = self._builder.get_object(
"appViewCommentTextBuffer")
self._app_comment_more_label = self._builder.get_object(
"appViewCommentMoreLabel")
self._stars_container = self._builder.get_object("appViewStarsSelVbox")
self._stars = ReactiveStar()
self._stars = ApplicationViewController.WindowedReactiveStar(
self._window)
self._stars_alignment = Gtk.Alignment.new(0.0, 0.5, 1.0, 1.0)
self._stars_alignment.set_padding(0, 5, 0, 0)
self._stars_alignment.add(self._stars)
@@ -378,6 +413,7 @@ class ApplicationViewController(GObject.Object):
self._app_comment_send_button.set_sensitive(False)
self._app_comment_text_buffer.connect(
"changed", self._on_comment_buffer_changed)
self._stars.connect("changed", self._on_stars_clicked)
def _on_comment_buffer_changed(self, widget):
"""
@@ -411,6 +447,149 @@ class ApplicationViewController(GObject.Object):
icon = self._app_store.get_icon(pkg_match)
self._setup_application_stats(stats, icon)
def _on_stars_clicked(self, widget, app=None):
"""
Stars clicked, user wants to vote.
"""
if app is None:
app = self._last_app
if app is None:
# wtf
return
def _sender(app, vote):
if not app.is_webservice_available():
GLib.idle_add(self._notify_webservice_na, app,
self.VOTE_NOTIFICATION_CONTEXT_ID)
return
ws_user = app.get_webservice_username()
if ws_user is not None:
GLib.idle_add(self._notify_vote_submit, app, ws_user, vote)
else:
GLib.idle_add(self._notify_login_request, app, vote,
self._on_stars_login_success,
self._on_stars_login_failed,
self.VOTE_NOTIFICATION_CONTEXT_ID)
vote = int(self._stars.get_rating()) # is float
task = ParallelTask(_sender, app, vote)
task.name = "AppViewSendVote"
task.start()
def _on_stars_login_success(self, widget, username, app):
"""
Notify user that we successfully logged in!
"""
box = NotificationBox(
_("Logged in as <b>%s</b>! How about your <b>vote</b>?") \
% (GObject.markup_escape_text(username),),
message_type=Gtk.MessageType.INFO,
context_id=self.VOTE_NOTIFICATION_CONTEXT_ID)
def _send_vote(widget):
# widget.destroy()
self._on_stars_clicked(self._stars, app=app)
box.add_button(_("_Vote now"), _send_vote)
box.add_destroy_button(_("_Abort"))
self._nc.append(box)
def _on_stars_login_failed(self, widget, app):
"""
Entropy Web Services Login failed message.
"""
box = NotificationBox(
_("Login failed. Your <b>vote</b> hasn't been added"),
message_type=Gtk.MessageType.ERROR,
context_id=self.VOTE_NOTIFICATION_CONTEXT_ID)
box.add_destroy_button(_("_Ok, thanks"))
self._nc.append(box)
def _notify_vote_submit(self, app, username, vote):
"""
Notify User about Comment submission with current credentials.
"""
box = NotificationBox(
_("Rate <b>%s</b> as <b>%s</b>, with <b>%d</b> stars?") \
% (app.name, GObject.markup_escape_text(username),
vote,),
message_type=Gtk.MessageType.INFO,
context_id=self.VOTE_NOTIFICATION_CONTEXT_ID)
def _vote_submit(widget):
#box.destroy()
self._vote_submit(app, username, vote)
box.add_button(_("_Ok, cool!"), _vote_submit)
def _send_vote():
self._on_stars_clicked(self._stars, app=app)
def _logout_webservice(widget):
#box.destroy()
self._logout_webservice(app, _send_vote)
box.add_button(_("_No, logout!"), _logout_webservice)
box.add_destroy_button(_("_Abort"))
self._nc.append(box)
def _vote_submit(self, app, username, vote):
"""
Do the actual vote submit.
"""
task = ParallelTask(
self._vote_submit_thread_body,
app, username, vote)
task.name = "VoteSubmitThreadBody"
task.daemon = True
task.start()
def _vote_submit_thread_body(self, app, username, vote):
"""
Called by _vote_submit(), does the actualy submit.
"""
repository_id = app.get_details().channelname
webserv = self._entropy_ws.get(repository_id)
if webserv is None:
# impossible!
return
key = app.get_details().pkgkey
err_msg = None
try:
voted = webserv.add_vote(
key, vote)
except WebService.WebServiceException as err:
voted = False
err_msg = str(err)
def _submit_success():
nbox = NotificationBox(
_("Your vote has been added!"),
message_type=Gtk.MessageType.INFO,
context_id=self.VOTE_NOTIFICATION_CONTEXT_ID)
nbox.add_destroy_button(_("Ok, great!"))
self._nc.append(nbox, timeout=10)
self._on_redraw_request(None, app.get_details().pkg)
def _submit_fail(err_msg):
if err_msg is None:
box = NotificationBox(
_("You already voted this <b>Application</b>"),
message_type=Gtk.MessageType.ERROR,
context_id=self.VOTE_NOTIFICATION_CONTEXT_ID)
else:
box = NotificationBox(
_("Vote error: <i>%s</i>") % (err_msg,),
message_type=Gtk.MessageType.ERROR,
context_id=self.VOTE_NOTIFICATION_CONTEXT_ID)
box.add_destroy_button(_("Ok, thanks"))
self._nc.append(box)
if voted:
GLib.idle_add(_submit_success)
else:
GLib.idle_add(_submit_fail, err_msg)
def __application_activate(self, app):
"""
Collect data from app, then call the UI setup in the main loop.
@@ -456,19 +635,23 @@ class ApplicationViewController(GObject.Object):
def _sender(app, text):
if not app.is_webservice_available():
GLib.idle_add(self._notify_webservice_na, app)
GLib.idle_add(self._notify_webservice_na, app,
self.COMMENT_NOTIFICATION_CONTEXT_ID)
return
ws_user = app.get_webservice_username()
if ws_user is not None:
GLib.idle_add(self._notify_comment_submit, app, ws_user, text)
else:
GLib.idle_add(self._notify_login_request, app, text)
GLib.idle_add(self._notify_login_request, app, text,
self._on_comment_login_success,
self._on_comment_login_failed,
self.COMMENT_NOTIFICATION_CONTEXT_ID)
task = ParallelTask(_sender, app, text)
task.name = "AppViewSendComment"
task.start()
def _notify_webservice_na(self, app):
def _notify_webservice_na(self, app, context_id):
"""
Notify Web Service unavailability for given Application object.
"""
@@ -476,7 +659,8 @@ class ApplicationViewController(GObject.Object):
"%s: <b>%s</b>" % (
_("Entropy Web Services not available for repository"),
app.get_details().channelname),
message_type=Gtk.MessageType.ERROR)
message_type=Gtk.MessageType.ERROR,
context_id=context_id)
box.add_destroy_button(_("Ok, thanks"))
self._nc.append(box)
@@ -487,15 +671,16 @@ class ApplicationViewController(GObject.Object):
box = NotificationBox(
_("You are about to add a <b>comment</b> as <b>%s</b>.") \
% (GObject.markup_escape_text(username),),
message_type=Gtk.MessageType.INFO)
message_type=Gtk.MessageType.INFO,
context_id=self.COMMENT_NOTIFICATION_CONTEXT_ID)
def _comment_submit(widget):
box.destroy()
#box.destroy()
self._comment_submit(app, username, text)
box.add_button(_("_Ok, cool!"), _comment_submit)
def _logout_webservice(widget):
box.destroy()
#box.destroy()
self._logout_webservice(app)
box.add_button(_("_No, logout!"), _logout_webservice)
@@ -544,7 +729,8 @@ class ApplicationViewController(GObject.Object):
nbox = NotificationBox(
_("Your comment has been submitted!"),
message_type=Gtk.MessageType.INFO)
message_type=Gtk.MessageType.INFO,
context_id=self.COMMENT_NOTIFICATION_CONTEXT_ID)
nbox.add_destroy_button(_("Ok, great!"))
self._app_comment_text_buffer.set_text("")
self._nc.append(nbox, timeout=10)
@@ -552,7 +738,8 @@ class ApplicationViewController(GObject.Object):
def _submit_fail():
box = NotificationBox(
_("Comment submit error: <i>%s</i>") % (err_msg,),
message_type=Gtk.MessageType.ERROR)
message_type=Gtk.MessageType.ERROR,
context_id=self.COMMENT_NOTIFICATION_CONTEXT_ID)
box.add_destroy_button(_("Ok, thanks"))
self._nc.append(box)
@@ -561,7 +748,7 @@ class ApplicationViewController(GObject.Object):
else:
GLib.idle_add(_submit_fail)
def _logout_webservice(self, app):
def _logout_webservice(self, app, reinit_callback):
"""
Execute logout of current credentials from Web Service.
Actually, this means removing the local cookie.
@@ -571,17 +758,16 @@ class ApplicationViewController(GObject.Object):
if webserv is not None:
webserv.remove_credentials()
def _send_comment():
self._on_send_comment(None, app=app)
GLib.idle_add(_send_comment)
GLib.idle_add(reinit_callback)
def _notify_login_request(self, app, text):
def _notify_login_request(self, app, text, on_success, on_fail,
context_id):
"""
Notify User that login is required
"""
box = LoginNotificationBox(self._entropy_ws, app)
box.connect("login-success", self._on_comment_login_success)
box.connect("login-failed", self._on_comment_login_failed)
box.connect("login-success", on_success)
box.connect("login-failed", on_fail)
self._nc.append(box)
def _on_comment_login_success(self, widget, username, app):
@@ -591,9 +777,10 @@ class ApplicationViewController(GObject.Object):
box = NotificationBox(
_("Logged in as <b>%s</b>! How about your <b>comment</b>?") \
% (GObject.markup_escape_text(username),),
message_type=Gtk.MessageType.INFO)
message_type=Gtk.MessageType.INFO,
context_id=self.COMMENT_NOTIFICATION_CONTEXT_ID)
def _send_comment(widget):
box.destroy()
#box.destroy()
self._on_send_comment(widget, app=app)
box.add_button(_("_Send now"), _send_comment)
box.add_destroy_button(_("_Abort"))
@@ -605,7 +792,8 @@ class ApplicationViewController(GObject.Object):
"""
box = NotificationBox(
_("Login failed. Your <b>comment</b> hasn't been added"),
message_type=Gtk.MessageType.ERROR)
message_type=Gtk.MessageType.ERROR,
context_id=self.COMMENT_NOTIFICATION_CONTEXT_ID)
box.add_destroy_button(_("_Ok, thanks"))
self._nc.append(box)
@@ -624,33 +812,25 @@ class ApplicationViewController(GObject.Object):
label.set_markup(
_("<i>No <b>comments</b> for this Application, yet!</i>"))
self._app_comments_box.pack_start(label, False, False, 1)
label = Gtk.Label()
url = build_register_url()
url = GObject.markup_escape_text(url)
reg_msg = _("You need to <a href=\"%s\">register here</a>") % (
url,)
label.set_markup("<small>" + reg_msg + "</small>")
label.show()
self._app_comments_box.pack_start(label, False, False, 1)
return
if has_more:
button_box = Gtk.HButtonBox()
button = Gtk.Button()
button.set_label(_("Older comments"))
button.set_alignment(0.5, 0.5)
def _enqueue_download(widget):
widget.hide()
widget.get_parent().destroy()
spinner = Gtk.Spinner()
spinner.set_size_request(-1, 24)
spinner.set_size_request(24, 24)
spinner.set_tooltip_text(_("Loading older comments..."))
spinner.set_name("comment-box-spinner")
self._app_comments_box.pack_start(spinner, False, False, 3)
self._app_comments_box.pack_end(spinner, False, False, 3)
spinner.show()
downloader.enqueue_download()
button.connect("clicked", _enqueue_download)
button_box = Gtk.HButtonBox()
button_box.pack_start(button, False, False, 0)
self._app_comments_box.pack_start(button_box, False, False, 1)
button_box.show_all()
@@ -687,7 +867,7 @@ class ApplicationViewController(GObject.Object):
self._app_downloaded_lbl.set_markup(down_msg)
if icon:
self._image.set_from_pixbuf(icon)
self._stars.set_rating(stats.ratings_average - 1)
self._stars.set_rating(stats.ratings_average)
self._stars_alignment.show_all()
def _setup_application_info(self, app, metadata):
@@ -699,7 +879,15 @@ class ApplicationViewController(GObject.Object):
# FIXME, lxnay complete
# install/remove/update buttons
# for the rest, point to the remote www service
# only comments supported, point to the remote
# www service for the rest
self._app_comment_more_label.set_markup(
"<b>%s</b>: <a href=\"%s\">%s</a>" % (
_("Want to add images, etc?"),
build_application_store_url(app, "ugc"),
_("click here!"),))
stats = metadata['stats']
icon = metadata['icon']
@@ -733,16 +921,7 @@ class ApplicationViewController(GObject.Object):
self._avc = avc
self._offset = 0
self._callback = callback
self._avc.connect("application-hide", self.stop)
self._task = ParallelTask(self._download)
self._started = False
def stop(self, *args):
"""
Stop downloading comments, if we're still doing it.
"""
self._started = False
print("Application-hide called, this is", self)
def start(self):
"""
@@ -750,7 +929,6 @@ class ApplicationViewController(GObject.Object):
Loop over until we have more of them to download.
"""
self._offset = 0
self._started = True
self._task.start()
def _download_callback(self, document_list):