Codebase list kupfer / d8797c5
Imported Upstream version 0+c10 SVN-Git Migration 6 years ago
40 changed file(s) with 2956 addition(s) and 1955 deletion(s). Raw diff Collapse all Expand all
0 c9.1
0 c10
00 NEWS for kupfer
11 ===============
2
3 kupfer version c10
4 -----------------
5
6 * Updated italian localization
7 * New plugins: Url Actions, Web Search (rewritten to use all Firefox' search
8 engines)
9 * New actions: _Set Default Application_, _Create Archive In..._,
10 _Restore_ (Restore trashed file)
11 * Add accelerators `Control+R` for reset, `Control+S` for select first
12 (source) pane and `Control+.` for untoggle text mode.
13 * Only the bookmarks plugins can toggle "include in toplevel" now.
14 * Other smaller changes (Refuse invalid Application objects from the
15 cache)
16
17 This release is localized in: Swedish (100%), Italian (93%)
218
319 kupfer version c9.1
420 -----------------
5454 [plugin_epiphany]
5555 kupfer_enabled = True
5656 kupfer_toplevel = False
57 kupfer_show_toplevel = True
5758
5859 [plugin_favorites]
5960 kupfer_enabled = True
6465 [plugin_firefox]
6566 kupfer_enabled = True
6667 kupfer_toplevel = False
68 kupfer_show_toplevel = True
6769
6870 [plugin_google]
6971 kupfer_enabled = True
8385 [plugin_tracker]
8486 kupfer_enabled = False
8587
88 [plugin_urlactions]
89 kupfer_enabled = True
90
8691 [plugin_volumes]
8792 kupfer_enabled = True
8893
0 <?xml version="1.0" encoding="UTF-8"?>
1 <SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/"
2 xmlns:os="http://a9.com/-/spec/opensearch/1.1/">
3 <os:ShortName>Google</os:ShortName>
4 <os:Description></os:Description>
5 <os:InputEncoding>UTF-8</os:InputEncoding>
6 <os:Url type="text/html" method="GET" template="http://www.google.com/search?q={searchTerms}"></os:Url>
7 </SearchPlugin>
11 bld.install_files("${DATADIR}/kupfer", "defaults.cfg")
22 bld.install_files("${DATADIR}/kupfer", "preferences.ui")
33
4 # install all art files
4 # install all pure data files
55 bld.install_files("${DATADIR}/kupfer/art", "art/*")
6 bld.install_files("${DATADIR}/kupfer/searchplugins", "searchplugins/*")
67
78 # compress and install man page
89 bld.new_task_gen(
+0
-87
debug.py less more
0 """
1 Debugging routines. To use this, simply import this module
2 """
3
4 import atexit
5
6 def mem_stats():
7 import gc
8 print "DEBUG: OBJ STATS"
9
10 print "enabled:", gc.isenabled()
11 print "objs", len(gc.get_objects())
12 print "collected (now)", gc.collect()
13
14 # after collection
15 hist = {}
16 for obj in gc.get_objects():
17 key = str(type(obj))
18 if key not in hist:
19 hist[key] =1
20 else:
21 hist[key] += 1
22
23 best = hist.items()
24 best.sort(key=lambda x:x[1], reverse=True)
25 print "\n".join("%s: %d" % (k,v) for k,v in best[:10])
26
27 our = []
28 gtk = []
29 for item in best:
30 if "objects." in item[0] or "kupfer." in item[0]:
31 our.append(item)
32 if "gtk" in item[0]:
33 gtk.append(item)
34
35 print "---just gtk (top)"
36 print "\n".join("%s: %d" % (k,v) for k,v in gtk[:10])
37 print "---Just our objects (all)"
38 print "\n".join("%s: %d" % (k,v) for k,v in our)
39
40 def make_histogram(vect, nbins=7):
41 """make a histogram out of @vect"""
42 mi,ma = 0, max(vect)
43 bins = [0]*nbins
44 bin_size = ma/nbins + 1
45 def brange(i):
46 return xrange(i*bin_size, (i+1)*bin_size)
47 for acc in vect:
48 for i in xrange(nbins):
49 if acc in brange(i):
50 bins[i] += 1
51 break
52 # headers
53 print " ".join("%10s" % ("[%2d, %2d)" % (min(brange(i)), max(brange(i))),) for i in xrange(nbins))
54 print " ".join("%10d" % bins[i] for i in xrange(nbins))
55
56
57 def icon_stats():
58 from kupfer.icons import icon_cache
59 print "DEBUG: ICON STATS"
60
61 c = 0
62 tot_acc = 0
63 tot_pix = 0
64 acc_vect = []
65 for size in icon_cache:
66 for k in icon_cache[size]:
67 rec = icon_cache[size][k]
68 acc = rec["accesses"]
69 acc_vect.append(acc)
70 if not acc:
71 c += 1
72 tot_acc += acc
73 icon = rec["icon"]
74 tot_pix += icon.get_height() * icon.get_width()
75 print "Cached icons:", len(icon_cache[size])
76 print "Unused cache entries", c
77 print "Total accesses", tot_acc
78 print make_histogram(acc_vect)
79 print "Sum pixels", tot_pix
80 print "Cached icon keys:"
81 for k in sorted(icon_cache[size],
82 key=lambda k: icon_cache[size][k]["accesses"]):
83 print k, icon_cache[size][k]["accesses"]
84
85 atexit.register(mem_stats)
86 atexit.register(icon_stats)
44 import signal
55 import os
66 import time
7
8 import pygtk
9 pygtk.require('2.0')
710
811 import gtk
912 import gio
702705 self._key_press_time = None
703706 self._key_press_interval = 0.8
704707 self._key_pressed = None
705 self._theme_entry_bg = self.entry.style.bg[gtk.STATE_NORMAL]
706 self._theme_entry_text = self.entry.style.text[gtk.STATE_NORMAL]
707 self.entry.connect("map-event", self._map_entry)
708 self._theme_colors = {}
709 self.entry.set_size_request(0, 0)
710 window.connect("map-event", self._map_window)
708711
709712 from pango import ELLIPSIZE_END
710713 self.label.set_width_chars(50)
771774 self._widget = vbox
772775 return vbox
773776
774 def _map_entry(self, widget, event):
777 def _map_window(self, widget, event):
775778 """When Interface's widget is mapped and shown on the screen"""
776779 # Now we can read the style from the real theme
777 self._theme_entry_bg = self.entry.style.bg[gtk.STATE_NORMAL]
778 self._theme_entry_text = self.entry.style.text[gtk.STATE_NORMAL]
780 if not self._theme_colors:
781 self._theme_colors["bg"] = self.entry.style.bg[gtk.STATE_NORMAL]
782 self._theme_colors["text"] = self.entry.style.text[gtk.STATE_NORMAL]
779783 self.update_text_mode()
780784
781785 def _pane_button_press(self, widget, event):
793797 """
794798 keyv = event.keyval
795799 key_book = self.key_book
800
801 # FIXME: These should be configurable
802 accels = {
803 "<Control>period" : "toggle_text_mode_quick",
804 "<Control>s" : "switch_to_source",
805 "<Control>r" : "reset_all",
806 }
796807 # test for alt modifier (MOD1_MASK is alt/option)
797808 modifiers = gtk.accelerator_get_default_mod_mask()
798809 mod1_mask = ((event.state & modifiers) == gtk.gdk.MOD1_MASK)
807818 # if input is slow/new, we reset
808819 if not text_mode and input_time_diff > self._slow_input_interval:
809820 self.reset_text()
821
822 # process accelerators
823 for accel in accels:
824 keyvalue, modifiers = gtk.accelerator_parse(accel)
825 if not keyvalue:
826 continue
827 if keyv == keyvalue and (modifiers == (event.state & modifiers)):
828 action = accels[accel]
829 action_method = getattr(self, action, None)
830 if not action_method:
831 print "Error: no action", action
832 else:
833 action_method()
834 return True
810835
811836 has_selection = (self.current.get_match_state() is State.Match)
812837 can_text_mode = self.get_can_enter_text_mode()
896921 else:
897922 self.current.reset()
898923
924 def reset_all(self):
925 """Reset all panes and focus the first"""
926 self.reset_current()
927 self.reset()
928 self.switch_to_source()
929 while self._browse_up():
930 pass
931
899932 def _reset_key_press(self, escape=False):
900933 """Handle leftarrow, backspace and escape
901934 Go up back through browsed sources.
934967 self.reset()
935968 return val
936969
970 def toggle_text_mode_quick(self):
971 """Toggle text mode or not, if we can, without reset"""
972 if self._is_text_mode:
973 self._is_text_mode = False
974 else:
975 self._is_text_mode = self.get_can_enter_text_mode()
976 self.update_text_mode()
977
937978 def update_text_mode(self):
938979 """update appearance to whether text mode enabled or not"""
980 if not self._theme_colors:
981 return
939982 if self._is_text_mode:
940983 self.entry.set_size_request(-1,-1)
941984 self.entry.set_property("has-frame", True)
942985 bgcolor = gtk.gdk.color_parse("light goldenrod yellow")
943 self.entry.modify_text(gtk.STATE_NORMAL, self._theme_entry_text)
944 self.entry.modify_text(gtk.STATE_NORMAL, gtk.gdk.color_parse("black"))
986 theme_entry_text = self._theme_colors["text"]
987 self.entry.modify_text(gtk.STATE_NORMAL, theme_entry_text)
945988 self.entry.modify_base(gtk.STATE_NORMAL, bgcolor)
946989 self.current.set_state(gtk.STATE_ACTIVE)
947990 else:
948991 self.entry.set_size_request(0,0)
949992 self.entry.set_property("has-frame", False)
950 self.entry.modify_text(gtk.STATE_NORMAL, self._theme_entry_bg)
951 self.entry.modify_base(gtk.STATE_NORMAL, self._theme_entry_bg)
993 theme_entry_bg = self._theme_colors["bg"]
994 self.entry.modify_text(gtk.STATE_NORMAL, theme_entry_bg)
995 self.entry.modify_base(gtk.STATE_NORMAL, theme_entry_bg)
952996 self.current.set_state(gtk.STATE_SELECTED)
953997 self._size_window_optimally()
954998
10501094 self.data_controller.browse_down(pane, alternate=alternate)
10511095
10521096 def _activate(self, widget, current):
1097 # reset self through toggle_text_mode
10531098 self.data_controller.activate()
1054 self.reset()
1099 self.toggle_text_mode(False)
10551100
10561101 def _search_result(self, sender, pane, matchrankable, matches, context):
10571102 key = context
11281173 """
11291174 """
11301175 self.icon_name = gtk.STOCK_FIND
1131 self.data_controller = data.DataController()
11321176 self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
1133 self.interface = Interface(self.data_controller, self.window)
1177
1178 data_controller = data.DataController()
1179 data_controller.connect("launched-action", self.launch_callback)
1180
1181 self.interface = Interface(data_controller, self.window)
1182 self.interface.connect("cancelled", self._cancelled)
11341183 self._setup_window()
1135 self.interface.connect("cancelled", self._cancelled)
1136 self.data_controller.connect("launched-action", self.launch_callback)
1137 self._keystr = ""
11381184 self._statusicon = None
11391185
11401186 def show_statusicon(self):
12051251
12061252 def activate(self, sender=None, time=0):
12071253 evttime = time if time else gtk.get_current_event_time()
1208 self.window.show()
12091254 self.window.stick()
1255 self.window.present_with_time(time)
12101256 self.window.window.focus(timestamp=evttime)
12111257 self.interface.focus()
12121258
12841330 (keybinding callback, session logout callbacks etc)
12851331 """
12861332 # register dbus callbacks
1287 from .listen import Service, AlreadyRunning, NoConnection
1333 from . import listen
12881334 from .session import SessionClient
12891335 from kupfer import scheduler, settings
12901336 from kupfer import keybindings
12911337
12921338 try:
1293 s = Service()
1294 except AlreadyRunning:
1339 s = listen.Service()
1340 except listen.AlreadyRunning:
12951341 s = None
12961342 self.output_info("An instance is already running, exiting...")
12971343 self.quit_now()
1298 except NoConnection:
1344 except listen.NoConnection:
12991345 pass
13001346 else:
13011347 s.connect("present", self.activate)
13301376 client.connect("save-yourself", self._session_save)
13311377 client.connect("die", self._session_die)
13321378
1379 def main_iterations(max_events=0):
1380 # use sentinel form of iter
1381 for idx, pending in enumerate(iter(gtk.events_pending, False)):
1382 if max_events and idx > max_events:
1383 break
1384 gtk.main_iteration()
1385
13331386 try:
13341387 gtk.main()
13351388 # put away window *before exiting further*
13361389 self.put_away()
1337 while gtk.events_pending():
1338 gtk.main_iteration()
1390 main_iterations(10)
13391391 except KeyboardInterrupt, info:
13401392 self.output_info(info, "exiting.. (Warning: Ctrl-C in the shell",
13411393 "will kill child processes)")
13421394 finally:
13431395 self.save_data()
13441396
1397 # Now dismantle everything but keep hanging
1398 listen.Unregister()
1399 keybindings.bind_key(None)
1400 main_iterations(100)
1401 # if we are still waiting, print a message
1402 if gtk.events_pending():
1403 self.output_info("Waiting for tasks to finish...")
1404 main_iterations()
3333 Return path to @filename if it exists
3434 anywhere in the data paths, else return None
3535 """
36 # Add "./data" in workdir for running from builddir
3736 data_paths = []
38 data_paths.append("./data")
39 data_paths.extend(base.load_data_paths(PACKAGE_NAME))
37 try:
38 from . import version_subst
39 except ImportError:
40 first_datadir = "./data"
41 else:
42 first_datadir = os.path.join(version_subst.DATADIR, PACKAGE_NAME)
43
44 data_paths.append(first_datadir)
45 for data_path in base.load_data_paths(PACKAGE_NAME):
46 if not data_path in data_paths:
47 data_paths.append(data_path)
4048
4149 for direc in data_paths:
4250 file_path = os.path.join(direc, filename)
6270 """
6371 return base.save_data_path(PACKAGE_NAME)
6472
65 def get_data_dirs(name=""):
73 def get_data_dirs(name="", package=PACKAGE_NAME):
6674 """
6775 Iterate over all data dirs of @name that exist
6876 """
69 return base.load_data_paths(os.path.join(PACKAGE_NAME, name))
77 return base.load_data_paths(os.path.join(package, name))
7078
7179 def get_config_file(filename):
7280 """
0 import gzip
1 import hashlib
02 import itertools
13 import os
24 import cPickle as pickle
79 import gobject
810 gobject.threads_init()
911
10 from . import search
1112 from . import objects
12 from . import config
13 from . import pretty
14 from . import learn
15 from . import scheduler
13 from . import search, learn
14 from . import config, pretty, scheduler, task
1615
1716 # "Enums"
1817 # Which pane
2120 # In two-pane or three-pane mode
2221 SourceActionMode, SourceActionObjectMode = (1,2)
2322
24
25 class SearchTask (pretty.OutputMixin):
23 def identity(x):
24 return x
25
26 def dress_leaves(seq, action):
27 """yield items of @seq "dressed" by the source controller"""
28 sc = GetSourceController()
29 for itm in seq:
30 sc.decorate_object(itm.object, action=action)
31 yield itm
32
33 class Searcher (object):
2634 """
35 This class searches KupferObjects efficiently, and
36 stores searches in a cache for a very limited time (*)
37
38 (*) As of this writing, the cache is used when the old key
39 is a prefix of the search key.
2740 """
2841
2942 def __init__(self):
3043 self._source_cache = {}
3144 self._old_key = None
3245
33 def __call__(self, sources, key, score=True, item=None, action=None):
34 """
35 @sources is a dict listing the inputs and how they are ranked
36
37 if @score, sort by score, else no sort
38 if @item, check against it's (Action) object requriements
39 and sort by it
46 def search(self, sources, key, score=True, item_check=None, decorator=None):
47 """
48 @sources is a sequence listing the inputs, which should be
49 Sources, TextSources or sequences of KupferObjects
50
51 If @score, sort by rank.
52 filters (with identity() as default):
53 item_check: Check items before adding to search pool
54 decorator: Decorate items before access
55
56 Return (first, match_iter), where first is the first match,
57 and match_iter an iterator to all matches, including the first match.
4058 """
4159 if not self._old_key or not key.startswith(self._old_key):
4260 self._source_cache.clear()
43 self._old_key = ""
4461 self._old_key = key
4562
46 # Set up object and type checking for
47 # action + secondary object
48 item_check = lambda x: x
49 if item and action:
50 types = tuple(action.object_types())
51 def type_obj_check(itms):
52 for i in itms:
53 if (isinstance(i, types) and
54 action.valid_object(i, for_item=item)):
55 yield i
56 def type_check(itms):
57 for i in itms:
58 if isinstance(i, types):
59 yield i
60
61 if hasattr(action, "valid_object"):
62 item_check = type_obj_check
63 else:
64 item_check = type_check
63 if not item_check: item_check = identity
64 if not decorator: decorator = identity
6565
6666 match_iters = []
6767 for src in sources:
68 items = ()
6968 fixedrank = 0
7069 rankables = None
7170 if isinstance(src, objects.Source):
8483 if not rankables:
8584 rankables = search.make_rankables(items)
8685
87 if fixedrank:
88 # we have a given rank
89 matches = search.add_rank_objects(rankables, fixedrank)
90 elif score:
91 if key:
86 if score:
87 if fixedrank:
88 rankables = search.add_rank_objects(rankables, fixedrank)
89 elif key:
9290 rankables = search.score_objects(rankables, key)
9391 matches = search.bonus_objects(rankables, key)
9492 if isinstance(src, objects.Source):
95 # we fork off a copy of the iterator
93 # we fork off a copy of the iterator to save
9694 matches, self._source_cache[src] = itertools.tee(matches)
9795 else:
9896 # we only want to list them
113111 if reprobj not in coll:
114112 yield obj
115113 coll.add(reprobj)
116
117 def dress_leaves(seq):
118 """yield items of @seq "dressed" by the source controller"""
119 sc = GetSourceController()
120 for itm in seq:
121 sc.decorate_object(itm.object, action=action)
122 yield itm
123114
124115 def valid_check(seq):
125116 """yield items of @seq that are valid"""
142133 # Check if the items are valid as the search
143134 # results are accessed through the iterators
144135 unique_matches = as_set_iter(matches)
145 match, match_iter = peekfirst(dress_leaves(valid_check(unique_matches)))
136 match, match_iter = peekfirst(decorator(valid_check(unique_matches)))
146137 return match, match_iter
147
148 class RescanThread (threading.Thread, pretty.OutputMixin):
149 def __init__(self, source, sender, signal, context=None, **kwargs):
150 super(RescanThread, self).__init__(**kwargs)
151 self.source = source
152 self.sender = sender
153 self.signal = signal
154 self.context = context
155
156 def run(self):
157 self.output_debug(repr(self.source))
158 items = self.source.get_leaves(force_update=True)
159 if self.sender and self.signal:
160 gobject.idle_add(self.sender.emit, self.signal, self.context)
161138
162139 class PeriodicRescanner (gobject.GObject, pretty.OutputMixin):
163140 """
174151 self.startup = startup
175152 self.period = period
176153 self.campaign=campaign
177 self.cur_event = 0
154 self.timer = scheduler.Timer()
178155 # Source -> time mapping
179156 self.latest_rescan_time = {}
180157 self._min_rescan_interval = campaign/10
182159 def set_catalog(self, catalog):
183160 self.catalog = catalog
184161 self.cur = iter(self.catalog)
185 if self.cur_event:
186 gobject.source_remove(self.cur_event)
187162 self.output_debug("Registering new campaign, in %d s" % self.startup)
188 self.cur_event = gobject.timeout_add_seconds(self.startup, self._new_campaign)
163 self.timer.set(self.startup, self._new_campaign)
189164
190165 def _new_campaign(self):
191166 self.output_info("Starting new campaign, interval %d s" % self.period)
192167 self.cur = iter(self.catalog)
193 self.cur_event = gobject.timeout_add_seconds(self.period, self._periodic_rescan_helper)
168 self.timer.set(self.period, self._periodic_rescan_helper)
194169
195170 def _periodic_rescan_helper(self):
196171 # Advance until we find a source that was not recently rescanned
197172 for next in self.cur:
198173 oldtime = self.latest_rescan_time.get(next, 0)
199174 if (time.time() - oldtime) > self._min_rescan_interval:
200 break
201 else:
202 # else <=> break not reached in loop
203 self.output_info("Campaign finished, pausing %d s" % self.campaign)
204 self.cur_event = gobject.timeout_add_seconds(self.campaign,
205 self._new_campaign)
206 return False
207 self.cur_event = gobject.idle_add(self.reload_source, next)
208 return True
209
210 def register_rescan(self, source, force=False):
175 self.timer.set(self.period, self._periodic_rescan_helper)
176 self._start_source_rescan(next)
177 return
178 # No source to scan found
179 self.output_info("Campaign finished, pausing %d s" % self.campaign)
180 self.timer.set(self.campaign, self._new_campaign)
181
182 def register_rescan(self, source, sync=False):
211183 """Register an object for rescan
212 dynamic sources will only be rescanned if @force is True
213 """
214 self.reload_source(source, force)
215
216 def reload_source(self, source, force=False):
184 If @sync, it will be rescanned synchronously
185 """
186 self._start_source_rescan(source, sync)
187
188 def _start_source_rescan(self, source, sync=False):
217189 self.latest_rescan_time[source] = time.time()
218 if force:
219 source.get_leaves(force_update=True)
220 self.emit("reloaded-source", source)
190 if sync:
191 self.rescan_source(source)
221192 elif not source.is_dynamic():
222 rt = RescanThread(source, self, "reloaded-source", context=source)
223 rt.start()
193 thread = threading.Thread(target=self.rescan_source, args=(source,))
194 thread.start()
195
196 def rescan_source(self, source):
197 items = source.get_leaves(force_update=True)
198 gobject.idle_add(self.emit, "reloaded-source", source)
224199
225200 gobject.signal_new("reloaded-source", PeriodicRescanner, gobject.SIGNAL_RUN_LAST,
226201 gobject.TYPE_BOOLEAN, (gobject.TYPE_PYOBJECT,))
227202
228 class SourcePickleService (pretty.OutputMixin, object):
203 class SourcePickler (pretty.OutputMixin):
229204 """
230 Singleton that should be accessed with
231 GetSourcePickleService()
205 Takes care of pickling and unpickling Kupfer Sources.
232206 """
233 pickle_version = 2
234 name_template = "kupfer-%s-v%d.pickle.gz"
235
236 def __call__(self):
237 return self
207 pickle_version = 3
208 name_template = "k%s-v%d.pickle.gz"
209
238210 def __init__(self):
239 import gzip
240211 self.open = lambda f,mode: gzip.open(f, mode, compresslevel=3)
241 # Check if there are old cache files
242 self._rm_old_cachefiles()
243
244 def _rm_old_cachefiles(self):
212
213 def rm_old_cachefiles(self):
214 """Checks if there are old cachefiles from last version,
215 and deletes those
216 """
245217 for dpath, dirs, files in os.walk(config.get_cache_home()):
246218 # Look for files matching beginning and end of
247219 # name_template, with the previous file version
258230 for fpath in obsolete_files:
259231 # be overly careful
260232 assert fpath.startswith(config.get_cache_home())
261 assert "kupfer" in os.path.basename(fpath)
233 assert "kupfer" in fpath
262234 os.unlink(fpath)
263235
264236 def get_filename(self, source):
265 from os import path
266
267 hashstr = "%010d" % abs(hash(source))
237 """Return cache filename for @source"""
238 bytes = hashlib.md5(repr(source)).digest()
239 hashstr = bytes.encode("base64").rstrip("\n=").replace("/", "-")
268240 filename = self.name_template % (hashstr, self.pickle_version)
269 return path.join(config.get_cache_home(), filename)
241 return os.path.join(config.get_cache_home(), filename)
270242
271243 def unpickle_source(self, source):
272244 cached = self._unpickle_source(self.get_filename(source))
274246 return None
275247
276248 # check consistency
277 if (type(source) == type(cached) and
278 (hasattr(source, "version") == hasattr(cached, "version") and
279 source.version == cached.version)):
249 if source == cached:
280250 return cached
281251 else:
282 self.output_debug("Source version changed to %s %s" %
283 (source, source.version))
252 self.output_debug("Cached version mismatches", source)
284253 return None
285254 def _unpickle_source(self, pickle_file):
286255 try:
290259 try:
291260 source = pickle.loads(pfile.read())
292261 assert isinstance(source, objects.Source), "Stored object not a Source"
293 self.output_debug("Reading %s from %s" % (source, pickle_file))
262 sname = os.path.basename
263 self.output_debug("Loading", source, "from", sname(pickle_file))
294264 except (pickle.PickleError, Exception), e:
295265 source = None
296266 self.output_info("Error loading %s: %s" % (pickle_file, e))
306276 of small writes are very slow
307277 """
308278 output = self.open(pickle_file, "wb")
309 self.output_debug("Saving %s to %s" % (source, pickle_file))
279 sname = os.path.basename
280 self.output_debug("Storing", source, "as", sname(pickle_file))
310281 output.write(pickle.dumps(source, pickle.HIGHEST_PROTOCOL))
311282 output.close()
312283 return True
313284
314 _source_pickle_service = None
315 def GetSourcePickleService():
316 global _source_pickle_service
317 if _source_pickle_service is None:
318 _source_pickle_service = SourcePickleService()
319 return _source_pickle_service
320285
321286 class SourceController (pretty.OutputMixin):
322287 """Control sources; loading, pickling, rescanning"""
446411 the "dummy" becomes live and is rescanned if @rescan
447412 """
448413 for source in list(sources):
414 sourcepickler = SourcePickler()
449415 if self.pickle:
450 news = GetSourcePickleService().unpickle_source(source)
416 news = sourcepickler.unpickle_source(source)
451417 else:
452418 news = None
453419 if news:
457423 # to "rescue the toplevel", we throw out sources that
458424 # raise exceptions on rescan
459425 try:
460 self.rescanner.register_rescan(source, force=True)
426 self.rescanner.register_rescan(source, sync=True)
461427 except StandardError, exp:
462428 self.output_error("Loading %s: raised %s %s" % (
463429 source, type(exp).__name__, exp))
466432 def _pickle_sources(self, sources):
467433 if not self.pickle:
468434 return
435 sourcepickler = SourcePickler()
436 sourcepickler.rm_old_cachefiles()
469437 for source in sources:
470438 if source.is_dynamic():
471439 continue
472 GetSourcePickleService().pickle_source(source)
440 sourcepickler.pickle_source(source)
473441
474442 _source_controller = None
475443 def GetSourceController():
490458 self.latest_key = None
491459 self.outstanding_search = -1
492460 self.outstanding_search_id = -1
461 self.searcher = Searcher()
493462
494463 def select(self, item):
495464 self.selection = item
515484 super(LeafPane, self).__init__()
516485 self.source_stack = []
517486 self.source = None
518 self.source_search_task = SearchTask()
519487
520488 def _load_source(self, src):
521489 """Try to get a source from the SourceController,
596564 sc = GetSourceController()
597565 textsrcs = sc.get_text_sources()
598566 sources.extend(textsrcs)
599 match, match_iter = self.source_search_task(sources, key,
600 score=bool(key))
567
568 decorator = lambda seq: dress_leaves(seq, action=None)
569 match, match_iter = self.searcher.search(sources, key, score=bool(key),
570 decorator=decorator)
601571 self.emit_search_result(match, match_iter, context)
572
602573 gobject.signal_new("new-source", LeafPane, gobject.SIGNAL_RUN_LAST,
603574 gobject.TYPE_BOOLEAN, (gobject.TYPE_PYOBJECT,))
604575
627598
628599 actions = [a for a in actions if a.valid_for_item(self.current_item)]
629600 sources = (actions, )
630 stask = SearchTask()
631 match, match_iter = stask(sources, key)
601 match, match_iter = self.searcher.search(sources, key)
632602 self.emit_search_result(match, match_iter, context)
633603
634604 class SecondaryObjectPane (LeafPane):
641611 self.source = None
642612 self.source_stack = None
643613 LeafPane.reset(self)
644 self.source_search_task = SearchTask()
614 self.searcher = Searcher()
645615 def set_item_and_action(self, item, act):
646616 self.current_item = item
647617 self.current_action = act
675645 sc = GetSourceController()
676646 textsrcs = sc.get_text_sources()
677647 sources.extend(textsrcs)
678 match, match_iter = self.source_search_task(sources, key,
679 item=self.current_item,
680 action=self.current_action,
681 score=True)
648
649 types = tuple(self.current_action.object_types())
650 def type_obj_check(itms):
651 valid_object = self.current_action.valid_object
652 item = self.current_item
653 for i in itms:
654 if (isinstance(i, types) and valid_object(i, for_item=item)):
655 yield i
656 def type_check(itms):
657 for i in itms:
658 if isinstance(i, types):
659 yield i
660
661 if hasattr(self.current_action, "valid_object"):
662 item_check = type_obj_check
663 else:
664 item_check = type_check
665
666 decorator = lambda seq: dress_leaves(seq, action=self.current_action)
667
668 match, match_iter = self.searcher.search(sources, key, score=True,
669 item_check=item_check, decorator=decorator)
682670 self.emit_search_result(match, match_iter, context)
683671
684672 class DataController (gobject.GObject, pretty.OutputMixin):
689677 so it can register itself at the scheduler correctly.
690678 """
691679 __gtype_name__ = "DataController"
692
693 def __call__(self):
694 return self
695680
696681 def __init__(self):
697682 super(DataController, self).__init__()
710695 ctl.connect("search-result", self._pane_search_result, pane)
711696 self.mode = None
712697 self._search_ids = itertools.count(1)
698 self._task_runner = task.TaskRunner(end_on_finish=False)
713699
714700 sch = scheduler.GetScheduler()
715701 sch.connect("load", self._load)
768754
769755 def _load(self, sched):
770756 """Load data from persistent store"""
757 self._setup_plugins()
771758 sc = GetSourceController()
772759 sc.add(self.direct_sources, toplevel=True)
773760 sc.add(self.other_sources, toplevel=False)
774761 self.source_pane.source_rebase(sc.root)
775762 learn.load()
763
764 def _setup_plugins(self):
765 from kupfer import settings, plugins
766 from kupfer.plugins import (load_plugin_sources, sources_attribute,
767 action_decorators_attribute, text_sources_attribute,
768 content_decorators_attribute,
769 initialize_plugin)
770
771 s_sources = []
772 S_sources = []
773
774 def dir_source(opt):
775 abs = os.path.abspath(os.path.expanduser(opt))
776 return objects.DirectorySource(abs)
777
778 def file_source(opt, depth=1):
779 abs = os.path.abspath(os.path.expanduser(opt))
780 return objects.FileSource((abs,), depth)
781
782 setctl = settings.GetSettingsController()
783 source_config = setctl.get_config
784
785 text_sources = []
786 action_decorators = []
787 content_decorators = []
788
789 for item in plugins.get_plugin_ids():
790 if not setctl.get_plugin_enabled(item):
791 continue
792 initialize_plugin(item)
793 text_sources.extend(load_plugin_sources(item, text_sources_attribute))
794 action_decorators.extend(load_plugin_sources(item,
795 action_decorators_attribute))
796 content_decorators.extend(load_plugin_sources(item,
797 content_decorators_attribute, instantiate=False))
798 if setctl.get_plugin_is_toplevel(item):
799 S_sources.extend(load_plugin_sources(item))
800 else:
801 s_sources.extend(load_plugin_sources(item))
802
803 dir_depth = source_config("DeepDirectories", "Depth")
804
805 for item in source_config("Directories", "Catalog"):
806 s_sources.append(dir_source(item))
807 for item in source_config("DeepDirectories","Catalog"):
808 s_sources.append(file_source(item, dir_depth))
809 for item in source_config("Directories", "Direct"):
810 S_sources.append(dir_source(item))
811 for item in source_config("DeepDirectories", "Direct"):
812 S_sources.append(file_source(item, dir_depth))
813
814 if not S_sources and not s_sources:
815 pretty.print_info(__name__, "No sources found!")
816
817 self.set_sources(S_sources, s_sources)
818 self.register_text_sources(text_sources)
819 self.register_action_decorators(action_decorators)
820 self.register_content_decorators(content_decorators)
776821
777822 def _finish(self, sched):
778823 self.output_info("Saving data...")
932977 self.source_pane.push_source(ret)
933978 return
934979 if action.is_async():
935 GetProcessManager().register_action(action, leaf, sobject, ret)
980 self._task_runner.add_task(ret)
936981 self.emit("launched-action", SourceActionMode, leaf, action)
937982
938983 # pane cleared (invalid item) item was invalid
9551000 gobject.signal_new("launched-action", DataController, gobject.SIGNAL_RUN_LAST,
9561001 gobject.TYPE_BOOLEAN, (gobject.TYPE_INT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT))
9571002
958 # Create singleton object shadowing main class!
959 DataController = DataController()
960
961
962 class ActionThread (threading.Thread, gobject.GObject, pretty.OutputMixin):
963 """
964 signals
965 completed (success)
966 """
967 __gtype_name__= "ActionThread"
968 def __init__(self, start_call, finish_call):
969 threading.Thread.__init__(self)
970 gobject.GObject.__init__(self)
971 self.start_call = start_call
972 self.finish_call = finish_call
973
974 def run(self):
975 try:
976 ret = self.start_call()
977 except StandardError, exc:
978 self.output_error("%s: %s" % (type(exc).__name__, exc))
979 gobject.idle_add(self.emit, "completed", False)
980 else:
981 gobject.idle_add(self.finish_call, ret)
982 gobject.idle_add(self.emit, "completed", True)
983 gobject.signal_new("completed", ActionThread, gobject.SIGNAL_RUN_LAST,
984 gobject.TYPE_BOOLEAN, (gobject.TYPE_BOOLEAN, ))
985
986 class ProcessManager (gobject.GObject, pretty.OutputMixin):
987 """
988 signals:
989 new-process ()
990 completed (success)
991 empty ()
992 """
993 __gtype_name__ = "ProcessManager"
994 def __init__(self):
995 super(ProcessManager, self).__init__()
996 self.queue = {}
997 self._process_ids = itertools.count()
998
999 def has_queue(self):
1000 return len(self.queue)
1001
1002 def _thread_completed(self, thread, success, thread_id):
1003 del self.queue[thread_id]
1004 self.emit("completed", success)
1005 self.output_debug("process %d completed success=%s" % (thread_id, success))
1006 if not self.has_queue():
1007 self.emit("empty")
1008
1009 def register_action(self, action, leaf, iobj, ret):
1010 start_cb, finish_cb = ret
1011 start_cb_composed = lambda : start_cb(leaf, iobj)
1012
1013 at = ActionThread(start_cb_composed, finish_cb)
1014 thread_id = self._process_ids.next()
1015 at.connect("completed", self._thread_completed, thread_id)
1016 self.queue[thread_id] = (leaf, action, iobj)
1017 self.output_debug("process %d started for %s " % (thread_id, action))
1018 at.start()
1019 self.emit("new-process")
1020
1021 gobject.signal_new("new-process", ProcessManager, gobject.SIGNAL_RUN_LAST,
1022 gobject.TYPE_BOOLEAN, ())
1023 gobject.signal_new("completed", ProcessManager, gobject.SIGNAL_RUN_LAST,
1024 gobject.TYPE_BOOLEAN, (gobject.TYPE_BOOLEAN, ))
1025 gobject.signal_new("empty", ProcessManager, gobject.SIGNAL_RUN_LAST,
1026 gobject.TYPE_BOOLEAN, ())
1027
1028 _process_manager = None
1029
1030 def GetProcessManager():
1031 global _process_manager
1032 if _process_manager is None:
1033 _process_manager = ProcessManager()
1034 return _process_manager
1035
1003
4646 try:
4747 import keybinder
4848 except ImportError:
49 pretty.print_error("Could not import keybinder, keybindings disabled!")
49 pretty.print_error(__name__, "Could not import keybinder, "
50 "keybindings disabled!")
5051 return False
5152
5253 keybinding_target = int(keybinding_target)
5354 callback = lambda : GetKeyboundObject()._keybinding(keybinding_target)
54 if len(keystr) == 1:
55 if keystr and len(keystr) == 1:
5556 pretty.print_error(__name__, "Refusing to bind key", repr(keystr))
5657 return False
5758
2424 def get_mnemonics(self):
2525 return self.mnemonics
2626
27 class Learning (pretty.OutputMixin, object):
28 def _unpickle_register(self, pickle_file):
27 class Learning (object):
28 @classmethod
29 def _unpickle_register(cls, pickle_file):
2930 try:
3031 pfile = open(pickle_file, "rb")
3132 except IOError, e:
3334 try:
3435 source = pickle.loads(pfile.read())
3536 assert isinstance(source, dict), "Stored object not a dict"
36 self.output_debug("Reading from %s" % (pickle_file, ))
37 pretty.print_debug(__name__, "Reading from %s" % (pickle_file, ))
3738 except (pickle.PickleError, Exception), e:
3839 source = None
39 self.output_info("Error loading %s: %s" % (pickle_file, e))
40 pretty.print_error(__name__, "Error loading %s: %s" % (pickle_file, e))
4041 return source
4142
43 @classmethod
4244 def _pickle_register(self, reg, pickle_file):
4345 output = open(pickle_file, "wb")
44 self.output_debug("Saving to %s" % (pickle_file, ))
46 pretty.print_debug(__name__, "Saving to %s" % (pickle_file, ))
4547 output.write(pickle.dumps(reg, pickle.HIGHEST_PROTOCOL))
4648 output.close()
4749 return True
4850
49 Learning = Learning()
5051 _register = {}
5152
5253 def record_search_hit(obj, key=u""):
9697 """
9798 Close and save the learning record
9899 """
100 if not _register:
101 pretty.print_debug(__name__, "Not writing empty register")
102 return
99103 filepath = config.save_data_file(mnemonics_filename)
100104 Learning._pickle_register(_register, filepath)
7171
7272 return _Service_obj
7373
74 def Unregister():
75 if session_bus:
76 session_bus.release_name(server_name)
0 import gettext
1 import locale
2
03 _debug = False
14
2 def setup_gettext():
5 def setup_locale_and_gettext():
36 """Set up localization with gettext"""
4 import gettext
5 import locale
6
77 package_name = "kupfer"
88 localedir = "./locale"
99 try:
10 import version_subst
10 from . import version_subst
1111 except ImportError:
1212 pass
1313 else:
1919 names=("ngettext",))
2020 # also bind this for gtkbuilder (wtf?)
2121 locale.bindtextdomain(package_name, localedir)
22 # to load in current locale properly for sorting etc
23 try:
24 locale.setlocale(locale.LC_ALL, "")
25 except locale.Error, e:
26 pass
2227
23 setup_gettext()
24
25 # to load in current locale properly for sorting etc
26 import locale
27 try:
28 locale.resetlocale()
29 except locale.Error, e:
30 pass
28 setup_locale_and_gettext()
3129
3230 def get_options(default_opts=""):
3331 """
114112 "program": version.PROGRAM_NAME, "desc": version.SHORT_DESCRIPTION,
115113 "website": version.WEBSITE, "copyright": version.COPYRIGHT
116114 }
117 banner = _("""%(program)s: %(desc)s
118 %(copyright)s
119 %(website)s
120 """) % var
121 # Be careful about unicode here
122 enc = locale.getpreferredencoding()
123 print banner.encode(enc, "replace")
115 banner = _(
116 "%(program)s: %(desc)s\n"
117 " %(copyright)s\n"
118 " %(website)s\n") % var
119
120 # Be careful about unicode here, since it might stop the whole program
121 try:
122 print banner
123 except UnicodeEncodeError, e:
124 print banner.encode("ascii", "replace")
124125
125126 def main():
126 import sys
127 from os import path
128
129 from . import browser, data
130 from . import objects, plugin
131 from . import pretty, plugins, settings
132 from .plugins import (load_plugin_sources, sources_attribute,
133 action_decorators_attribute, text_sources_attribute,
134 content_decorators_attribute,
135 initialize_plugin)
136
127 # parse commandline before importing UI
137128 cli_opts = get_options()
138129 print_banner()
130
131 from . import browser, pretty
132
139133 if _debug:
140134 pretty.debug = _debug
141135
142 s_sources = []
143 S_sources = []
144
145 def dir_source(opt):
146 abs = path.abspath(path.expanduser(opt))
147 return objects.DirectorySource(abs)
148
149 def file_source(opt, depth=1):
150 abs = path.abspath(path.expanduser(opt))
151 return objects.FileSource((abs,), depth)
152
153 setctl = settings.GetSettingsController()
154 source_config = setctl.get_config
155
156 text_sources = []
157 action_decorators = []
158 content_decorators = []
159
160 for item in plugins.get_plugin_ids():
161 if not setctl.get_plugin_enabled(item):
162 continue
163 initialize_plugin(item)
164 text_sources.extend(load_plugin_sources(item, text_sources_attribute))
165 action_decorators.extend(load_plugin_sources(item,
166 action_decorators_attribute))
167 content_decorators.extend(load_plugin_sources(item,
168 content_decorators_attribute, instantiate=False))
169 if setctl.get_plugin_is_toplevel(item):
170 S_sources.extend(load_plugin_sources(item))
171 else:
172 s_sources.extend(load_plugin_sources(item))
173
174 dir_depth = source_config("DeepDirectories", "Depth")
175
176 for item in source_config("Directories", "Catalog"):
177 s_sources.append(dir_source(item))
178 for item in source_config("DeepDirectories","Catalog"):
179 s_sources.append(file_source(item, dir_depth))
180 for item in source_config("Directories", "Direct"):
181 S_sources.append(dir_source(item))
182 for item in source_config("DeepDirectories", "Direct"):
183 S_sources.append(file_source(item, dir_depth))
184
185 if not S_sources and not s_sources:
186 print pretty.print_info(__name__, "No sources found!")
187
188 dc = data.DataController()
189 dc.set_sources(S_sources, s_sources)
190 dc.register_text_sources(text_sources)
191 dc.register_action_decorators(action_decorators)
192 dc.register_content_decorators(content_decorators)
193136 w = browser.WindowController()
194137
195138 quiet = ("--no-splash" in cli_opts)
99
1010 import itertools
1111 from os import path
12 import os
13 import locale
1412
1513 import gobject
1614 import gio
268266 """Format the path shorter:
269267 replace homedir by ~/
270268 """
271 # Use glib filename reading to make display name out of filenames
272 # this function returns a `unicode` object
273 desc = gobject.filename_display_name(self.object)
274 homedir = path.expanduser("~/")
275 if desc.startswith(homedir) and homedir != desc:
276 desc = desc.replace(homedir, "~/", 1)
277 return desc
269 return utils.get_display_path_for_bytestring(self.object)
278270
279271 def get_actions(self):
280272 acts = [RevealFile(), ]
281 app_actions=[]
273 app_actions = []
282274 default = None
283275 if self.is_dir():
284276 acts.append(OpenTerminal())
302294 pass
303295 if def_key:
304296 if not def_key in apps:
305 pretty.output_debug("No default found for %s, but found %s" % (self, apps))
297 pretty.print_debug("No default found for %s, but found %s" % (self, apps))
306298 else:
307299 app_actions.append(apps.pop(def_key))
308300 # sort the non-default OpenWith actions
354346 root, ext = path.splitext(obj)
355347 if ext == ".desktop":
356348 try:
357 return AppLeaf(path=obj)
349 return AppLeaf(init_path=obj)
358350 except InvalidDataError:
359351 pass
360352 return FileLeaf(obj)
381373 return self.object.get_icon_name()
382374
383375 class AppLeaf (Leaf, PicklingHelperMixin, pretty.OutputMixin):
384 def __init__(self, item=None, path=None, app_id=None):
376 def __init__(self, item=None, init_path=None, app_id=None):
385377 """Try constructing an Application for GAppInfo @item,
386378 for file @path or for package name @app_id.
387379 """
388380 self.init_item = item
389 self.init_path = path
381 self.init_path = init_path
390382 self.init_item_id = app_id and app_id + ".desktop"
391 self.path = path
383 # unpickle_finish will raise InvalidDataError on invalid item
392384 self.unpickle_finish()
393 if not self.object:
394 raise InvalidDataError
395385 Leaf.__init__(self, self.object, self.object.get_name())
396386 self.name_aliases = self._get_aliases()
397387
410400 return name_aliases
411401
412402 def pickle_prepare(self):
413 self.init_item_id = self.object.get_id()
403 self.init_item_id = self.object and self.object.get_id()
414404 self.object = None
415405 self.init_item = None
416406
417407 def unpickle_finish(self):
418408 """Try to set self.object from init's parameters"""
409 item = None
419410 if self.init_item:
420 self.object = self.init_item
421 return
422 # Construct an AppInfo item from either path or item_id
423 from gio.unix import DesktopAppInfo, desktop_app_info_new_from_filename
424 item = None
425 if self.init_path:
426 item = desktop_app_info_new_from_filename(self.init_path)
427 elif self.init_item_id:
428 try:
429 item = DesktopAppInfo(self.init_item_id)
430 except RuntimeError:
431 self.output_debug(self, "Application", self.init_item_id,
432 "not found")
433 item = None
411 item = self.init_item
412 else:
413 # Construct an AppInfo item from either path or item_id
414 from gio.unix import DesktopAppInfo, desktop_app_info_new_from_filename
415 if self.init_path:
416 item = desktop_app_info_new_from_filename(self.init_path)
417 elif self.init_item_id:
418 try:
419 item = DesktopAppInfo(self.init_item_id)
420 except RuntimeError:
421 self.output_debug(self, "Application", self.init_item_id,
422 "not found")
434423 self.object = item
424 if not self.object:
425 raise InvalidDataError
435426
436427 def repr_key(self):
437428 return self.get_id() or self
778769 return self._version
779770
780771 def __eq__(self, other):
781 return (type(self) == type(other) and repr(self).__eq__(repr(other)))
772 return type(self) == type(other) and repr(self) == repr(other)
782773
783774 def __hash__(self ):
784775 return hash(repr(self))
785776
786777 def repr_key(self):
787 return ""
778 # use the source's name so that it is reloaded on locale change
779 return (str(self), self.version)
788780
789781 def get_items(self):
790782 """
880872 def get_items(self):
881873 iters = []
882874
883 def mkleaves(dir):
884 files = utils.get_dirlist(dir, depth=self.depth, exclude=self._exclude_file)
875 def mkleaves(directory):
876 files = utils.get_dirlist(directory, depth=self.depth,
877 exclude=self._exclude_file)
885878 return (ConstructFileLeaf(f) for f in files)
886879
887880 for d in self.dirlist:
11151108 """
11161109 def __init__(self, text, name=None):
11171110 """@text *must* be unicode or UTF-8 str"""
1111 text = tounicode(text)
11181112 if not name:
11191113 lines = [l for l in text.splitlines() if l.strip()]
11201114 name = lines[0] if lines else text
1121 Leaf.__init__(self, tounicode(text), name)
1115 Leaf.__init__(self, text, name)
11221116
11231117 def get_actions(self):
11241118 return ()
11251119
11261120 def get_description(self):
1127 # FIXME: We should return full text and UI should handle truncating?
1128 lines = self.object.splitlines()
1129 striplines = [l for l in lines if l.strip()]
1121 lines = [l for l in self.object.splitlines() if l.strip()]
1122 desc = lines[0] if lines else self.object
11301123 numlines = len(lines) or 1
1131 firstline = striplines[0] if striplines else self.object
11321124
11331125 # TRANS: This is description for a TextLeaf, a free-text search
11341126 # TRANS: The plural parameter is the number of lines %(num)d
11351127 return ngettext('"%(text)s"', '(%(num)d lines) "%(text)s"',
1136 numlines) % {"num": numlines, "text": firstline }
1128 numlines) % {"num": numlines, "text": desc }
11371129
11381130 def get_icon_name(self):
11391131 return "gtk-select-all"
0 import gio
1 from gio import app_info_get_all
2 from gio.unix import desktop_app_info_set_desktop_env
3
04 from kupfer.objects import Source, AppLeaf, Action, FileLeaf
1 from kupfer import utils
5 from kupfer import utils, plugin_support
26
37 __kupfer_name__ = _("Applications")
48 __kupfer_sources__ = ("AppSource", )
5 __kupfer_actions__ = ("OpenWith", )
9 __kupfer_actions__ = (
10 "OpenWith",
11 "SetDefaultApplication",
12 )
613 __description__ = _("All applications and preferences")
714 __version__ = ""
815 __author__ = "Ulrik Sverdrup <ulrik.sverdrup@gmail.com>"
16
17 __kupfer_settings__ = plugin_support.PluginSettings(
18 {
19 "key" : "desktop_type",
20 "label": _("Applications for Desktop Environment"),
21 "type": str,
22 "value": "GNOME",
23 "alternatives": ("GNOME", "KDE", "XFCE")
24 },
25 )
926
1027 class AppSource (Source):
1128 """
1835 super(AppSource, self).__init__(_("Applications"))
1936
2037 def get_items(self):
21 from gio import app_info_get_all
22 from gio.unix import desktop_app_info_set_desktop_env
2338 # If we set proper desktop environment
2439 # We get exactly the apps shown in the menu,
2540 # as well as the preference panes
26 desktop_app_info_set_desktop_env("GNOME")
41 desktop_type = __kupfer_settings__["desktop_type"]
42 desktop_app_info_set_desktop_env(desktop_type)
2743 # Add this to the default
2844 whitelist = []
2945 for item in app_info_get_all():
5470 yield AppLeaf
5571 def get_description(self):
5672 return _("Open with any application")
73
74 class SetDefaultApplication (Action):
75 def __init__(self):
76 Action.__init__(self, _("Set Default Application..."))
77 def activate(self, leaf, obj):
78 gfile = gio.File(leaf.object)
79 info = gfile.query_info(gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE)
80 content_type = info.get_attribute_string(gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE)
81 print content_type, gfile
82 desktop_item = obj.object
83 desktop_item.set_as_default_for_type(content_type)
84 def item_types(self):
85 yield FileLeaf
86 def requires_object(self):
87 return True
88 def object_types(self):
89 yield AppLeaf
90 def get_description(self):
91 return _("Set default application to open this file type")
2121 )
2222
2323 class ClipboardText (TextLeaf):
24 def __init__(self, text):
25 # take first non-empty line
26 firstline = [l for l in text.splitlines() if l.strip()][0]
27 TextLeaf.__init__(self, text, name=firstline)
2824 def get_description(self):
2925 lines = self.object.splitlines()
3026 desc = unicode(self)
31 numlines = len(lines)
27 numlines = len(lines) or 1
3228
3329 return ngettext('Clipboard "%(desc)s"',
3430 'Clipboard with %(num)d lines "%(desc)s"',
00 import gtk
11 import gio
2 import gobject
23
34 from kupfer.objects import Leaf, Action, Source, RunnableLeaf
45 from kupfer import objects, utils, icons, pretty
8586 def get_icon_name(self):
8687 return "folder"
8788
89 TRASH_URI="trash://"
90
91 class RestoreTrashedFile (Action):
92 def __init__(self):
93 Action.__init__(self, _("Restore"))
94
95 def activate(self, leaf):
96 orig_path = leaf.get_orig_path()
97 if not orig_path:
98 return
99 orig_gfile = gio.File(orig_path)
100 cur_gfile = leaf.get_gfile()
101 if orig_gfile.query_exists():
102 raise IOError("Target file exists at %s" % orig_gfile.get_path())
103 pretty.print_debug(__name__, "Move %s to %s" % (cur_gfile, orig_gfile))
104 ret = cur_gfile.move(orig_gfile)
105 pretty.print_debug(__name__, "Move ret=%s" % (ret, ))
106
107 def get_description(self):
108 return _("Move file back to original location")
109 def get_icon_name(self):
110 return "gtk-undo-ltr"
111
112 class TrashFile (Leaf):
113 """A file in the trash. Represented object is a file info object"""
114 def __init__(self, info):
115 name = info.get_display_name()
116 Leaf.__init__(self, info, name)
117 def get_actions(self):
118 if self.get_orig_path():
119 yield RestoreTrashedFile()
120 def get_gfile(self):
121 cur_gfile = gio.File(TRASH_URI).get_child(self.object.get_name())
122 return cur_gfile
123 def get_orig_path(self):
124 try:
125 orig_path = self.object.get_attribute_byte_string("trash::orig-path")
126 return orig_path
127 except AttributeError:
128 pass
129 return None
130
131 def is_valid(self):
132 return self.get_gfile().query_exists()
133
134 def get_description(self):
135 orig_path = self.get_orig_path()
136 return utils.get_display_path_for_bytestring(orig_path) if orig_path \
137 else None
138 def get_gicon(self):
139 return self.object.get_icon()
140 def get_icon_name(self):
141 return "gtk-file"
142
143 class TrashContentSource (Source):
144 def is_dynamic(self):
145 return True
146 def get_items(self):
147 gfile = gio.File(TRASH_URI)
148 enumerator = gfile.enumerate_children("standard::*,trash::*")
149 for info in enumerator:
150 yield TrashFile(info)
151 def should_sort_lexically(self):
152 return True
153 def get_gicon(self):
154 return icons.get_gicon_for_file(TRASH_URI)
155
88156 class Trash (SpecialLocation):
89157 def __init__(self, name=None):
90 SpecialLocation.__init__(self, "trash://", name=name)
91 def get_description(self):
158 SpecialLocation.__init__(self, TRASH_URI, name=name)
159
160 def has_content(self):
161 return self.get_item_count()
162 def content_source(self, alternate=False):
163 return TrashContentSource(name=unicode(self))
164
165 def get_item_count(self):
92166 gfile = gio.File(self.object)
93167 info = gfile.query_info(gio.FILE_ATTRIBUTE_TRASH_ITEM_COUNT)
94 item_count = info.get_attribute_uint32(gio.FILE_ATTRIBUTE_TRASH_ITEM_COUNT)
168 return info.get_attribute_uint32(gio.FILE_ATTRIBUTE_TRASH_ITEM_COUNT)
169
170 def get_description(self):
171 item_count = self.get_item_count()
95172 if not item_count:
96173 return _("Trash is empty")
97174 # proper translation of plural
33 from os import path as os_path
44
55 from kupfer.objects import Action, FileLeaf
6 from kupfer import utils, pretty
6 from kupfer import utils, pretty, task
7 from kupfer import plugin_support
78
89
910 __kupfer_name__ = _("File Actions")
1415 "MoveTo",
1516 "CopyTo",
1617 "UnpackHere",
17 "CreateArchive"
18 "CreateArchive",
19 "CreateArchiveIn",
1820 )
1921 __description__ = _("More file actions")
2022 __version__ = ""
2123 __author__ = "Ulrik Sverdrup <ulrik.sverdrup@gmail.com>"
24
25 __kupfer_settings__ = plugin_support.PluginSettings(
26 {
27 "key" : "archive_type",
28 "label": _("Compressed archive type for 'Create Archive In'"),
29 "type": str,
30 "value": ".tar.gz",
31 "alternatives": (
32 ".7z",
33 ".rar",
34 ".tar",
35 ".tar.gz",
36 ".zip",
37 )
38 },
39 )
2240
2341 class Trash (Action):
2442 # this should never be default
85103 def get_description(self):
86104 return _("Move file to new location")
87105
106 class CopyTask (task.ThreadTask, pretty.OutputMixin):
107 def __init__(self, spath, dpath):
108 self.done = False
109 self.sfile = gio.File(spath)
110 bname = self.sfile.get_basename()
111 self.dfile = gio.File(os_path.join(dpath, bname))
112 super(CopyTask, self).__init__()
113
114 def thread_do(self):
115 self.ret = self.sfile.copy(self.dfile)
116 self.output_debug("Copy %s to %s (ret: %s)" % (self.sfile, self.dfile, self.ret))
117
88118 class CopyTo (Action, pretty.OutputMixin):
89119 def __init__(self):
90120 Action.__init__(self, _("Copy To..."))
92122 def is_async(self):
93123 return True
94124 def activate(self, leaf, obj):
95 return self._start_action, self._finish_action
96
97 def _start_action(self, leaf, iobj=None):
98 sfile = gio.File(leaf.object)
99 bname = sfile.get_basename()
100 dfile = gio.File(os_path.join(iobj.object, bname))
101 ret = sfile.copy(dfile)
102 self.output_debug("Copy %s to %s (ret: %s)" % (sfile, dfile, ret))
103
104 def _finish_action(self, ret):
105 pass
125 return CopyTask(leaf.object, obj.object)
106126
107127 def item_types(self):
108128 yield FileLeaf
148168 yield FileLeaf
149169 def get_description(self):
150170 return _("Create a compressed archive from folder")
171
172 class CreateArchiveIn (Action):
173 def __init__(self):
174 Action.__init__(self, _("Create Archive In..."))
175 def activate(self, leaf, iobj):
176 archive_type = __kupfer_settings__["archive_type"]
177 dirpath = iobj.object
178 basename = os_path.basename(leaf.object)
179 archive_path = \
180 utils.get_destpath_in_directory(dirpath, basename, archive_type)
181 utils.launch_commandline("file-roller --add-to='%s' '%s'" %
182 (archive_path, leaf.object))
183
184 def valid_for_item(self, item):
185 # FIXME: Only for directories right now
186 return item.is_dir()
187 def item_types(self):
188 yield FileLeaf
189 def requires_object(self):
190 return True
191 def object_types(self):
192 yield FileLeaf
193 def valid_object(self, obj, for_item=None):
194 return utils.is_directory_writable(obj.object)
195 def get_description(self):
196 return _("Create a compressed archive from folder")
0 import gobject
1
2 from kupfer.objects import Action, Source
0 import os
1 import urllib
2 import xml.sax
3
4 from kupfer.objects import Action, Source, Leaf
35 from kupfer.objects import TextLeaf
4 from kupfer import utils
5
6 from kupfer import utils, config
7
8 from kupfer.plugin import firefox_support, xml_support
69
710 __kupfer_name__ = _("Search the Web")
8 __kupfer_sources__ = ()
11 __kupfer_sources__ = ("OpenSearchSource", )
912 __kupfer_text_sources__ = ()
10 __kupfer_actions__ = ("GoogleSearch", )
11 __description__ = _("Send search queries to Google")
13 __kupfer_actions__ = (
14 "SearchFor",
15 "SearchWithEngine",
16 )
17 __description__ = _("Search the web with OpenSearch search engines")
1218 __version__ = ""
1319 __author__ = "Ulrik Sverdrup <ulrik.sverdrup@gmail.com>"
1420
15 class GoogleSearch (Action):
21 class OpenSearchHandler (xml_support.XMLEntryHandler):
22 """Parse OpenSearch specification files (Mozilla flavor)
23
24 We use the generic entry parser from xml_support, but have
25 to hack up a solution for the Url element, which _can_ be
26 an entry itself with Param specifications.
27 """
28 def __init__(self, entries, elem_name, attributes, keys):
29 keys = set(keys)
30 keys.update(("Param", "MozParam"))
31 xml_support.XMLEntryHandler.__init__(self, entries, elem_name,
32 attributes, keys)
33 self.url_params = None
34
35 def startElement(self, sName, attributes):
36 if self.url_params is not None and sName == "Param":
37 try:
38 name, value = attributes["name"], attributes["value"]
39 except AttributeError:
40 return
41 self.url_params.append((name, value))
42 elif sName in ("Url", "os:Url"):
43 if not attributes["type"] == "text/html":
44 return
45 self.element_content = attributes["template"]
46 self.is_wanted_element = True
47 self.url_params = []
48 elif sName in ("MozParam", ):
49 pass
50 else:
51 xml_support.XMLEntryHandler.startElement(self, sName, attributes)
52
53 def endElement(self, sName):
54 if self.url_params is not None and sName in ("Url", "os:Url"):
55 # Assemble the URL with query string
56 url = self.element_content.strip()
57 if self.url_params:
58 url += "?" + "&".join("%s=%s" % (n,v) for n,v in self.url_params)
59 self.element_content = url
60 self.url_params = None
61 xml_support.XMLEntryHandler.endElement(self, sName)
62
63 def _urlencode(word):
64 """Urlencode a single string of bytes @word"""
65 return urllib.urlencode({"q": word})[2:]
66
67 def _do_search_engine(terms, search_url, encoding="UTF-8"):
68 """Show an url searching for @search_url with @terms"""
69 search_url = search_url.encode(encoding, "ignore")
70 terms_enc = terms.encode(encoding, "ignore")
71 query_url = search_url.replace("{searchTerms}", _urlencode(terms_enc))
72 utils.show_url(query_url)
73
74 class SearchWithEngine (Action):
75 """TextLeaf -> SearchWithEngine -> SearchEngine"""
1676 def __init__(self):
17 Action.__init__(self, _("Search with Google"))
18
19 def activate(self, leaf):
20 from urllib import urlencode
21 search_url = "http://www.google.com/search?"
22 # will encode search=text, where `text` is escaped
23 query_url = search_url + urlencode({"q": leaf.object, "ie": "utf-8"})
24 utils.show_url(query_url)
25 def get_description(self):
26 return _("Search for this term with Google")
27 def get_icon_name(self):
28 return "gtk-find"
77 Action.__init__(self, _("Search With..."))
78
79 def activate(self, leaf, iobj):
80 coding = iobj.object.get("InputEncoding")
81 url = iobj.object["Url"]
82 _do_search_engine(leaf.object, url, encoding=coding)
83
2984 def item_types(self):
3085 yield TextLeaf
3186
87 def requires_object(self):
88 return True
89 def object_types(self):
90 yield SearchEngine
91
92 def object_source(self, for_item=None):
93 return OpenSearchSource()
94
95 def get_description(self):
96 return _("Search the web with OpenSearch search engines")
97 def get_icon_name(self):
98 return "gtk-find"
99
100 class SearchFor (Action):
101 """SearchEngine -> SearchFor -> TextLeaf
102
103 This is the opposite action to SearchWithEngine
104 """
105 def __init__(self):
106 Action.__init__(self, _("Search For..."))
107
108 def activate(self, leaf, iobj):
109 coding = leaf.object.get("InputEncoding")
110 url = leaf.object["Url"]
111 terms = iobj.object
112 _do_search_engine(terms, url, encoding=coding)
113
114 def item_types(self):
115 yield SearchEngine
116
117 def requires_object(self):
118 return True
119 def object_types(self):
120 yield TextLeaf
121
122 def get_description(self):
123 return _("Search the web with OpenSearch search engines")
124 def get_icon_name(self):
125 return "gtk-find"
126
127 class SearchEngine (Leaf):
128 def get_description(self):
129 desc = self.object.get("Description")
130 return desc if desc != unicode(self) else None
131 def get_icon_name(self):
132 return "text-html"
133
134 def coroutine(func):
135 """Coroutine decorator: Start the coroutine"""
136 def startcr(*ar, **kw):
137 cr = func(*ar, **kw)
138 cr.next()
139 return cr
140 return startcr
141
142 class OpenSearchSource (Source):
143 def __init__(self):
144 Source.__init__(self, _("Search Engines"))
145
146 @coroutine
147 def _parse_opensearch(self, target):
148 """This is a coroutine to parse OpenSearch files"""
149 parser = xml.sax.make_parser()
150 reqkeys = ["Description", "Url", "ShortName"]
151 allkeys = reqkeys + ["InputEncoding"]
152 keys = allkeys[:]
153 keys += ["os:" + k for k in allkeys]
154 searches = []
155 handler = OpenSearchHandler(searches, "SearchPlugin", {}, keys)
156 parser.setContentHandler(handler)
157 while True:
158 del searches[:]
159 try:
160 path = (yield)
161 parser.parse(path)
162 except xml.sax.SAXException, exc:
163 self.output_debug("%s: %s" % (type(exc).__name__, exc))
164 else:
165 # normalize to unnamespaced values and sanitize
166 for s in searches:
167 for key, val in s.items():
168 skey = key.replace("os:", "", 1)
169 del s[key]
170 s[skey] = val.strip()
171 if all((k in s) for k in reqkeys):
172 target.send(s)
173
174 def get_items(self):
175 plugin_dirs = []
176
177 # accept in kupfer data dirs
178 plugin_dirs.extend(config.get_data_dirs("searchplugins"))
179
180 # firefox in home directory
181 ffx_home = firefox_support.get_firefox_home_file("searchplugins")
182 if ffx_home:
183 plugin_dirs.append(ffx_home)
184
185 plugin_dirs.extend(config.get_data_dirs("searchplugins",
186 package="firefox"))
187 plugin_dirs.extend(config.get_data_dirs("searchplugins",
188 package="iceweasel"))
189
190 self.output_debug("Found following searchplugins directories",
191 sep="\n", *plugin_dirs)
192
193 def listfiles(directory):
194 """Return a list of files in @directory, without recursing"""
195 for dirname, dirs, files in os.walk(directory):
196 return files
197
198 @coroutine
199 def collect(seq):
200 """Collect items in list @seq"""
201 while True:
202 seq.append((yield))
203
204 searches = []
205 collector = collect(searches)
206 parser = self._parse_opensearch(collector)
207 # files are unique by filename to allow override
208 visited_files = set()
209 for pdir in plugin_dirs:
210 for f in listfiles(pdir):
211 if f in visited_files:
212 continue
213 parser.send(os.path.join(pdir, f))
214 visited_files.add(f)
215
216 for s in searches:
217 yield SearchEngine(s, s["ShortName"])
218
219 def should_sort_lexically(self):
220 return True
221
222 def get_icon_name(self):
223 return "applications-internet"
3838 self.max_items = 500
3939
4040 def get_items(self):
41 command = "locate --quiet --null --limit %d %s" % \
41 command = "locate --quiet --null --limit %d '%s'" % \
4242 (self.max_items, self.query)
4343 locate_output = os.popen(command).read()
4444 files = locate_output.split("\x00")[:-1]
0 import itertools
1 from hashlib import md5
2
03 import gio
1 from hashlib import md5
24
35 from kupfer.objects import (Leaf, Source, AppLeaf, Action, RunnableLeaf,
46 SourceLeaf, AppLeafContentMixin)
307309 yield ArtistLeaf
308310
309311 def _locale_sort_artist_album_songs(artists):
310 """Sort by Artist, then Album, then Track"""
312 """Locale sort dictionary @artists by Artist, then Album;
313 each artist in @artists should already contain songs
314 grouped by album and sorted by track number.
315 """
311316 for artist in utils.locale_sort(artists):
312317 artist_songs = artists[artist]
313 albums = set(s["album"] for s in artist_songs)
318 albums = {}
319 albumkey = lambda song: song["album"]
320 for album, songs in itertools.groupby(artist_songs, albumkey):
321 albums[album] = list(songs)
314322 for album in utils.locale_sort(albums):
315 album_songs = []
316 for song in artist_songs:
317 if song["album"] == album:
318 album_songs.append(song)
319 album_songs.sort(key=lambda s: s.get("track-number", u""))
320 for song in album_songs:
323 for song in albums[album]:
321324 yield song
322325
323326 class RhythmboxSongsSource (Source):
0 #!/usr/bin/python
1
2 """
3 Copyright (c) 2007 Tyler G. Hicks-Wright
4 2009 Ulrik Sverdrup <ulrik.sverdrup@gmail.com>
5
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 THE SOFTWARE.
23 """
240
251 import os
26 from xml.sax import make_parser
27 from xml.sax.saxutils import XMLGenerator
28 from xml.sax.handler import ContentHandler
2 import xml.sax
293
30 class RhythmBoxHandler(ContentHandler):
31 """Parse rhythmbox library into a list of dictionaries.
32 Get only entries of type @entry_type (commonly "song"),
33 and only record keys in the iterable wanted_keys, or all
34 if None.
35 """
36 def __init__(self, songs, entry_type, wanted_keys=None):
37 ContentHandler.__init__(self)
38 self.all_entries = songs
39 self.entry_type = entry_type
40 self.wanted_keys = wanted_keys and set(wanted_keys)
41 self.is_parsing_tag = False
42 self.is_wanted_element = False
43 self.song_entry = None
44 self.element_content = ''
45
46 def startElement(self, sName, attributes):
47 if sName == "entry" and attributes["type"] == self.entry_type:
48 self.song_entry = {}
49 self.is_parsing_tag = True
50 self.is_wanted_element = True
51 else:
52 self.is_wanted_element = \
53 (not self.wanted_keys or sName in self.wanted_keys)
54 self.element_content = ''
55
56 def characters(self, sData):
57 if self.is_wanted_element:
58 self.element_content += sData
59
60 def endElement(self,sName):
61 if sName == 'entry':
62 if self.song_entry:
63 self.all_entries.append(self.song_entry)
64 self.song_entry = None
65 self.is_parsing_tag = False
66 elif self.is_parsing_tag and self.is_wanted_element:
67 self.song_entry[sName] = self.element_content
4 from . import xml_support
685
696 NEEDED_KEYS= ("title", "artist", "album", "track-number", "location", )
7
708 def get_rhythmbox_songs(typ="song", keys=NEEDED_KEYS,
719 dbfile='~/.local/share/rhythmbox/rhythmdb.xml'):
7210 rhythmbox_dbfile = os.path.expanduser(dbfile)
73 rbParser = make_parser()
11 rbParser = xml.sax.make_parser()
7412 lSongs = []
75 rbHandler = RhythmBoxHandler(lSongs, typ, keys)
13 attributes = {"type": typ}
14 rbHandler = xml_support.XMLEntryHandler(lSongs, "entry", attributes, keys)
7615 rbParser.setContentHandler(rbHandler)
7716 rbParser.parse(rhythmbox_dbfile)
7817 return lSongs
9029 album.sort(key=get_track_number)
9130
9231 def sort_album_order(songs):
93 """Sort songs in order by album then by track number"""
32 """Sort songs in order by album then by track number
33
34 >>> songs = [
35 ... {"title": "a", "album": "B", "track-number": "2"},
36 ... {"title": "b", "album": "A", "track-number": "1"},
37 ... {"title": "c", "album": "B", "track-number": "1"},
38 ... ]
39 >>> sort_album_order(songs)
40 >>> [s["title"] for s in songs]
41 ['b', 'c', 'a']
42 """
9443 def get_album_order(rec):
9544 tnr = rec.get("track-number")
9645 if not tnr: return None
00 import gtk
11
22 from kupfer.objects import Source, Leaf, TextLeaf, SourceLeaf, PicklingHelperMixin
3 from kupfer import objects
34
45 __kupfer_name__ = _("Selected Text")
56 __kupfer_sources__ = ("SelectionSource", )
910
1011 class SelectedText (TextLeaf):
1112 def __init__(self, text):
12 TextLeaf.__init__(self, text, _("Selected Text"))
13 text = objects.tounicode(text)
14 lines = filter(None, text.splitlines())
15 summary = lines[0] if lines else text
16 maxlen = 10
17 if len(summary) > maxlen:
18 summary = summary[:maxlen] + u".."
19 TextLeaf.__init__(self, text, _('Selected Text "%s"') % summary)
20
21 def rank_key(self):
22 # return a constant rank key despite the changing name
23 return _("Selected Text")
1324
1425 class InvisibleSourceLeaf (SourceLeaf):
1526 """Hack to hide this source"""
3434
3535 class TrackerSearchHere (Action):
3636 def __init__(self):
37 Action.__init__(self, _("Get Tracker results..."))
37 Action.__init__(self, _("Get Tracker Results..."))
3838
3939 def is_factory(self):
4040 return True
0 import os
1 import urllib2
2
3 from kupfer.objects import Action, Source, UrlLeaf, FileLeaf
4 from kupfer import utils, pretty, task
5
6 __kupfer_name__ = _("URL Actions")
7 __kupfer_sources__ = ()
8 __kupfer_text_sources__ = ()
9 __kupfer_actions__ = (
10 "DownloadAndOpen",
11 "DownloadTo",
12 )
13 __description__ = _("URL Actions")
14 __version__ = ""
15 __author__ = "Ulrik Sverdrup <ulrik.sverdrup@gmail.com>"
16
17 class DownloadTask (task.StepTask):
18 def __init__(self, uri, destdir, finish_callback=None):
19 super(DownloadTask, self).__init__()
20 self.response = urllib2.urlopen(uri)
21
22 header_basename = self.response.headers.get('Content-Disposition')
23 destname = header_basename or os.path.basename(self.response.url)
24 self.destpath = utils.get_destpath_in_directory(destdir, destname)
25 self.done = False
26 self.destfile = open(self.destpath, "wb")
27 self.bufsize = 8192
28 self.finish_callback = finish_callback
29
30 def step(self):
31 buf = self.response.read(self.bufsize)
32 if not buf:
33 self.done = True
34 return False
35 self.destfile.write(buf)
36 return True
37
38 def finish(self):
39 self.destfile.close()
40 self.response.close()
41 if not self.done:
42 print "Deleting unfinished", self.destfile
43 os.unlink(self.destpath)
44 elif self.finish_callback:
45 self.finish_callback(self.destpath)
46
47 class DownloadAndOpen (Action):
48 """Asynchronous action to download file and open it"""
49 def __init__(self):
50 Action.__init__(self, _("Download and Open"))
51
52 def is_async(self):
53 return True
54 def activate(self, leaf):
55 uri = leaf.object
56 destdir = "/tmp"
57 return DownloadTask(uri, destdir, self._finish_action)
58
59 def _finish_action(self, filename):
60 utils.show_path(filename)
61
62 def item_types(self):
63 yield UrlLeaf
64 def get_description(self):
65 return None
66
67 class DownloadTo (Action):
68 def __init__(self):
69 Action.__init__(self, _("Download To..."))
70
71 def is_async(self):
72 return True
73 def activate(self, leaf, obj):
74 uri = leaf.object
75 return DownloadTask(uri, obj.object)
76
77 def item_types(self):
78 yield UrlLeaf
79 def requires_object(self):
80 return True
81 def object_types(self):
82 yield FileLeaf
83 def valid_object(self, obj, for_item=None):
84 return utils.is_directory_writable(obj.object)
85 def get_description(self):
86 return _("Download URL to a chosen location")
87
0
1 from xml.sax.handler import ContentHandler
2
3 class XMLEntryHandler(ContentHandler):
4 """Parse XML input into a list of dictionaries.
5 Get only entries of type @entry_type are taken.
6 and only record keys in the iterable wanted_keys.
7
8 This ContentHandler keeps a big string mapping open, to
9 make sure that equal strings are using equal instances to save memory.
10 """
11 def __init__(self, entries, entry_name, entry_attributes, wanted_keys):
12 ContentHandler.__init__(self)
13 self.all_entries = entries
14 self.entry_name = entry_name
15 self.entry_attributes = entry_attributes.items()
16 self.wanted_keys = dict((k, k) for k in wanted_keys)
17 self.is_parsing_tag = False
18 self.is_wanted_element = False
19 self.song_entry = None
20 self.string_map = {}
21 self.element_content = ''
22
23 def startElement(self, sName, attributes):
24 if (sName == self.entry_name and
25 all(attributes.get(k) == v for k, v in self.entry_attributes)):
26 self.song_entry = {}
27 self.is_parsing_tag = True
28 self.is_wanted_element = True
29 else:
30 self.is_wanted_element = (sName in self.wanted_keys)
31 self.element_content = ''
32
33 def characters(self, sData):
34 if self.is_wanted_element:
35 self.element_content += sData
36
37 def _get_or_internalize(self, string):
38 if string not in self.string_map:
39 self.string_map[string] = string
40 return string
41 return self.string_map[string]
42
43 def endElement(self,sName):
44 if sName == self.entry_name:
45 if self.song_entry:
46 self.all_entries.append(self.song_entry)
47 self.song_entry = None
48 self.is_parsing_tag = False
49 elif self.is_parsing_tag and self.is_wanted_element:
50 sName = self.wanted_keys[sName]
51 self.song_entry[sName] = self._get_or_internalize(self.element_content)
5555 def get_label(self, key):
5656 """Return label for setting @key"""
5757 return self.setting_descriptions[key]["label"]
58 def get_alternatives(self, key):
59 """Return alternatives for setting @key (if any)"""
60 return self.setting_descriptions[key].get("alternatives")
306306 return True
307307
308308 def _plugin_makes_sense_in_catalog(self, plugin_id):
309 """Whether the setting for toplevel makes sense for @plugin_id"""
310 return plugins.get_plugin_attribute(plugin_id,
311 plugins.sources_attribute)
309 """Whether the setting for toplevel should be shown for @plugin_id"""
310 setctl = settings.GetSettingsController()
311 return setctl.get_plugin_show_toplevel_option(plugin_id)
312312
313313 def on_buttonpluginsettings_clicked(self, widget):
314314 curpath, curcol = self.table.get_cursor()
333333 if self._plugin_makes_sense_in_catalog(plugin_id):
334334 setctl = settings.GetSettingsController()
335335 incl_label = _("Include in top level")
336 incl_tooltip = _("If enabled, objects from the plugin's source(s) \
337 will be available in the top level.\n\
338 Sources are always available as subcatalogs in the top level.")
336 incl_tooltip = _(
337 "If enabled, objects from the plugin's source(s) "
338 "will be available in the top level.\n"
339 "Sources are always available as subcatalogs in the top level.")
339340 incl_active = setctl.get_plugin_is_toplevel(plugin_id)
340341 incl_type = bool
341342 inclwid = gtk.CheckButton(incl_label)
348349 plugin_settings_keys = iter(plugin_settings) if plugin_settings else ()
349350 for setting in plugin_settings_keys:
350351 typ = plugin_settings.get_value_type(setting)
352 alternatives = plugin_settings.get_alternatives(setting)
351353 wid = None
352354 hbox = gtk.HBox()
353355 hbox.set_property("spacing", 10)
354356 label = plugin_settings.get_label(setting)
355357 label_wid = gtk.Label(label)
356358 if issubclass(typ, basestring):
357 wid = gtk.Entry()
358 wid.set_text(plugin_settings[setting])
359 if alternatives:
360 wid = gtk.combo_box_new_text()
361 val = plugin_settings[setting]
362 active_index = -1
363 for idx, text in enumerate(alternatives):
364 wid.append_text(text)
365 if text == val:
366 active_index = idx
367 if active_index < 0:
368 wid.prepend_text(val)
369 active_index = 0
370 wid.set_active(active_index)
371 wid.connect("changed", self._get_plugin_change_callback(
372 plugin_id, setting, typ, "get_active_text"))
373 else:
374 wid = gtk.Entry()
375 wid.set_text(plugin_settings[setting])
376 wid.connect("changed", self._get_plugin_change_callback(
377 plugin_id, setting, typ, "get_text",
378 no_false_values=True))
359379 hbox.pack_start(label_wid, False)
360380 hbox.pack_start(wid, True)
361 wid.connect("changed", self._get_plugin_change_callback(
362 plugin_id, setting, typ, "get_text", no_false_values=True))
363381
364382 elif issubclass(typ, bool):
365383 wid = gtk.CheckButton(label)
2828 gobject.TYPE_BOOLEAN, ())
2929 gobject.signal_new("finish", Scheduler, gobject.SIGNAL_RUN_LAST,
3030 gobject.TYPE_BOOLEAN, ())
31
32 class Timer (object):
33 def __init__(self, call_at_finish=False):
34 self._current_timer = -1
35 self._call_at_finish = call_at_finish
36 self._current_callback = None
37 GetScheduler().connect("finish", self._on_finish)
38
39 def set(self, timeout_seconds, callback, *arguments):
40 """Setup timer to call @timeout_seconds in the future.
41 If the timer was previously set, it is postponed
42 """
43 self.invalidate()
44 self._current_callback = lambda : callback(*arguments)
45 self._current_timer = gobject.timeout_add_seconds(timeout_seconds,
46 self._call)
47
48 def set_idle(self, callback, *arguments):
49 self.invalidate()
50 self._current_callback = lambda : callback(*arguments)
51 self._current_timer = gobject.idle_add(self._call)
52
53 def _call(self, timer=None):
54 self._current_timer = -1
55 self._current_callback()
56
57 def invalidate(self):
58 if self._current_timer > 0:
59 gobject.source_remove(self._current_timer)
60 self._current_timer = -1
61
62 def is_valid(self):
63 """If Timer is currently set"""
64 return (self._current_timer > 0)
65
66 def _on_finish(self, scheduler):
67 if self._call_at_finish and self.is_valid():
68 self._call()
69 else:
70 self.invalidate()
3232 def __init__(self):
3333 gobject.GObject.__init__(self)
3434 self._config = self._read_config()
35 # connect to save settings
36 sch = scheduler.GetScheduler()
37 sch.connect("finish", self._save_config)
35 self._save_timer = scheduler.Timer(True)
36
37 def _update_config_save_timer(self):
38 self._save_timer.set(60, self._save_config)
39
3840 def _read_config(self, read_config=True):
3941 """
4042 Read cascading config files
104106 return confmap
105107
106108 def _save_config(self, scheduler=None):
109 self.output_debug("Saving config")
107110 config_path = config.save_config_file(self.config_filename)
108111 if not config_path:
109112 self.output_info("Unable to save settings, can't find config dir")
164167 value_type = type(oldvalue)
165168 self._config[section][key] = value_type(value)
166169 self.emit("value-changed", section, key, value)
170 self._update_config_save_timer()
167171 return True
168172 self.output_info("Settings key", section, key, "is invalid")
169173 return False
181185 if section not in self._config:
182186 self._config[section] = {}
183187 self._config[section][key] = str(value)
188 self._update_config_save_timer()
184189 return False
185190
186191 def get_plugin_enabled(self, plugin_id):
197202 """Convenience: if @plugin_id items are included in toplevel"""
198203 return self.get_plugin_config(plugin_id, "kupfer_toplevel",
199204 value_type=strbool, default=True)
205
206 def get_plugin_show_toplevel_option(self, plugin_id):
207 """Convenience: if @plugin_id should show toplevel option"""
208 return self.get_plugin_config(plugin_id, "kupfer_show_toplevel",
209 value_type=strbool, default=False)
200210
201211 def get_plugin_is_hidden(self, plugin_id):
202212 """Convenience: if @plugin_id is hidden"""
0 import threading
1
2 from kupfer import scheduler, pretty
3
4 class Task (object):
5 """Represent a task that can be done in the background"""
6 def __init__(self):
7 self._name = None
8
9 def set_name(self, name):
10 """Allow setting the user-visible name of this task"""
11 self._name = name
12
13 def __str__(self):
14 return self._name and self._name.decode("utf-8")
15
16 def __unicode__(self):
17 return self.name
18
19 def is_thread(self):
20 return False
21
22 def run(self):
23 raise NotImplementedError
24
25 class StepTask (Task):
26 """A step task runs a part of the task in StepTask.step,
27 doing final cleanup in StepTask.finish, which is guaranteed to
28 be called regardless of exit or failure mode
29 """
30 def step(self):
31 """Do a small part of the task.
32 Return True to continue processing,
33 or a False value to finish.
34 """
35 pass
36 def finish(self):
37 pass
38 def run(self):
39 try:
40 while True:
41 if not self.step():
42 break
43 yield
44 finally:
45 self.finish()
46
47 class ThreadTask (Task):
48 """Run in a thread"""
49 def __init__(self):
50 Task.__init__(self)
51 self._thread = None
52
53 def is_thread(self):
54 return True
55
56 def thread_do(self):
57 """Override this to run what should be done in the thread"""
58 raise NotImplementedError
59
60 def run(self):
61 while True:
62 if not self._thread:
63 self._thread = threading.Thread(target=self.thread_do)
64 self._thread.start()
65 elif not self._thread.isAlive():
66 return
67 yield
68
69 class TaskRunner (pretty.OutputMixin):
70 """Run Tasks in the idle Loop"""
71 def __init__(self, end_on_finish):
72 self.task_iters = {}
73 self.thread_iters = {}
74 self.idle_timer = scheduler.Timer(True)
75 self.end_on_finish = end_on_finish
76 scheduler.GetScheduler().connect("finish", self._finish_cleanup)
77
78 def add_task(self, task):
79 """Register @task to be run"""
80 if task.is_thread():
81 # start thread
82 self.thread_iters[task] = task.run()
83 # run through all threads
84 self._step_tasks(self.thread_iters)
85 else:
86 self.task_iters[task] = task.run()
87 self._setup_timers()
88
89 def _setup_timers(self):
90 if self.task_iters:
91 self.idle_timer.set_idle(self._step_tasks, self.task_iters)
92
93 def _step_tasks(self, tasks):
94 for task, task_iter in tasks.items():
95 try:
96 task_iter.next()
97 except StopIteration:
98 self.output_debug("Task done:", task)
99 del tasks[task]
100 self._setup_timers()
101
102 def _finish_cleanup(self, sched):
103 if self.end_on_finish:
104 self.task_iters.clear()
105 self.thread_iters.clear()
106 return
107 self._step_tasks(self.thread_iters)
108 if self.task_iters or self.thread_iters:
109 self.output_info("Uncompleted tasks:")
110 for task in self.task_iters:
111 self.output_info(task)
112 for task in self.thread_iters:
113 self.output_info(task)
114
0 from os import path
0 import itertools
1 import os
2 from os import path as os_path
13 import locale
4
5 import gobject
26
37 from kupfer import pretty
48
1721 for dirname, dirnames, fnames in walk(folder):
1822 # skip deep directories
1923 head, dp = dirname, 0
20 while not path.samefile(head, folder):
21 head, tail = path.split(head)
24 while not os_path.samefile(head, folder):
25 head, tail = os_path.split(head)
2226 dp += 1
2327 if dp > depth:
2428 del dirnames[:]
2933 if not include_file(dir):
3034 excl_dir.append(dir)
3135 continue
32 abspath = path.join(dirname, dir)
36 abspath = os_path.join(dirname, dir)
3337 paths.append(abspath)
3438
3539 for file in fnames:
3640 if not include_file(file):
3741 continue
38 abspath = path.join(dirname, file)
42 abspath = os_path.join(dirname, file)
3943 paths.append(abspath)
4044
4145 for dir in reversed(excl_dir):
4549
4650 def locale_sort(seq, key=unicode):
4751 """Return @seq of objects with @key function as a list sorted
48 in locale lexical order"""
52 in locale lexical order
53
54 >>> locale.setlocale(locale.LC_ALL, "C")
55 'C'
56 >>> locale_sort("abcABC")
57 ['A', 'B', 'C', 'a', 'b', 'c']
58
59 >>> locale.setlocale(locale.LC_ALL, "en_US.UTF-8")
60 'en_US.UTF-8'
61 >>> locale_sort("abcABC")
62 ['a', 'A', 'b', 'B', 'c', 'C']
63 """
4964 locale_cmp = lambda s, o: locale.strcoll(key(s), key(o))
5065 seq = seq if isinstance(seq, list) else list(seq)
5166 seq.sort(cmp=locale_cmp)
5267 return seq
5368
5469 def spawn_async(argv, in_dir="."):
55 import gobject
5670 pretty.print_debug(__name__, "Spawn commandline", argv, in_dir)
5771 try:
5872 return gobject.spawn_async (argv, working_directory=in_dir,
97111 from gtk.gdk import screen_get_default
98112 from glib import GError
99113 try:
114 pretty.print_debug(__name__, "show_url", url)
100115 return show_uri(screen_get_default(), url, get_current_event_time())
101116 except GError, exc:
102117 pretty.print_error(__name__, "gtk.show_uri:", exc)
118
119 def is_directory_writable(dpath):
120 """If directory path @dpath is a valid destination to write new files?
121 """
122 if not os_path.isdir(dpath):
123 return False
124 return os.access(dpath, os.R_OK | os.W_OK | os.X_OK)
125
126 def get_destpath_in_directory(directory, filename, extension=None):
127 """Find a good destpath for a file named @filename in path @directory
128 Try naming the file as filename first, before trying numbered versions
129 if the previous already exist.
130
131 If @extension, it is used as the extension. Else the filename is split and
132 the last extension is used
133 """
134 # find a nonexisting destname
135 ctr = itertools.count(1)
136 basename = filename + (extension or "")
137 destpath = os_path.join(directory, basename)
138 while True:
139 if not os_path.exists(destpath):
140 break
141 if extension:
142 root, ext = filename, extension
143 else:
144 root, ext = os_path.splitext(filename)
145 basename = "%s-%s%s" % (root, ctr.next(), ext)
146 destpath = os_path.join(directory, basename)
147 return destpath
148
149 def get_display_path_for_bytestring(filepath):
150 """Return a unicode path for display for bytestring @filepath
151
152 Will use glib's filename decoding functions, and will
153 format nicely (denote home by ~/ etc)
154 """
155 desc = gobject.filename_display_name(filepath)
156 homedir = os.path.expanduser("~/")
157 if desc.startswith(homedir) and homedir != desc:
158 desc = desc.replace(homedir, "~/", 1)
159 return desc
1313 ICON_NAME = "search"
1414 PROGRAM_NAME = _("Kupfer")
1515
16 AUTHORS = """Ulrik Sverdrup <ulrik.sverdrup@gmail.com>
16 AUTHORS = u"""Ulrik Sverdrup <ulrik.sverdrup@gmail.com>
1717 """.splitlines()
18
19 PACKAGERS=u"""
20 Luca Falavigna (Debian, Ubuntu)
21 """.splitlines()
22
23 TRANSLATORS=u"""
24 Andrea Zagli (it)
25 """.splitlines()
26
27 AUTHORS += PACKAGERS + TRANSLATORS
1828
1929 DOCUMENTERS = []
2030
2131 TRANSLATOR_CREDITS = _("translator-credits")
2232
23 WEBSITE = "http://kaizer.se/wiki/kupfer/"
33 WEBSITE = u"http://kaizer.se/wiki/kupfer/"
2434
2535 SHORT_DESCRIPTION = _("A free software (GPLv3+) launcher")
26 COPYRIGHT = """Copyright © 2007--2009 Ulrik Sverdrup"""
36 COPYRIGHT = u"""Copyright © 2007--2009 Ulrik Sverdrup"""
2737
2838 LICENSE = _("""
2939 This program is free software: you can redistribute it and/or modify
00 VERSION = "@VERSION@"
11 PACKAGE_NAME = "@PACKAGE@"
22 LOCALEDIR = "@LOCALEDIR@"
3 DATADIR = "@DATADIR@"
0 <?xml version="1.0"?>
1 <Project xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
2 xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
3 xmlns:foaf="http://xmlns.com/foaf/0.1/"
4 xmlns:gnome="http://api.gnome.org/doap-extensions#"
5 xmlns="http://usefulinc.com/ns/doap#">
6 <name xml:lang="en">kupfer</name>
7 <shortdesc xml:lang="en">convenient command and access tool</shortdesc>
8 <homepage rdf:resource="http://kaizer.se/wiki/kupfer/"/>
9 <mailing-list rdf:resource="http://mail.gnome.org/mailman/listinfo/kupfer-list"/>
10 <maintainer>
11 <foaf:Person>
12 <foaf:name>Ulrik Sverdrup</foaf:name>
13 <gnome:userid>usverdrup</gnome:userid>
14 </foaf:Person>
15 </maintainer>
16 </Project>
+0
-23
makedist.sh less more
0 #!/bin/sh
1
2 # I use this script to make the release tarballs
3 # It takes just a fresh clone of the repository, copies
4 # the waf binary in, and packages it up.
5 # Thus the dist ball is reasonably clean
6
7 set -x
8 set -e
9
10 OLDPWD=$PWD
11 TMPDIR="/tmp/$(basename $PWD)-dist"
12
13 test -e "$TMPDIR" && echo "$TMPDIR exists" && exit 2
14 echo Using $TMPDIR
15
16 git clone . "$TMPDIR"
17 cp waf "$TMPDIR"
18
19 cd "$TMPDIR"
20 ./waf dist
21 cp -vi *.tar.gz "$OLDPWD"
22 rm -r "$TMPDIR"
55 kupfer/data.py
66 kupfer/main.py
77 kupfer/objects.py
8 kupfer/preferences.py
98 kupfer/plugin/abiword.py
109 kupfer/plugin/applications.py
1110 kupfer/plugin/clipboard.py
2019 kupfer/plugin/fileactions.py
2120 kupfer/plugin/firefox.py
2221 kupfer/plugin/google.py
22 kupfer/plugin/locate.py
2323 kupfer/plugin/rhythmbox.py
2424 kupfer/plugin/screen.py
2525 kupfer/plugin/selection.py
2828 kupfer/plugin/tracker.py
2929 kupfer/plugin/wikipedia.py
3030 kupfer/plugin/windows.py
31 kupfer/plugin/urlactions.py
3132 kupfer/plugin/volumes.py
33 kupfer/preferences.py
3234 kupfer/version.py
+895
-516
po/it.po less more
66 msgstr ""
77 "Project-Id-Version: kupfer beta\n"
88 "Report-Msgid-Bugs-To: \n"
9 "POT-Creation-Date: 2009-07-12 20:12+0200\n"
10 "PO-Revision-Date: 2009-07-05 10:04+0200\n"
9 "POT-Creation-Date: 2009-08-22 09:42+0200\n"
10 "PO-Revision-Date: 2009-08-20 21:49+0200\n"
1111 "Last-Translator: Andrea Zagli <azagli@libero.it>\n"
1212 "Language-Team: Italian <tp@lists.linux.it>\n"
1313 "MIME-Version: 1.0\n"
1616 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
1717
1818 #: ../data/kupfer.desktop.in.in.h:1
19 msgid "A simple flexible launcher"
20 msgstr ""
21
22 #: ../data/kupfer.desktop.in.in.h:2 ../kupfer/browser.py:873
23 #: ../kupfer/browser.py:893 ../kupfer/version.py:15
19 msgid "Application Launcher"
20 msgstr "Lanciatore di applicazioni"
21
22 #: ../data/kupfer.desktop.in.in.h:2
23 msgid "Convenient command and access tool for applications and documents"
24 msgstr "Comodo comando e strumento di accesso per applicazioni e documenti"
25
26 #: ../data/kupfer.desktop.in.in.h:3 ../kupfer/browser.py:1156
27 #: ../kupfer/browser.py:1187 ../kupfer/plugin/core.py:176
28 #: ../kupfer/version.py:15
2429 msgid "Kupfer"
2530 msgstr "Kupfer"
2631
27 #: ../kupfer/browser.py:566
32 #: ../data/preferences.ui.h:1
33 msgid "<b>Interface</b>"
34 msgstr "<b>Interfaccia</b>"
35
36 #: ../data/preferences.ui.h:2
37 msgid "<b>Keybinding</b>"
38 msgstr "<b>Associazione di tasti</b>"
39
40 #: ../data/preferences.ui.h:3
41 msgid "<b>Start</b>"
42 msgstr "<b>Avvio</b>"
43
44 #: ../data/preferences.ui.h:4
45 msgid "General"
46 msgstr "Generale"
47
48 #: ../data/preferences.ui.h:5 ../kupfer/plugin/core.py:163
49 msgid "Kupfer Preferences"
50 msgstr "Preferenze di Kupfer"
51
52 #: ../data/preferences.ui.h:6
53 msgid "Plugins"
54 msgstr "Plugin"
55
56 #: ../data/preferences.ui.h:7
57 msgid "Show icon in notification area"
58 msgstr "Mostrare l'icona nell'area di notifica"
59
60 #: ../data/preferences.ui.h:8
61 msgid "Start automatically on login"
62 msgstr "Avvia automaticamente all'accesso"
63
64 #: ../kupfer/browser.py:638
2865 #, python-format
2966 msgid "%s is empty"
3067 msgstr "%s è vuoto"
3168
32 #: ../kupfer/browser.py:568
69 #: ../kupfer/browser.py:640
3370 #, python-format
3471 msgid "No matches in %s"
3572 msgstr "Nessuna corrispondenza in %s"
3673
37 #: ../kupfer/browser.py:573
74 #: ../kupfer/browser.py:645
3875 msgid "Searching..."
3976 msgstr "Ricerca..."
4077
41 #: ../kupfer/browser.py:576
78 #: ../kupfer/browser.py:651
4279 #, python-format
4380 msgid "Searching %(source)s..."
44 msgstr "Ricerca di %(source)s..."
45
46 #: ../kupfer/main.py:34
81 msgstr "Ricerca in %(source)s..."
82
83 #: ../kupfer/main.py:38
4784 msgid "Usage:"
4885 msgstr "Uso:"
4986
50 #: ../kupfer/main.py:37
87 #: ../kupfer/main.py:41
5188 msgid "do not present main interface on launch"
52 msgstr ""
53
54 #: ../kupfer/main.py:40
89 msgstr "non presentare l'interfaccia principale all'avvio"
90
91 #: ../kupfer/main.py:44
5592 msgid "show usage help"
5693 msgstr "mostra l'aiuto per l'uso"
5794
58 #: ../kupfer/main.py:41
95 #: ../kupfer/main.py:45
5996 msgid "show version information"
6097 msgstr "mostra informazioni sulla versione"
6198
62 #: ../kupfer/main.py:42
99 #: ../kupfer/main.py:46
63100 msgid "enable debug info"
64101 msgstr "abilita informazioni di debug"
65102
66 #: ../kupfer/main.py:47
103 #: ../kupfer/main.py:51
67104 msgid "To configure kupfer, edit:"
68105 msgstr "Per configurare kupfer, modificare:"
69106
70 #: ../kupfer/main.py:48
107 #: ../kupfer/main.py:52
71108 msgid "The default config for reference is at:"
72109 msgstr "La configurazione predefinita di riferimento è in:"
73110
74 #: ../kupfer/main.py:49
111 #: ../kupfer/main.py:53
75112 msgid "Available plugins:"
76113 msgstr "Plugin disponibili:"
77114
78 #: ../kupfer/main.py:114
115 #: ../kupfer/main.py:118
79116 #, python-format
80117 msgid ""
81118 "%(program)s: %(desc)s\n"
82119 "\t%(copyright)s\n"
83120 "\t%(website)s\n"
84 "\t"
85121 msgstr ""
86122 "%(program)s: %(desc)s\n"
87123 "\t%(copyright)s\n"
88124 "\t%(website)s\n"
89 "\t"
90
91 #: ../kupfer/objects.py:155
125
126 #: ../kupfer/objects.py:227
92127 msgid "No matches"
93128 msgstr "Nessuna corrispondenza"
94129
95 #: ../kupfer/objects.py:350
96 #, python-format
97 msgid "%(description)s (%(exec)s)"
98 msgstr "%(description)s (%(exec)s)"
99
100 #: ../kupfer/objects.py:426 ../kupfer/objects.py:470 ../kupfer/objects.py:484
130 #: ../kupfer/objects.py:569 ../kupfer/objects.py:630 ../kupfer/objects.py:645
101131 msgid "Open"
102132 msgstr "Apri"
103133
104 #: ../kupfer/objects.py:426 ../kupfer/objects.py:440
134 #: ../kupfer/objects.py:569 ../kupfer/objects.py:578 ../kupfer/objects.py:581
135 #: ../kupfer/objects.py:593
105136 #, python-format
106137 msgid "Open with %s"
107138 msgstr "Apri con %s"
108139
109 #: ../kupfer/objects.py:438
110 #, python-format
111 msgid "Open with %s (default)"
112 msgstr "Apri con %s (predefinito)"
113
114 #: ../kupfer/objects.py:452
140 #: ../kupfer/objects.py:611
115141 msgid "Open URL"
116142 msgstr "Apri URL"
117143
118 #: ../kupfer/objects.py:463
144 #: ../kupfer/objects.py:622
119145 msgid "Open URL with default viewer"
120146 msgstr "Apri URL con visualizzatore predefinito"
121147
122 #: ../kupfer/objects.py:477
148 #: ../kupfer/objects.py:637
123149 msgid "Open with default viewer"
124150 msgstr "Apri con visualizzatore predefinito"
125151
126 #: ../kupfer/objects.py:487
152 #: ../kupfer/objects.py:648
127153 msgid "Open folder"
128154 msgstr "Apri cartella"
129155
130 #: ../kupfer/objects.py:493
156 #: ../kupfer/objects.py:654
131157 msgid "Reveal"
132158 msgstr "Rivela"
133159
134 #: ../kupfer/objects.py:502
160 #: ../kupfer/objects.py:663
135161 msgid "Open parent folder"
136162 msgstr "Apri cartella superiore"
137163
138 #: ../kupfer/objects.py:508
139 msgid "Open Terminal here"
164 #: ../kupfer/objects.py:669
165 msgid "Open Terminal Here"
140166 msgstr "Apri terminale qui"
141167
142 #: ../kupfer/objects.py:526
168 #: ../kupfer/objects.py:678
169 msgid "Open this location in a terminal"
170 msgstr "Apre questa posizione in un terminale"
171
172 #: ../kupfer/objects.py:691
143173 msgid "Launch"
144174 msgstr "Lancia"
145175
146 #: ../kupfer/objects.py:536
176 #: ../kupfer/objects.py:701
147177 msgid "Launch application"
148178 msgstr "Lancia applicazione"
149179
150 #: ../kupfer/objects.py:542 ../kupfer/plugin/windows.py:48
151 msgid "Go to"
180 #: ../kupfer/objects.py:708 ../kupfer/plugin/windows.py:49
181 msgid "Go To"
152182 msgstr "Vai a"
153183
154 #: ../kupfer/objects.py:546
155 #, fuzzy
184 #: ../kupfer/objects.py:712
156185 msgid "Show application window"
157 msgstr "Lancia applicazione"
158
159 #: ../kupfer/objects.py:554
160 #, fuzzy
161 msgid "Launch again"
162 msgstr "Lancia applicazione"
163
164 #: ../kupfer/objects.py:558
186 msgstr "Mostra la finestra dell'applicazione"
187
188 #: ../kupfer/objects.py:721
189 msgid "Launch Again"
190 msgstr "Lancia di nuovo"
191
192 #: ../kupfer/objects.py:725
165193 msgid "Launch another instance of this application"
166 msgstr ""
167
168 #: ../kupfer/objects.py:565
194 msgstr "Lancia un'altra istanza di questa applicazione"
195
196 #: ../kupfer/objects.py:732
169197 msgid "Run in Terminal"
170198 msgstr "Esegui nel terminale"
171199
172 #: ../kupfer/objects.py:565
200 #: ../kupfer/objects.py:732
173201 msgid "Run"
174202 msgstr "Esegui"
175203
176 #: ../kupfer/objects.py:576
204 #: ../kupfer/objects.py:746
177205 msgid "Run this program in a Terminal"
178 msgstr "Esegui questo programma nel terminale"
179
180 #: ../kupfer/objects.py:578
206 msgstr "Esegui questo programma in un terminale"
207
208 #: ../kupfer/objects.py:748
181209 msgid "Run this program"
182210 msgstr "Esegui questo programma"
183211
184 #: ../kupfer/objects.py:590
185 msgid "Search content..."
212 #: ../kupfer/objects.py:756
213 msgid "No action"
214 msgstr "Nessuna azione"
215
216 #. TRANS: Multiple artist description "Artist1 et. al. "
217 #: ../kupfer/objects.py:871 ../kupfer/plugin/rhythmbox.py:218
218 #, python-format
219 msgid "%s et. al."
220 msgstr "%s et. al."
221
222 #: ../kupfer/objects.py:900
223 #, python-format
224 msgid "Recursive source of %(dir)s, (%(levels)d levels)"
225 msgstr "Sorgente ricorsiva di %(dir)s, (%(levels)d livelli)"
226
227 #: ../kupfer/objects.py:968
228 #, python-format
229 msgid "Directory source %s"
230 msgstr "Directory sorgente «%s»"
231
232 #: ../kupfer/objects.py:984
233 msgid "Catalog Index"
234 msgstr "Indice del catalogo"
235
236 #: ../kupfer/objects.py:999
237 msgid "An index of all available sources"
238 msgstr "Un indice di tutte le sorgenti disponibili"
239
240 #: ../kupfer/objects.py:1010
241 msgid "Catalog"
242 msgstr "Catalogo"
243
244 #: ../kupfer/objects.py:1029
245 msgid "Root catalog"
246 msgstr "Catalogo radice"
247
248 #: ../kupfer/objects.py:1106
249 msgid "Do"
250 msgstr "Esegui"
251
252 #: ../kupfer/objects.py:1111
253 msgid "Perform action"
254 msgstr "Esegui azione"
255
256 #. TRANS: This is description for a TextLeaf, a free-text search
257 #. TRANS: The plural parameter is the number of lines %(num)d
258 #: ../kupfer/objects.py:1136
259 #, python-format
260 msgid "\"%(text)s\""
261 msgid_plural "(%(num)d lines) \"%(text)s\""
262 msgstr[0] "\"%(text)s\""
263 msgstr[1] "(%(num)d righe) \"%(text)s\""
264
265 #: ../kupfer/objects.py:1148 ../kupfer/plugin/text.py:18
266 msgid "Text Matches"
267 msgstr "Corrispondenze del testo"
268
269 #: ../kupfer/preferences.py:160
270 msgid "Applied"
271 msgstr "Applicato"
272
273 #: ../kupfer/preferences.py:165
274 msgid "Keybinding could not be bound"
275 msgstr "L'associazione di tasti non può essere associata"
276
277 #. TRANS: Plugin contents header
278 #: ../kupfer/preferences.py:283
279 msgid "Sources"
280 msgstr "Sorgenti"
281
282 #. TRANS: Plugin contents header
283 #: ../kupfer/preferences.py:287
284 msgid "Actions"
285 msgstr "Azioni"
286
287 #: ../kupfer/preferences.py:324
288 #, python-format
289 msgid "Settings for %s"
290 msgstr "Impostazioni per %s"
291
292 #: ../kupfer/preferences.py:336
293 msgid "Include in top level"
294 msgstr "Includi nel livello principale"
295
296 #: ../kupfer/preferences.py:337
297 msgid ""
298 "If enabled, objects from the plugin's source(s) will be available in the top "
299 "level.\n"
300 "Sources are always available as subcatalogs in the top level."
301 msgstr ""
302 "Se abilitata, gli oggetti dal sorgente dei plugin saranno disponibili nel "
303 "livello principale.\n"
304 "I sorgenti sono sempre disponibili come sotto cataloghi nel livello "
305 "principale."
306
307 #: ../kupfer/plugin/abiword.py:12
308 msgid "Abiword"
309 msgstr "Abiword"
310
311 #: ../kupfer/plugin/abiword.py:15 ../kupfer/plugin/abiword.py:103
312 msgid "Recently used documents in Abiword"
313 msgstr "Documenti utilizzati recentemente in Abiword"
314
315 #: ../kupfer/plugin/abiword.py:56
316 msgid "Abiword Recent Items"
317 msgstr "Voci recenti di Abiword"
318
319 #: ../kupfer/plugin/applications.py:4 ../kupfer/plugin/applications.py:19
320 msgid "Applications"
321 msgstr "Applicazioni"
322
323 #: ../kupfer/plugin/applications.py:7 ../kupfer/plugin/applications.py:37
324 msgid "All applications and preferences"
325 msgstr "Tutte le applicazioni e le preferenze"
326
327 #: ../kupfer/plugin/applications.py:46
328 msgid "Open With..."
329 msgstr "Apri con..."
330
331 #: ../kupfer/plugin/applications.py:57
332 msgid "Open with any application"
333 msgstr "Apri con qualsiasi applicazione"
334
335 #: ../kupfer/plugin/clipboard.py:8 ../kupfer/plugin/clipboard.py:42
336 msgid "Clipboards"
337 msgstr "Appunti"
338
339 #: ../kupfer/plugin/clipboard.py:11 ../kupfer/plugin/clipboard.py:68
340 msgid "Recent clipboards"
341 msgstr "Appunti recenti"
342
343 #: ../kupfer/plugin/clipboard.py:18
344 msgid "Number of recent clipboards"
345 msgstr "Numero di appunti recenti"
346
347 #: ../kupfer/plugin/clipboard.py:34
348 #, python-format
349 msgid "Clipboard \"%(desc)s\""
350 msgid_plural "Clipboard with %(num)d lines \"%(desc)s\""
351 msgstr[0] "Appunti \"%(desc)s\""
352 msgstr[1] "Appunti con %(num)d righe \"%(desc)s\""
353
354 #: ../kupfer/plugin/clipboard.py:78
355 msgid "Copy"
356 msgstr "Copia"
357
358 #: ../kupfer/plugin/clipboard.py:85
359 msgid "Copy to clipboard"
360 msgstr "Copia negli appunti"
361
362 #: ../kupfer/plugin/commands.py:10 ../kupfer/plugin/commands.py:36
363 msgid "Shell Commands"
364 msgstr "Comandi della shell"
365
366 #: ../kupfer/plugin/commands.py:13 ../kupfer/plugin/commands.py:55
367 msgid "Run commandline programs"
368 msgstr "Esegui programmi a riga di comando"
369
370 #: ../kupfer/plugin/common.py:8
371 msgid "Common"
372 msgstr "Comuni"
373
374 #: ../kupfer/plugin/common.py:10
375 msgid "Special items and actions"
376 msgstr "Voci speciali e azioni"
377
378 #: ../kupfer/plugin/common.py:28
379 msgid "Log Out..."
380 msgstr "Uscita..."
381
382 #: ../kupfer/plugin/common.py:34
383 msgid "Log out or change user"
384 msgstr "Esci o cambia utente"
385
386 #: ../kupfer/plugin/common.py:41
387 msgid "Shut Down..."
388 msgstr "Arresto..."
389
390 #: ../kupfer/plugin/common.py:48
391 msgid "Shut down, restart or suspend computer"
392 msgstr "Arresta, riavvia o sospende il computer"
393
394 #: ../kupfer/plugin/common.py:55
395 msgid "Lock Screen"
396 msgstr "Blocca lo schermo"
397
398 #: ../kupfer/plugin/common.py:61
399 msgid "Enable screensaver and lock"
400 msgstr "Abilita il salvaschermo e blocca"
401
402 #: ../kupfer/plugin/common.py:97
403 msgid "Trash is empty"
404 msgstr "Il cestino è vuoto"
405
406 #. proper translation of plural
407 #: ../kupfer/plugin/common.py:99
408 #, python-format
409 msgid "Trash contains one file"
410 msgid_plural "Trash contains %(num)s files"
411 msgstr[0] "Il cestino contiene un file"
412 msgstr[1] "Il cestino contiene %(num)s file"
413
414 #: ../kupfer/plugin/common.py:103
415 msgid "Special Items"
416 msgstr "Voci speciali"
417
418 #: ../kupfer/plugin/common.py:118
419 msgid "Items and special actions"
420 msgstr "Voci e azioni speciali"
421
422 #: ../kupfer/plugin/core.py:25
423 msgid "Search Content..."
186424 msgstr "Cerca contenuto..."
187425
188 #: ../kupfer/objects.py:601
426 #: ../kupfer/plugin/core.py:40
189427 msgid "Search inside this catalog"
190428 msgstr "Cerca all'interno del catalogo"
191429
192 #: ../kupfer/objects.py:611
430 #: ../kupfer/plugin/core.py:48
193431 msgid "Rescan"
194432 msgstr "Nuova scansione"
195433
196 #: ../kupfer/objects.py:624
434 #: ../kupfer/plugin/core.py:57
197435 msgid "Force reindex of this source"
198 msgstr "Forza l'indicizzazione di questa sorgente"
199
200 #: ../kupfer/objects.py:635
201 msgid "No action"
202 msgstr "Nessuna azione"
203
204 #: ../kupfer/objects.py:713
205 #, python-format
206 msgid "%s et al"
207 msgstr "%s et al"
208
209 #: ../kupfer/objects.py:739
210 #, python-format
211 msgid "Recursive source of %(dir)s, (%(levels)d levels)"
212 msgstr "Sorgente ricorsiva di %(dir)s, (%(levels)d livelli)"
213
214 #: ../kupfer/objects.py:810
215 #, python-format
216 msgid "Directory source %s"
217 msgstr "Directory sorgente «%s»"
218
219 #: ../kupfer/objects.py:823
220 msgid "Catalog index"
221 msgstr "Catalogo di cataloghi"
222
223 #: ../kupfer/objects.py:834
224 msgid "An index of all available sources"
225 msgstr "Un indice di tutte le sorgenti disponibili"
226
227 #: ../kupfer/objects.py:845
228 msgid "Catalog"
229 msgstr "Catalogo"
230
231 #: ../kupfer/objects.py:864
232 msgid "Root catalog"
233 msgstr "Catalogo radice"
234
235 #. TRANS: This is description for a TextLeaf, a free-text search
236 #: ../kupfer/objects.py:1010
237 #, python-format
238 msgid "\"%s\""
239 msgstr "«%s»"
240
241 #: ../kupfer/objects.py:905 ../kupfer/plugin/text.py:16
242 msgid "Text matches"
243 msgstr "Corrispondenze del testo"
244
245 #: ../kupfer/plugins.py:41
436 msgstr "Forza la re-indicizzazione di questa sorgente"
437
438 #: ../kupfer/plugin/core.py:141
439 msgid "Quit"
440 msgstr "Esci"
441
442 #: ../kupfer/plugin/core.py:146
443 msgid "Quit Kupfer"
444 msgstr "Esce da Kupfer"
445
446 #: ../kupfer/plugin/core.py:152
447 msgid "About Kupfer"
448 msgstr "Informazioni su Kupfer"
449
450 #: ../kupfer/plugin/core.py:157
451 msgid "Show information about Kupfer authors and license"
452 msgstr "Mostra informazioni sugli autori di Kupfer e sulla licenza"
453
454 #: ../kupfer/plugin/core.py:170
455 msgid "Show preferences window for Kupfer"
456 msgstr "Mostra la finestra delle preferenze di Kupfer"
457
458 #: ../kupfer/plugin/core.py:187
459 msgid "Kupfer items and actions"
460 msgstr "Voci e azioni speciali di Kupfer"
461
462 #: ../kupfer/plugin/devhelp.py:4
463 msgid "Devhelp"
464 msgstr "Devhelp"
465
466 #: ../kupfer/plugin/devhelp.py:6 ../kupfer/plugin/devhelp.py:12
467 msgid "Search in Devhelp"
468 msgstr "Cerca in Devhelp"
469
470 #: ../kupfer/plugin/dictionary.py:4
471 msgid "Dictionary"
472 msgstr "Dizionario"
473
474 #: ../kupfer/plugin/dictionary.py:6 ../kupfer/plugin/dictionary.py:23
475 msgid "Look up word in dictionary"
476 msgstr "Cerca la parola nel dizionario"
477
478 #: ../kupfer/plugin/dictionary.py:12 ../kupfer/plugin/dictionary.py:16
479 msgid "Look Up"
480 msgstr "Cerca"
481
482 #: ../kupfer/plugin/documents.py:11
483 msgid "Documents"
484 msgstr "Documenti"
485
486 #: ../kupfer/plugin/documents.py:14
487 msgid "Recently used documents and nautilus places"
488 msgstr "Documenti utilizzati recentemente e risorse di nautilus"
489
490 #: ../kupfer/plugin/documents.py:21
491 msgid "Max recent document days"
492 msgstr "Giorni massimi dei documenti recenti"
493
494 #: ../kupfer/plugin/documents.py:31
495 msgid "Recent Items"
496 msgstr "Voci recenti"
497
498 #: ../kupfer/plugin/documents.py:77
499 msgid "Recently used documents"
500 msgstr "Documenti utilizzati recentemente"
501
502 #: ../kupfer/plugin/documents.py:87
503 #, python-format
504 msgid "%s Documents"
505 msgstr "Documenti %s"
506
507 #: ../kupfer/plugin/documents.py:112
508 #, python-format
509 msgid "Recently used documents for %s"
510 msgstr "Documenti utilizzati recentemente per %s"
511
512 #: ../kupfer/plugin/documents.py:131
513 msgid "Places"
514 msgstr "Risorse"
515
516 #: ../kupfer/plugin/documents.py:163
517 msgid "Bookmarked locations in Nautilus"
518 msgstr "Posizioni nei segnalibri di Nautilus"
519
520 #: ../kupfer/plugin/epiphany.py:4 ../kupfer/plugin/epiphany.py:14
521 msgid "Epiphany Bookmarks"
522 msgstr "Segnalibri di Epiphany"
523
524 #: ../kupfer/plugin/epiphany.py:7 ../kupfer/plugin/epiphany.py:23
525 msgid "Index of Epiphany bookmarks"
526 msgstr "Indice dei segnalibri di Epiphany"
527
528 #: ../kupfer/plugin/favorites.py:8 ../kupfer/plugin/favorites.py:27
529 msgid "Favorites"
530 msgstr "Preferiti"
531
532 #: ../kupfer/plugin/favorites.py:11
533 msgid "(Simple) favorites plugin"
534 msgstr "(Semplice) plugin favoriti"
535
536 #: ../kupfer/plugin/favorites.py:54
537 msgid "Shelf of \"Favorite\" items"
538 msgstr "Lista di voci preferite"
539
540 #: ../kupfer/plugin/favorites.py:66
541 msgid "Add to Favorites"
542 msgstr "Aggiungi ai preferiti"
543
544 #: ../kupfer/plugin/favorites.py:76
545 msgid "Add item to favorites shelf"
546 msgstr "Aggiunge la voce alla lista dei preferiti"
547
548 #: ../kupfer/plugin/favorites.py:82
549 msgid "Remove from Favorites"
550 msgstr "Rimuovi dai preferiti"
551
552 #: ../kupfer/plugin/favorites.py:90
553 msgid "Remove item from favorites shelf"
554 msgstr "Rimuove la voce dalla lista dei preferiti"
555
556 #: ../kupfer/plugin/fileactions.py:10
557 msgid "File Actions"
558 msgstr "Azioni file"
559
560 #: ../kupfer/plugin/fileactions.py:20
561 msgid "More file actions"
562 msgstr "Altre azioni file"
563
564 #: ../kupfer/plugin/fileactions.py:28
565 msgid "Move to Trash"
566 msgstr "Sposta nel cestino"
567
568 #: ../kupfer/plugin/fileactions.py:36
569 msgid "Move this file to trash"
570 msgstr "Sposta questo file nel cestino"
571
572 #: ../kupfer/plugin/fileactions.py:64
573 msgid "Move To..."
574 msgstr "Sposta in..."
575
576 #: ../kupfer/plugin/fileactions.py:87
577 msgid "Move file to new location"
578 msgstr "Sposta il file in una nuova posizione"
579
580 #: ../kupfer/plugin/fileactions.py:91
581 msgid "Copy To..."
582 msgstr "Copia in..."
583
584 #: ../kupfer/plugin/fileactions.py:119
585 msgid "Copy file to a chosen location"
586 msgstr "Copia i file in una nuova posizione"
587
588 #: ../kupfer/plugin/fileactions.py:123
589 msgid "Extract Here"
590 msgstr "Estrai qui"
591
592 #: ../kupfer/plugin/fileactions.py:137
593 msgid "Extract compressed archive"
594 msgstr "Estrae l'archivio compresso"
595
596 #: ../kupfer/plugin/fileactions.py:141
597 msgid "Create Archive"
598 msgstr "Crea archivio"
599
600 #: ../kupfer/plugin/fileactions.py:151
601 msgid "Create a compressed archive from folder"
602 msgstr "Crea un archivio compresso dalla cartella"
603
604 #: ../kupfer/plugin/firefox.py:4 ../kupfer/plugin/firefox.py:14
605 msgid "Firefox Bookmarks"
606 msgstr "Segnalibri di Firefox"
607
608 #: ../kupfer/plugin/firefox.py:7 ../kupfer/plugin/firefox.py:22
609 msgid "Index of Firefox bookmarks"
610 msgstr "Indice dei segnalibri di Firefox"
611
612 #: ../kupfer/plugin/google.py:8
613 msgid "Search the Web"
614 msgstr "Cerca sul web"
615
616 #: ../kupfer/plugin/google.py:12
617 msgid "Send search queries to Google"
618 msgstr "Invia le interrogazioni di ricerca a Google"
619
620 #: ../kupfer/plugin/google.py:18
621 msgid "Search with Google"
622 msgstr "Cerca con Google"
623
624 #: ../kupfer/plugin/google.py:27
625 msgid "Search for this term with Google"
626 msgstr "Cerca questo termine con Google"
627
628 #: ../kupfer/plugin/rhythmbox.py:10 ../kupfer/plugin/rhythmbox.py:347
629 msgid "Rhythmbox"
630 msgstr "Rhythmbox"
631
632 #: ../kupfer/plugin/rhythmbox.py:15 ../kupfer/plugin/rhythmbox.py:382
633 msgid "Play and enqueue tracks and browse the music library"
634 msgstr "Riproduce, accoda tracce e sfoglia la libreria musicale"
635
636 #: ../kupfer/plugin/rhythmbox.py:22
637 msgid "Include artists in top level"
638 msgstr "Include gli artisti nel livello principale"
639
640 #: ../kupfer/plugin/rhythmbox.py:28
641 msgid "Include albums in top level"
642 msgstr "Include gli album nel livello principale"
643
644 #: ../kupfer/plugin/rhythmbox.py:34
645 msgid "Include songs in top level"
646 msgstr "Include le canzoni nel livello principale"
647
648 #: ../kupfer/plugin/rhythmbox.py:63 ../kupfer/plugin/rhythmbox.py:116
649 msgid "Play"
650 msgstr "Riproduci"
651
652 #: ../kupfer/plugin/rhythmbox.py:67
653 msgid "Resume playback in Rhythmbox"
654 msgstr "Riprende la riproduzione in Rhythmbox"
655
656 #: ../kupfer/plugin/rhythmbox.py:73
657 msgid "Pause"
658 msgstr "Pausa"
659
660 #: ../kupfer/plugin/rhythmbox.py:77
661 msgid "Pause playback in Rhythmbox"
662 msgstr "Mette in pausa la riproduzione in Rhythmbox"
663
664 #: ../kupfer/plugin/rhythmbox.py:83
665 msgid "Next"
666 msgstr "Successiva"
667
668 #: ../kupfer/plugin/rhythmbox.py:87
669 msgid "Jump to next track in Rhythmbox"
670 msgstr "Salta alla traccia successiva in Rhythmbox"
671
672 #: ../kupfer/plugin/rhythmbox.py:93
673 msgid "Previous"
674 msgstr "Precedente"
675
676 #: ../kupfer/plugin/rhythmbox.py:97
677 msgid "Jump to previous track in Rhythmbox"
678 msgstr "Salta alla traccia precedente in Rhythmbox"
679
680 #: ../kupfer/plugin/rhythmbox.py:103
681 msgid "Show Playing"
682 msgstr "Mostra riproduzione"
683
684 #: ../kupfer/plugin/rhythmbox.py:107
685 msgid "Tell which song is currently playing"
686 msgstr "Mostra quale canzone è attualmente riprodotta"
687
688 #: ../kupfer/plugin/rhythmbox.py:129
689 msgid "Play tracks in Rhythmbox"
690 msgstr "Riproduce tracce in Rhythmbox"
691
692 #: ../kupfer/plugin/rhythmbox.py:135
693 msgid "Enqueue"
694 msgstr "Accoda"
695
696 #: ../kupfer/plugin/rhythmbox.py:146
697 msgid "Add tracks to the play queue"
698 msgstr "Aggiunge tracce alla coda di riproduzione"
699
700 #. TRANS: Song description
701 #: ../kupfer/plugin/rhythmbox.py:168
702 #, python-format
703 msgid "by %(artist)s from %(album)s"
704 msgstr "di %(artist)s da %(album)s"
705
706 #. TRANS: Album description "by Artist"
707 #: ../kupfer/plugin/rhythmbox.py:221
708 #, python-format
709 msgid "by %s"
710 msgstr "di %s"
711
712 #. TRANS: Artist songs collection description
713 #: ../kupfer/plugin/rhythmbox.py:260
714 #, python-format
715 msgid "Tracks by %s"
716 msgstr "Traccia da %s"
717
718 #: ../kupfer/plugin/rhythmbox.py:270
719 msgid "Albums"
720 msgstr "Album"
721
722 #: ../kupfer/plugin/rhythmbox.py:280
723 msgid "Music albums in Rhythmbox Library"
724 msgstr "Album musicali nella libreria di Rhythmbox"
725
726 #: ../kupfer/plugin/rhythmbox.py:291
727 msgid "Artists"
728 msgstr "Artisti"
729
730 #: ../kupfer/plugin/rhythmbox.py:301
731 msgid "Music artists in Rhythmbox Library"
732 msgstr "Artisti musicali nella libreria di Rhythmbox"
733
734 #: ../kupfer/plugin/rhythmbox.py:327
735 msgid "Songs"
736 msgstr "Canzoni"
737
738 #: ../kupfer/plugin/rhythmbox.py:337
739 msgid "Songs in Rhythmbox library"
740 msgstr "Canzoni nella libreria di Rhythmbox"
741
742 #: ../kupfer/plugin/screen.py:7 ../kupfer/plugin/screen.py:109
743 msgid "GNU Screen"
744 msgstr "GNU Screen"
745
746 #: ../kupfer/plugin/screen.py:9 ../kupfer/plugin/screen.py:94
747 msgid "Active GNU Screen sessions"
748 msgstr "Sessioni attive di GNU Screen"
749
750 #: ../kupfer/plugin/screen.py:49
751 msgid "Attached"
752 msgstr "Attaccato"
753
754 #: ../kupfer/plugin/screen.py:50
755 msgid "Detached"
756 msgstr "Separato"
757
758 #: ../kupfer/plugin/screen.py:53
759 #, python-format
760 msgid "%(status)s session (%(pid)s) created %(time)s"
761 msgstr "Sessione %(status)s (%(pid)s) creata %(time)s"
762
763 #: ../kupfer/plugin/screen.py:62
764 msgid "Screen Sessions"
765 msgstr "Sessioni di Screen"
766
767 #: ../kupfer/plugin/screen.py:104
768 msgid "Attach"
769 msgstr "Attacca"
770
771 #: ../kupfer/plugin/selection.py:5 ../kupfer/plugin/selection.py:13
772 #: ../kupfer/plugin/selection.py:22
773 msgid "Selected Text"
774 msgstr "Testo selezionato"
775
776 #: ../kupfer/plugin/selection.py:7 ../kupfer/plugin/selection.py:39
777 msgid "Provides current selection"
778 msgstr "Fornisce la selezione attuale"
779
780 #: ../kupfer/plugin/selection.py:20
781 #, python-format
782 msgid "Selected Text \"%s\""
783 msgstr "Testo selezionato «%s»"
784
785 #: ../kupfer/plugins.py:51
246786 msgid "(no description)"
247787 msgstr "(nessuna descrizione)"
248788
249 #: ../kupfer/plugins.py:60
789 #: ../kupfer/plugins.py:70
250790 #, python-format
251791 msgid " %(name)-20s %(version)-4s %(description)s"
252792 msgstr " %(name)-20s %(version)-4s %(description)s"
793
794 #: ../kupfer/plugin/text.py:8
795 msgid "Free-text Queries"
796 msgstr "Interrogazioni a testo libero"
797
798 #: ../kupfer/plugin/text.py:11
799 msgid "Basic support for free-text queries"
800 msgstr "Supporto base per testi d'interrogazione liberi"
801
802 #: ../kupfer/plugin/text.py:31
803 msgid "Filesystem Text Matches"
804 msgstr "Corrispondenze di testo nel file system"
805
806 #: ../kupfer/plugin/text.py:49
807 msgid "URL Text Matches"
808 msgstr "Corrispondenze di testo in URL"
809
810 #: ../kupfer/plugin/tracker.py:9
811 msgid "Tracker"
812 msgstr "Tracker"
813
814 #: ../kupfer/plugin/tracker.py:18
815 msgid "Tracker desktop search integration"
816 msgstr "Integrazione con Tracker, ricerca scrivania"
817
818 #: ../kupfer/plugin/tracker.py:24
819 msgid "Search in Tracker"
820 msgstr "Cerca in Tracker"
821
822 #: ../kupfer/plugin/tracker.py:29
823 msgid "Open Tracker Search Tool and search for this term"
824 msgstr "Apre lo strumento di ricerca Tracker e cerca questo termine"
825
826 #: ../kupfer/plugin/tracker.py:38
827 msgid "Get Tracker Results..."
828 msgstr "Recupero risultati di Tracker..."
829
830 #: ../kupfer/plugin/tracker.py:47
831 msgid "Show Tracker results for query"
832 msgstr "Mostra i risultati di Tracker per l'interrogazione"
833
834 #: ../kupfer/plugin/tracker.py:55 ../kupfer/plugin/tracker.py:92
835 #, python-format
836 msgid "Results for \"%s\""
837 msgstr "Risultati per «%s»"
838
839 #: ../kupfer/plugin/tracker.py:123 ../kupfer/plugin/tracker.py:129
840 msgid "Tracker tags"
841 msgstr "Etichette di Tracker"
842
843 #: ../kupfer/plugin/tracker.py:138
844 msgid "Tracker Tags"
845 msgstr "Etichette di Tracker"
846
847 #: ../kupfer/plugin/tracker.py:144
848 msgid "Browse Tracker's tags"
849 msgstr "Esplora le etichette di Tracker"
850
851 #: ../kupfer/plugin/tracker.py:155 ../kupfer/plugin/tracker.py:162
852 #, python-format
853 msgid "Tag %s"
854 msgstr "Etichetta %s"
855
856 #: ../kupfer/plugin/tracker.py:169
857 #, python-format
858 msgid "Objects tagged %s with Tracker"
859 msgstr "Oggetti etichettati «%s» con Tracker"
860
861 #: ../kupfer/plugin/tracker.py:181
862 msgid "Add Tag..."
863 msgstr "Aggiungi etichetta..."
864
865 #: ../kupfer/plugin/tracker.py:207
866 msgid "Add tracker tag to file"
867 msgstr "Aggiunge l'etichetta di tracker al file"
868
869 #: ../kupfer/plugin/tracker.py:213
870 msgid "Remove Tag..."
871 msgstr "Rimuovi etichetta..."
872
873 #: ../kupfer/plugin/tracker.py:232
874 msgid "Remove tracker tag from file"
875 msgstr "Rimuove l'etichetta di tracker dal file"
876
877 #: ../kupfer/plugin/wikipedia.py:10
878 msgid "Wikipedia"
879 msgstr "Wikipedia"
880
881 #: ../kupfer/plugin/wikipedia.py:13 ../kupfer/plugin/wikipedia.py:30
882 msgid "Search in Wikipedia"
883 msgstr "Cerca in Wikipedia"
884
885 #: ../kupfer/plugin/wikipedia.py:20
886 msgid "Wikipedia language"
887 msgstr "Lingua di Wikipedia"
888
889 #. TRANS: Default wikipedia language code
890 #: ../kupfer/plugin/wikipedia.py:23
891 msgid "en"
892 msgstr "it"
893
894 #: ../kupfer/plugin/wikipedia.py:43
895 #, python-format
896 msgid "Search for this term in %s.wikipedia.org"
897 msgstr "Cerca questo termine in %s.wikipedia.org"
898
899 #: ../kupfer/plugin/windows.py:7 ../kupfer/plugin/windows.py:91
900 msgid "Window List"
901 msgstr "Elenco finestre"
902
903 #: ../kupfer/plugin/windows.py:9 ../kupfer/plugin/windows.py:112
904 msgid "All windows on all workspaces"
905 msgstr "Tutte le finestre in tutti gli spazi di lavoro"
906
907 #: ../kupfer/plugin/windows.py:18
908 msgid "Activate"
909 msgstr "Attiva"
910
911 #: ../kupfer/plugin/windows.py:20
912 msgid "Unshade"
913 msgstr "Rimuovi ombra"
914
915 #: ../kupfer/plugin/windows.py:22
916 msgid "Shade"
917 msgstr "Ombra"
918
919 #: ../kupfer/plugin/windows.py:24
920 msgid "Unminimize"
921 msgstr "Deminimizza"
922
923 #: ../kupfer/plugin/windows.py:26
924 msgid "Minimize"
925 msgstr "Minimizza"
926
927 #: ../kupfer/plugin/windows.py:28
928 msgid "Unmaximize"
929 msgstr "Demassimizza"
930
931 #: ../kupfer/plugin/windows.py:30
932 msgid "Maximize"
933 msgstr "Massimizza"
934
935 #: ../kupfer/plugin/windows.py:32
936 msgid "Unmaximize Vertically"
937 msgstr "Demassimizza verticalmente"
938
939 #: ../kupfer/plugin/windows.py:35
940 msgid "Maximize Vertically"
941 msgstr "Massimizza verticalmente"
942
943 #: ../kupfer/plugin/windows.py:37
944 msgid "Close"
945 msgstr "Chiudi"
946
947 #. TRANS: Window on (Workspace name), window description
948 #: ../kupfer/plugin/windows.py:43
949 #, python-format
950 msgid "Window on %(wkspc)s"
951 msgstr "Finestra in %(wkspc)s"
952
953 #: ../kupfer/plugin/windows.py:58
954 msgid "Jump to this window's workspace and focus"
955 msgstr "Salta in questo spazio di lavoro della finestra e dà il focus"
956
957 #: ../kupfer/plugin/volumes.py:6 ../kupfer/plugin/volumes.py:71
958 msgid "Volumes and Disks"
959 msgstr "Volumi e dischi"
960
961 #: ../kupfer/plugin/volumes.py:8 ../kupfer/plugin/volumes.py:81
962 msgid "Mounted volumes and disks"
963 msgstr "Volumi e dischi montati"
964
965 #: ../kupfer/plugin/volumes.py:32
966 #, python-format
967 msgid "Volume mounted at %s"
968 msgstr "Volume montato su «%s»"
969
970 #: ../kupfer/plugin/volumes.py:40
971 msgid "Eject"
972 msgstr "Espelli"
973
974 #: ../kupfer/plugin/volumes.py:50
975 msgid "Unmount and eject this media"
976 msgstr "Smonta ed espelli questo supporto"
977
978 #: ../kupfer/plugin/volumes.py:56
979 msgid "Unmount"
980 msgstr "Smonta"
981
982 #: ../kupfer/plugin/volumes.py:66
983 msgid "Unmount this volume"
984 msgstr "Smonta questo volume"
253985
254986 #: ../kupfer/version.py:22
255987 msgid "translator-credits"
2921024 "della Licenza Pubblica Generale GNU. In caso contrario vedere <http://www."
2931025 "gnu.org/licenses/>.\n"
2941026
295 #: ../kupfer/plugin/applications.py:5
1027 #~ msgid "%(description)s (%(exec)s)"
1028 #~ msgstr "%(description)s (%(exec)s)"
1029
1030 #~ msgid "Open with %s (default)"
1031 #~ msgstr "Apri con %s (predefinito)"
1032
1033 #~ msgid "\"%s\""
1034 #~ msgstr "«%s»"
1035
2961036 #, fuzzy
297 msgid "Applications"
298 msgstr "Tutte le applicazioni"
299
300 #: ../kupfer/plugin/applications.py:7 ../kupfer/plugin/applications.py:38
301 msgid "All applications and preferences"
302 msgstr "Tutte le applicazioni e le preferenze"
303
304 #: ../kupfer/plugin/applications.py:19
305 msgid "All Applications"
306 msgstr "Tutte le applicazioni"
307
308 #: ../kupfer/plugin/applications.py:46
309 msgid "Open with..."
310 msgstr "Apri con..."
311
312 #: ../kupfer/plugin/commands.py:8
1037 #~ msgid "Shell"
1038 #~ msgstr "Ombra"
1039
3131040 #, fuzzy
314 msgid "Shell"
315 msgstr "Ombra"
316
317 #: ../kupfer/plugin/commands.py:11
318 msgid "Run commandline programs"
319 msgstr "Esegui programmi a riga di comando"
320
321 #: ../kupfer/plugin/commands.py:34
322 msgid "Shell commands"
323 msgstr "Comandi della shell"
324
325 #: ../kupfer/plugin/common.py:7
1041 #~ msgid "Core"
1042 #~ msgstr "Chiudi"
1043
1044 #~ msgid "Settings are not implemented yet; see 'kupfer --help'"
1045 #~ msgstr ""
1046 #~ "Le impostazioni non sono ancora implementate; vedere 'kupfer --help'"
1047
1048 #~ msgid "Trash"
1049 #~ msgstr "Cestino"
1050
1051 #~ msgid "Computer"
1052 #~ msgstr "Computer"
1053
1054 #~ msgid "Browse local disks and mounts"
1055 #~ msgstr "Esplora dischi locali e punti di mount"
1056
3261057 #, fuzzy
327 msgid "Core"
328 msgstr "Chiudi"
329
330 #: ../kupfer/plugin/common.py:9
331 msgid "Core actions and miscellaneous items"
332 msgstr ""
333
334 #: ../kupfer/plugin/common.py:27
335 msgid "Do"
336 msgstr "Esegui"
337
338 #: ../kupfer/plugin/common.py:32
339 msgid "Perform action"
340 msgstr "Esegui azione"
341
342 #: ../kupfer/plugin/common.py:38
343 msgid "Quit"
344 msgstr "Esci"
345
346 #: ../kupfer/plugin/common.py:43
347 msgid "Quit Kupfer"
348 msgstr "Esce da Kupfer"
349
350 #: ../kupfer/plugin/common.py:50 ../kupfer/plugin/common.py:53
351 #: ../kupfer/plugin/common.py:55
352 msgid "Log out..."
353 msgstr "Uscita..."
354
355 #: ../kupfer/plugin/common.py:57
356 msgid "Log out or change user"
357 msgstr "Esci o cambia utente"
358
359 #: ../kupfer/plugin/common.py:64 ../kupfer/plugin/common.py:67
360 #: ../kupfer/plugin/common.py:69
361 msgid "Shut down..."
362 msgstr "Arresto..."
363
364 #: ../kupfer/plugin/common.py:72
365 msgid "Shut down, restart or suspend computer"
366 msgstr "Arresta, riavvia o sospende il computer"
367
368 #: ../kupfer/plugin/common.py:79 ../kupfer/plugin/common.py:82
369 msgid "Lock screen"
370 msgstr "Blocca lo schermo"
371
372 #: ../kupfer/plugin/common.py:84
373 msgid "Enable screensaver and lock"
374 msgstr "Abilita il salva schermo e blocca"
375
376 #: ../kupfer/plugin/common.py:90
377 msgid "About Kupfer"
378 msgstr "Informazioni su Kupfer"
379
380 #: ../kupfer/plugin/common.py:95
381 msgid "Show information about Kupfer authors and license"
382 msgstr "Mostra informazioni sugli autori di Kupfer e sulla licenza"
383
384 #: ../kupfer/plugin/common.py:101
385 msgid "Kupfer Preferences"
386 msgstr "Preferenze di Kupfer"
387
388 #: ../kupfer/plugin/common.py:106
389 msgid "Settings are not implemented yet; see 'kupfer --help'"
390 msgstr "Le impostazioni non sono ancora implementate; vedere 'kupfer --help'"
391
392 #: ../kupfer/plugin/common.py:114 ../kupfer/plugin/trash.py:7
393 msgid "Trash"
394 msgstr "Cestino"
395
396 #: ../kupfer/plugin/common.py:125
397 msgid "Computer"
398 msgstr "Computer"
399
400 #: ../kupfer/plugin/common.py:129
401 msgid "Browse local disks and mounts"
402 msgstr "Esplora dischi locali e punti di mount"
403
404 #: ../kupfer/plugin/common.py:134
405 msgid "Special items"
406 msgstr "Voci speciali"
407
408 #: ../kupfer/plugin/common.py:150
409 msgid "Items and special actions"
410 msgstr "Voci e azioni speciali"
411
412 #: ../kupfer/plugin/documents.py:7
413 msgid "Documents"
414 msgstr ""
415
416 #: ../kupfer/plugin/documents.py:9
417 msgid "Recently used documents and nautilus places"
418 msgstr "Documenti utilizzati recentemente e posizioni di nautilus"
419
420 #: ../kupfer/plugin/documents.py:15
421 msgid "Recent items"
422 msgstr "Voci recenti"
423
424 #: ../kupfer/plugin/documents.py:42
425 msgid "Recently used documents"
426 msgstr "Documenti utilizzati recentemente"
427
428 #: ../kupfer/plugin/documents.py:51
429 msgid "Places"
430 msgstr "Posizioni"
431
432 #: ../kupfer/plugin/documents.py:83
433 msgid "Bookmarked locations in Nautilus"
434 msgstr "Posizioni nei segnalibri di Nautilus"
435
436 #: ../kupfer/plugin/epiphany.py:4
1058 #~ msgid "Epiphany"
1059 #~ msgstr "Epiphany"
1060
1061 #~ msgid "GNU Screen session"
1062 #~ msgstr "Sessione di GNU Screen"
1063
4371064 #, fuzzy
438 msgid "Epiphany"
439 msgstr "Epiphany"
440
441 #: ../kupfer/plugin/epiphany.py:6 ../kupfer/plugin/epiphany.py:21
442 msgid "Index of Epiphany bookmarks"
443 msgstr "Indice dei segnalibri di Epiphany"
444
445 #: ../kupfer/plugin/epiphany.py:12
446 msgid "Epiphany Bookmarks"
447 msgstr "Segnalibri di Epiphany"
448
449 #: ../kupfer/plugin/firefox.py:4
450 msgid "Firefox"
451 msgstr ""
452
453 #: ../kupfer/plugin/firefox.py:6 ../kupfer/plugin/firefox.py:20
454 msgid "Index of Firefox bookmarks"
455 msgstr "Indice dei segnalibri di Firefox"
456
457 #: ../kupfer/plugin/firefox.py:12
458 msgid "Firefox Bookmarks"
459 msgstr "Segnalibri di Firefox"
460
461 #: ../kupfer/plugin/google.py:8
462 #, fuzzy
463 msgid "Search the web"
464 msgstr "Cerca con Google"
465
466 #: ../kupfer/plugin/google.py:12
467 msgid "Send search queries to Google"
468 msgstr "Invia le interrogazioni di ricerca a Google"
469
470 #: ../kupfer/plugin/google.py:24
471 msgid "Search with Google"
472 msgstr "Cerca con Google"
473
474 #: ../kupfer/plugin/google.py:33
475 msgid "Search for this term with Google"
476 msgstr "Cerca questo termine con Google"
477
478 #: ../kupfer/plugin/screen.py:4
479 #, fuzzy
480 msgid "GNU Screen"
481 msgstr "GNU Screen"
482
483 #: ../kupfer/plugin/screen.py:6 ../kupfer/plugin/screen.py:62
484 msgid "Active GNU Screen sessions"
485 msgstr "Sessioni attive di GNU Screen"
486
487 #: ../kupfer/plugin/screen.py:41
488 msgid "Attached"
489 msgstr "Allegato"
490
491 #: ../kupfer/plugin/screen.py:42
492 msgid "Detached"
493 msgstr "Separato"
494
495 #: ../kupfer/plugin/screen.py:45
496 #, python-format
497 msgid "%(status)s session %(name)s (%(pid)s) created %(time)s"
498 msgstr "Sessione %(name)s %(status)s (%(pid)s) creata %(time)s"
499
500 #: ../kupfer/plugin/screen.py:54
501 msgid "Screen sessions"
502 msgstr "Sessioni di Screen"
503
504 #: ../kupfer/plugin/screen.py:70
505 msgid "Attach"
506 msgstr "Allega"
507
508 #: ../kupfer/plugin/screen.py:75
509 msgid "GNU Screen session"
510 msgstr "Sessione di GNU Screen"
511
512 #: ../kupfer/plugin/text.py:6
513 #, fuzzy
514 msgid "Free-text queries"
515 msgstr "Supporto base per testi d'interrogazione liberi"
516
517 #: ../kupfer/plugin/text.py:9
518 msgid "Basic support for free-text queries"
519 msgstr "Supporto base per testi d'interrogazione liberi"
520
521 #: ../kupfer/plugin/text.py:27
522 msgid "Filesystem text matches"
523 msgstr "Corrispondenze di testo nel file system"
524
525 #: ../kupfer/plugin/text.py:41
526 msgid "URL text matches"
527 msgstr "Corrispondenze di testo in URL"
528
529 #: ../kupfer/plugin/trackerlive.py:8 ../kupfer/plugin/trackerlive.py:16
530 #, fuzzy
531 msgid "Tracker live search"
532 msgstr "Ricerca dal vivo di Tracker"
533
534 #: ../kupfer/plugin/trackerlive.py:10
535 msgid "(Experimental) Tracker live search results"
536 msgstr ""
537
538 #: ../kupfer/plugin/trackerlive.py:62 ../kupfer/plugin/tracker.py:88
539 #, python-format
540 msgid "Results for query \"%s\""
541 msgstr "Risultati per l'interrogazione «%s»"
542
543 #: ../kupfer/plugin/tracker.py:10
544 #, fuzzy
545 msgid "Tracker"
546 msgstr "Tracker"
547
548 #: ../kupfer/plugin/tracker.py:13
549 msgid "Tracker desktop search integration"
550 msgstr "Integrazione con Tracker, ricerca scrivania"
551
552 #: ../kupfer/plugin/tracker.py:25
553 msgid "Search in Tracker"
554 msgstr "Cerca in Tracker"
555
556 #: ../kupfer/plugin/tracker.py:30
557 msgid "Open Tracker Search Tool and search for this term"
558 msgstr "Apre lo strumento di ricerca Tracker e cerca questo termine"
559
560 #: ../kupfer/plugin/tracker.py:36
561 msgid "Get Tracker results..."
562 msgstr "Ottenimento risultati di Tracker..."
563
564 #: ../kupfer/plugin/tracker.py:45
565 msgid "Show Tracker results for query"
566 msgstr "Mostra i risultati di Tracker per l'interrogazione"
567
568 #: ../kupfer/plugin/tracker.py:51
569 msgid "Tracker query"
570 msgstr "Interrogazione di Tracker"
571
572 #: ../kupfer/plugin/tracker.py:109
573 msgid "Tracker tags"
574 msgstr "Etichette di Tracker"
575
576 #: ../kupfer/plugin/tracker.py:115
577 msgid "Browse Tracker's tags"
578 msgstr "Sfoglia le etichette di Tracker"
579
580 #: ../kupfer/plugin/tracker.py:122
581 #, python-format
582 msgid "Tag %s"
583 msgstr "Etichetta %s"
584
585 #: ../kupfer/plugin/tracker.py:129
586 #, python-format
587 msgid "Objects tagged %s with Tracker"
588 msgstr "Oggetto «%s» etichettato con Tracker"
589
590 #: ../kupfer/plugin/trash.py:11
591 msgid "Move files to Trash"
592 msgstr "Sposta i file nel cestino"
593
594 #: ../kupfer/plugin/trash.py:23
595 msgid "Move to trash"
596 msgstr "Sposta nel cestino"
597
598 #: ../kupfer/plugin/trash.py:29
599 msgid "Move this file to trash"
600 msgstr "Sposta questo file nel cestino"
601
602 #: ../kupfer/plugin/windows.py:7 ../kupfer/plugin/windows.py:86
603 msgid "Windows"
604 msgstr "Finestre"
605
606 #: ../kupfer/plugin/windows.py:9 ../kupfer/plugin/windows.py:107
607 msgid "All windows on all workspaces"
608 msgstr "Tutte le finestre nelle aree di lavoro"
609
610 #: ../kupfer/plugin/windows.py:17
611 msgid "Activate"
612 msgstr "Attiva"
613
614 #: ../kupfer/plugin/windows.py:20
615 msgid "Unshade"
616 msgstr "Rimuovi ombra"
617
618 #: ../kupfer/plugin/windows.py:22
619 msgid "Shade"
620 msgstr "Ombra"
621
622 #: ../kupfer/plugin/windows.py:24
623 msgid "Unminimize"
624 msgstr "Deminimizza"
625
626 #: ../kupfer/plugin/windows.py:26
627 msgid "Minimize"
628 msgstr "Minimizza"
629
630 #: ../kupfer/plugin/windows.py:28
631 msgid "Unmaximize"
632 msgstr "Demassimizza"
633
634 #: ../kupfer/plugin/windows.py:30
635 msgid "Maximize"
636 msgstr "Massimizza"
637
638 #: ../kupfer/plugin/windows.py:32
639 msgid "Unmaximize vertically"
640 msgstr "Demassimizza verticalmente"
641
642 #: ../kupfer/plugin/windows.py:35
643 msgid "Maximize vertically"
644 msgstr "Massimizza verticalmente"
645
646 #: ../kupfer/plugin/windows.py:37
647 msgid "Close"
648 msgstr "Chiudi"
649
650 #: ../kupfer/plugin/windows.py:42
651 #, python-format
652 msgid "Window %(name)s on %(wkspc)s"
653 msgstr "Finestra %(name)s in %(wkspc)s"
654
655 #: ../kupfer/plugin/windows.py:57
656 msgid "Jump to this window's workspace and focus"
657 msgstr "Salta a quest'area di lavoro della finestra e dai il focus"
658
659 #: ../kupfer/plugin/volumes.py:6
660 msgid "Volumes"
661 msgstr ""
662
663 #: ../kupfer/plugin/volumes.py:8 ../kupfer/plugin/volumes.py:82
664 msgid "Mounted volumes and disks"
665 msgstr "Volumi e dischi montati"
666
667 #: ../kupfer/plugin/volumes.py:33
668 #, python-format
669 msgid "Volume mounted at %s"
670 msgstr "Volume montato su «%s»"
671
672 #: ../kupfer/plugin/volumes.py:41
673 msgid "Eject"
674 msgstr "Espelli"
675
676 #: ../kupfer/plugin/volumes.py:51
677 msgid "Unmount and eject this media"
678 msgstr "Smonta ed espelli questo media"
679
680 #: ../kupfer/plugin/volumes.py:57
681 msgid "Unmount"
682 msgstr "Smonta"
683
684 #: ../kupfer/plugin/volumes.py:67
685 msgid "Unmount this volume"
686 msgstr "Smonta questo volume"
687
688 #: ../kupfer/plugin/volumes.py:72
689 msgid "Volumes and disks"
690 msgstr "Volumi e dischi"
1065 #~ msgid "Tracker live search"
1066 #~ msgstr "Ricerca dal vivo di Tracker"
1067
1068 #~ msgid "Tracker query"
1069 #~ msgstr "Interrogazione di Tracker"
6911070
6921071 #~ msgid "Catalog of Catalogs"
6931072 #~ msgstr "Catalogo di cataloghi"
+792
-801
po/sv.po less more
77 msgstr ""
88 "Project-Id-Version: kupfer beta\n"
99 "Report-Msgid-Bugs-To: \n"
10 "POT-Creation-Date: 2009-08-16 06:15+0200\n"
10 "POT-Creation-Date: 2009-08-25 01:59+0200\n"
1111 "PO-Revision-Date: 2009-06-23 20:19+0200\n"
1212 "Last-Translator: Ulrik Sverdrup <ulrik.sverdrup@gmail.com>\n"
1313 "Language-Team: Swedish\n"
2424 msgid "Convenient command and access tool for applications and documents"
2525 msgstr "Flexibelt kommandoprogram för program och dokument"
2626
27 #: ../data/kupfer.desktop.in.in.h:3 ../kupfer/browser.py:1103
28 #: ../kupfer/browser.py:1134 ../kupfer/plugin/core.py:176
27 #: ../data/kupfer.desktop.in.in.h:3 ../kupfer/browser.py:1165
28 #: ../kupfer/browser.py:1196 ../kupfer/plugin/core.py:176
2929 #: ../kupfer/version.py:15
3030 msgid "Kupfer"
3131 msgstr "Kupfer"
6262 msgid "Start automatically on login"
6363 msgstr "Starta automatiskt vid login"
6464
65 #: ../kupfer/browser.py:630
65 #: ../kupfer/browser.py:641
6666 #, python-format
6767 msgid "%s is empty"
6868 msgstr "%s är tom"
6969
70 #: ../kupfer/browser.py:632
70 #: ../kupfer/browser.py:643
7171 #, python-format
7272 msgid "No matches in %s"
7373 msgstr "Inga träffar i %s"
7474
75 #: ../kupfer/browser.py:637
75 #: ../kupfer/browser.py:648
7676 msgid "Searching..."
7777 msgstr "Söker..."
7878
79 #: ../kupfer/browser.py:643
79 #: ../kupfer/browser.py:654
8080 #, python-format
8181 msgid "Searching %(source)s..."
8282 msgstr "Söker i %(source)s..."
8383
84 #: ../kupfer/main.py:38
84 #: ../kupfer/main.py:36
8585 msgid "Usage:"
8686 msgstr "Användning:"
8787
88 #: ../kupfer/main.py:41
88 #: ../kupfer/main.py:39
8989 msgid "do not present main interface on launch"
9090 msgstr "visa ej fönster vid start"
9191
92 #: ../kupfer/main.py:44
92 #: ../kupfer/main.py:42
9393 msgid "show usage help"
9494 msgstr "visa hjälpmeddelande"
9595
96 #: ../kupfer/main.py:45
96 #: ../kupfer/main.py:43
9797 msgid "show version information"
9898 msgstr "visa programversion"
9999
100 #: ../kupfer/main.py:46
100 #: ../kupfer/main.py:44
101101 msgid "enable debug info"
102102 msgstr "felsökningsläge"
103103
104 #: ../kupfer/main.py:51
104 #: ../kupfer/main.py:49
105105 msgid "To configure kupfer, edit:"
106106 msgstr "För att konfigurera kupfer, redigera:"
107107
108 #: ../kupfer/main.py:52
108 #: ../kupfer/main.py:50
109109 msgid "The default config for reference is at:"
110110 msgstr "Standardinställningarna är dokumenterade i:"
111111
112 #: ../kupfer/main.py:53
112 #: ../kupfer/main.py:51
113113 msgid "Available plugins:"
114114 msgstr "Tillgängliga insticksmoduler:"
115115
116 #: ../kupfer/main.py:118
116 #: ../kupfer/main.py:117
117117 #, python-format
118118 msgid ""
119119 "%(program)s: %(desc)s\n"
120120 "\t%(copyright)s\n"
121121 "\t%(website)s\n"
122 "\t"
123122 msgstr ""
124123 "%(program)s: %(desc)s\n"
125124 "\t%(copyright)s\n"
126125 "\t%(website)s\n"
127 "\t"
128
129 #: ../kupfer/objects.py:223
126
127 #: ../kupfer/objects.py:225
130128 msgid "No matches"
131129 msgstr "Inga träffar"
132130
133 #: ../kupfer/objects.py:534 ../kupfer/objects.py:592 ../kupfer/objects.py:607
131 #: ../kupfer/objects.py:560 ../kupfer/objects.py:621 ../kupfer/objects.py:636
134132 msgid "Open"
135133 msgstr "Öppna"
136134
137 #: ../kupfer/objects.py:534 ../kupfer/objects.py:543 ../kupfer/objects.py:546
138 #: ../kupfer/objects.py:555
135 #: ../kupfer/objects.py:560 ../kupfer/objects.py:569 ../kupfer/objects.py:572
136 #: ../kupfer/objects.py:584
139137 #, python-format
140138 msgid "Open with %s"
141139 msgstr "Öppna med %s"
142140
143 #: ../kupfer/objects.py:573
141 #: ../kupfer/objects.py:602
144142 msgid "Open URL"
145143 msgstr "Öppna URL"
146144
147 #: ../kupfer/objects.py:584
145 #: ../kupfer/objects.py:613
148146 msgid "Open URL with default viewer"
149147 msgstr "Öppna URL med standardprogram"
150148
151 #: ../kupfer/objects.py:599
149 #: ../kupfer/objects.py:628
152150 msgid "Open with default viewer"
153151 msgstr "Öppna med standardprogram"
154152
155 #: ../kupfer/objects.py:610
153 #: ../kupfer/objects.py:639
156154 msgid "Open folder"
157155 msgstr "Öppna mapp"
158156
159 #: ../kupfer/objects.py:616
157 #: ../kupfer/objects.py:645
160158 msgid "Reveal"
161159 msgstr "Visa"
162160
163 #: ../kupfer/objects.py:625
161 #: ../kupfer/objects.py:654
164162 msgid "Open parent folder"
165163 msgstr "Öppna föräldermapp i filhanteraren"
166164
167 #: ../kupfer/objects.py:631
165 #: ../kupfer/objects.py:660
168166 msgid "Open Terminal Here"
169167 msgstr "Öppna i terminalfönster"
170168
171 #: ../kupfer/objects.py:640
169 #: ../kupfer/objects.py:669
172170 msgid "Open this location in a terminal"
173171 msgstr "Öppna platsen i terminalfönster"
174172
175 #: ../kupfer/objects.py:653
173 #: ../kupfer/objects.py:682
176174 msgid "Launch"
177175 msgstr "Starta"
178176
179 #: ../kupfer/objects.py:663
177 #: ../kupfer/objects.py:692
180178 msgid "Launch application"
181179 msgstr "Starta program"
182180
183 #: ../kupfer/objects.py:670 ../kupfer/plugin/windows.py:48
181 #: ../kupfer/objects.py:699 ../kupfer/plugin/windows.py:49
184182 msgid "Go To"
185183 msgstr "Gå till"
186184
187 #: ../kupfer/objects.py:674
185 #: ../kupfer/objects.py:703
188186 msgid "Show application window"
189187 msgstr "Visa programfönster"
190188
191 #: ../kupfer/objects.py:683
189 #: ../kupfer/objects.py:712
192190 msgid "Launch Again"
193191 msgstr "Starta igen"
194192
195 #: ../kupfer/objects.py:687
193 #: ../kupfer/objects.py:716
196194 msgid "Launch another instance of this application"
197195 msgstr "Starta programmet igen"
198196
199 #: ../kupfer/objects.py:694
197 #: ../kupfer/objects.py:723
200198 msgid "Run in Terminal"
201199 msgstr "Kör i terminalfönster"
202200
203 #: ../kupfer/objects.py:694
201 #: ../kupfer/objects.py:723
204202 msgid "Run"
205203 msgstr "Kör"
206204
207 #: ../kupfer/objects.py:705
205 #: ../kupfer/objects.py:737
208206 msgid "Run this program in a Terminal"
209207 msgstr "Kör programmet i terminalfönster"
210208
211 #: ../kupfer/objects.py:707
209 #: ../kupfer/objects.py:739
212210 msgid "Run this program"
213211 msgstr "Kör programmet"
214212
215 #: ../kupfer/objects.py:715
213 #: ../kupfer/objects.py:747
216214 msgid "No action"
217215 msgstr "Inget kommando"
218216
219217 #. TRANS: Multiple artist description "Artist1 et. al. "
220 #: ../kupfer/objects.py:830 ../kupfer/plugin/rhythmbox.py:214
218 #: ../kupfer/objects.py:863 ../kupfer/plugin/rhythmbox.py:220
221219 #, python-format
222220 msgid "%s et. al."
223221 msgstr "%s et. al."
224222
225 #: ../kupfer/objects.py:859
223 #: ../kupfer/objects.py:893
226224 #, python-format
227225 msgid "Recursive source of %(dir)s, (%(levels)d levels)"
228226 msgstr "Rekursiv källa %(dir)s, (%(levels)d nivåer)"
229227
230 #: ../kupfer/objects.py:926
228 #: ../kupfer/objects.py:961
231229 #, python-format
232230 msgid "Directory source %s"
233231 msgstr "Katalogkälla %s"
234232
235 #: ../kupfer/objects.py:942
233 #: ../kupfer/objects.py:977
236234 msgid "Catalog Index"
237235 msgstr "Katalogindex"
238236
239 #: ../kupfer/objects.py:957
237 #: ../kupfer/objects.py:992
240238 msgid "An index of all available sources"
241239 msgstr "Index över alla tilgängliga kataloger"
242240
243 #: ../kupfer/objects.py:968
241 #: ../kupfer/objects.py:1003
244242 msgid "Catalog"
245243 msgstr "Katalog"
246244
247 #: ../kupfer/objects.py:987
245 #: ../kupfer/objects.py:1022
248246 msgid "Root catalog"
249247 msgstr "Rotkatalog"
250248
251 #: ../kupfer/objects.py:1064
249 #: ../kupfer/objects.py:1099
252250 msgid "Do"
253251 msgstr "Utför"
254252
255 #: ../kupfer/objects.py:1069
253 #: ../kupfer/objects.py:1104
256254 msgid "Perform action"
257255 msgstr "Utför kommando"
258256
259257 #. TRANS: This is description for a TextLeaf, a free-text search
260258 #. TRANS: The plural parameter is the number of lines %(num)d
261 #: ../kupfer/objects.py:1094
259 #: ../kupfer/objects.py:1130
262260 #, python-format
263261 msgid "\"%(text)s\""
264262 msgid_plural "(%(num)d lines) \"%(text)s\""
265263 msgstr[0] "\"%(text)s\""
266264 msgstr[1] "(%(num)d lines) \"%(text)s\""
267265
268 #: ../kupfer/objects.py:1106 ../kupfer/plugin/text.py:18
266 #: ../kupfer/objects.py:1142 ../kupfer/plugin/text.py:18
269267 msgid "Text Matches"
270268 msgstr "Fritextträffar"
269
270 #: ../kupfer/plugin/abiword.py:12
271 msgid "Abiword"
272 msgstr "Abiword"
273
274 #: ../kupfer/plugin/abiword.py:15 ../kupfer/plugin/abiword.py:103
275 msgid "Recently used documents in Abiword"
276 msgstr "Senaste dokument i Abiword"
277
278 #: ../kupfer/plugin/abiword.py:56
279 msgid "Abiword Recent Items"
280 msgstr "Abiwords senaste dokument"
281
282 #: ../kupfer/plugin/applications.py:8 ../kupfer/plugin/applications.py:36
283 msgid "Applications"
284 msgstr "Program"
285
286 #: ../kupfer/plugin/applications.py:14 ../kupfer/plugin/applications.py:53
287 msgid "All applications and preferences"
288 msgstr "Alla program och inställningspaneler"
289
290 #: ../kupfer/plugin/applications.py:21
291 msgid "Applications for Desktop Environment"
292 msgstr "Program för skrivbordsmiljö"
293
294 #: ../kupfer/plugin/applications.py:62
295 msgid "Open With..."
296 msgstr "Öppna med..."
297
298 #: ../kupfer/plugin/applications.py:73
299 msgid "Open with any application"
300 msgstr "Öppna med godtyckligt program"
301
302 #: ../kupfer/plugin/applications.py:77
303 msgid "Set Default Application..."
304 msgstr "Välj standardprogram..."
305
306 #: ../kupfer/plugin/applications.py:92
307 msgid "Set default application to open this file type"
308 msgstr "Välj förvalsprogram att öppna filer av den här typen med."
309
310 #: ../kupfer/plugin/clipboard.py:8 ../kupfer/plugin/clipboard.py:42
311 msgid "Clipboards"
312 msgstr "Urklipp"
313
314 #: ../kupfer/plugin/clipboard.py:11 ../kupfer/plugin/clipboard.py:68
315 msgid "Recent clipboards"
316 msgstr "Senaste urklipp"
317
318 #: ../kupfer/plugin/clipboard.py:18
319 msgid "Number of recent clipboards"
320 msgstr "Antal senaste urklipp"
321
322 #: ../kupfer/plugin/clipboard.py:34
323 #, python-format
324 msgid "Clipboard \"%(desc)s\""
325 msgid_plural "Clipboard with %(num)d lines \"%(desc)s\""
326 msgstr[0] "Urklipp \"%(desc)s\""
327 msgstr[1] "Urklipp med %(num)d rader \"%(desc)s\""
328
329 #: ../kupfer/plugin/clipboard.py:78
330 msgid "Copy"
331 msgstr "Kopiera"
332
333 #: ../kupfer/plugin/clipboard.py:85
334 msgid "Copy to clipboard"
335 msgstr "Kopiera till urklipp"
336
337 #: ../kupfer/plugin/commands.py:10 ../kupfer/plugin/commands.py:36
338 msgid "Shell Commands"
339 msgstr "Skalkommandon"
340
341 #: ../kupfer/plugin/commands.py:13 ../kupfer/plugin/commands.py:55
342 msgid "Run commandline programs"
343 msgstr "Kör kommandoradsprogram"
344
345 #: ../kupfer/plugin/common.py:9
346 msgid "Common"
347 msgstr "Bas"
348
349 #: ../kupfer/plugin/common.py:11
350 msgid "Special items and actions"
351 msgstr "Speicella objekt och kommandon"
352
353 #: ../kupfer/plugin/common.py:29
354 msgid "Log Out..."
355 msgstr "Logga ut..."
356
357 #: ../kupfer/plugin/common.py:35
358 msgid "Log out or change user"
359 msgstr "Logga ut eller byt användare"
360
361 #: ../kupfer/plugin/common.py:42
362 msgid "Shut Down..."
363 msgstr "Stäng av..."
364
365 #: ../kupfer/plugin/common.py:49
366 msgid "Shut down, restart or suspend computer"
367 msgstr "Stäng av, starta om eller sätt datorn i vänteläge"
368
369 #: ../kupfer/plugin/common.py:56
370 msgid "Lock Screen"
371 msgstr "Lås skärmen"
372
373 #: ../kupfer/plugin/common.py:62
374 msgid "Enable screensaver and lock"
375 msgstr "Aktivera skärmsläckaren och lås skärmen"
376
377 #: ../kupfer/plugin/common.py:94
378 msgid "Restore"
379 msgstr "Återskapa"
380
381 #: ../kupfer/plugin/common.py:109
382 msgid "Move file back to original location"
383 msgstr "Flytta tillbaka till ursprunglig plats"
384
385 #: ../kupfer/plugin/common.py:174
386 msgid "Trash is empty"
387 msgstr "Papperskorgen är tom"
388
389 #. proper translation of plural
390 #: ../kupfer/plugin/common.py:176
391 #, python-format
392 msgid "Trash contains one file"
393 msgid_plural "Trash contains %(num)s files"
394 msgstr[0] "Papperskorgen innehåller ett objekt"
395 msgstr[1] "Papperskorgen innehåller %(num)s objekt"
396
397 #: ../kupfer/plugin/common.py:180
398 msgid "Special Items"
399 msgstr "Speciella objekt"
400
401 #: ../kupfer/plugin/common.py:195
402 msgid "Items and special actions"
403 msgstr "Speciella objekt och övriga kommandon"
404
405 #: ../kupfer/plugin/core.py:25
406 msgid "Search Content..."
407 msgstr "Sök i..."
408
409 #: ../kupfer/plugin/core.py:40
410 msgid "Search inside this catalog"
411 msgstr "Sök bland objekt i katalogen"
412
413 #: ../kupfer/plugin/core.py:48
414 msgid "Rescan"
415 msgstr "Uppdatera"
416
417 #: ../kupfer/plugin/core.py:57
418 msgid "Force reindex of this source"
419 msgstr "Tvinga omläsning av källan"
420
421 #: ../kupfer/plugin/core.py:141
422 msgid "Quit"
423 msgstr "Avsluta"
424
425 #: ../kupfer/plugin/core.py:146
426 msgid "Quit Kupfer"
427 msgstr "Avsluta Kupfer"
428
429 #: ../kupfer/plugin/core.py:152
430 msgid "About Kupfer"
431 msgstr "Om Kupfer"
432
433 #: ../kupfer/plugin/core.py:157
434 msgid "Show information about Kupfer authors and license"
435 msgstr "Visa information om Kupfers upphovsmän och licens"
436
437 #: ../kupfer/plugin/core.py:170
438 msgid "Show preferences window for Kupfer"
439 msgstr "Visa Kupfers inställningsfönster"
440
441 #: ../kupfer/plugin/core.py:187
442 msgid "Kupfer items and actions"
443 msgstr "Kupfer-objekt och kommandon"
444
445 #: ../kupfer/plugin/devhelp.py:4
446 msgid "Devhelp"
447 msgstr "Devhelp"
448
449 #: ../kupfer/plugin/devhelp.py:6 ../kupfer/plugin/devhelp.py:12
450 msgid "Search in Devhelp"
451 msgstr "Sök i Devhelp"
452
453 #: ../kupfer/plugin/dictionary.py:4
454 msgid "Dictionary"
455 msgstr "Ordbok"
456
457 #: ../kupfer/plugin/dictionary.py:6 ../kupfer/plugin/dictionary.py:23
458 msgid "Look up word in dictionary"
459 msgstr "Slå upp ord i ordboken"
460
461 #: ../kupfer/plugin/dictionary.py:12 ../kupfer/plugin/dictionary.py:16
462 msgid "Look Up"
463 msgstr "Slå upp"
464
465 #: ../kupfer/plugin/documents.py:11
466 msgid "Documents"
467 msgstr "Dokument"
468
469 #: ../kupfer/plugin/documents.py:14
470 msgid "Recently used documents and nautilus places"
471 msgstr "Senaste dokument och sparade platser"
472
473 #: ../kupfer/plugin/documents.py:21
474 msgid "Max recent document days"
475 msgstr "Maximal ålder för senaste dokument"
476
477 #: ../kupfer/plugin/documents.py:31
478 msgid "Recent Items"
479 msgstr "Senaste dokument"
480
481 #: ../kupfer/plugin/documents.py:77
482 msgid "Recently used documents"
483 msgstr "Senast använda dokument"
484
485 #: ../kupfer/plugin/documents.py:87
486 #, python-format
487 msgid "%s Documents"
488 msgstr "%s-dokument"
489
490 #: ../kupfer/plugin/documents.py:112
491 #, python-format
492 msgid "Recently used documents for %s"
493 msgstr "Senaste dokument för %s"
494
495 #: ../kupfer/plugin/documents.py:131
496 msgid "Places"
497 msgstr "Platser"
498
499 #: ../kupfer/plugin/documents.py:163
500 msgid "Bookmarked locations in Nautilus"
501 msgstr "Sparade platser i Nautilus"
502
503 #: ../kupfer/plugin/epiphany.py:4 ../kupfer/plugin/epiphany.py:14
504 msgid "Epiphany Bookmarks"
505 msgstr "Epiphany-bokmärken"
506
507 #: ../kupfer/plugin/epiphany.py:7 ../kupfer/plugin/epiphany.py:23
508 msgid "Index of Epiphany bookmarks"
509 msgstr "Index över Epiphany-bokmärken"
510
511 #: ../kupfer/plugin/favorites.py:8 ../kupfer/plugin/favorites.py:27
512 msgid "Favorites"
513 msgstr "Favoriter"
514
515 #: ../kupfer/plugin/favorites.py:11
516 msgid "(Simple) favorites plugin"
517 msgstr "(Enkel) modul för favoritobjekt"
518
519 #: ../kupfer/plugin/favorites.py:54
520 msgid "Shelf of \"Favorite\" items"
521 msgstr "Plats för favoritobjekt"
522
523 #: ../kupfer/plugin/favorites.py:66
524 msgid "Add to Favorites"
525 msgstr "Lägg till favorit"
526
527 #: ../kupfer/plugin/favorites.py:76
528 msgid "Add item to favorites shelf"
529 msgstr "Lägg till objekt till favorithyllan"
530
531 #: ../kupfer/plugin/favorites.py:82
532 msgid "Remove from Favorites"
533 msgstr "Ta bort favorit"
534
535 #: ../kupfer/plugin/favorites.py:90
536 msgid "Remove item from favorites shelf"
537 msgstr "Ta bort objekt från favorithyllan"
538
539 #: ../kupfer/plugin/fileactions.py:11
540 msgid "File Actions"
541 msgstr "Filkommandon"
542
543 #: ../kupfer/plugin/fileactions.py:22
544 msgid "More file actions"
545 msgstr "Fler filkommandon"
546
547 #: ../kupfer/plugin/fileactions.py:29
548 msgid "Compressed archive type for 'Create Archive In'"
549 msgstr "Arkivtyp för 'Skapa arkiv i'"
550
551 #: ../kupfer/plugin/fileactions.py:46
552 msgid "Move to Trash"
553 msgstr "Flytta till papperskorgen"
554
555 #: ../kupfer/plugin/fileactions.py:54
556 msgid "Move this file to trash"
557 msgstr "Flytta filen till papperskorgen"
558
559 #: ../kupfer/plugin/fileactions.py:82
560 msgid "Move To..."
561 msgstr "Flytta till..."
562
563 #: ../kupfer/plugin/fileactions.py:105
564 msgid "Move file to new location"
565 msgstr "Flytta till ny plats"
566
567 #: ../kupfer/plugin/fileactions.py:121
568 msgid "Copy To..."
569 msgstr "Kopiera till..."
570
571 #: ../kupfer/plugin/fileactions.py:139
572 msgid "Copy file to a chosen location"
573 msgstr "Kopiera filen till en vald plats"
574
575 #: ../kupfer/plugin/fileactions.py:143
576 msgid "Extract Here"
577 msgstr "Packa upp här"
578
579 #: ../kupfer/plugin/fileactions.py:157
580 msgid "Extract compressed archive"
581 msgstr "Packa upp komprimerad fil"
582
583 #: ../kupfer/plugin/fileactions.py:161
584 msgid "Create Archive"
585 msgstr "Skapa arkiv"
586
587 #: ../kupfer/plugin/fileactions.py:171 ../kupfer/plugin/fileactions.py:197
588 msgid "Create a compressed archive from folder"
589 msgstr "Skapa komprimerat arkiv av mappen"
590
591 #: ../kupfer/plugin/fileactions.py:175
592 msgid "Create Archive In..."
593 msgstr "Skapa arkiv i..."
594
595 #: ../kupfer/plugin/firefox.py:4 ../kupfer/plugin/firefox.py:14
596 msgid "Firefox Bookmarks"
597 msgstr "Firefox-bokmärken"
598
599 #: ../kupfer/plugin/firefox.py:7 ../kupfer/plugin/firefox.py:22
600 msgid "Index of Firefox bookmarks"
601 msgstr "Index över Firefox-bokmärken"
602
603 #: ../kupfer/plugin/google.py:11
604 msgid "Search the Web"
605 msgstr "Webbsökning"
606
607 #: ../kupfer/plugin/google.py:18 ../kupfer/plugin/google.py:89
608 #: ../kupfer/plugin/google.py:116
609 msgid "Search the web with OpenSearch search engines"
610 msgstr "Sök webben med OpenSearch-sökmotorer"
611
612 #: ../kupfer/plugin/google.py:73
613 msgid "Search With..."
614 msgstr "Sök med..."
615
616 #: ../kupfer/plugin/google.py:99
617 msgid "Search For..."
618 msgstr "Sök efter..."
619
620 #: ../kupfer/plugin/google.py:137
621 msgid "Search Engines"
622 msgstr "Sökmotorer"
623
624 #: ../kupfer/plugin/locate.py:8 ../kupfer/plugin/locate.py:19
625 msgid "Locate Files"
626 msgstr "Locate"
627
628 #: ../kupfer/plugin/locate.py:12 ../kupfer/plugin/locate.py:29
629 msgid "Search filesystem using locate"
630 msgstr "Sök filsystemet med 'locate'"
631
632 #: ../kupfer/plugin/locate.py:37 ../kupfer/plugin/tracker.py:55
633 #: ../kupfer/plugin/tracker.py:92
634 #, python-format
635 msgid "Results for \"%s\""
636 msgstr "Resultat för \"%s\""
637
638 #: ../kupfer/plugin/rhythmbox.py:12 ../kupfer/plugin/rhythmbox.py:350
639 msgid "Rhythmbox"
640 msgstr "Rhythmbox"
641
642 #: ../kupfer/plugin/rhythmbox.py:17 ../kupfer/plugin/rhythmbox.py:385
643 msgid "Play and enqueue tracks and browse the music library"
644 msgstr "Spela spår och sök i musikbiblioteket"
645
646 #: ../kupfer/plugin/rhythmbox.py:24
647 msgid "Include artists in top level"
648 msgstr "Inkludera artister i toppnivån"
649
650 #: ../kupfer/plugin/rhythmbox.py:30
651 msgid "Include albums in top level"
652 msgstr "Inkludera album i toppnivån"
653
654 #: ../kupfer/plugin/rhythmbox.py:36
655 msgid "Include songs in top level"
656 msgstr "Inkludera låtar i toppnivån"
657
658 #: ../kupfer/plugin/rhythmbox.py:65 ../kupfer/plugin/rhythmbox.py:118
659 msgid "Play"
660 msgstr "Spela upp"
661
662 #: ../kupfer/plugin/rhythmbox.py:69
663 msgid "Resume playback in Rhythmbox"
664 msgstr "Starta uppspelning i Rhythmbox"
665
666 #: ../kupfer/plugin/rhythmbox.py:75
667 msgid "Pause"
668 msgstr "Paus"
669
670 #: ../kupfer/plugin/rhythmbox.py:79
671 msgid "Pause playback in Rhythmbox"
672 msgstr "Pausa uppspelning i Rhythmbox"
673
674 #: ../kupfer/plugin/rhythmbox.py:85
675 msgid "Next"
676 msgstr "Nästa"
677
678 #: ../kupfer/plugin/rhythmbox.py:89
679 msgid "Jump to next track in Rhythmbox"
680 msgstr "Hoppa till nästa spår i Rhythmbox"
681
682 #: ../kupfer/plugin/rhythmbox.py:95
683 msgid "Previous"
684 msgstr "Föregående"
685
686 #: ../kupfer/plugin/rhythmbox.py:99
687 msgid "Jump to previous track in Rhythmbox"
688 msgstr "Hoppa till föregående spår i Rhythmbox"
689
690 #: ../kupfer/plugin/rhythmbox.py:105
691 msgid "Show Playing"
692 msgstr "Vilken låt?"
693
694 #: ../kupfer/plugin/rhythmbox.py:109
695 msgid "Tell which song is currently playing"
696 msgstr "Visa vilken låt som spelas just nu"
697
698 #: ../kupfer/plugin/rhythmbox.py:131
699 msgid "Play tracks in Rhythmbox"
700 msgstr "Spela upp spår i Rhythmbox"
701
702 #: ../kupfer/plugin/rhythmbox.py:137
703 msgid "Enqueue"
704 msgstr "Köa"
705
706 #: ../kupfer/plugin/rhythmbox.py:148
707 msgid "Add tracks to the play queue"
708 msgstr "Lägg till spår i spelkön"
709
710 #. TRANS: Song description
711 #: ../kupfer/plugin/rhythmbox.py:170
712 #, python-format
713 msgid "by %(artist)s from %(album)s"
714 msgstr "av %(artist)s från %(album)s"
715
716 #. TRANS: Album description "by Artist"
717 #: ../kupfer/plugin/rhythmbox.py:223
718 #, python-format
719 msgid "by %s"
720 msgstr "av %s"
721
722 #. TRANS: Artist songs collection description
723 #: ../kupfer/plugin/rhythmbox.py:262
724 #, python-format
725 msgid "Tracks by %s"
726 msgstr "Spår av %s"
727
728 #: ../kupfer/plugin/rhythmbox.py:272
729 msgid "Albums"
730 msgstr "Album"
731
732 #: ../kupfer/plugin/rhythmbox.py:282
733 msgid "Music albums in Rhythmbox Library"
734 msgstr "Album i Rhythmboxs bibliotek"
735
736 #: ../kupfer/plugin/rhythmbox.py:293
737 msgid "Artists"
738 msgstr "Artister"
739
740 #: ../kupfer/plugin/rhythmbox.py:303
741 msgid "Music artists in Rhythmbox Library"
742 msgstr "Artister i Rhythmboxs bibliotek"
743
744 #: ../kupfer/plugin/rhythmbox.py:330
745 msgid "Songs"
746 msgstr "Låtar"
747
748 #: ../kupfer/plugin/rhythmbox.py:340
749 msgid "Songs in Rhythmbox library"
750 msgstr "Låtar i Rhythmboxs bibliotek"
751
752 #: ../kupfer/plugin/screen.py:7 ../kupfer/plugin/screen.py:109
753 msgid "GNU Screen"
754 msgstr "GNU Screen"
755
756 #: ../kupfer/plugin/screen.py:9 ../kupfer/plugin/screen.py:94
757 msgid "Active GNU Screen sessions"
758 msgstr "Aktiva GNU Screen-sessioner"
759
760 #: ../kupfer/plugin/screen.py:49
761 msgid "Attached"
762 msgstr "Ansluten"
763
764 #: ../kupfer/plugin/screen.py:50
765 msgid "Detached"
766 msgstr "Frånkopplad"
767
768 #: ../kupfer/plugin/screen.py:53
769 #, python-format
770 msgid "%(status)s session (%(pid)s) created %(time)s"
771 msgstr "%(status)s session %(pid)s) skapad %(time)s"
772
773 #: ../kupfer/plugin/screen.py:62
774 msgid "Screen Sessions"
775 msgstr "Screen-sessioner"
776
777 #: ../kupfer/plugin/screen.py:104
778 msgid "Attach"
779 msgstr "Anslut till"
780
781 #. return a constant rank key despite the changing name
782 #: ../kupfer/plugin/selection.py:6 ../kupfer/plugin/selection.py:24
783 #: ../kupfer/plugin/selection.py:33
784 msgid "Selected Text"
785 msgstr "Markering"
786
787 #: ../kupfer/plugin/selection.py:8 ../kupfer/plugin/selection.py:50
788 msgid "Provides current selection"
789 msgstr "Tillhandahåller aktuell markering"
790
791 #: ../kupfer/plugin/selection.py:20
792 #, python-format
793 msgid "Selected Text \"%s\""
794 msgstr "Markering \"%s\""
795
796 #: ../kupfer/plugins.py:51
797 msgid "(no description)"
798 msgstr "(ingen beskrivning)"
799
800 #: ../kupfer/plugins.py:70
801 #, python-format
802 msgid " %(name)-20s %(version)-4s %(description)s"
803 msgstr " %(name)-20s %(version)-4s %(description)s"
804
805 #: ../kupfer/plugin/text.py:8
806 msgid "Free-text Queries"
807 msgstr "Fritextsökningar"
808
809 #: ../kupfer/plugin/text.py:11
810 msgid "Basic support for free-text queries"
811 msgstr "Grundstöd för fritextsökningar"
812
813 #: ../kupfer/plugin/text.py:31
814 msgid "Filesystem Text Matches"
815 msgstr "Fritextträffar i filsystemet"
816
817 #: ../kupfer/plugin/text.py:49
818 msgid "URL Text Matches"
819 msgstr "URL-täffar i fritext"
820
821 #: ../kupfer/plugin/tracker.py:9
822 msgid "Tracker"
823 msgstr "Tracker"
824
825 #: ../kupfer/plugin/tracker.py:18
826 msgid "Tracker desktop search integration"
827 msgstr "Integration med sökprogrammet Tracker"
828
829 #: ../kupfer/plugin/tracker.py:24
830 msgid "Search in Tracker"
831 msgstr "Sök i Tracker"
832
833 #: ../kupfer/plugin/tracker.py:29
834 msgid "Open Tracker Search Tool and search for this term"
835 msgstr "Sök efter denna term i Sökverktyget Tracker"
836
837 #: ../kupfer/plugin/tracker.py:38
838 msgid "Get Tracker Results..."
839 msgstr "Hämta träffar från Tracker..."
840
841 #: ../kupfer/plugin/tracker.py:47
842 msgid "Show Tracker results for query"
843 msgstr "Visa träffar för sökning med Tracker"
844
845 #: ../kupfer/plugin/tracker.py:123 ../kupfer/plugin/tracker.py:129
846 msgid "Tracker tags"
847 msgstr "Tracker-taggar"
848
849 #: ../kupfer/plugin/tracker.py:138
850 msgid "Tracker Tags"
851 msgstr "Tracker-taggar"
852
853 #: ../kupfer/plugin/tracker.py:144
854 msgid "Browse Tracker's tags"
855 msgstr "Bläddra i Trackers taggar"
856
857 #: ../kupfer/plugin/tracker.py:155 ../kupfer/plugin/tracker.py:162
858 #, python-format
859 msgid "Tag %s"
860 msgstr "Taggen %s"
861
862 #: ../kupfer/plugin/tracker.py:169
863 #, python-format
864 msgid "Objects tagged %s with Tracker"
865 msgstr "Objekt taggade %s med Tracker"
866
867 #: ../kupfer/plugin/tracker.py:181
868 msgid "Add Tag..."
869 msgstr "Lägg till tagg..."
870
871 #: ../kupfer/plugin/tracker.py:207
872 msgid "Add tracker tag to file"
873 msgstr "Lägg till tracker-tagg till filen"
874
875 #: ../kupfer/plugin/tracker.py:213
876 msgid "Remove Tag..."
877 msgstr "Ta bort tagg..."
878
879 #: ../kupfer/plugin/tracker.py:232
880 msgid "Remove tracker tag from file"
881 msgstr "Ta bort tracker-tagg från filen"
882
883 #: ../kupfer/plugin/wikipedia.py:10
884 msgid "Wikipedia"
885 msgstr "Wikipedia"
886
887 #: ../kupfer/plugin/wikipedia.py:13 ../kupfer/plugin/wikipedia.py:30
888 msgid "Search in Wikipedia"
889 msgstr "Sök i Wikipedia"
890
891 #: ../kupfer/plugin/wikipedia.py:20
892 msgid "Wikipedia language"
893 msgstr "Wikipedia-språk"
894
895 #. TRANS: Default wikipedia language code
896 #: ../kupfer/plugin/wikipedia.py:23
897 msgid "en"
898 msgstr "sv"
899
900 #: ../kupfer/plugin/wikipedia.py:43
901 #, python-format
902 msgid "Search for this term in %s.wikipedia.org"
903 msgstr "Sök efter denna termen i %s.wikipedia.org"
904
905 #: ../kupfer/plugin/windows.py:7 ../kupfer/plugin/windows.py:91
906 msgid "Window List"
907 msgstr "Fönsterlista"
908
909 #: ../kupfer/plugin/windows.py:9 ../kupfer/plugin/windows.py:112
910 msgid "All windows on all workspaces"
911 msgstr "Alla fönster på alla arbetsytor"
912
913 #: ../kupfer/plugin/windows.py:18
914 msgid "Activate"
915 msgstr "Aktivera"
916
917 #: ../kupfer/plugin/windows.py:20
918 msgid "Unshade"
919 msgstr "Rulla ner"
920
921 #: ../kupfer/plugin/windows.py:22
922 msgid "Shade"
923 msgstr "Rulla upp"
924
925 #: ../kupfer/plugin/windows.py:24
926 msgid "Unminimize"
927 msgstr "Avminimera"
928
929 #: ../kupfer/plugin/windows.py:26
930 msgid "Minimize"
931 msgstr "Minimera"
932
933 #: ../kupfer/plugin/windows.py:28
934 msgid "Unmaximize"
935 msgstr "Avmaximera"
936
937 #: ../kupfer/plugin/windows.py:30
938 msgid "Maximize"
939 msgstr "Maximera"
940
941 #: ../kupfer/plugin/windows.py:32
942 msgid "Unmaximize Vertically"
943 msgstr "Avmaximera vertikalt"
944
945 #: ../kupfer/plugin/windows.py:35
946 msgid "Maximize Vertically"
947 msgstr "Maximera vertikalt"
948
949 #: ../kupfer/plugin/windows.py:37
950 msgid "Close"
951 msgstr "Stäng"
952
953 #. TRANS: Window on (Workspace name), window description
954 #: ../kupfer/plugin/windows.py:43
955 #, python-format
956 msgid "Window on %(wkspc)s"
957 msgstr "Fönster på %(wkspc)s"
958
959 #: ../kupfer/plugin/windows.py:58
960 msgid "Jump to this window's workspace and focus"
961 msgstr "Gå till fönstrets arbetsyta och aktivera"
962
963 #: ../kupfer/plugin/urlactions.py:7 ../kupfer/plugin/urlactions.py:14
964 msgid "URL Actions"
965 msgstr "URL-kommandon"
966
967 #: ../kupfer/plugin/urlactions.py:51
968 msgid "Download and Open"
969 msgstr "Ladda ner och öppna"
970
971 #: ../kupfer/plugin/urlactions.py:70
972 msgid "Download To..."
973 msgstr "Ladda ner till..."
974
975 #: ../kupfer/plugin/urlactions.py:87
976 msgid "Download URL to a chosen location"
977 msgstr "Ladda ner till en vald plats"
978
979 #: ../kupfer/plugin/volumes.py:6 ../kupfer/plugin/volumes.py:71
980 msgid "Volumes and Disks"
981 msgstr "Volymer"
982
983 #: ../kupfer/plugin/volumes.py:8 ../kupfer/plugin/volumes.py:81
984 msgid "Mounted volumes and disks"
985 msgstr "Monterade volymer och löstagbara enheter"
986
987 #: ../kupfer/plugin/volumes.py:32
988 #, python-format
989 msgid "Volume mounted at %s"
990 msgstr "Volym monterad vid %s"
991
992 #: ../kupfer/plugin/volumes.py:40
993 msgid "Eject"
994 msgstr "Mata ut"
995
996 #: ../kupfer/plugin/volumes.py:50
997 msgid "Unmount and eject this media"
998 msgstr "Avmontera och mata ut media"
999
1000 #: ../kupfer/plugin/volumes.py:56
1001 msgid "Unmount"
1002 msgstr "Avmontera"
1003
1004 #: ../kupfer/plugin/volumes.py:66
1005 msgid "Unmount this volume"
1006 msgstr "Avmontera volym"
2711007
2721008 #: ../kupfer/preferences.py:160
2731009 msgid "Applied"
2781014 msgstr "Snabbtangenten kunde inte bindas"
2791015
2801016 #. TRANS: Plugin contents header
281 #: ../kupfer/preferences.py:280
1017 #: ../kupfer/preferences.py:283
2821018 msgid "Sources"
2831019 msgstr "Källor"
2841020
2851021 #. TRANS: Plugin contents header
286 #: ../kupfer/preferences.py:284
1022 #: ../kupfer/preferences.py:287
2871023 msgid "Actions"
2881024 msgstr "Kommandon"
2891025
2961032 msgid "Include in top level"
2971033 msgstr "Inkludera i toppnivån"
2981034
299 #: ../kupfer/preferences.py:337
1035 #: ../kupfer/preferences.py:338
3001036 msgid ""
3011037 "If enabled, objects from the plugin's source(s) will be available in the top "
3021038 "level.\n"
3051041 "När alternativet är aktiverat inkluderas objekt från insticksmodulens "
3061042 "källori toppnivån.\n"
3071043 "Källor är alltid tillgängliga som underkataloger i toppnivån."
308
309 #: ../kupfer/plugin/abiword.py:12
310 msgid "Abiword"
311 msgstr "Abiword"
312
313 #: ../kupfer/plugin/abiword.py:15 ../kupfer/plugin/abiword.py:103
314 msgid "Recently used documents in Abiword"
315 msgstr "Senaste dokument i Abiword"
316
317 #: ../kupfer/plugin/abiword.py:56
318 msgid "Abiword Recent Items"
319 msgstr "Abiwords senaste dokument"
320
321 #: ../kupfer/plugin/applications.py:4 ../kupfer/plugin/applications.py:19
322 msgid "Applications"
323 msgstr "Program"
324
325 #: ../kupfer/plugin/applications.py:7 ../kupfer/plugin/applications.py:37
326 msgid "All applications and preferences"
327 msgstr "Alla program och inställningspaneler"
328
329 #: ../kupfer/plugin/applications.py:46
330 msgid "Open With..."
331 msgstr "Öppna med..."
332
333 #: ../kupfer/plugin/applications.py:57
334 msgid "Open with any application"
335 msgstr "Öppna med godtyckligt program"
336
337 #: ../kupfer/plugin/clipboard.py:8 ../kupfer/plugin/clipboard.py:42
338 msgid "Clipboards"
339 msgstr "Urklipp"
340
341 #: ../kupfer/plugin/clipboard.py:11 ../kupfer/plugin/clipboard.py:68
342 msgid "Recent clipboards"
343 msgstr "Senaste urklipp"
344
345 #: ../kupfer/plugin/clipboard.py:18
346 msgid "Number of recent clipboards"
347 msgstr "Antal senaste urklipp"
348
349 #: ../kupfer/plugin/clipboard.py:34
350 #, python-format
351 msgid "Clipboard \"%(desc)s\""
352 msgid_plural "Clipboard with %(num)d lines \"%(desc)s\""
353 msgstr[0] "Urklipp \"%(desc)s\""
354 msgstr[1] "Urklipp med %(num)d rader \"%(desc)s\""
355
356 #: ../kupfer/plugin/clipboard.py:77
357 msgid "Copy"
358 msgstr "Kopiera"
359
360 #: ../kupfer/plugin/clipboard.py:84
361 msgid "Copy to clipboard"
362 msgstr "Kopiera till urklipp"
363
364 #: ../kupfer/plugin/commands.py:10 ../kupfer/plugin/commands.py:36
365 msgid "Shell Commands"
366 msgstr "Skalkommandon"
367
368 #: ../kupfer/plugin/commands.py:13 ../kupfer/plugin/commands.py:55
369 msgid "Run commandline programs"
370 msgstr "Kör kommandoradsprogram"
371
372 #: ../kupfer/plugin/common.py:8
373 msgid "Common"
374 msgstr "Bas"
375
376 #: ../kupfer/plugin/common.py:10
377 msgid "Special items and actions"
378 msgstr "Speicella objekt och kommandon"
379
380 #: ../kupfer/plugin/common.py:28
381 msgid "Log Out..."
382 msgstr "Logga ut..."
383
384 #: ../kupfer/plugin/common.py:34
385 msgid "Log out or change user"
386 msgstr "Logga ut eller byt användare"
387
388 #: ../kupfer/plugin/common.py:41
389 msgid "Shut Down..."
390 msgstr "Stäng av..."
391
392 #: ../kupfer/plugin/common.py:48
393 msgid "Shut down, restart or suspend computer"
394 msgstr "Stäng av, starta om eller sätt datorn i vänteläge"
395
396 #: ../kupfer/plugin/common.py:55
397 msgid "Lock Screen"
398 msgstr "Lås skärmen"
399
400 #: ../kupfer/plugin/common.py:61
401 msgid "Enable screensaver and lock"
402 msgstr "Aktivera skärmsläckaren och lås skärmen"
403
404 #: ../kupfer/plugin/common.py:97
405 msgid "Trash is empty"
406 msgstr "Papperskorgen är tom"
407
408 #. proper translation of plural
409 #: ../kupfer/plugin/common.py:99
410 #, python-format
411 msgid "Trash contains one file"
412 msgid_plural "Trash contains %(num)s files"
413 msgstr[0] "Papperskorgen innehåller ett objekt"
414 msgstr[1] "Papperskorgen innehåller %(num)s objekt"
415
416 #: ../kupfer/plugin/common.py:103
417 msgid "Special Items"
418 msgstr "Speciella objekt"
419
420 #: ../kupfer/plugin/common.py:118
421 msgid "Items and special actions"
422 msgstr "Speciella objekt och övriga kommandon"
423
424 #: ../kupfer/plugin/core.py:25
425 msgid "Search Content..."
426 msgstr "Sök i..."
427
428 #: ../kupfer/plugin/core.py:40
429 msgid "Search inside this catalog"
430 msgstr "Sök bland objekt i katalogen"
431
432 #: ../kupfer/plugin/core.py:48
433 msgid "Rescan"
434 msgstr "Uppdatera"
435
436 #: ../kupfer/plugin/core.py:57
437 msgid "Force reindex of this source"
438 msgstr "Tvinga omläsning av källan"
439
440 #: ../kupfer/plugin/core.py:141
441 msgid "Quit"
442 msgstr "Avsluta"
443
444 #: ../kupfer/plugin/core.py:146
445 msgid "Quit Kupfer"
446 msgstr "Avsluta Kupfer"
447
448 #: ../kupfer/plugin/core.py:152
449 msgid "About Kupfer"
450 msgstr "Om Kupfer"
451
452 #: ../kupfer/plugin/core.py:157
453 msgid "Show information about Kupfer authors and license"
454 msgstr "Visa information om Kupfers upphovsmän och licens"
455
456 #: ../kupfer/plugin/core.py:170
457 msgid "Show preferences window for Kupfer"
458 msgstr "Visa Kupfers inställningsfönster"
459
460 #: ../kupfer/plugin/core.py:187
461 msgid "Kupfer items and actions"
462 msgstr "Kupfer-objekt och kommandon"
463
464 #: ../kupfer/plugin/devhelp.py:4
465 msgid "Devhelp"
466 msgstr "Devhelp"
467
468 #: ../kupfer/plugin/devhelp.py:6 ../kupfer/plugin/devhelp.py:12
469 msgid "Search in Devhelp"
470 msgstr "Sök i Devhelp"
471
472 #: ../kupfer/plugin/dictionary.py:4
473 msgid "Dictionary"
474 msgstr "Ordbok"
475
476 #: ../kupfer/plugin/dictionary.py:6 ../kupfer/plugin/dictionary.py:23
477 msgid "Look up word in dictionary"
478 msgstr "Slå upp ord i ordboken"
479
480 #: ../kupfer/plugin/dictionary.py:12 ../kupfer/plugin/dictionary.py:16
481 msgid "Look Up"
482 msgstr "Slå upp"
483
484 #: ../kupfer/plugin/documents.py:11
485 msgid "Documents"
486 msgstr "Dokument"
487
488 #: ../kupfer/plugin/documents.py:14
489 msgid "Recently used documents and nautilus places"
490 msgstr "Senaste dokument och sparade platser"
491
492 #: ../kupfer/plugin/documents.py:21
493 msgid "Max recent document days"
494 msgstr "Maximal ålder för senaste dokument"
495
496 #: ../kupfer/plugin/documents.py:31
497 msgid "Recent Items"
498 msgstr "Senaste dokument"
499
500 #: ../kupfer/plugin/documents.py:77
501 msgid "Recently used documents"
502 msgstr "Senast använda dokument"
503
504 #: ../kupfer/plugin/documents.py:87
505 #, python-format
506 msgid "%s Documents"
507 msgstr "%s-dokument"
508
509 #: ../kupfer/plugin/documents.py:109
510 #, python-format
511 msgid "Recently used documents for %s"
512 msgstr "Senaste dokument för %s"
513
514 #: ../kupfer/plugin/documents.py:128
515 msgid "Places"
516 msgstr "Platser"
517
518 #: ../kupfer/plugin/documents.py:160
519 msgid "Bookmarked locations in Nautilus"
520 msgstr "Sparade platser i Nautilus"
521
522 #: ../kupfer/plugin/epiphany.py:4 ../kupfer/plugin/epiphany.py:14
523 msgid "Epiphany Bookmarks"
524 msgstr "Epiphany-bokmärken"
525
526 #: ../kupfer/plugin/epiphany.py:7 ../kupfer/plugin/epiphany.py:23
527 msgid "Index of Epiphany bookmarks"
528 msgstr "Index över Epiphany-bokmärken"
529
530 #: ../kupfer/plugin/favorites.py:8 ../kupfer/plugin/favorites.py:27
531 msgid "Favorites"
532 msgstr "Favoriter"
533
534 #: ../kupfer/plugin/favorites.py:11
535 msgid "(Simple) favorites plugin"
536 msgstr "(Enkel) modul för favoritobjekt"
537
538 #: ../kupfer/plugin/favorites.py:54
539 msgid "Shelf of \"Favorite\" items"
540 msgstr "Plats för favoritobjekt"
541
542 #: ../kupfer/plugin/favorites.py:66
543 msgid "Add to Favorites"
544 msgstr "Lägg till favorit"
545
546 #: ../kupfer/plugin/favorites.py:76
547 msgid "Add item to favorites shelf"
548 msgstr "Lägg till objekt till favorithyllan"
549
550 #: ../kupfer/plugin/favorites.py:82
551 msgid "Remove from Favorites"
552 msgstr "Ta bort favorit"
553
554 #: ../kupfer/plugin/favorites.py:90
555 msgid "Remove item from favorites shelf"
556 msgstr "Ta bort objekt från favorithyllan"
557
558 #: ../kupfer/plugin/fileactions.py:10
559 msgid "File Actions"
560 msgstr "Filkommandon"
561
562 #: ../kupfer/plugin/fileactions.py:20
563 msgid "More file actions"
564 msgstr "Fler filkommandon"
565
566 #: ../kupfer/plugin/fileactions.py:28
567 msgid "Move to Trash"
568 msgstr "Flytta till papperskorgen"
569
570 #: ../kupfer/plugin/fileactions.py:36
571 msgid "Move this file to trash"
572 msgstr "Flytta filen till papperskorgen"
573
574 #: ../kupfer/plugin/fileactions.py:58
575 msgid "Move To..."
576 msgstr "Flytta till..."
577
578 #: ../kupfer/plugin/fileactions.py:81
579 msgid "Move file to new location"
580 msgstr "Flytta till ny plats"
581
582 #: ../kupfer/plugin/fileactions.py:85
583 msgid "Copy To..."
584 msgstr "Kopiera till..."
585
586 #: ../kupfer/plugin/fileactions.py:107
587 msgid "Copy file to a chosen location"
588 msgstr "Kopiera filen till en vald plats"
589
590 #: ../kupfer/plugin/fileactions.py:111
591 msgid "Extract Here"
592 msgstr "Packa upp här"
593
594 #: ../kupfer/plugin/fileactions.py:125
595 msgid "Extract compressed archive"
596 msgstr "Packa upp komprimerad fil"
597
598 #: ../kupfer/plugin/fileactions.py:129
599 msgid "Create Archive"
600 msgstr "Skapa arkiv"
601
602 #: ../kupfer/plugin/fileactions.py:139
603 msgid "Create a compressed archive from folder"
604 msgstr "Skapa komprimerat arkiv av mappen"
605
606 #: ../kupfer/plugin/firefox.py:4 ../kupfer/plugin/firefox.py:14
607 msgid "Firefox Bookmarks"
608 msgstr "Firefox-bokmärken"
609
610 #: ../kupfer/plugin/firefox.py:7 ../kupfer/plugin/firefox.py:22
611 msgid "Index of Firefox bookmarks"
612 msgstr "Index över Firefox-bokmärken"
613
614 #: ../kupfer/plugin/google.py:8
615 msgid "Search the Web"
616 msgstr "Webbsökning"
617
618 #: ../kupfer/plugin/google.py:12
619 msgid "Send search queries to Google"
620 msgstr "Skicka sökningar till Google"
621
622 #: ../kupfer/plugin/google.py:18
623 msgid "Search with Google"
624 msgstr "Sök med Google"
625
626 #: ../kupfer/plugin/google.py:27
627 msgid "Search for this term with Google"
628 msgstr "Sök efter denna termen med Google"
629
630 #: ../kupfer/plugin/rhythmbox.py:10 ../kupfer/plugin/rhythmbox.py:343
631 msgid "Rhythmbox"
632 msgstr "Rhythmbox"
633
634 #: ../kupfer/plugin/rhythmbox.py:15 ../kupfer/plugin/rhythmbox.py:378
635 msgid "Play and enqueue tracks and browse the music library"
636 msgstr "Spela spår och sök i musikbiblioteket"
637
638 #: ../kupfer/plugin/rhythmbox.py:22
639 msgid "Include artists in top level"
640 msgstr "Inkludera artister i toppnivån"
641
642 #: ../kupfer/plugin/rhythmbox.py:28
643 msgid "Include albums in top level"
644 msgstr "Inkludera album i toppnivån"
645
646 #: ../kupfer/plugin/rhythmbox.py:34
647 msgid "Include songs in top level"
648 msgstr "Inkludera låtar i toppnivån"
649
650 #: ../kupfer/plugin/rhythmbox.py:63 ../kupfer/plugin/rhythmbox.py:116
651 msgid "Play"
652 msgstr "Spela upp"
653
654 #: ../kupfer/plugin/rhythmbox.py:67
655 msgid "Resume playback in Rhythmbox"
656 msgstr "Starta uppspelning i Rhythmbox"
657
658 #: ../kupfer/plugin/rhythmbox.py:73
659 msgid "Pause"
660 msgstr "Paus"
661
662 #: ../kupfer/plugin/rhythmbox.py:77
663 msgid "Pause playback in Rhythmbox"
664 msgstr "Pausa uppspelning i Rhythmbox"
665
666 #: ../kupfer/plugin/rhythmbox.py:83
667 msgid "Next"
668 msgstr "Nästa"
669
670 #: ../kupfer/plugin/rhythmbox.py:87
671 msgid "Jump to next track in Rhythmbox"
672 msgstr "Hoppa till nästa spår i Rhythmbox"
673
674 #: ../kupfer/plugin/rhythmbox.py:93
675 msgid "Previous"
676 msgstr "Föregående"
677
678 #: ../kupfer/plugin/rhythmbox.py:97
679 msgid "Jump to previous track in Rhythmbox"
680 msgstr "Hoppa till föregående spår i Rhythmbox"
681
682 #: ../kupfer/plugin/rhythmbox.py:103
683 msgid "Show Playing"
684 msgstr "Vilken låt?"
685
686 #: ../kupfer/plugin/rhythmbox.py:107
687 msgid "Tell which song is currently playing"
688 msgstr "Visa vilken låt som spelas just nu"
689
690 #: ../kupfer/plugin/rhythmbox.py:129
691 msgid "Play tracks in Rhythmbox"
692 msgstr "Spela upp spår i Rhythmbox"
693
694 #: ../kupfer/plugin/rhythmbox.py:135
695 msgid "Enqueue"
696 msgstr "Köa"
697
698 #: ../kupfer/plugin/rhythmbox.py:146
699 msgid "Add tracks to the play queue"
700 msgstr "Lägg till spår i spelkön"
701
702 #. TRANS: Song description
703 #: ../kupfer/plugin/rhythmbox.py:164
704 #, python-format
705 msgid "by %(artist)s from %(album)s"
706 msgstr "av %(artist)s från %(album)s"
707
708 #. TRANS: Album description "by Artist"
709 #: ../kupfer/plugin/rhythmbox.py:217
710 #, python-format
711 msgid "by %s"
712 msgstr "av %s"
713
714 #. TRANS: Artist songs collection description
715 #: ../kupfer/plugin/rhythmbox.py:256
716 #, python-format
717 msgid "Tracks by %s"
718 msgstr "Spår av %s"
719
720 #: ../kupfer/plugin/rhythmbox.py:266
721 msgid "Albums"
722 msgstr "Album"
723
724 #: ../kupfer/plugin/rhythmbox.py:276
725 msgid "Music albums in Rhythmbox Library"
726 msgstr "Album i Rhythmboxs bibliotek"
727
728 #: ../kupfer/plugin/rhythmbox.py:287
729 msgid "Artists"
730 msgstr "Artister"
731
732 #: ../kupfer/plugin/rhythmbox.py:297
733 msgid "Music artists in Rhythmbox Library"
734 msgstr "Artister i Rhythmboxs bibliotek"
735
736 #: ../kupfer/plugin/rhythmbox.py:323
737 msgid "Songs"
738 msgstr "Låtar"
739
740 #: ../kupfer/plugin/rhythmbox.py:333
741 msgid "Songs in Rhythmbox library"
742 msgstr "Låtar i Rhythmboxs bibliotek"
743
744 #: ../kupfer/plugin/screen.py:7 ../kupfer/plugin/screen.py:109
745 msgid "GNU Screen"
746 msgstr "GNU Screen"
747
748 #: ../kupfer/plugin/screen.py:9 ../kupfer/plugin/screen.py:94
749 msgid "Active GNU Screen sessions"
750 msgstr "Aktiva GNU Screen-sessioner"
751
752 #: ../kupfer/plugin/screen.py:49
753 msgid "Attached"
754 msgstr "Ansluten"
755
756 #: ../kupfer/plugin/screen.py:50
757 msgid "Detached"
758 msgstr "Frånkopplad"
759
760 #: ../kupfer/plugin/screen.py:53
761 #, python-format
762 msgid "%(status)s session (%(pid)s) created %(time)s"
763 msgstr "%(status)s session %(pid)s) skapad %(time)s"
764
765 #: ../kupfer/plugin/screen.py:62
766 msgid "Screen Sessions"
767 msgstr "Screen-sessioner"
768
769 #: ../kupfer/plugin/screen.py:104
770 msgid "Attach"
771 msgstr "Anslut till"
772
773 #: ../kupfer/plugin/selection.py:5 ../kupfer/plugin/selection.py:13
774 #: ../kupfer/plugin/selection.py:22
775 msgid "Selected Text"
776 msgstr "Markering"
777
778 #: ../kupfer/plugin/selection.py:7 ../kupfer/plugin/selection.py:39
779 msgid "Provides current selection"
780 msgstr "Tillhandahåller aktuell markering"
781
782 #: ../kupfer/plugins.py:51
783 msgid "(no description)"
784 msgstr "(ingen beskrivning)"
785
786 #: ../kupfer/plugins.py:70
787 #, python-format
788 msgid " %(name)-20s %(version)-4s %(description)s"
789 msgstr " %(name)-20s %(version)-4s %(description)s"
790
791 #: ../kupfer/plugin/text.py:8
792 msgid "Free-text Queries"
793 msgstr "Fritextsökningar"
794
795 #: ../kupfer/plugin/text.py:11
796 msgid "Basic support for free-text queries"
797 msgstr "Grundstöd för fritextsökningar"
798
799 #: ../kupfer/plugin/text.py:29
800 msgid "Filesystem Text Matches"
801 msgstr "Fritextträffar i filsystemet"
802
803 #: ../kupfer/plugin/text.py:45
804 msgid "URL Text Matches"
805 msgstr "URL-täffar i fritext"
806
807 #: ../kupfer/plugin/tracker.py:10
808 msgid "Tracker"
809 msgstr "Tracker"
810
811 #: ../kupfer/plugin/tracker.py:19
812 msgid "Tracker desktop search integration"
813 msgstr "Integration med sökprogrammet Tracker"
814
815 #: ../kupfer/plugin/tracker.py:25
816 msgid "Search in Tracker"
817 msgstr "Sök i Tracker"
818
819 #: ../kupfer/plugin/tracker.py:30
820 msgid "Open Tracker Search Tool and search for this term"
821 msgstr "Sök efter denna term i Sökverktyget Tracker"
822
823 #: ../kupfer/plugin/tracker.py:39
824 msgid "Get Tracker results..."
825 msgstr "Hämta träffar från Tracker..."
826
827 #: ../kupfer/plugin/tracker.py:48
828 msgid "Show Tracker results for query"
829 msgstr "Visa träffar för sökning med Tracker"
830
831 #: ../kupfer/plugin/tracker.py:56 ../kupfer/plugin/tracker.py:93
832 #, python-format
833 msgid "Results for \"%s\""
834 msgstr "Resultat för \"%s\""
835
836 #: ../kupfer/plugin/tracker.py:124 ../kupfer/plugin/tracker.py:130
837 msgid "Tracker tags"
838 msgstr "Tracker-taggar"
839
840 #: ../kupfer/plugin/tracker.py:139
841 msgid "Tracker Tags"
842 msgstr "Tracker-taggar"
843
844 #: ../kupfer/plugin/tracker.py:145
845 msgid "Browse Tracker's tags"
846 msgstr "Bläddra i Trackers taggar"
847
848 #: ../kupfer/plugin/tracker.py:156 ../kupfer/plugin/tracker.py:163
849 #, python-format
850 msgid "Tag %s"
851 msgstr "Taggen %s"
852
853 #: ../kupfer/plugin/tracker.py:170
854 #, python-format
855 msgid "Objects tagged %s with Tracker"
856 msgstr "Objekt taggade %s med Tracker"
857
858 #: ../kupfer/plugin/tracker.py:182
859 msgid "Add Tag..."
860 msgstr "Lägg till tagg..."
861
862 #: ../kupfer/plugin/tracker.py:208
863 msgid "Add tracker tag to file"
864 msgstr "Lägg till tracker-tagg till filen"
865
866 #: ../kupfer/plugin/tracker.py:214
867 msgid "Remove Tag..."
868 msgstr "Ta bort tagg..."
869
870 #: ../kupfer/plugin/tracker.py:233
871 msgid "Remove tracker tag from file"
872 msgstr "Ta bort tracker-tagg från filen"
873
874 #: ../kupfer/plugin/wikipedia.py:10
875 msgid "Wikipedia"
876 msgstr "Wikipedia"
877
878 #: ../kupfer/plugin/wikipedia.py:13 ../kupfer/plugin/wikipedia.py:30
879 msgid "Search in Wikipedia"
880 msgstr "Sök i Wikipedia"
881
882 #: ../kupfer/plugin/wikipedia.py:20
883 msgid "Wikipedia language"
884 msgstr "Wikipedia-språk"
885
886 #. TRANS: Default wikipedia language code
887 #: ../kupfer/plugin/wikipedia.py:23
888 msgid "en"
889 msgstr "sv"
890
891 #: ../kupfer/plugin/wikipedia.py:43
892 #, python-format
893 msgid "Search for this term in %s.wikipedia.org"
894 msgstr "Sök efter denna termen i %s.wikipedia.org"
895
896 #: ../kupfer/plugin/windows.py:7 ../kupfer/plugin/windows.py:86
897 msgid "Window List"
898 msgstr "Fönsterlista"
899
900 #: ../kupfer/plugin/windows.py:9 ../kupfer/plugin/windows.py:107
901 msgid "All windows on all workspaces"
902 msgstr "Alla fönster på alla arbetsytor"
903
904 #: ../kupfer/plugin/windows.py:17
905 msgid "Activate"
906 msgstr "Aktivera"
907
908 #: ../kupfer/plugin/windows.py:20
909 msgid "Unshade"
910 msgstr "Rulla ner"
911
912 #: ../kupfer/plugin/windows.py:22
913 msgid "Shade"
914 msgstr "Rulla upp"
915
916 #: ../kupfer/plugin/windows.py:24
917 msgid "Unminimize"
918 msgstr "Avminimera"
919
920 #: ../kupfer/plugin/windows.py:26
921 msgid "Minimize"
922 msgstr "Minimera"
923
924 #: ../kupfer/plugin/windows.py:28
925 msgid "Unmaximize"
926 msgstr "Avmaximera"
927
928 #: ../kupfer/plugin/windows.py:30
929 msgid "Maximize"
930 msgstr "Maximera"
931
932 #: ../kupfer/plugin/windows.py:32
933 msgid "Unmaximize Vertically"
934 msgstr "Avmaximera vertikalt"
935
936 #: ../kupfer/plugin/windows.py:35
937 msgid "Maximize Vertically"
938 msgstr "Maximera vertikalt"
939
940 #: ../kupfer/plugin/windows.py:37
941 msgid "Close"
942 msgstr "Stäng"
943
944 #. TRANS: Window on (Workspace name), window description
945 #: ../kupfer/plugin/windows.py:43
946 #, python-format
947 msgid "Window on %(wkspc)s"
948 msgstr "Fönster på %(wkspc)s"
949
950 #: ../kupfer/plugin/windows.py:58
951 msgid "Jump to this window's workspace and focus"
952 msgstr "Gå till fönstrets arbetsyta och aktivera"
953
954 #: ../kupfer/plugin/volumes.py:6 ../kupfer/plugin/volumes.py:71
955 msgid "Volumes and Disks"
956 msgstr "Volymer"
957
958 #: ../kupfer/plugin/volumes.py:8 ../kupfer/plugin/volumes.py:81
959 msgid "Mounted volumes and disks"
960 msgstr "Monterade volymer och löstagbara enheter"
961
962 #: ../kupfer/plugin/volumes.py:32
963 #, python-format
964 msgid "Volume mounted at %s"
965 msgstr "Volym monterad vid %s"
966
967 #: ../kupfer/plugin/volumes.py:40
968 msgid "Eject"
969 msgstr "Mata ut"
970
971 #: ../kupfer/plugin/volumes.py:50
972 msgid "Unmount and eject this media"
973 msgstr "Avmontera och mata ut media"
974
975 #: ../kupfer/plugin/volumes.py:56
976 msgid "Unmount"
977 msgstr "Avmontera"
978
979 #: ../kupfer/plugin/volumes.py:66
980 msgid "Unmount this volume"
981 msgstr "Avmontera volym"
9821044
9831045 #: ../kupfer/version.py:22
9841046 msgid "translator-credits"
10181080 "Du bör ha fått en kopia av GNU General Public License tillsammans med\n"
10191081 "detta program. Om inte, <http://www.gnu.org/licenses/>.\n"
10201082
1021 #~ msgid "%s et al"
1022 #~ msgstr "%s et al"
1023
1024 #~ msgid "Open with %s (default)"
1025 #~ msgstr "Öppna med %s (standardval)"
1026
1027 #~ msgid "Miscellaneous items"
1028 #~ msgstr "Blandade objekt"
1029
1030 #~ msgid "%(description)s (%(exec)s)"
1031 #~ msgstr "%(description)s (%(exec)s)"
1032
1033 #~ msgid "\"%s\""
1034 #~ msgstr "\"%s\""
1035
10361083 #~ msgid "Core"
10371084 #~ msgstr "Bas"
10381085
1039 #~ msgid "Kupfer items"
1040 #~ msgstr "Kupfer-objekt"
1041
10421086 #~ msgid "%d lines"
10431087 #~ msgstr "%d rader"
10441088
1045 #~ msgid "Clipboard with %s \"%s\""
1046 #~ msgstr "Urklipp med %s \"%s\""
1047
1048 #~ msgid "A simple flexible launcher"
1049 #~ msgstr "En enkel programstartare"
1050
1051 #~ msgid "Send search queries to Wikipedia"
1052 #~ msgstr "Skicka sökningar till Google"
1053
1054 #~ msgid "<b>Notification</b>"
1055 #~ msgstr "<b>Notifiering</b>"
1056
10571089 #~ msgid "Directories"
10581090 #~ msgstr "Kataloger"
10591091
10601092 #~ msgid "Clipboard"
10611093 #~ msgstr "Urklipp"
10621094
1063 #~ msgid "gtk-preferences"
1064 #~ msgstr "Inställningar för Kupfer"
1065
1066 #~ msgid "Recent documents for %s"
1067 #~ msgstr "Senast använda dokument"
1068
1069 #~ msgid "Settings are not implemented yet; see 'kupfer --help'"
1070 #~ msgstr "Inställningar är inte implementerade än; se 'kupfer --help'"
1071
1072 #~ msgid "All Applications"
1073 #~ msgstr "Alla program"
1074
1075 #~ msgid "Shell"
1076 #~ msgstr "Skal"
1077
1078 #~ msgid "Epiphany"
1079 #~ msgstr "Epiphany"
1080
1081 #~ msgid "Firefox"
1082 #~ msgstr "Firefox"
1083
1084 #~ msgid "GNU Screen session"
1085 #~ msgstr "GNU Screen-session"
1086
1087 #~ msgid "Tracker live search"
1088 #~ msgstr "Livesökning med Tracker"
1089
1090 #~ msgid "(Experimental) Tracker live search results"
1091 #~ msgstr "(Experimentell) Trackersökningsresultat live"
1092
1093 #~ msgid "Results for query \"%s\""
1094 #~ msgstr "Resultat för \"%s\""
1095
1096 #~ msgid "Text query \"%s\""
1097 #~ msgstr "Textsökning \"%s\""
1098
1099 #~ msgid "Trash"
1100 #~ msgstr "Papperskorg"
1101
1102 #~ msgid "Computer"
1103 #~ msgstr "Dator"
3737 # these variables are mandatory ('/' are converted automatically)
3838 srcdir = '.'
3939 blddir = 'build'
40
41 def dist_hook():
42 """in the dist preparation dir, delete unwanted files"""
43 DIST_GIT_IGNORE = """
44 debug.py
45 makedist.sh
46 """.split()
47
48 for ignfile in filter(os.path.exists, DIST_GIT_IGNORE):
49 os.unlink(ignfile)
4050
4151 def dist():
4252 """Make the dist tarball and print its SHA-1 """