コード例 #1
0
ファイル: adddialog.py プロジェクト: GNOME/billreminder
    def _populate_category(self, categoryname=None):
        """ Populates combobox with existing categories """
        # Connects to the database
        actions = Actions()

        # List of categories from database
        categories = []
        records = actions.get_categories()

        ret = 0
        empty_color = create_pixbuf()
        for rec in records:
            #if [rec['categoryname'], rec['id']] not in categories:
            #TODO: Better put color creation in a function
            color = rec.color and rec.color or '#000'

            categories.append([create_pixbuf(color=color), rec.name, int(rec.id)])
            if categoryname and categoryname == rec.name:
                ret = len(categories) + 1

        store = gtk.ListStore(gtk.gdk.Pixbuf, str, int)

        self.category.set_model(store)
        store.append([empty_color, _("None"), 0])
        store.append([None, "---", -1])

        for category in categories:
            store.append(category)
        store.append([None, "---", -1])
        store.append([empty_color, _("New Category"), -2])
        self.category.set_active(ret)

        return ret
コード例 #2
0
    def _populate_widgets_with_record(self):
        # Format the amount field
        if self.currentrecord.amount:
            self.amount.set_text(
                utils.float_to_currency(self.currentrecord.amount))
        else:
            self.amount.set_text("")
        # Format the dueDate field
        dt = self.currentrecord.dueDate
        self.dueDate.set_date(dt)
        utils.select_combo_text(self.payee, self.currentrecord.payee)

        if self.currentrecord.category:
            actions = Actions()
            cat_name = self.currentrecord.category.name
            records = actions.get_categories(name=cat_name)
            if records:
                categoryname = records[0].name
                utils.select_combo_text(self.category, categoryname, 1)
        else:
            self.category.set_active(0)

        if self.currentrecord.notes:
            self.txtbuffer.set_text(self.currentrecord.notes)
        #self.chkPaid.set_active(self.currentrecord.Paid)

        if self.currentrecord.alarmDate:
            self.alarmbutton.set_date(self.currentrecord.alarmDate)
コード例 #3
0
ファイル: adddialog.py プロジェクト: GNOME/billreminder
    def _populate_widgets_with_record(self):
        # Format the amount field
        if self.currentrecord.amount:
            self.amount.set_text(utils.float_to_currency(self.currentrecord.amount))
        else:
            self.amount.set_text("")
        # Format the dueDate field
        dt = self.currentrecord.dueDate
        self.dueDate.set_date(dt)
        utils.select_combo_text(self.payee, self.currentrecord.payee)

        if self.currentrecord.category:
            actions = Actions()
            cat_name = self.currentrecord.category.name
            records = actions.get_categories(name=cat_name)
            if records:
                categoryname = records[0].name
                utils.select_combo_text(self.category, categoryname, 1)
        else:
            self.category.set_active(0)

        if self.currentrecord.notes:
            self.txtbuffer.set_text(self.currentrecord.notes)
        #self.chkPaid.set_active(self.currentrecord.Paid)

        if self.currentrecord.alarmDate:
            self.alarmbutton.set_date(self.currentrecord.alarmDate)
コード例 #4
0
    def _populate_category(self, categoryname=None):
        """ Populates combobox with existing categories """
        # Connects to the database
        actions = Actions()

        # List of categories from database
        categories = []
        records = actions.get_categories()

        ret = 0
        empty_color = create_pixbuf()
        for rec in records:
            #if [rec['categoryname'], rec['id']] not in categories:
            #TODO: Better put color creation in a function
            color = rec.color and rec.color or '#000'

            categories.append(
                [create_pixbuf(color=color), rec.name,
                 int(rec.id)])
            if categoryname and categoryname == rec.name:
                ret = len(categories) + 1

        store = gtk.ListStore(gtk.gdk.Pixbuf, str, int)

        self.category.set_model(store)
        store.append([empty_color, _("None"), 0])
        store.append([None, "---", -1])

        for category in categories:
            store.append(category)
        store.append([None, "---", -1])
        store.append([empty_color, _("New Category"), -2])
        self.category.set_active(ret)

        return ret
コード例 #5
0
    def __init__(self, parent=None, new=False):
        gtk.Dialog.__init__(self, title=_("Categories Manager"),
                            parent=parent, flags=gtk.DIALOG_MODAL)

        self.closebutton = self.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)
        self.okbutton = self.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
        self.set_icon_from_file(common.APP_ICON)

        self.new = new

        if parent:
            self.set_transient_for(parent)
            self.set_position(gtk.WIN_POS_CENTER_ON_PARENT)

        self.currentrecord = None

        # Set up the UI
        self._initialize_dialog_widgets()
        self._connect_fields()
        #self._populate_fields()
        self.actions = Actions()
        self._populateTreeView(self.actions.get_categories())

        if new:
            self._on_newbutton_clicked(None)
            self.topcontainer.get_label_widget().set_markup("<b>%s</b>" \
                                                     % _("New Category"))
            self.okbutton.set_label(gtk.STOCK_SAVE)
            self.closebutton.set_label(gtk.STOCK_CANCEL)

        else:
            index = parent.category.get_active()-2
            if index >= 0:
                self.list.set_cursor((index,))
コード例 #6
0
    def _get_category(self):
        """ Extracts information typed into comboboxentry """

        actions = Actions()

        if self.category.get_active_iter() is not None:
            model = self.category.get_model()
            iteration = self.category.get_active_iter()
            if iteration:
                name = model.get_value(iteration, 1)
        else:
            name = None

        if not name or name == _("None"):
            return None

        records = actions.get_categories(name=name)
        if records:
            return records[0]
        else:
            return None
コード例 #7
0
ファイル: adddialog.py プロジェクト: GNOME/billreminder
    def _get_category(self):
        """ Extracts information typed into comboboxentry """

        actions = Actions()

        if self.category.get_active_iter() is not None:
            model = self.category.get_model()
            iteration = self.category.get_active_iter()
            if iteration:
                name = model.get_value(iteration, 1)
        else:
            name = None

        if not name or name == _("None"):
            return None

        records = actions.get_categories(name=name)
        if records:
            return records[0]
        else:
            return None
コード例 #8
0
    def _populate_payee(self):
        """ Populates combobox with existing payees """
        # Connects to the database
        actions = Actions()

        # List of payees from database
        payees = []
        records = actions.get_bills()
        for rec in records:
            if rec.payee not in payees:
                payees.append(rec.payee)

        store = gtk.ListStore(gobject.TYPE_STRING)
        for payee in payees:
            store.append([payee])

        self.payee.set_model(store)
        self.payeecompletion.set_model(store)
        self.payee.set_text_column(0)
        self.payeecompletion.set_text_column(0)
        self.payeeEntry = self.payee.child
        self.selectedText = ''
コード例 #9
0
ファイル: adddialog.py プロジェクト: GNOME/billreminder
    def _populate_payee(self):
        """ Populates combobox with existing payees """
        # Connects to the database
        actions = Actions()

        # List of payees from database
        payees = []
        records = actions.get_bills()
        for rec in records:
            if rec.payee not in payees:
                payees.append(rec.payee)

        store = gtk.ListStore(gobject.TYPE_STRING)
        for payee in payees:
            store.append([payee])

        self.payee.set_model(store)
        self.payeecompletion.set_model(store)
        self.payee.set_text_column(0)
        self.payeecompletion.set_text_column(0)
        self.payeeEntry = self.payee.child
        self.selectedText = ''
コード例 #10
0
    def __init__(self, options):

        # Verify if Lock File exist and if there is another instance running
        if not lock():
            lockfd = open(common.DAEMON_LOCK_FILE, 'r')
            lockpid = int(lockfd.readline())
            lockfd.close()
            if verify_pid(lockpid):
                print _('Lock File found:' \
                        ' You have another instance running. (pid=%d)') % \
                        lockpid
                raise SystemExit
            else:
                print _('Lock File found: ' \
                        'Possibly the program was exited unexpectedly.')
                try:
                    print _('Removing Lock File...')
                    os.remove(common.DAEMON_LOCK_FILE)
                    print _('Successfully.')
                except OSError:
                    print _('Failed.')

        # Verify if there is another Billreminder-Daemon DBus Service
        if verify_service(common.DBUS_INTERFACE):
            print _('BillReminder Notifier is already running.')
            raise SystemExit

        Daemon.__init__(self, options)

        self.client_pid = None

        self.actions = Actions()
        self.dbus_server = Server(self)
        if options.app_opengui:
            gui = Popen('billreminder', shell=True)
            self.client_pid = gui.pid
        self.alarm = Alarm(self)

        # Create the mainloop
        self.mainloop = gobject.MainLoop()
        self.mainloop.run()
