~ubuntu-branches/ubuntu/lucid/awn-extras-applets/lucid

« back to all changes in this revision

Viewing changes to applets/maintained/file-browser-launcher/file-browser-launcher.py

  • Committer: Bazaar Package Importer
  • Author(s): Julien Lavergne
  • Date: 2010-03-30 20:26:40 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20100330202640-vza3bdnv9gc9bg5z
Tags: 0.4.0~rc1-0ubuntu1
* New upstream release (rc1) (LP: #551309)
 - Stack applet close on click (LP: #261520)
* debian/patches/
 - 03-remove-cairo-menu-pref.patch: From upstream (r1244 + r1245 + r1252),
   remove menu entry for cairo-menu preferences, it's not implemented
   (LP: #511254)
 - 04-tomboy-threading-free.patch: From upstream (r1246), remove threading to
   make the applet working. 
* debian/*.install: Update installation location of comics and digital 
  applets.
* debian/control: 
 - Move digital applet from python to C, and add proper Replaces.
 - Add Replaces for awn-applets-c-core to handle migration from 0.3.2.2.
   (LP: #524559)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#! /usr/bin/python
2
2
# -*- coding: utf-8 -*-
3
3
#
4
 
# Copyright (c) 2009 sharkbaitbobby <sharkbaitbobby+awn@gmail.com>
 
4
# Copyright (c) 2009, 2010 sharkbaitbobby <sharkbaitbobby+awn@gmail.com>
5
5
#
6
6
# This library is free software; you can redistribute it and/or
7
7
# modify it under the terms of the GNU Lesser General Public
43
43
from awn.extras import _
44
44
gettext.bindtextdomain('xdg-user-dirs', '/usr/share/locale')
45
45
 
46
 
class App (awn.AppletSimple):
 
46
 
 
47
class App(awn.Applet):
47
48
  icons = {}
48
49
  timer = None
49
50
  num_times = 0
50
 
  drag_done = False
 
51
  drag_done = True
51
52
  droppable_places = []
 
53
  places_data = []
 
54
  docklet_visible = False
52
55
 
53
56
  def __init__(self, uid, panel_id):
54
 
    self.uid = uid
55
 
 
56
57
    #AWN Applet Configuration
57
 
    awn.AppletSimple.__init__(self, 'file-browser-launcher', uid, panel_id)
58
 
    self.set_tooltip_text(_("File Browser Launcher"))
 
58
    awn.Applet.__init__(self, 'file-browser-launcher', uid, panel_id)
 
59
 
 
60
    self.icon_box = awn.IconBox(self)
 
61
    self.add(self.icon_box)
 
62
    self.icon = awn.ThemedIcon()
 
63
    self.icon.set_tooltip_text(_("File Browser Launcher"))
 
64
    self.icon.set_size(self.get_size())
59
65
    self.dialog = awn.Dialog(self)
60
66
 
61
67
    #AwnConfigClient instance
63
69
 
64
70
    #Get the default icon theme
65
71
    self.theme = gtk.icon_theme_get_default()
66
 
    self.icons['stock_folder'] = self.theme.load_icon('stock_folder', 24, 24)
 
72
    self.icons[24] = {}
 
73
    self.icons[24]['stock_folder'] = self.theme.load_icon('stock_folder', 24, 0)
 
74
 
 
75
    #Docklet...
 
76
    self.mode = self.client.get_int(group, 'mode')
 
77
    self.client.notify_add(group, 'mode', self.update_mode)
 
78
 
 
79
    if self.mode == 2:
 
80
      self.docklet_visible = True
 
81
      self.update_docklet(False)
 
82
 
 
83
    else:
 
84
      self.icon_box.add(self.icon)
67
85
 
68
86
    #Set the icon
69
 
    self.set_icon_name('stock_folder')
70
 
    self.icon = self.get_icon().get_icon_at_size(48, None)
 
87
    self.icon.set_info_simple('file-browser-launcher', uid, 'stock_folder')
71
88
 
72
89
    #This part (and other progress overlay code) adapted from
73
90
    #mhr3's 'Dropper' applet
76
93
      self.timer_overlay = awn.OverlayProgressCircle()
77
94
      self.timer_overlay.props.active = False
78
95
      self.timer_overlay.props.apply_effects = False
79
 
      self.get_icon().add_overlay(self.timer_overlay)
 
96
      self.icon.add_overlay(self.timer_overlay)
80
97
 
81
98
    else:
82
99
      #Read fstab for mounting info
123
140
 
124
141
    if gio:
125
142
      self.monitor = gio.volume_monitor_get()
126
 
      self.monitor.connect('volume-added', self.do_gio_places)
127
 
      self.monitor.connect('volume-changed', self.do_gio_places)
128
 
      self.monitor.connect('volume-removed', self.do_gio_places)
129
 
      self.monitor.connect('mount-added', self.do_gio_places)
130
 
      self.monitor.connect('mount-changed', self.do_gio_places)
131
 
      self.monitor.connect('mount-removed', self.do_gio_places)
 
143
      for signal in ('volume-added', 'volume-changed', 'volume-removed', 'mount-added',
 
144
        'mount-changed', 'mount-removed'):
 
145
        self.monitor.connect(signal, self.do_gio_places)
132
146
 
133
 
      self.client.notify_add(group, 'show_home', self.do_gio_places)
134
 
      self.client.notify_add(group, 'show_local', self.do_gio_places)
135
 
      self.client.notify_add(group, 'show_network', self.do_gio_places)
136
 
      self.client.notify_add(group, 'show_connect', self.do_gio_places)
137
 
      self.client.notify_add(group, 'show_bookmarks', self.do_gio_places)
138
 
      self.client.notify_add(group, 'show_filesystem', self.do_gio_places)
 
147
      for key in ('show_home', 'show_local', 'show_network', 'show_connect', 'show_bookmarks',
 
148
        'show_filesystem'):
 
149
        self.client.notify_add(group, key, self.do_gio_places)
139
150
 
140
151
      self.do_gio_places()
141
152
 
169
180
    self.dialog.add(self.vbox)
170
181
 
171
182
    #Connect to signals
172
 
    self.connect('button-press-event', self.button_press)
 
183
    self.icon.connect('clicked', self.icon_clicked)
 
184
    self.icon.connect('middle-clicked', self.icon_clicked)
 
185
    self.icon.connect('context-menu-popup', self.show_context_menu)
 
186
    self.connect('size-changed', self.size_changed)
173
187
    self.dialog.connect('focus-out-event', self.dialog_focus_out)
174
188
    self.theme.connect('changed', self.icon_theme_changed)
175
189
 
180
194
      #maybe unmounted places). The move the file/folder and (if successful)
181
195
      #open the place in the file browser
182
196
      #The Applet icon - just open the dialog after a short delay
183
 
      self.get_icon().drag_dest_set(gtk.DEST_DEFAULT_DROP | gtk.DEST_DEFAULT_MOTION, \
 
197
      self.icon.drag_dest_set(gtk.DEST_DEFAULT_DROP | gtk.DEST_DEFAULT_MOTION, \
184
198
        [("text/uri-list", 0, 0)], \
185
199
        gtk.gdk.ACTION_COPY)
186
 
      self.get_icon().connect('drag-data-received', self.applet_drag_data_received)
187
 
      self.get_icon().connect('drag-motion', self.applet_drag_motion)
188
 
      self.get_icon().connect('drag-leave', self.applet_drag_leave)
189
 
  
 
200
      self.icon.connect('drag-data-received', self.applet_drag_data_received)
 
201
      self.icon.connect('drag-motion', self.applet_drag_motion)
 
202
      self.icon.connect('drag-leave', self.applet_drag_leave)
 
203
 
190
204
      #The TreeView - drop the file to move it to the folder
191
205
      self.treeview.drag_dest_set(gtk.DEST_DEFAULT_DROP | gtk.DEST_DEFAULT_MOTION, \
192
206
        [("text/uri-list", 0, 0)], \
195
209
      self.treeview.connect('drag-motion', self.treeview_drag_motion)
196
210
      self.treeview.connect('drag-leave', self.treeview_drag_leave)
197
211
 
 
212
  def size_changed(self, *args):
 
213
    if self.docklet_visible:
 
214
      self.update_docklet()
 
215
 
 
216
    self.icon.set_size(self.get_size())
 
217
 
198
218
  #Applet drag and drop
199
219
  def applet_drag_data_received(self, w, context, x, y, data, info, time):
200
220
    context.finish(True, False, time)
212
232
 
213
233
      self.timer = gobject.timeout_add(30, self.update_timer)
214
234
 
215
 
    if not self.dialog.flags() & gtk.VISIBLE:
216
 
      self.get_effects().start(awn.EFFECT_LAUNCHING)
 
235
    if self.client.get_int(group, 'mode') == 0:
 
236
      if not self.dialog.flags() & gtk.VISIBLE:
 
237
        self.icon.get_effects().start(awn.EFFECT_LAUNCHING)
217
238
 
218
239
  def applet_drag_leave(self, widget, context, time):
219
 
    self.get_effects().stop(awn.EFFECT_LAUNCHING)
 
240
    self.icon.get_effects().stop(awn.EFFECT_LAUNCHING)
220
241
 
221
242
    if self.timer:
222
243
      gobject.source_remove(self.timer)
242
263
      self.timer_overlay.props.active = False
243
264
      self.timer_overlay.props.percent_complete = 0
244
265
 
245
 
      self.get_effects().stop(awn.EFFECT_LAUNCHING)
 
266
      self.icon.get_effects().stop(awn.EFFECT_LAUNCHING)
246
267
 
247
268
      self.dialog_config(1)
248
269
 
259
280
    path = self.liststore[treepath][3]
260
281
 
261
282
    if path in self.droppable_places:
262
 
      dropped_path = data.data
263
 
 
264
 
      if dropped_path[:8] == 'file:///':
265
 
        dropped_path = dropped_path.strip()
266
 
 
267
 
        dropped_path = urllib.unquote(dropped_path)
268
 
 
269
 
        from_file = gio.File(dropped_path)
270
 
 
271
 
        to_file = gio.File(path + '/' + from_file.get_basename())
272
 
 
273
 
        #Make sure we're not just moving the file to the same directory
274
 
        if not from_file.equal(to_file):
275
 
          if from_file.move(to_file):
276
 
 
277
 
            config_fb = self.client.get_string(group, 'fb')
278
 
            open_dir = path.replace(' ', '\ ')
279
 
            os.system('%s %s &' % (config_fb, open_dir))
280
 
 
281
 
          self.dialog.hide()
 
283
      dropped_paths = data.data.split('\n')
 
284
      num_success = 0
 
285
 
 
286
      for dropped_path in dropped_paths:
 
287
        if len(dropped_path) >= 8:
 
288
          if dropped_path[:8] == 'file:///':
 
289
            dropped_path = dropped_path.strip()
 
290
 
 
291
            dropped_path = urllib.unquote(dropped_path)
 
292
 
 
293
            from_file = gio.File(dropped_path)
 
294
 
 
295
            to_file = gio.File(path + '/' + from_file.get_basename())
 
296
 
 
297
            #Make sure we're not just moving the file to the same directory
 
298
            if not from_file.equal(to_file):
 
299
              if from_file.move(to_file):
 
300
                num_success += 1
 
301
 
 
302
      if num_success > 0:
 
303
        config_fb = self.client.get_string(group, 'fb')
 
304
        open_dir = path.replace(' ', '\ ')
 
305
        os.system('%s %s &' % (config_fb, open_dir))
 
306
        self.dialog.hide()
282
307
 
283
308
    return True
284
309
 
306
331
  def do_places(self):
307
332
    self.liststore.clear()
308
333
    self.places_paths = []
 
334
    self.places_data = []
309
335
 
310
336
    #Get the needed config values
311
337
    self.show_home = self.client.get_int(group, 'show_home')
334
360
        icon = vol.get_icon()
335
361
        eject = None
336
362
 
337
 
        if type(icon) == gio.ThemedIcon:
338
 
          icons = icon.get_names()
339
 
 
340
 
        else:
 
363
        icons = None
 
364
 
 
365
        try:
 
366
          if isinstance(icon, gio.ThemedIcon):
 
367
            icons = icon.get_names()
 
368
 
 
369
          elif isinstance(icon, gio.FileIcon):
 
370
            icons = (icon.get_file().get_path(), )
 
371
        except:
 
372
          pass
 
373
 
 
374
        if icons is None:
341
375
          icons = ('drive-harddisk', 'drive')
342
376
 
343
377
        #Get the human-readable name
346
380
        #Get the path
347
381
        if vol.get_mount():
348
382
          path = vol.get_mount().get_root().get_uri()
349
 
          icons = vol.get_mount().get_icon().get_names()
 
383
          icon = vol.get_mount().get_icon()
 
384
 
 
385
          icons = None
 
386
          try:
 
387
            if isinstance(icon, gio.ThemedIcon):
 
388
              icons = icon.get_names()
 
389
 
 
390
            elif isinstance(icon, gio.FileIcon):
 
391
              icons = (icon.get_file().get_path(), )
 
392
          except:
 
393
            pass
 
394
 
 
395
          if icons is None:
 
396
            icons = ('drive-harddisk', 'drive')
350
397
 
351
398
          #Get the eject icon if this volume can be unmounted
352
399
          if vol.get_mount().can_unmount():
363
410
        icon = self.load_pixbuf(icons)
364
411
 
365
412
        self.liststore.append((icon, name, eject, path, i))
 
413
        self.places_data.append([icons, name, bool(eject), path, i])
366
414
 
367
415
        i += 1
368
416
 
372
420
          #Get the icon
373
421
          icon = mount.get_icon()
374
422
 
375
 
          if type(icon) == gio.ThemedIcon:
376
 
            icons = icon.get_names()
377
 
 
378
 
          else:
 
423
          icons = None
 
424
          try:
 
425
            if isinstance(icon, gio.ThemedIcon):
 
426
              icons = icon.get_names()
 
427
 
 
428
            elif isinstance(icon, gio.FileIcon):
 
429
              icons = (icon.get_file().get_path(), )
 
430
          except:
 
431
            pass
 
432
 
 
433
          if icons is None:
379
434
            icons = ('applications-internet', )
380
435
 
381
436
          #Human-readable name
398
453
                self.droppable_places.append(path)
399
454
 
400
455
          self.liststore.append((icon, name, eject, path, i))
 
456
          self.places_data.append([icons, name, bool(eject), path, i])
401
457
 
402
458
          i += 1
403
459
 
404
460
    self.do_ncs()
405
461
    self.do_bookmarks()
406
462
 
 
463
    if self.docklet_visible:
 
464
      self.update_docklet()
 
465
 
407
466
  #A volume was mounted through file-browser-launcher; open the file manager to the path
408
467
  def gio_mounted(self, vol, blah):
409
468
    self.launch_fb(None, vol.get_mount().get_root().get_uri())
427
486
 
428
487
      for path in self.bmarks:
429
488
        path = path.replace('file://', '').replace('\n', '')
430
 
        path = urllib.unquote(path)
431
489
 
432
490
        #Get the human-readable name
433
491
        try:
434
492
          name = ' '.join(path.split(' ')[1:])
435
 
          assert name.replace(' ', '') != ''
 
493
          assert name.strip() != ''
436
494
        except:
437
495
          name = None
438
496
 
439
 
        path = path.split(' ')[0]
 
497
        path = urllib.unquote(path.split(' ')[0])
440
498
        type = path.split(':')[0]
441
499
 
442
500
        #Check if this path hasn't been used already
443
 
        if path not in self.paths and path != os.environ['HOME']:
444
 
 
 
501
        if path not in self.paths and path.rstrip('/') != os.environ['HOME'].rstrip('/'):
445
502
          #Check if this is a path on the filesystem
446
503
          if path[0] == '/':
447
504
            if os.path.isdir(path):
448
 
 
449
505
              #If the user did not rename the bookmark - get the name from
450
506
              #the folder name (/media/Lexar -> Lexar)
451
507
              if name is None:
646
702
          pass
647
703
 
648
704
        elif path.split('/')[1] == 'media':
649
 
          if path.split('/')[2] in ['cdrom0','cdrom1','cdrom2','cdrom3','cdrom4','cdrom5']:
 
705
          if path.split('/')[2] in ['cdrom0', 'cdrom1', 'cdrom2', 'cdrom3', 'cdrom4', 'cdrom5']:
650
706
 
651
707
            #Find out if it's a CD or DVD
652
708
            if path in self.dvd_paths:
692
748
 
693
749
    self.do_bookmarks()
694
750
 
695
 
  def load_pixbuf(self, names):
 
751
    if self.docklet_visible:
 
752
      self.update_docklet()
 
753
 
 
754
  def load_pixbuf(self, names, size=24):
696
755
    if type(names) == str:
697
756
      names = (names, )
698
757
 
 
758
    if size not in self.icons:
 
759
      self.icons[size] = {}
 
760
 
699
761
    worked = False
700
762
    for name in names:
701
763
      #Load the icon if it hasn't been yet
702
 
      if not self.icons.has_key(name):
703
 
        try:
704
 
          icon = self.theme.load_icon(name, 24, 0)
705
 
          worked = True
706
 
          break
707
 
 
708
 
        except:
709
 
          pass
 
764
      if not self.icons[size].has_key(name):
 
765
        if name[0] == '/':
 
766
          try:
 
767
            icon = gtk.gdk.pixbuf_new_from_file_at_size(size, size)
 
768
            worked = True
 
769
            break
 
770
          except:
 
771
            pass
 
772
 
 
773
        else:
 
774
          try:
 
775
            icon = self.theme.load_icon(name, size, 0)
 
776
            worked = True
 
777
            break
 
778
 
 
779
          except:
 
780
            pass
710
781
 
711
782
      #Icon has already been loaded
712
783
      else:
713
784
        worked = True
714
 
        icon = self.icons[name]
 
785
        icon = self.icons[size][name]
715
786
        break
716
787
 
717
788
    #If no icon does exists - load default folder icon
718
789
    if not worked:
719
 
      icon = self.icons['stock_folder']
720
 
      self.icons[name] = icon
 
790
      if 'stock_folder' not in self.icons[size]:
 
791
        self.icons[size]['stock_folder'] = self.theme.load_icon('stock_folder', size, 0)
 
792
 
 
793
      icon = self.icons[size]['stock_folder']
 
794
      self.icons[size][name] = icon
721
795
 
722
796
    else:
723
 
      self.icons[name] = icon
 
797
      self.icons[size][name] = icon
724
798
 
725
799
    return icon
726
800
 
727
801
  def place(self, icon_names, human_name, path, alt_name=None):
728
802
    icon = self.load_pixbuf(icon_names)
729
803
    self.liststore.append([icon, [human_name, alt_name][human_name is None], None, path, -1])
 
804
    self.places_data.append([icon_names, [human_name, alt_name][human_name is None], False, path, -1])
730
805
 
731
806
    if gio:
732
807
      if path not in self.droppable_places:
751
826
        #Check if this is a volume or a mount
752
827
        num = self.liststore[path][4]
753
828
        if num != -1:
754
 
          li = self.monitor.get_volumes()
755
 
          li.extend(self.monitor.get_mounts())
756
 
 
757
 
          #If it's a volume
758
 
          if isinstance(li[num], gio.Volume):
759
 
            if li[num].get_mount():
760
 
              #If the volume can eject
761
 
              if li[num].get_mount().can_eject():
762
 
                li[num].get_mount().eject(self.ejected_or_unmounted)
763
 
                return False
764
 
 
765
 
              #If the volume can unmount
766
 
              if li[num].get_mount().can_unmount():
767
 
                li[num].get_mount().unmount(self.ejected_or_unmounted)
768
 
                return False
769
 
 
770
 
          #It's a mount
771
 
          else:
772
 
            #If the mount can eject
773
 
            if li[num].can_eject():
774
 
              li[num].eject(self.ejected_or_unmounted)
775
 
              return False
776
 
 
777
 
            #If the mount can unmount
778
 
            elif li[num].can_unmount():
779
 
              li[num].unmount(self.ejected_or_unmounted)
780
 
              return False
781
 
 
 
829
          if self.unmount(num):
 
830
            return False
782
831
          #Otherwise, just open it
783
832
 
784
833
    if self.open_clicked == 2:
789
838
      self.entry.set_text(self.liststore[selection.get_selected()[1]][3])
790
839
      self.entry.grab_focus()
791
840
 
792
 
  #Applet show/hide methods - copied from MiMenu (and edited)
793
 
  #When a button is pressed
794
 
  def button_press(self, widget, event):
795
 
    if event.button in (1, 2):
 
841
  def unmount(self, num):
 
842
    li = self.monitor.get_volumes()
 
843
    li.extend(self.monitor.get_mounts())
 
844
 
 
845
    #If it's a volume
 
846
    if isinstance(li[num], gio.Volume):
 
847
      if li[num].get_mount():
 
848
        #If the volume can eject
 
849
        if li[num].get_mount().can_eject():
 
850
          li[num].get_mount().eject(self.ejected_or_unmounted)
 
851
          return True
 
852
 
 
853
        #If the volume can unmount
 
854
        if li[num].get_mount().can_unmount():
 
855
          li[num].get_mount().unmount(self.ejected_or_unmounted)
 
856
          return True
 
857
 
 
858
    #It's a mount
 
859
    else:
 
860
      #If the mount can eject
 
861
      if li[num].can_eject():
 
862
        li[num].eject(self.ejected_or_unmounted)
 
863
        return True
 
864
 
 
865
      #If the mount can unmount
 
866
      elif li[num].can_unmount():
 
867
        li[num].unmount(self.ejected_or_unmounted)
 
868
        return True
 
869
 
 
870
    return False
 
871
 
 
872
  def icon_clicked(self, widget):
 
873
    event = gtk.get_current_event()
 
874
 
 
875
    #Dialog mode
 
876
    if self.client.get_int(group, 'mode') == 0:
796
877
      if self.dialog.flags() & gtk.VISIBLE:
797
878
        self.dialog.hide()
798
879
 
799
880
      else:
800
881
        self.dialog_config(event.button)
801
882
 
802
 
    elif event.button == 3:
803
 
      self.dialog.hide()
804
 
      self.show_menu(event)
 
883
    #Docklet mode
 
884
    else:
 
885
      self.dialog_config(event.button)
 
886
 
 
887
  def show_context_menu(self, widget, event):
 
888
    self.dialog.hide()
 
889
    self.show_menu(event)
 
890
 
 
891
  def show_docklet(self, window_id):
 
892
    self.docklet_visible = True
 
893
    docklet = awn.Applet(self.get_canonical_name(), self.props.uid, self.props.panel_id)
 
894
    docklet.props.quit_on_delete = False
 
895
    self.docklet = docklet
 
896
 
 
897
    def invalidate_docklet(widget, applet):
 
898
      applet.docklet_visible = False
 
899
      applet.docklet = None
 
900
      applet.docklet_play_pause = None
 
901
    docklet.connect("destroy", invalidate_docklet, self)
 
902
 
 
903
    docklet_position = docklet.get_pos_type()
 
904
    top_box = awn.Box()
 
905
    top_box.set_orientation_from_pos_type(docklet_position)
 
906
 
 
907
    align = awn.Alignment(docklet)
 
908
    box = awn.Box()
 
909
    box.set_orientation_from_pos_type(docklet_position)
 
910
    align.add(box)
 
911
 
 
912
    align.set(0.5, 0.5, 1.0, 1.0)
 
913
    top_box.pack_start(align)
 
914
 
 
915
    self.docklet_box = awn.IconBox(docklet)
 
916
 
 
917
    self.update_docklet(False)
 
918
 
 
919
    top_box.pack_start(self.docklet_box, True, True)
 
920
    docklet.add(top_box)
 
921
 
 
922
    gtk.Plug.__init__(docklet, long(window_id))
 
923
 
 
924
    self.update_docklet()
 
925
 
 
926
  def update_docklet(self, show_all=True):
 
927
    if self.mode == 1:
 
928
      box = self.docklet_box
 
929
 
 
930
    elif self.mode == 2:
 
931
      box = self.icon_box
 
932
 
 
933
    for icon in box.get_children():
 
934
      if icon == self.icon:
 
935
        box.remove(icon)
 
936
      else:
 
937
        icon.destroy()
 
938
 
 
939
    for place in self.places_data:
 
940
      icon = awn.Icon()
 
941
      icon.set_from_pixbuf(self.load_pixbuf(place[0], self.get_size()))
 
942
      icon.set_tooltip_text(place[1])
 
943
      icon.connect('clicked', self.docklet_icon_clicked, place[3])
 
944
      icon.connect('context-menu-popup', self.docklet_icon_menu, place)
 
945
      box.add(icon)
 
946
      box.set_child_packing(icon, False, True, 0, gtk.PACK_START)
 
947
 
 
948
      if gio and place[3] in self.droppable_places:
 
949
        icon.drag_dest_set(gtk.DEST_DEFAULT_DROP | gtk.DEST_DEFAULT_MOTION, \
 
950
          [("text/uri-list", 0, 0)], gtk.gdk.ACTION_MOVE)
 
951
        icon.connect('drag-data-received', self.docklet_drag_data_received, place[3])
 
952
        icon.connect('drag-motion', self.docklet_drag_motion)
 
953
        icon.connect('drag-leave', self.docklet_drag_leave)
 
954
 
 
955
    if show_all and self.mode == 1:
 
956
      self.docklet.show_all()
 
957
 
 
958
    elif show_all and self.mode == 2:
 
959
      self.icon_box.show_all()
 
960
 
 
961
  def docklet_drag_data_received(self, w, context, x, y, data, info, time, path):
 
962
    if data and data.format == 8:
 
963
      context.finish(True, False, time)
 
964
 
 
965
      if path in self.droppable_places:
 
966
        dropped_paths = data.data.split('\n')
 
967
        num_success = 0
 
968
 
 
969
        for dropped_path in dropped_paths:
 
970
          if len(dropped_path) >= 8:
 
971
            if dropped_path[:8] == 'file:///':
 
972
              dropped_path = dropped_path.strip()
 
973
 
 
974
              dropped_path = urllib.unquote(dropped_path)
 
975
 
 
976
              from_file = gio.File(dropped_path)
 
977
 
 
978
              to_file = gio.File(path + '/' + from_file.get_basename())
 
979
 
 
980
              #Make sure we're not just moving the file to the same directory
 
981
              if not from_file.equal(to_file):
 
982
                if from_file.move(to_file):
 
983
                  num_success += 1
 
984
 
 
985
        if num_success > 0:
 
986
          config_fb = self.client.get_string(group, 'fb')
 
987
          open_dir = path.replace(' ', '\ ')
 
988
          os.system('%s %s &' % (config_fb, open_dir))
 
989
          self.dialog.hide()
 
990
 
 
991
      return True
 
992
 
 
993
  def docklet_drag_motion(self, icon, context, x, y, time):
 
994
    icon.get_effects().start(awn.EFFECT_LAUNCHING)
 
995
    icon.get_tooltip().update_position()
 
996
    icon.get_tooltip().show()
 
997
 
 
998
    return True
 
999
 
 
1000
  def docklet_drag_leave(self, icon, context, time):
 
1001
    icon.get_effects().stop(awn.EFFECT_LAUNCHING)
 
1002
    icon.get_tooltip().hide()
 
1003
 
 
1004
    return True
 
1005
 
 
1006
  def docklet_icon_clicked(self, icon, uri):
 
1007
    self.launch_fb(None, uri)
 
1008
 
 
1009
    if self.mode == 1:
 
1010
      self.docklet.destroy()
 
1011
 
 
1012
  def docklet_icon_menu(self, icon, event, place):
 
1013
    menu = self.create_default_menu()
 
1014
 
 
1015
    #If the place is ejectable
 
1016
    if place[2]:
 
1017
      eject = awn.image_menu_item_new_with_label(_("Eject"))
 
1018
      image = gtk.image_new_from_icon_name('media-eject', gtk.ICON_SIZE_MENU)
 
1019
      eject.set_image(image)
 
1020
      menu.append(eject)
 
1021
 
 
1022
      eject.connect('activate', self.docklet_menu_eject, place[4])
 
1023
 
 
1024
    prefs = gtk.ImageMenuItem(gtk.STOCK_PREFERENCES)
 
1025
    prefs.connect('activate', self.open_prefs)
 
1026
    menu.append(prefs)
 
1027
 
 
1028
    about = gtk.ImageMenuItem(gtk.STOCK_ABOUT)
 
1029
    about.connect("activate", self.open_about)
 
1030
    menu.append(about)
 
1031
 
 
1032
    menu.show_all()
 
1033
    menu.popup(None, None, None, event.button, event.time)
 
1034
 
 
1035
  def docklet_menu_eject(self, menu, num):
 
1036
    self.unmount(num)
805
1037
 
806
1038
  #The user changed the icon theme
807
1039
  def icon_theme_changed(self, icon_theme):
808
 
    for key in self.icons.keys():
809
 
      del self.icons[key]
 
1040
    for d in self.icons.values():
 
1041
      for key in d.keys():
 
1042
        del d[key]
810
1043
 
811
1044
    if gio:
812
1045
      self.do_gio_places()
813
1046
 
814
1047
    #Reload the stock folder icon
815
 
    self.icons['stock_folder'] = self.theme.load_icon('stock_folder', 24, 24)
 
1048
    self.icons[24]['stock_folder'] = self.theme.load_icon('stock_folder', 24, 0)
816
1049
 
817
 
  #dialog_config: 
818
1050
  def dialog_config(self, button):
819
 
    if button not in (1, 2):
820
 
      return False
821
 
    self.curr_button = button
 
1051
    #Left click data
 
1052
    if button == 1:
 
1053
      action = self.client.get_int(group, 'lmb')
 
1054
      path = os.path.expanduser(self.client.get_string(group, 'lmb_path'))
 
1055
 
 
1056
    #Middle click data
 
1057
    elif button == 2:
 
1058
      action = self.client.get_int(group, 'mmb')
 
1059
      path = os.path.expanduser(self.client.get_string(group, 'mmb_path'))
 
1060
 
 
1061
    if action == 3:
 
1062
      return
 
1063
 
 
1064
    if not gio:
 
1065
      self.add_places()
 
1066
 
 
1067
    mode = self.client.get_int(group, 'mode')
822
1068
 
823
1069
    #Get whether to focus the entry when displaying the dialog or not
824
1070
    config_focus = self.client.get_int(group, 'focus_entry')
825
1071
 
826
 
    if button == 1: #Left mouse button
827
 
    #Get the value for the left mouse button to automatically open.
828
 
    #Create and default to 1 the entry if it doesn't exist
829
 
    #Also get the default directory or default to ~
830
 
      config_lmb = self.client.get_int(group, 'lmb')
831
 
      config_lmb_path = self.client.get_string(group, 'lmb_path')
832
 
      config_lmb_path = os.path.expanduser(config_lmb_path)
833
 
 
834
 
    elif button == 2: #Middle mouse button
835
 
    #Get the value for the middle mouse button to automatically open.
836
 
    #Create and default to 2 the entry if it doesn't exist
837
 
    #Also get the default directory or default to ~
838
 
      config_mmb = self.client.get_int(group, 'mmb')
839
 
      config_mmb_path = self.client.get_string(group, 'mmb_path')
840
 
      config_mmb_path = os.path.expanduser(config_mmb_path)
841
 
 
842
 
    #Left mouse button - either popup with correct path or launch correct path OR do nothing
843
 
    if button == 1:
844
 
      if config_lmb == 1:
845
 
        self.entry.set_text(config_lmb_path)
846
 
 
847
 
        if not gio:
848
 
          self.add_places()
849
 
 
850
 
        if config_focus == 2:
851
 
          self.entry.grab_focus()
852
 
          self.entry.set_position(-1)
853
 
 
854
 
        self.dialog.show_all()
855
 
 
856
 
      elif config_lmb == 2:
857
 
        self.launch_fb(None, config_lmb_path)
858
 
 
859
 
    #Right mouse button - either popup with correct path or launch correct path OR do nothing
860
 
    if button == 2:
861
 
      if config_mmb == 1:
862
 
        self.entry.set_text(config_mmb_path)
863
 
 
864
 
        if not gio:
865
 
          self.add_places()
866
 
 
867
 
        if config_focus == 2:
868
 
          self.entry.grab_focus()
869
 
          self.entry.set_position(-1)
870
 
 
871
 
        self.dialog.show_all()
872
 
 
873
 
      elif config_mmb == 2:
874
 
        self.launch_fb(None, config_mmb_path)
 
1072
    #Show dialog/docklet
 
1073
    if action == 1:
 
1074
      #Docklet
 
1075
      if mode == 1:
 
1076
        #Occasionally this happens; don't do two docklets at once
 
1077
        if not self.docklet_visible:
 
1078
          win = self.docklet_request(0, True, True)
 
1079
          if win != 0:
 
1080
            self.show_docklet(win)
 
1081
 
 
1082
      #Dialog
 
1083
      else:
 
1084
        self.entry.set_text(path)
 
1085
 
 
1086
        if config_focus == 2:
 
1087
          self.entry.grab_focus()
 
1088
          self.entry.set_position(-1)
 
1089
 
 
1090
        self.dialog.show_all()
 
1091
 
 
1092
    #Launch path
 
1093
    elif action == 2:
 
1094
      self.launch_fb(None, path)
 
1095
 
 
1096
  def update_mode(self, *args):
 
1097
    self.mode = self.client.get_int(group, 'mode')
 
1098
 
 
1099
    self.dialog.hide()
 
1100
 
 
1101
    if 'docklet' in dir(self) and self.docklet is not None:
 
1102
      self.docklet.destroy()
 
1103
 
 
1104
    if self.mode != 2:
 
1105
      self.docklet_visible = False
 
1106
 
 
1107
      for icon in self.icon_box.get_children():
 
1108
        if icon == self.icon:
 
1109
          self.icon_box.remove(icon)
 
1110
        else:
 
1111
          icon.destroy()
 
1112
 
 
1113
      self.icon_box.add(self.icon)
 
1114
      self.show_all()
 
1115
 
 
1116
    else:
 
1117
      self.docklet_visible = True
 
1118
      self.update_docklet()
875
1119
 
876
1120
  #If the user hits the enter key on the main part OR the number pad
877
1121
  def detect_enter(self, a, event):
888
1132
    config_fb = self.client.get_string(group, 'fb')
889
1133
 
890
1134
    #In case there is nothing but whitespace (or at all) in the entry widget
891
 
    if path.replace(' ','') == '':
 
1135
    if path.replace(' ', '') == '':
892
1136
      path = os.environ['HOME']
893
1137
 
894
1138
    #Check if we're supposed to open nautilus-connect-server
906
1150
      os.system('%s %s &' % (config_fb, path.replace(' ', '\ ')))
907
1151
 
908
1152
  #Right click menu - Preferences or About
909
 
  def show_menu(self,event):
 
1153
  def show_menu(self, event):
910
1154
    #Hide the dialog if it's shown
911
1155
    self.dialog.hide()
912
1156
 
913
1157
    #Create the items for Preferences and About
914
 
    self.prefs = gtk.ImageMenuItem(gtk.STOCK_PREFERENCES)
915
 
    self.about = gtk.ImageMenuItem(gtk.STOCK_ABOUT)
 
1158
    prefs = gtk.ImageMenuItem(gtk.STOCK_PREFERENCES)
 
1159
    about = gtk.ImageMenuItem(gtk.STOCK_ABOUT)
916
1160
 
917
1161
    #Connect the two items to functions when clicked
918
 
    self.prefs.connect("activate", self.open_prefs)
919
 
    self.about.connect("activate", self.open_about)
 
1162
    prefs.connect("activate", self.open_prefs)
 
1163
    about.connect("activate", self.open_about)
920
1164
 
921
1165
    #Now create the menu to put the items in and show it
922
1166
    self.menu = self.create_default_menu()
923
 
    self.menu.append(self.prefs)
924
 
    self.menu.append(self.about)
 
1167
    self.menu.append(prefs)
 
1168
    self.menu.append(about)
925
1169
    self.menu.show_all()
926
1170
    self.menu.popup(None, None, None, event.button, event.time)
927
1171
 
928
1172
  #Show the preferences window
929
 
  def open_prefs(self,widget):
 
1173
  def open_prefs(self, widget):
930
1174
    #Import the prefs file from the same directory
931
1175
    import prefs
932
1176
 
935
1179
    gtk.main()
936
1180
 
937
1181
  #Show the about window
938
 
  def open_about(self,widget):
 
1182
  def open_about(self, widget):
939
1183
    #Import the about file from the same directory
940
1184
    import about
941
1185