Hello community,

here is the log from the commit of package syncthing-gtk for openSUSE:Factory 
checked in at 2015-11-08 11:26:42
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/syncthing-gtk (Old)
 and      /work/SRC/openSUSE:Factory/.syncthing-gtk.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "syncthing-gtk"

Changes:
--------
--- /work/SRC/openSUSE:Factory/syncthing-gtk/syncthing-gtk.changes      
2015-10-14 16:45:10.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.syncthing-gtk.new/syncthing-gtk.changes 
2015-11-08 11:26:52.000000000 +0100
@@ -1,0 +2,7 @@
+Thu Nov  5 20:43:01 UTC 2015 - sor.ale...@meowr.ru
+
+- Update to 0.8:
+  * Syncthing 0.12 and above API.
+  * No 'ignore' button on Unknown device message.
+
+-------------------------------------------------------------------

Old:
----
  syncthing-gtk-0.7.6.1.tar.gz

New:
----
  syncthing-gtk-0.8.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ syncthing-gtk.spec ++++++
--- /var/tmp/diff_new_pack.d4lySk/_old  2015-11-08 11:26:53.000000000 +0100
+++ /var/tmp/diff_new_pack.d4lySk/_new  2015-11-08 11:26:53.000000000 +0100
@@ -16,10 +16,10 @@
 #
 
 
-%global __requires_exclude 
typelib\\(Caja\\)|typelib\\(Nautilus\\)|typelib\\(Nemo\\)
+%global __requires_exclude typelib\\((Caja|Nautilus|Nemo)\\)
 %define _name   syncthing_gtk
 Name:           syncthing-gtk
-Version:        0.7.6.1
+Version:        0.8
 Release:        0
 Summary:        Syncthing Gtk-based graphical interface
 License:        GPL-2.0+
@@ -36,7 +36,7 @@
 Requires:       python-dateutil
 Requires:       python-gobject
 Requires:       python-gobject-cairo
-Requires:       syncthing >= 0.11
+Requires:       syncthing >= 0.12
 Recommends:     libnotify
 Recommends:     librsvg
 Recommends:     python-pyinotify

++++++ syncthing-gtk-0.7.6.1.tar.gz -> syncthing-gtk-0.8.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/syncthing-gtk-0.7.6.1/README.md 
new/syncthing-gtk-0.8/README.md
--- old/syncthing-gtk-0.7.6.1/README.md 2015-10-07 10:04:07.000000000 +0200
+++ new/syncthing-gtk-0.8/README.md     2015-11-05 18:16:32.000000000 +0100
@@ -22,12 +22,11 @@
 
 Dependencies:
 - python 2.7, GTK 3.8 or newer and 