コード例 #11
0
    def __init__(self):
        gobject.GObject.__init__(self)

        if exists(join(USER_CFG_PATH, CFG_NAME)):
            from lib.migrate_to_gconf import migrate

            migrate(join(USER_CFG_PATH, CFG_NAME))

        self.gconf_client = Configuration()
        self.message = Message()
        # Connects to the database
        self.actions = Actions()

        self.ui = gtk.Builder()
        self.ui.add_from_file(os.path.join(DEFAULT_CFG_PATH, "main.ui"))

        self.window = self.ui.get_object("main_window")
        self.window.set_title("%s" % common.APPNAME)
        self.window.set_icon_from_file(common.APP_ICON)

        # ViewBill
        self.list = ViewBill()
        self.list.connect("cursor_changed", self._on_list_cursor_changed)
        self.list.connect("row_activated", self._on_list_row_activated)
        self.list.connect("button_press_event", self._on_list_button_press_event)

        self.ui.get_object("bill_box").add(self.list)

        # Toolbar
        self.toolbar = self.ui.get_object("toolbar")

        # Menubar
        self._populate_menubar()

        # Statusbar
        self.statusbar = Statusbar()
        self.ui.get_object("statusbar_box").add(self.statusbar)

        # Restore timeline zoom
        timeline_count = self.gconf_client.get("timeline_count")

        # Timeline
        self.timeline = Timeline(count=timeline_count, callback=self.on_timeline_cb)
        self.timeline.connect("range-changed", self._on_timeline_changed)
        self.timeline.connect("button-press-event", self._on_timeline_click)
        self.timeline.connect("cleared", self._on_timeline_cleared)
        self.ui.get_object("timeline_box").add(self.timeline)

        # Chart
        self.chart = ChartWidget()
        self.chart.set_border_width(10)
        self.ui.get_object("chart_box").add(self.chart)

        # Restore position and size of window
        width = self.gconf_client.get("window_width")
        height = self.gconf_client.get("window_height")
        x = self.gconf_client.get("window_position_x")
        y = self.gconf_client.get("window_position_y")
        if width and height:
            self.window.resize(width, height)
        if x and y:
            self.window.move(x, y)

        self.window.show_all()

        # Whether to display toolbar or not
        self.on_showToolbar_toggled(self.ui.get_object("showToolbar"))
        self.list.grab_focus()

        if self.gconf_client.get("start_in_tray"):
            self.window.hide()

        self.toggle_buttons()

        # Connects to the Daemon
        self.iface = None
        iface = get_dbus_interface(common.DBUS_INTERFACE, common.DBUS_PATH)
        if iface:
            iface.connect_to_signal("bill_edited", self.reloadTreeView)
            iface.connect_to_signal("bill_edited", self.reloadTimeline)
            iface.connect_to_signal("show_main_window", self.window.show)
            self.iface = iface
            gobject.timeout_add(2000, self._send_tray_hints)

        self.set_action_strings()
        self.ui.connect_signals(self)

        # populate treeview
        self.reloadTreeView()
        self.notify = NotifyIcon(self)

        # Integrate with Ubuntu Unity
        if UNITY:
            self.unity = UnityIntegration(self)
