Ejemplo n.º 1
0
class Diary(ProxyDelegate):
    def __init__(self):
        self.entries = ObjectList([
            Column("title", width=120, sorted=True),
            Column("period", width=80),
            Column("text", expand=True, visible=False)
        ])
        ProxyDelegate.__init__(self,
                               DiaryEntry(),
                               ['title', 'period', 'text', 'chars', 'words'],
                               gladefile="diary2.ui",
                               delete_handler=self.quit_if_last)
        self.hbox.pack_start(self.entries, True, True, 0)
        self.entries.show()
        self.entries.grab_focus()
        self.set_editable(False)

    def set_editable(self, editable):
        self.leftbox.set_sensitive(editable)
        self.remove.set_sensitive(editable)

    def proxy_updated(self, *args):
        self.entries.update(self.model)

    def on_add__clicked(self, button):
        entry = DiaryEntry()
        entry.title = 'Untitled'
        self.entries.append(entry, select=True)
        self.set_editable(True)

    def on_remove__clicked(self, button):
        entry = self.entries.get_selected()
        if entry:
            self.entries.remove(entry, select=True)

        self.set_editable(len(self.entries) >= 1)
        if not len(self.entries):
            self.set_model(None)

    def on_text__content_changed(self, text):
        self.proxy.update_many(("chars", "words"))
        self.entries.update(self.model)

    def on_entries__selection_changed(self, entries, instance):
        if instance:
            self.set_model(instance)
            self.title.grab_focus()
Ejemplo n.º 2
0
class Diary(ProxyDelegate):
    def __init__(self):
        self.entries = ObjectList([Column("title", width=120, sorted=True),
                                   Column("period", width=80),
                                   Column("text", expand=True, visible=False)])
        ProxyDelegate.__init__(self, DiaryEntry(),
                               ['title', 'period', 'text', 'chars', 'words'],
                               gladefile="diary2.ui",
                               delete_handler=self.quit_if_last)
        self.hbox.pack_start(self.entries, True, True, 0)
        self.entries.show()
        self.entries.grab_focus()
        self.set_editable(False)

    def set_editable(self, editable):
        self.leftbox.set_sensitive(editable)
        self.remove.set_sensitive(editable)

    def proxy_updated(self, *args):
        self.entries.update(self.model)

    def on_add__clicked(self, button):
        entry = DiaryEntry()
        entry.title = 'Untitled'
        self.entries.append(entry, select=True)
        self.set_editable(True)

    def on_remove__clicked(self, button):
        entry = self.entries.get_selected()
        if entry:
            self.entries.remove(entry, select=True)

        self.set_editable(len(self.entries) >= 1)
        if not len(self.entries):
            self.set_model(None)

    def on_text__content_changed(self, text):
        self.proxy.update_many(("chars", "words"))
        self.entries.update(self.model)

    def on_entries__selection_changed(self, entries, instance):
        if instance:
            self.set_model(instance)
            self.title.grab_focus()
Ejemplo n.º 3
0
class DataTests(unittest.TestCase):
    """In all this tests we use the same configuration for a list"""
    def setUp(self):
        self.win = gtk.Window()
        self.win.set_default_size(400, 400)
        self.list = ObjectList([Column('name'), Column('age')])
        self.win.add(self.list)
        refresh_gui()

    def tearDown(self):
        self.win.destroy()
        del self.win

    def testAddingOneInstance(self):
        # we should have two columns now
        self.assertEqual(2, len(self.list.get_columns()))

        person = Person('henrique', 21)
        self.list.append(person)

        refresh_gui()

        # usually you don't use the model directly, but tests are all about
        # breaking APIs, right?
        self.assertEqual(self.list[0], person)
        self.assertEqual(self.list[0].name, 'henrique')
        self.assertEqual(self.list[0].age, 21)

        # we still have to columns, right?
        self.assertEqual(2, len(self.list.get_columns()))

    def testAddingAObjectList(self):
        global persons

        self.list.add_list(persons)
        refresh_gui()

        self.assertEqual(len(self.list), len(persons))

    def testAddingABunchOfInstances(self):
        global persons

        for person in persons:
            self.list.append(person)
            refresh_gui()

        self.assertEqual(len(self.list), len(persons))

    def testRemovingOneInstance(self):
        global  persons

        self.list.add_list(persons)
        refresh_gui()

        # we are going to remove Kiko
        person = persons[2]

        self.list.remove(person)

        self.assertEqual(len(self.list), len(persons) - 1)

        # now let's remove something that is not on the list
        #new_person = Person('Evandro', 24)
        #self.assertRaises(ValueError, self.list.remove, new_person)

        # note that even a new person with the same values as a person
        # in the list is not considered to be in the list
        #existing_person = Person('Gustavo', 25)
        #self.assertRaises(ValueError, self.list.remove,
        #                  existing_person)

    def testClearObjectList(self):
        global persons

        self.list.add_list(persons)
        refresh_gui()

        self.list.clear()

        self.assertEqual(len(self.list), 0)


    def testUpdatingOneInstance(self):
        global persons

        self.list.add_list(persons)
        refresh_gui()

        persons[0].age = 29
        self.list.update(persons[0])

        refresh_gui()

        # Do we have the same number of instances that we had before ?
        self.assertEqual(len(self.list), len(persons))

        # Trying to find our updated instance in the list
        self.assertEqual(self.list[0].age, 29)

        # let's be evil
        new_person = Person('Nando', 32)
        self.assertRaises(ValueError, self.list.update, new_person)


    def testContains(self):
        global persons

        self.list.add_list(persons)
        self.assertEqual(persons[0] in self.list, True)

        new_person = Person('Nando', 32)
        self.assertEqual(new_person in self.list, False)

    def testSelect(self):
        first = persons[0]
        self.list.add_list(persons)
        self.list.select(first)
        self.assertEqual(self.list.get_selected(), first)

        self.list.remove(first)
        self.assertRaises(ValueError, self.list.select, first)
