[postr] Added tag autocomplete (#507242)



commit 9c6d50ad4b2da243683a3ceb714cbcfffcf02f56
Author: Francisco Rojas <frojas alumnos utalca cl>
Date:   Mon Dec 21 18:22:30 2009 -0300

    Added tag autocomplete (#507242)
    
    Use the 200 most popular tags of the user and the 20 hottest
    tag of the day to autocomplete the tag field.
    
    Signed-off-by: Germán Póo-Caamaño <gpoo gnome org>

 src/TagsEntry.py |  112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/postr.glade  |   23 +----------
 src/postr.py     |   10 ++++-
 3 files changed, 124 insertions(+), 21 deletions(-)
---
diff --git a/src/TagsEntry.py b/src/TagsEntry.py
new file mode 100644
index 0000000..9fa4fd0
--- /dev/null
+++ b/src/TagsEntry.py
@@ -0,0 +1,112 @@
+# Postr, a Flickr Uploader
+#
+# Copyright (C) 2009 Francisco Rojas <frojas alumnos utalca cl>
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
+# St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import gtk
+
+_USER_POPULAR_TAGS = 200
+_HOTS_TAGS = 20
+_COL_TAG_NAME = 0
+
+class TagsEntry(gtk.Entry):
+    def __init__(self, flickr):
+        gtk.Entry.__init__(self)
+
+        self.flickr = flickr
+
+        # Create the completion object
+        self.completion = gtk.EntryCompletion()
+        self.completion.set_match_func(self.__match_func, None)
+        self.completion.connect('match-selected', self.on_completion_match)
+
+        # Assign the completion to the entry
+        self.set_completion(self.completion)
+
+        # Use model column _COL_TAG_NAME as the text column
+        self.completion.set_text_column(_COL_TAG_NAME)
+
+        self.completion.set_minimum_key_length(1)
+
+
+        self.completion_model = gtk.ListStore(str)
+
+        self.show_all()
+
+    def on_completion_match(self, completion, model, iter):
+        current_text = self.get_text()
+        # if more than a word has been typed, we throw away the
+        # last one because we want to replace it with the matching word
+        # note: the user may have typed only a part of the entire word
+        #       and so this step is necessary
+        if ' ' in current_text:
+            current_text = ' '.join(current_text.split(' ')[:-1])
+            # add the matching word
+            current_text = '%s %s ' % (current_text, model[iter][_COL_TAG_NAME])
+        else:
+            current_text = model[iter][_COL_TAG_NAME] +' '
+
+        # set back the whole text
+        self.set_text(current_text)
+        # move the cursor at the end
+        self.set_position(-1)
+
+        return True
+
+
+    def __match_func(self, completion, key_string, iter, data):
+        model = completion.get_model()
+        # get the completion strings
+        modelstr = model[iter][_COL_TAG_NAME]
+        # check if the user has typed in a space char,
+        # get the last word and check if it matches something
+        if ' ' in key_string:
+            last_word = key_string.split(' ')[-1].strip()
+            if last_word == '':
+                return False
+            else:
+                return modelstr.lower().startswith(last_word.lower())
+        # we have only one word typed
+        return modelstr.lower().startswith(key_string.lower())
+
+    def update(self):
+
+        self.completion_model.clear()
+
+        self.flickr.tags_getListUserPopular(user_id=self.flickr.get_nsid(), \
+        count=_USER_POPULAR_TAGS).addCallbacks(self.create_completion_model,
+        self.twisted_error)
+
+        self.flickr.tags_getHotList(user_id=self.flickr.get_nsid(), count=_HOTS_TAGS)\
+        .addCallbacks(self.create_completion_model, self.twisted_error)
+
+    def create_completion_model(self, rsp):
+        '''
+            Creates a tree model containing the completions.
+        '''
+
+        for tag in rsp.getiterator('tag'):
+            self.completion_model.set(self.completion_model.append(),
+                                    _COL_TAG_NAME,
+                                    tag.text)
+
+        self.completion.set_model(self.completion_model)
+
+    def twisted_error(self, failure):
+        #TODO: throw a message in a less invasive way
+        from ErrorDialog import ErrorDialog
+        dialog = ErrorDialog()
+        dialog.set_from_failure(failure)
+        dialog.show_all()
diff --git a/src/postr.glade b/src/postr.glade
index ccf4a7e..c29f42b 100644
--- a/src/postr.glade
+++ b/src/postr.glade
@@ -654,14 +654,15 @@
                   </packing>
                 </child>
                 <child>
-                  <widget class="GtkEntry" id="tags_entry">
+                  <widget class="Custom" id="tags_entry">
                     <property name="visible">True</property>
                     <property name="sensitive">False</property>
                     <property name="can_focus">True</property>
+                    <property name="creation_function">tag_entry_new</property>
                   </widget>
                   <packing>
                     <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
+                    <property name="right_attach">3</property>
                     <property name="top_attach">3</property>
                     <property name="bottom_attach">4</property>
                     <property name="y_options"></property>
@@ -682,24 +683,6 @@
                   </packing>
                 </child>
                 <child>
-                  <widget class="GtkButton" id="tags_button">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="label" translatable="yes">...</property>
-                    <property name="relief">GTK_RELIEF_HALF</property>
-                    <property name="use_underline">True</property>
-                    <property name="response_id">0</property>
-                  </widget>
-                  <packing>
-                    <property name="left_attach">2</property>
-                    <property name="right_attach">3</property>
-                    <property name="top_attach">3</property>
-                    <property name="bottom_attach">4</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
                   <widget class="GtkLabel" id="set_label">
                     <property name="visible">True</property>
                     <property name="xalign">0</property>
diff --git a/src/postr.py b/src/postr.py
index de292f7..afbf28f 100644
--- a/src/postr.py
+++ b/src/postr.py
@@ -262,7 +262,11 @@ class Postr(UniqueApp):
         bar = StatusBar.StatusBar(self.flickr)
         bar.show()
         return bar
-    
+    def tag_entry_new(self, *args):
+        import TagsEntry
+        entry = TagsEntry.TagsEntry(self.flickr)
+        return entry
+
     def on_message(self, app, command, command_data, startup_id, screen, workspace):
         """Callback from UniqueApp, when a message arrives."""
         if command == gtkunique.OPEN:
@@ -299,6 +303,7 @@ class Postr(UniqueApp):
             self.set_combo.update()
             self.license_combo.update()
             self.update_avatar()
+            self.update_tag_list()
 
     def on_statusbar_box_expose(self, widget, event):
         """
@@ -1289,3 +1294,6 @@ class Postr(UniqueApp):
             self._set_value_in_model(ImageStore.COL_SAFETY, safety_iter, [index])
         self._set_value_in_model(ImageStore.COL_VISIBLE, visible, [index])
 
+    def update_tag_list(self):
+        self.tags_entry.update()
+



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]