コード例 #12
0
class MainDialog(gobject.GObject):
    search_text = ""
    _bullet_cache = {}

    __gsignals__ = {
        "bill-added": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)),
        "bill-updated": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)),
        "bill-removed": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)),
    }

    def __init__(self):
        gobject.GObject.__init__(self)

        if exists(join(USER_CFG_PATH, CFG_NAME)):
            from lib.migrate_to_gconf import migrate

            migrate(join(USER_CFG_PATH, CFG_NAME))

        self.gconf_client = Configuration()
        self.message = Message()
        # Connects to the database
        self.actions = Actions()

        self.ui = gtk.Builder()
        self.ui.add_from_file(os.path.join(DEFAULT_CFG_PATH, "main.ui"))

        self.window = self.ui.get_object("main_window")
        self.window.set_title("%s" % common.APPNAME)
        self.window.set_icon_from_file(common.APP_ICON)

        # ViewBill
        self.list = ViewBill()
        self.list.connect("cursor_changed", self._on_list_cursor_changed)
        self.list.connect("row_activated", self._on_list_row_activated)
        self.list.connect("button_press_event", self._on_list_button_press_event)

        self.ui.get_object("bill_box").add(self.list)

        # Toolbar
        self.toolbar = self.ui.get_object("toolbar")

        # Menubar
        self._populate_menubar()

        # Statusbar
        self.statusbar = Statusbar()
        self.ui.get_object("statusbar_box").add(self.statusbar)

        # Restore timeline zoom
        timeline_count = self.gconf_client.get("timeline_count")

        # Timeline
        self.timeline = Timeline(count=timeline_count, callback=self.on_timeline_cb)
        self.timeline.connect("range-changed", self._on_timeline_changed)
        self.timeline.connect("button-press-event", self._on_timeline_click)
        self.timeline.connect("cleared", self._on_timeline_cleared)
        self.ui.get_object("timeline_box").add(self.timeline)

        # Chart
        self.chart = ChartWidget()
        self.chart.set_border_width(10)
        self.ui.get_object("chart_box").add(self.chart)

        # Restore position and size of window
        width = self.gconf_client.get("window_width")
        height = self.gconf_client.get("window_height")
        x = self.gconf_client.get("window_position_x")
        y = self.gconf_client.get("window_position_y")
        if width and height:
            self.window.resize(width, height)
        if x and y:
            self.window.move(x, y)

        self.window.show_all()

        # Whether to display toolbar or not
        self.on_showToolbar_toggled(self.ui.get_object("showToolbar"))
        self.list.grab_focus()

        if self.gconf_client.get("start_in_tray"):
            self.window.hide()

        self.toggle_buttons()

        # Connects to the Daemon
        self.iface = None
        iface = get_dbus_interface(common.DBUS_INTERFACE, common.DBUS_PATH)
        if iface:
            iface.connect_to_signal("bill_edited", self.reloadTreeView)
            iface.connect_to_signal("bill_edited", self.reloadTimeline)
            iface.connect_to_signal("show_main_window", self.window.show)
            self.iface = iface
            gobject.timeout_add(2000, self._send_tray_hints)

        self.set_action_strings()
        self.ui.connect_signals(self)

        # populate treeview
        self.reloadTreeView()
        self.notify = NotifyIcon(self)

        # Integrate with Ubuntu Unity
        if UNITY:
            self.unity = UnityIntegration(self)

    def set_action_strings(self):
        # for some reason the actions strings do not get translated yet
        # so we define them here so they would be picked up by the pyfile scanner
        self.ui.get_object("newBill").set_label(_("_New"))
        self.ui.get_object("newBill").set_tooltip(_("Add new bill"))

        self.ui.get_object("editBill").set_label(_("_Edit"))
        self.ui.get_object("editBill").set_tooltip(_("Edit a bill"))

        self.ui.get_object("removeBill").set_label(_("_Delete"))
        self.ui.get_object("removeBill").set_tooltip(_("Delete selected bill"))

        self.ui.get_object("markPaid").set_label(_("P_aid"))
        self.ui.get_object("markPaid").set_tooltip(_("Mark as paid"))

        self.ui.get_object("markNotPaid").set_label(_("No_t Paid"))
        self.ui.get_object("markNotPaid").set_tooltip(_("Mark as not paid"))

        self.ui.get_object("showToolbar").set_label(_("_Show Toolbar"))
        self.ui.get_object("showToolbar").set_tooltip(_("Show the toolbar"))

    # Methods:  UI
    def _send_tray_hints(self):
        self.iface.set_tray_hints(force_string(self.notify.get_hints()))
        gobject.timeout_add(60000, self._send_tray_hints)

    def get_window_visibility(self):
        return self.window.get_property("visible")

    def show_hide_window(self):
        if self.window.get_property("visible"):
            self.window.hide()
        else:
            self.window.show()

    def get_selected_record(self):
        """ Returns a bill object from the current selected record """
        if len(self.list.listStore) > 0:
            model_ = self.list.get_model()
            if self.list.get_cursor()[0]:
                index = self.list.get_cursor()[0][0]
            else:
                index = 0

            b_id = model_[index][0]

            records = self.actions.get_bills(id=b_id)
            self.currentrecord = records[0]

        else:
            self.currentrecord = None
        print "Current record is: %s" % self.currentrecord

    def populate_view(self, records):
        """ Populates the treeview control with the records passed """

        # Reset list
        self.list.listStore.clear()

        if not records:
            return 0

        # Loops through bills collection
        path = 0
        for rec in records:
            # Format the record prior to adding it to treeview
            row = self.format_row(rec)
            self.list.add(row)

        # Set the cursor to the first (top) record
        self.list.set_cursor(path)

        # Returns how many records there are in the treeview
        return len(records)

    def reloadTreeView(self, *arg):
        # Update list with updated record
        status = self.gconf_client.get("show_paid_bills")

        path = self.list.get_cursor()[0]
        self.list.listStore.clear()
        self.currentrecord = None

        first = self.timeline.start_date
        last = self.timeline.end_date
        # Get list of records
        records = self.actions.get_interval_bills(first, last, status)

        # Populate treeview
        self.populate_view(records)
        # Update status bar
        self.update_statusbar()
        # populate chart
        self._populate_chart(status, first, last)

        return len(records)

    def format_row(self, row):
        """ Formats a bill to be displayed as a row. """

        categoryName = row.category.name if row.category else _("None")
        categoryColor = row.category.color if row.category else "#d3d7cf"
        formatted = [
            row.id,
            create_pixbuf(color=categoryColor),
            categoryName,
            row.payee,
            row.dueDate.strftime(_("%m/%d").encode("ASCII")),
            row.amount,
            row.notes,
            int(row.paid),
            None,
        ]

        return formatted

    def _populate_chart(self, status, start, end):

        records = []
        categories = []
        totals = []

        records = self.actions.get_monthly_totals(start, end, status)
        # Chart widget takes data in format (('CategoryName', amount),)
        categories = [cat or "None" for cat, total in records]
        totals = [float(total) for cat, total in records]
        # records = [(c if c else 'None',float(t)) for c,t in records]

        # set bar colors
        all_categories = self.actions.get_categories()
        self.chart.chart.key_colors = dict([(cat.name or "None", cat.color) for cat in all_categories])

        self.chart.plot(categories, totals)

    def _populate_menubar(self):
        try:
            saved_view = self.gconf_client.get("show_paid_bills")
        except:
            saved_view = 1
            self.gconf_client.set("show_paid_bills", saved_view)

        if saved_view == 0:
            self.ui.get_object("showNotPaid").set_active(True)
        elif saved_view == 1:
            self.ui.get_object("showPaid").set_active(True)
        else:
            self.ui.get_object("showAll").set_active(True)

        # Check whether we display the toolbar or not
        self.ui.get_object("showToolbar").set_active(self.gconf_client.get("show_toolbar"))

    def add_bill(self):
        selectedDate = self.timeline.value
        records = dialogs.add_dialog(parent=self.window, selectedDate=selectedDate)

        # Checks if the user did not cancel the action
        if records:
            # Add new bill to database
            for rec in records:
                bill_id = self.actions.add(rec)
                bill = self.actions.get_bills(id=bill_id)[0]
                if bill:
                    self.list.add(self.format_row(bill))
            self.update_statusbar()
            # Reload records tree (something changed)
            self.reloadTreeView()
            self.reloadTimeline()

    def edit_bill(self):
        records = dialogs.edit_dialog(parent=self.window, record=self.currentrecord)

        # Checks if the user did not cancel the action
        if records:
            for rec in records:
                # Edit bill to database
                rec = self.actions.edit(rec)
                self.emit("bill-updated", rec)

            # Reload records tree (something changed)
            self.reloadTreeView()
            self.reloadTimeline()

    def remove_bill(self):
        self.actions.delete(self.currentrecord)
        self.list.remove()
        self.emit("bill-removed", None)
        self.update_statusbar()
        self.reloadTreeView()
        self.reloadTimeline()

    def toggle_bill_paid(self):
        # Fetch record from database
        record = self.actions.get_bills(id=self.currentrecord.id)[0]
        # Toggle paid field
        record.paid = False if record.paid else True

        # Edit bill in the database
        transaction = self.actions.add(record)

        self.emit("bill-updated", record)

        # Update our current copy
        self.currentrecord = self.actions.get_bills(id=self.currentrecord.id)[0]
        # Update timeline widget to reflect change
        self._bullet_cache[self.currentrecord.dueDate] = [self.currentrecord]
        # Update list with updated record
        idx = self.list.get_cursor()[0][0]
        self.update_statusbar(idx)
        self.reloadTreeView()
        self.reloadTimeline()

    def about(self):
        dialogs.about_dialog(parent=self.window)

    def preferences(self):
        dialogs.preferences_dialog(parent=self.window)

    # Methods
    def _quit_application(self):
        self.save_position()
        self.save_size()
        self.save_timeline_zoom()
        gtk.main_quit()
        return False

    def save_position(self):
        x, y = self.window.get_position()
        self.gconf_client.set("window_position_x", x)
        self.gconf_client.set("window_position_y", y)

    def save_size(self):
        width, height = self.window.get_size()
        self.gconf_client.set("window_width", width)
        self.gconf_client.set("window_height", height)

    def save_timeline_zoom(self):
        count = self.timeline.count
        self.gconf_client.set("timeline_count", count)

    def toggle_buttons(self, paid=None):
        """ Toggles all buttons conform number of records present and
            their state """

        for widget in ["editBill", "removeBill", "markPaid", "markNotPaid"]:
            self.ui.get_object(widget).set_sensitive(len(self.list.listStore) > 0)

        if len(self.list.listStore) > 0:
            self.ui.get_object("markPaid").set_sensitive(paid == False)
            self.ui.get_object("markNotPaid").set_sensitive(paid == True)

    def update_statusbar(self, index=0):
        """ This function is used to update status bar informations
            about the list """
        records = len(self.list.listStore)

        # Record count
        self.statusbar.Records(records)
        if self.currentrecord:
            # Display the status
            self.statusbar.Notes(self.currentrecord.notes)
            # Toggles toolbar buttons on/off
            self.toggle_buttons(self.currentrecord.paid)
        else:
            # Clear the status for the selected row
            self.statusbar.Notes("")
            # Toggles toolbar buttons on/off
            self.toggle_buttons()

        show_paid_bills = self.gconf_client.get("show_paid_bills")
        if show_paid_bills is 0:
            self.statusbar.Info(_("Not Paid Only"))
        elif show_paid_bills is 1:
            self.statusbar.Info(_("Paid Only"))
        else:
            self.statusbar.Info("")

    # Event handlers
    def _on_list_button_press_event(self, widget, event):
        """ This function will handle the signal to show a popup menu
            sent by a right click on tvBill widget. """
        if event.button == 3 and event.type == gtk.gdk.BUTTON_PRESS:
            self.get_selected_record()

            c = self.ui.get_object("context_menu")
            c.popup(None, None, None, event.button, event.get_time())

    def _on_list_row_activated(self, widget, path, column):
        self._on_list_cursor_changed(widget)
        self.on_editBill_activate(None)

    def _on_list_cursor_changed(self, widget):
        # Get currently selected bill
        self.get_selected_record()
        # Update statusbar
        self.update_statusbar()

    def on_newBill_activate(self, toolbutton):
        self.add_bill()

    def on_editBill_activate(self, toolbutton):
        if self.currentrecord:
            self.edit_bill()

    def on_removeBill_activate(self, toolbutton):
        if self.currentrecord:
            resp = self.message.ShowQuestionYesNo(
                _('Do you really want to delete "%s"?') % self.currentrecord.payee, self.window, _("Confirmation")
            )
            if resp:
                self.remove_bill()

    def on_markNotPaid_activate(self, toolbutton):
        self.on_markPaid_activate(toolbutton)  # forward

    def on_markPaid_activate(self, toolbutton):
        if self.currentrecord:
            self.toggle_bill_paid()

    def on_btnAbout_activate(self, toolbutton):
        self.about()

    def on_btnPrefs_activate(self, toolbutton):
        self.preferences()

    def on_btnQuit_activate(self, toolbutton):
        self._quit_application()

    def on_delete_event(self, widget, event, data=None):
        self._quit_application()

    def _on_timeline_changed(self, widget, args):
        self.reloadTreeView()

    def _on_timeline_cleared(self, widget, args):
        self._bullet_cache = {}

    def _on_timeline_click(self, widget, event):
        if event.button == 1 and event.type == gtk.gdk._2BUTTON_PRESS:
            self.add_bill()

    def switch_view(self, view_number):
        self.gconf_client.set("show_paid_bills", view_number)
        self.reloadTreeView()
        self.reloadTimeline()

    def on_showNotPaid_toggled(self, action):
        if action.get_active():
            self.switch_view(0)

    def on_showPaid_toggled(self, action):
        if action.get_active():
            self.switch_view(1)

    def on_showAll_toggled(self, action):
        if action.get_active():
            self.switch_view(2)

    def on_showToolbar_toggled(self, action):
        # Toggle toolbar's visibility
        if action.get_active():
            self.toolbar.show_all()
        else:
            self.toolbar.hide_all()

        self.gconf_client.set("show_toolbar", action.get_active())

    def reloadTimeline(self, *args):
        self._bullet_cache = {}
        self.timeline.refresh()

    def on_timeline_cb(self, date, display_type, force=False):
        # TODO: Improve tooltip
        # TODO: Improve cache

        if date in self._bullet_cache.keys() and not force:
            return None

        self._bullet_cache[date] = self.actions.get_bills(dueDate=date)
        if self._bullet_cache[date]:
            status = self.gconf_client.get("show_paid_bills")
            amount = 0
            amount_not_paid = 0
            tooltip = ""
            bullet = Event()
            bullet.date = date

            for bill in self._bullet_cache[date]:
                amount += bill.amount
                if tooltip:
                    tooltip += "\n"
                tooltip += bill.payee + " (" + str(float_to_currency(bill.amount)) + ")"

                if bill.paid:
                    tooltip += " [%s]" % _("Paid")

                    if status == 0:
                        return False
                    bullet.status = bullet.status | bullet.PAID
                else:
                    amount_not_paid += bill.amount
                    if date <= datetime.date.today():
                        if status == 1:
                            return False
                        bullet.status = bullet.status | bullet.OVERDUE
                    else:
                        if status == 1:
                            return False
                        bullet.status = bullet.status | bullet.TO_BE_PAID

                if bill.notes:
                    tooltip += " - " + bill.notes

            bullet.amountdue = amount_not_paid if amount_not_paid else amount
            bullet.payee = bill.payee

            bills = len(self._bullet_cache[date])
            if bills > 1:
                bullet.multi = bills
                bullet.payee = "%d bills" % bills
            bullet.tooltip = tooltip
            return bullet

        return None