Ejemplo n.º 4
0
class ListContainer(gtk.HBox):
    """A ListContainer is an L{ObjectList} with buttons to be able
    to modify the content of the list.
    Depending on the list_mode, @see L{set_list_mode} you will
    have add, remove and edit buttons.

    Signals
    =======
      - B{add-item} (returns item):
        - emitted when the add button is clicked, you're expected to
          return an object here
      - B{remove-item} (item, returns bool):
        - emitted when removing an item,
          you can block the removal from the list by returning False
      - B{edit-item} (item):
        - emitted when editing an item
          you can block the update afterwards by returning False

    @ivar add_button: add button
    @type add_button: L{gtk.Button}
    @ivar remove_button: remove button
    @type remove_button: L{gtk.Button}
    @ivar edit_button: edit button
    @type edit_button: L{gtk.Button}
    """

    gsignal('add-item', retval=object)
    gsignal('remove-item', object, retval=bool)
    gsignal('edit-item', object, retval=bool)
    gsignal('selection-changed', object)

    def __init__(self, columns, orientation=gtk.ORIENTATION_VERTICAL):
        """
        Create a new ListContainer object.
        @param columns: columns for the L{kiwi.ui.objectlist.ObjectList}
        @type columns: a list of L{kiwi.ui.objectlist.Columns}
        @param orientation: the position where the buttons will be
            placed: at the right (vertically) or at the bottom (horizontally)
            of the list. Defaults to the right of the list.
        @type: gtk.ORIENTATION_HORIZONTAL or gtk.ORIENTATION_VERTICAL
        """
        self._list_type = None

        gtk.HBox.__init__(self)

        self._orientation = orientation

        self._create_ui(columns)
        self.set_list_type(ListType.NORMAL)

    # Private API

    def _create_ui(self, columns):
        self.list = ObjectList(columns)
        self.list.connect('selection-changed',
                          self._on_list__selection_changed)
        self.list.connect('row-activated', self._on_list__row_activated)

        self.add_button = gtk.Button(stock=gtk.STOCK_ADD)
        self.add_button.connect('clicked', self._on_add_button__clicked)

        self.remove_button = gtk.Button(stock=gtk.STOCK_REMOVE)
        self.remove_button.set_sensitive(False)
        self.remove_button.connect('clicked', self._on_remove_button__clicked)

        self.edit_button = gtk.Button(stock=gtk.STOCK_EDIT)
        self.edit_button.set_sensitive(False)
        self.edit_button.connect('clicked', self._on_edit_button__clicked)

        self._vbox = gtk.VBox(spacing=6)

        if self._orientation == gtk.ORIENTATION_VERTICAL:
            self.pack_start(self.list)
            self.list.show()
            self._add_buttons_to_box(self._vbox)
            self._pack_vbox()
        elif self._orientation == gtk.ORIENTATION_HORIZONTAL:
            self._vbox.pack_start(self.list)
            self.list.show()
            hbox = gtk.HBox(spacing=6)
            self._add_buttons_to_box(hbox)
            self._vbox.pack_start(hbox, expand=False)
            hbox.show()
            self._pack_vbox()
        else:
            raise TypeError(
                "buttons_orientation must be gtk.ORIENTATION_VERTICAL "
                " or gtk.ORIENTATION_HORIZONTAL")

    def _add_buttons_to_box(self, box):
        box.pack_start(self.add_button, expand=False)
        box.pack_start(self.remove_button, expand=False)
        box.pack_start(self.edit_button, expand=False)

    def _pack_vbox(self):
        self.pack_start(self._vbox, expand=False, padding=6)
        self._vbox.show()

    def _set_child_packing(self, padding):
        expand = self._orientation == gtk.ORIENTATION_HORIZONTAL

        self.set_child_packing(self._vbox, expand, True, padding,
                               gtk.PACK_START)

    def _add_item(self):
        retval = self.emit('add-item')
        if retval is None:
            return
        elif isinstance(retval, NotImplementedError):
            raise retval

        self.list.append(retval)

    def _remove_item(self, item):
        retval = self.emit('remove-item', item)
        if retval:
            self.list.remove(item)

    def _edit_item(self, item):
        retval = self.emit('edit-item', item)
        if retval:
            self.list.update(item)

    # Public API

    def add_item(self, item):
        """Appends an item to the list
        @param item: item to append
        """
        self.list.append(item)

    def add_items(self, items):
        """Appends a list of items to the list
        @param items: items to add
        @type items: a sequence of items
        """
        self.list.extend(items)

    def remove_item(self, item):
        """Removes an item from the list
        @param item: item to remove
        """
        self.list.remove(item)

    def update_item(self, item):
        """Updates an item in the list.
        You should call this if you change the object
        @param item: item to update
        """
        self.list.update(item)

    def default_remove(self, item):
        """Asks the user confirmation for removal of an item.
        @param item: a description of the item that will be removed
        @returns: True if the user confirm the removal, False otherwise
        """
        response = yesno(_('Do you want to remove %s ?') %
                         (quote(str(item)), ),
                         parent=None,
                         default=gtk.RESPONSE_OK,
                         buttons=((gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
                                  (gtk.STOCK_REMOVE, gtk.RESPONSE_OK)))
        return response == gtk.RESPONSE_OK

    def set_list_type(self, list_type):
        """Sets the kind of list type.
        @param list_type:
        """
        if not isinstance(list_type, ListType):
            raise TypeError("list_type must be a ListType enum")

        self.add_button.set_property('visible',
                                     (list_type != ListType.READONLY
                                      and list_type != ListType.REMOVEONLY
                                      and list_type != ListType.UNADDABLE))
        self.remove_button.set_property(
            'visible', (list_type != ListType.READONLY
                        and list_type != ListType.UNREMOVABLE))
        self.edit_button.set_property('visible',
                                      (list_type != ListType.READONLY
                                       and list_type != ListType.UNEDITABLE
                                       and list_type != ListType.REMOVEONLY))
        if list_type in [ListType.READONLY, ListType.REMOVEONLY]:
            padding = 0
        else:
            padding = 6
        self._set_child_packing(padding)
        self._list_type = list_type

    def clear(self):
        """Removes all the items in the list"""
        self.list.clear()

    # Callbacks

    def _on_list__selection_changed(self, list, selection):
        object_selected = selection is not None
        self.remove_button.set_sensitive(object_selected)
        self.edit_button.set_sensitive(object_selected)
        self.emit('selection-changed', selection)

    def _on_list__row_activated(self, list, item):
        if (self._list_type != ListType.READONLY
                and self._list_type != ListType.UNEDITABLE):
            self._edit_item(item)

    def _on_add_button__clicked(self, button):
        self._add_item()

    def _on_remove_button__clicked(self, button):
        self._remove_item(self.list.get_selected())

    def _on_edit_button__clicked(self, button):
        self._edit_item(self.list.get_selected())
Ejemplo n.º 5
0
class ListContainer(gtk.HBox):
    """A ListContainer is an L{ObjectList} with buttons to be able
    to modify the content of the list.
    Depending on the list_mode, @see L{set_list_mode} you will
    have add, remove and edit buttons.

    Signals
    =======
      - B{add-item} (returns item):
        - emitted when the add button is clicked, you're expected to
          return an object here
      - B{remove-item} (item, returns bool):
        - emitted when removing an item,
          you can block the removal from the list by returning False
      - B{edit-item} (item):
        - emitted when editing an item
          you can block the update afterwards by returning False

    @ivar add_button: add button
    @type add_button: L{gtk.Button}
    @ivar remove_button: remove button
    @type remove_button: L{gtk.Button}
    @ivar edit_button: edit button
    @type edit_button: L{gtk.Button}
    """

    gsignal('add-item', retval=object)
    gsignal('remove-item', object, retval=bool)
    gsignal('edit-item', object, retval=bool)
    gsignal('selection-changed', object)

    def __init__(self, columns, orientation=gtk.ORIENTATION_VERTICAL):
        """
        Create a new ListContainer object.
        @param columns: columns for the L{kiwi.ui.objectlist.ObjectList}
        @type columns: a list of L{kiwi.ui.objectlist.Columns}
        @param orientation: the position where the buttons will be
            placed: at the right (vertically) or at the bottom (horizontally)
            of the list. Defaults to the right of the list.
        @type: gtk.ORIENTATION_HORIZONTAL or gtk.ORIENTATION_VERTICAL
        """
        self._list_type = None

        gtk.HBox.__init__(self)

        self._orientation = orientation

        self._create_ui(columns)
        self.set_list_type(ListType.NORMAL)

    # Private API

    def _create_ui(self, columns):
        self.list = ObjectList(columns)
        self.list.connect('selection-changed',
                          self._on_list__selection_changed)
        self.list.connect('row-activated',
                          self._on_list__row_activated)

        self.add_button = gtk.Button(stock=gtk.STOCK_ADD)
        self.add_button.connect('clicked', self._on_add_button__clicked)

        self.remove_button = gtk.Button(stock=gtk.STOCK_REMOVE)
        self.remove_button.set_sensitive(False)
        self.remove_button.connect('clicked', self._on_remove_button__clicked)

        self.edit_button = gtk.Button(stock=gtk.STOCK_EDIT)
        self.edit_button.set_sensitive(False)
        self.edit_button.connect('clicked', self._on_edit_button__clicked)

        self._vbox = gtk.VBox(spacing=6)

        if self._orientation == gtk.ORIENTATION_VERTICAL:
            self.pack_start(self.list)
            self.list.show()
            self._add_buttons_to_box(self._vbox)
            self._pack_vbox()
        elif self._orientation == gtk.ORIENTATION_HORIZONTAL:
            self._vbox.pack_start(self.list)
            self.list.show()
            hbox = gtk.HBox(spacing=6)
            self._add_buttons_to_box(hbox)
            self._vbox.pack_start(hbox, expand=False)
            hbox.show()
            self._pack_vbox()
        else:
            raise TypeError(
                "buttons_orientation must be gtk.ORIENTATION_VERTICAL "
                " or gtk.ORIENTATION_HORIZONTAL")

    def _add_buttons_to_box(self, box):
        box.pack_start(self.add_button, expand=False)
        box.pack_start(self.remove_button, expand=False)
        box.pack_start(self.edit_button, expand=False)

    def _pack_vbox(self):
        self.pack_start(self._vbox, expand=False, padding=6)
        self._vbox.show()

    def _set_child_packing(self, padding):
        expand = self._orientation == gtk.ORIENTATION_HORIZONTAL

        self.set_child_packing(self._vbox, expand, True, padding,
                               gtk.PACK_START)

    def _add_item(self):
        retval = self.emit('add-item')
        if retval is None:
            return
        elif isinstance(retval, NotImplementedError):
            raise retval

        self.list.append(retval)

    def _remove_item(self, item):
        retval = self.emit('remove-item', item)
        if retval:
            self.list.remove(item)

    def _edit_item(self, item):
        retval = self.emit('edit-item', item)
        if retval:
            self.list.update(item)

    # Public API

    def add_item(self, item):
        """Appends an item to the list
        @param item: item to append
        """
        self.list.append(item)

    def add_items(self, items):
        """Appends a list of items to the list
        @param items: items to add
        @type items: a sequence of items
        """
        self.list.extend(items)

    def remove_item(self, item):
        """Removes an item from the list
        @param item: item to remove
        """
        self.list.remove(item)

    def update_item(self, item):
        """Updates an item in the list.
        You should call this if you change the object
        @param item: item to update
        """
        self.list.update(item)

    def default_remove(self, item):
        """Asks the user confirmation for removal of an item.
        @param item: a description of the item that will be removed
        @returns: True if the user confirm the removal, False otherwise
        """
        response = yesno(_('Do you want to remove %s ?') % (quote(str(item)),),
                         parent=None,
                         default=gtk.RESPONSE_OK,
                         buttons=((gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
                                  (gtk.STOCK_REMOVE, gtk.RESPONSE_OK)))
        return response == gtk.RESPONSE_OK

    def set_list_type(self, list_type):
        """Sets the kind of list type.
        @param list_type:
        """
        if not isinstance(list_type, ListType):
            raise TypeError("list_type must be a ListType enum")

        self.add_button.set_property(
            'visible',
            (list_type != ListType.READONLY and
             list_type != ListType.REMOVEONLY and
             list_type != ListType.UNADDABLE))
        self.remove_button.set_property(
            'visible',
            (list_type != ListType.READONLY and
             list_type != ListType.UNREMOVABLE))
        self.edit_button.set_property(
            'visible',
            (list_type != ListType.READONLY and
             list_type != ListType.UNEDITABLE and
             list_type != ListType.REMOVEONLY))
        if list_type in [ListType.READONLY, ListType.REMOVEONLY]:
            padding = 0
        else:
            padding = 6
        self._set_child_packing(padding)
        self._list_type = list_type

    def clear(self):
        """Removes all the items in the list"""
        self.list.clear()

    # Callbacks

    def _on_list__selection_changed(self, list, selection):
        object_selected = selection is not None
        self.remove_button.set_sensitive(object_selected)
        self.edit_button.set_sensitive(object_selected)
        self.emit('selection-changed', selection)

    def _on_list__row_activated(self, list, item):
        if (self._list_type != ListType.READONLY and
            self._list_type != ListType.UNEDITABLE):
            self._edit_item(item)

    def _on_add_button__clicked(self, button):
        self._add_item()

    def _on_remove_button__clicked(self, button):
        self._remove_item(self.list.get_selected())

    def _on_edit_button__clicked(self, button):
        self._edit_item(self.list.get_selected())
Ejemplo n.º 6
0
class ChecklistView(PidaView):
    
    key = 'checklist.view'

    icon_name = 'gtk-todo'
    label_text = _('Check list')

    def create_ui(self):
        self._vbox = gtk.VBox(spacing=3)
        self._vbox.set_border_width(3)
        self.create_toolbar()
        self.create_newitem()
        self.create_list()
        self.add_main_widget(self._vbox)
        self._vbox.show_all()

    def create_tab_label(self, icon_name, text):
        if None in [icon_name, text]:
            return None
        label = gtk.Label(text)
        b_factory = gtk.HBox
        b = b_factory(spacing=2)
        icon = gtk.image_new_from_stock(icon_name, gtk.ICON_SIZE_MENU)
        b.pack_start(icon)
        b.pack_start(label)
        b.show_all()
        return b

    def create_list(self):
        self._list = ObjectList([
                Column('done', title=_('Done'), data_type=bool, editable=True),
                Column('title', title=_('Title'), data_type=str,
                    editable=True, expand=True),
                Column('priority', title=_('Priority'),
                    data_type=ChecklistStatus, editable=True)
                ])
        self._list.connect('cell-edited', self._on_item_edit)
        self._list.connect('selection-changed', self._on_item_selected)
        self._list.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        self._vbox.add(self._list)

        self._sort_combo = AttrSortCombo(self._list,
            [
                ('done', _('Done')),
                ('title', _('Title')),
                ('priority', _('Priority')),
            ],
            'title')

        self._vbox.pack_start(self._sort_combo, expand=False)
        self._list.show_all()
        self._sort_combo.show_all()

    def create_newitem(self):
        self._hbox = gtk.HBox(spacing=3)
        self._newitem_title = gtk.Entry()
        self._newitem_title.connect('changed', self._on_newitem_changed)
        self._newitem_ok = gtk.Button(stock=gtk.STOCK_ADD)
        self._newitem_ok.connect('clicked', self._on_item_add)
        self._newitem_ok.set_sensitive(False)
        self._hbox.pack_start(self._newitem_title, expand=True)
        self._hbox.pack_start(self._newitem_ok, expand=False)
        self._vbox.pack_start(self._hbox, expand=False)
        self._hbox.show_all()

    def create_toolbar(self):
        self._uim = gtk.UIManager()
        self._uim.insert_action_group(self.svc.get_action_group(), 0)
        uim_data = pkgutil.get_data(__name__, 'uidef/checklist-toolbar.xml')
        self._uim.add_ui_from_string(uim_data)
        self._uim.ensure_update()
        self._toolbar = self._uim.get_toplevels('toolbar')[0]
        self._toolbar.set_style(gtk.TOOLBAR_ICONS)
        self._toolbar.set_icon_size(gtk.ICON_SIZE_SMALL_TOOLBAR)
        self._vbox.pack_start(self._toolbar, expand=False)
        self.svc.get_action('checklist_del').set_sensitive(False)
        self._toolbar.show_all()

    def add_item(self, item):
        self._list.append(item, select=True)
        self.svc.save()

    def update_item(self, item):
        self._list.update(item)
        self.svc.save()

    def remove_item(self, item):
        self._list.remove(item)
        self.svc.save()

    def clear(self):
        self._list.clear()

    def _on_item_selected(self, olist, item):
        self.svc.get_action('checklist_del').set_sensitive(item is not None)
        self.svc.set_current(item)

    def _on_item_edit(self, olist, item, value):
        self.svc.save()

    def _on_item_add(self, w):
        title = self._newitem_title.get_text()
        self.svc.add_item(ChecklistItem(title=title))
        self._newitem_title.set_text('')

    def _on_newitem_changed(self, w):
        self._newitem_ok.set_sensitive(self._newitem_title.get_text() != '')

    def can_be_closed(self):
        self.svc.get_action('show_checklist').set_active(False)
Ejemplo n.º 7
0
class DataTests(unittest.TestCase):
    """In all this tests we use the same configuration for a list"""
    def setUp(self):
        self.win = Gtk.Window()
        self.win.set_default_size(400, 400)
        self.list = ObjectList([Column('name'), Column('age')])
        self.win.add(self.list)
        refresh_gui()

    def tearDown(self):
        self.win.destroy()
        del self.win

    def testAddingOneInstance(self):
        # we should have two columns now
        self.assertEqual(2, len(self.list.get_columns()))

        person = Person('henrique', 21)
        self.list.append(person)

        refresh_gui()

        # usually you don't use the model directly, but tests are all about
        # breaking APIs, right?
        self.assertEqual(self.list[0], person)
        self.assertEqual(self.list[0].name, 'henrique')
        self.assertEqual(self.list[0].age, 21)

        # we still have to columns, right?
        self.assertEqual(2, len(self.list.get_columns()))

    def testAddingAObjectList(self):
        global persons

        self.list.add_list(persons)
        refresh_gui()

        self.assertEqual(len(self.list), len(persons))

    def testAddingABunchOfInstances(self):
        global persons

        for person in persons:
            self.list.append(person)
            refresh_gui()

        self.assertEqual(len(self.list), len(persons))

    def testRemovingOneInstance(self):
        global persons

        self.list.add_list(persons)
        refresh_gui()

        # we are going to remove Kiko
        person = persons[2]

        self.list.remove(person)

        self.assertEqual(len(self.list), len(persons) - 1)

        # now let's remove something that is not on the list
        #new_person = Person('Evandro', 24)
        #self.assertRaises(ValueError, self.list.remove, new_person)

        # note that even a new person with the same values as a person
        # in the list is not considered to be in the list
        #existing_person = Person('Gustavo', 25)
        #self.assertRaises(ValueError, self.list.remove,
        #                  existing_person)

    def testClearObjectList(self):
        global persons

        self.list.add_list(persons)
        refresh_gui()

        self.list.clear()

        self.assertEqual(len(self.list), 0)

    def testUpdatingOneInstance(self):
        global persons

        self.list.add_list(persons)
        refresh_gui()

        persons[0].age = 29
        self.list.update(persons[0])

        refresh_gui()

        # Do we have the same number of instances that we had before ?
        self.assertEqual(len(self.list), len(persons))

        # Trying to find our updated instance in the list
        self.assertEqual(self.list[0].age, 29)

        # let's be evil
        new_person = Person('Nando', 32)
        self.assertRaises(ValueError, self.list.update, new_person)

    def testContains(self):
        global persons

        self.list.add_list(persons)
        self.assertEqual(persons[0] in self.list, True)

        new_person = Person('Nando', 32)
        self.assertEqual(new_person in self.list, False)

    def testSelect(self):
        first = persons[0]
        self.list.add_list(persons)
        self.list.select(first)
        self.assertEqual(self.list.get_selected(), first)

        self.list.remove(first)
        self.assertRaises(ValueError, self.list.select, first)
Ejemplo n.º 8
0
class ListContainer(Gtk.Box):
    """A ListContainer is an :class:`ObjectList` with buttons to be able
    to modify the content of the list.
    Depending on the list_mode, @see :class:`set_list_mode` you will
    have add, remove and edit buttons.

    Signals
    =======
      - B{add-item} (returns item):
        - emitted when the add button is clicked, you're expected to
          return an object here
      - B{remove-item} (item, returns bool):
        - emitted when removing an item,
          you can block the removal from the list by returning False
      - B{edit-item} (item):
        - emitted when editing an item
          you can block the update afterwards by returning False

    :ivar add_button: add button
    :type add_button: :class:`Gtk.Button`
    :ivar remove_button: remove button
    :type remove_button: :class:`Gtk.Button`
    :ivar edit_button: edit button
    :type edit_button: :class:`Gtk.Button`
    """

    __gtype_name__ = 'ListContainer'
    gsignal('add-item', retval=object)
    gsignal('remove-item', object, retval=bool)
    gsignal('edit-item', object, retval=bool)
    gsignal('selection-changed', object)

    def __init__(self, columns, orientation=Gtk.Orientation.VERTICAL):
        """
        Create a new ListContainer object.
        :param columns: columns for the :class:`kiwi.ui.objectlist.ObjectList`
        :type columns: a list of :class:`kiwi.ui.objectlist.Columns`
        :param orientation: the position where the buttons will be
            placed: at the right (vertically) or at the bottom (horizontally)
            of the list. Defaults to the right of the list.
        :type: Gtk.Orientation.HORIZONTAL or Gtk.Orientation.VERTICAL
        """
        self._list_type = None

        super(ListContainer, self).__init__(orientation=Gtk.Orientation.HORIZONTAL)

        self._orientation = orientation

        self._create_ui(columns)
        self.set_list_type(ListType.NORMAL)

    # Private API

    def _create_ui(self, columns):
        self.list = ObjectList(columns)
        self.list.connect('selection-changed',
                          self._on_list__selection_changed)
        self.list.connect('row-activated',
                          self._on_list__row_activated)

        self.add_button = Gtk.Button(stock=Gtk.STOCK_ADD)
        self.add_button.connect('clicked', self._on_add_button__clicked)

        self.remove_button = Gtk.Button(stock=Gtk.STOCK_REMOVE)
        self.remove_button.set_sensitive(False)
        self.remove_button.connect('clicked', self._on_remove_button__clicked)

        self.edit_button = Gtk.Button(stock=Gtk.STOCK_EDIT)
        self.edit_button.set_sensitive(False)
        self.edit_button.connect('clicked', self._on_edit_button__clicked)

        self._vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)

        if self._orientation == Gtk.Orientation.VERTICAL:
            self.pack_start(self.list, True, True, 0)
            self.list.show()
            self._add_buttons_to_box(self._vbox)
            self._pack_vbox()
        elif self._orientation == Gtk.Orientation.HORIZONTAL:
            self._vbox.pack_start(self.list, True, True, 0)
            self.list.show()
            hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
            self._add_buttons_to_box(hbox)
            self._vbox.pack_start(hbox, False, True, 0)
            hbox.show()
            self._pack_vbox()
        else:
            raise TypeError(
                "buttons_orientation must be Gtk.Orientation.VERTICAL "
                " or Gtk.Orientation.HORIZONTAL")

    def _add_buttons_to_box(self, box):
        box.pack_start(self.add_button, False, True, 0)
        box.pack_start(self.remove_button, False, True, 0)
        box.pack_start(self.edit_button, False, True, 0)

    def _pack_vbox(self):
        self.pack_start(self._vbox, False, True, 6)
        self._vbox.show()

    def _set_child_packing(self, padding):
        expand = self._orientation == Gtk.Orientation.HORIZONTAL

        self.set_child_packing(self._vbox, expand, True, padding,
                               Gtk.PackType.START)

    def _add_item(self):
        retval = self.emit('add-item')
        if retval is None:
            return
        elif isinstance(retval, NotImplementedError):
            raise retval

        self.list.append(retval)
        self.list.refresh()

    def _remove_item(self, item):
        retval = self.emit('remove-item', item)
        if retval:
            self.list.remove(item)

    def _edit_item(self, item):
        retval = self.emit('edit-item', item)
        if retval:
            self.list.update(item)

    # Public API

    def add_item(self, item):
        """Appends an item to the list
        :param item: item to append
        """
        self.list.append(item)

    def add_items(self, items):
        """Appends a list of items to the list
        :param items: items to add
        :type items: a sequence of items
        """
        self.list.extend(items)

    def remove_item(self, item):
        """Removes an item from the list
        :param item: item to remove
        """
        self.list.remove(item)

    def update_item(self, item):
        """Updates an item in the list.
        You should call this if you change the object
        :param item: item to update
        """
        self.list.update(item)

    def default_remove(self, item):
        """Asks the user confirmation for removal of an item.
        :param item: a description of the item that will be removed
        :returns: True if the user confirm the removal, False otherwise
        """
        response = yesno(_('Do you want to remove %s ?') %
                        (GLib.markup_escape_text(str(item)),),
                         parent=None,
                         default=Gtk.ResponseType.OK,
                         buttons=((Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL),
                                  (Gtk.STOCK_REMOVE, Gtk.ResponseType.OK)))
        return response == Gtk.ResponseType.OK

    def set_list_type(self, list_type):
        """Sets the kind of list type.
        :param list_type:
        """
        if not isinstance(list_type, ListType):
            raise TypeError("list_type must be a ListType enum")

        self.add_button.set_property(
            'visible',
            list_type not in [ListType.READONLY, ListType.REMOVEONLY,
                              ListType.UNADDABLE])
        self.remove_button.set_property(
            'visible',
            list_type not in [ListType.READONLY, ListType.ADDONLY,
                              ListType.UNREMOVABLE])
        self.edit_button.set_property(
            'visible',
            list_type not in [ListType.READONLY, ListType.ADDONLY,
                              ListType.UNEDITABLE, ListType.REMOVEONLY])
        if list_type in [ListType.READONLY, ListType.REMOVEONLY]:
            padding = 0
        else:
            padding = 6
        self._set_child_packing(padding)
        self._list_type = list_type

    def clear(self):
        """Removes all the items in the list"""
        self.list.clear()

    # Callbacks

    def _on_list__selection_changed(self, list, selection):
        object_selected = selection is not None
        self.remove_button.set_sensitive(object_selected)
        self.edit_button.set_sensitive(object_selected)
        self.emit('selection-changed', selection)

    def _on_list__row_activated(self, list, item):
        if self._list_type not in [ListType.READONLY, ListType.ADDONLY,
                                   ListType.UNEDITABLE]:
            self._edit_item(item)

    def _on_add_button__clicked(self, button):
        self._add_item()

    def _on_remove_button__clicked(self, button):
        self._remove_item(self.list.get_selected())

    def _on_edit_button__clicked(self, button):
        self._edit_item(self.list.get_selected())
Ejemplo n.º 9
0
class ChecklistView(PidaView):

    key = 'checklist.view'

    icon_name = 'gtk-todo'
    label_text = _('Check list')

    def create_ui(self):
        self._vbox = gtk.VBox(spacing=3)
        self._vbox.set_border_width(3)
        self.create_toolbar()
        self.create_newitem()
        self.create_list()
        self.add_main_widget(self._vbox)
        self._vbox.show_all()

    def create_tab_label(self, icon_name, text):
        if None in [icon_name, text]:
            return None
        label = gtk.Label(text)
        b_factory = gtk.HBox
        b = b_factory(spacing=2)
        icon = gtk.image_new_from_stock(icon_name, gtk.ICON_SIZE_MENU)
        b.pack_start(icon)
        b.pack_start(label)
        b.show_all()
        return b

    def create_list(self):
        self._list = ObjectList([
            Column('done', title=_('Done'), data_type=bool, editable=True),
            Column('title',
                   title=_('Title'),
                   data_type=str,
                   editable=True,
                   expand=True),
            Column('priority',
                   title=_('Priority'),
                   data_type=ChecklistStatus,
                   editable=True)
        ])
        self._list.connect('cell-edited', self._on_item_edit)
        self._list.connect('selection-changed', self._on_item_selected)
        self._list.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        self._vbox.add(self._list)

        self._sort_combo = AttrSortCombo(self._list, [
            ('done', _('Done')),
            ('title', _('Title')),
            ('priority', _('Priority')),
        ], 'title')

        self._vbox.pack_start(self._sort_combo, expand=False)
        self._list.show_all()
        self._sort_combo.show_all()

    def create_newitem(self):
        self._hbox = gtk.HBox(spacing=3)
        self._newitem_title = gtk.Entry()
        self._newitem_title.connect('changed', self._on_newitem_changed)
        self._newitem_ok = gtk.Button(stock=gtk.STOCK_ADD)
        self._newitem_ok.connect('clicked', self._on_item_add)
        self._newitem_ok.set_sensitive(False)
        self._hbox.pack_start(self._newitem_title, expand=True)
        self._hbox.pack_start(self._newitem_ok, expand=False)
        self._vbox.pack_start(self._hbox, expand=False)
        self._hbox.show_all()

    def create_toolbar(self):
        self._uim = gtk.UIManager()
        self._uim.insert_action_group(self.svc.get_action_group(), 0)
        uim_data = pkgutil.get_data(__name__, 'uidef/checklist-toolbar.xml')
        self._uim.add_ui_from_string(uim_data)
        self._uim.ensure_update()
        self._toolbar = self._uim.get_toplevels('toolbar')[0]
        self._toolbar.set_style(gtk.TOOLBAR_ICONS)
        self._toolbar.set_icon_size(gtk.ICON_SIZE_SMALL_TOOLBAR)
        self._vbox.pack_start(self._toolbar, expand=False)
        self.svc.get_action('checklist_del').set_sensitive(False)
        self._toolbar.show_all()

    def add_item(self, item):
        self._list.append(item, select=True)
        self.svc.save()

    def update_item(self, item):
        self._list.update(item)
        self.svc.save()

    def remove_item(self, item):
        self._list.remove(item)
        self.svc.save()

    def clear(self):
        self._list.clear()

    def _on_item_selected(self, olist, item):
        self.svc.get_action('checklist_del').set_sensitive(item is not None)
        self.svc.set_current(item)

    def _on_item_edit(self, olist, item, value):
        self.svc.save()

    def _on_item_add(self, w):
        title = self._newitem_title.get_text()
        self.svc.add_item(ChecklistItem(title=title))
        self._newitem_title.set_text('')

    def _on_newitem_changed(self, w):
        self._newitem_ok.set_sensitive(self._newitem_title.get_text() != '')

    def can_be_closed(self):
        self.svc.get_action('show_checklist').set_active(False)
Ejemplo n.º 10
0
class ListContainer(Gtk.Box):
    """A ListContainer is an :class:`ObjectList` with buttons to be able
    to modify the content of the list.
    Depending on the list_mode, @see :class:`set_list_mode` you will
    have add, remove and edit buttons.

    Signals
    =======
      - B{add-item} (returns item):
        - emitted when the add button is clicked, you're expected to
          return an object here
      - B{remove-item} (item, returns bool):
        - emitted when removing an item,
          you can block the removal from the list by returning False
      - B{edit-item} (item):
        - emitted when editing an item
          you can block the update afterwards by returning False

    :ivar add_button: add button
    :type add_button: :class:`Gtk.Button`
    :ivar remove_button: remove button
    :type remove_button: :class:`Gtk.Button`
    :ivar edit_button: edit button
    :type edit_button: :class:`Gtk.Button`
    """

    __gtype_name__ = 'ListContainer'
    gsignal('add-item', retval=object)
    gsignal('remove-item', object, retval=bool)
    gsignal('edit-item', object, retval=bool)
    gsignal('selection-changed', object)

    def __init__(self, columns, orientation=Gtk.Orientation.VERTICAL):
        """
        Create a new ListContainer object.
        :param columns: columns for the :class:`kiwi.ui.objectlist.ObjectList`
        :type columns: a list of :class:`kiwi.ui.objectlist.Columns`
        :param orientation: the position where the buttons will be
            placed: at the right (vertically) or at the bottom (horizontally)
            of the list. Defaults to the right of the list.
        :type: Gtk.Orientation.HORIZONTAL or Gtk.Orientation.VERTICAL
        """
        self._list_type = None

        super(ListContainer,
              self).__init__(orientation=Gtk.Orientation.HORIZONTAL)

        self._orientation = orientation

        self._create_ui(columns)
        self.set_list_type(ListType.NORMAL)

    # Private API

    def _create_ui(self, columns):
        self.list = ObjectList(columns)
        self.list.connect('selection-changed',
                          self._on_list__selection_changed)
        self.list.connect('row-activated', self._on_list__row_activated)

        self.add_button = Gtk.Button(stock=Gtk.STOCK_ADD)
        self.add_button.connect('clicked', self._on_add_button__clicked)

        self.remove_button = Gtk.Button(stock=Gtk.STOCK_REMOVE)
        self.remove_button.set_sensitive(False)
        self.remove_button.connect('clicked', self._on_remove_button__clicked)

        self.edit_button = Gtk.Button(stock=Gtk.STOCK_EDIT)
        self.edit_button.set_sensitive(False)
        self.edit_button.connect('clicked', self._on_edit_button__clicked)

        self._vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)

        if self._orientation == Gtk.Orientation.VERTICAL:
            self.pack_start(self.list, True, True, 0)
            self.list.show()
            self._add_buttons_to_box(self._vbox)
            self._pack_vbox()
        elif self._orientation == Gtk.Orientation.HORIZONTAL:
            self._vbox.pack_start(self.list, True, True, 0)
            self.list.show()
            hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
            self._add_buttons_to_box(hbox)
            self._vbox.pack_start(hbox, False, True, 0)
            hbox.show()
            self._pack_vbox()
        else:
            raise TypeError(
                "buttons_orientation must be Gtk.Orientation.VERTICAL "
                " or Gtk.Orientation.HORIZONTAL")

    def _add_buttons_to_box(self, box):
        box.pack_start(self.add_button, False, True, 0)
        box.pack_start(self.remove_button, False, True, 0)
        box.pack_start(self.edit_button, False, True, 0)

    def _pack_vbox(self):
        self.pack_start(self._vbox, False, True, 6)
        self._vbox.show()

    def _set_child_packing(self, padding):
        expand = self._orientation == Gtk.Orientation.HORIZONTAL

        self.set_child_packing(self._vbox, expand, True, padding,
                               Gtk.PackType.START)

    def _add_item(self):
        retval = self.emit('add-item')
        if retval is None:
            return
        elif isinstance(retval, NotImplementedError):
            raise retval

        self.list.append(retval)
        self.list.refresh()

    def _remove_item(self, item):
        retval = self.emit('remove-item', item)
        if retval:
            self.list.remove(item)

    def _edit_item(self, item):
        retval = self.emit('edit-item', item)
        if retval:
            self.list.update(item)

    # Public API

    def add_item(self, item):
        """Appends an item to the list
        :param item: item to append
        """
        self.list.append(item)

    def add_items(self, items):
        """Appends a list of items to the list
        :param items: items to add
        :type items: a sequence of items
        """
        self.list.extend(items)

    def remove_item(self, item):
        """Removes an item from the list
        :param item: item to remove
        """
        self.list.remove(item)

    def update_item(self, item):
        """Updates an item in the list.
        You should call this if you change the object
        :param item: item to update
        """
        self.list.update(item)

    def default_remove(self, item):
        """Asks the user confirmation for removal of an item.
        :param item: a description of the item that will be removed
        :returns: True if the user confirm the removal, False otherwise
        """
        response = yesno(_('Do you want to remove %s ?') %
                         (GLib.markup_escape_text(str(item)), ),
                         parent=None,
                         default=Gtk.ResponseType.OK,
                         buttons=((Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL),
                                  (Gtk.STOCK_REMOVE, Gtk.ResponseType.OK)))
        return response == Gtk.ResponseType.OK

    def set_list_type(self, list_type):
        """Sets the kind of list type.
        :param list_type:
        """
        if not isinstance(list_type, ListType):
            raise TypeError("list_type must be a ListType enum")

        self.add_button.set_property(
            'visible', list_type not in [
                ListType.READONLY, ListType.REMOVEONLY, ListType.UNADDABLE
            ])
        self.remove_button.set_property(
            'visible', list_type
            not in [ListType.READONLY, ListType.ADDONLY, ListType.UNREMOVABLE])
        self.edit_button.set_property(
            'visible', list_type not in [
                ListType.READONLY, ListType.ADDONLY, ListType.UNEDITABLE,
                ListType.REMOVEONLY
            ])
        if list_type in [ListType.READONLY, ListType.REMOVEONLY]:
            padding = 0
        else:
            padding = 6
        self._set_child_packing(padding)
        self._list_type = list_type

    def clear(self):
        """Removes all the items in the list"""
        self.list.clear()

    # Callbacks

    def _on_list__selection_changed(self, list, selection):
        object_selected = selection is not None
        self.remove_button.set_sensitive(object_selected)
        self.edit_button.set_sensitive(object_selected)
        self.emit('selection-changed', selection)

    def _on_list__row_activated(self, list, item):
        if self._list_type not in [
                ListType.READONLY, ListType.ADDONLY, ListType.UNEDITABLE
        ]:
            self._edit_item(item)

    def _on_add_button__clicked(self, button):
        self._add_item()

    def _on_remove_button__clicked(self, button):
        self._remove_item(self.list.get_selected())

    def _on_edit_button__clicked(self, button):
        self._edit_item(self.list.get_selected())