#!/usr/bin/python

# This is a part of the external Liferea applet for Cairo-Dock
#
# Author: Eduardo Mucelli Rezende Oliveira
# E-mail: edumucelli@gmail.com or eduardom@dcc.ufmg.br
#
# This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.

# This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#    GNU General Public License for more details.

# This applet creates an interface with Liferea feed reader.
# Directly from the applet you can show the number of unread, or new messages,
# subscribe feeds, and change the status between online, and offline.
# Through the configuration screen you can choose to show the number of unread, or new messages
# Right-click, and change the status directly from the menu
# Middle-click, enter the feed URL to be subscribed, or drag-n-drop the URL on the icon
# Left-click controls the Liferea window and it seems like a Launcher

import dbus, os, subprocess
from util import log
from CDApplet import CDApplet, _

class Applet(CDApplet):

    def __init__(self):
        
        self.liferea = None
        self.number_of_unread_msgs = 0
        self.number_of_new_msgs = 0
        self.show_number_of_unread_msgs = 0
        self.show_number_of_new_msgs = 1

        self.set_status_online_key = 1
        self.set_status_offline_key = 2

        self.dialog_active_time = 30                                                    # time in seconds that the dialog window will be active
        CDApplet.__init__(self)                                                         # call high-level init

    def connect_to_liferea(self):
        try:
            bus = dbus.SessionBus()
            liferea_object = bus.get_object('org.gnome.feed.Reader', '/org/gnome/feed/Reader')
            self.liferea = dbus.Interface(liferea_object, dbus_interface='org.gnome.feed.Reader')
        except dbus.DBusException:
            # Something more elaborated could be done here, e.g., use gobject.idle_add and using,
            # as callback, a method that would keep checking if Lirefea is open. Opted for the simpler approach
            self.icon.PopupDialog({'message':'Impossible connect to Liferea, check if it is running', 'time-length':self.dialog_active_time},{})
        return self.liferea

    def get_number_of_unread_msgs(self):
        self.number_of_unread_msgs = self.liferea.GetUnreadItems()

    def get_number_of_new_msgs(self):
        self.number_of_new_msgs = self.liferea.GetNewItems()

    def set_offline(self):
        self.liferea.SetOnline(False)
        self.set_offline_icon()

    def set_offline_icon(self):
        self.icon.SetIcon(os.path.abspath("./data/offline.png"))

    def set_online(self):
        self.liferea.SetOnline(True)
        self.set_online_icon()

    def set_online_icon(self):
        self.icon.SetIcon(os.path.abspath("./data/online.png"))

    def subscribe(self, url):
        self.liferea.Subscribe(url) 

    def switch_window_focus(self):
        if not self.icon.Get("has_focus"):                                          # liferea running, but its window has not the focus
            try:                                                                    
                self.icon.ActOnAppli("show")                                           # bring the window to the foreground
            except:                                                                 # if liferea is in the notification area, its window is actually closed, so we must re-open it
                subprocess.Popen("liferea")                                         # ... so it is necessary to recall the application
        else:
            self.icon.ActOnAppli("minimize")                                              # take the window to the background

    def show_icon_information(self):
        if self.config_info == self.show_number_of_unread_msgs:
            self.icon.SetQuickInfo(str(self.number_of_unread_msgs))
        elif self.config_info == self.show_number_of_new_msgs:
            self.icon.SetQuickInfo(str(self.number_of_new_msgs))
    
    def bind_to_liferea_window(self):
        self.icon.ControlAppli("liferea")

    def build_status_menu(self):
        status_menu = []
        index = 1
        for status in ["Online", "Offline"]:
            status_menu.append({
                'type'  : CDApplet.MENU_ENTRY,
                'label' : status,
                'menu'  : CDApplet.MAIN_MENU_ID,
                'id'    : index,
                'icon'  : os.path.abspath("./data/%s.png") % status.lower()})
            index += 1
        self.icon.AddMenuItems(status_menu)

    # CDApplet

    def begin(self):
        self.bind_to_liferea_window()
        if self.connect_to_liferea():
            self.get_number_of_unread_msgs()
            self.get_number_of_new_msgs()
            self.show_icon_information()

    def get_config(self, keyfile):
        self.config_info = keyfile.getint('Configuration', 'icon_info')                 # get the source of quotations

    def reload(self):
        self.show_icon_information()

    # Callbacks

    def on_click(self, param):
        if self.liferea:
            self.switch_window_focus()

    # Probably the user read something when he focus Liferea, therefore,
    # it is useful to check again and refresh the number of unread, and new items
    # I will avoid polling to keep checking this variables
    def on_change_focus(self, has_focus):
        self.get_number_of_unread_msgs()
        self.get_number_of_new_msgs()
        self.show_icon_information()

    def on_drop_data(self, text):
        self.subscribe(text)

    def on_middle_click(self):
        self.icon.PopupDialog ({'message':'Enter the feed URL', 'buttons':'ok;cancel'}, {'widget-type':'text-entry'})

    def on_answer_dialog(self, key, content):
        if (key == 0 or key == -1) and content:                                         # Ok or Enter
            self.subscribe(content)

    def on_build_menu(self):
        self.build_status_menu()

    def on_menu_select(self, selected_menu):
        if selected_menu == self.set_status_online_key:
            self.set_online()
        elif selected_menu == self.set_status_offline_key:
            self.set_offline()
    
if __name__ == '__main__':
    Applet().run()