コード例 #13
0
ファイル: iug.py プロジェクト: avelino/iug
    def __init__(self):
        self.gui = GTKWrappers()
        self.actions = Actions()
        
        # setup a default icon
        self.icons = gtk.icon_theme_get_default()
        self.current_category_id = 0
        
        self.gui.get_glade(MAIN_GLADE, 'window_main')
        #Main widget
        self.window_main = self.gui.get_widget('window_main')
        self.window_main.set_icon(load_pixbuf_image('iug')[0])
    
        # Sexy search entry
        self.search_hbox = self.gui.get_widget('search_hbox')
        self.search_entry = SearchEntry(self.icons)
        self.search_hbox.add(self.search_entry)
        self.search_entry.show()
        
        #creates the GamesListView to view a list of games
        self.scrolled_window = self.gui.get_widget('scrolled_window')
        self.treeview_games = GamesListView()
        self.scrolled_window.add(self.treeview_games)
        self.treeview_games.show()
        
        #create the description listview to show games info.
        self.scrolled_description = self.gui.get_widget('scrolled_description')
        self.treeview_description = DescriptionTreeView()
        self.scrolled_description.add(self.treeview_description)
        self.treeview_description.show()
        
        #Application menu
        self.menu_download = self.gui.get_widget('menu_download')
        self.menu_download.set_sensitive(False)
        self.menu_viewsite = self.gui.get_widget('menu_viewsite')
        self.menu_viewsite.set_sensitive(False)
        self.menu_quit = self.gui.get_widget('menu_quit')
        self.menu_preferences = self.gui.get_widget('menu_preferences')
        self.menu_fullscreen = self.gui.get_widget('menu_fullscreen')
        self.menu_fullscreen.set_sensitive(False)
        self.menu_reportbug = self.gui.get_widget('menu_reportbug')
        self.menu_about = self.gui.get_widget('menu_about')

        #Application buttons
        self.button_close = self.gui.get_widget('button_close')
        self.button_download = self.gui.get_widget('button_download')
        self.button_zoom = self.gui.get_widget("button_zoom")
        self.menu_viewsite.set_sensitive(False)
        self.button_download.set_sensitive(False)
        self.menu_download.set_sensitive(False)
        self.button_zoom.set_sensitive(False)
        
        # image widget to show the game screenshot
        self.image_game = self.gui.get_widget('image_game')
        # create the category treeview
        self.treeview_categories = self.gui.get_widget('treeview_categories')
        renderer_cat_name = gtk.CellRendererText()
        renderer_cat_name.set_property('scale', 1.0)
        column_cat = gtk.TreeViewColumn(MSG_000001,renderer_cat_name)
        column_cat.add_attribute(renderer_cat_name, 'markup', COL_CAT_NAME)
        self.treeview_categories.append_column(column_cat)
        self.treeview_categories.set_search_column(COL_CAT_NAME)
        self.category_selection = self.treeview_categories.get_selection()
        self.category_selection.set_mode(gtk.SELECTION_SINGLE)
        
        self.window_main.show()
        self.connect_events()
        
        self.check_version()
        
        self.fill_category()
        
        self.search_entry.grab_focus()
