Imported Upstream version 0+c10
SVN-Git Migration
6 years ago
0 | 0 | NEWS for kupfer |
1 | 1 | =============== |
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%) | |
2 | 18 | |
3 | 19 | kupfer version c9.1 |
4 | 20 | ----------------- |
54 | 54 | [plugin_epiphany] |
55 | 55 | kupfer_enabled = True |
56 | 56 | kupfer_toplevel = False |
57 | kupfer_show_toplevel = True | |
57 | 58 | |
58 | 59 | [plugin_favorites] |
59 | 60 | kupfer_enabled = True |
64 | 65 | [plugin_firefox] |
65 | 66 | kupfer_enabled = True |
66 | 67 | kupfer_toplevel = False |
68 | kupfer_show_toplevel = True | |
67 | 69 | |
68 | 70 | [plugin_google] |
69 | 71 | kupfer_enabled = True |
83 | 85 | [plugin_tracker] |
84 | 86 | kupfer_enabled = False |
85 | 87 | |
88 | [plugin_urlactions] | |
89 | kupfer_enabled = True | |
90 | ||
86 | 91 | [plugin_volumes] |
87 | 92 | kupfer_enabled = True |
88 | 93 |
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> |
1 | 1 | bld.install_files("${DATADIR}/kupfer", "defaults.cfg") |
2 | 2 | bld.install_files("${DATADIR}/kupfer", "preferences.ui") |
3 | 3 | |
4 | # install all art files | |
4 | # install all pure data files | |
5 | 5 | bld.install_files("${DATADIR}/kupfer/art", "art/*") |
6 | bld.install_files("${DATADIR}/kupfer/searchplugins", "searchplugins/*") | |
6 | 7 | |
7 | 8 | # compress and install man page |
8 | 9 | bld.new_task_gen( |
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) |
4 | 4 | import signal |
5 | 5 | import os |
6 | 6 | import time |
7 | ||
8 | import pygtk | |
9 | pygtk.require('2.0') | |
7 | 10 | |
8 | 11 | import gtk |
9 | 12 | import gio |
702 | 705 | self._key_press_time = None |
703 | 706 | self._key_press_interval = 0.8 |
704 | 707 | 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) | |
708 | 711 | |
709 | 712 | from pango import ELLIPSIZE_END |
710 | 713 | self.label.set_width_chars(50) |
771 | 774 | self._widget = vbox |
772 | 775 | return vbox |
773 | 776 | |
774 | def _map_entry(self, widget, event): | |
777 | def _map_window(self, widget, event): | |
775 | 778 | """When Interface's widget is mapped and shown on the screen""" |
776 | 779 | # 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] | |
779 | 783 | self.update_text_mode() |
780 | 784 | |
781 | 785 | def _pane_button_press(self, widget, event): |
793 | 797 | """ |
794 | 798 | keyv = event.keyval |
795 | 799 | 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 | } | |
796 | 807 | # test for alt modifier (MOD1_MASK is alt/option) |
797 | 808 | modifiers = gtk.accelerator_get_default_mod_mask() |
798 | 809 | mod1_mask = ((event.state & modifiers) == gtk.gdk.MOD1_MASK) |
807 | 818 | # if input is slow/new, we reset |
808 | 819 | if not text_mode and input_time_diff > self._slow_input_interval: |
809 | 820 | 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 | |
810 | 835 | |
811 | 836 | has_selection = (self.current.get_match_state() is State.Match) |
812 | 837 | can_text_mode = self.get_can_enter_text_mode() |
896 | 921 | else: |
897 | 922 | self.current.reset() |
898 | 923 | |
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 | ||
899 | 932 | def _reset_key_press(self, escape=False): |
900 | 933 | """Handle leftarrow, backspace and escape |
901 | 934 | Go up back through browsed sources. |
934 | 967 | self.reset() |
935 | 968 | return val |
936 | 969 | |
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 | ||
937 | 978 | def update_text_mode(self): |
938 | 979 | """update appearance to whether text mode enabled or not""" |
980 | if not self._theme_colors: | |
981 | return | |
939 | 982 | if self._is_text_mode: |
940 | 983 | self.entry.set_size_request(-1,-1) |
941 | 984 | self.entry.set_property("has-frame", True) |
942 | 985 | 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) | |
945 | 988 | self.entry.modify_base(gtk.STATE_NORMAL, bgcolor) |
946 | 989 | self.current.set_state(gtk.STATE_ACTIVE) |
947 | 990 | else: |
948 | 991 | self.entry.set_size_request(0,0) |
949 | 992 | 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) | |
952 | 996 | self.current.set_state(gtk.STATE_SELECTED) |
953 | 997 | self._size_window_optimally() |
954 | 998 | |
1050 | 1094 | self.data_controller.browse_down(pane, alternate=alternate) |
1051 | 1095 | |
1052 | 1096 | def _activate(self, widget, current): |
1097 | # reset self through toggle_text_mode | |
1053 | 1098 | self.data_controller.activate() |
1054 | self.reset() | |
1099 | self.toggle_text_mode(False) | |
1055 | 1100 | |
1056 | 1101 | def _search_result(self, sender, pane, matchrankable, matches, context): |
1057 | 1102 | key = context |
1128 | 1173 | """ |
1129 | 1174 | """ |
1130 | 1175 | self.icon_name = gtk.STOCK_FIND |
1131 | self.data_controller = data.DataController() | |
1132 | 1176 | 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) | |
1134 | 1183 | self._setup_window() |
1135 | self.interface.connect("cancelled", self._cancelled) | |
1136 | self.data_controller.connect("launched-action", self.launch_callback) | |
1137 | self._keystr = "" | |
1138 | 1184 | self._statusicon = None |
1139 | 1185 | |
1140 | 1186 | def show_statusicon(self): |
1205 | 1251 | |
1206 | 1252 | def activate(self, sender=None, time=0): |
1207 | 1253 | evttime = time if time else gtk.get_current_event_time() |
1208 | self.window.show() | |
1209 | 1254 | self.window.stick() |
1255 | self.window.present_with_time(time) | |
1210 | 1256 | self.window.window.focus(timestamp=evttime) |
1211 | 1257 | self.interface.focus() |
1212 | 1258 | |
1284 | 1330 | (keybinding callback, session logout callbacks etc) |
1285 | 1331 | """ |
1286 | 1332 | # register dbus callbacks |
1287 | from .listen import Service, AlreadyRunning, NoConnection | |
1333 | from . import listen | |
1288 | 1334 | from .session import SessionClient |
1289 | 1335 | from kupfer import scheduler, settings |
1290 | 1336 | from kupfer import keybindings |
1291 | 1337 | |
1292 | 1338 | try: |
1293 | s = Service() | |
1294 | except AlreadyRunning: | |
1339 | s = listen.Service() | |
1340 | except listen.AlreadyRunning: | |
1295 | 1341 | s = None |
1296 | 1342 | self.output_info("An instance is already running, exiting...") |
1297 | 1343 | self.quit_now() |
1298 | except NoConnection: | |
1344 | except listen.NoConnection: | |
1299 | 1345 | pass |
1300 | 1346 | else: |
1301 | 1347 | s.connect("present", self.activate) |
1330 | 1376 | client.connect("save-yourself", self._session_save) |
1331 | 1377 | client.connect("die", self._session_die) |
1332 | 1378 | |
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 | ||
1333 | 1386 | try: |
1334 | 1387 | gtk.main() |
1335 | 1388 | # put away window *before exiting further* |
1336 | 1389 | self.put_away() |
1337 | while gtk.events_pending(): | |
1338 | gtk.main_iteration() | |
1390 | main_iterations(10) | |
1339 | 1391 | except KeyboardInterrupt, info: |
1340 | 1392 | self.output_info(info, "exiting.. (Warning: Ctrl-C in the shell", |
1341 | 1393 | "will kill child processes)") |
1342 | 1394 | finally: |
1343 | 1395 | self.save_data() |
1344 | 1396 | |
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() |
33 | 33 | Return path to @filename if it exists |
34 | 34 | anywhere in the data paths, else return None |
35 | 35 | """ |
36 | # Add "./data" in workdir for running from builddir | |
37 | 36 | 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) | |
40 | 48 | |
41 | 49 | for direc in data_paths: |
42 | 50 | file_path = os.path.join(direc, filename) |
62 | 70 | """ |
63 | 71 | return base.save_data_path(PACKAGE_NAME) |
64 | 72 | |
65 | def get_data_dirs(name=""): | |
73 | def get_data_dirs(name="", package=PACKAGE_NAME): | |
66 | 74 | """ |
67 | 75 | Iterate over all data dirs of @name that exist |
68 | 76 | """ |
69 | return base.load_data_paths(os.path.join(PACKAGE_NAME, name)) | |
77 | return base.load_data_paths(os.path.join(package, name)) | |
70 | 78 | |
71 | 79 | def get_config_file(filename): |
72 | 80 | """ |
0 | import gzip | |
1 | import hashlib | |
0 | 2 | import itertools |
1 | 3 | import os |
2 | 4 | import cPickle as pickle |
7 | 9 | import gobject |
8 | 10 | gobject.threads_init() |
9 | 11 | |
10 | from . import search | |
11 | 12 | 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 | |
16 | 15 | |
17 | 16 | # "Enums" |
18 | 17 | # Which pane |
21 | 20 | # In two-pane or three-pane mode |
22 | 21 | SourceActionMode, SourceActionObjectMode = (1,2) |
23 | 22 | |
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): | |
26 | 34 | """ |
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. | |
27 | 40 | """ |
28 | 41 | |
29 | 42 | def __init__(self): |
30 | 43 | self._source_cache = {} |
31 | 44 | self._old_key = None |
32 | 45 | |
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. | |
40 | 58 | """ |
41 | 59 | if not self._old_key or not key.startswith(self._old_key): |
42 | 60 | self._source_cache.clear() |
43 | self._old_key = "" | |
44 | 61 | self._old_key = key |
45 | 62 | |
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 | |
65 | 65 | |
66 | 66 | match_iters = [] |
67 | 67 | for src in sources: |
68 | items = () | |
69 | 68 | fixedrank = 0 |
70 | 69 | rankables = None |
71 | 70 | if isinstance(src, objects.Source): |
84 | 83 | if not rankables: |
85 | 84 | rankables = search.make_rankables(items) |
86 | 85 | |
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: | |
92 | 90 | rankables = search.score_objects(rankables, key) |
93 | 91 | matches = search.bonus_objects(rankables, key) |
94 | 92 | 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 | |
96 | 94 | matches, self._source_cache[src] = itertools.tee(matches) |
97 | 95 | else: |
98 | 96 | # we only want to list them |
113 | 111 | if reprobj not in coll: |
114 | 112 | yield obj |
115 | 113 | 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 | |
123 | 114 | |
124 | 115 | def valid_check(seq): |
125 | 116 | """yield items of @seq that are valid""" |
142 | 133 | # Check if the items are valid as the search |
143 | 134 | # results are accessed through the iterators |
144 | 135 | 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))) | |
146 | 137 | 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) | |
161 | 138 | |
162 | 139 | class PeriodicRescanner (gobject.GObject, pretty.OutputMixin): |
163 | 140 | """ |
174 | 151 | self.startup = startup |
175 | 152 | self.period = period |
176 | 153 | self.campaign=campaign |
177 | self.cur_event = 0 | |
154 | self.timer = scheduler.Timer() | |
178 | 155 | # Source -> time mapping |
179 | 156 | self.latest_rescan_time = {} |
180 | 157 | self._min_rescan_interval = campaign/10 |
182 | 159 | def set_catalog(self, catalog): |
183 | 160 | self.catalog = catalog |
184 | 161 | self.cur = iter(self.catalog) |
185 | if self.cur_event: | |
186 | gobject.source_remove(self.cur_event) | |
187 | 162 | 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) | |
189 | 164 | |
190 | 165 | def _new_campaign(self): |
191 | 166 | self.output_info("Starting new campaign, interval %d s" % self.period) |
192 | 167 | 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) | |
194 | 169 | |
195 | 170 | def _periodic_rescan_helper(self): |
196 | 171 | # Advance until we find a source that was not recently rescanned |
197 | 172 | for next in self.cur: |
198 | 173 | oldtime = self.latest_rescan_time.get(next, 0) |
199 | 174 | 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): | |
211 | 183 | """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): | |
217 | 189 | 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) | |
221 | 192 | 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) | |
224 | 199 | |
225 | 200 | gobject.signal_new("reloaded-source", PeriodicRescanner, gobject.SIGNAL_RUN_LAST, |
226 | 201 | gobject.TYPE_BOOLEAN, (gobject.TYPE_PYOBJECT,)) |
227 | 202 | |
228 | class SourcePickleService (pretty.OutputMixin, object): | |
203 | class SourcePickler (pretty.OutputMixin): | |
229 | 204 | """ |
230 | Singleton that should be accessed with | |
231 | GetSourcePickleService() | |
205 | Takes care of pickling and unpickling Kupfer Sources. | |
232 | 206 | """ |
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 | ||
238 | 210 | def __init__(self): |
239 | import gzip | |
240 | 211 | 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 | """ | |
245 | 217 | for dpath, dirs, files in os.walk(config.get_cache_home()): |
246 | 218 | # Look for files matching beginning and end of |
247 | 219 | # name_template, with the previous file version |
258 | 230 | for fpath in obsolete_files: |
259 | 231 | # be overly careful |
260 | 232 | assert fpath.startswith(config.get_cache_home()) |
261 | assert "kupfer" in os.path.basename(fpath) | |
233 | assert "kupfer" in fpath | |
262 | 234 | os.unlink(fpath) |
263 | 235 | |
264 | 236 | 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("/", "-") | |
268 | 240 | 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) | |
270 | 242 | |
271 | 243 | def unpickle_source(self, source): |
272 | 244 | cached = self._unpickle_source(self.get_filename(source)) |
274 | 246 | return None |
275 | 247 | |
276 | 248 | # 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: | |
280 | 250 | return cached |
281 | 251 | else: |
282 | self.output_debug("Source version changed to %s %s" % | |
283 | (source, source.version)) | |
252 | self.output_debug("Cached version mismatches", source) | |
284 | 253 | return None |
285 | 254 | def _unpickle_source(self, pickle_file): |
286 | 255 | try: |
290 | 259 | try: |
291 | 260 | source = pickle.loads(pfile.read()) |
292 | 261 | 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)) | |
294 | 264 | except (pickle.PickleError, Exception), e: |
295 | 265 | source = None |
296 | 266 | self.output_info("Error loading %s: %s" % (pickle_file, e)) |
306 | 276 | of small writes are very slow |
307 | 277 | """ |
308 | 278 | 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)) | |
310 | 281 | output.write(pickle.dumps(source, pickle.HIGHEST_PROTOCOL)) |
311 | 282 | output.close() |
312 | 283 | return True |
313 | 284 | |
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 | |
320 | 285 | |
321 | 286 | class SourceController (pretty.OutputMixin): |
322 | 287 | """Control sources; loading, pickling, rescanning""" |
446 | 411 | the "dummy" becomes live and is rescanned if @rescan |
447 | 412 | """ |
448 | 413 | for source in list(sources): |
414 | sourcepickler = SourcePickler() | |
449 | 415 | if self.pickle: |
450 | news = GetSourcePickleService().unpickle_source(source) | |
416 | news = sourcepickler.unpickle_source(source) | |
451 | 417 | else: |
452 | 418 | news = None |
453 | 419 | if news: |
457 | 423 | # to "rescue the toplevel", we throw out sources that |
458 | 424 | # raise exceptions on rescan |
459 | 425 | try: |
460 | self.rescanner.register_rescan(source, force=True) | |
426 | self.rescanner.register_rescan(source, sync=True) | |
461 | 427 | except StandardError, exp: |
462 | 428 | self.output_error("Loading %s: raised %s %s" % ( |
463 | 429 | source, type(exp).__name__, exp)) |
466 | 432 | def _pickle_sources(self, sources): |
467 | 433 | if not self.pickle: |
468 | 434 | return |
435 | sourcepickler = SourcePickler() | |
436 | sourcepickler.rm_old_cachefiles() | |
469 | 437 | for source in sources: |
470 | 438 | if source.is_dynamic(): |
471 | 439 | continue |
472 | GetSourcePickleService().pickle_source(source) | |
440 | sourcepickler.pickle_source(source) | |
473 | 441 | |
474 | 442 | _source_controller = None |
475 | 443 | def GetSourceController(): |
490 | 458 | self.latest_key = None |
491 | 459 | self.outstanding_search = -1 |
492 | 460 | self.outstanding_search_id = -1 |
461 | self.searcher = Searcher() | |
493 | 462 | |
494 | 463 | def select(self, item): |
495 | 464 | self.selection = item |
515 | 484 | super(LeafPane, self).__init__() |
516 | 485 | self.source_stack = [] |
517 | 486 | self.source = None |
518 | self.source_search_task = SearchTask() | |
519 | 487 | |
520 | 488 | def _load_source(self, src): |
521 | 489 | """Try to get a source from the SourceController, |
596 | 564 | sc = GetSourceController() |
597 | 565 | textsrcs = sc.get_text_sources() |
598 | 566 | 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) | |
601 | 571 | self.emit_search_result(match, match_iter, context) |
572 | ||
602 | 573 | gobject.signal_new("new-source", LeafPane, gobject.SIGNAL_RUN_LAST, |
603 | 574 | gobject.TYPE_BOOLEAN, (gobject.TYPE_PYOBJECT,)) |
604 | 575 | |
627 | 598 | |
628 | 599 | actions = [a for a in actions if a.valid_for_item(self.current_item)] |
629 | 600 | sources = (actions, ) |
630 | stask = SearchTask() | |
631 | match, match_iter = stask(sources, key) | |
601 | match, match_iter = self.searcher.search(sources, key) | |
632 | 602 | self.emit_search_result(match, match_iter, context) |
633 | 603 | |
634 | 604 | class SecondaryObjectPane (LeafPane): |
641 | 611 | self.source = None |
642 | 612 | self.source_stack = None |
643 | 613 | LeafPane.reset(self) |
644 | self.source_search_task = SearchTask() | |
614 | self.searcher = Searcher() | |
645 | 615 | def set_item_and_action(self, item, act): |
646 | 616 | self.current_item = item |
647 | 617 | self.current_action = act |
675 | 645 | sc = GetSourceController() |
676 | 646 | textsrcs = sc.get_text_sources() |
677 | 647 | 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) | |
682 | 670 | self.emit_search_result(match, match_iter, context) |
683 | 671 | |
684 | 672 | class DataController (gobject.GObject, pretty.OutputMixin): |
689 | 677 | so it can register itself at the scheduler correctly. |
690 | 678 | """ |
691 | 679 | __gtype_name__ = "DataController" |
692 | ||
693 | def __call__(self): | |
694 | return self | |
695 | 680 | |
696 | 681 | def __init__(self): |
697 | 682 | super(DataController, self).__init__() |
710 | 695 | ctl.connect("search-result", self._pane_search_result, pane) |
711 | 696 | self.mode = None |
712 | 697 | self._search_ids = itertools.count(1) |
698 | self._task_runner = task.TaskRunner(end_on_finish=False) | |
713 | 699 | |
714 | 700 | sch = scheduler.GetScheduler() |
715 | 701 | sch.connect("load", self._load) |
768 | 754 | |
769 | 755 | def _load(self, sched): |
770 | 756 | """Load data from persistent store""" |
757 | self._setup_plugins() | |
771 | 758 | sc = GetSourceController() |
772 | 759 | sc.add(self.direct_sources, toplevel=True) |
773 | 760 | sc.add(self.other_sources, toplevel=False) |
774 | 761 | self.source_pane.source_rebase(sc.root) |
775 | 762 | 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) | |
776 | 821 | |
777 | 822 | def _finish(self, sched): |
778 | 823 | self.output_info("Saving data...") |
932 | 977 | self.source_pane.push_source(ret) |
933 | 978 | return |
934 | 979 | if action.is_async(): |
935 | GetProcessManager().register_action(action, leaf, sobject, ret) | |
980 | self._task_runner.add_task(ret) | |
936 | 981 | self.emit("launched-action", SourceActionMode, leaf, action) |
937 | 982 | |
938 | 983 | # pane cleared (invalid item) item was invalid |
955 | 1000 | gobject.signal_new("launched-action", DataController, gobject.SIGNAL_RUN_LAST, |
956 | 1001 | gobject.TYPE_BOOLEAN, (gobject.TYPE_INT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT)) |
957 | 1002 | |
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 |
46 | 46 | try: |
47 | 47 | import keybinder |
48 | 48 | except ImportError: |
49 | pretty.print_error("Could not import keybinder, keybindings disabled!") | |
49 | pretty.print_error(__name__, "Could not import keybinder, " | |
50 | "keybindings disabled!") | |
50 | 51 | return False |
51 | 52 | |
52 | 53 | keybinding_target = int(keybinding_target) |
53 | 54 | callback = lambda : GetKeyboundObject()._keybinding(keybinding_target) |
54 | if len(keystr) == 1: | |
55 | if keystr and len(keystr) == 1: | |
55 | 56 | pretty.print_error(__name__, "Refusing to bind key", repr(keystr)) |
56 | 57 | return False |
57 | 58 |
24 | 24 | def get_mnemonics(self): |
25 | 25 | return self.mnemonics |
26 | 26 | |
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): | |
29 | 30 | try: |
30 | 31 | pfile = open(pickle_file, "rb") |
31 | 32 | except IOError, e: |
33 | 34 | try: |
34 | 35 | source = pickle.loads(pfile.read()) |
35 | 36 | 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, )) | |
37 | 38 | except (pickle.PickleError, Exception), e: |
38 | 39 | 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)) | |
40 | 41 | return source |
41 | 42 | |
43 | @classmethod | |
42 | 44 | def _pickle_register(self, reg, pickle_file): |
43 | 45 | output = open(pickle_file, "wb") |
44 | self.output_debug("Saving to %s" % (pickle_file, )) | |
46 | pretty.print_debug(__name__, "Saving to %s" % (pickle_file, )) | |
45 | 47 | output.write(pickle.dumps(reg, pickle.HIGHEST_PROTOCOL)) |
46 | 48 | output.close() |
47 | 49 | return True |
48 | 50 | |
49 | Learning = Learning() | |
50 | 51 | _register = {} |
51 | 52 | |
52 | 53 | def record_search_hit(obj, key=u""): |
96 | 97 | """ |
97 | 98 | Close and save the learning record |
98 | 99 | """ |
100 | if not _register: | |
101 | pretty.print_debug(__name__, "Not writing empty register") | |
102 | return | |
99 | 103 | filepath = config.save_data_file(mnemonics_filename) |
100 | 104 | Learning._pickle_register(_register, filepath) |
71 | 71 | |
72 | 72 | return _Service_obj |
73 | 73 | |
74 | def Unregister(): | |
75 | if session_bus: | |
76 | session_bus.release_name(server_name) |
0 | import gettext | |
1 | import locale | |
2 | ||
0 | 3 | _debug = False |
1 | 4 | |
2 | def setup_gettext(): | |
5 | def setup_locale_and_gettext(): | |
3 | 6 | """Set up localization with gettext""" |
4 | import gettext | |
5 | import locale | |
6 | ||
7 | 7 | package_name = "kupfer" |
8 | 8 | localedir = "./locale" |
9 | 9 | try: |
10 | import version_subst | |
10 | from . import version_subst | |
11 | 11 | except ImportError: |
12 | 12 | pass |
13 | 13 | else: |
19 | 19 | names=("ngettext",)) |
20 | 20 | # also bind this for gtkbuilder (wtf?) |
21 | 21 | 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 | |
22 | 27 | |
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() | |
31 | 29 | |
32 | 30 | def get_options(default_opts=""): |
33 | 31 | """ |
114 | 112 | "program": version.PROGRAM_NAME, "desc": version.SHORT_DESCRIPTION, |
115 | 113 | "website": version.WEBSITE, "copyright": version.COPYRIGHT |
116 | 114 | } |
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") | |
124 | 125 | |
125 | 126 | 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 | |
137 | 128 | cli_opts = get_options() |
138 | 129 | print_banner() |
130 | ||
131 | from . import browser, pretty | |
132 | ||
139 | 133 | if _debug: |
140 | 134 | pretty.debug = _debug |
141 | 135 | |
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) | |
193 | 136 | w = browser.WindowController() |
194 | 137 | |
195 | 138 | quiet = ("--no-splash" in cli_opts) |
9 | 9 | |
10 | 10 | import itertools |
11 | 11 | from os import path |
12 | import os | |
13 | import locale | |
14 | 12 | |
15 | 13 | import gobject |
16 | 14 | import gio |
268 | 266 | """Format the path shorter: |
269 | 267 | replace homedir by ~/ |
270 | 268 | """ |
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) | |
278 | 270 | |
279 | 271 | def get_actions(self): |
280 | 272 | acts = [RevealFile(), ] |
281 | app_actions=[] | |
273 | app_actions = [] | |
282 | 274 | default = None |
283 | 275 | if self.is_dir(): |
284 | 276 | acts.append(OpenTerminal()) |
302 | 294 | pass |
303 | 295 | if def_key: |
304 | 296 | 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)) | |
306 | 298 | else: |
307 | 299 | app_actions.append(apps.pop(def_key)) |
308 | 300 | # sort the non-default OpenWith actions |
354 | 346 | root, ext = path.splitext(obj) |
355 | 347 | if ext == ".desktop": |
356 | 348 | try: |
357 | return AppLeaf(path=obj) | |
349 | return AppLeaf(init_path=obj) | |
358 | 350 | except InvalidDataError: |
359 | 351 | pass |
360 | 352 | return FileLeaf(obj) |
381 | 373 | return self.object.get_icon_name() |
382 | 374 | |
383 | 375 | 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): | |
385 | 377 | """Try constructing an Application for GAppInfo @item, |
386 | 378 | for file @path or for package name @app_id. |
387 | 379 | """ |
388 | 380 | self.init_item = item |
389 | self.init_path = path | |
381 | self.init_path = init_path | |
390 | 382 | self.init_item_id = app_id and app_id + ".desktop" |
391 | self.path = path | |
383 | # unpickle_finish will raise InvalidDataError on invalid item | |
392 | 384 | self.unpickle_finish() |
393 | if not self.object: | |
394 | raise InvalidDataError | |
395 | 385 | Leaf.__init__(self, self.object, self.object.get_name()) |
396 | 386 | self.name_aliases = self._get_aliases() |
397 | 387 | |
410 | 400 | return name_aliases |
411 | 401 | |
412 | 402 | 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() | |
414 | 404 | self.object = None |
415 | 405 | self.init_item = None |
416 | 406 | |
417 | 407 | def unpickle_finish(self): |
418 | 408 | """Try to set self.object from init's parameters""" |
409 | item = None | |
419 | 410 | 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") | |
434 | 423 | self.object = item |
424 | if not self.object: | |
425 | raise InvalidDataError | |
435 | 426 | |
436 | 427 | def repr_key(self): |
437 | 428 | return self.get_id() or self |
778 | 769 | return self._version |
779 | 770 | |
780 | 771 | 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) | |
782 | 773 | |
783 | 774 | def __hash__(self ): |
784 | 775 | return hash(repr(self)) |
785 | 776 | |
786 | 777 | 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) | |
788 | 780 | |
789 | 781 | def get_items(self): |
790 | 782 | """ |
880 | 872 | def get_items(self): |
881 | 873 | iters = [] |
882 | 874 | |
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) | |
885 | 878 | return (ConstructFileLeaf(f) for f in files) |
886 | 879 | |
887 | 880 | for d in self.dirlist: |
1115 | 1108 | """ |
1116 | 1109 | def __init__(self, text, name=None): |
1117 | 1110 | """@text *must* be unicode or UTF-8 str""" |
1111 | text = tounicode(text) | |
1118 | 1112 | if not name: |
1119 | 1113 | lines = [l for l in text.splitlines() if l.strip()] |
1120 | 1114 | name = lines[0] if lines else text |
1121 | Leaf.__init__(self, tounicode(text), name) | |
1115 | Leaf.__init__(self, text, name) | |
1122 | 1116 | |
1123 | 1117 | def get_actions(self): |
1124 | 1118 | return () |
1125 | 1119 | |
1126 | 1120 | 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 | |
1130 | 1123 | numlines = len(lines) or 1 |
1131 | firstline = striplines[0] if striplines else self.object | |
1132 | 1124 | |
1133 | 1125 | # TRANS: This is description for a TextLeaf, a free-text search |
1134 | 1126 | # TRANS: The plural parameter is the number of lines %(num)d |
1135 | 1127 | return ngettext('"%(text)s"', '(%(num)d lines) "%(text)s"', |
1136 | numlines) % {"num": numlines, "text": firstline } | |
1128 | numlines) % {"num": numlines, "text": desc } | |
1137 | 1129 | |
1138 | 1130 | def get_icon_name(self): |
1139 | 1131 | 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 | ||
0 | 4 | from kupfer.objects import Source, AppLeaf, Action, FileLeaf |
1 | from kupfer import utils | |
5 | from kupfer import utils, plugin_support | |
2 | 6 | |
3 | 7 | __kupfer_name__ = _("Applications") |
4 | 8 | __kupfer_sources__ = ("AppSource", ) |
5 | __kupfer_actions__ = ("OpenWith", ) | |
9 | __kupfer_actions__ = ( | |
10 | "OpenWith", | |
11 | "SetDefaultApplication", | |
12 | ) | |
6 | 13 | __description__ = _("All applications and preferences") |
7 | 14 | __version__ = "" |
8 | 15 | __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 | ) | |
9 | 26 | |
10 | 27 | class AppSource (Source): |
11 | 28 | """ |
18 | 35 | super(AppSource, self).__init__(_("Applications")) |
19 | 36 | |
20 | 37 | def get_items(self): |
21 | from gio import app_info_get_all | |
22 | from gio.unix import desktop_app_info_set_desktop_env | |
23 | 38 | # If we set proper desktop environment |
24 | 39 | # We get exactly the apps shown in the menu, |
25 | 40 | # 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) | |
27 | 43 | # Add this to the default |
28 | 44 | whitelist = [] |
29 | 45 | for item in app_info_get_all(): |
54 | 70 | yield AppLeaf |
55 | 71 | def get_description(self): |
56 | 72 | 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") |
21 | 21 | ) |
22 | 22 | |
23 | 23 | 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) | |
28 | 24 | def get_description(self): |
29 | 25 | lines = self.object.splitlines() |
30 | 26 | desc = unicode(self) |
31 | numlines = len(lines) | |
27 | numlines = len(lines) or 1 | |
32 | 28 | |
33 | 29 | return ngettext('Clipboard "%(desc)s"', |
34 | 30 | 'Clipboard with %(num)d lines "%(desc)s"', |
0 | 0 | import gtk |
1 | 1 | import gio |
2 | import gobject | |
2 | 3 | |
3 | 4 | from kupfer.objects import Leaf, Action, Source, RunnableLeaf |
4 | 5 | from kupfer import objects, utils, icons, pretty |
85 | 86 | def get_icon_name(self): |
86 | 87 | return "folder" |
87 | 88 | |
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 | ||
88 | 156 | class Trash (SpecialLocation): |
89 | 157 | 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): | |
92 | 166 | gfile = gio.File(self.object) |
93 | 167 | 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() | |
95 | 172 | if not item_count: |
96 | 173 | return _("Trash is empty") |
97 | 174 | # proper translation of plural |
3 | 3 | from os import path as os_path |
4 | 4 | |
5 | 5 | 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 | |
7 | 8 | |
8 | 9 | |
9 | 10 | __kupfer_name__ = _("File Actions") |
14 | 15 | "MoveTo", |
15 | 16 | "CopyTo", |
16 | 17 | "UnpackHere", |
17 | "CreateArchive" | |
18 | "CreateArchive", | |
19 | "CreateArchiveIn", | |
18 | 20 | ) |
19 | 21 | __description__ = _("More file actions") |
20 | 22 | __version__ = "" |
21 | 23 | __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 | ) | |
22 | 40 | |
23 | 41 | class Trash (Action): |
24 | 42 | # this should never be default |
85 | 103 | def get_description(self): |
86 | 104 | return _("Move file to new location") |
87 | 105 | |
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 | ||
88 | 118 | class CopyTo (Action, pretty.OutputMixin): |
89 | 119 | def __init__(self): |
90 | 120 | Action.__init__(self, _("Copy To...")) |
92 | 122 | def is_async(self): |
93 | 123 | return True |
94 | 124 | 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) | |
106 | 126 | |
107 | 127 | def item_types(self): |
108 | 128 | yield FileLeaf |
148 | 168 | yield FileLeaf |
149 | 169 | def get_description(self): |
150 | 170 | 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 | |
3 | 5 | 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 | |
6 | 9 | |
7 | 10 | __kupfer_name__ = _("Search the Web") |
8 | __kupfer_sources__ = () | |
11 | __kupfer_sources__ = ("OpenSearchSource", ) | |
9 | 12 | __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") | |
12 | 18 | __version__ = "" |
13 | 19 | __author__ = "Ulrik Sverdrup <ulrik.sverdrup@gmail.com>" |
14 | 20 | |
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""" | |
16 | 76 | 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 | ||
29 | 84 | def item_types(self): |
30 | 85 | yield TextLeaf |
31 | 86 | |
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" |
38 | 38 | self.max_items = 500 |
39 | 39 | |
40 | 40 | def get_items(self): |
41 | command = "locate --quiet --null --limit %d %s" % \ | |
41 | command = "locate --quiet --null --limit %d '%s'" % \ | |
42 | 42 | (self.max_items, self.query) |
43 | 43 | locate_output = os.popen(command).read() |
44 | 44 | files = locate_output.split("\x00")[:-1] |
0 | import itertools | |
1 | from hashlib import md5 | |
2 | ||
0 | 3 | import gio |
1 | from hashlib import md5 | |
2 | 4 | |
3 | 5 | from kupfer.objects import (Leaf, Source, AppLeaf, Action, RunnableLeaf, |
4 | 6 | SourceLeaf, AppLeafContentMixin) |
307 | 309 | yield ArtistLeaf |
308 | 310 | |
309 | 311 | 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 | """ | |
311 | 316 | for artist in utils.locale_sort(artists): |
312 | 317 | 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) | |
314 | 322 | 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]: | |
321 | 324 | yield song |
322 | 325 | |
323 | 326 | 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 | """ | |
24 | 0 | |
25 | 1 | 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 | |
29 | 3 | |
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 | |
68 | 5 | |
69 | 6 | NEEDED_KEYS= ("title", "artist", "album", "track-number", "location", ) |
7 | ||
70 | 8 | def get_rhythmbox_songs(typ="song", keys=NEEDED_KEYS, |
71 | 9 | dbfile='~/.local/share/rhythmbox/rhythmdb.xml'): |
72 | 10 | rhythmbox_dbfile = os.path.expanduser(dbfile) |
73 | rbParser = make_parser() | |
11 | rbParser = xml.sax.make_parser() | |
74 | 12 | lSongs = [] |
75 | rbHandler = RhythmBoxHandler(lSongs, typ, keys) | |
13 | attributes = {"type": typ} | |
14 | rbHandler = xml_support.XMLEntryHandler(lSongs, "entry", attributes, keys) | |
76 | 15 | rbParser.setContentHandler(rbHandler) |
77 | 16 | rbParser.parse(rhythmbox_dbfile) |
78 | 17 | return lSongs |
90 | 29 | album.sort(key=get_track_number) |
91 | 30 | |
92 | 31 | 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 | """ | |
94 | 43 | def get_album_order(rec): |
95 | 44 | tnr = rec.get("track-number") |
96 | 45 | if not tnr: return None |
0 | 0 | import gtk |
1 | 1 | |
2 | 2 | from kupfer.objects import Source, Leaf, TextLeaf, SourceLeaf, PicklingHelperMixin |
3 | from kupfer import objects | |
3 | 4 | |
4 | 5 | __kupfer_name__ = _("Selected Text") |
5 | 6 | __kupfer_sources__ = ("SelectionSource", ) |
9 | 10 | |
10 | 11 | class SelectedText (TextLeaf): |
11 | 12 | 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") | |
13 | 24 | |
14 | 25 | class InvisibleSourceLeaf (SourceLeaf): |
15 | 26 | """Hack to hide this source""" |
34 | 34 | |
35 | 35 | class TrackerSearchHere (Action): |
36 | 36 | def __init__(self): |
37 | Action.__init__(self, _("Get Tracker results...")) | |
37 | Action.__init__(self, _("Get Tracker Results...")) | |
38 | 38 | |
39 | 39 | def is_factory(self): |
40 | 40 | 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) |
55 | 55 | def get_label(self, key): |
56 | 56 | """Return label for setting @key""" |
57 | 57 | 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") |
306 | 306 | return True |
307 | 307 | |
308 | 308 | 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) | |
312 | 312 | |
313 | 313 | def on_buttonpluginsettings_clicked(self, widget): |
314 | 314 | curpath, curcol = self.table.get_cursor() |
333 | 333 | if self._plugin_makes_sense_in_catalog(plugin_id): |
334 | 334 | setctl = settings.GetSettingsController() |
335 | 335 | 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.") | |
339 | 340 | incl_active = setctl.get_plugin_is_toplevel(plugin_id) |
340 | 341 | incl_type = bool |
341 | 342 | inclwid = gtk.CheckButton(incl_label) |
348 | 349 | plugin_settings_keys = iter(plugin_settings) if plugin_settings else () |
349 | 350 | for setting in plugin_settings_keys: |
350 | 351 | typ = plugin_settings.get_value_type(setting) |
352 | alternatives = plugin_settings.get_alternatives(setting) | |
351 | 353 | wid = None |
352 | 354 | hbox = gtk.HBox() |
353 | 355 | hbox.set_property("spacing", 10) |
354 | 356 | label = plugin_settings.get_label(setting) |
355 | 357 | label_wid = gtk.Label(label) |
356 | 358 | 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)) | |
359 | 379 | hbox.pack_start(label_wid, False) |
360 | 380 | 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)) | |
363 | 381 | |
364 | 382 | elif issubclass(typ, bool): |
365 | 383 | wid = gtk.CheckButton(label) |
28 | 28 | gobject.TYPE_BOOLEAN, ()) |
29 | 29 | gobject.signal_new("finish", Scheduler, gobject.SIGNAL_RUN_LAST, |
30 | 30 | 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() |
32 | 32 | def __init__(self): |
33 | 33 | gobject.GObject.__init__(self) |
34 | 34 | 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 | ||
38 | 40 | def _read_config(self, read_config=True): |
39 | 41 | """ |
40 | 42 | Read cascading config files |
104 | 106 | return confmap |
105 | 107 | |
106 | 108 | def _save_config(self, scheduler=None): |
109 | self.output_debug("Saving config") | |
107 | 110 | config_path = config.save_config_file(self.config_filename) |
108 | 111 | if not config_path: |
109 | 112 | self.output_info("Unable to save settings, can't find config dir") |
164 | 167 | value_type = type(oldvalue) |
165 | 168 | self._config[section][key] = value_type(value) |
166 | 169 | self.emit("value-changed", section, key, value) |
170 | self._update_config_save_timer() | |
167 | 171 | return True |
168 | 172 | self.output_info("Settings key", section, key, "is invalid") |
169 | 173 | return False |
181 | 185 | if section not in self._config: |
182 | 186 | self._config[section] = {} |
183 | 187 | self._config[section][key] = str(value) |
188 | self._update_config_save_timer() | |
184 | 189 | return False |
185 | 190 | |
186 | 191 | def get_plugin_enabled(self, plugin_id): |
197 | 202 | """Convenience: if @plugin_id items are included in toplevel""" |
198 | 203 | return self.get_plugin_config(plugin_id, "kupfer_toplevel", |
199 | 204 | 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) | |
200 | 210 | |
201 | 211 | def get_plugin_is_hidden(self, plugin_id): |
202 | 212 | """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 | |
1 | 3 | import locale |
4 | ||
5 | import gobject | |
2 | 6 | |
3 | 7 | from kupfer import pretty |
4 | 8 | |
17 | 21 | for dirname, dirnames, fnames in walk(folder): |
18 | 22 | # skip deep directories |
19 | 23 | 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) | |
22 | 26 | dp += 1 |
23 | 27 | if dp > depth: |
24 | 28 | del dirnames[:] |
29 | 33 | if not include_file(dir): |
30 | 34 | excl_dir.append(dir) |
31 | 35 | continue |
32 | abspath = path.join(dirname, dir) | |
36 | abspath = os_path.join(dirname, dir) | |
33 | 37 | paths.append(abspath) |
34 | 38 | |
35 | 39 | for file in fnames: |
36 | 40 | if not include_file(file): |
37 | 41 | continue |
38 | abspath = path.join(dirname, file) | |
42 | abspath = os_path.join(dirname, file) | |
39 | 43 | paths.append(abspath) |
40 | 44 | |
41 | 45 | for dir in reversed(excl_dir): |
45 | 49 | |
46 | 50 | def locale_sort(seq, key=unicode): |
47 | 51 | """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 | """ | |
49 | 64 | locale_cmp = lambda s, o: locale.strcoll(key(s), key(o)) |
50 | 65 | seq = seq if isinstance(seq, list) else list(seq) |
51 | 66 | seq.sort(cmp=locale_cmp) |
52 | 67 | return seq |
53 | 68 | |
54 | 69 | def spawn_async(argv, in_dir="."): |
55 | import gobject | |
56 | 70 | pretty.print_debug(__name__, "Spawn commandline", argv, in_dir) |
57 | 71 | try: |
58 | 72 | return gobject.spawn_async (argv, working_directory=in_dir, |
97 | 111 | from gtk.gdk import screen_get_default |
98 | 112 | from glib import GError |
99 | 113 | try: |
114 | pretty.print_debug(__name__, "show_url", url) | |
100 | 115 | return show_uri(screen_get_default(), url, get_current_event_time()) |
101 | 116 | except GError, exc: |
102 | 117 | 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 |
13 | 13 | ICON_NAME = "search" |
14 | 14 | PROGRAM_NAME = _("Kupfer") |
15 | 15 | |
16 | AUTHORS = """Ulrik Sverdrup <ulrik.sverdrup@gmail.com> | |
16 | AUTHORS = u"""Ulrik Sverdrup <ulrik.sverdrup@gmail.com> | |
17 | 17 | """.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 | |
18 | 28 | |
19 | 29 | DOCUMENTERS = [] |
20 | 30 | |
21 | 31 | TRANSLATOR_CREDITS = _("translator-credits") |
22 | 32 | |
23 | WEBSITE = "http://kaizer.se/wiki/kupfer/" | |
33 | WEBSITE = u"http://kaizer.se/wiki/kupfer/" | |
24 | 34 | |
25 | 35 | SHORT_DESCRIPTION = _("A free software (GPLv3+) launcher") |
26 | COPYRIGHT = """Copyright © 2007--2009 Ulrik Sverdrup""" | |
36 | COPYRIGHT = u"""Copyright © 2007--2009 Ulrik Sverdrup""" | |
27 | 37 | |
28 | 38 | LICENSE = _(""" |
29 | 39 | This program is free software: you can redistribute it and/or modify |
0 | 0 | VERSION = "@VERSION@" |
1 | 1 | PACKAGE_NAME = "@PACKAGE@" |
2 | 2 | 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 | #!/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" |
5 | 5 | kupfer/data.py |
6 | 6 | kupfer/main.py |
7 | 7 | kupfer/objects.py |
8 | kupfer/preferences.py | |
9 | 8 | kupfer/plugin/abiword.py |
10 | 9 | kupfer/plugin/applications.py |
11 | 10 | kupfer/plugin/clipboard.py |
20 | 19 | kupfer/plugin/fileactions.py |
21 | 20 | kupfer/plugin/firefox.py |
22 | 21 | kupfer/plugin/google.py |
22 | kupfer/plugin/locate.py | |
23 | 23 | kupfer/plugin/rhythmbox.py |
24 | 24 | kupfer/plugin/screen.py |
25 | 25 | kupfer/plugin/selection.py |
28 | 28 | kupfer/plugin/tracker.py |
29 | 29 | kupfer/plugin/wikipedia.py |
30 | 30 | kupfer/plugin/windows.py |
31 | kupfer/plugin/urlactions.py | |
31 | 32 | kupfer/plugin/volumes.py |
33 | kupfer/preferences.py | |
32 | 34 | kupfer/version.py |
6 | 6 | msgstr "" |
7 | 7 | "Project-Id-Version: kupfer beta\n" |
8 | 8 | "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" | |
11 | 11 | "Last-Translator: Andrea Zagli <azagli@libero.it>\n" |
12 | 12 | "Language-Team: Italian <tp@lists.linux.it>\n" |
13 | 13 | "MIME-Version: 1.0\n" |
16 | 16 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" |
17 | 17 | |
18 | 18 | #: ../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 | |
24 | 29 | msgid "Kupfer" |
25 | 30 | msgstr "Kupfer" |
26 | 31 | |
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 | |
28 | 65 | #, python-format |
29 | 66 | msgid "%s is empty" |
30 | 67 | msgstr "%s è vuoto" |
31 | 68 | |
32 | #: ../kupfer/browser.py:568 | |
69 | #: ../kupfer/browser.py:640 | |
33 | 70 | #, python-format |
34 | 71 | msgid "No matches in %s" |
35 | 72 | msgstr "Nessuna corrispondenza in %s" |
36 | 73 | |
37 | #: ../kupfer/browser.py:573 | |
74 | #: ../kupfer/browser.py:645 | |
38 | 75 | msgid "Searching..." |
39 | 76 | msgstr "Ricerca..." |
40 | 77 | |
41 | #: ../kupfer/browser.py:576 | |
78 | #: ../kupfer/browser.py:651 | |
42 | 79 | #, python-format |
43 | 80 | 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 | |
47 | 84 | msgid "Usage:" |
48 | 85 | msgstr "Uso:" |
49 | 86 | |
50 | #: ../kupfer/main.py:37 | |
87 | #: ../kupfer/main.py:41 | |
51 | 88 | 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 | |
55 | 92 | msgid "show usage help" |
56 | 93 | msgstr "mostra l'aiuto per l'uso" |
57 | 94 | |
58 | #: ../kupfer/main.py:41 | |
95 | #: ../kupfer/main.py:45 | |
59 | 96 | msgid "show version information" |
60 | 97 | msgstr "mostra informazioni sulla versione" |
61 | 98 | |
62 | #: ../kupfer/main.py:42 | |
99 | #: ../kupfer/main.py:46 | |
63 | 100 | msgid "enable debug info" |
64 | 101 | msgstr "abilita informazioni di debug" |
65 | 102 | |
66 | #: ../kupfer/main.py:47 | |
103 | #: ../kupfer/main.py:51 | |
67 | 104 | msgid "To configure kupfer, edit:" |
68 | 105 | msgstr "Per configurare kupfer, modificare:" |
69 | 106 | |
70 | #: ../kupfer/main.py:48 | |
107 | #: ../kupfer/main.py:52 | |
71 | 108 | msgid "The default config for reference is at:" |
72 | 109 | msgstr "La configurazione predefinita di riferimento è in:" |
73 | 110 | |
74 | #: ../kupfer/main.py:49 | |
111 | #: ../kupfer/main.py:53 | |
75 | 112 | msgid "Available plugins:" |
76 | 113 | msgstr "Plugin disponibili:" |
77 | 114 | |
78 | #: ../kupfer/main.py:114 | |
115 | #: ../kupfer/main.py:118 | |
79 | 116 | #, python-format |
80 | 117 | msgid "" |
81 | 118 | "%(program)s: %(desc)s\n" |
82 | 119 | "\t%(copyright)s\n" |
83 | 120 | "\t%(website)s\n" |
84 | "\t" | |
85 | 121 | msgstr "" |
86 | 122 | "%(program)s: %(desc)s\n" |
87 | 123 | "\t%(copyright)s\n" |
88 | 124 | "\t%(website)s\n" |
89 | "\t" | |
90 | ||
91 | #: ../kupfer/objects.py:155 | |
125 | ||
126 | #: ../kupfer/objects.py:227 | |
92 | 127 | msgid "No matches" |
93 | 128 | msgstr "Nessuna corrispondenza" |
94 | 129 | |
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 | |
101 | 131 | msgid "Open" |
102 | 132 | msgstr "Apri" |
103 | 133 | |
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 | |
105 | 136 | #, python-format |
106 | 137 | msgid "Open with %s" |
107 | 138 | msgstr "Apri con %s" |
108 | 139 | |
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 | |
115 | 141 | msgid "Open URL" |
116 | 142 | msgstr "Apri URL" |
117 | 143 | |
118 | #: ../kupfer/objects.py:463 | |
144 | #: ../kupfer/objects.py:622 | |
119 | 145 | msgid "Open URL with default viewer" |
120 | 146 | msgstr "Apri URL con visualizzatore predefinito" |
121 | 147 | |
122 | #: ../kupfer/objects.py:477 | |
148 | #: ../kupfer/objects.py:637 | |
123 | 149 | msgid "Open with default viewer" |
124 | 150 | msgstr "Apri con visualizzatore predefinito" |
125 | 151 | |
126 | #: ../kupfer/objects.py:487 | |
152 | #: ../kupfer/objects.py:648 | |
127 | 153 | msgid "Open folder" |
128 | 154 | msgstr "Apri cartella" |
129 | 155 | |
130 | #: ../kupfer/objects.py:493 | |
156 | #: ../kupfer/objects.py:654 | |
131 | 157 | msgid "Reveal" |
132 | 158 | msgstr "Rivela" |
133 | 159 | |
134 | #: ../kupfer/objects.py:502 | |
160 | #: ../kupfer/objects.py:663 | |
135 | 161 | msgid "Open parent folder" |
136 | 162 | msgstr "Apri cartella superiore" |
137 | 163 | |
138 | #: ../kupfer/objects.py:508 | |
139 | msgid "Open Terminal here" | |
164 | #: ../kupfer/objects.py:669 | |
165 | msgid "Open Terminal Here" | |
140 | 166 | msgstr "Apri terminale qui" |
141 | 167 | |
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 | |
143 | 173 | msgid "Launch" |
144 | 174 | msgstr "Lancia" |
145 | 175 | |
146 | #: ../kupfer/objects.py:536 | |
176 | #: ../kupfer/objects.py:701 | |
147 | 177 | msgid "Launch application" |
148 | 178 | msgstr "Lancia applicazione" |
149 | 179 | |
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" | |
152 | 182 | msgstr "Vai a" |
153 | 183 | |
154 | #: ../kupfer/objects.py:546 | |
155 | #, fuzzy | |
184 | #: ../kupfer/objects.py:712 | |
156 | 185 | 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 | |
165 | 193 | 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 | |
169 | 197 | msgid "Run in Terminal" |
170 | 198 | msgstr "Esegui nel terminale" |
171 | 199 | |
172 | #: ../kupfer/objects.py:565 | |
200 | #: ../kupfer/objects.py:732 | |
173 | 201 | msgid "Run" |
174 | 202 | msgstr "Esegui" |
175 | 203 | |
176 | #: ../kupfer/objects.py:576 | |
204 | #: ../kupfer/objects.py:746 | |
177 | 205 | 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 | |
181 | 209 | msgid "Run this program" |
182 | 210 | msgstr "Esegui questo programma" |
183 | 211 | |
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..." | |
186 | 424 | msgstr "Cerca contenuto..." |
187 | 425 | |
188 | #: ../kupfer/objects.py:601 | |
426 | #: ../kupfer/plugin/core.py:40 | |
189 | 427 | msgid "Search inside this catalog" |
190 | 428 | msgstr "Cerca all'interno del catalogo" |
191 | 429 | |
192 | #: ../kupfer/objects.py:611 | |
430 | #: ../kupfer/plugin/core.py:48 | |
193 | 431 | msgid "Rescan" |
194 | 432 | msgstr "Nuova scansione" |
195 | 433 | |
196 | #: ../kupfer/objects.py:624 | |
434 | #: ../kupfer/plugin/core.py:57 | |
197 | 435 | 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 | |
246 | 786 | msgid "(no description)" |
247 | 787 | msgstr "(nessuna descrizione)" |
248 | 788 | |
249 | #: ../kupfer/plugins.py:60 | |
789 | #: ../kupfer/plugins.py:70 | |
250 | 790 | #, python-format |
251 | 791 | msgid " %(name)-20s %(version)-4s %(description)s" |
252 | 792 | 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" | |
253 | 985 | |
254 | 986 | #: ../kupfer/version.py:22 |
255 | 987 | msgid "translator-credits" |
292 | 1024 | "della Licenza Pubblica Generale GNU. In caso contrario vedere <http://www." |
293 | 1025 | "gnu.org/licenses/>.\n" |
294 | 1026 | |
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 | ||
296 | 1036 | #, 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 | ||
313 | 1040 | #, 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 | ||
326 | 1057 | #, 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 | ||
437 | 1064 | #, 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" | |
691 | 1070 | |
692 | 1071 | #~ msgid "Catalog of Catalogs" |
693 | 1072 | #~ msgstr "Catalogo di cataloghi" |
7 | 7 | msgstr "" |
8 | 8 | "Project-Id-Version: kupfer beta\n" |
9 | 9 | "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" | |
11 | 11 | "PO-Revision-Date: 2009-06-23 20:19+0200\n" |
12 | 12 | "Last-Translator: Ulrik Sverdrup <ulrik.sverdrup@gmail.com>\n" |
13 | 13 | "Language-Team: Swedish\n" |
24 | 24 | msgid "Convenient command and access tool for applications and documents" |
25 | 25 | msgstr "Flexibelt kommandoprogram för program och dokument" |
26 | 26 | |
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 | |
29 | 29 | #: ../kupfer/version.py:15 |
30 | 30 | msgid "Kupfer" |
31 | 31 | msgstr "Kupfer" |
62 | 62 | msgid "Start automatically on login" |
63 | 63 | msgstr "Starta automatiskt vid login" |
64 | 64 | |
65 | #: ../kupfer/browser.py:630 | |
65 | #: ../kupfer/browser.py:641 | |
66 | 66 | #, python-format |
67 | 67 | msgid "%s is empty" |
68 | 68 | msgstr "%s är tom" |
69 | 69 | |
70 | #: ../kupfer/browser.py:632 | |
70 | #: ../kupfer/browser.py:643 | |
71 | 71 | #, python-format |
72 | 72 | msgid "No matches in %s" |
73 | 73 | msgstr "Inga träffar i %s" |
74 | 74 | |
75 | #: ../kupfer/browser.py:637 | |
75 | #: ../kupfer/browser.py:648 | |
76 | 76 | msgid "Searching..." |
77 | 77 | msgstr "Söker..." |
78 | 78 | |
79 | #: ../kupfer/browser.py:643 | |
79 | #: ../kupfer/browser.py:654 | |
80 | 80 | #, python-format |
81 | 81 | msgid "Searching %(source)s..." |
82 | 82 | msgstr "Söker i %(source)s..." |
83 | 83 | |
84 | #: ../kupfer/main.py:38 | |
84 | #: ../kupfer/main.py:36 | |
85 | 85 | msgid "Usage:" |
86 | 86 | msgstr "Användning:" |
87 | 87 | |
88 | #: ../kupfer/main.py:41 | |
88 | #: ../kupfer/main.py:39 | |
89 | 89 | msgid "do not present main interface on launch" |
90 | 90 | msgstr "visa ej fönster vid start" |
91 | 91 | |
92 | #: ../kupfer/main.py:44 | |
92 | #: ../kupfer/main.py:42 | |
93 | 93 | msgid "show usage help" |
94 | 94 | msgstr "visa hjälpmeddelande" |
95 | 95 | |
96 | #: ../kupfer/main.py:45 | |
96 | #: ../kupfer/main.py:43 | |
97 | 97 | msgid "show version information" |
98 | 98 | msgstr "visa programversion" |
99 | 99 | |
100 | #: ../kupfer/main.py:46 | |
100 | #: ../kupfer/main.py:44 | |
101 | 101 | msgid "enable debug info" |
102 | 102 | msgstr "felsökningsläge" |
103 | 103 | |
104 | #: ../kupfer/main.py:51 | |
104 | #: ../kupfer/main.py:49 | |
105 | 105 | msgid "To configure kupfer, edit:" |
106 | 106 | msgstr "För att konfigurera kupfer, redigera:" |
107 | 107 | |
108 | #: ../kupfer/main.py:52 | |
108 | #: ../kupfer/main.py:50 | |
109 | 109 | msgid "The default config for reference is at:" |
110 | 110 | msgstr "Standardinställningarna är dokumenterade i:" |
111 | 111 | |
112 | #: ../kupfer/main.py:53 | |
112 | #: ../kupfer/main.py:51 | |
113 | 113 | msgid "Available plugins:" |
114 | 114 | msgstr "Tillgängliga insticksmoduler:" |
115 | 115 | |
116 | #: ../kupfer/main.py:118 | |
116 | #: ../kupfer/main.py:117 | |
117 | 117 | #, python-format |
118 | 118 | msgid "" |
119 | 119 | "%(program)s: %(desc)s\n" |
120 | 120 | "\t%(copyright)s\n" |
121 | 121 | "\t%(website)s\n" |
122 | "\t" | |
123 | 122 | msgstr "" |
124 | 123 | "%(program)s: %(desc)s\n" |
125 | 124 | "\t%(copyright)s\n" |
126 | 125 | "\t%(website)s\n" |
127 | "\t" | |
128 | ||
129 | #: ../kupfer/objects.py:223 | |
126 | ||
127 | #: ../kupfer/objects.py:225 | |
130 | 128 | msgid "No matches" |
131 | 129 | msgstr "Inga träffar" |
132 | 130 | |
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 | |
134 | 132 | msgid "Open" |
135 | 133 | msgstr "Öppna" |
136 | 134 | |
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 | |
139 | 137 | #, python-format |
140 | 138 | msgid "Open with %s" |
141 | 139 | msgstr "Öppna med %s" |
142 | 140 | |
143 | #: ../kupfer/objects.py:573 | |
141 | #: ../kupfer/objects.py:602 | |
144 | 142 | msgid "Open URL" |
145 | 143 | msgstr "Öppna URL" |
146 | 144 | |
147 | #: ../kupfer/objects.py:584 | |
145 | #: ../kupfer/objects.py:613 | |
148 | 146 | msgid "Open URL with default viewer" |
149 | 147 | msgstr "Öppna URL med standardprogram" |
150 | 148 | |
151 | #: ../kupfer/objects.py:599 | |
149 | #: ../kupfer/objects.py:628 | |
152 | 150 | msgid "Open with default viewer" |
153 | 151 | msgstr "Öppna med standardprogram" |
154 | 152 | |
155 | #: ../kupfer/objects.py:610 | |
153 | #: ../kupfer/objects.py:639 | |
156 | 154 | msgid "Open folder" |
157 | 155 | msgstr "Öppna mapp" |
158 | 156 | |
159 | #: ../kupfer/objects.py:616 | |
157 | #: ../kupfer/objects.py:645 | |
160 | 158 | msgid "Reveal" |
161 | 159 | msgstr "Visa" |
162 | 160 | |
163 | #: ../kupfer/objects.py:625 | |
161 | #: ../kupfer/objects.py:654 | |
164 | 162 | msgid "Open parent folder" |
165 | 163 | msgstr "Öppna föräldermapp i filhanteraren" |
166 | 164 | |
167 | #: ../kupfer/objects.py:631 | |
165 | #: ../kupfer/objects.py:660 | |
168 | 166 | msgid "Open Terminal Here" |
169 | 167 | msgstr "Öppna i terminalfönster" |
170 | 168 | |
171 | #: ../kupfer/objects.py:640 | |
169 | #: ../kupfer/objects.py:669 | |
172 | 170 | msgid "Open this location in a terminal" |
173 | 171 | msgstr "Öppna platsen i terminalfönster" |
174 | 172 | |
175 | #: ../kupfer/objects.py:653 | |
173 | #: ../kupfer/objects.py:682 | |
176 | 174 | msgid "Launch" |
177 | 175 | msgstr "Starta" |
178 | 176 | |
179 | #: ../kupfer/objects.py:663 | |
177 | #: ../kupfer/objects.py:692 | |
180 | 178 | msgid "Launch application" |
181 | 179 | msgstr "Starta program" |
182 | 180 | |
183 | #: ../kupfer/objects.py:670 ../kupfer/plugin/windows.py:48 | |
181 | #: ../kupfer/objects.py:699 ../kupfer/plugin/windows.py:49 | |
184 | 182 | msgid "Go To" |
185 | 183 | msgstr "Gå till" |
186 | 184 | |
187 | #: ../kupfer/objects.py:674 | |
185 | #: ../kupfer/objects.py:703 | |
188 | 186 | msgid "Show application window" |
189 | 187 | msgstr "Visa programfönster" |
190 | 188 | |
191 | #: ../kupfer/objects.py:683 | |
189 | #: ../kupfer/objects.py:712 | |
192 | 190 | msgid "Launch Again" |
193 | 191 | msgstr "Starta igen" |
194 | 192 | |
195 | #: ../kupfer/objects.py:687 | |
193 | #: ../kupfer/objects.py:716 | |
196 | 194 | msgid "Launch another instance of this application" |
197 | 195 | msgstr "Starta programmet igen" |
198 | 196 | |
199 | #: ../kupfer/objects.py:694 | |
197 | #: ../kupfer/objects.py:723 | |
200 | 198 | msgid "Run in Terminal" |
201 | 199 | msgstr "Kör i terminalfönster" |
202 | 200 | |
203 | #: ../kupfer/objects.py:694 | |
201 | #: ../kupfer/objects.py:723 | |
204 | 202 | msgid "Run" |
205 | 203 | msgstr "Kör" |
206 | 204 | |
207 | #: ../kupfer/objects.py:705 | |
205 | #: ../kupfer/objects.py:737 | |
208 | 206 | msgid "Run this program in a Terminal" |
209 | 207 | msgstr "Kör programmet i terminalfönster" |
210 | 208 | |
211 | #: ../kupfer/objects.py:707 | |
209 | #: ../kupfer/objects.py:739 | |
212 | 210 | msgid "Run this program" |
213 | 211 | msgstr "Kör programmet" |
214 | 212 | |
215 | #: ../kupfer/objects.py:715 | |
213 | #: ../kupfer/objects.py:747 | |
216 | 214 | msgid "No action" |
217 | 215 | msgstr "Inget kommando" |
218 | 216 | |
219 | 217 | #. 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 | |
221 | 219 | #, python-format |
222 | 220 | msgid "%s et. al." |
223 | 221 | msgstr "%s et. al." |
224 | 222 | |
225 | #: ../kupfer/objects.py:859 | |
223 | #: ../kupfer/objects.py:893 | |
226 | 224 | #, python-format |
227 | 225 | msgid "Recursive source of %(dir)s, (%(levels)d levels)" |
228 | 226 | msgstr "Rekursiv källa %(dir)s, (%(levels)d nivåer)" |
229 | 227 | |
230 | #: ../kupfer/objects.py:926 | |
228 | #: ../kupfer/objects.py:961 | |
231 | 229 | #, python-format |
232 | 230 | msgid "Directory source %s" |
233 | 231 | msgstr "Katalogkälla %s" |
234 | 232 | |
235 | #: ../kupfer/objects.py:942 | |
233 | #: ../kupfer/objects.py:977 | |
236 | 234 | msgid "Catalog Index" |
237 | 235 | msgstr "Katalogindex" |
238 | 236 | |
239 | #: ../kupfer/objects.py:957 | |
237 | #: ../kupfer/objects.py:992 | |
240 | 238 | msgid "An index of all available sources" |
241 | 239 | msgstr "Index över alla tilgängliga kataloger" |
242 | 240 | |
243 | #: ../kupfer/objects.py:968 | |
241 | #: ../kupfer/objects.py:1003 | |
244 | 242 | msgid "Catalog" |
245 | 243 | msgstr "Katalog" |
246 | 244 | |
247 | #: ../kupfer/objects.py:987 | |
245 | #: ../kupfer/objects.py:1022 | |
248 | 246 | msgid "Root catalog" |
249 | 247 | msgstr "Rotkatalog" |
250 | 248 | |
251 | #: ../kupfer/objects.py:1064 | |
249 | #: ../kupfer/objects.py:1099 | |
252 | 250 | msgid "Do" |
253 | 251 | msgstr "Utför" |
254 | 252 | |
255 | #: ../kupfer/objects.py:1069 | |
253 | #: ../kupfer/objects.py:1104 | |
256 | 254 | msgid "Perform action" |
257 | 255 | msgstr "Utför kommando" |
258 | 256 | |
259 | 257 | #. TRANS: This is description for a TextLeaf, a free-text search |
260 | 258 | #. TRANS: The plural parameter is the number of lines %(num)d |
261 | #: ../kupfer/objects.py:1094 | |
259 | #: ../kupfer/objects.py:1130 | |
262 | 260 | #, python-format |
263 | 261 | msgid "\"%(text)s\"" |
264 | 262 | msgid_plural "(%(num)d lines) \"%(text)s\"" |
265 | 263 | msgstr[0] "\"%(text)s\"" |
266 | 264 | msgstr[1] "(%(num)d lines) \"%(text)s\"" |
267 | 265 | |
268 | #: ../kupfer/objects.py:1106 ../kupfer/plugin/text.py:18 | |
266 | #: ../kupfer/objects.py:1142 ../kupfer/plugin/text.py:18 | |
269 | 267 | msgid "Text Matches" |
270 | 268 | 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" | |
271 | 1007 | |
272 | 1008 | #: ../kupfer/preferences.py:160 |
273 | 1009 | msgid "Applied" |
278 | 1014 | msgstr "Snabbtangenten kunde inte bindas" |
279 | 1015 | |
280 | 1016 | #. TRANS: Plugin contents header |
281 | #: ../kupfer/preferences.py:280 | |
1017 | #: ../kupfer/preferences.py:283 | |
282 | 1018 | msgid "Sources" |
283 | 1019 | msgstr "Källor" |
284 | 1020 | |
285 | 1021 | #. TRANS: Plugin contents header |
286 | #: ../kupfer/preferences.py:284 | |
1022 | #: ../kupfer/preferences.py:287 | |
287 | 1023 | msgid "Actions" |
288 | 1024 | msgstr "Kommandon" |
289 | 1025 | |
296 | 1032 | msgid "Include in top level" |
297 | 1033 | msgstr "Inkludera i toppnivån" |
298 | 1034 | |
299 | #: ../kupfer/preferences.py:337 | |
1035 | #: ../kupfer/preferences.py:338 | |
300 | 1036 | msgid "" |
301 | 1037 | "If enabled, objects from the plugin's source(s) will be available in the top " |
302 | 1038 | "level.\n" |
305 | 1041 | "När alternativet är aktiverat inkluderas objekt från insticksmodulens " |
306 | 1042 | "källori toppnivån.\n" |
307 | 1043 | "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" | |
982 | 1044 | |
983 | 1045 | #: ../kupfer/version.py:22 |
984 | 1046 | msgid "translator-credits" |
1018 | 1080 | "Du bör ha fått en kopia av GNU General Public License tillsammans med\n" |
1019 | 1081 | "detta program. Om inte, <http://www.gnu.org/licenses/>.\n" |
1020 | 1082 | |
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 | ||
1036 | 1083 | #~ msgid "Core" |
1037 | 1084 | #~ msgstr "Bas" |
1038 | 1085 | |
1039 | #~ msgid "Kupfer items" | |
1040 | #~ msgstr "Kupfer-objekt" | |
1041 | ||
1042 | 1086 | #~ msgid "%d lines" |
1043 | 1087 | #~ msgstr "%d rader" |
1044 | 1088 | |
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 | ||
1057 | 1089 | #~ msgid "Directories" |
1058 | 1090 | #~ msgstr "Kataloger" |
1059 | 1091 | |
1060 | 1092 | #~ msgid "Clipboard" |
1061 | 1093 | #~ msgstr "Urklipp" |
1062 | 1094 | |
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" |
37 | 37 | # these variables are mandatory ('/' are converted automatically) |
38 | 38 | srcdir = '.' |
39 | 39 | 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) | |
40 | 50 | |
41 | 51 | def dist(): |
42 | 52 | """Make the dist tarball and print its SHA-1 """ |