[PyGObject](https://live.gnome.org/PyGObject)
-- [python-gi-cairo](https://packages.debian.org/sid/python-gi-cairo) on debian 
based distros (included in PyGObject elsewhere)
-- [gir1.2-rsvg-2.0](https://packages.debian.org/sid/gir1.2-rsvg-2.0) on debian 
based distros (included in PyGObject elsewhere)
+- [python-gi-cairo](https://packages.debian.org/sid/python-gi-cairo) and 
[gir1.2-rsvg-2.0](https://packages.debian.org/sid/gir1.2-rsvg-2.0) on debian 
based distros (included in PyGObject elsewhere)
 - [python-dateutil](http://labix.org/python-dateutil) (Python 2 version)
 - [setuptools](https://pypi.python.org/pypi/setuptools)
 - [psmisc](http://psmisc.sourceforge.net) (for the `killall` command)
-- [Syncthing][syncthing] v0.11 or newer
+- [Syncthing][syncthing] v0.12 or newer
 
 Optional Dependencies:
 - [pyinotify](https://github.com/seb-m/pyinotify/wiki) for instant 
synchronization.
@@ -36,8 +35,9 @@
 
 Packages:
 - Ubuntu (deb-based distros): in [Web Upd8 
PPA](https://launchpad.net/~nilarimogard/+archive/ubuntu/webupd8/) (thanks!) or 
[DEBs](http://ppa.launchpad.net/nilarimogard/webupd8/ubuntu/pool/main/s/syncthing-gtk/)
-- SUSE, Fedora (rpm-based distros): in [OpenSUSE Build 
Service](http://software.opensuse.org/download.html?project=home%3Akozec&package=syncthing-gtk).
 You can install [Syncthing 
Package](http://software.opensuse.org/package/syncthing) first.
 - Arch Linux: In [[community] 
repository](https://www.archlinux.org/packages/community/any/syncthing-gtk/)
+- Fedora: [in decathorpe's copr 
repository](https://copr.fedoraproject.org/coprs/decathorpe/syncthing/)
+- SUSE (and other rpm-based distros): in [OpenSUSE Build 
Service](http://software.opensuse.org/download.html?project=home%3Akozec&package=syncthing-gtk).
 - Windows: Get [latest installer from 
here](https://github.com/kozec/syncthing-gui/releases/latest), or use [the 
Chocolatey package](https://chocolatey.org/packages/syncthing-gtk).
 - Or, in worst case scenario, download [latest 
tarball](https://github.com/kozec/syncthing-gui/releases/latest), extract it 
and run syncthing-gtk.py.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/syncthing-gtk-0.7.6.1/app.glade 
new/syncthing-gtk-0.8/app.glade
--- old/syncthing-gtk-0.7.6.1/app.glade 2015-10-07 10:04:07.000000000 +0200
+++ new/syncthing-gtk-0.8/app.glade     2015-11-05 18:16:32.000000000 +0100
@@ -594,6 +594,29 @@
                </object>
        </child>
        <child>
+               <object class="GtkImageMenuItem" id="menu-popup-pause-device">
+                       <property name="visible">True</property>
+                       <property name="can_focus">False</property>
+                       <property name="label" 
translatable="yes">gtk-media-pause</property>
+                       <property name="use_underline">True</property>
+                       <property name="use_stock">True</property>
+                       <property name="always_show_image">True</property>
+                       <signal name="activate" 
handler="cb_menu_popup_pause_device" swapped="no"/>
+               </object>
+       </child>
+       <child>
+               <object class="GtkImageMenuItem" id="menu-popup-resume-device">
+                       <property name="visible">True</property>
+                       <property name="can_focus">False</property>
+                       <property name="label" 
translatable="yes">Resume</property>
+                       <property 
name="image">menu-popup-resume-image</property>
+                       <property name="use_underline">True</property>
+                       <property name="use_stock">True</property>
+                       <property name="always_show_image">True</property>
+                       <signal name="activate" 
handler="cb_menu_popup_resume_device" swapped="no"/>
+               </object>
+       </child>
+       <child>
                <object class="GtkImageMenuItem" id="menu-popup-delete-device">
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
@@ -988,6 +1011,13 @@
        <property name="can_focus">False</property>
        <property name="icon-name">folder-open</property>
 </object>
+
+<object class="GtkImage" id="menu-popup-resume-image">
+       <property name="visible">True</property>
+       <property name="can_focus">False</property>
+       <property name="icon-name">gtk-media-play</property>
+</object>
+
 <!-- /Popup menu icon images -->
 
 </interface>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/syncthing-gtk-0.7.6.1/syncthing_gtk/app.py 
new/syncthing-gtk-0.8/syncthing_gtk/app.py
--- old/syncthing-gtk-0.7.6.1/syncthing_gtk/app.py      2015-10-07 
10:04:07.000000000 +0200
+++ new/syncthing-gtk-0.8/syncthing_gtk/app.py  2015-11-05 18:16:32.000000000 
+0100
@@ -15,9 +15,9 @@
 log = logging.getLogger("App")
 
 # Internal version used by updater (if enabled)
-INTERNAL_VERSION               = "v0.7"
+INTERNAL_VERSION               = "v0.8"
 # Minimal Syncthing version supported by App
-MIN_ST_VERSION                 = "0.11.0"
+MIN_ST_VERSION                 = "0.12.0"
 
 COLOR_DEVICE                   = "#707070"                                     
# Dark-gray
 COLOR_DEVICE_SYNCING   = "#2A89C8"                                     # Blue
@@ -37,6 +37,7 @@
 RESPONSE_RESTART               = 256
 RESPONSE_FIX_FOLDER_ID = 257
 RESPONSE_FIX_NEW_DEVICE        = 258
+RESPONSE_FIX_IGNORE            = 259
 RESPONSE_QUIT                  = 260
 RESPONSE_START_DAEMON  = 271
 RESPONSE_SLAIN_DAEMON  = 272
@@ -346,6 +347,8 @@
                self.daemon.connect("last-seen-changed", 
self.cb_syncthing_last_seen_changed)
                self.daemon.connect("device-connected", 
self.cb_syncthing_device_state_changed, True)
                self.daemon.connect("device-disconnected", 
self.cb_syncthing_device_state_changed, False)
+               self.daemon.connect("device-paused", 
self.cb_syncthing_device_paused_resumed, True)
+               self.daemon.connect("device-resumed", 
self.cb_syncthing_device_paused_resumed, False)
                self.daemon.connect("device-sync-started", 
self.cb_syncthing_device_sync_progress)
                self.daemon.connect("device-sync-progress", 
self.cb_syncthing_device_sync_progress)
                self.daemon.connect("device-sync-finished", 
self.cb_syncthing_device_sync_progress, 1.0)
@@ -356,6 +359,7 @@
                self.daemon.connect("folder-sync-progress", 
self.cb_syncthing_folder_state_changed, COLOR_FOLDER_SYNCING, _("Syncing"))
                self.daemon.connect("folder-sync-finished", 
self.cb_syncthing_folder_up_to_date)
                self.daemon.connect("folder-scan-started", 
self.cb_syncthing_folder_state_changed, 1.0, COLOR_FOLDER_SCANNING, 
_("Scanning"))
+               self.daemon.connect("folder-scan-progress", 
self.cb_syncthing_folder_state_changed, COLOR_FOLDER_SCANNING, _("Scanning"))
                self.daemon.connect("folder-scan-finished", 
self.cb_syncthing_folder_up_to_date)
                self.daemon.connect("folder-stopped", 
self.cb_syncthing_folder_stopped) 
                self.daemon.connect("system-data-updated", 
self.cb_syncthing_system_data)
@@ -640,7 +644,7 @@
                                        else:
                                                self.display_run_daemon_dialog()
                        self.set_status(False)
-               elif reason == Daemon.OLD_VERSION and 
self.config["st_autoupdate"] and not self.process and not StDownloader is None:
+               elif reason == Daemon.OLD_VERSION and 
self.config["st_autoupdate"] and not self.process is None and not StDownloader 
is None:
                        # Daemon is too old, but autoupdater is enabled and I 
have control of deamon.
                        # Try to update.
                        from configuration import LONG_AGO
@@ -790,6 +794,7 @@
                r = RIBar("", Gtk.MessageType.WARNING,)
                r.get_label().set_markup(markup)
                r.add_button(RIBar.build_button(_("_Add")), 
RESPONSE_FIX_NEW_DEVICE)
+               r.add_button(RIBar.build_button(_("_Ignore")), 
RESPONSE_FIX_IGNORE)
                self.show_error_box(r, {"nid" : nid, "address" : address} )
        
        def cb_syncthing_my_id_changed(self, daemon, device_id):
@@ -871,6 +876,19 @@
                                dtf = dt.strftime("%Y-%m-%d %H:%M")
                                device['last-seen'] = str(dtf)
        
+       def cb_syncthing_device_paused_resumed(self, daemon, nid, paused):
+               if nid in self.devices: # Should be always
+                       device = self.devices[nid]
+                       device.set_status(_("Paused") if paused else 
_("Disconnected"))
+                       device.set_color_hex(COLOR_DEVICE_OFFLINE)
+                       device["online"] = False
+                       device["connected"] = False
+                       # Update visible values
+                       device.hide_values("sync", "inbps", "outbps", "version")
+                       device.show_values("last-seen")
+               self.update_folders()
+               self.set_status(True)
+       
        def cb_syncthing_device_state_changed(self, daemon, nid, connected):
                if nid in self.devices: # Should be always
                        device = self.devices[nid]
@@ -1379,9 +1397,11 @@
                                GLib.timeout_add_seconds(1, self.watcher.start)
                self.daemon.reload_config(callback)
        
-       def change_setting_n_restart(self, setting_name, value, 
retry_on_error=False):
+       def change_setting_async(self, setting_name, value, 
retry_on_error=False, restart=True):
                """
-               Changes one value in daemon configuration and restarts daemon
+               Asynchronously changes one value in daemon configuration and
+               optionaly restarts daemon.
+               
                This will:
                 - call daemon.read_config() to read configuration from daemon
                 - change value in recieved YAML document
@@ -1389,58 +1409,66 @@
                 - call daemon.restart()
                Everthing will be done asynchronously and will be repeated
                until succeed, if retry_on_error is set to True.
-               Even if retry_on_error is True, error in write_config will
+               Even if retry_on_error is False, error in write_config will
                be only logged.
                
                It is possible to change nested setting using '/' as separator.
                That may cause error if parent setting node is not present and
                this error will not cause retrying process as well.
+               
+               If value is callable, it's called instead of setting it.
+               In such case, callable is called as:
+                  value(config_node_as_dict, setting_name)
                """
                # ^^ Longest comment in entire project
                
                # Callbacks
                def csnr_error(e, trash, setting_name, value, retry_on_error):
                        """
-                       Error handler for change_setting_n_restart method
+                       Error handler for change_setting_async method
                        """
-                       log.error("change_setting_n_restart: Failed to read 
configuration: %s", e)
+                       log.error("change_setting_async: Failed to read 
configuration: %s", e)
                        if retry_on_error:
                                log.error("Retrying...")
-                               change_setting_n_restart(setting_name, value, 
True)
+                               change_setting_async(setting_name, value, 
retry_on_error, restart)
                        else:
                                log.error("Giving up.")
                
                def csnr_save_error(e, *a):
                        """
-                       Another error handler for change_setting_n_restart 
method.
+                       Another error handler for change_setting_async method.
                        This one just reports failure.
                        """
-                       log.error("change_setting_n_restart: Failed to store 
configuration: %s", e)
+                       log.error("change_setting_async: Failed to store 
configuration: %s", e)
                        log.error("Giving up.")
                
                def csnr_config_read(config, setting_name, value, 
retry_on_error):
                        """
-                       Handler for change_setting_n_restart
+                       Handler for change_setting_async
                        Modifies recieved config and post it back.
                        """
                        c, setting = config, setting_name
                        while "/" in setting:
                                key, setting = setting.split("/", 1)
                                c = c[key]
-                       c[setting] = value
+                       if hasattr(value, '__call__'):
+                               value(c, setting)
+                       else:
+                               c[setting] = value
                        self.daemon.write_config(config, csnr_config_saved, 
csnr_save_error, setting_name, value)
                
                def csnr_config_saved(setting_name, value):
                        """
-                       Handler for change_setting_n_restart
+                       Handler for change_setting_async
                        Reports good stuff and restarts daemon.
                        """
                        log.verbose("Configuration value '%s' set to '%s'", 
setting_name, value)
-                       message = "%s %s..." % (_("Syncthing is restarting."), 
_("Please wait"))
-                       self.display_connect_dialog(message)
-                       self.set_status(False)
-                       self.restart()
-                       GLib.idle_add(self.daemon.restart)
+                       if restart:
+                               message = "%s %s..." % (_("Syncthing is 
restarting."), _("Please wait"))
+                               self.display_connect_dialog(message)
+                               self.set_status(False)
+                               self.restart()
+                               GLib.idle_add(self.daemon.restart)
                
                # Call
                self.daemon.read_config(csnr_config_read, csnr_error, 
setting_name, value, retry_on_error)
@@ -1584,11 +1612,11 @@
        
        def cb_menu_recvlimit(self, menuitem, speed=0):
                if menuitem.get_active() and self.recv_limit != speed:
-                       self.change_setting_n_restart("options/maxRecvKbps", 
speed)
+                       self.change_setting_async("options/maxRecvKbps", speed)
        
        def cb_menu_sendlimit(self, menuitem, speed=0):
                if menuitem.get_active() and self.send_limit != speed:
-                       self.change_setting_n_restart("options/maxSendKbps", 
speed)
+                       self.change_setting_async("options/maxSendKbps", speed)
        
        def cb_menu_recvlimit_other(self, menuitem):
                return self.cb_menu_limit_other(menuitem, self.recv_limit)
@@ -1628,6 +1656,8 @@
                b = box["id"] != self.daemon.get_my_id()
                self["menu-popup-edit-device"].set_visible(b)
                self["menu-popup-delete-device"].set_visible(b)
+               self["menu-popup-pause-device"].set_visible(box.get_status() != 
_("Paused"))
+               self["menu-popup-resume-device"].set_visible(box.get_status() 
== _("Paused"))
                self["popup-menu-device"].popup(None, None, None, None, button, 
time)
        
        def cb_menu_popup(self, source, menu):
@@ -1689,9 +1719,16 @@
        
        def cb_menu_popup_delete_device(self, *a):
                """ Handler for other 'edit' context menu item """
-               # Editing device
                self.check_delete("device", self.rightclick_box["id"], 
self.rightclick_box.get_title())
        
+       def cb_menu_popup_pause_device(self, *a):
+               """ Handler for 'resume device' context menu item """
+               self.daemon.pause(self.rightclick_box["id"])
+       
+       def cb_menu_popup_resume_device(self, *a):
+               """ Handler for 'resume device' context menu item """
+               self.daemon.resume(self.rightclick_box["id"])
+       
        def check_delete(self, mode, id, name):
                """
                Asks user if he really wants to do what he just asked to do
@@ -1831,12 +1868,19 @@
                        e = DeviceEditorDialog(self, True, 
additional_data["nid"])
                        e.load()
                        e.show(self["window"])
+               elif response_id == RESPONSE_FIX_IGNORE:
+                       # Ignore unknown device
+                       def add_ignored(target, trash):
+                               if not "ignoredDevices" in target:
+                                       target["ignoredDevices"] = []
+                               
target["ignoredDevices"].append(additional_data["nid"])
+                       self.change_setting_async("ignoredDevices", 
add_ignored, restart=False)
                elif response_id == RESPONSE_UR_ALLOW:
                        # Allow Usage reporting
-                       self.change_setting_n_restart("options/urAccepted", 1)
+                       self.change_setting_async("options/urAccepted", 1)
                elif response_id == RESPONSE_UR_FORBID:
                        # Allow Usage reporting
-                       self.change_setting_n_restart("options/urAccepted", -1)
+                       self.change_setting_async("options/urAccepted", -1)
                self.cb_infobar_close(bar)
        
        def cb_open_closed(self, box):
@@ -1880,6 +1924,7 @@
                        self.quit()
        
        def cb_daemon_exit(self, proc, error_code):
+               print "cb_daemon_exit", proc, self.process
                if proc == self.process:
                        # Whatever happens, if daemon dies while it shouldn't,
                        # restart it
@@ -1917,6 +1962,6 @@
                r = d.run()
                d.destroy()
                if r == FindDaemonDialog.RESPONSE_SAVED:
-                       self.cb_daemon_exit(None, -1)
+                       self.cb_daemon_exit(self.process, -1)
                else:
                        self.quit()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/syncthing-gtk-0.7.6.1/syncthing_gtk/configuration.py 
new/syncthing-gtk-0.8/syncthing_gtk/configuration.py
--- old/syncthing-gtk-0.7.6.1/syncthing_gtk/configuration.py    2015-10-07 
10:04:07.000000000 +0200
+++ new/syncthing-gtk-0.8/syncthing_gtk/configuration.py        2015-11-05 
18:16:32.000000000 +0100
@@ -59,7 +59,7 @@
                        self.load()
                except Exception, e:
                        log.warning("Failed to load configuration; Creating new 
one.")
-                       log.warning("Reason: %s", e)
+                       log.warning("Reason: %s", (e,))
                        self.create()
                
                # Convert objects serialized as string back to object
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/syncthing-gtk-0.7.6.1/syncthing_gtk/daemon.py 
new/syncthing-gtk-0.8/syncthing_gtk/daemon.py
--- old/syncthing-gtk-0.7.6.1/syncthing_gtk/daemon.py   2015-10-07 
10:04:07.000000000 +0200
+++ new/syncthing-gtk-0.8/syncthing_gtk/daemon.py       2015-11-05 
18:16:32.000000000 +0100
@@ -20,7 +20,7 @@
 log = logging.getLogger("Daemon")
 
 # Minimal version supported by Daemon class
-MIN_VERSION = "0.11"
+MIN_VERSION = "0.12"
 
 # Random constant used as key when adding headers to returned data in
 # REST requests; Anything goes, as long as it isn't string
@@ -129,6 +129,14 @@
                                id:                     id of device
                                last_seen:      datetime object or None, if 
device was never seen
                
+               device-paused (id):
+                       Emited when synchronization with device is paused
+                               id:             id of folder
+               
+               device-resumed (id):
+                       Emited when synchronization with device is resumed
+                               id:             id of folder
+               
                device-sync-started (id, progress):
                        Emited after device synchronization is started
                                id:                     id of folder
@@ -160,6 +168,11 @@
                        daemon needs to be restarted
                                id:             id of folder
                
+               folder-scan-progress (id, progress):
+                       Emited repeatedly while folder is being scanned
+                               id:                     id of folder
+                               progress:       scan progress (0.0 to 1.0)
+               
                folder-sync-progress (id, progress):
                        Emited repeatedly while folder is being synchronized
                                id:                     id of folder
@@ -228,18 +241,20 @@
                        b"device-discovered"    : (GObject.SIGNAL_RUN_FIRST, 
None, (object,object,)),
                        b"device-data-changed"  : (GObject.SIGNAL_RUN_FIRST, 
None, (object, object, object, float, float, object, object)),
                        b"last-seen-changed"    : (GObject.SIGNAL_RUN_FIRST, 
None, (object, object)),
+                       b"device-paused"                : 
(GObject.SIGNAL_RUN_FIRST, None, (object,)),
+                       b"device-resumed"               : 
(GObject.SIGNAL_RUN_FIRST, None, (object,)),
                        b"device-sync-started"  : (GObject.SIGNAL_RUN_FIRST, 
None, (object, float)),
                        b"device-sync-progress" : (GObject.SIGNAL_RUN_FIRST, 
None, (object, float)),
                        b"device-sync-finished" : (GObject.SIGNAL_RUN_FIRST, 
None, (object,)),
                        b"folder-added"                 : 
(GObject.SIGNAL_RUN_FIRST, None, (object, object)),
                        b"folder-data-changed"  : (GObject.SIGNAL_RUN_FIRST, 
None, (object, object)),
                        b"folder-data-failed"   : (GObject.SIGNAL_RUN_FIRST, 
None, (object,)),
-                       b"folder-sync-started"  : (GObject.SIGNAL_RUN_FIRST, 
None, (object,)),
                        b"folder-sync-finished" : (GObject.SIGNAL_RUN_FIRST, 
None, (object,)),
                        b"folder-sync-progress" : (GObject.SIGNAL_RUN_FIRST, 
None, (object, float)),
-                       b"folder-scan-started"  : (GObject.SIGNAL_RUN_FIRST, 
None, (object,)),
+                       b"folder-sync-started"  : (GObject.SIGNAL_RUN_FIRST, 
None, (object,)),
                        b"folder-scan-finished" : (GObject.SIGNAL_RUN_FIRST, 
None, (object,)),
-                       b"folder-scan-progress" : (GObject.SIGNAL_RUN_FIRST, 
None, (object,)),
+                       b"folder-scan-started"  : (GObject.SIGNAL_RUN_FIRST, 
None, (object,)),
+                       b"folder-scan-progress" : (GObject.SIGNAL_RUN_FIRST, 
None, (object, float)),
                        b"folder-stopped"               : 
(GObject.SIGNAL_RUN_FIRST, None, (object,object)),
                        b"item-started"                 : 
(GObject.SIGNAL_RUN_FIRST, None, (object,object,object)),
                        b"item-updated"                 : 
(GObject.SIGNAL_RUN_FIRST, None, (object,object,object)),
@@ -736,11 +751,12 @@
                self.timer("event", self._refresh_interval, 
self._request_events)
        
        def _syncthing_cb_errors(self, errors):
-               for e in errors["errors"]:
-                       t = parsetime(e["time"])
-                       if t > self._last_error_time:
-                               self.emit("error", e["error"])
-                               self._last_error_time = t
+               if errors["errors"] is not None:
+                       for e in errors["errors"]:
+                               t = parsetime(e["time"])
+                               if t > self._last_error_time:
+                                       self.emit("error", e["error"])
+                                       self._last_error_time = t
                self.timer("errors", self._refresh_interval * 5, 
self._rest_request, "system/error", self._syncthing_cb_errors)
        
        def _syncthing_cb_events_error(self, exception, command):
@@ -783,13 +799,20 @@
                                cons[id]["outbps"] = 0.0
                        # Store updated device_data
                        for key in cons[id]:
-                               if key != "clientVersion" or cons[id][key] != 
"":       # Happens for 'total'
-                                       device_data[key] = cons[id][key]
+                               if not key in ('clientVersion', 'connected'):   
        # Don't want copy those
+                                       if cons[id][key] != "":                 
                                # Happens for 'total'
+                                               device_data[key] = cons[id][key]
                        
-                       # Send "device-connected" signal, if device was 
disconnected until now
-                       if not device_data["connected"] and nid != self._my_id:
-                               device_data["connected"] = True
-                               self.emit("device-connected", nid)
+                       if cons[id]["paused"]:
+                               # Send "device-paused" signal if device needed
+                               device_data["connected"] = False
+                               self.emit("device-paused", nid)
+                       else:
+                               # Send "device-connected" signal, if device was 
disconnected until now
+                               if cons[id]["connected"]:
+                                       if not device_data["connected"] and nid 
!= self._my_id:
+                                               device_data["connected"] = True
+                                               self.emit("device-connected", 
nid)
                        # Send "device-data-changed" signal
                        self.emit("device-data-changed", nid, 
                                device_data["address"],
@@ -907,7 +930,8 @@
                if state in ('error', 'stopped'):
                        if not rid in self._stopped_folders:
                                self._stopped_folders.add(rid)
-                               self.emit("folder-stopped", rid, 
data["invalid"])
+                               reason = data["invalid"] or data["error"]
+                               self.emit("folder-stopped", rid, reason)
                self.emit('folder-data-changed', rid, data)
                p = 0.0
                if state == "syncing":
@@ -1003,9 +1027,7 @@
                                        self.emit("folder-sync-started", rid)
                elif state == "scanning":
                        if not rid in self._stopped_folders:
-                               if rid in self._scanning_folders:
-                                       self.emit("folder-scan-progress", rid)
-                               else:
+                               if not rid in self._scanning_folders:
                                        self._scanning_folders.add(rid)
                                        self.emit("folder-scan-started", rid)
        
@@ -1026,13 +1048,19 @@
                        nid = e["data"]["id"]
                        self.emit("device-connected", nid)
                elif eType == "DeviceDisconnected":
-                       nid = e["data"]["id"]
-                       self.emit("device-disconnected", nid)
-                       self._request_last_seen()
+                          nid = e["data"]["id"]
+                          self.emit("device-disconnected", nid)
                elif eType == "DeviceDiscovered":
                        nid = e["data"]["device"]
                        addresses = e["data"]["addrs"]
                        self.emit("device-discovered", nid, addresses)
+               elif eType == "DevicePaused":
+                       nid = e["data"]["device"]
+                       self.emit("device-paused", nid)
+               elif eType == "DeviceResumed":
+                       nid = e["data"]["device"]
+                       self.emit("device-resumed", nid)
+                       self._request_last_seen()
                elif eType == "FolderRejected":
                        nid = e["data"]["device"]
                        rid = e["data"]["folder"]
@@ -1041,6 +1069,13 @@
                        nid = e["data"]["device"]
                        address = e["data"]["address"]
                        self.emit("device-rejected", nid, address)
+               elif eType == "FolderScanProgress":
+                       rid = e["data"]["folder"]
+                       total = float(e["data"]["total"])
+                       if total > 0:
+                               # ^^ just in case
+                               status = float(e["data"]["current"]) / total
+                               self.emit("folder-scan-progress", rid, status)
                elif eType == "ItemStarted":
                        rid = e["data"]["folder"]
                        filename = e["data"]["item"]
@@ -1059,11 +1094,8 @@
                                self.emit("item-updated", rid, filename, mtime)
                elif eType == "ConfigSaved":
                        self.emit("config-saved")
-               elif eType == "ItemFinished":
-                       # Not handled (yet?)
-                       pass
-               elif eType == "DownloadProgress":
-                       # Not handled (yet?)
+               elif eType in ("ItemFinished", "DownloadProgress", 
"RelayStateChanged"):
+                       # Not handled
                        pass
                else:
                        log.warning("Unhandled event type: %s", e)
@@ -1231,21 +1263,27 @@
                """ Returns True if daemon is known to be alive """
                return self._connected
        
-       def rescan(self, folder_id, path=None):
-               """ Asks daemon to rescan entire folder or specified path """
+       def pause(self, device_id):
+               """ Pauses synchronization with specified device """
+               self._rest_post("system/pause?device=%s" % (device_id,), {}, 
lambda *a: a, lambda *a: log.error(a), device_id)
+       
+       def resume(self, device_id):
+               """ Resumes synchronization with specified device """
                def on_error(*a):
                        log.error(a)
+               self._rest_post("system/resume?device=%s" % (device_id,), {}, 
lambda *a: a, lambda *a: log.error(a), device_id)
+       
+       def rescan(self, folder_id, path=None):
+               """ Asks daemon to rescan entire folder or specified path """
                if path is None:
-                       self._rest_post("db/scan?folder=%s" % (folder_id,), {}, 
lambda *a: a, on_error, folder_id)
+                       self._rest_post("db/scan?folder=%s" % (folder_id,), {}, 
lambda *a: a, lambda *a: log.error(a), folder_id)
                else:
                        path_enc = urllib.quote(path.encode('utf-8'), 
''.encode('utf-8'))
                        self._rest_post("db/scan?folder=%s&sub=%s" % 
(folder_id, path_enc), {}, lambda *a: a, on_error, folder_id)
        
        def override(self, folder_id):
                """ Asks daemon to override changes made in specified folder """
-               def on_error(*a):
-                       log.error(a)
-               self._rest_post("model/override?folder=%s" % (folder_id,), {}, 
lambda *a: a, on_error, folder_id)
+               self._rest_post("model/override?folder=%s" % (folder_id,), {}, 
lambda *a: a, lambda *a: log.error(a), folder_id)
        
        def request_events(self):
                """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/syncthing-gtk-0.7.6.1/syncthing_gtk/foldereditor.py 
new/syncthing-gtk-0.8/syncthing_gtk/foldereditor.py
--- old/syncthing-gtk-0.7.6.1/syncthing_gtk/foldereditor.py     2015-10-07 
10:04:07.000000000 +0200
+++ new/syncthing-gtk-0.8/syncthing_gtk/foldereditor.py 2015-11-05 
18:16:32.000000000 +0100
@@ -15,8 +15,6 @@
 log = logging.getLogger("FolderEditor")
 
 COLOR_NEW                              = "#A0A0A0"
-# Regexp to check if folder id is valid
-RE_FOLDER_ID = re.compile("^([a-zA-Z0-9\-\._]{1,64})$")
 # Regexp to generate folder id from filename
 RE_GEN_ID = re.compile("([a-zA-Z0-9\-\._]{1,64}).*")
 VALUES = [ "vid", "vpath", "vreadOnly", "vignorePerms", "vdevices",
@@ -254,9 +252,6 @@
                if value in self.app.folders:
                        # Duplicate folder id
                        return False
-               if RE_FOLDER_ID.match(value) is None:
-                       # Invalid string
-                       return False
                return True
        
        def check_path(self, value):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/syncthing-gtk-0.7.6.1/syncthing_gtk/tools.py 
new/syncthing-gtk-0.8/syncthing_gtk/tools.py
--- old/syncthing-gtk-0.7.6.1/syncthing_gtk/tools.py    2015-10-07 
10:04:07.000000000 +0200
+++ new/syncthing-gtk-0.8/syncthing_gtk/tools.py        2015-11-05 
18:16:32.000000000 +0100
@@ -312,6 +312,12 @@
        Returns ~/.config, %APPDATA% or whatever has user set as
        configuration directory.
        """
+       if IS_WINDOWS:
+               try:
+                       import windows
+                       return windows.get_unicode_home()
+               except Exception:
+                       pass
        confdir = GLib.get_user_config_dir()
        if confdir is None or IS_XP:
                if IS_WINDOWS:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/syncthing-gtk-0.7.6.1/syncthing_gtk/windows.py 
new/syncthing-gtk-0.8/syncthing_gtk/windows.py
--- old/syncthing-gtk-0.7.6.1/syncthing_gtk/windows.py  2015-10-07 
10:04:07.000000000 +0200
+++ new/syncthing-gtk-0.8/syncthing_gtk/windows.py      2015-11-05 
18:16:32.000000000 +0100
@@ -11,6 +11,7 @@
 from gi.repository import Gio, GLib, GObject, Gtk, Gdk
 import os, sys, logging, codecs, msvcrt, win32pipe, win32api, _winreg
 import win32process
+from win32com.shell import shell, shellcon
 log = logging.getLogger("windows.py")
 
 SM_SHUTTINGDOWN = 0x2000
@@ -85,6 +86,9 @@
                Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
        )
 
+def get_unicode_home():
+       return shell.SHGetFolderPath(0, shellcon.CSIDL_LOCAL_APPDATA, None, 0)
+
 class WinPopenReader:
        """
        Reads from PIPE using GLib timers or idle_add. Emulates part of


Reply via email to