コード例 #14
0
ファイル: iug.py プロジェクト: avelino/iug
class IUG():
    
    def __init__(self):
        self.gui = GTKWrappers()
        self.actions = Actions()
        
        # setup a default icon
        self.icons = gtk.icon_theme_get_default()
        self.current_category_id = 0
        
        self.gui.get_glade(MAIN_GLADE, 'window_main')
        #Main widget
        self.window_main = self.gui.get_widget('window_main')
        self.window_main.set_icon(load_pixbuf_image('iug')[0])
    
        # Sexy search entry
        self.search_hbox = self.gui.get_widget('search_hbox')
        self.search_entry = SearchEntry(self.icons)
        self.search_hbox.add(self.search_entry)
        self.search_entry.show()
        
        #creates the GamesListView to view a list of games
        self.scrolled_window = self.gui.get_widget('scrolled_window')
        self.treeview_games = GamesListView()
        self.scrolled_window.add(self.treeview_games)
        self.treeview_games.show()
        
        #create the description listview to show games info.
        self.scrolled_description = self.gui.get_widget('scrolled_description')
        self.treeview_description = DescriptionTreeView()
        self.scrolled_description.add(self.treeview_description)
        self.treeview_description.show()
        
        #Application menu
        self.menu_download = self.gui.get_widget('menu_download')
        self.menu_download.set_sensitive(False)
        self.menu_viewsite = self.gui.get_widget('menu_viewsite')
        self.menu_viewsite.set_sensitive(False)
        self.menu_quit = self.gui.get_widget('menu_quit')
        self.menu_preferences = self.gui.get_widget('menu_preferences')
        self.menu_fullscreen = self.gui.get_widget('menu_fullscreen')
        self.menu_fullscreen.set_sensitive(False)
        self.menu_reportbug = self.gui.get_widget('menu_reportbug')
        self.menu_about = self.gui.get_widget('menu_about')

        #Application buttons
        self.button_close = self.gui.get_widget('button_close')
        self.button_download = self.gui.get_widget('button_download')
        self.button_zoom = self.gui.get_widget("button_zoom")
        self.menu_viewsite.set_sensitive(False)
        self.button_download.set_sensitive(False)
        self.menu_download.set_sensitive(False)
        self.button_zoom.set_sensitive(False)
        
        # image widget to show the game screenshot
        self.image_game = self.gui.get_widget('image_game')
        # create the category treeview
        self.treeview_categories = self.gui.get_widget('treeview_categories')
        renderer_cat_name = gtk.CellRendererText()
        renderer_cat_name.set_property('scale', 1.0)
        column_cat = gtk.TreeViewColumn(MSG_000001,renderer_cat_name)
        column_cat.add_attribute(renderer_cat_name, 'markup', COL_CAT_NAME)
        self.treeview_categories.append_column(column_cat)
        self.treeview_categories.set_search_column(COL_CAT_NAME)
        self.category_selection = self.treeview_categories.get_selection()
        self.category_selection.set_mode(gtk.SELECTION_SINGLE)
        
        self.window_main.show()
        self.connect_events()
        
        self.check_version()
        
        self.fill_category()
        
        self.search_entry.grab_focus()
        
    def connect_events(self):
        # Make things responsible
        self.gui.connect(self.button_zoom,'clicked', self.on_zoom)
        self.gui.connect(self.menu_fullscreen,'activate', self.on_zoom)
        self.gui.connect(self.menu_viewsite,'activate', self.on_menu_viewsite)
        self.gui.connect(self.window_main, 'delete-event', gtk.main_quit)
        self.gui.connect(self.window_main, 'destroy', gtk.main_quit)
        self.gui.connect(self.menu_quit, 'activate', gtk.main_quit)
        self.gui.connect(self.treeview_games,"game-selected", self.on_treeview_games_selected)
        self.gui.connect(self.category_selection,'changed', self.on_treeview_categories_changed)
        self.gui.connect(self.button_download, 'clicked', self.on_button_download)
        self.gui.connect(self.menu_download, 'activate', self.on_button_download)
        self.gui.connect(self.menu_reportbug, 'activate', self.on_menu_reportbug)
        self.gui.connect(self.menu_about, 'activate', self.on_menu_about)
        self.search_entry.connect("terms-changed", self.on_search)
    
    def download_images(self, categoryid):
        need_download = []
        cat = self.actions.get_games({'category':categoryid})
        if cat:
            for n in cat:
                if load_pixbuf_image(n['image_file'])[1]:
                    need_download.append(n)
        if len(need_download)>0:
            dialog = ProgressDialog(self.window_main ,'') 
            dialog.connect("download-failed", self._fileDownloadFailed)
            
            # Download queue
            downloadItems = set()
            for n in need_download:
                    downloadItems.add(DownloadItem('%s image' % n['game'], n['image_url'], os.path.join(CONFIG_DIR, n['image_file'])))
                    
            # Try to download all items
            #response = dialog.download(downloadItems)
            dialog.message('Downloading Games images...')
            response = dialog.download(downloadItems)

            # Destroy wizard
            dialog.destroy()

            # Abort installation if user pressed cancel during the download
            #if response == gtk.RESPONSE_ACCEPT:
            self.window_main.set_sensitive(True) 
             
    def on_search(self, widget, search_string):
        print 'on_search' 
        self.gui.setBusy(self.window_main, True)
        search_terms = search_string.lower()
        model = self.treeview_games.get_model()
        if search_terms != None:
            for it in lib.utils.iterate_list_store(model, model.get_iter_first()):
                aname = model.get_value(it, COL_ITEM).lower()
                if search_terms in aname.split(' '):
                    print "selecting: %s (%s)" % (search_terms, model.get_path(it))
                    self.treeview_games.set_cursor(model.get_path(it))
                    self.gui.setBusy(self.window_main, False)
                    return
        elif len(model) > 0:
            self.treeview_games.set_cursor(0)
        self.gui.setBusy(self.window_main, False)
        
    def on_menu_viewsite(self,widget):
    	game = self.treeview_games.get_selected_game()
    	website = game.website
    	lib.utils.url_open(website)
    
    def on_menu_reportbug(self,widget):
        lib.utils.url_open('https://bugs.edge.launchpad.net/iug/+filebug')

    def on_menu_about(self,widget):
    	dialog = ui.aboutdialog.AboutDialog()
    
    def check_version(self):
        version = IUGVersionChecker()
        if not version.check_version(self.actions):
            dlg = CacheDialog(self.window_main)
            title = MSG_000002
            dlg.set_title(title)
            
            result = dlg.run()
            dlg.destroy()
            if result == gtk.RESPONSE_YES :
                dialog = DownloadWizard(self.window_main,MSG_000003, True)
                dialog.connect("download-failed", self._fileDownloadFailed)
                
                # Download queue
                downloadItems = set()
        
                downloadItems.add(DownloadItem(MSG_000011, 'http://archive.ubuntugames.org/iug/version.txt', '/tmp/version.txt'))
                downloadItems.add(DownloadItem(MSG_000012, 'http://archive.ubuntugames.org/iug/iug.xml', '/tmp/iug.xml'))
                
                # Try to download all items
                response = dialog.download(downloadItems)
        
                # Destroy wizard
                dialog.destroy()
        
                # Abort installation if user pressed cancel during the download.
                txt_file = '/tmp/version.txt'
                xml_file = '/tmp/iug.xml'
                if response == gtk.RESPONSE_ACCEPT:
                    if os.path.exists(txt_file) and os.path.exists(txt_file):
                            self.parse_files(txt_file, xml_file)
                    else:
                        dlg_error = gtk.MessageDialog(None, gtk.DIALOG_MODAL,	gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, None)
                        dlg_error.set_markup(txt_file + ' or ' + xml_file + '\n\nFile not found. Verify if the download was done.')
                        dlg_error.run()
                        dlg_error.destroy()
                        print 'File not found. Verify if the download was done.'
                    
        self.window_main.set_sensitive(True)    
    
    def on_button_download(self, widget):
        game = self.treeview_games.get_selected_game()
        download_type = game.download_type
        install_command = game.download_url
        if download_type == 'wget':
            self.gui.show_info('<b>%s</b>\n%s' % (download_type,install_command), self.window_main)
            dialog = ProgressDialog(self.window_main ,'') 
            dialog.connect("download-failed", self._fileDownloadFailed)
            # Download queue
            downloadItems = set()
            filedownload = os.path.join('/tmp/',game.download_url.split('/')[-1])
            downloadItems.add(DownloadItem(game.game,game.download_url, filedownload))

            # Try to download all items
            #response = dialog.download(downloadItems)
            dialog.message('Downloading Game...')
            response = dialog.download(downloadItems)
            
            if response == gtk.RESPONSE_ACCEPT:
                commands = game.install_command.split('|')
                if lib.utils.get_mimetype(filedownload) == 'application/x-tar':
                    gunzip(filedownload)
                
            # Destroy wizard
            dialog.destroy()
        elif download_type =='deb':
            print 'gnome-terminal --command sudo dpkg -i %s' % game.install_command
            os.system('gnome-terminal --command sudo dpkg -i %s' % game.deb_filename)
        else:
            self.gui.show_info('Instalando:%s' % download_type, self.window_main)
            
    def on_zoom(self, widget):
        zoom = ZoomWindow(self.window_main, self.treeview_games.get_selected_game().image_filename)
        zoom.run()
        
    def _fileDownloadFailed(self, wizard, handle):
        print "Could not fetch file.", handle.item.source
    
    def parse_files(self, versionfile, xmlfile):
        self.gui.setBusy(self.window_main)
       	dversion = open(versionfile).readline()
        dversion = float(dversion)
        print "version:", dversion
        rec = self.actions.get_iugversion()[0]
        id = rec['id']
        lversion = rec['version']
        
        print id, lversion , lversion < dversion,lversion , dversion
        if lversion < dversion :
            self.actions.edit_iugversion({'version': dversion,'id': id, 'version_date': get_current_date()})
            xFile = XML2obj(xmlfile)
            xobj = xFile.get_python_from_xml()
            game = xobj.game
            for n in game:
                exist = self.actions.get_categories({'categoryname':decode(n.category)})
                if not exist:
                    self.actions.add_category({'categoryname':decode(n.category)})
                cat = self.actions.get_categories({'categoryname':decode(n.category)})[0]
                game_exist = self.actions.get_games({'game': decode(n.name)})
                print decode(n.description)
                if not game_exist :
                    game_dict=dict({'category': cat['id'],
                        'game': decode(n.name),
                        'description': decode(n.description),
                        'image_url': decode(n.image_url),
                        'image_file': get_file_name(decode(n.image_url)),
                        'requires': decode(n.requires),
                        'download_url':decode(n.download_url),
                        'download_type':decode(n.download_type),
                        'file_size':decode(n.file_size),
                        'website': decode(n.site),
                        'deb_filename':decode(n.deb_filename),
                        'install_command':decode(n.install_command),
                        'version':decode(n.version),
                        'file_size': decode(n.file_size),
                        'rate':decode(n.rate)})
                    
                    self.actions.add_game(game_dict);
                else:
                    game_dict=dict({'category': cat['id'],
                        'id' : game_exist[0]['id'],
                        'game': decode(n.name),
                        'description': decode(n.description),
                        'image_url': decode(n.image_url),
                        'image_file': get_file_name(decode(n.image_url)),
                        'requires': decode(n.requires),
                        'download_url':decode(n.download_url),
                        'download_type':decode(n.download_type),
                        'file_size':decode(n.file_size),
                        'website': decode(n.site),
                        'deb_filename':decode(n.deb_filename),
                        'install_command':decode(n.install_command),
                        'version':decode(n.version),
                        'file_size': decode(n.file_size),
                        'rate':decode(n.rate)})
                    
                    self.actions.edit_game(game_dict)
                    

        self.gui.setBusy(self.window_main, True)    
            
    def fill_category(self):
        self.gui.setBusy(self.window_main, True)
        model = gtk.ListStore(gobject.TYPE_STRING,gobject.TYPE_INT)
        self.treeview_categories.set_model(model)
        
        cat = self.actions.get_categories('')
        #added a category to show all games in the list
        model.append([MSG_000026,0])
        for n in cat:
            model.append([n['categoryname'],n['id']])
        
        self.gui.setBusy(self.window_main)
    
    def fill_games(self, categoryid):
        self.gui.setBusy(self.window_main, True)
        self.treeview_games.clear()
        if categoryid == 0:
            cat = self.actions.get_games()
        else:
            cat = self.actions.get_games({'category':categoryid})
        if cat:
            self.download_images(categoryid)
            for n in cat:
                game = Game(n['game'])
                game.game_id = n['id']
                game.category = n['category']
                game.rate = n['rate']
                game.description = n['description']
                game.image_filename = n['image_file']
                game.version = n['version']
                game.file_size = n['file_size']
                game.image_url = n['image_url']
                game.website = n['website']
                game.requires = n['requires']
                game.install_command =  n['install_command']
                game.deb_filename = n['deb_filename']
                game.download_url = n['download_url']
                game.download_type= n['download_type']
                game.localpicture = not load_pixbuf_image(game.image_filename)[1]
                self.treeview_games.add(game)
        self.gui.setBusy(self.window_main)
    
    # widget event handler
    
    def on_treeview_games_selected(self, widget, game):
        self.treeview_description.clear()
        self.image_game.clear()
        self.menu_viewsite.set_sensitive(True)
        self.button_download.set_sensitive(True)
        self.menu_download.set_sensitive(True)
        self.button_zoom.set_sensitive(True)
        self.menu_fullscreen.set_sensitive(True)
        self.treeview_description.add(game)
        pixbuf,isdefault = load_pixbuf_image(game.image_filename)
        pixscaled = self.gui.scale(pixbuf,192,192)
        self.image_game.set_from_pixbuf(pixscaled)
    
    def on_treeview_categories_changed(self, treeview):
        model, iter = treeview.get_selected()
        if iter:
            self.menu_viewsite.set_sensitive(False)
            self.button_download.set_sensitive(False)
            self.menu_download.set_sensitive(False)
            self.button_zoom.set_sensitive(False)
            self.menu_fullscreen.set_sensitive(False)
            self.treeview_description.clear()
            self.image_game.clear()
            self.fill_games( model.get_value(iter,COL_CAT_ITEM))
コード例 #15
0
class CategoriesDialog(gtk.Dialog):
    """
    Class used to generate dialog to allow user to enter/edit categories.
    """
    def __init__(self, parent=None, new=False):
        gtk.Dialog.__init__(self, title=_("Categories Manager"),
                            parent=parent, flags=gtk.DIALOG_MODAL)

        self.closebutton = self.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)
        self.okbutton = self.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
        self.set_icon_from_file(common.APP_ICON)

        self.new = new

        if parent:
            self.set_transient_for(parent)
            self.set_position(gtk.WIN_POS_CENTER_ON_PARENT)

        self.currentrecord = None

        # Set up the UI
        self._initialize_dialog_widgets()
        self._connect_fields()
        #self._populate_fields()
        self.actions = Actions()
        self._populateTreeView(self.actions.get_categories())

        if new:
            self._on_newbutton_clicked(None)
            self.topcontainer.get_label_widget().set_markup("<b>%s</b>" \
                                                     % _("New Category"))
            self.okbutton.set_label(gtk.STOCK_SAVE)
            self.closebutton.set_label(gtk.STOCK_CANCEL)

        else:
            index = parent.category.get_active()-2
            if index >= 0:
                self.list.set_cursor((index,))

    def _initialize_dialog_widgets(self):
        self.vbox.set_spacing(8)
        self.topcontainer = gtk.Frame("<b>%s</b>" % _("Categories"))
        self.topcontainer.props.label_widget.set_use_markup(True)
        self.topcontainer.set_shadow_type(gtk.SHADOW_NONE)
        self.topcontainer_alignment = gtk.Alignment()
        self.topcontainer_alignment.set_padding(10, 0, 12, 0)
        self.topcontainer.add(self.topcontainer_alignment)
        self.fieldbox = gtk.VBox(homogeneous=False, spacing=6)

        self.list = ViewCategory()
        self.list.set_size_request(300, 150)

        # ScrolledWindow
        self.scrolledwindow = gtk.ScrolledWindow()
        self.scrolledwindow.set_shadow_type(gtk.SHADOW_OUT)
        self.scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC,
                                       gtk.POLICY_AUTOMATIC)
        self.scrolledwindow.add(self.list)

        self.table = gtk.Table(rows=2, columns=2, homogeneous=False)
        self.table.set_col_spacing(0, 6)
        self.table.set_row_spacing(0, 6)

        self.namelabel = gtk.Label()
        self.namelabel.set_markup("%s " % _("Name:"))
        self.namelabel.set_alignment(0.00, 0.50)
        self.colorlabel = gtk.Label()
        self.colorlabel.set_markup("%s " % _("Color:"))
        self.colorlabel.set_alignment(0.00, 0.50)

        self.name_ = gtk.Entry()
        self.color = gtk.ColorButton()

        self.table.attach(self.namelabel, 0, 1, 0, 1, gtk.FILL, gtk.FILL)
        self.table.attach(self.colorlabel, 0, 1, 1, 2, gtk.FILL, gtk.FILL)
        self.table.attach(self.name_, 1, 2, 0, 1)
        self.table.attach(self.color, 1, 2, 1, 2)

        self.actionspack = gtk.HButtonBox()
        self.actionspack.set_layout(gtk.BUTTONBOX_END)
        self.actionspack.set_spacing(6)

        self.newbutton = gtk.Button(stock=gtk.STOCK_NEW)
        self.savebutton = gtk.Button(stock=gtk.STOCK_SAVE)
        self.deletebutton = gtk.Button(stock=gtk.STOCK_DELETE)

        self.actionspack.pack_start(self.newbutton)
        self.actionspack.pack_start(self.savebutton)
        self.actionspack.pack_start(self.deletebutton)

        if not self.new:
            self.fieldbox.pack_start(self.scrolledwindow,
                                     expand=True, fill=True)
        self.fieldbox.pack_start(self.table,
                                 expand=False, fill=True)
        if not self.new:
            self.fieldbox.pack_start(self.actionspack,
                                     expand=False, fill=True)
        self.topcontainer_alignment.add(self.fieldbox)
        self.vbox.pack_start(self.topcontainer,
                             expand=True, fill=True, padding=10)

        # Show all widgets
        self.show_all()

    def _connect_fields(self):
        self.list.connect('cursor_changed', self._on_list_cursor_changed)
        self.name_.connect("changed", self._on_edit)
        self.color.connect("color-set", self._on_edit)
        self.newbutton.connect("clicked", self._on_newbutton_clicked)
        self.savebutton.connect("clicked", self._on_savebutton_clicked)
        self.deletebutton.connect("clicked", self._on_deletebutton_clicked)

    def _populateTreeView(self, records):
        """ Populates the treeview control with the records passed """
        # Loops through bills collection
        path = 0
        found = 0

        for rec in records:
            self.list.add(self._formated_row(rec))
            if self.currentrecord:
                if rec.name == self.currentrecord.name:
                    found = path
            path += 1

        # Only select an item if we have data
        if len(self.list):
            self.list.set_cursor(found)

        return

    def _formated_row(self, row):
        """ Formats a bill to be displayed as a row. """
        color = row.color and row.color or '#d3d7cf'

        formated = []
        formated.append(row.id)
        formated.append(create_pixbuf(color=color))
        formated.append(row.name)
        formated.append(row.color)

        return formated

    def _on_list_cursor_changed(self, widget):
        # Get currently selected bill
        self._get_selected_record()
        # Update statusbar
        self._update_fields()
        self.deletebutton.set_sensitive(True)
        self.savebutton.set_sensitive(False)

    def _get_selected_record(self):
        """ Keeps track of the currently selected record """
        if len(self.list.listStore) > 0:
            selection = self.list.get_selection()
            _model, iteration = selection.get_selected()
            # The ID for the selected record
            category_id = _model.get_value(iteration, 0)
            # Now fetch it from the database
            self.currentrecord = self.actions.get_categories(id=category_id)[0]
        else:
            self.currentrecord = None

    def _update_fields(self):
        if not self.currentrecord:
            self.name_.set_text("")
            self.color.set_color(gtk.gdk.color_parse("#d3d7cf"))
        else:
            self.name_.set_text(self.currentrecord.name)

            color = self.currentrecord.color and self.currentrecord.color or '#d3d7cf'
            color = gtk.gdk.color_parse(color)
            self.color.set_color(color)

    def reloadTreeView(self, *arg):
        # Update list with updated record
        self.list.listStore.clear()
        self._populateTreeView(self.actions.get_categories())

    def _on_newbutton_clicked(self, button):
        self.currentrecord = None
        self.name_.set_text("")
        self.color.set_color(gtk.gdk.color_parse("#d3d7cf"))
        self.deletebutton.set_sensitive(False)
        self.savebutton.set_sensitive(False)
        self.name_.grab_focus()

    def _on_savebutton_clicked(self, button):
        # Extract input data
        name =  self.name_.get_text()
        color = self.color.get_color().to_string()

        # Check if it already exists
        rec = self.actions.get_categories(name=name)
        if rec:
            message = Message()
            if message.ShowQuestionYesNo(_("The category \"%s\" already exists in the database!\n\n"\
                "Do you want to save your change to the existing category?") % name, self):
                # We're updating an existing category.
                cat = rec[0]
                cat.name = name
                cat.color = color
                row = self.actions.edit(cat)
        # We're adding a new category.
        else:
            cat = Category(name, color)
            row = self.actions.add(cat)
            # Update our local "copy" directly from database
            self.currentrecord = self.actions.get_categories(name=name)[0]

        # Repopulate the grid
        self.reloadTreeView()

    def _on_deletebutton_clicked(self, button):
        if self.currentrecord:
            id = self.currentrecord.id
            more = self.actions.get_bills(id=id)
            if len(more) > 1:
                message = Message()
                confirm = message.ShowQuestionYesNo("%s%s" % (
                    _("Do you really want to delete this category?\n") ,
                    ngettext("There is %d more bill in this category.",
                        "There are %d more bills in this category.",
                        (len(more) - 1)) % (len(more) - 1)), 
                    parentWindow=self, title=_("Confirmation"))
                if not confirm:
                    return
            try:
                row = self.actions.delete(self.currentrecord)
                self.currentrecord = None
                self.name_.set_text("")
                self.color.set_color(gtk.gdk.color_parse("#d3d7cf"))
                self.savebutton.set_sensitive(False)
                self.reloadTreeView()
            except Exception, e:
                print "Failed to delete the selected category with error: %s" % str(e)
コード例 #16
0
    def __init__(self):
        gobject.GObject.__init__(self)

        if exists(join(USER_CFG_PATH, CFG_NAME)):
            from lib.migrate_to_gconf import migrate
            migrate(join(USER_CFG_PATH, CFG_NAME))

        self.gconf_client = Configuration()
        self.message = Message()
        # Connects to the database
        self.actions = Actions()

        self.ui = gtk.Builder()
        self.ui.add_from_file(os.path.join(DEFAULT_CFG_PATH, "main.ui"))

        self.window = self.ui.get_object("main_window")
        self.window.set_title("%s" % common.APPNAME)
        self.window.set_icon_from_file(common.APP_ICON)

        # ViewBill
        self.list = ViewBill()
        self.list.connect('cursor_changed', self._on_list_cursor_changed)
        self.list.connect('row_activated', self._on_list_row_activated)
        self.list.connect('button_press_event',
                          self._on_list_button_press_event)

        self.ui.get_object("bill_box").add(self.list)

        # Toolbar
        self.toolbar = self.ui.get_object("toolbar")

        # Menubar
        self._populate_menubar()

        # Statusbar
        self.statusbar = Statusbar()
        self.ui.get_object("statusbar_box").add(self.statusbar)

        # Restore timeline zoom
        timeline_count = self.gconf_client.get('timeline_count')

        # Timeline
        self.timeline = Timeline(count=timeline_count,
                                 callback=self.on_timeline_cb)
        self.timeline.connect("value-changed", self._on_timeline_changed)
        self.timeline.connect("cleared", self._on_timeline_cleared)
        self.ui.get_object("timeline_box").add(self.timeline)

        # Chart
        self.chart = ChartWidget()
        self.chart.set_border_width(10)
        self.ui.get_object("chart_box").add(self.chart)

        # Restore position and size of window
        width = self.gconf_client.get('window_width')
        height = self.gconf_client.get('window_height')
        x = self.gconf_client.get('window_position_x')
        y = self.gconf_client.get('window_position_y')
        if width and height:
            self.window.resize(width, height)
        if x and y:
            self.window.move(x, y)

        self.window.show_all()

        # Whether to display toolbar or not
        self.on_showToolbar_toggled(self.ui.get_object("showToolbar"))
        self.list.grab_focus()

        if self.gconf_client.get('start_in_tray'):
            self.window.hide()

        self.toggle_buttons()

        # Connects to the Daemon
        self.iface = None
        iface = get_dbus_interface(common.DBUS_INTERFACE, common.DBUS_PATH)
        if iface:
            iface.connect_to_signal("bill_edited", self.reloadTreeView)
            iface.connect_to_signal("bill_edited", self.reloadTimeline)
            iface.connect_to_signal("show_main_window", self.window.show)
            self.iface = iface
            timeout_add(2000, self._send_tray_hints)

        self.set_action_strings()
        self.ui.connect_signals(self)

        # populate treeview
        self.reloadTreeView()
        self.notify = NotifyIcon(self)

        # Integrate with Ubuntu Unity
        if UNITY:
            self.unity = UnityIntegration(self)
コード例 #17
0
class MainDialog(gobject.GObject):
    search_text = ""
    _bullet_cache = {}

    __gsignals__ = {
        'bill-added': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
                       (gobject.TYPE_PYOBJECT, )),
        'bill-updated': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
                         (gobject.TYPE_PYOBJECT, )),
        'bill-removed':
        (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT, ))
    }

    def __init__(self):
        gobject.GObject.__init__(self)

        if exists(join(USER_CFG_PATH, CFG_NAME)):
            from lib.migrate_to_gconf import migrate
            migrate(join(USER_CFG_PATH, CFG_NAME))

        self.gconf_client = Configuration()
        self.message = Message()
        # Connects to the database
        self.actions = Actions()

        self.ui = gtk.Builder()
        self.ui.add_from_file(os.path.join(DEFAULT_CFG_PATH, "main.ui"))

        self.window = self.ui.get_object("main_window")
        self.window.set_title("%s" % common.APPNAME)
        self.window.set_icon_from_file(common.APP_ICON)

        # ViewBill
        self.list = ViewBill()
        self.list.connect('cursor_changed', self._on_list_cursor_changed)
        self.list.connect('row_activated', self._on_list_row_activated)
        self.list.connect('button_press_event',
                          self._on_list_button_press_event)

        self.ui.get_object("bill_box").add(self.list)

        # Toolbar
        self.toolbar = self.ui.get_object("toolbar")

        # Menubar
        self._populate_menubar()

        # Statusbar
        self.statusbar = Statusbar()
        self.ui.get_object("statusbar_box").add(self.statusbar)

        # Restore timeline zoom
        timeline_count = self.gconf_client.get('timeline_count')

        # Timeline
        self.timeline = Timeline(count=timeline_count,
                                 callback=self.on_timeline_cb)
        self.timeline.connect("value-changed", self._on_timeline_changed)
        self.timeline.connect("cleared", self._on_timeline_cleared)
        self.ui.get_object("timeline_box").add(self.timeline)

        # Chart
        self.chart = ChartWidget()
        self.chart.set_border_width(10)
        self.ui.get_object("chart_box").add(self.chart)

        # Restore position and size of window
        width = self.gconf_client.get('window_width')
        height = self.gconf_client.get('window_height')
        x = self.gconf_client.get('window_position_x')
        y = self.gconf_client.get('window_position_y')
        if width and height:
            self.window.resize(width, height)
        if x and y:
            self.window.move(x, y)

        self.window.show_all()

        # Whether to display toolbar or not
        self.on_showToolbar_toggled(self.ui.get_object("showToolbar"))
        self.list.grab_focus()

        if self.gconf_client.get('start_in_tray'):
            self.window.hide()

        self.toggle_buttons()

        # Connects to the Daemon
        self.iface = None
        iface = get_dbus_interface(common.DBUS_INTERFACE, common.DBUS_PATH)
        if iface:
            iface.connect_to_signal("bill_edited", self.reloadTreeView)
            iface.connect_to_signal("bill_edited", self.reloadTimeline)
            iface.connect_to_signal("show_main_window", self.window.show)
            self.iface = iface
            timeout_add(2000, self._send_tray_hints)

        self.set_action_strings()
        self.ui.connect_signals(self)

        # populate treeview
        self.reloadTreeView()
        self.notify = NotifyIcon(self)

        # Integrate with Ubuntu Unity
        if UNITY:
            self.unity = UnityIntegration(self)

    def set_action_strings(self):
        # for some reason the actions strings do not get translated yet
        # so we define them here so they would be picked up by the pyfile scanner
        self.ui.get_object("newBill").set_label(_("_New"))
        self.ui.get_object("newBill").set_tooltip(_("Add new bill"))

        self.ui.get_object("editBill").set_label(_("_Edit"))
        self.ui.get_object("editBill").set_tooltip(_("Edit a bill"))

        self.ui.get_object("removeBill").set_label(_("_Delete"))
        self.ui.get_object("removeBill").set_tooltip(_("Delete selected bill"))

        self.ui.get_object("markPaid").set_label(_("P_aid"))
        self.ui.get_object("markPaid").set_tooltip(_("Mark as paid"))

        self.ui.get_object("markNotPaid").set_label(_("No_t Paid"))
        self.ui.get_object("markNotPaid").set_tooltip(_("Mark as not paid"))

        self.ui.get_object("showToolbar").set_label(_("_Show Toolbar"))
        self.ui.get_object("showToolbar").set_tooltip(_("Show the toolbar"))

    # Methods:  UI
    def _send_tray_hints(self):
        self.iface.set_tray_hints(force_string(self.notify.get_hints()))
        timeout_add(60000, self._send_tray_hints)

    def get_window_visibility(self):
        return self.window.get_property("visible")

    def show_hide_window(self):
        if self.window.get_property("visible"):
            self.window.hide()
        else:
            self.window.show()

    def get_selected_record(self):
        """ Returns a bill object from the current selected record """
        if len(self.list.listStore) > 0:
            model_ = self.list.get_model()
            if self.list.get_cursor()[0]:
                index = self.list.get_cursor()[0][0]
            else:
                index = 0

            b_id = model_[index][0]

            records = self.actions.get_bills(id=b_id)
            self.currentrecord = records[0]

        else:
            self.currentrecord = None
        print "Current record is: %s" % self.currentrecord

    def populate_view(self, records):
        """ Populates the treeview control with the records passed """

        # Reset list
        self.list.listStore.clear()

        if not records:
            return 0

        # Loops through bills collection
        path = 0
        for rec in records:
            # Format the record prior to adding it to treeview
            row = self.format_row(rec)
            self.list.add(row)

        # Set the cursor to the first (top) record
        self.list.set_cursor(path)

        # Returns how many records there are in the treeview
        return len(records)

    def reloadTreeView(self, *arg):
        # Update list with updated record
        status = self.gconf_client.get('show_paid_bills')

        path = self.list.get_cursor()[0]
        self.list.listStore.clear()
        self.currentrecord = None

        first = self.timeline.start_date
        last = self.timeline.end_date
        # Get list of records
        records = self.actions.get_interval_bills(first, last, status)

        # Populate treeview
        self.populate_view(records)
        # Update status bar
        self.update_statusbar()
        # populate chart
        self._populate_chart(status, first, last)

        return len(records)

    def format_row(self, row):
        """ Formats a bill to be displayed as a row. """

        categoryName = row.category.name if row.category else _('None')
        categoryColor = row.category.color if row.category else '#d3d7cf'
        formatted = [
            row.id,
            create_pixbuf(color=categoryColor), categoryName, row.payee,
            row.dueDate.strftime(_('%m/%d').encode('ASCII')), row.amount,
            row.notes,
            int(row.paid), None
        ]

        return formatted

    def _populate_chart(self, status, start, end):

        records = []
        categories = []
        totals = []

        records = self.actions.get_monthly_totals(start, end, status)
        # Chart widget takes data in format (('CategoryName', amount),)
        categories = [cat or 'None' for cat, total in records]
        totals = [float(total) for cat, total in records]
        #records = [(c if c else 'None',float(t)) for c,t in records]

        # set bar colors
        all_categories = self.actions.get_categories()
        self.chart.chart.key_colors = dict([(cat.name or 'None', cat.color)
                                            for cat in all_categories])

        self.chart.plot(categories, totals)

    def _populate_menubar(self):
        try:
            saved_view = self.gconf_client.get('show_paid_bills')
        except:
            saved_view = 1
            self.gconf_client.set("show_paid_bills", saved_view)

        if saved_view == 0:
            self.ui.get_object("showNotPaid").set_active(True)
        elif saved_view == 1:
            self.ui.get_object("showPaid").set_active(True)
        else:
            self.ui.get_object("showAll").set_active(True)

        # Check whether we display the toolbar or not
        self.ui.get_object("showToolbar").set_active(
            self.gconf_client.get('show_toolbar'))

    def add_bill(self):
        selectedDate = self.timeline.value
        records = dialogs.add_dialog(parent=self.window,
                                     selectedDate=selectedDate)

        # Checks if the user did not cancel the action
        if records:
            # Add new bill to database
            for rec in records:
                bill_id = self.actions.add(rec)
                bill = self.actions.get_bills(id=bill_id)[0]
                if bill:
                    self.list.add(self.format_row(bill))
            self.update_statusbar()
            # Reload records tree (something changed)
            self.reloadTreeView()
            self.reloadTimeline()

    def edit_bill(self):
        records = dialogs.edit_dialog(parent=self.window,
                                      record=self.currentrecord)

        # Checks if the user did not cancel the action
        if records:
            for rec in records:
                # Edit bill to database
                rec = self.actions.edit(rec)
                self.emit('bill-updated', rec)

            # Reload records tree (something changed)
            self.reloadTreeView()
            self.reloadTimeline()

    def remove_bill(self):
        self.actions.delete(self.currentrecord)
        self.list.remove()
        self.emit('bill-removed', None)
        self.update_statusbar()
        self.reloadTreeView()
        self.reloadTimeline()

    def toggle_bill_paid(self):
        # Fetch record from database
        record = self.actions.get_bills(id=self.currentrecord.id)[0]
        # Toggle paid field
        record.paid = False if record.paid else True

        # Edit bill in the database
        transaction = self.actions.add(record)

        self.emit('bill-updated', record)

        # Update our current copy
        self.currentrecord = self.actions.get_bills(
            id=self.currentrecord.id)[0]
        # Update timeline widget to reflect change
        self._bullet_cache[self.currentrecord.dueDate] = [self.currentrecord]
        # Update list with updated record
        idx = self.list.get_cursor()[0][0]
        self.update_statusbar(idx)
        self.reloadTreeView()
        self.reloadTimeline()

    def about(self):
        dialogs.about_dialog(parent=self.window)

    def preferences(self):
        dialogs.preferences_dialog(parent=self.window)

    # Methods
    def _quit_application(self):
        self.save_position()
        self.save_size()
        self.save_timeline_zoom()
        gtk.main_quit()
        return False

    def save_position(self):
        x, y = self.window.get_position()
        self.gconf_client.set('window_position_x', x)
        self.gconf_client.set('window_position_y', y)

    def save_size(self):
        width, height = self.window.get_size()
        self.gconf_client.set('window_width', width)
        self.gconf_client.set('window_height', height)

    def save_timeline_zoom(self):
        count = self.timeline.count
        self.gconf_client.set('timeline_count', count)

    def toggle_buttons(self, paid=None):
        """ Toggles all buttons conform number of records present and
            their state """

        for widget in ["editBill", "removeBill", "markPaid", "markNotPaid"]:
            self.ui.get_object(widget).set_sensitive(
                len(self.list.listStore) > 0)

        if len(self.list.listStore) > 0:
            self.ui.get_object("markPaid").set_sensitive(paid == False)
            self.ui.get_object("markNotPaid").set_sensitive(paid == True)

    def update_statusbar(self, index=0):
        """ This function is used to update status bar informations
            about the list """
        records = len(self.list.listStore)

        # Record count
        self.statusbar.Records(records)
        if self.currentrecord:
            # Display the status
            self.statusbar.Notes(self.currentrecord.notes)
            # Toggles toolbar buttons on/off
            self.toggle_buttons(self.currentrecord.paid)
        else:
            # Clear the status for the selected row
            self.statusbar.Notes("")
            # Toggles toolbar buttons on/off
            self.toggle_buttons()

        show_paid_bills = self.gconf_client.get('show_paid_bills')
        if show_paid_bills is 0:
            self.statusbar.Info(_("Not Paid Only"))
        elif show_paid_bills is 1:
            self.statusbar.Info(_("Paid Only"))
        else:
            self.statusbar.Info('')

    # Event handlers
    def _on_list_button_press_event(self, widget, event):
        """ This function will handle the signal to show a popup menu
            sent by a right click on tvBill widget. """
        if event.button == 3 and event.type == gtk.gdk.BUTTON_PRESS:
            self.get_selected_record()

            c = self.ui.get_object("context_menu")
            c.popup(None, None, None, event.button, event.get_time())

    def _on_list_row_activated(self, widget, path, column):
        self._on_list_cursor_changed(widget)
        self.on_editBill_activate(None)

    def _on_list_cursor_changed(self, widget):
        # Get currently selected bill
        self.get_selected_record()
        # Update statusbar
        self.update_statusbar()

    def on_newBill_activate(self, toolbutton):
        self.add_bill()

    def on_editBill_activate(self, toolbutton):
        if self.currentrecord:
            self.edit_bill()

    def on_removeBill_activate(self, toolbutton):
        if self.currentrecord:
            resp = self.message.ShowQuestionYesNo(
                _("Do you really want to delete \"%s\"?") % \
                self.currentrecord.payee,
                self.window, _("Confirmation"))
            if resp:
                self.remove_bill()

    def on_markNotPaid_activate(self, toolbutton):
        self.on_markPaid_activate(toolbutton)  # forward

    def on_markPaid_activate(self, toolbutton):
        if self.currentrecord:
            self.toggle_bill_paid()

    def on_btnAbout_activate(self, toolbutton):
        self.about()

    def on_btnPrefs_activate(self, toolbutton):
        self.preferences()

    def on_btnQuit_activate(self, toolbutton):
        self._quit_application()

    def on_delete_event(self, widget, event, data=None):
        self._quit_application()

    def _on_timeline_changed(self, widget, args):
        self.reloadTreeView()

    def _on_timeline_cleared(self, widget, args):
        self._bullet_cache = {}

    def switch_view(self, view_number):
        self.gconf_client.set('show_paid_bills', view_number)
        self.reloadTreeView()
        self.reloadTimeline()

    def on_showNotPaid_toggled(self, action):
        if action.get_active():
            self.switch_view(0)

    def on_showPaid_toggled(self, action):
        if action.get_active():
            self.switch_view(1)

    def on_showAll_toggled(self, action):
        if action.get_active():
            self.switch_view(2)

    def on_showToolbar_toggled(self, action):
        # Toggle toolbar's visibility
        if action.get_active():
            self.toolbar.show_all()
        else:
            self.toolbar.hide_all()

        self.gconf_client.set("show_toolbar", action.get_active())

    def reloadTimeline(self, *args):
        self._bullet_cache = {}
        self.timeline.refresh()

    def on_timeline_cb(self, date, display_type, force=False):
        # TODO: Improve tooltip
        # TODO: Improve cache

        if date in self._bullet_cache.keys() and not force:
            return None

        self._bullet_cache[date] = self.actions.get_bills(dueDate=date)
        if self._bullet_cache[date]:
            status = self.gconf_client.get('show_paid_bills')
            amount = 0
            amount_not_paid = 0
            tooltip = ''
            bullet = Event()
            bullet.date = date

            for bill in self._bullet_cache[date]:
                amount += bill.amount
                if tooltip:
                    tooltip += '\n'
                tooltip += bill.payee + ' (' + str(
                    float_to_currency(bill.amount)) + ')'

                if bill.paid:
                    tooltip += ' [%s]' % _('Paid')

                    if status == 0:
                        return False
                    bullet.status = bullet.status | bullet.PAID
                else:
                    amount_not_paid += bill.amount
                    if date <= datetime.date.today():
                        if status == 1:
                            return False
                        bullet.status = bullet.status | bullet.OVERDUE
                    else:
                        if status == 1:
                            return False
                        bullet.status = bullet.status | bullet.TO_BE_PAID

                if bill.notes:
                    tooltip += ' - ' + bill.notes

            bullet.amountdue = amount_not_paid if amount_not_paid else amount
            bullet.payee = bill.payee

            bills = len(self._bullet_cache[date])
            if bills > 1:
                bullet.multi = bills
                bullet.payee = '%d bills' % bills
            bullet.tooltip = tooltip
            return bullet

        return None